diff --git a/packages/linux/package.mk b/packages/linux/package.mk index dd9908f452..70fbf650ea 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -56,7 +56,7 @@ case "$LINUX" in PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET imx6-status-led imx6-soc-fan irqbalanced" ;; *) - PKG_VERSION="4.8.13" + PKG_VERSION="4.9" PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_PATCH_DIRS="default" ;; diff --git a/packages/linux/patches/default/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch b/packages/linux/patches/default/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch index 2bc9542311..6b09bc0073 100644 --- a/packages/linux/patches/default/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch +++ b/packages/linux/patches/default/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch @@ -17,7 +17,7 @@ - toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); - scancode &= ~RC6_6A_MCE_TOGGLE_MASK; - } else { -- protocol = RC_BIT_RC6_6A_32; +- protocol = RC_TYPE_RC6_6A_32; - toggle = 0; - } + protocol = RC_TYPE_RC6_MCE; diff --git a/packages/linux/patches/default/linux-220.01-tbs-support.patch b/packages/linux/patches/default/linux-220.01-tbs-support.patch new file mode 100644 index 0000000000..a3fd782525 --- /dev/null +++ b/packages/linux/patches/default/linux-220.01-tbs-support.patch @@ -0,0 +1,60954 @@ +From: https://github.com/tbsdtv/linux_media +Date: 13 Dec 2016 00:00:00 +Subject: [PATCH] add TBS DVB card support + +diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c +index fd89314..b824edd 100644 +--- a/drivers/media/dvb-core/dvb_ca_en50221.c ++++ b/drivers/media/dvb-core/dvb_ca_en50221.c +@@ -253,7 +253,7 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) + int cam_present_old = (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE); + cam_changed = (cam_present_now != cam_present_old); + } +- ++ + if (cam_changed) { + if (!cam_present_now) { + ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; +@@ -1055,7 +1055,6 @@ static int dvb_ca_en50221_thread(void *data) + dvb_ca_en50221_thread_update_delay(ca); + atomic_dec(&ca->slot_info[slot].camchange_count); + } +- + // CAM state machine + switch (ca->slot_info[slot].slot_state) { + case DVB_CA_SLOTSTATE_NONE: +@@ -1772,6 +1771,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, + ret); + goto unregister_device; + } ++ + return 0; + + unregister_device: +diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig +index c841fa1..2a10e95 100644 +--- a/drivers/media/dvb-frontends/Kconfig ++++ b/drivers/media/dvb-frontends/Kconfig +@@ -698,6 +698,14 @@ config DVB_MB86A20S + A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator. + Say Y when you want to support this frontend. + ++config DVB_MTV23X ++ tristate "RAONTECH mtv23x" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A driver for RAONTECH mtv23x DVB-T/ISDB-T demodulator. ++ Say Y when you want to support this frontend. ++ + comment "ISDB-S (satellite) & ISDB-T (terrestrial) frontends" + depends on DVB_CORE + +@@ -782,6 +790,13 @@ config DVB_ISL6421 + help + An SEC control chip. + ++config DVB_ISL6422 ++ tristate "ISL6422[B] SEC controller" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A Dual SEC controller chip from Intersil ++ + config DVB_ISL6423 + tristate "ISL6423 SEC controller" + depends on DVB_CORE && I2C +@@ -875,8 +890,52 @@ config DVB_HELENE + help + Say Y when you want to support this frontend. + ++config DVB_TAS2101 ++ tristate "Tmax TAS2101 based" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y when you want to support this frontend. ++ ++config DVB_MXL5XX ++ tristate "MaxLinear MXL5XX based" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A DVB-S demod and tuner module. ++ Say Y when you want to support this frontend. ++ ++config DVB_SI2183 ++ tristate "Silicon Labs Si2183" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y when you want to support this frontend. + comment "Tools to develop new frontends" + ++config DVB_STV0910 ++ tristate "STV0910 based" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators. ++ Say Y when you want to support these frontends. ++ ++config DVB_AVL6882 ++ tristate "Availink AVL6882 DVB-T/T2/C/S/S2 demodulator" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y when you want to support this frontend. ++ ++config DVB_MN88436 ++ tristate "Panasonic MN88436" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want ++ to support this frontend. ++ + config DVB_DUMMY_FE + tristate "Dummy frontend driver" + depends on DVB_CORE +diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile +index 93921a4..075449f 100644 +--- a/drivers/media/dvb-frontends/Makefile ++++ b/drivers/media/dvb-frontends/Makefile +@@ -97,6 +97,7 @@ obj-$(CONFIG_DVB_STV6110x) += stv6110x.o + obj-$(CONFIG_DVB_M88DS3103) += m88ds3103.o + obj-$(CONFIG_DVB_MN88472) += mn88472.o + obj-$(CONFIG_DVB_MN88473) += mn88473.o ++obj-$(CONFIG_DVB_ISL6422) += isl6422.o + obj-$(CONFIG_DVB_ISL6423) += isl6423.o + obj-$(CONFIG_DVB_EC100) += ec100.o + obj-$(CONFIG_DVB_HD29L2) += hd29l2.o +@@ -126,3 +127,10 @@ obj-$(CONFIG_DVB_TC90522) += tc90522.o + obj-$(CONFIG_DVB_HORUS3A) += horus3a.o + obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o + obj-$(CONFIG_DVB_HELENE) += helene.o ++obj-$(CONFIG_DVB_TAS2101) += tas2101.o ++obj-$(CONFIG_DVB_MXL5XX) += mxl5xx.o ++obj-$(CONFIG_DVB_SI2183) += si2183.o ++obj-$(CONFIG_DVB_STV0910) += stv0910.o ++obj-$(CONFIG_DVB_AVL6882) += avl6882.o ++obj-$(CONFIG_DVB_MN88436) += mn88436.o ++obj-$(CONFIG_DVB_MTV23X) += mtv23x.o +diff --git a/drivers/media/dvb-frontends/avl6882.c b/drivers/media/dvb-frontends/avl6882.c +new file mode 100644 +index 0000000..3b723e8 +--- /dev/null ++++ b/drivers/media/dvb-frontends/avl6882.c +@@ -0,0 +1,2392 @@ ++/* ++ * Availink AVL6882 demod driver ++ * ++ * Copyright (C) 2015 Luis Alves ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dvb_frontend.h" ++#include "avl6882.h" ++#include "avl6882_priv.h" ++ ++#define AVL6882_FIRMWARE "dvb-demod-avl6882.fw" ++ ++static int avl6882_i2c_rd(struct avl6882_priv *priv, u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg[] = { ++ { ++ .addr = priv->config->demod_address, ++ .flags = 0, ++ .len = 3, ++ .buf = buf, ++ }, ++ { ++ .addr= priv->config->demod_address, ++ .flags= I2C_M_RD, ++ .len = len, ++ .buf = buf, ++ } ++ }; ++ ++ ret = i2c_transfer(priv->i2c, msg, 2); ++ if (ret == 2) { ++ ret = 0; ++ } else { ++ dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d " \ ++ "len=%d\n", KBUILD_MODNAME, ret, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++ ++static int avl6882_i2c_wr(struct avl6882_priv *priv, u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg = { ++ .addr= priv->config->demod_address, ++ .flags = 0, ++ .buf = buf, ++ .len = len, ++ }; ++ ++ ret = i2c_transfer(priv->i2c, &msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d " \ ++ "len=%d\n", KBUILD_MODNAME, ret, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++#if 0 ++static int avl6882_i2c_wrm(struct avl6882_priv *priv, u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg = { ++ .addr= priv->config->demod_address, ++ .flags = 1, /* ?? */ ++ .buf = buf, ++ .len = len, ++ }; ++ ++ ret = i2c_transfer(priv->i2c, &msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ dev_warn(&priv->i2c->dev, "%s: i2c wrm failed=%d " \ ++ "len=%d\n", KBUILD_MODNAME, ret, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++#endif ++/* write 32bit words at addr */ ++#define MAX_WORDS_WR_LEN ((MAX_I2C_WRITE_SIZE-3) / 4) ++static int avl6882_i2c_wr_data(struct avl6882_priv *priv, ++ u32 addr, u32 *data, int len) ++{ ++ int ret = 0, this_len; ++ u32 buf[MAX_WORDS_WR_LEN + 1], *p; ++ u8 *b = ((u8*) buf) + 1, i; ++ ++ ++ while (len > 0) { ++ p = buf; ++ *(p++) = cpu_to_be32(addr); ++ ++ this_len = (len > MAX_WORDS_WR_LEN) ? MAX_WORDS_WR_LEN : len; ++ ++ for (i = 0; i < this_len; i++) ++ *(p++) = cpu_to_be32(*data++); ++ ++ ret = avl6882_i2c_wr(priv, b, this_len * 4 + 3); ++ if (ret) ++ break; ++ ++ len -= this_len; ++ if (len) ++ addr += this_len * 4; ++ ++ } ++ return ret; ++} ++ ++static int avl6882_i2c_wr_reg(struct avl6882_priv *priv, ++ u32 addr, u32 data, int reg_size) ++{ ++ u8 buf[3 + 4]; ++ u8 *p = buf; ++ ++ *(p++) = (u8) (addr >> 16); ++ *(p++) = (u8) (addr >> 8); ++ *(p++) = (u8) (addr); ++ ++ switch (reg_size) { ++ case 4: ++ *(p++) = (u8) (data >> 24); ++ *(p++) = (u8) (data >> 16); ++ case 2: ++ *(p++) = (u8) (data >> 8); ++ case 1: ++ default: ++ *(p++) = (u8) (data); ++ break; ++ } ++ ++ return avl6882_i2c_wr(priv, buf, 3 + reg_size); ++} ++ ++#define AVL6882_WR_REG8(_priv, _addr, _data) \ ++ avl6882_i2c_wr_reg(_priv, _addr, _data, 1) ++#define AVL6882_WR_REG16(_priv, _addr, _data) \ ++ avl6882_i2c_wr_reg(_priv, _addr, _data, 2) ++#define AVL6882_WR_REG32(_priv, _addr, _data) \ ++ avl6882_i2c_wr_reg(_priv, _addr, _data, 4) ++ ++static int avl6882_i2c_rd_reg(struct avl6882_priv *priv, ++ u32 addr, u32 *data, int reg_size) ++{ ++ int ret; ++ u8 buf[3 + 4]; ++ u8 *p = buf; ++ ++ *(p++) = (u8) (addr >> 16); ++ *(p++) = (u8) (addr >> 8); ++ *(p++) = (u8) (addr); ++ //ret = avl6882_i2c_wr(priv, buf, 3); ++ ret = avl6882_i2c_rd(priv, buf, reg_size); ++ ++ *data = 0; ++ p = buf; ++ ++ switch (reg_size) { ++ case 4: ++ *data |= (u32) (*(p++)) << 24; ++ *data |= (u32) (*(p++)) << 16; ++ case 2: ++ *data |= (u32) (*(p++)) << 8; ++ case 1: ++ default: ++ *data |= (u32) *(p); ++ break; ++ } ++ return ret; ++} ++ ++#define AVL6882_RD_REG8(_priv, _addr, _data) \ ++ avl6882_i2c_rd_reg(_priv, _addr, _data, 1) ++#define AVL6882_RD_REG16(_priv, _addr, _data) \ ++ avl6882_i2c_rd_reg(_priv, _addr, _data, 2) ++#define AVL6882_RD_REG32(_priv, _addr, _data) \ ++ avl6882_i2c_rd_reg(_priv, _addr, _data, 4) ++ ++inline static int avl6882_gpio_set(struct avl6882_priv *priv, u8 pin, u8 val) ++{ ++ return AVL6882_WR_REG32(priv, AVLREG_GPIO_BASE + pin, val); ++} ++ ++static int avl6882_setup_pll(struct avl6882_priv *priv) ++{ ++ int ret; ++ ++ /* sys_pll */ ++ ret = AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_divr, 2); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_divf, 99); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_divq, 7); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_range, 1); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_divq2, 11); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_divq3, 13); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_enable2, 0); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_sys_pll_enable3, 0); ++ ++ /* mpeg_pll */ ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_divr, 0); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_divf, 35); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_divq, 7); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_range, 3); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_divq2, 11); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_divq3, 13); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_enable2, 0); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_mpeg_pll_enable3, 0); ++ ++ /* adc_pll */ ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_divr, 2); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_divf, 99); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_divq, 7); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_range, 1); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_divq2, 11); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_divq3, 13); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_enable2, 1); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_adc_pll_enable3, 1); ++ ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_RESET, 0); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_RESET, 1); ++ msleep(20); ++ ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_dll_out_phase, 96); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_dll_rd_phase, 0); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_deglitch_mode, 1); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_dll_init, 1); ++ ret |= AVL6882_WR_REG32(priv, AVLREG_PLL_dll_init, 0); ++ return ret; ++} ++ ++#define DEMOD_WAIT_RETRIES (10) ++#define DEMOD_WAIT_MS (20) ++static int avl6882_wait_demod(struct avl6882_priv *priv) ++{ ++ u32 cmd = 0; ++ int ret, retry = DEMOD_WAIT_RETRIES; ++ ++ do { ++ ret = AVL6882_RD_REG16(priv, 0x200 + rc_fw_command_saddr_offset, &cmd); ++ if ((ret == 0) && (cmd == 0)) ++ return ret; ++ else ++ msleep(DEMOD_WAIT_MS); ++ } while (--retry); ++ ret = -EBUSY; ++ return ret; ++} ++ ++/* TODO remove one of the waits */ ++static int avl6882_exec_n_wait(struct avl6882_priv *priv, u8 cmd) ++{ ++ int ret; ++ ++ ret = avl6882_wait_demod(priv); ++ if (ret) ++ return ret; ++ ret = AVL6882_WR_REG16(priv, 0x200 + rc_fw_command_saddr_offset, (u32) cmd); ++ if (ret) ++ return ret; ++ return avl6882_wait_demod(priv); ++} ++ ++ ++#define DMA_MAX_TRIES (20) ++static int avl6882_patch_demod(struct avl6882_priv *priv, u32 *patch) ++{ ++ int ret = 0; ++ u8 unary_op, binary_op, addr_mode_op; ++ u32 cmd, num_cmd_words, next_cmd_idx, num_cond_words, num_rvs; ++ u32 condition = 0; ++ u32 value = 0; ++ u32 operation; ++ u32 tmp_top_valid, core_rdy_word; ++ u32 exp_crc_val, crc_result; ++ u32 data = 0; ++ u32 type, ref_addr, ref_size; ++ u32 data_section_offset; ++ u32 args_addr, src_addr, dest_addr, data_offset, length; ++ u32 idx, len, i; ++ u32 variable_array[PATCH_VAR_ARRAY_SIZE]; ++ ++ for(i=0; i < PATCH_VAR_ARRAY_SIZE; i++) ++ variable_array[i] = 0; ++ ++ ++ printk("PATCHING---------\n"); ++ ++ //total_patch_len = patch[1]; ++ //standard = patch[2]; ++ idx = 3; ++ args_addr = patch[idx++]; ++ data_section_offset = patch[idx++]; ++ /* reserved length */ ++ len = patch[idx++]; ++ idx += len; ++ /* script length */ ++ len = patch[idx++]; ++ len += idx; ++ ++ while (idx < len) { ++ num_cmd_words = patch[idx++]; ++ next_cmd_idx = idx + num_cmd_words - 1; ++ num_cond_words = patch[idx++]; ++ if (num_cond_words == 0) { ++ condition = 1; ++ } else { ++ for (i = 0; i < num_cond_words; i++) { ++ operation = patch[idx++]; ++ value = patch[idx++]; ++ unary_op = (operation >> 8) & 0xff; ++ binary_op = operation & 0xff; ++ addr_mode_op = ((operation >> 16) & 0x3); ++ ++ if ((addr_mode_op == PATCH_OP_ADDR_MODE_VAR_IDX) && ++ (binary_op != PATCH_OP_BINARY_STORE)) { ++ value = variable_array[value]; //grab variable value ++ } ++ ++ switch(unary_op) { ++ case PATCH_OP_UNARY_LOGICAL_NEGATE: ++ value = !value; ++ break; ++ case PATCH_OP_UNARY_BITWISE_NEGATE: ++ value = ~value; ++ break; ++ default: ++ break; ++ } ++ switch(binary_op) { ++ case PATCH_OP_BINARY_LOAD: ++ condition = value; ++ break; ++ case PATCH_OP_BINARY_STORE: ++ variable_array[value] = condition; ++ break; ++ case PATCH_OP_BINARY_AND: ++ condition = condition && value; ++ break; ++ case PATCH_OP_BINARY_OR: ++ condition = condition || value; ++ break; ++ case PATCH_OP_BINARY_BITWISE_AND: ++ condition = condition & value; ++ break; ++ case PATCH_OP_BINARY_BITWISE_OR: ++ condition = condition | value; ++ break; ++ case PATCH_OP_BINARY_EQUALS: ++ condition = condition == value; ++ break; ++ case PATCH_OP_BINARY_NOT_EQUALS: ++ condition = condition != value; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ ++ AVL6882_RD_REG32(priv, 0x29A648, &tmp_top_valid); ++ AVL6882_RD_REG32(priv, 0x0A0, &core_rdy_word); ++ ++ if (condition) { ++ cmd = patch[idx++]; ++ switch(cmd) { ++ case PATCH_CMD_PING: ++ ret = avl6882_exec_n_wait(priv, AVL_FW_CMD_PING); ++ num_rvs = patch[idx++]; ++ i = patch[idx]; ++ variable_array[i] = (ret == 0); ++ break; ++ case PATCH_CMD_VALIDATE_CRC: ++ exp_crc_val = patch[idx++]; ++ src_addr = patch[idx++]; ++ length = patch[idx++]; ++ AVL6882_WR_REG32(priv,0x200 + rc_fw_command_args_addr_iaddr_offset, args_addr); ++ AVL6882_WR_REG32(priv,args_addr+0, src_addr); ++ AVL6882_WR_REG32(priv,args_addr+4, length); ++ ret = avl6882_exec_n_wait(priv, AVL_FW_CMD_CALC_CRC); ++ AVL6882_RD_REG32(priv,args_addr+8, &crc_result); ++ num_rvs = patch[idx++]; ++ i = patch[idx]; ++ variable_array[i] = (crc_result == exp_crc_val); ++ break; ++ case PATCH_CMD_LD_TO_DEVICE: ++ length = patch[idx++]; ++ dest_addr = patch[idx++]; ++ data_offset = patch[idx++]; ++ data_offset += data_section_offset; ++ ret = avl6882_i2c_wr_data(priv, dest_addr, &patch[data_offset], length); ++ num_rvs = patch[idx++]; ++ break; ++ case PATCH_CMD_LD_TO_DEVICE_IMM: ++ length = patch[idx++]; ++ dest_addr = patch[idx++]; ++ data = patch[idx++]; ++ ret = avl6882_i2c_wr_reg(priv, dest_addr, data, length); ++ num_rvs = patch[idx++]; ++ break; ++ case PATCH_CMD_RD_FROM_DEVICE: ++ length = patch[idx++]; ++ src_addr = patch[idx++]; ++ num_rvs = patch[idx++]; ++ ret = avl6882_i2c_rd_reg(priv, src_addr, &data, length); ++ i = patch[idx]; ++ variable_array[i] = data; ++ break; ++ case PATCH_CMD_DMA: ++ dest_addr = patch[idx++]; ++ length = patch[idx++]; ++ if (length > 0) ++ ret = avl6882_i2c_wr_data(priv, dest_addr, &patch[idx], length * 3); ++ AVL6882_WR_REG32(priv,0x200 + rc_fw_command_args_addr_iaddr_offset, dest_addr); ++ ret = avl6882_exec_n_wait(priv,AVL_FW_CMD_DMA); ++ idx += length * 3; ++ num_rvs = patch[idx++]; ++ break; ++ case PATCH_CMD_DECOMPRESS: ++ type = patch[idx++]; ++ src_addr = patch[idx++]; ++ dest_addr = patch[idx++]; ++ if(type == PATCH_CMP_TYPE_ZLIB) { ++ ref_addr = patch[idx++]; ++ ref_size = patch[idx++]; ++ } ++ AVL6882_WR_REG32(priv,0x200 + rc_fw_command_args_addr_iaddr_offset, args_addr); ++ AVL6882_WR_REG32(priv,args_addr+0, type); ++ AVL6882_WR_REG32(priv,args_addr+4, src_addr); ++ AVL6882_WR_REG32(priv,args_addr+8, dest_addr); ++ if(type == PATCH_CMP_TYPE_ZLIB) { ++ AVL6882_WR_REG32(priv,args_addr+12, ref_addr); ++ AVL6882_WR_REG32(priv,args_addr+16, ref_size); ++ } ++ ret = avl6882_exec_n_wait(priv,AVL_FW_CMD_DECOMPRESS); ++ num_rvs = patch[idx++]; ++ break; ++ case PATCH_CMD_ASSERT_CPU_RESET: ++ ret |= AVL6882_WR_REG32(priv,0x110840, 1); ++ num_rvs = patch[idx++]; ++ break; ++ case PATCH_CMD_RELEASE_CPU_RESET: ++ AVL6882_WR_REG32(priv, 0x110840, 0); ++ num_rvs = patch[idx++]; ++ break; ++ case PATCH_CMD_DMA_HW: ++ dest_addr = patch[idx++]; ++ length = patch[idx++]; ++ if (length > 0) ++ ret = avl6882_i2c_wr_data(priv, dest_addr, &patch[idx], length * 3); ++ i = 0; ++ do { ++ if (i++ > DMA_MAX_TRIES) ++ return -ENODEV; ++ ret |= AVL6882_RD_REG32(priv, 0x110048, &data); ++ } while (!(0x01 & data)); ++ ++ if (data) ++ ret |= AVL6882_WR_REG32(priv, 0x110050, dest_addr); ++ idx += length * 3; ++ num_rvs = patch[idx++]; ++ break; ++ case PATCH_CMD_SET_COND_IMM: ++ data = patch[idx++]; ++ num_rvs = patch[idx++]; ++ i = patch[idx]; ++ variable_array[i] = data; ++ break; ++ default: ++ return -ENODEV; ++ break; ++ } ++ idx += num_rvs; ++ } else { ++ idx = next_cmd_idx; ++ continue; ++ } ++ } ++ ++ return ret; ++} ++ ++#define DEMOD_WAIT_RETRIES_BOOT (100) ++#define DEMOD_WAIT_MS_BOOT (20) ++static int avl6882_wait_demod_boot(struct avl6882_priv *priv) ++{ ++ int ret, retry = DEMOD_WAIT_RETRIES_BOOT; ++ u32 ready_code = 0; ++ u32 status = 0; ++ ++ do { ++ ret = AVL6882_RD_REG32(priv, 0x110840, &status); ++ ret |= AVL6882_RD_REG32(priv, rs_core_ready_word_iaddr_offset, &ready_code); ++ if ((ret == 0) && (status == 0) && (ready_code == 0x5aa57ff7)) ++ return ret; ++ else ++ msleep(DEMOD_WAIT_MS_BOOT); ++ } while (--retry); ++ ret = -EBUSY; ++ return ret; ++} ++ ++ ++/* firmware loader */ ++static int avl6882_load_firmware(struct avl6882_priv *priv) ++{ ++ struct avl6882_fw *fw; ++ int ret = 0; ++ ++ switch (priv->delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ fw = &priv->fw[AVL6882_FW_DVBC]; ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ fw = &priv->fw[AVL6882_FW_DVBS]; ++ break; ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ fw = &priv->fw[AVL6882_FW_DVBT]; ++ break; ++ } ++ ++ ret |= AVL6882_WR_REG32(priv, 0x110010, 1); ++ ret |= avl6882_setup_pll(priv); ++ if (ret) ++ goto err; ++ ret |= AVL6882_WR_REG32(priv, 0x0a4 + rs_core_ready_word_iaddr_offset, 0x00000000); ++ ret |= AVL6882_WR_REG32(priv, 0x110010, 0); ++ ++ /* check patch version - only v1 supported */ ++ if ((fw->data[0] & 0xff) != 1) ++ return -EINVAL; ++ ++ ret |= avl6882_patch_demod(priv, fw->data); ++ if (ret) ++ return ret; ++ ret = avl6882_wait_demod_boot(priv); ++err: ++ return ret; ++} ++ ++ ++ ++int ErrorStatMode_Demod( struct avl6882_priv *priv,AVL_ErrorStatConfig stErrorStatConfig ) ++{ ++ int r = AVL_EC_OK; ++ u64 time_tick_num = 270000 * stErrorStatConfig.uiTimeThresholdMs; ++ ++ r = AVL6882_WR_REG32(priv,0x132050 + esm_mode_offset,(u32) stErrorStatConfig.eErrorStatMode); ++ r |= AVL6882_WR_REG32(priv,0x132050 + tick_type_offset,(u32) stErrorStatConfig.eAutoErrorStatType); ++ ++ r |= AVL6882_WR_REG32(priv,0x132050 + time_tick_low_offset, (u32) (time_tick_num)); ++ r |= AVL6882_WR_REG32(priv,0x132050 + time_tick_high_offset, (u32) (time_tick_num >> 32)); ++ ++ r |= AVL6882_WR_REG32(priv,0x132050 + byte_tick_low_offset, stErrorStatConfig.uiTimeThresholdMs); ++ r |= AVL6882_WR_REG32(priv,0x132050 + byte_tick_high_offset, 0);//high 32-bit is not used ++ ++ if(stErrorStatConfig.eErrorStatMode == AVL_ERROR_STAT_AUTO)//auto mode ++ { ++ //reset auto error stat ++ r |= AVL6882_WR_REG32(priv,0x132050 + tick_clear_offset,0); ++ r |= AVL6882_WR_REG32(priv,0x132050 + tick_clear_offset,1); ++ r |= AVL6882_WR_REG32(priv,0x132050 + tick_clear_offset,0); ++ } ++ ++ return (r); ++} ++ ++ ++int ResetPER_Demod( struct avl6882_priv *priv) ++{ ++ int r = AVL_EC_OK; ++ u32 uiTemp = 0; ++ ++ r |= AVL6882_RD_REG32(priv,0x132050 + esm_cntrl_offset, &uiTemp); ++ uiTemp |= 0x00000001; ++ r |= AVL6882_WR_REG32(priv,0x132050 + esm_cntrl_offset, uiTemp); ++ ++ r |= AVL6882_RD_REG32(priv,0x132050 + esm_cntrl_offset, &uiTemp); ++ uiTemp |= 0x00000008; ++ r |= AVL6882_WR_REG32(priv,0x132050 + esm_cntrl_offset, uiTemp); ++ uiTemp |= 0x00000001; ++ r |= AVL6882_WR_REG32(priv,0x132050 + esm_cntrl_offset, uiTemp); ++ uiTemp &= 0xFFFFFFFE; ++ r |= AVL6882_WR_REG32(priv,0x132050 + esm_cntrl_offset, uiTemp); ++ ++ return r; ++} ++ ++static int InitErrorStat_Demod( struct avl6882_priv *priv ) ++{ ++ int r = AVL_EC_OK; ++ AVL_ErrorStatConfig stErrorStatConfig; ++ ++ stErrorStatConfig.eErrorStatMode = AVL_ERROR_STAT_AUTO; ++ stErrorStatConfig.eAutoErrorStatType = AVL_ERROR_STAT_TIME; ++ stErrorStatConfig.uiTimeThresholdMs = 3000; ++ stErrorStatConfig.uiNumberThresholdByte = 0; ++ ++ r = ErrorStatMode_Demod(priv,stErrorStatConfig); ++ r |= ResetPER_Demod(priv); ++ ++ return r; ++} ++ ++ ++ ++ ++ ++static int avl6882_init_diseqc( struct avl6882_priv *priv,AVL_Diseqc_Para *pDiseqcPara) ++{ ++ int r; ++ u32 i1 = 0; ++ ++ r = AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_srst_offset, 1); ++ ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_samp_frac_n_offset, 2000000); //2M=200*10kHz ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_samp_frac_d_offset, 166666667); //uiDDCFrequencyHz 166666667 ++ ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tone_frac_n_offset, ((pDiseqcPara->uiToneFrequencyKHz)<<1)); ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tone_frac_d_offset, (166666667/1000));//uiDDCFrequencyHz 166666667 ++ ++ // Initialize the tx_control ++ r |= AVL6882_RD_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, &i1); ++ i1 &= 0x00000300; ++ i1 |= 0x20; //reset tx_fifo ++ i1 |= ((u32)(pDiseqcPara->eTXGap) << 6); ++ i1 |= ((u32)(pDiseqcPara->eTxWaveForm) << 4); ++ i1 |= (1<<3); //enable tx gap. ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, i1); ++ i1 &= ~(0x20); //release tx_fifo reset ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, i1); ++ ++ // Initialize the rx_control ++ i1 = ((u32)(pDiseqcPara->eRxWaveForm) << 2); ++ i1 |= (1<<1); //active the receiver ++ i1 |= (1<<3); //envelop high when tone present ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_rx_cntrl_offset, i1); ++ i1 = (u32)(pDiseqcPara->eRxTimeout); ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_rx_msg_tim_offset, i1); ++ ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_srst_offset, 0); ++ ++ return r; ++} ++ ++ ++static int avl6882_init_dvbs(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ AVL_Diseqc_Para stDiseqcConfig; ++ ++ ret = AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_int_mpeg_clk_MHz_saddr_offset,27000); ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_int_fec_clk_MHz_saddr_offset,25000); ++ ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_int_adc_clk_MHz_saddr_offset,12500);// uiADCFrequencyHz 125000000 ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_int_dmd_clk_MHz_saddr_offset,166666667/10000); //uiDDCFrequencyHz 166666667 ++ ++ ret |= AVL6882_WR_REG32(priv, 0xe00 + rc_DVBSx_rfagc_pol_iaddr_offset,AVL_AGC_INVERTED); ++ ++ ret |= AVL6882_WR_REG32(priv, 0xe00 + rc_DVBSx_format_iaddr_offset, AVL_OFFBIN);//Offbin ++ ret |= AVL6882_WR_REG32(priv, 0xe00 + rc_DVBSx_input_iaddr_offset, AVL_ADC_IN);//ADC in ++ ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_IF_Offset_10kHz_saddr_offset,0); ++ ++ /* enble agc */ ++ ret |= avl6882_gpio_set(priv, GPIO_AGC_DVBS, GPIO_AGC_ON); ++ ++ stDiseqcConfig.eRxTimeout = AVL_DRT_150ms; ++ stDiseqcConfig.eRxWaveForm = AVL_DWM_Normal; ++ stDiseqcConfig.uiToneFrequencyKHz = 22; ++ stDiseqcConfig.eTXGap = AVL_DTXG_15ms; ++ stDiseqcConfig.eTxWaveForm = AVL_DWM_Normal; ++ ++ ret |= avl6882_init_diseqc(priv, &stDiseqcConfig); ++ return ret; ++} ++ ++ ++static int avl6882_init_dvbc(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ ++ ret = AVL6882_WR_REG32(priv, 0x600 + rc_DVBC_dmd_clk_Hz_iaddr_offset, 250000000); ++ ret |= AVL6882_WR_REG32(priv, 0x600 + rc_DVBC_fec_clk_Hz_iaddr_offset, 250000000); ++ ret |= AVL6882_WR_REG8(priv, 0x600 + rc_DVBC_rfagc_pol_caddr_offset,AVL_AGC_NORMAL); ++ ret |= AVL6882_WR_REG32(priv, 0x600 + rc_DVBC_if_freq_Hz_iaddr_offset, 5000000); ++ ret |= AVL6882_WR_REG8(priv, 0x600 + rc_DVBC_adc_sel_caddr_offset, (u8) AVL_IF_Q); ++ ret |= AVL6882_WR_REG32(priv, 0x600 + rc_DVBC_symbol_rate_Hz_iaddr_offset, 6875000); ++ ret |= AVL6882_WR_REG8(priv, 0x600 + rc_DVBC_j83b_mode_caddr_offset, AVL_DVBC_J83A); ++ ++ //DDC configuration ++ ret |= AVL6882_WR_REG8(priv, 0x600 + rc_DVBC_input_format_caddr_offset, AVL_ADC_IN); //ADC in ++ ret |= AVL6882_WR_REG8(priv, 0x600 + rc_DVBC_input_select_caddr_offset, AVL_OFFBIN); //RX_OFFBIN ++ ret |= AVL6882_WR_REG8(priv, 0x600 + rc_DVBC_tuner_type_caddr_offset, AVL_DVBC_IF); //IF ++ ++ //ADC configuration ++ ret |= AVL6882_WR_REG8(priv, 0x600 + rc_DVBC_adc_use_pll_clk_caddr_offset, 0); ++ ret |= AVL6882_WR_REG32(priv, 0x600 + rc_DVBC_sample_rate_Hz_iaddr_offset, 30000000); ++ ++ /* enable agc */ ++ ret |= avl6882_gpio_set(priv, GPIO_AGC_DVBTC, GPIO_AGC_ON); ++ return ret; ++} ++ ++ ++static int avl6882_init_dvbt(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ ++ ret = AVL6882_WR_REG32(priv, 0xa00 + rc_DVBTx_sample_rate_Hz_iaddr_offset, 30000000); ++ ret |= AVL6882_WR_REG32(priv, 0xa00 + rc_DVBTx_mpeg_clk_rate_Hz_iaddr_offset, 270000000); ++ ++ /* DDC configuration */ ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_input_format_caddr_offset, AVL_OFFBIN); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_input_select_caddr_offset, AVL_ADC_IN); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_tuner_type_caddr_offset, AVL_DVBTX_REAL_IF); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_rf_agc_pol_caddr_offset, 0); ++ ret |= AVL6882_WR_REG32(priv, 0xa00 + rc_DVBTx_nom_carrier_freq_Hz_iaddr_offset, 5000000); ++ ++ /* ADC configuration */ ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_adc_sel_caddr_offset, (u8)AVL_IF_Q); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_adc_use_pll_clk_caddr_offset, 0); ++ ++ /* enable agc */ ++ ret |= avl6882_gpio_set(priv, GPIO_AGC_DVBTC, GPIO_AGC_ON); ++ return ret; ++} ++ ++ ++static int avl6882_read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ u32 reg; ++ ++ *status = 0; ++ ++ switch (priv->delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ ret = AVL6882_RD_REG32(priv,0x400 + rs_DVBC_mode_status_iaddr_offset, ®); ++ if ((reg & 0xff) == 0x15) ++ reg = 1; ++ else ++ reg = 0; ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ ret = AVL6882_RD_REG16(priv, 0xc00 + rs_DVBSx_fec_lock_saddr_offset, ®); ++ break; ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ ret = AVL6882_RD_REG8(priv, 0x800 + rs_DVBTx_fec_lock_caddr_offset, ®); ++ break; ++ } ++ if (ret) { ++ *status = 0; ++ return ret; ++ } ++ ++ if (reg) ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ ++ return ret; ++} ++ ++ ++static int avl6882_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ ++ dev_dbg(&priv->i2c->dev, "%s: %d\n", __func__, enable); ++ ++ if (enable) { ++ ret = AVL6882_WR_REG32(priv,0x118000 + tuner_i2c_bit_rpt_cntrl_offset, 0x07); ++ } else ++ ret = AVL6882_WR_REG32(priv,0x118000 + tuner_i2c_bit_rpt_cntrl_offset, 0x06); ++ ++ return ret; ++} ++ ++ ++static int avl6882_set_dvbs(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ ++ //printk("[avl6882_set_dvbs] Freq:%d Mhz,sym:%d Khz\n", c->frequency, c->symbol_rate); ++ ++ ret = AVL6882_WR_REG16(priv, 0xc00 + rs_DVBSx_fec_lock_saddr_offset, 0); ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_decode_mode_saddr_offset, 0x14); ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_fec_bypass_coderate_saddr_offset, 0); //DVBS auto lock ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_iq_mode_saddr_offset, 1); //enable spectrum auto detection ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_decode_mode_saddr_offset, 0x14); ++ ret |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_fec_bypass_coderate_saddr_offset, 0); ++ ret |= AVL6882_WR_REG32(priv, 0xe00 + rc_DVBSx_int_sym_rate_MHz_iaddr_offset, c->symbol_rate); ++ ret |= avl6882_exec_n_wait(priv,AVL_FW_CMD_ACQUIRE); ++ return ret; ++} ++ ++ ++static int avl6882_set_dvbc(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ ++ //printk("[avl6882_set_dvbc] Freq:%d Mhz,sym:%d\n", c->frequency, c->symbol_rate); ++ ++ ret = AVL6882_WR_REG32(priv, 0x600 + rc_DVBC_qam_mode_scan_control_iaddr_offset, 0x0101); ++ ret |= AVL6882_WR_REG32(priv, 0x600 + rc_DVBC_symbol_rate_Hz_iaddr_offset, c->symbol_rate); ++ ret |= avl6882_exec_n_wait(priv, AVL_FW_CMD_ACQUIRE); ++ return ret; ++} ++ ++ ++static int avl6882_set_dvbt(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u32 bw_fft; ++ int ret; ++ ++ //printk("[avl6882_set_dvbtx] Freq:%d bw:%d\n", c->frequency, c->bandwidth_hz); ++ ++ /* set bandwidth */ ++ if(c->bandwidth_hz <= 1700000) { ++ bw_fft = 1845070; ++ } else if(c->bandwidth_hz <= 5000000) { ++ bw_fft = 5714285; ++ } else if(c->bandwidth_hz <= 6000000) { ++ bw_fft = 6857143; ++ } else if(c->bandwidth_hz <= 7000000) { ++ bw_fft = 8000000; ++ } else { // if(c->bandwidth_hz <= 8000) { ++ bw_fft = 9142857; ++ } ++ ret = AVL6882_WR_REG32(priv, 0xa00 + rc_DVBTx_fund_rate_Hz_iaddr_offset, bw_fft); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_l1_proc_only_caddr_offset, 0); ++ ++ /* spectrum inversion */ ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_spectrum_invert_caddr_offset, AVL_SPECTRUM_AUTO); ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_acquire_mode_caddr_offset, (u8) AVL_DVBTx_LockMode_T_ONLY); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_dvbt_layer_select_caddr_offset, 0); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_data_PLP_ID_caddr_offset, 0); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_ID_caddr_offset, 0); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_present_caddr_offset, 0); ++ break; ++ case SYS_DVBT2: ++ default: ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_acquire_mode_caddr_offset, AVL_DVBTx_LockMode_ALL); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_data_PLP_ID_caddr_offset, c->stream_id); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_ID_caddr_offset, 0); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_present_caddr_offset, 2); ++ break; ++ } ++ ret |= avl6882_exec_n_wait(priv, AVL_FW_CMD_ACQUIRE); ++ return ret; ++} ++ ++static int avl6882_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ //printk("%s()\n", __func__); ++ *ucblocks = 0x00; ++ return 0; ++} ++ ++static void avl6882_release(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int i; ++ //printk("%s()\n", __func__); ++ for (i = 0; i < AVL6882_FW_COUNT; i++) ++ kfree(priv->fw[i].data); ++ kfree(priv); ++} ++ ++static int avl6882_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret = 0; ++ u32 tmp; ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ ret = AVL6882_RD_REG16(priv, ++ 0x800 + rs_DVBTx_post_viterbi_BER_estimate_x10M_iaddr_offset, ++ &tmp); ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ ret = AVL6882_RD_REG16(priv, ++ 0xc00 + rs_DVBSx_post_viterbi_BER_estimate_x10M_iaddr_offset, ++ &tmp); ++ break; ++ case SYS_DVBC_ANNEX_A: ++ ret = AVL6882_RD_REG16(priv, ++ 0x400 + rs_DVBC_post_viterbi_BER_estimate_x10M_iaddr_offset, ++ &tmp); ++ break; ++ } ++ ++ *ber = tmp; ++ return ret; ++} ++ ++static int avl6882_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) ++{ ++ //printk("%s()\n", __func__); ++ return 0; ++} ++ ++static int avl6882_set_tone(struct dvb_frontend* fe, enum fe_sec_tone_mode tone) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ u32 reg; ++ ++ ret = AVL6882_RD_REG32(priv, 0x16c000 + hw_diseqc_tx_cntrl_offset, ®); ++ if (ret) ++ return ret; ++ ++ switch(tone) { ++ case SEC_TONE_ON: ++ reg &= 0xfffffff8; ++ reg |= 0x3; // continuous mode ++ reg |= (1<<10); // on ++ break; ++ case SEC_TONE_OFF: ++ reg &= 0xfffff3ff; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, reg); ++} ++ ++static int avl6882_set_voltage(struct dvb_frontend* fe, enum fe_sec_voltage voltage) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ u32 pwr, vol; ++ int ret; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ pwr = GPIO_1; ++ vol = GPIO_0; ++ break; ++ case SEC_VOLTAGE_13: ++ pwr = GPIO_0; ++ vol = GPIO_0; ++ break; ++ case SEC_VOLTAGE_18: ++ pwr = GPIO_0; ++ vol = GPIO_Z; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ret = avl6882_gpio_set(priv, GPIO_LNB_PWR, pwr); ++ ret |= avl6882_gpio_set(priv, GPIO_LNB_VOLT, vol); ++ return ret; ++} ++ ++/* diseqc master command */ ++static int avl6882_diseqc_send_master_cmd(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *d) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ u8 tx_done, tx_remain, continuous_flag = 0; ++ int i, ret, timeout = 0; ++ u32 reg, tmp; ++ ++ if (d->msg_len > 8) ++ return -EINVAL; ++ ++ // reset rx_fifo ++ ret = AVL6882_RD_REG32(priv, 0x16c000 + hw_diseqc_rx_cntrl_offset, &tmp); ++ ret |= AVL6882_WR_REG32(priv, 0x16c000 + hw_diseqc_rx_cntrl_offset, tmp | 1); ++ ret |= AVL6882_WR_REG32(priv, 0x16c000 + hw_diseqc_rx_cntrl_offset, tmp & ~1); ++ ++ ret = AVL6882_RD_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, ®); ++ if (reg & 0x400) { ++ /* remember tone setting */ ++ continuous_flag = 1; ++ /* turn off tone */ ++ reg &= 0xfffff3ff; ++ } ++ ++ // set to modulation mode and load FIFO ++ reg &= 0xfffffff8; ++ ret |= AVL6882_WR_REG32(priv, 0x16c000 + hw_diseqc_tx_cntrl_offset, reg); ++ for (i = 0; i < d->msg_len; i++) ++ ret |= AVL6882_WR_REG32(priv, 0x16c000 + hw_tx_fifo_map_offset, (u32) d->msg[i]); ++ msleep(20); ++ ++ // start tx ++ reg |= 4; ++ ret |= AVL6882_WR_REG32(priv, 0x16c000 + hw_diseqc_tx_cntrl_offset, reg); ++ do { ++ ret |= AVL6882_RD_REG32(priv, 0x16c000 + hw_diseqc_tx_st_offset, &tmp); ++ tx_done = (u8) ((tmp & 0x00000040) >> 6); ++ tx_remain = (u8) ((tmp & 0x0000003c) >> 2); ++ msleep(20); ++ if (++timeout > 25) ++ ret = -ETIMEDOUT; ++ } while ((tx_done == 0) || ret); ++ ++ if (continuous_flag) { ++ /* restore tone */ ++ reg &= 0xfffffff8; ++ reg |= 0x403; ++ ret |= AVL6882_WR_REG32(priv, 0x16c000 + hw_diseqc_tx_cntrl_offset, reg); ++ } ++ return ret; ++} ++ ++ ++static int avl6882_init(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++ ++ ++#define I2C_RPT_DIV ((0x2A)*(250000)/(240*1000)) //m_CoreFrequency_Hz 250000000 ++ ++static int avl6882_set_dvbmode(struct dvb_frontend *fe, ++ enum fe_delivery_system delsys) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ u32 reg; ++ ++ /* these modes use the same fw / config */ ++ if (delsys == SYS_DVBS2) ++ delsys = SYS_DVBS; ++ else if (delsys == SYS_DVBT2) ++ delsys = SYS_DVBT; ++ ++ /* already in the requested mode */ ++ if (priv->delivery_system == delsys) ++ return 0; ++ ++ priv->delivery_system = delsys; ++ //printk("initing demod for delsys=%d\n", delsys); ++ ++ ret = avl6882_load_firmware(priv); ++ ++ // Load the default configuration ++ ret |= avl6882_exec_n_wait(priv, AVL_FW_CMD_LD_DEFAULT); ++ ret |= avl6882_exec_n_wait(priv, AVL_FW_CMD_INIT_SDRAM); ++ ret |= avl6882_exec_n_wait(priv, AVL_FW_CMD_INIT_ADC); ++ ++ switch (priv->delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ ret |= avl6882_init_dvbc(fe); ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ ret |= avl6882_init_dvbs(fe); ++ break; ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ ret |= avl6882_init_dvbt(fe); ++ break; ++ } ++ ++ /* set gpio / turn off lnb, set 13V */ ++ ret = avl6882_gpio_set(priv, GPIO_LNB_PWR, GPIO_1); ++ ret |= avl6882_gpio_set(priv, GPIO_LNB_VOLT, GPIO_0); ++ ++ /* set TS mode */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_serial_caddr_offset, AVL_TS_PARALLEL); ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_clock_edge_caddr_offset, AVL_MPCM_RISING); ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_enable_ts_continuous_caddr_offset, AVL_TS_CONTINUOUS_ENABLE); ++ ++ /* TS serial pin */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_serial_outpin_caddr_offset, AVL_MPSP_DATA0); ++ /* TS serial order */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_serial_msb_caddr_offset, AVL_MPBO_MSB); ++ /* TS serial sync pulse */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_sync_pulse_caddr_offset, AVL_TS_SERIAL_SYNC_1_PULSE); ++ /* TS error pol */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_error_polarity_caddr_offset, AVL_MPEP_Normal); ++ /* TS valid pol */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_valid_polarity_caddr_offset, AVL_MPVP_Normal); ++ /* TS packet len */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_packet_len_caddr_offset, AVL_TS_188); ++ /* TS parallel order */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + rc_ts_packet_order_caddr_offset, AVL_TS_PARALLEL_ORDER_NORMAL); ++ /* TS parallel phase */ ++ ret |= AVL6882_WR_REG8(priv, 0x200 + ts_clock_phase_caddr_offset, AVL_TS_PARALLEL_PHASE_0); ++ ++ /* TS output enable */ ++ ret |= AVL6882_WR_REG32(priv, AVLREG_TS_OUTPUT, TS_OUTPUT_ENABLE); ++ ++ /* init tuner i2c repeater */ ++ /* hold in reset */ ++ ret |= AVL6882_WR_REG32(priv, 0x118000 + tuner_i2c_srst_offset, 1); ++ /* close gate */ ++ ret |= avl6882_i2c_gate_ctrl(fe, 0); ++ //ret |= AVL6882_WR_REG32(priv, 0x118000 + tuner_i2c_bit_rpt_cntrl_offset, 0x6); ++ ret |= AVL6882_RD_REG32(priv, 0x118000 + tuner_i2c_cntrl_offset, ®); ++ reg &= 0xfffffffe; ++ ret |= AVL6882_WR_REG32(priv, 0x118000 + tuner_i2c_cntrl_offset, reg); ++ /* set bit clock */ ++ ret |= AVL6882_WR_REG32(priv, 0x118000 + tuner_i2c_bit_rpt_clk_div_offset, I2C_RPT_DIV); ++ /* release from reset */ ++ ret |= AVL6882_WR_REG32(priv, 0x118000 + tuner_i2c_srst_offset, 0); ++ ++ ret |= InitErrorStat_Demod(priv); ++ ++ if (ret) { ++ dev_err(&priv->i2c->dev, "%s: demod init failed", ++ KBUILD_MODNAME); ++ } ++ ++ return ret; ++} ++ ++static int avl6882_sleep(struct dvb_frontend *fe) ++{ ++ //printk("%s()\n", __func__); ++ return 0; ++} ++ ++ ++static int avl6882fe_strength(struct dvb_frontend *fe, u16 *signal_strength) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ int ret; ++ u32 tmp; ++ ret = AVL6882_RD_REG16(priv,0x0a4 + rs_rf_agc_saddr_offset, &tmp); ++ ++ *signal_strength = (u16) tmp; ++ return 0; ++} ++ ++static int avl6882fe_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret = 0; ++ u32 tmp; ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ ret = AVL6882_RD_REG16(priv, ++ 0x800 + rs_DVBTx_snr_dB_x100_saddr_offset, ++ &tmp); ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ ret = AVL6882_RD_REG32(priv, ++ 0xc00 + rs_DVBSx_int_SNR_dB_iaddr_offset, ++ &tmp); ++ break; ++ case SYS_DVBC_ANNEX_A: ++ //reg = 0x400 + rs_DVBC_snr_dB_x100_saddr_offset; ++ break; ++ } ++ ++ if (tmp > 10000) ++ *snr = 0; ++ else ++ *snr = (u16) (tmp * 10); ++ return ret; ++} ++ ++static int avl6882fe_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++static int avl6882_set_frontend(struct dvb_frontend *fe) ++{ ++ struct avl6882_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u32 demod_mode; ++ int ret; ++ ++ //printk("%s() mode=%d\n", __func__, c->delivery_system); ++ ++ /* check that mode is correctly set */ ++ ret = AVL6882_RD_REG32(priv, 0x200 + rs_current_active_mode_iaddr_offset, &demod_mode); ++ if (ret) ++ return ret; ++ ++ /* setup tuner */ ++ if (fe->ops.tuner_ops.set_params) { ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ ret = fe->ops.tuner_ops.set_params(fe); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ if (ret) ++ return ret; ++ } ++ //printk("%s() demod_mode=%d\n", __func__, demod_mode); ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ if (demod_mode != AVL_DVBTX) { ++ dev_err(&priv->i2c->dev, "%s: failed to enter DVBTx mode", ++ KBUILD_MODNAME); ++ ret = -EAGAIN; ++ break; ++ } ++ ret = avl6882_set_dvbt(fe); ++ break; ++ case SYS_DVBC_ANNEX_A: ++ if (demod_mode != AVL_DVBC) { ++ dev_err(&priv->i2c->dev, "%s: failed to enter DVBC mode", ++ KBUILD_MODNAME); ++ ret = -EAGAIN; ++ break; ++ } ++ ret = avl6882_set_dvbc(fe); ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ if (demod_mode != AVL_DVBSX) { ++ dev_err(&priv->i2c->dev, "%s: failed to enter DVBSx mode", ++ KBUILD_MODNAME); ++ ret = -EAGAIN; ++ break; ++ } ++ ret = avl6882_set_dvbs(fe); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int avl6882_tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, unsigned int *delay, enum fe_status *status) ++{ ++ *delay = HZ / 5; ++ if (re_tune) { ++ int ret = avl6882_set_frontend(fe); ++ if (ret) ++ return ret; ++ } ++ return avl6882_read_status(fe, status); ++} ++ ++static int avl6882_get_frontend(struct dvb_frontend *fe, ++ struct dtv_frontend_properties *c) ++{ ++ return 0; ++} ++ ++static int avl6882_set_property(struct dvb_frontend *fe, ++ struct dtv_property *p) ++{ ++ int ret = 0; ++ ++ switch (p->cmd) { ++ case DTV_DELIVERY_SYSTEM: ++ //printk("DTV_set_prop delsys %d\n", p->u.data); ++ ret = avl6882_set_dvbmode(fe, p->u.data); ++ if (ret) { ++ printk("error set_dvbmode\n"); ++ } ++ switch (p->u.data) { ++ case SYS_DVBC_ANNEX_A: ++ fe->ops.info.frequency_min = 47000000; ++ fe->ops.info.frequency_max = 862000000; ++ fe->ops.info.frequency_stepsize = 62500; ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ fe->ops.info.frequency_min = 950000; ++ fe->ops.info.frequency_max = 2150000; ++ fe->ops.info.frequency_stepsize = 0; ++ break; ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ fe->ops.info.frequency_min = 174000000; ++ fe->ops.info.frequency_max = 862000000; ++ fe->ops.info.frequency_stepsize = 250000; ++ break; ++ } ++ ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static int avl6882_get_property(struct dvb_frontend *fe, ++ struct dtv_property *p) ++{ ++ int ret = 0; ++ u16 tmp; ++ u32 tmp2; ++ ++ switch (p->cmd) { ++ case DTV_STAT_CNR: ++ ret |= avl6882fe_snr(fe, &tmp); ++ p->u.st.stat[0].scale = FE_SCALE_DECIBEL; ++ p->u.st.stat[0].svalue = tmp; ++ ++ if (tmp > 25000) ++ tmp2 = 0xffff; ++ else ++ tmp2 = (tmp * 0xffff) / 25000; ++ p->u.st.stat[1].scale = FE_SCALE_RELATIVE; ++ p->u.st.stat[1].svalue = (u16) tmp2; ++ p->u.st.len = 2; ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static struct dvb_frontend_ops avl6882_ops = { ++ .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A, SYS_DVBS, SYS_DVBS2}, ++ .info = { ++ .name = "Availink AVL6882", ++ .frequency_min = 0, ++ .frequency_max = 0, ++ .frequency_stepsize = 0, ++ .frequency_tolerance = 0, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = FE_CAN_FEC_1_2 | ++ FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_4_5 | ++ FE_CAN_FEC_5_6 | ++ FE_CAN_FEC_6_7 | ++ FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_QAM_16 | ++ FE_CAN_QAM_32 | ++ FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | ++ FE_CAN_QAM_256 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_MUTE_TS | ++ FE_CAN_2G_MODULATION | ++ FE_CAN_MULTISTREAM | ++ FE_CAN_INVERSION_AUTO ++ }, ++ ++ .release = avl6882_release, ++ .init = avl6882_init, ++ ++ .sleep = avl6882_sleep, ++ .i2c_gate_ctrl = avl6882_i2c_gate_ctrl, ++ ++ .read_status = avl6882_read_status, ++ .read_ber = avl6882_read_ber, ++ .read_signal_strength = avl6882fe_strength, ++ .read_snr = avl6882fe_snr, ++ .read_ucblocks = avl6882_read_ucblocks, ++ .set_tone = avl6882_set_tone, ++ .set_voltage = avl6882_set_voltage, ++ .diseqc_send_master_cmd = avl6882_diseqc_send_master_cmd, ++ .diseqc_send_burst = avl6882_burst, ++ .get_frontend_algo = avl6882fe_algo, ++ .tune = avl6882_tune, ++ ++ .set_property = avl6882_set_property, ++ .get_property = avl6882_get_property, ++ .set_frontend = avl6882_set_frontend, ++ .get_frontend = avl6882_get_frontend, ++}; ++ ++ ++static int avl6882_setup_firmware(struct avl6882_priv *priv) ++{ ++ const struct firmware *fw; ++ struct avl6882_fw *afw = priv->fw; ++ int ret, i; ++ u32 *ptr, size = 0; ++ ++ ret = request_firmware(&fw, AVL6882_FIRMWARE, priv->i2c->dev.parent); ++ if (ret) { ++ dev_err(&priv->i2c->dev, "Error loading firmware: %s " ++ "(timeout or file not found?)\n", AVL6882_FIRMWARE); ++ goto err1; ++ } ++ if (fw->size < AVL6882_FW_HEADER_SIZE) { ++ dev_err(&priv->i2c->dev, "Error loading firmware: %s " ++ "(invalid file size?)\n", AVL6882_FIRMWARE); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ ptr = (u32*) fw->data; ++ ++ for (i = 0; i < AVL6882_FW_COUNT; i++) { ++ afw[i].offset = le32_to_cpu(*ptr++); ++ afw[i].size = le32_to_cpu(*ptr++) & 0xfffffffc; ++ size += afw[i].size; ++ } ++ ++ if (size != fw->size - AVL6882_FW_HEADER_SIZE) { ++ dev_err(&priv->i2c->dev, "Error loading firmware: %s " ++ "(invalid fw size?)\n", AVL6882_FIRMWARE); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ for (i = 0; i < AVL6882_FW_COUNT; i++) { ++ afw[i].data = kzalloc(afw[i].size, GFP_KERNEL); ++ if (afw[i].data == NULL) { ++ dev_err(&priv->i2c->dev, "Error loading firmware: %s " ++ "(not enough mem)\n", AVL6882_FIRMWARE); ++ ret = -ENOMEM; ++ goto err3; ++ } ++ ptr = (u32*) &fw->data[afw[i].offset]; ++ for (size = 0; size < afw[i].size / 4; size++) ++ afw[i].data[size] = be32_to_cpu(*ptr++); ++ /* check valid FW */ ++ if ((afw[i].data[0] & 0xf0000000) != 0x10000000) { ++ dev_err(&priv->i2c->dev, "Error loading firmware: %s " ++ "(invalid fw)\n", AVL6882_FIRMWARE); ++ ret = -EINVAL; ++ goto err3; ++ } ++ } ++ ++ return ret; ++err3: ++ while (--i >= 0) ++ kfree(afw[i].data); ++err2: ++ release_firmware(fw); ++err1: ++ return ret; ++} ++ ++struct dvb_frontend *avl6882_attach(struct avl6882_config *config, ++ struct i2c_adapter *i2c) ++{ ++ struct avl6882_priv *priv; ++ int ret; ++ u32 id, fid; ++ ++ ++ priv = kzalloc(sizeof(struct avl6882_priv), GFP_KERNEL); ++ if (priv == NULL) ++ goto err; ++ ++ memcpy(&priv->frontend.ops, &avl6882_ops, ++ sizeof(struct dvb_frontend_ops)); ++ ++ priv->frontend.demodulator_priv = priv; ++ priv->config = config; ++ priv->i2c = i2c; ++ priv->g_nChannel_ts_total = 0, ++ priv->delivery_system = -1; ++ ++ /* get chip id */ ++ ret = AVL6882_RD_REG32(priv, 0x108000, &id); ++ /* get chip family id */ ++ ret |= AVL6882_RD_REG32(priv, 0x40000, &fid); ++ if (ret) { ++ dev_err(&priv->i2c->dev, "%s: attach failed reading id", ++ KBUILD_MODNAME); ++ goto err1; ++ } ++ ++ if (fid != 0x68624955) { ++ dev_err(&priv->i2c->dev, "%s: attach failed family id mismatch", ++ KBUILD_MODNAME); ++ goto err1; ++ } ++ ++ dev_info(&priv->i2c->dev, "%s: found id=0x%x " \ ++ "family_id=0x%x", KBUILD_MODNAME, id, fid); ++ ++ /* setup firmware */ ++ if (avl6882_setup_firmware(priv)) ++ goto err1; ++ ++ return &priv->frontend; ++ ++err1: ++ kfree(priv); ++err: ++ return NULL; ++} ++EXPORT_SYMBOL(avl6882_attach); ++ ++MODULE_DESCRIPTION("Availink AVL6882 DVB demodulator driver"); ++MODULE_AUTHOR("Luis Alves (ljalvs@gmail.com)"); ++MODULE_LICENSE("GPL"); ++MODULE_FIRMWARE(AVL6882_FIRMWARE); ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++#if 0 ++static int DVBSx_GetSignalQuality_Demod(struct avl6882_priv *priv, AVL_puint16 puiQuality ) ++{ ++ int r = AVL_EC_OK; ++ u32 uiTemp = 0; ++ ++ r = DVBSx_GetSNR_Demod(priv,&uiTemp); ++ if(uiTemp > 2500) { ++ *puiQuality = 100; ++ } else { ++ *puiQuality = uiTemp*100/2500; ++ } ++ ++ return r; ++} ++ ++int AVL_Demod_GetSQI ( struct avl6882_priv *priv,AVL_puint16 pusSQI) ++{ ++ int r = AVL_EC_OK; ++ ++ *pusSQI = 0; ++ r=DVBSx_GetSignalQuality_Demod(priv,pusSQI); ++ ++ return (r); ++} ++#endif ++ ++ ++ ++ ++ ++#if 0 ++ ++ ++ ++static int AVL_LockChannel_T2(struct avl6882_priv *priv, u32 Freq_Khz, u32 BandWidth_Khz, u8 T2_Profile, AVL_int32 PLP_ID) ++{ ++ int ret; ++ AVL_DVBTxBandWidth nBand = AVL_DVBTx_BW_8M; ++ AVL_DVBTx_LockMode eDVBTxLockMode; ++ AVL_DVBT2_PROFILE eDVTB2Profile = (AVL_DVBT2_PROFILE) T2_Profile; ++ ++ printk("[AVL_LockChannel_T2] Freq:%d Mhz,sym:%d Khz\n",Freq_Khz,BandWidth_Khz); ++ ++ //return_code = r848_lock_n_wait(priv, Freq_Khz, BandWidth_Khz); ++ //AVL_Demod_DVBT2AutoLock(priv, nBand, , PLP_ID); ++ ++ ret = AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_l1_proc_only_caddr_offset, 0); ++ if (eDVTB2Profile == AVL_DVBT2_PROFILE_BASE) { ++ eDVBTxLockMode = AVL_DVBTx_LockMode_T2BASE; ++ } else if (eDVTB2Profile == AVL_DVBT2_PROFILE_LITE) { ++ eDVBTxLockMode = AVL_DVBTx_LockMode_T2LITE; ++ } else { ++ eDVBTxLockMode = AVL_DVBTx_LockMode_ALL; ++ } ++ ++ nBand = Convert2DemodBand(BandWidth_Khz); ++ ret |= DVBTx_SetBandWidth_Demod(priv, nBand); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_acquire_mode_caddr_offset, (u8) eDVBTxLockMode); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_spectrum_invert_caddr_offset, AVL_SPECTRUM_AUTO); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_data_PLP_ID_caddr_offset, PLP_ID); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_ID_caddr_offset, 0); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_present_caddr_offset, 2); ++ ret |= avl6882_exec_n_wait(priv,AVL_FW_CMD_ACQUIRE); ++ if (ret) ++ printk("[AVL_LockChannel_DVBT2] Failed to lock the channel!\n"); ++ return ret; ++} ++ ++ ++static int AVL_LockChannel_T(struct avl6882_priv *priv,u32 Freq_Khz,u16 BandWidth_Khz, AVL_int32 DVBT_layer_info) ++{ ++ int ret; ++ AVL_DVBTxBandWidth nBand = AVL_DVBTx_BW_8M; ++ ++ printk("[AVL_LockChannel_T] Freq is %d MHz, Bandwide is %d MHz, Layer Info is %d (0 : LP; 1 : HP)\n", ++ Freq_Khz/1000, BandWidth_Khz/1000, DVBT_layer_info); ++ ++ //ret = r848_lock_n_wait(priv, Freq_Khz, BandWidth_Khz); ++ nBand = Convert2DemodBand(BandWidth_Khz); ++ //AVL_Demod_DVBTAutoLock ++ ret = AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_l1_proc_only_caddr_offset, 0); ++ ret |= DVBTx_SetBandWidth_Demod(priv, nBand); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_acquire_mode_caddr_offset, (u8) AVL_DVBTx_LockMode_T_ONLY); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_spectrum_invert_caddr_offset, AVL_SPECTRUM_AUTO); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_dvbt_layer_select_caddr_offset, DVBT_layer_info); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_data_PLP_ID_caddr_offset, 0); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_ID_caddr_offset, 0); ++ ret |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_common_PLP_present_caddr_offset, 0); ++ ret |= avl6882_exec_n_wait(priv, AVL_FW_CMD_ACQUIRE); ++ if(ret) ++ printk("[AVL_LockChannel_T] Failed to lock the channel!\n"); ++ ++ return ret; ++} ++ ++ ++ ++ ++static int IBase_SendRxOP_Demod(struct avl6882_priv *priv,u8 cmd) ++{ ++ int ret = avl6882_wait_demod(priv); ++ if (ret) ++ return ret; ++ return AVL6882_WR_REG16(priv, 0x200 + rc_fw_command_saddr_offset, (u32) cmd); ++} ++ ++int TestSDRAM_Demod( struct avl6882_priv *priv,AVL_puint32 puiTestResult, AVL_puint32 puiTestPattern) ++{ ++ int r = AVL_EC_OK; ++ u16 uiTimeDelay = 100; ++ u16 uiMaxRetries = 200; ++ u32 i=0; ++ ++ r = IBase_SendRxOP_Demod(priv,AVL_FW_CMD_SDRAM_TEST); ++ if(AVL_EC_OK == r ) ++ { ++ ++ r |= avl6882_wait_demod(priv); ++/* while (AVL_EC_OK != IBase_GetRxOPStatus_Demod(priv)) ++ { ++ if (uiMaxRetries < i++) ++ { ++ r |= AVL_EC_RUNNING; ++ break; ++ } ++ msleep(uiTimeDelay); ++ }*/ ++ ++ r |= AVL6882_RD_REG32(priv,0x0a4 + rc_sdram_test_return_iaddr_offset, puiTestPattern); ++ r |= AVL6882_RD_REG32(priv,0x0a4 + rc_sdram_test_result_iaddr_offset, puiTestResult); ++ } ++ ++ return r; ++} ++ ++static int avl6882_demod_lock_wait(struct avl6882_priv *priv, u8 *lock_flag) ++{ ++ int ret, retry = 50; ++ enum fe_status locked; ++ do { ++ ret = avl6882_read_status(&priv->frontend, &locked); ++ if (ret) { ++ *lock_flag = 0; ++ break; ++ } ++ if (locked) { ++ *lock_flag = 1; ++ break; ++ } ++ msleep(20); ++ } while (--retry); ++ return ret; ++} ++ ++int AVL_Demod_DVBTxChannelScan(struct avl6882_priv *priv, AVL_DVBTxBandWidth eBandWidth, AVL_DVBTx_LockMode eLockMode) ++{ ++ int r = AVL_EC_OK; ++ ++ r = DVBTx_SetBandWidth_Demod(priv,eBandWidth); ++ r |= AVL6882_WR_REG8(priv,0xa00 + rc_DVBTx_acquire_mode_caddr_offset, eLockMode); ++ r |= AVL6882_WR_REG8(priv, 0xa00 + rc_DVBTx_l1_proc_only_caddr_offset, 1); ++ r |= avl6882_exec_n_wait(priv,AVL_FW_CMD_ACQUIRE); ++ ++ return r; ++} ++ ++ ++int AVL_Demod_DVBTxGetScanInfo(struct avl6882_priv *priv, AVL_DVBTxScanInfo* pstDVBTxScanInfo) ++{ ++ int r = AVL_EC_OK; ++ u32 ucTemp0 = 0; ++ u32 ucTemp1 = 0; ++ enum fe_status ucDemodLockStatus; ++ ++ r = avl6882_read_status(&priv->frontend, &ucDemodLockStatus); ++ if(ucDemodLockStatus == 0) ++ return r; ++ ++ r |= AVL6882_RD_REG8(priv, 0x800 + rs_DVBTx_rx_mode_caddr_offset, ++ &ucTemp0); ++ ++ pstDVBTxScanInfo->eTxStandard = (AVL_DVBTx_Standard)ucTemp0; ++ ++ ++ if(AVL_DVBTx_Standard_T == pstDVBTxScanInfo->eTxStandard) ++ { ++ r |= AVL6882_RD_REG8(priv, 0x8f0 + rs_DVBTx_hierarchy_caddr_offset,&ucTemp0); ++ } ++ else if(AVL_DVBTx_Standard_T2 == pstDVBTxScanInfo->eTxStandard) ++ { ++ r |= AVL6882_RD_REG8(priv,0x800 + rs_DVBTx_P1_S2_field_2_caddr_offset, &ucTemp1); ++ r |= AVL6882_RD_REG8(priv, 0x800 + rs_DVBTx_T2_profile_caddr_offset, &ucTemp0); ++ } ++ ++ pstDVBTxScanInfo->ucTxInfo = ucTemp0; ++ pstDVBTxScanInfo->ucFEFInfo = ucTemp1; ++ ++ return r; ++} ++ ++ ++ ++ ++static int AVL_Demod_DVBT2GetPLPList(struct avl6882_priv *priv, AVL_puchar pucPLPIndexArray, AVL_puchar pucPLPNumber) ++{ ++ int r = AVL_EC_OK; ++ u32 ucTemp = 0; ++ u32 uiPLPBuffer = 0x2912b4; ++ u32 ucPLPID = 0; ++ u32 ucPLPType = 0; ++ u32 ucPLPGroupID = 0; ++ u32 i = 0; ++ u8 ucDataPLPNum = 0; ++ u32 uiDelayMS = 20; ++ u32 uiTimes = 10; //time-out window 10*20 = 200ms ++ enum fe_status ucDemodLockStatus = 0; ++ ++ r = avl6882_read_status(&priv->frontend, &ucDemodLockStatus); ++ if (ucDemodLockStatus == 0) { ++ *pucPLPNumber = 0; ++ return r; ++ } ++ ++ for(i = 0; i < uiTimes; i++) ++ { ++ msleep(uiDelayMS); ++ r |= AVL6882_RD_REG8(priv,0x800 + rs_DVBTx_plp_list_request_caddr_offset, &ucTemp); ++ if(ucTemp == 0) ++ { ++ break; ++ } ++ } ++ ++ if(i == uiTimes) ++ { ++ r |= AVL_EC_GENERAL_FAIL; ++ return (r); ++ } ++ ++ r |= AVL6882_RD_REG8(priv,0x830 + rs_DVBTx_NUM_PLP_caddr_offset, &ucTemp); ++ ++ ++ for(i = 0; ifrequency/1000; ++ u16 BandWidth_Khz = c->bandwidth_hz/1000; ++ ++ int return_code = AVL_EC_OK; ++ AVL_DVBTxScanInfo stDVBTxScanInfo; ++ AVL_DVBTxBandWidth nBand = AVL_DVBTx_BW_8M; ++ u16 cur_index = 0; ++ u8 ucLockFlag = 0; ++ AVL_DVBT2_PROFILE ucT2Profile = AVL_DVBT2_PROFILE_UNKNOWN; ++ u8 ucDataPLPArray[255] = {0}; ++ u8 ucDataPLPNumber = 0; ++ u16 i; ++ ++ printk("[AVL_ChannelScan_Tx] Freq is %d MHz BW is %d MHz \n", ++ Freq_Khz/1000, BandWidth_Khz/1000); ++ ++ priv->g_nChannel_ts_total = 0; ++ ++ //=====Tuner Lock=====// ++ return_code = r848_lock_n_wait(priv, Freq_Khz, c->bandwidth_hz); ++ //=====Demod Lock=====// ++ nBand = Convert2DemodBand(BandWidth_Khz); ++ return_code = AVL_Demod_DVBTxChannelScan(priv, nBand, AVL_DVBTx_LockMode_ALL); ++ //=====Check Lock Status =====// ++ avl6882_demod_lock_wait(priv, &ucLockFlag); ++ ++ if(ucLockFlag == 1) { //DVBTx is locked ++ return_code |= AVL_Demod_DVBTxGetScanInfo(priv, &stDVBTxScanInfo); ++ if(stDVBTxScanInfo.eTxStandard == AVL_DVBTx_Standard_T2) { ++ //get PLP ID list only for DVBT2 signal, not for DVBT ++ cur_index = priv->g_nChannel_ts_total; ++ return_code = AVL_Demod_DVBT2GetPLPList(priv, ucDataPLPArray, &ucDataPLPNumber); ++ ++ for (i = 0; i < ucDataPLPNumber; i++) { ++ printk("[DVB-T2_Scan_Info] DATA PLP ID is %d, profile = %d\n", ++ ucDataPLPArray[i], stDVBTxScanInfo.ucTxInfo); ++ ++ //save channel RF frequency ++ priv->global_channel_ts_table[cur_index].channel_freq_khz = Freq_Khz; ++ // save channel bandwidth ++ priv->global_channel_ts_table[cur_index].channel_bandwith_khz = BandWidth_Khz; ++ // save data plp id ++ priv->global_channel_ts_table[cur_index].data_plp_id = ucDataPLPArray[i]; ++ // 0 - DVBT; 1 - DVBT2. ++ priv->global_channel_ts_table[cur_index].channel_type = AVL_DVBTx_Standard_T2; ++ // 0 - Base profile; 1 - Lite profile. ++ priv->global_channel_ts_table[cur_index].channel_profile = (AVL_DVBT2_PROFILE)stDVBTxScanInfo.ucTxInfo; ++ cur_index++; ++ } ++ priv->g_nChannel_ts_total = cur_index % MAX_CHANNEL_INFO; ++ if (stDVBTxScanInfo.ucFEFInfo == 1) { ++ ucT2Profile = (AVL_DVBT2_PROFILE) stDVBTxScanInfo.ucTxInfo; ++ if (ucT2Profile == AVL_DVBT2_PROFILE_BASE) { ++ //profile is base ++ //If T2 base is locked, try to lock T2 lite ++ AVL_Demod_DVBTxChannelScan(priv, nBand, AVL_DVBTx_LockMode_T2LITE); ++ ucT2Profile = AVL_DVBT2_PROFILE_LITE; ++ } else { ++ //If T2 lite is locked, try to lock T2 base ++ AVL_Demod_DVBTxChannelScan(priv, nBand, AVL_DVBTx_LockMode_T2BASE); ++ ucT2Profile = AVL_DVBT2_PROFILE_BASE; ++ } ++ avl6882_demod_lock_wait(priv, &ucLockFlag); ++ if (ucLockFlag == 1) { ++ //DVBTx is locked ++ cur_index = priv->g_nChannel_ts_total; ++ ucDataPLPNumber = 0; ++ return_code = AVL_Demod_DVBT2GetPLPList(priv, ucDataPLPArray, &ucDataPLPNumber); ++ ++ // data PLP ID and common PLP ID pairing ++ for (i = 0; i < ucDataPLPNumber; i++) { ++ printk("[DVB-T2_Scan_Info] DATA PLP ID is %d, profile = %d\n", ++ ucDataPLPArray[i], ucT2Profile); ++ ++ //save channel RF frequency ++ priv->global_channel_ts_table[cur_index].channel_freq_khz = Freq_Khz; ++ // save channel bandwidth ++ priv->global_channel_ts_table[cur_index].channel_bandwith_khz = BandWidth_Khz; ++ // save data plp id ++ priv->global_channel_ts_table[cur_index].data_plp_id = ucDataPLPArray[i]; ++ // 0 - DVBT; 1 - DVBT2. ++ priv->global_channel_ts_table[cur_index].channel_type = AVL_DVBTx_Standard_T2; ++ // 0 - Base profile; 1 - Lite profile. ++ priv->global_channel_ts_table[cur_index].channel_profile = ucT2Profile; ++ ++ cur_index++; ++ } ++ priv->g_nChannel_ts_total = cur_index % MAX_CHANNEL_INFO; ++ } ++ } else { ++ printk("Lock DVB-T2: No FEFInfo\n"); ++ } ++ } else { ++ // DVBT ++ cur_index = priv->g_nChannel_ts_total; ++ // save channel RF frequency ++ priv->global_channel_ts_table[cur_index].channel_freq_khz = Freq_Khz; ++ // save channel bandwidth ++ priv->global_channel_ts_table[cur_index].channel_bandwith_khz = BandWidth_Khz; ++ // save data plp id(not used for DVBT, set to 0xff) ++ priv->global_channel_ts_table[cur_index].data_plp_id = 0; ++ // 0 - DVBT; 1 - DVBT2. ++ priv->global_channel_ts_table[cur_index].channel_type = AVL_DVBTx_Standard_T; ++ // 0 - Low priority layer, 1 - High priority layer ++ priv->global_channel_ts_table[cur_index].dvbt_hierarchy_layer = 1; ++ cur_index++; ++ ++ if(stDVBTxScanInfo.ucTxInfo == 1) { ++ // for hierarchy ++ // save channel RF frequency ++ priv->global_channel_ts_table[cur_index].channel_freq_khz = Freq_Khz; ++ // save channel bandwidth ++ priv->global_channel_ts_table[cur_index].channel_bandwith_khz = BandWidth_Khz; ++ // save data plp id(not used for DVBT, set to 0xff) ++ priv->global_channel_ts_table[cur_index].data_plp_id = 0; ++ // 0 - DVBT; 1 - DVBT2. ++ priv->global_channel_ts_table[cur_index].channel_type = AVL_DVBTx_Standard_T; ++ // 0 - Low priority layer, 1 - High priority layer ++ priv->global_channel_ts_table[cur_index].dvbt_hierarchy_layer = 0; ++ cur_index++; ++ } ++ priv->g_nChannel_ts_total = cur_index % MAX_CHANNEL_INFO; ++ } ++ } else { ++ // return for unlock ++ printk("[DVBTx_ScanChannel_Tx] DVBTx channel scan is fail,Err.\n"); ++ } ++ ++ /* lock channel */ ++ for(i = 0; i < priv->g_nChannel_ts_total; i++) { ++ ucLockFlag = 0; ++ if(priv->global_channel_ts_table[i].channel_type == AVL_DVBTx_Standard_T) { ++ //DVB-T signal.. ++ AVL_LockChannel_T(priv, Freq_Khz, BandWidth_Khz, priv->global_channel_ts_table[i].dvbt_hierarchy_layer); ++ } else if (priv->global_channel_ts_table[i].channel_type == AVL_DVBTx_Standard_T2) { ++ //DVB-T2 signal, do not process FEF... ++ AVL_LockChannel_T2(priv, Freq_Khz, BandWidth_Khz,priv->global_channel_ts_table[i].channel_profile, priv->global_channel_ts_table[i].data_plp_id); ++ } ++ avl6882_demod_lock_wait(priv, &ucLockFlag); ++ } ++ ++ return return_code; ++} ++ ++ ++ ++ ++int AVL_Demod_DVBSx_Diseqc_SendTone( struct avl6882_priv *priv,u8 ucTone, u8 ucCount) ++{ ++ int r = 0; ++ u32 i1 = 0; ++ u32 i2 = 0; ++ //u8 pucBuffTemp[8] = {0}; ++ u8 Continuousflag = 0; ++ u16 uiTempOutTh = 0; ++ ++ if( ucCount>8 ) ++ { ++ r = AVL_EC_WARNING; ++ } ++ else ++ { ++ if (priv->config->eDiseqcStatus == AVL_DOS_InContinuous) ++ { ++ r |= AVL6882_RD_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, &i1); ++ if ((i1>>10) & 0x01) ++ { ++ Continuousflag = 1; ++ i1 &= 0xfffff3ff; ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, i1); ++ msleep(Diseqc_delay); //delay 20ms ++ } ++ } ++ //No data in the FIFO. ++ r |= AVL6882_RD_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, &i1); ++ i1 &= 0xfffffff8; //put it into the FIFO load mode. ++ if( 0 == ucTone ) ++ { ++ i1 |= 0x01; ++ } ++ else ++ { ++ i1 |= 0x02; ++ } ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, i1); ++ ++ ++ for (i2 = 0; i2 < ucCount; i2++) { ++ r |= AVL6882_WR_REG32(priv, 0x16c000 + hw_tx_fifo_map_offset, 1); ++ } ++#if 0 ++ //trunk address ++ ChunkAddr_Demod(0x16c000 + hw_tx_fifo_map_offset, pucBuffTemp); ++ pucBuffTemp[3] = 0; ++ pucBuffTemp[4] = 0; ++ pucBuffTemp[5] = 0; ++ pucBuffTemp[6] = 1; ++ ++ for( i2=0; i2config->eDiseqcStatus = AVL_DOS_InTone; ++ } ++ do ++ { ++ msleep(1); ++ if (++uiTempOutTh > 500) ++ { ++ r |= AVL_EC_TIMEOUT; ++ return(r); ++ } ++ r = AVL6882_RD_REG32(priv,0x16c000 + hw_diseqc_tx_st_offset, &i1); ++ } while ( 1 != ((i1 & 0x00000040) >> 6) ); ++ ++ msleep(Diseqc_delay); //delay 20ms ++ if (Continuousflag == 1) //resume to send out wave ++ { ++ //No data in FIFO ++ r |= AVL6882_RD_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, &i1); ++ i1 &= 0xfffffff8; ++ i1 |= 0x03; //switch to continuous mode ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, i1); ++ ++ //start to send out wave ++ i1 |= (1<<10); ++ r |= AVL6882_WR_REG32(priv,0x16c000 + hw_diseqc_tx_cntrl_offset, i1); ++ ++ } ++ } ++ return (r); ++} ++ ++ ++ ++ ++ ++#endif ++ ++ ++ ++ ++#if 0 ++ ++ ++ ++ ++ ++ ++ ++int AVL_Demod_DVBSxManualLock( struct avl6882_priv *priv,AVL_DVBSxManualLockInfo *pstManualLockInfo) ++{ ++ int r = AVL_EC_OK; ++ AVL_FunctionalMode eFuncMode = AVL_FuncMode_BlindScan; ++ ++ ++ r = AVL_Demod_DVBSx_GetFunctionalMode(priv,&eFuncMode); ++ if(eFuncMode == AVL_FuncMode_Demod) ++ { ++ r |= AVL6882_WR_REG16(priv,0xc00 + rs_DVBSx_fec_lock_saddr_offset, 0); ++ ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_fec_bypass_coderate_saddr_offset, 1);//DVBS manual lock ++ ++ if (pstManualLockInfo->eDVBSxStandard == AVL_DVBS ) ++ { ++ r |= AVL6882_WR_REG32(priv, 0xe00 + rc_DVBSx_dvbs_fec_coderate_iaddr_offset, pstManualLockInfo->eDVBSCodeRate); ++ } ++ else if(pstManualLockInfo->eDVBSxStandard == AVL_DVBS2 ) ++ { ++ r |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_dvbs2_code_rate_saddr_offset, pstManualLockInfo->eDVBS2CodeRate); ++ r |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_dvbs2_modulation_saddr_offset, pstManualLockInfo->eDVBSxModulationMode); ++ } ++ else ++ { ++ return AVL_EC_NOT_SUPPORTED; ++ } ++ r |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_decode_mode_saddr_offset, pstManualLockInfo->eDVBSxStandard); ++ ++ if(pstManualLockInfo->eDVBSxSpecInversion == AVL_SPECTRUM_AUTO) ++ { ++ r |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_iq_mode_saddr_offset, 1);//enable spectrum auto detection ++ } ++ else ++ { ++ r |= AVL6882_WR_REG32(priv, 0xe00 + rc_DVBSx_specinv_iaddr_offset, pstManualLockInfo->eDVBSxSpecInversion); ++ r |= AVL6882_WR_REG16(priv, 0xe00 + rc_DVBSx_iq_mode_saddr_offset, 0); ++ } ++ ++ r |= AVL6882_WR_REG32(priv, 0xe00 + rc_DVBSx_int_sym_rate_MHz_iaddr_offset, pstManualLockInfo->uiDVBSxSymbolRateSps); ++ ++ r |= avl6882_exec_n_wait(priv,AVL_FW_CMD_ACQUIRE ); ++ } ++ else if(eFuncMode == AVL_FuncMode_BlindScan) ++ { ++ return AVL_EC_NOT_SUPPORTED; ++ } ++ ++ return (r); ++} ++int AVL_Demod_DVBSxGetModulationInfo( struct avl6882_priv *priv,AVL_DVBSxModulationInfo *pstModulationInfo) ++{ ++ int r = AVL_EC_OK; ++ u32 uiTemp = 0; ++ u32 temp_uchar = 0; ++ ++ r = AVL6882_RD_REG32(priv, 0xc00 + rs_DVBSx_pilot_iaddr_offset, &uiTemp); ++ pstModulationInfo->eDVBSxPilot = (AVL_DVBSx_Pilot)(uiTemp); ++ ++ r |= AVL6882_RD_REG32(priv, 0xe00 + rc_DVBSx_internal_decode_mode_iaddr_offset,&uiTemp); ++ pstModulationInfo->eDVBSxStandard = (AVL_DVBSx_Standard)uiTemp; ++ ++ if(AVL_DVBS == (AVL_DVBSx_Standard)uiTemp) ++ { ++ r |= AVL6882_RD_REG32(priv, 0xe00 + rc_DVBSx_dvbs_fec_coderate_iaddr_offset,&uiTemp); ++ pstModulationInfo->eDVBSCodeRate = (AVL_DVBS_CodeRate)(uiTemp); ++ } ++ else ++ { ++ r |= AVL6882_RD_REG8(priv, 0xe00 + rc_DVBSx_dvbs2_fec_coderate_caddr_offset,&temp_uchar); ++ pstModulationInfo->eDVBS2CodeRate = (AVL_DVBS2_CodeRate)(temp_uchar); ++ } ++ ++ r |= AVL6882_RD_REG32(priv, 0xc00 + rs_DVBSx_modulation_iaddr_offset, &uiTemp); ++ pstModulationInfo->eDVBSxModulationMode = (AVL_DVBSx_ModulationMode)(uiTemp); ++ ++ r |= AVL6882_RD_REG32(priv, 0xc00 + rs_DVBSx_detected_alpha_iaddr_offset, &uiTemp); ++ pstModulationInfo->eDVBSxRollOff = (AVL_DVBSx_RollOff)(uiTemp); ++ ++ return (r); ++ ++} ++ ++int AVL_Demod_DVBSx_BlindScan_Start( struct avl6882_priv *priv,AVL_BlindScanPara * pBSPara, u16 uiTunerLPF_100kHz) ++{ ++ int r = AVL_EC_OK; ++ u16 uiCarrierFreq_100kHz = 0; ++ u16 uiMinSymRate = 0; ++ AVL_FunctionalMode enumFunctionalMode = AVL_FuncMode_Demod; ++ ++ r = AVL_Demod_DVBSx_GetFunctionalMode(priv,&enumFunctionalMode); ++ ++ if (enumFunctionalMode == AVL_FuncMode_BlindScan) { ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_tuner_LPF_100kHz_saddr_offset, uiTunerLPF_100kHz); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_blind_scan_tuner_spectrum_inversion_saddr_offset, pBSPara->m_enumBSSpectrumPolarity); ++ ++ uiMinSymRate = pBSPara->m_uiMinSymRate_kHz - 200; // give some tolerance ++ ++ if (uiMinSymRate < 800) //Blind scan doesn't support symbol rate less then 1M, give 200K margin ++ { ++ uiMinSymRate = 800; ++ } ++ ++ if( pBSPara->m_uiStartFreq_100kHz < pBSPara->m_uiStopFreq_100kHz ) ++ { ++ if( AVL_EC_OK == r ) ++ { ++ uiCarrierFreq_100kHz = ((pBSPara->m_uiStopFreq_100kHz)+(pBSPara->m_uiStartFreq_100kHz))>>1; ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_tuner_frequency_100kHz_saddr_offset, uiCarrierFreq_100kHz); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_blind_scan_min_sym_rate_kHz_saddr_offset, uiMinSymRate); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_blind_scan_max_sym_rate_kHz_saddr_offset, (pBSPara->m_uiMaxSymRate_kHz)+200); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_blind_scan_start_freq_100kHz_saddr_offset, (pBSPara->m_uiStartFreq_100kHz)); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_blind_scan_end_freq_100kHz_saddr_offset, (pBSPara->m_uiStopFreq_100kHz)); ++ ++ if( AVL_EC_OK == r ) ++ { ++ r = avl6882_exec_n_wait(priv,AVL_FW_CMD_BLIND_SCAN); ++ } ++ } ++ } ++ else ++ { ++ r = AVL_EC_GENERAL_FAIL; ++ } ++ } ++ else ++ { ++ r = AVL_EC_GENERAL_FAIL; ++ } ++ ++ return (r); ++} ++#endif ++ ++#if 0 ++// need fix read data size ++int AVL_Demod_DVBSx_BlindScan_GetStatus( struct avl6882_priv *priv,AVL_BSInfo * pBSInfo) ++{ ++ int r = AVL_EC_OK; ++ ++ r = AVL6882_RD_REG16(priv,0xc00 + rs_DVBSx_blind_scan_progress_saddr_offset, &(pBSInfo->m_uiProgress)); ++ r |= AVL6882_RD_REG16(priv,0xc00 + rs_DVBSx_blind_scan_channel_count_saddr_offset, &(pBSInfo->m_uiChannelCount)); ++ r |= AVL6882_RD_REG16(priv,0xe00 + rc_DVBSx_blind_scan_start_freq_100kHz_saddr_offset, &(pBSInfo->m_uiNextStartFreq_100kHz)); ++ r |= AVL6882_RD_REG16(priv,0xc00 + rs_DVBSx_blind_scan_error_code_saddr_offset, &(pBSInfo->m_uiResultCode)); ++ if( pBSInfo->m_uiProgress > 100 ) ++ { ++ pBSInfo->m_uiProgress = 0; ++ } ++ ++ return(r); ++} ++ ++int AVL_Demod_DVBSx_BlindScan_Cancel( struct avl6882_priv *priv ) ++{ ++ int r; ++ enum AVL_FunctionalMode enumFunctionalMode = AVL_FuncMode_Demod; ++ ++ ++ ++ r = AVL_Demod_DVBSx_GetFunctionalMode(priv,&enumFunctionalMode); ++ ++ if(enumFunctionalMode == AVL_FuncMode_BlindScan) ++ { ++ r |= avl6882_exec_n_wait(priv,AVL_FW_CMD_HALT); ++ } ++ else ++ { ++ r = AVL_EC_GENERAL_FAIL; ++ } ++ ++ return(r); ++} ++ ++ ++int AVL_Demod_DVBSx_BlindScan_ReadChannelInfo( struct avl6882_priv *priv,u16 uiStartIndex, AVL_puint16 pChannelCount, AVL_ChannelInfo * pChannel) ++{ ++ int r = 0; ++ u32 channel_addr = 0; ++ u16 i1 = 0; ++ u16 i2 = 0; ++ u32 uiMinFreq = 0; ++ u16 iMinIdx = 0; ++ AVL_ChannelInfo sTempChannel; ++ ++ ++ ++ r = AVL6882_RD_REG16(priv,0xc00 + rs_DVBSx_blind_scan_channel_count_saddr_offset, &i1); ++ if( (uiStartIndex + (*pChannelCount)) > (i1) ) ++ { ++ *pChannelCount = i1-uiStartIndex; ++ } ++ r |= AVL6882_RD_REG16(priv,0xe00 + rc_DVBSx_blind_scan_channel_info_offset_saddr_offset, &i1); ++ channel_addr = 0x200C00 + uiStartIndex*sizeof(AVL_ChannelInfo); ++ for( i1=0; i1<(*pChannelCount); i1++ ) ++ { ++#if 1 //for some processors which can not read 12 bytes ++ //dump the channel information ++ r |= AVL6882_RD_REG32(priv, channel_addr, &(pChannel[i1].m_uiFrequency_kHz)); ++ channel_addr += 4; ++ r |= AVL6882_RD_REG32(priv, channel_addr, &(pChannel[i1].m_uiSymbolRate_Hz)); ++ channel_addr += 4; ++ r |= AVL6882_RD_REG32(priv, channel_addr, &(pChannel[i1].m_Flags)); ++ channel_addr += 4; ++#endif ++ } ++ ++ // Sort the results ++ for(i1=0; i1<(*pChannelCount); i1++) ++ { ++ iMinIdx = i1; ++ uiMinFreq = pChannel[i1].m_uiFrequency_kHz; ++ for(i2=(i1+1); i2<(*pChannelCount); i2++) ++ { ++ if(pChannel[i2].m_uiFrequency_kHz < uiMinFreq) ++ { ++ uiMinFreq = pChannel[i2].m_uiFrequency_kHz; ++ iMinIdx = i2; ++ } ++ } ++ sTempChannel = pChannel[iMinIdx]; ++ pChannel[iMinIdx] = pChannel[i1]; ++ pChannel[i1] = sTempChannel; ++ } ++ ++ return(r); ++} ++ ++ ++int AVL_Demod_DVBSx_BlindScan_Reset( struct avl6882_priv *priv ) ++{ ++ return AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_blind_scan_reset_saddr_offset, 1); ++} ++ ++ ++int AVL_Demod_DVBSx_SetFunctionalMode( struct avl6882_priv *priv,AVL_FunctionalMode enumFunctionalMode ) ++{ ++ int r = AVL_EC_OK; ++ r = AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_functional_mode_saddr_offset, (u16)enumFunctionalMode); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_iq_mode_saddr_offset,0); ++ return(r); ++} ++ ++int AVL_Demod_DVBSx_SetDishPointingMode( struct avl6882_priv *priv,AVL_Switch enumOn_Off) ++{ ++ int r = AVL_EC_OK; ++ AVL_FunctionalMode enumFunctionalMode = AVL_FuncMode_BlindScan; ++ ++ r |= AVL_Demod_DVBSx_GetFunctionalMode(priv,&enumFunctionalMode); ++ if(enumFunctionalMode == AVL_FuncMode_Demod) ++ { ++ if(enumOn_Off == AVL_ON) ++ { ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_aagc_acq_gain_saddr_offset, 12); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_dishpoint_mode_saddr_offset, 1); ++ } ++ else ++ { ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_aagc_acq_gain_saddr_offset, 10); ++ r |= AVL6882_WR_REG16(priv,0xe00 + rc_DVBSx_dishpoint_mode_saddr_offset, 0); ++ } ++ } ++ else ++ { ++ r = AVL_EC_GENERAL_FAIL; ++ } ++ ++ return(r); ++} ++#endif ++ ++ ++ ++ ++ ++ ++ ++ ++ ++#if 0 ++int AVL_Demod_GetVersion( struct avl6882_priv *priv,AVL_DemodVersion *pstDemodVersion) ++{ ++ int r = AVL_EC_OK; ++ u32 uiTemp = 0; ++ u8 ucBuff[4] = {0}; ++ ++ r = AVL6882_RD_REG32(priv,0x40000, &uiTemp); ++ if( AVL_EC_OK == r ) ++ { ++ pstDemodVersion->uiChip = uiTemp; ++ } ++ ++ r |= AVL6882_RD_REG32(priv,0x0a4 + rs_patch_ver_iaddr_offset, &uiTemp); ++ if( AVL_EC_OK == r ) ++ { ++ Chunk32_Demod(uiTemp, ucBuff); ++ pstDemodVersion->stPatch.ucMajor = ucBuff[0]; ++ pstDemodVersion->stPatch.ucMinor = ucBuff[1]; ++ pstDemodVersion->stPatch.usBuild = ucBuff[2]; ++ pstDemodVersion->stPatch.usBuild = ((u16)((pstDemodVersion->stPatch.usBuild)<<8)) + ucBuff[3]; ++ } ++ ++ return r; ++} ++#endif ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/drivers/media/dvb-frontends/avl6882.h b/drivers/media/dvb-frontends/avl6882.h +new file mode 100644 +index 0000000..9ede95d +--- /dev/null ++++ b/drivers/media/dvb-frontends/avl6882.h +@@ -0,0 +1,42 @@ ++/* ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++*/ ++ ++#ifndef AVL6882_H ++#define AVL6882_H ++ ++ ++struct avl6882_config { ++ /* the demodulator's i2c address */ ++ u8 demod_address; ++}; ++ ++ ++#if defined(CONFIG_DVB_AVL6882) || (defined(CONFIG_DVB_AVL6882_MODULE) && \ ++ defined(MODULE)) ++extern struct dvb_frontend *avl6882_attach(struct avl6882_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *avl6882_attach(struct avl6882_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_AVL6882 */ ++ ++#endif /* AVL6882_H */ +diff --git a/drivers/media/dvb-frontends/avl6882_priv.h b/drivers/media/dvb-frontends/avl6882_priv.h +new file mode 100644 +index 0000000..8e4b5e80f +--- /dev/null ++++ b/drivers/media/dvb-frontends/avl6882_priv.h +@@ -0,0 +1,1672 @@ ++#ifndef AVL6882_PRIV_H ++#define AVL6882_PRIV_H ++ ++#include "dvb_frontend.h" ++ ++ ++#define MAX_CHANNEL_INFO 256 ++ ++typedef struct s_DVBTx_Channel_TS ++{ ++ // number, example 474*1000 is RF frequency 474MHz. ++ int channel_freq_khz; ++ // number, example 8000 is 8MHz bandwith channel. ++ int channel_bandwith_khz; ++ ++ u8 channel_type; ++ // 0 - Low priority layer, 1 - High priority layer ++ u8 dvbt_hierarchy_layer; ++ // data PLP id, 0 to 255; for single PLP DVBT2 channel, this ID is 0; for DVBT channel, this ID isn't used. ++ u8 data_plp_id; ++ u8 channel_profile; ++}s_DVBTx_Channel_TS; ++ ++ ++ ++#define AVL6882_FW_DVBC 0 ++#define AVL6882_FW_DVBS 1 ++#define AVL6882_FW_DVBT 2 ++#define AVL6882_FW_ISDBT 3 ++ ++#define AVL6882_FW_COUNT 3 ++#define AVL6882_FW_HEADER_SIZE (8 * AVL6882_FW_COUNT) ++ ++ ++/* i2c */ ++#define MAX_I2C_READ_SIZE 64 ++#define MAX_I2C_WRITE_SIZE 62 ++//64 ++ ++ ++/* registers */ ++/* PLL */ ++#define AVLREG_PLL_RESET 0x00100000 ++#define AVLREG_PLL_dll_init 0x00100008 ++#define AVLREG_PLL_deglitch_mode 0x00100010 ++#define AVLREG_PLL_sys_pll_bypass 0x00100040 ++#define AVLREG_PLL_sys_pll_enable 0x00100044 ++#define AVLREG_PLL_sys_pll_divr 0x00100048 ++#define AVLREG_PLL_sys_pll_divf 0x0010004c ++#define AVLREG_PLL_sys_pll_divq 0x00100050 ++#define AVLREG_PLL_sys_pll_range 0x00100054 ++#define AVLREG_PLL_sys_pll_lock 0x00100058 ++#define AVLREG_PLL_mpeg_pll_bypass 0x0010005c ++#define AVLREG_PLL_mpeg_pll_enable 0x00100060 ++#define AVLREG_PLL_mpeg_pll_divr 0x00100064 ++#define AVLREG_PLL_mpeg_pll_divf 0x00100068 ++#define AVLREG_PLL_mpeg_pll_divq 0x0010006c ++#define AVLREG_PLL_mpeg_pll_range 0x00100070 ++#define AVLREG_PLL_mpeg_pll_lock 0x00100074 ++#define AVLREG_PLL_adc_pll_bypass 0x00100078 ++#define AVLREG_PLL_adc_pll_enable 0x0010007c ++#define AVLREG_PLL_adc_pll_divr 0x00100080 ++#define AVLREG_PLL_adc_pll_divf 0x00100084 ++#define AVLREG_PLL_adc_pll_divq 0x00100088 ++#define AVLREG_PLL_adc_pll_range 0x0010008c ++#define AVLREG_PLL_adc_pll_lock 0x00100090 ++#define AVLREG_PLL_mpeg_pll_reset 0x00100094 ++#define AVLREG_PLL_adc_pll_reset 0x00100098 ++#define AVLREG_PLL_sys_pll_reset 0x0010009c ++#define AVLREG_PLL_sys_pll_enable2 0x001000b4 ++#define AVLREG_PLL_sys_pll_enable3 0x001000b8 ++#define AVLREG_PLL_sys_pll_divq2 0x001000bc ++#define AVLREG_PLL_sys_pll_divq3 0x001000c0 ++#define AVLREG_PLL_mpeg_pll_enable2 0x001000c4 ++#define AVLREG_PLL_mpeg_pll_enable3 0x001000c8 ++#define AVLREG_PLL_mpeg_pll_divq2 0x001000cc ++#define AVLREG_PLL_mpeg_pll_divq3 0x001000d0 ++#define AVLREG_PLL_adc_pll_enable2 0x001000d4 ++#define AVLREG_PLL_adc_pll_enable3 0x001000d8 ++#define AVLREG_PLL_adc_pll_divq2 0x001000dc ++#define AVLREG_PLL_adc_pll_divq3 0x001000e0 ++#define AVLREG_PLL_ddc_clk_sel 0x001000e4 ++#define AVLREG_PLL_sdram_clk_sel 0x001000e8 ++#define AVLREG_PLL_dll_out_phase 0x00000100 ++#define AVLREG_PLL_dll_rd_phase 0x00000104 ++ ++/* TS */ ++#define AVLREG_TS_OUTPUT 0x00130420 ++#define TS_OUTPUT_ENABLE 0x00000000 ++#define TS_OUTPUT_DISABLE 0x00000fff ++ ++/* GPIO */ ++#define AVLREG_GPIO_BASE 0x00120000 ++#define GPIO_AGC_DVBTC (0x00) /* agc1_sel */ ++#define GPIO_AGC_DVBS (0x10) /* agc2_sel */ ++#define GPIO_LNB_VOLT (0x08) /* pin 38 - lnb_ctrl_1_sel */ ++#define GPIO_LNB_PWR (0x0c) /* pin 37 - lnb_ctrl_0_sel */ ++#define GPIO_RD_MASK (0x40) ++#define GPIO_0 (0) ++#define GPIO_1 (1) ++#define GPIO_Z (2) ++#define GPIO_AGC_ON (6) ++ ++ ++ ++//GPIO control ++#define lnb_cntrl_1_sel_offset 0x08 ++#define lnb_cntrl_0_sel_offset 0x0c ++ ++#define lnb_cntrl_1_i_offset 0x48 ++#define lnb_cntrl_0_i_offset 0x4c ++ ++ ++ ++ ++struct avl6882_fw { ++ u32 offset; ++ u32 size; ++ u32 *data; ++}; ++ ++struct avl6882_priv { ++ struct i2c_adapter *i2c; ++ struct avl6882_config *config; ++ struct dvb_frontend frontend; ++ enum fe_delivery_system delivery_system; ++ ++ /* DVB-Tx */ ++ u16 g_nChannel_ts_total; ++ s_DVBTx_Channel_TS global_channel_ts_table[MAX_CHANNEL_INFO]; ++ ++ struct avl6882_fw fw[AVL6882_FW_COUNT]; ++}; ++ ++ ++ ++ ++ ++typedef unsigned char AVL_semaphore; ///< the semaphore data type. ++ ++ ++ ++ ++ ++ ++/* known registers */ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++//SDK Version ++#define AVL_API_VER_MAJOR 0x02 ++#define AVL_API_VER_MINOR 0x03 ++#define AVL_API_VER_BUILD 0x02 ++ ++ ++#define AVL68XX 0x68624955 ++ ++#define AVL_FW_CMD_IDLE 0 ++#define AVL_FW_CMD_LD_DEFAULT 1 ++#define AVL_FW_CMD_ACQUIRE 2 ++#define AVL_FW_CMD_HALT 3 ++#define AVL_FW_CMD_DEBUG 4 ++#define AVL_FW_CMD_SLEEP 7 ++#define AVL_FW_CMD_WAKE 8 ++#define AVL_FW_CMD_BLIND_SCAN 9 ++#define AVL_FW_CMD_SDRAM_TEST 16 ++#define AVL_FW_CMD_INIT_SDRAM 17 ++#define AVL_FW_CMD_INIT_ADC 18 ++#define AVL_FW_CMD_CHANGE_MODE 19 ++ ++#define AVL_FW_CMD_DMA 21 ++#define AVL_FW_CMD_CALC_CRC 22 ++#define AVL_FW_CMD_PING 23 ++#define AVL_FW_CMD_DECOMPRESS 24 ++ ++ ++ ++/* ++ * Patch file stuff ++ */ ++#define PATCH_VAR_ARRAY_SIZE 32 ++ ++#define PATCH_CMD_VALIDATE_CRC 0 ++#define PATCH_CMD_PING 1 ++#define PATCH_CMD_LD_TO_DEVICE 2 ++#define PATCH_CMD_DMA 3 ++#define PATCH_CMD_DECOMPRESS 4 ++#define PATCH_CMD_ASSERT_CPU_RESET 5 ++#define PATCH_CMD_RELEASE_CPU_RESET 6 ++#define PATCH_CMD_LD_TO_DEVICE_IMM 7 ++#define PATCH_CMD_RD_FROM_DEVICE 8 ++#define PATCH_CMD_DMA_HW 9 ++#define PATCH_CMD_SET_COND_IMM 10 ++#define PATCH_CMD_EXIT 11 ++ ++ ++#define PATCH_CMP_TYPE_ZLIB 0 ++#define PATCH_CMP_TYPE_ZLIB_NULL 1 ++#define PATCH_CMP_TYPE_GLIB 2 ++#define PATCH_CMP_TYPE_NONE 3 ++ ++//Addr modes 2 bits ++#define PATCH_OP_ADDR_MODE_VAR_IDX 0 ++#define PATCH_OP_ADDR_MODE_IMMIDIATE 1 ++ ++//Unary operators 6 bits ++#define PATCH_OP_UNARY_NOP 0 ++#define PATCH_OP_UNARY_LOGICAL_NEGATE 1 ++#define PATCH_OP_UNARY_BITWISE_NEGATE 2 ++#define PATCH_OP_UNARY_BITWISE_AND 3 ++#define PATCH_OP_UNARY_BITWISE_OR 4 ++ ++//Binary operators 1 Byte ++#define PATCH_OP_BINARY_LOAD 0 ++#define PATCH_OP_BINARY_AND 1 ++#define PATCH_OP_BINARY_OR 2 ++#define PATCH_OP_BINARY_BITWISE_AND 3 ++#define PATCH_OP_BINARY_BITWISE_OR 4 ++#define PATCH_OP_BINARY_EQUALS 5 ++#define PATCH_OP_BINARY_STORE 6 ++#define PATCH_OP_BINARY_NOT_EQUALS 7 ++ ++#define PATCH_COND_EXIT_AFTER_LD 8 ++ ++ ++ ++ ++#define tuner_i2c_srst_offset 0x0 ++#define tuner_i2c_cntrl_offset 0x4 ++#define tuner_i2c_bit_rpt_clk_div_offset 0x18 ++#define tuner_i2c_bit_rpt_cntrl_offset 0x1C ++ ++#define esm_cntrl_offset 0x4 ++#define bit_error_offset 0x8 ++#define byte_num_offset 0xC ++#define packet_error_offset 0x10 ++#define packet_num_offset 0x14 ++#define tick_clear_offset 0x88 ++#define tick_type_offset 0x8C ++#define time_tick_low_offset 0x90 ++#define time_tick_high_offset 0x94 ++#define byte_tick_low_offset 0x98 ++#define byte_tick_high_offset 0x9C ++#define esm_mode_offset 0xC0 ++ ++#define rs_current_active_mode_iaddr_offset 0x24 ++#define rc_fw_command_saddr_offset 0x00 ++#define rs_core_ready_word_iaddr_offset 0xa0 ++#define rc_sdram_test_return_iaddr_offset 0x3C ++#define rc_sdram_test_result_iaddr_offset 0x40 ++#define rs_rf_agc_saddr_offset 0x44 ++ ++#define rc_fw_command_args_addr_iaddr_offset 0x58 ++ ++#define rc_ts_cntns_clk_frac_d_iaddr_offset 0x0000007c ++#define rc_ts_cntns_clk_frac_n_iaddr_offset 0x00000078 ++#define rc_enable_ts_continuous_caddr_offset 0x0000003a ++#define rc_ts_clock_edge_caddr_offset 0x0000003b ++#define rc_ts_serial_caddr_offset 0x0000003c ++#define rc_ts_serial_outpin_caddr_offset 0x0000003f ++#define rc_ts_serial_msb_caddr_offset 0x0000003e ++#define rc_ts_packet_len_caddr_offset 0x00000039 ++#define rc_ts_packet_order_caddr_offset rc_ts_serial_msb_caddr_offset ++#define rc_ts_error_bit_en_caddr_offset 0x000000000 ++#define rc_ts_error_polarity_caddr_offset 0x00000041 ++#define rc_ts_valid_polarity_caddr_offset 0x00000040 ++#define rc_ts_sync_pulse_caddr_offset 0x00000097 ++#define ts_clock_phase_caddr_offset 0x00000096 ++ ++#define rs_patch_ver_iaddr_offset 0x00000004 ++ ++#define hw_AVL_rx_rf_aagc_gain 0x160888 ++ ++ ++//Define ADC channel selection ++typedef enum AVL_ADC_Channel ++{ ++ AVL_ADC_CHAN2 = 0, ++ AVL_ADC_CHAN1 = 1, ++ AVL_ADC_OFF = 2 ++}AVL_ADC_Channel; ++ ++typedef enum AVL_ADC_Output_format ++{ ++ AVL_2COMP = 0, ++ AVL_OFFBIN = 1 ++}AVL_ADC_Output_format; ++ ++//Input_select enumeration definitions ++typedef enum AVL_DDC_Input ++{ ++ AVL_DIG_IN = 0, ++ AVL_ADC_IN = 1, ++ AVL_VEC_IN = 2, ++ AVL_VEC1x_IN = 3, ++ AVL_DIG1x_IN = 4 ++}AVL_DDC_Input; ++ ++// Defines BER type ++typedef enum AVL_BER_Type ++{ ++ AVL_PRE_VITERBI_BER = 0, // previous viterbi BER will be acquired. ++ AVL_POST_VITERBI_BER = 1, // post viterbi BER will be acquired. ++ AVL_PRE_LDPC_BER = 2, // previous LDPC BER will be acquired. ++ AVL_POST_LDPC_BER = 3, // post LDPC BER will be acquired. ++ AVL_FINAL_BER = 4 // final BER will be acquired. ++}AVL_BER_Type; ++ ++// Defines different standards supported by the demod. ++typedef enum AVL_DemodMode ++{ ++ AVL_DVBC = 0, ++ AVL_DVBSX = 1, ++ AVL_DVBTX = 2, ++ AVL_ISDBT = 3, ++ AVL_DTMB = 4, ++ AVL_ISDBS = 5, ++ AVL_ABSS = 6, ++ AVL_ATSC = 7, ++ AVL_DVBC2 = 8 ++} AVL_DemodMode; ++ ++// Defines the channel lock mode. ++typedef enum AVL_LockMode ++{ ++ AVL_LOCK_MODE_AUTO = 0, // lock channel automatically. ++ AVL_LOCK_MODE_MANUAL = 1 // lock channel manually. ++}AVL_LockMode; ++ ++// Defines channel lock status ++typedef enum AVL_LockStatus ++{ ++ AVL_STATUS_UNLOCK = 0, // channel isn't locked ++ AVL_STATUS_LOCK = 1 // channel is in locked state. ++}AVL_LockStatus; ++ ++typedef enum AVL_TSMode ++{ ++ AVL_TS_PARALLEL = 0, ++ AVL_TS_SERIAL = 1 ++}AVL_TSMode; ++ ++typedef enum AVL_TSClockEdge ++{ ++ AVL_MPCM_FALLING = 0, ++ AVL_MPCM_RISING = 1 ++} AVL_TSClockEdge; ++ ++typedef enum AVL_TSClockMode ++{ ++ AVL_TS_CONTINUOUS_ENABLE = 0, ++ AVL_TS_CONTINUOUS_DISABLE = 1 ++} AVL_TSClockMode; ++ ++typedef enum AVL_TSSerialPin ++{ ++ AVL_MPSP_DATA0 = 0, ++ AVL_MPSP_DATA7 = 1 ++} AVL_TSSerialPin; ++ ++typedef enum AVL_TSSerialOrder ++{ ++ AVL_MPBO_LSB = 0, ++ AVL_MPBO_MSB = 1 ++} AVL_TSSerialOrder; ++ ++typedef enum AVL_TSSerialSyncPulse ++{ ++ AVL_TS_SERIAL_SYNC_8_PULSE = 0, ++ AVL_TS_SERIAL_SYNC_1_PULSE = 1 ++} AVL_TSSerialSyncPulse; ++ ++typedef enum AVL_TSErrorBit ++{ ++ AVL_TS_ERROR_BIT_DISABLE = 0, ++ AVL_TS_ERROR_BIT_ENABLE = 1 ++} AVL_TSErrorBit; ++ ++typedef enum AVL_TSErrorPolarity ++{ ++ AVL_MPEP_Normal = 0, ++ AVL_MPEP_Invert = 1 ++} AVL_TSErrorPolarity; ++ ++typedef enum AVL_TSValidPolarity ++{ ++ AVL_MPVP_Normal = 0, ++ AVL_MPVP_Invert = 1 ++} AVL_TSValidPolarity; ++ ++typedef enum AVL_TSPacketLen ++{ ++ AVL_TS_188 = 0, ++ AVL_TS_204 = 1 ++} AVL_TSPacketLen; ++ ++typedef enum AVL_AGCPola ++{ ++ AVL_AGC_NORMAL = 0, // normal AGC polarity. Used for a tuner whose gain increases with increased AGC voltage. ++ AVL_AGC_INVERTED= 1 // inverted AGC polarity. Used for tuner whose gain decreases with increased AGC voltage. ++}AVL_AGCPola; ++ ++typedef enum AVL_TSParallelOrder ++{ ++ AVL_TS_PARALLEL_ORDER_INVERT = 0, ++ AVL_TS_PARALLEL_ORDER_NORMAL = 1 ++} AVL_TSParallelOrder; ++ ++typedef enum AVL_TSParallelPhase ++{ ++ AVL_TS_PARALLEL_PHASE_0 = 0, ++ AVL_TS_PARALLEL_PHASE_1 = 1, ++ AVL_TSG_PARALLEL_PHASE_2 = 2, ++ AVL_TS_PARALLEL_PHASE_3 = 3 ++}AVL_TSParallelPhase; ++ ++// Stores an unsigned 64-bit integer ++typedef struct AVLuint64 ++{ ++ u32 uiHighWord; // The most significant 32-bits of the unsigned 64-bit integer ++ u32 uiLowWord; // The least significant 32-bits of the unsigned 64-bit integer ++}AVLuint64; ++ ++ ++// Defines whether the feeback bit of the LFSR used to generate the BER/PER test pattern is inverted. ++typedef enum AVL_LFSR_FbBit ++{ ++ AVL_LFSR_FB_NOT_INVERTED = 0, // LFSR feedback bit isn't inverted ++ AVL_LFSR_FB_INVERTED = 1 // LFSR feedback bit is inverted ++}AVL_LFSR_FbBit; ++ ++// Defines the test pattern being used for BER/PER measurements. ++typedef enum AVL_TestPattern ++{ ++ AVL_TEST_LFSR_15 = 0, // BER test pattern is LFSR15 ++ AVL_TEST_LFSR_23 = 1 // BER test pattern is LFSR23 ++}AVL_TestPattern; ++ ++// Defines the type of auto error statistics ++typedef enum AVL_AutoErrorStat_Type ++{ ++ AVL_ERROR_STAT_BYTE = 0, // error statistics will be reset according to the number of received bytes. ++ AVL_ERROR_STAT_TIME = 1 // error statistics will be reset according to time interval. ++}AVL_AutoErrorStat_Type; ++ ++// Defines Error statistics mode ++typedef enum AVL_ErrorStat_Mode ++{ ++ AVL_ERROR_STAT_MANUAL = 0, ++ AVL_ERROR_STAT_AUTO = 1 ++}AVL_ErrorStat_Mode; ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++// Defines the DiSEqC status ++typedef enum AVL_DiseqcStatus ++{ ++ AVL_DOS_Uninitialized = 0, // DiSEqC has not been initialized yet. ++ AVL_DOS_Initialized = 1, // DiSEqC has been initialized. ++ AVL_DOS_InContinuous = 2, // DiSEqC is in continuous mode. ++ AVL_DOS_InTone = 3, // DiSEqC is in tone burst mode. ++ AVL_DOS_InModulation = 4 // DiSEqC is in modulation mode. ++}AVL_DiseqcStatus; ++ ++// Contains variables for storing error statistics used in the BER and PER calculations. ++typedef struct AVL_ErrorStats ++{ ++ u16 usLFSRSynced; // Indicates whether the receiver is synchronized with the transmitter generating the BER test pattern. ++ u16 usLostLock; // Indicates whether the receiver has lost lock since the BER/PER measurement was started. ++ AVLuint64 stSwCntNumBits; // A software counter which stores the number of bits which have been received. ++ AVLuint64 stSwCntBitErrors; // A software counter which stores the number of bit errors which have been detected. ++ AVLuint64 stNumBits; // The total number of bits which have been received. ++ AVLuint64 stBitErrors; // The total number of bit errors which have been detected. ++ AVLuint64 stSwCntNumPkts; // A software counter which stores the number of packets which have been received. ++ AVLuint64 stSwCntPktErrors; // A software counter which stores the number of packet errors which have been detected. ++ AVLuint64 stNumPkts; // The total number of packets which have been received. ++ AVLuint64 stPktErrors; // The total number of packet errors which have been detected. ++ u32 uiBER; // The bit error rate scaled by 1e9. ++ u32 uiPER; // The packet error rate scaled by 1e9. ++}AVL_ErrorStats; ++ ++typedef enum AVL_Demod_Xtal ++{ ++ Xtal_30M = 0, ++ Xtal_16M, ++ Xtal_24M, ++ Xtal_27M ++} AVL_Demod_Xtal; ++ ++typedef enum AVL_InputPath ++{ ++ AVL_IF_I, ++ AVL_IF_Q ++} AVL_InputPath; ++ ++// Contains variables for storing error statistics used in the BER and PER calculations. ++typedef struct AVL_ErrorStatConfig ++{ ++ AVL_ErrorStat_Mode eErrorStatMode; // indicates the error statistics mode. ++ AVL_AutoErrorStat_Type eAutoErrorStatType; // indicates the MPEG data sampling clock mode. ++ u32 uiTimeThresholdMs; // used to set time interval for auto error statistics. ++ u32 uiNumberThresholdByte; // used to set the received byte number threshold for auto error statistics. ++}AVL_ErrorStatConfig; ++ ++// Contains variables for storing error statistics used in the BER and PER calculations. ++typedef struct AVL_BERConfig ++{ ++ AVL_TestPattern eBERTestPattern; // indicates the pattern of LFSR. ++ AVL_LFSR_FbBit eBERFBInversion; // indicates LFSR feedback bit inversion. ++ u32 uiLFSRSynced; // indicates the LFSR synchronization status. ++ u32 uiLFSRStartPos; //set LFSR start byte positon ++}AVL_BERConfig; ++ ++ ++ ++ ++/* ++typedef struct AVL_StandardSpecificFunctions ++{ ++ AVL_Func_Initialize fpRxInitializeFunc; ++ AVL_Func_GetLockStatus fpGetLockStatus; ++ AVL_Func_GetSNR fpGetSNR; ++ AVL_Func_GetSQI fpGetSQI; ++ AVL_Func_GetPrePostBER fpGetPrePostBER; ++}AVL_StandardSpecificFunctions; ++*/ ++typedef struct AVL_DVBTxPara ++{ ++ AVL_InputPath eDVBTxInputPath; ++ u32 uiDVBTxIFFreqHz; ++ AVL_AGCPola eDVBTxAGCPola; ++} AVL_DVBTxPara; ++ ++typedef enum AVL_Diseqc_WaveFormMode ++{ ++ AVL_DWM_Normal = 0, // Normal waveform mode ++ AVL_DWM_Envelope = 1 // Envelope waveform mode ++}AVL_Diseqc_WaveFormMode; ++ ++typedef struct AVL_DVBSxPara ++{ ++ AVL_semaphore semDiseqc; ++ AVL_DiseqcStatus eDiseqcStatus; ++ AVL_AGCPola eDVBSxAGCPola; ++ AVL_Diseqc_WaveFormMode e22KWaveForm; ++}AVL_DVBSxPara; ++ ++typedef enum AVL_ISDBT_BandWidth ++{ ++ AVL_ISDBT_BW_6M = 0, ++ AVL_ISDBT_BW_8M = 1, ++}AVL_ISDBT_BandWidth; ++ ++typedef struct AVL_ISDBTPara ++{ ++ AVL_InputPath eISDBTInputPath; ++ AVL_ISDBT_BandWidth eISDBTBandwidth; ++ u32 uiISDBTIFFreqHz; ++ AVL_AGCPola eISDBTAGCPola; ++} AVL_ISDBTPara; ++ ++typedef struct AVL_DTMBPara ++{ ++ AVL_InputPath eDTMBInputPath; ++ u32 uiDTMBIFFreqHz; ++ u32 uiDTMBSymbolRateHz; ++ AVL_AGCPola eDTMBAGCPola; ++} AVL_DTMBPara; ++ ++typedef enum AVL_DVBC_Standard ++{ ++ AVL_DVBC_J83A = 0, //the J83A standard ++ AVL_DVBC_J83B = 1, //the J83B standard ++ AVL_DVBC_UNKNOWN = 2 ++}AVL_DVBC_Standard; ++ ++typedef struct AVL_DVBCPara ++{ ++ AVL_InputPath eDVBCInputPath; ++ u32 uiDVBCIFFreqHz; ++ u32 uiDVBCSymbolRateSps; ++ AVL_AGCPola eDVBCAGCPola; ++ AVL_DVBC_Standard eDVBCStandard; ++} AVL_DVBCPara; ++ ++/**************************************************/ ++typedef struct AVL_CommonConfig ++{ ++ u16 usI2CAddr; ++ AVL_Demod_Xtal eDemodXtal; ++ AVL_TSMode eTSMode; ++ AVL_TSClockEdge eClockEdge; ++ AVL_TSClockMode eClockMode; ++}AVL_CommonConfig; ++ ++typedef struct AVL_DVBTxConfig ++{ ++ AVL_InputPath eDVBTxInputPath; ++ u32 uiDVBTxIFFreqHz; ++ AVL_AGCPola eDVBTxAGCPola; ++} AVL_DVBTxConfig; ++ ++typedef struct AVL_DVBCConfig ++{ ++ AVL_InputPath eDVBCInputPath; ++ u32 uiDVBCIFFreqHz; ++ u32 uiDVBCSymbolRateSps; ++ AVL_AGCPola eDVBCAGCPola; ++ AVL_DVBC_Standard eDVBCStandard; ++} AVL_DVBCConfig; ++ ++typedef struct AVL_DVBSxConfig ++{ ++ AVL_AGCPola eDVBSxAGCPola; ++ AVL_Diseqc_WaveFormMode e22KWaveForm; ++} AVL_DVBSxConfig; ++ ++typedef struct AVL_DTMBConfig ++{ ++ AVL_InputPath eDTMBInputPath; ++ u32 uiDTMBIFFreqHz; ++ u32 uiDTMBSymbolRateHz; ++ AVL_AGCPola eDTMBAGCPola; ++} AVL_DTMBConfig; ++ ++typedef struct AVL_ISDBTConfig ++{ ++ AVL_InputPath eISDBTInputPath; ++ AVL_ISDBT_BandWidth eISDBTBandwidth; ++ u32 uiISDBTIFFreqHz; ++ AVL_AGCPola eISDBTAGCPola; ++} AVL_ISDBTConfig; ++ ++typedef struct AVL_TSConfig ++{ ++ AVL_TSMode eMode; ++ AVL_TSClockEdge eClockEdge; ++ AVL_TSClockMode eClockMode; ++ AVL_TSSerialPin eSerialPin; ++ AVL_TSSerialOrder eSerialOrder; ++ AVL_TSSerialSyncPulse eSerialSyncPulse; ++ AVL_TSErrorBit eErrorBit; ++ AVL_TSErrorPolarity eErrorPolarity; ++ AVL_TSValidPolarity eValidPolarity; ++ AVL_TSPacketLen ePacketLen; ++ AVL_TSParallelOrder eParallelOrder; ++ u32 guiDVBTxSerialTSContinuousHz; ++ u32 guiDVBSxSerialTSContinuousHz; ++ u32 guiISDBTSerialTSContinuousHz; ++ u32 guiDTMBSerialTSContinuousHz; ++ u32 guiDVBCSerialTSContinuousHz; ++}AVL_TSConfig; ++ ++ ++ ++// The Availink version structure. ++typedef struct AVL_Version ++{ ++ u8 ucMajor; // The major version number. ++ u8 ucMinor; // The minor version number. ++ u16 usBuild; // The build version number. ++}AVL_Version; ++ ++// Stores AVLEM61 device version information. ++typedef struct AVL_DemodVersion ++{ ++ u32 uiChip; // Hardware version information. 0xYYYYMMDD ++ AVL_Version stPatch; // The version of the internal patch. ++} AVL_DemodVersion; ++ ++ ++#define Diseqc_delay 20 ++ ++#define AVL_EC_OK 0 // There is no error. ++#define AVL_EC_WARNING 1 // There is warning. ++#define AVL_EC_GENERAL_FAIL 2 // A general failure has occurred. ++#define AVL_EC_I2C_FAIL 4 // An I2C operation failed during communication with the AVLEM61 through the BSP. ++#define AVL_EC_I2C_REPEATER_FAIL 8 // An error ocurred during communication between AVLEM61 I2C master and tuner. This error code is defined by enum AVLEM61_MessageType_II2C_Repeater_Status. ++#define AVL_EC_RUNNING 16 // The AVLEM61 device is busy processing a previous receiver/i2c repeater command. ++#define AVL_EC_TIMEOUT 32 // Operation failed in a given time period ++#define AVL_EC_SLEEP 64 // Demod in sleep mode ++#define AVL_EC_NOT_SUPPORTED 128 // Specified operation isn't support in current senario ++#define AVL_EC_BSP_ERROR1 256 // BSP Error 1, if it's used, need to be customized ++#define AVL_EC_BSP_ERROR2 512 // BSP Error 2, if it's used, need to be customized ++ ++#define AVL_CONSTANT_10_TO_THE_9TH 1000000000 //10e9 ++ ++ ++ ++ ++ ++ ++ ++ ++/* DVBS header file */ ++#define rc_DVBSx_rfagc_pol_iaddr_offset 0x00000000 ++#define rc_DVBSx_internal_decode_mode_iaddr_offset 0x0000000c ++#define rc_DVBSx_format_iaddr_offset 0x00000010 ++#define rc_DVBSx_input_iaddr_offset 0x00000014 ++#define rc_DVBSx_specinv_iaddr_offset 0x00000034 ++#define rc_DVBSx_dvbs_fec_coderate_iaddr_offset 0x00000044 ++#define rc_DVBSx_int_sym_rate_MHz_iaddr_offset 0x00000054 ++#define rc_DVBSx_aagc_acq_gain_saddr_offset 0x000000fe ++#define rc_DVBSx_Max_LowIF_sps_iaddr_offset 0x000000a4 ++#define rc_DVBSx_int_dmd_clk_MHz_saddr_offset 0x00000164 ++#define rc_DVBSx_int_mpeg_clk_MHz_saddr_offset 0x00000168 ++#define rc_DVBSx_int_fec_clk_MHz_saddr_offset 0x0000016a ++#define rc_DVBSx_fec_bypass_coderate_saddr_offset 0x0000019a ++#define rc_DVBSx_tuner_frequency_100kHz_saddr_offset 0x000001c0 ++#define rc_DVBSx_tuner_LPF_100kHz_saddr_offset 0x000001c6 ++#define rc_DVBSx_blind_scan_start_freq_100kHz_saddr_offset 0x000001cc ++#define rc_DVBSx_blind_scan_min_sym_rate_kHz_saddr_offset 0x000001d0 ++#define rc_DVBSx_blind_scan_end_freq_100kHz_saddr_offset 0x000001d2 ++#define rc_DVBSx_blind_scan_channel_info_offset_saddr_offset 0x000001d4 ++#define rc_DVBSx_blind_scan_max_sym_rate_kHz_saddr_offset 0x000001d6 ++#define rc_DVBSx_decode_mode_saddr_offset 0x00000204 ++#define rc_DVBSx_iq_mode_saddr_offset 0x0000020a ++#define rc_DVBSx_dishpoint_mode_saddr_offset 0x0000020e ++#define rc_DVBSx_blind_scan_reset_saddr_offset 0x00000210 ++#define rc_DVBSx_functional_mode_saddr_offset 0x00000212 ++#define rc_DVBSx_blind_scan_tuner_spectrum_inversion_saddr_offset 0x00000226 ++#define rc_DVBSx_IF_Offset_10kHz_saddr_offset 0x00000234 ++#define rc_DVBSx_dvbs2_fec_coderate_caddr_offset 0x0000023f ++#define rc_DVBSx_adc_Q_chan_sel_caddr_offset 0x00000246 ++#define rc_DVBSx_adc_I_chan_sel_caddr_offset 0x00000247 ++#define rc_DVBSx_dvbs2_code_rate_saddr_offset 0x00000258 ++#define rc_DVBSx_dvbs2_modulation_saddr_offset 0x0000025a ++#define rc_DVBSx_int_adc_clk_MHz_saddr_offset 0x000002a0 ++ ++#define rs_DVBSx_modulation_iaddr_offset 0x0000000c ++#define rs_DVBSx_pilot_iaddr_offset 0x00000010 ++#define rs_DVBSx_int_SNR_dB_iaddr_offset 0x00000020 ++#define rs_DVBSx_blind_scan_channel_count_saddr_offset 0x000000b0 ++#define rs_DVBSx_blind_scan_error_code_saddr_offset 0x000000b4 ++#define rs_DVBSx_blind_scan_progress_saddr_offset 0x000000b6 ++#define rs_DVBSx_post_viterbi_BER_estimate_x10M_iaddr_offset 0x000000c4 ++#define rs_DVBSx_post_LDPC_BER_estimate_x10M_iaddr_offset 0x000000c8 ++#define rs_DVBSx_pre_LDPC_BER_estimate_x10M_iaddr_offset 0x000000cc ++#define rs_DVBSx_detected_alpha_iaddr_offset 0x000000d0 ++#define rs_DVBSx_int_carrier_freq_100kHz_saddr_offset 0x00000078 ++#define rs_DVBSx_fec_lock_saddr_offset 0x0000009e ++ ++ ++#define hw_diseqc_tx_cntrl_offset 0x0 ++#define hw_diseqc_tone_frac_n_offset 0x4 ++#define hw_diseqc_tone_frac_d_offset 0x8 ++#define hw_diseqc_tx_st_offset 0xC ++#define hw_diseqc_rx_parity_offset 0x10 ++#define hw_diseqc_rx_msg_tim_offset 0x14 ++#define hw_diseqc_rx_st_offset 0x18 ++#define hw_diseqc_rx_cntrl_offset 0x1C ++#define hw_diseqc_srst_offset 0x20 ++#define hw_diseqc_samp_frac_n_offset 0x28 ++#define hw_diseqc_samp_frac_d_offset 0x2C ++#define hw_rx_fifo_map_offset 0x40 ++#define hw_tx_fifo_map_offset 0x80 ++ ++/// Represents the code rate. The Availink device can automatically detect the code rate of the input signal. ++typedef enum AVL_DVBS_CodeRate ++{ ++ AVL_DVBS_CR_1_2 = 0, ++ AVL_DVBS_CR_2_3 = 1, ++ AVL_DVBS_CR_3_4 = 2, ++ AVL_DVBS_CR_5_6 = 3, ++ AVL_DVBS_CR_6_7 = 4, ++ AVL_DVBS_CR_7_8 = 5 ++}AVL_DVBS_CodeRate; ++ ++ ++typedef enum AVL_DVBS2_CodeRate ++{ ++ AVL_DVBS2_CR_1_4 = 0, ++ AVL_DVBS2_CR_1_3 = 1, ++ AVL_DVBS2_CR_2_5 = 2, ++ AVL_DVBS2_CR_1_2 = 3, ++ AVL_DVBS2_CR_3_5 = 4, ++ AVL_DVBS2_CR_2_3 = 5, ++ AVL_DVBS2_CR_3_4 = 6, ++ AVL_DVBS2_CR_4_5 = 7, ++ AVL_DVBS2_CR_5_6 = 8, ++ AVL_DVBS2_CR_8_9 = 9, ++ AVL_DVBS2_CR_9_10 = 10 ++}AVL_DVBS2_CodeRate; ++ ++typedef enum AVL_DVBSx_Pilot ++{ ++ AVL_DVBSx_Pilot_OFF = 0, // Pilot off ++ AVL_DVBSx_Pilot_ON = 1 // Pilot on ++}AVL_DVBSx_Pilot; ++ ++typedef enum AVL_DVBSx_ModulationMode ++{ ++ AVL_DVBSx_QPSK = 0, // QPSK ++ AVL_DVBSx_8PSK = 1, // 8-PSK ++ AVL_DVBSx_16APSK = 2, // 16-APSK ++ AVL_DVBSx_32APSK = 3 // 32-APSK ++}AVL_DVBSx_ModulationMode; ++ ++ ++typedef enum AVL_DVBSx_RollOff ++{ ++ AVL_DVBSx_RollOff_20 = 0, // Roll off is 0.20 ++ AVL_DVBSx_RollOff_25 = 1, // Roll off is 0.25 ++ AVL_DVBSx_RollOff_35 = 2 // Roll off is 0.35 ++}AVL_DVBSx_RollOff; ++ ++typedef enum AVL_DVBSx_Standard ++{ ++ AVL_DVBS = 0, // DVBS standard ++ AVL_DVBS2 = 1 // DVBS2 standard ++}AVL_DVBSx_Standard; ++ ++// Defines the AVL device spectrum inversion mode ++typedef enum AVL_SpectrumInversion ++{ ++ AVL_SPECTRUM_NORMAL = 0, // Signal spectrum in normal. ++ AVL_SPECTRUM_INVERTED = 1, // Signal spectrum in inverted. ++ AVL_SPECTRUM_AUTO = 2 // Signal spectrum isn't known. ++}AVL_SpectrumInversion; ++ ++// Defines the ON/OFF options for the AVLEM61 device. ++typedef enum AVL_Switch ++{ ++ AVL_ON = 0, // switched on ++ AVL_OFF = 1 // switched off ++}AVL_Switch; ++ ++// Defines the device functional mode. ++typedef enum AVL_FunctionalMode ++{ ++ AVL_FuncMode_Demod = 0, // The device is in demod mode. ++ AVL_FuncMode_BlindScan = 1 // The device is in blind scan mode. ++}AVL_FunctionalMode; ++ ++typedef enum AVL_Diseqc_TxGap ++{ ++ AVL_DTXG_15ms = 0, // The gap is 15 ms. ++ AVL_DTXG_20ms = 1, // The gap is 20 ms. ++ AVL_DTXG_25ms = 2, // The gap is 25 ms. ++ AVL_DTXG_30ms = 3 // The gap is 30 ms. ++}AVL_Diseqc_TxGap; ++ ++typedef enum AVL_Diseqc_TxMode ++{ ++ AVL_DTM_Modulation = 0, // Use modulation mode. ++ AVL_DTM_Tone0 = 1, // Send out tone 0. ++ AVL_DTM_Tone1 = 2, // Send out tone 1. ++ AVL_DTM_Continuous = 3 // Continuously send out pulses. ++}AVL_Diseqc_TxMode; ++ ++typedef enum AVL_Diseqc_RxTime ++{ ++ AVL_DRT_150ms = 0, // Wait 150 ms for receive data and then close the input FIFO. ++ AVL_DRT_170ms = 1, // Wait 170 ms for receive data and then close the input FIFO. ++ AVL_DRT_190ms = 2, // Wait 190 ms for receive data and then close the input FIFO. ++ AVL_DRT_210ms = 3 // Wait 210 ms for receive data and then close the input FIFO. ++}AVL_Diseqc_RxTime; ++ ++// Stores blind scan info ++typedef struct AVL_BSInfo ++{ ++ u16 m_uiProgress; // The percentage completion of the blind scan procedure. A value of 100 indicates that the blind scan is finished. ++ u16 m_uiChannelCount; // The number of channels detected thus far by the blind scan operation. The Availink device can store up to 120 detected channels. ++ u16 m_uiNextStartFreq_100kHz; // The start frequency of the next scan in units of 100kHz. ++ u16 m_uiResultCode; // The result of the blind scan operation. Possible values are: 0 - blind scan operation normal; 1 -- more than 120 channels have been detected. ++}AVL_BSInfo; ++ ++// Stores channel info ++typedef struct AVL_ChannelInfo ++{ ++ u32 m_uiFrequency_kHz; // The channel carrier frequency in units of kHz. ++ u32 m_uiSymbolRate_Hz; // The symbol rate in units of Hz. ++ u32 m_Flags; // Contains bit-mapped fields which store additional channel configuration information. ++}AVL_ChannelInfo; ++ ++typedef struct AVL_DVBSxModulationInfo ++{ ++ AVL_DVBSx_ModulationMode eDVBSxModulationMode; ++ AVL_DVBS_CodeRate eDVBSCodeRate; ++ AVL_DVBS2_CodeRate eDVBS2CodeRate; ++ AVL_DVBSx_Pilot eDVBSxPilot; ++ AVL_DVBSx_RollOff eDVBSxRollOff; ++ AVL_DVBSx_Standard eDVBSxStandard; ++}AVL_DVBSxModulationInfo; ++ ++typedef struct AVL_DVBSxManualLockInfo ++{ ++ AVL_DVBSx_ModulationMode eDVBSxModulationMode; ++ AVL_DVBS_CodeRate eDVBSCodeRate; ++ AVL_DVBS2_CodeRate eDVBS2CodeRate; ++ AVL_DVBSx_Pilot eDVBSxPilot; ++ AVL_SpectrumInversion eDVBSxSpecInversion; ++ AVL_DVBSx_Standard eDVBSxStandard; ++ u32 uiDVBSxSymbolRateSps; ++}AVL_DVBSxManualLockInfo; ++ ++// Defines the device spectrum polarity setting. ++typedef enum AVL_BlindSanSpectrumPolarity ++{ ++ AVL_Spectrum_Invert = 0, ++ AVL_Spectrum_Normal = 1 ++}AVL_BlindSanSpectrumPolarity; ++ ++/// Stores the blind scan parameters which are passed to the blind scan function. ++typedef struct AVL_BlindScanPara ++{ ++ u16 m_uiStartFreq_100kHz; // The start scan frequency in units of 100kHz. The minimum value depends on the tuner specification. ++ u16 m_uiStopFreq_100kHz; // The stop scan frequency in units of 100kHz. The maximum value depends on the tuner specification. ++ u16 m_uiMinSymRate_kHz; // The minimum symbol rate to be scanned in units of kHz. The minimum value is 1000 kHz. ++ u16 m_uiMaxSymRate_kHz; // The maximum symbol rate to be scanned in units of kHz. The maximum value is 45000 kHz. ++ AVL_BlindSanSpectrumPolarity m_enumBSSpectrumPolarity; ++}AVL_BlindScanPara; ++ ++// Stores DiSEqC operation parameters ++typedef struct AVL_Diseqc_Para ++{ ++ u16 uiToneFrequencyKHz;// The DiSEqC bus speed in units of kHz. Normally, it is 22kHz. ++ AVL_Diseqc_TxGap eTXGap; // Transmit gap ++ AVL_Diseqc_WaveFormMode eTxWaveForm; // Transmit waveform format ++ AVL_Diseqc_RxTime eRxTimeout; // Receive time frame window ++ AVL_Diseqc_WaveFormMode eRxWaveForm; // Receive waveform format ++}AVL_Diseqc_Para; ++ ++// Stores the DiSEqC transmitter status. ++typedef struct AVL_Diseqc_TxStatus ++{ ++ u8 m_TxDone; // Indicates whether the transmission is complete (1 - transmission is finished, 0 - transmission is still in progress). ++ u8 m_TxFifoCount; // The number of bytes remaining in the transmit FIFO ++}AVL_Diseqc_TxStatus; ++ ++// Stores the DiSEqC receiver status ++typedef struct AVL_Diseqc_RxStatus ++{ ++ u8 m_RxFifoCount; // The number of bytes in the DiSEqC receive FIFO. ++ u8 m_RxFifoParChk; // The parity check result of the received data. This is a bit-mapped field in which each bit represents the parity check result for each each byte in the receive FIFO. The upper bits without corresponding data are undefined. If a bit is 1, the corresponding byte in the FIFO has good parity. For example, if three bytes are in the FIFO, and the parity check value is 0x03 (value of bit 2 is zero), then the first and the second bytes in the receive FIFO are good. The third byte had bad parity. ++ u8 m_RxDone; // 1 if the receiver window is turned off, 0 if it is still in receiving state. ++}AVL_Diseqc_RxStatus; ++ ++ ++ ++ ++ ++ ++/* DVBC */ ++//DVBC config registers offset address ++#define rc_DVBC_symbol_rate_Hz_iaddr_offset 0x00000000 ++#define rc_DVBC_sample_rate_Hz_iaddr_offset 0x00000004 ++#define rc_DVBC_dmd_clk_Hz_iaddr_offset 0x00000008 ++#define rc_DVBC_j83b_mode_caddr_offset 0x00000017 ++#define rc_DVBC_tuner_type_caddr_offset 0x00000024 ++#define rc_DVBC_input_format_caddr_offset 0x00000025 ++#define rc_DVBC_spectrum_invert_caddr_offset 0x00000026 ++#define rc_DVBC_input_select_caddr_offset 0x00000027 ++#define rc_DVBC_if_freq_Hz_iaddr_offset 0x00000028 ++#define rc_DVBC_qam_mode_iaddr_offset 0x0000002c ++#define rc_DVBC_rfagc_pol_caddr_offset 0x00000049 ++#define rc_DVBC_fec_clk_Hz_iaddr_offset 0x00000050 ++#define rc_DVBC_get_btr_crl_iaddr_offset 0x00000080 ++#define rc_DVBC_qam_mode_scan_control_iaddr_offset 0x00000090 ++#define rc_DVBC_adc_sel_caddr_offset 0x000001ef ++#define rc_DVBC_adc_use_pll_clk_caddr_offset 0x000001ee ++ ++ ++ ++//DVBC status registers offset address ++#define rs_DVBC_mode_status_iaddr_offset 0x00000004 ++#define rs_DVBC_snr_dB_x100_saddr_offset 0x0000000e ++#define rs_DVBC_j83b_il_mode_caddr_offset 0x0000001d ++#define rs_DVBC_post_viterbi_BER_estimate_x10M_iaddr_offset 0x0000004c ++ ++typedef enum AVL_DVBC_TunerType ++{ ++ AVL_DVBC_IF = 0, ++ AVL_DVBC_BASEBAND = 1 ++}AVL_DVBC_TunerType; ++ ++typedef enum AVL_DVBC_ChannelType ++{ ++ AVL_DVBC_I_CHANNEL = 0, ++ AVL_DVBC_Q_CHANNEL = 1 ++}AVL_DVBC_ChannelType; ++ ++typedef enum AVL_DVBCQAMMode ++{ ++ AVL_DVBC_16QAM = 0, ++ AVL_DVBC_32QAM = 1, ++ AVL_DVBC_64QAM = 2, ++ AVL_DVBC_128QAM = 3, ++ AVL_DVBC_256QAM = 4 ++}AVL_DVBCQAMMode; ++ ++// Defines the symbol interleave mode of the received DVBC signal, only used for J.83B. ++typedef enum AVL_DVBCInterleaveMode ++{ ++ AVL_DVBC_INTERLEAVE_128_1_0 = 0, ++ AVL_DVBC_INTERLEAVE_128_1_1 = 1, ++ AVL_DVBC_INTERLEAVE_128_2 = 2, ++ AVL_DVBC_INTERLEAVE_64_2 = 3, ++ AVL_DVBC_INTERLEAVE_128_3 = 4, ++ AVL_DVBC_INTERLEAVE_32_4 = 5, ++ AVL_DVBC_INTERLEAVE_128_4 = 6, ++ AVL_DVBC_INTERLEAVE_16_8 = 7, ++ AVL_DVBC_INTERLEAVE_128_5 = 8, ++ AVL_DVBC_INTERLEAVE_8_16 = 9, ++ AVL_DVBC_INTERLEAVE_128_6 = 10, ++ AVL_DVBC_INTERLEAVE_128_7 = 12, ++ AVL_DVBC_INTERLEAVE_128_8 = 14 ++}AVL_DVBCInterleaveMode; ++ ++ ++typedef struct AVL_DVBCModulationInfo ++{ ++ AVL_DVBCQAMMode eQAMMode; ++ AVL_DVBCInterleaveMode eInterleaveMode; ++}AVL_DVBCModulationInfo; ++ ++ typedef struct AVL_DVBC_SQI_CN_Table_Element ++ { ++ AVL_DVBC_Standard eStandard; ++ AVL_DVBCQAMMode modulation; ++ u32 CN_Test_Result_x100_db; ++ }AVL_DVBC_SQI_CN_Table_Element; ++ ++ ++/* DVBT2 */ ++ ++#define rc_DVBTx_fund_rate_Hz_iaddr_offset 0x00000004 ++#define rc_DVBTx_sample_rate_Hz_iaddr_offset 0x00000008 ++#define rc_DVBTx_rf_agc_pol_caddr_offset 0x0000000f ++#define rc_DVBTx_tuner_type_caddr_offset 0x00000040 ++#define rc_DVBTx_input_format_caddr_offset 0x00000041 ++#define rc_DVBTx_spectrum_invert_caddr_offset 0x00000042 ++#define rc_DVBTx_input_select_caddr_offset 0x00000043 ++#define rc_DVBTx_nom_carrier_freq_Hz_iaddr_offset 0x00000044 ++#define rc_DVBTx_l1_proc_only_caddr_offset 0x00000054 ++#define rc_DVBTx_common_PLP_present_caddr_offset 0x00000055 ++#define rc_DVBTx_common_PLP_ID_caddr_offset 0x00000056 ++#define rc_DVBTx_data_PLP_ID_caddr_offset 0x00000057 ++#define rc_DVBTx_dvbt_layer_select_caddr_offset 0x0000006a ++#define rc_DVBTx_acquire_mode_caddr_offset 0x0000006b ++#define rc_DVBTx_mpeg_clk_rate_Hz_iaddr_offset 0x0000006c ++#define rc_DVBTx_adc_sel_caddr_offset 0x00000077 ++#define rc_DVBTx_adc_use_pll_clk_caddr_offset 0x00000076 ++ ++ ++#define rs_DVBTx_rx_mode_caddr_offset 0x000000d0 ++#define rs_DVBTx_fec_lock_caddr_offset 0x000000d2 ++#define rs_DVBTx_snr_dB_x100_saddr_offset 0x000000d6 ++#define rs_DVBTx_post_viterbi_BER_estimate_x10M_iaddr_offset 0x00000114 ++#define rs_DVBTx_post_LDPC_BER_estimate_x1B_iaddr_offset 0x00000118 ++#define rs_DVBTx_pre_LDPC_BER_estimate_x10M_iaddr_offset 0x0000011c ++#define rs_DVBTx_plp_list_request_caddr_offset 0x00000133 ++ ++#define rs_DVBTx_data_PLP_ID_caddr_offset 0x00000000 ++#define rs_DVBTx_data_PLP_TYPE_caddr_offset 0x00000001 ++#define rs_DVBTx_data_PLP_COD_caddr_offset 0x00000007 ++#define rs_DVBTx_data_PLP_MOD_caddr_offset 0x00000008 ++#define rs_DVBTx_data_PLP_ROTATION_caddr_offset 0x00000009 ++#define rs_DVBTx_data_PLP_FEC_TYPE_caddr_offset 0x0000000b ++ ++#define rs_DVBTx_common_PLP_ID_caddr_offset 0x00000000 ++#define rs_DVBTx_common_PLP_COD_caddr_offset 0x00000007 ++#define rs_DVBTx_common_PLP_MOD_caddr_offset 0x00000008 ++#define rs_DVBTx_common_PLP_ROTATION_caddr_offset 0x00000009 ++#define rs_DVBTx_common_PLP_FEC_TYPE_caddr_offset 0x0000000b ++ ++#define rs_DVBTx_P1_S2_field_2_caddr_offset 0x00000003 ++#define rs_DVBTx_MISO_SISO_caddr_offset 0x00000005 ++#define rs_DVBTx_T2_profile_caddr_offset 0x00000006 ++#define rs_DVBTx_FFT_size_caddr_offset 0x00000007 ++ ++#define rs_DVBTx_NUM_PLP_caddr_offset 0x00000002 ++ ++#define rs_DVBTx_constellation_caddr_offset 0x00000001 ++#define rs_DVBTx_hierarchy_caddr_offset 0x00000002 ++#define rs_DVBTx_HP_code_rate_caddr_offset 0x00000003 ++#define rs_DVBTx_LP_code_rate_caddr_offset 0x00000004 ++#define rs_DVBTx_guard_interval_caddr_offset 0x00000005 ++#define rs_DVBTx_transmission_mode_caddr_offset 0x00000006 ++ ++#define rs_DVBTx_BWT_EXT_caddr_offset 0x00000001 ++#define rs_DVBTx_GUARD_INTERVAL_caddr_offset 0x00000005 ++#define rs_DVBTx_PAPR_caddr_offset 0x00000006 ++#define rs_DVBTx_L1_MOD_caddr_offset 0x00000007 ++#define rs_DVBTx_PILOT_PATTERN_caddr_offset 0x00000014 ++#define rs_DVBTx_CELL_ID_saddr_offset 0x00000016 ++#define rs_DVBTx_NETWORK_ID_saddr_offset 0x00000018 ++#define rs_DVBTx_T2_SYSTEM_ID_saddr_offset 0x0000001a ++#define rs_DVBTx_NUM_T2_FRAMES_caddr_offset 0x0000001d ++#define rs_DVBTx_NUM_DATA_SYMBOLS_saddr_offset 0x0000001e ++ ++#define rs_DVBTx_Signal_Presence_iaddr_offset 0x00000150 ++ ++typedef enum AVL_DVBTx_TunerType ++{ ++ AVL_DVBTX_REAL_IF = 0, ++ AVL_DVBTX_COMPLEX_BASEBAND = 1, ++ AVL_DVBTX_REAL_IF_FROM_Q = 2 ++}AVL_DVBTx_TunerType; ++ ++typedef enum AVL_DVBT2_PLP_Type ++{ ++ AVL_DVBT2_SINGLE_PLP = 0, ++ AVL_DVBT2_MULTIPLE_PLP = 1 ++}AVL_DVBT2_PLP_Type; ++ ++typedef enum AVL_DVBTxBandWidth ++{ ++ AVL_DVBTx_BW_1M7 = 0, ++ AVL_DVBTx_BW_5M = 1, ++ AVL_DVBTx_BW_6M = 2, ++ AVL_DVBTx_BW_7M = 3, ++ AVL_DVBTx_BW_8M = 4 ++}AVL_DVBTxBandWidth; ++ ++typedef enum AVL_DVBTx_LockMode ++{ ++ AVL_DVBTx_LockMode_T2BASE_T = 0, ++ AVL_DVBTx_LockMode_T2LITE_T = 1, ++ AVL_DVBTx_LockMode_T2BASE = 2, ++ AVL_DVBTx_LockMode_T2LITE = 3, ++ AVL_DVBTx_LockMode_T_ONLY = 4, ++ AVL_DVBTx_LockMode_ALL = 5 ++}AVL_DVBTx_LockMode; ++ ++typedef enum AVL_DVBT_Layer ++{ ++ AVL_DVBT_LAYER_LP = 0, ++ AVL_DVBT_LAYER_HP = 1 ++}AVL_DVBT_Layer; ++ ++typedef enum AVL_DVBT_FFTSize ++{ ++ AVL_DVBT_FFT_2K = 0, ++ AVL_DVBT_FFT_8K = 1, ++ AVL_DVBT_FFT_UNKNOWN = 2 ++}AVL_DVBT_FFTSize; ++ ++typedef enum AVL_DVBT_GuardInterval ++{ ++ AVL_DVBT_GUARD_1_32 = 0, ++ AVL_DVBT_GUARD_1_16 = 1, ++ AVL_DVBT_GUARD_1_8 = 2, ++ AVL_DVBT_GUARD_1_4 = 3 ++}AVL_DVBT_GuardInterval; ++ ++typedef enum AVL_DVBT_ModulationMode ++{ ++ AVL_DVBT_QPSK = 0, ++ AVL_DVBT_16QAM = 1, ++ AVL_DVBT_64QAM = 2, ++ AVL_DVBT_MOD_UNKNOWN = 3 ++}AVL_DVBT_ModulationMode; ++ ++typedef enum AVL_DVBT_Hierarchy ++{ ++ AVL_DVBT_HIER_NONE = 0, ++ AVL_DVBT_HIER_ALPHA_1 = 1, ++ AVL_DVBT_HIER_ALPHA_2 = 2, ++ AVL_DVBT_HIER_ALPHA_4 = 3 ++}AVL_DVBT_Hierarchy; ++ ++typedef enum AVL_DVBT_CodeRate ++{ ++ AVL_DVBT_CR_1_2 = 0, ++ AVL_DVBT_CR_2_3 = 1, ++ AVL_DVBT_CR_3_4 = 2, ++ AVL_DVBT_CR_5_6 = 3, ++ AVL_DVBT_CR_7_8 = 4 ++}AVL_DVBT_CodeRate; ++ ++typedef enum AVL_DVBT2_FFTSize ++{ ++ AVL_DVBT2_FFT_1K = 0, ++ AVL_DVBT2_FFT_2K = 1, ++ AVL_DVBT2_FFT_4K = 2, ++ AVL_DVBT2_FFT_8K = 3, ++ AVL_DVBT2_FFT_16K = 4, ++ AVL_DVBT2_FFT_32K = 5 ++}AVL_DVBT2_FFTSize; ++ ++typedef enum AVL_DVBT2_MISO_SISO ++{ ++ AVL_DVBT2_SISO = 0, ++ AVL_DVBT2_MISO = 1 ++}AVL_DVBT2_MISO_SISO; ++ ++ ++typedef enum AVL_DVBT2_PROFILE ++{ ++ AVL_DVBT2_PROFILE_BASE = 0, ++ AVL_DVBT2_PROFILE_LITE = 1, ++ AVL_DVBT2_PROFILE_UNKNOWN = 2 ++}AVL_DVBT2_PROFILE; ++ ++typedef enum AVL_DVBT2_PILOT_PATTERN ++{ ++ AVL_DVBT2_PP_PP1 = 0, ++ AVL_DVBT2_PP_PP2 = 1, ++ AVL_DVBT2_PP_PP3 = 2, ++ AVL_DVBT2_PP_PP4 = 3, ++ AVL_DVBT2_PP_PP5 = 4, ++ AVL_DVBT2_PP_PP6 = 5, ++ AVL_DVBT2_PP_PP7 = 6, ++ AVL_DVBT2_PP_PP8 = 7, ++ AVL_DVBT2_PP_DVBT = 8, ++ AVL_DVBT2_PP_DVBT_REVERSE = 9, ++ AVL_DVBT2_PP_UNKNOWN = 10 ++}AVL_DVBT2_PILOT_PATTERN; ++ ++typedef enum AVL_DVBT2_DATA_PLP_TYPE ++{ ++ AVL_DVBT2_DATA_PLP_TYPE1 = 1, ++ AVL_DVBT2_DATA_PLP_TYPE2 = 2 ++}AVL_DVBT2_DATA_PLP_TYPE; ++ ++typedef enum AVL_DVBT2_CodeRate ++{ ++ AVL_DVBT2_CR_1_2 = 0, ++ AVL_DVBT2_CR_3_5 = 1, ++ AVL_DVBT2_CR_2_3 = 2, ++ AVL_DVBT2_CR_3_4 = 3, ++ AVL_DVBT2_CR_4_5 = 4, ++ AVL_DVBT2_CR_5_6 = 5, ++ AVL_DVBT2_CR_1_3 = 6, ++ AVL_DVBT2_CR_2_5 = 7 ++}AVL_DVBT2_CodeRate; ++ ++typedef enum AVL_DVBT2_PLP_ModulationMode ++{ ++ AVL_DVBT2_QPSK = 0, ++ AVL_DVBT2_16QAM = 1, ++ AVL_DVBT2_64QAM = 2, ++ AVL_DVBT2_256QAM = 3 ++}AVL_DVBT2_PLP_ModulationMode; ++ ++typedef enum AVL_DVBT2_L1_Modulation ++{ ++ AVL_DVBT2_L1_BPSK = 0, ++ AVL_DVBT2_L1_QPSK = 1, ++ AVL_DVBT2_L1_16QAM = 2, ++ AVL_DVBT2_L1_64QAM = 3 ++}AVL_DVBT2_L1_Modulation; ++ ++typedef enum AVL_DVBT2_PLP_Constellation_Rotation ++{ ++ AVL_DVBT2_PLP_NOT_ROTATION = 0, ++ AVL_DVBT2_PLP_ROTATION = 1 ++}AVL_DVBT2_PLP_Constellation_Rotation; ++ ++typedef enum AVL_DVBT2_PLP_FEC_Type ++{ ++ AVL_DVBT2_FEC_LDPC16K = 0, ++ AVL_DVBT2_FEC_LDPC64K = 1 ++}AVL_DVBT2_PLP_FEC_Type; ++ ++typedef enum AVL_DVBTx_Standard ++{ ++ AVL_DVBTx_Standard_T = 0, //the DVB-T standard ++ AVL_DVBTx_Standard_T2 = 1 //the DVB-T2 standard ++}AVL_DVBTx_Standard; ++ ++typedef enum AVL_DVBT2_PAPR ++{ ++ AVL_DVBT2_PAPR_NONE = 0, ++ AVL_DVBT2_PAPR_ACE = 1, ++ AVL_DVBT2_PAPR_TR = 2, ++ AVL_DVBT2_PAPR_BOTH = 3 ++}AVL_DVBT2_PAPR; ++ ++typedef enum AVL_DVBT2_GUARD_INTERVAL ++{ ++ AVL_DVBT2_GI_1_32 = 0, ++ AVL_DVBT2_GI_1_16 = 1, ++ AVL_DVBT2_GI_1_8 = 2, ++ AVL_DVBT2_GI_1_4 = 3, ++ AVL_DVBT2_GI_1_128 = 4, ++ AVL_DVBT2_GI_19_128 = 5, ++ AVL_DVBT2_GI_19_256 = 6 ++}AVL_DVBT2_GUARD_INTERVAL; ++ ++ ++ ++typedef struct AVL_DVBT_RF_Table_Element ++{ ++ AVL_DVBT_ModulationMode modulation; ++ AVL_DVBT_CodeRate code_rate; ++ int Nordig_RF_Ref_dbm; ++}AVL_DVBT_RF_Table_Element; ++ ++typedef struct AVL_DVBT_BERSQI_List ++{ ++ u32 m_ber; ++ u32 m_ber_sqi; ++}AVL_DVBT_BERSQI_List; ++ ++typedef struct AVL_DVBT_Non_Hierarchical_CN_Table_Element ++{ ++ AVL_DVBT_ModulationMode modulation; ++ AVL_DVBT_CodeRate hp_code_rate; ++ int CN_NordigP1_x100_db; ++}AVL_DVBT_Non_Hierarchical_CN_Table_Element; ++ ++typedef struct AVL_DVBT_Hierarchical_CN_Table_Element ++{ ++ AVL_DVBT_Layer selected_layer; ++ AVL_DVBT_ModulationMode modulation; ++ AVL_DVBT_CodeRate code_rate; ++ AVL_DVBT_Hierarchy hierarchy; ++ int CN_NordigP1_x100_db; ++}AVL_DVBT_Hierarchical_CN_Table_Element; ++ ++typedef struct DVBT2_CN_Table_Element ++{ ++ AVL_DVBT2_PLP_ModulationMode modulation; ++ AVL_DVBT2_CodeRate code_rate; ++ int CN_NordigP1_x100_db; ++}DVBT2_CN_Table_Element; ++ ++// DVBT2 pilot boosting correct CN table ++typedef struct DVBT2_PBC_CN_Table_Element ++{ ++ AVL_DVBT2_FFTSize fft_size; ++ AVL_DVBT2_PILOT_PATTERN pilot_pattern; ++ int PCB_CN; ++}DVBT2_PBC_CN_Table_Element; ++typedef struct AVL_DVBT2_RF_Table_Element ++{ ++ AVL_DVBT2_PLP_ModulationMode modulation; ++ AVL_DVBT2_CodeRate code_rate; ++ int Nordig_RF_Ref_dbm; ++}AVL_DVBT2_RF_Table_Element; ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++AVL_DVBC_SQI_CN_Table_Element AVL_DVBC_CN_Table[]= ++{ ++ //profile 1, AWGN ++ {AVL_DVBC_J83A, AVL_DVBC_16QAM , 1700}, ++ {AVL_DVBC_J83A, AVL_DVBC_32QAM , 1980}, ++ {AVL_DVBC_J83A, AVL_DVBC_64QAM , 2300}, ++ {AVL_DVBC_J83A, AVL_DVBC_128QAM , 2600}, ++ {AVL_DVBC_J83A, AVL_DVBC_256QAM , 2920}, ++ ++ {AVL_DVBC_J83B, AVL_DVBC_64QAM , 2180}, ++ {AVL_DVBC_J83B, AVL_DVBC_256QAM , 2810} ++}; ++ ++AVL_DVBT_Non_Hierarchical_CN_Table_Element AVL_DVBT_Non_Hierarchical_CN_Table[]= ++{ ++ //profile 1, Gaussian ++ {AVL_DVBT_QPSK, AVL_DVBT_CR_1_2, 510}, ++ {AVL_DVBT_QPSK, AVL_DVBT_CR_2_3, 690}, ++ {AVL_DVBT_QPSK, AVL_DVBT_CR_3_4, 790}, ++ {AVL_DVBT_QPSK, AVL_DVBT_CR_5_6, 890}, ++ {AVL_DVBT_QPSK, AVL_DVBT_CR_7_8, 970}, ++ ++ {AVL_DVBT_16QAM, AVL_DVBT_CR_1_2, 1080}, ++ {AVL_DVBT_16QAM, AVL_DVBT_CR_2_3, 1310}, ++ {AVL_DVBT_16QAM, AVL_DVBT_CR_3_4, 1460}, ++ {AVL_DVBT_16QAM, AVL_DVBT_CR_5_6, 1560}, ++ {AVL_DVBT_16QAM, AVL_DVBT_CR_7_8, 1600}, ++ ++ {AVL_DVBT_64QAM, AVL_DVBT_CR_1_2, 1650}, ++ {AVL_DVBT_64QAM, AVL_DVBT_CR_2_3, 1870}, ++ {AVL_DVBT_64QAM, AVL_DVBT_CR_3_4, 2020}, ++ {AVL_DVBT_64QAM, AVL_DVBT_CR_5_6, 2160}, ++ {AVL_DVBT_64QAM, AVL_DVBT_CR_7_8, 2250} ++}; ++ ++ ++ ++AVL_DVBT_Hierarchical_CN_Table_Element AVL_DVBT_Hierarchical_CN_Table[]= ++{ ++ //profile 1, Gaussian ++ //For HP, only QPSK is used ++ ++ //64QAM ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_64QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_1,1090}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_64QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_1,1670}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_64QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_1,1410}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_64QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_1,1910}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_64QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_1,1570}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_64QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_1,2090}, ++ ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_64QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_2,850}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_64QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_2,1850}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_64QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_2,1100}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_64QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_2,2120}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_64QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_2,1280}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_64QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_2,2360}, ++ ++ //16QAM ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_16QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_2,680}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_16QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_2,1500}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_16QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_2,910}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_16QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_2,1720}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_16QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_2,1040}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_16QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_2,1840}, ++ ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_16QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_4,580}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_16QAM, AVL_DVBT_CR_1_2,AVL_DVBT_HIER_ALPHA_4,1950}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_16QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_4,790}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_16QAM, AVL_DVBT_CR_2_3,AVL_DVBT_HIER_ALPHA_4,2140}, ++ ++ {AVL_DVBT_LAYER_HP, AVL_DVBT_16QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_4,910}, ++ {AVL_DVBT_LAYER_LP, AVL_DVBT_16QAM, AVL_DVBT_CR_3_4,AVL_DVBT_HIER_ALPHA_4,2250} ++}; ++ ++ ++DVBT2_CN_Table_Element DVBT2_RAW_CN_Table[]= ++{ ++ //profile 1, Gaussian ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_1_3, -120}, //from DVB-S2 std ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_2_5, -030}, //from DVB-S2 std ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_1_2, 100}, ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_3_5, 220}, ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_2_3, 310}, ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_3_4, 410}, ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_4_5, 470}, ++ {AVL_DVBT2_QPSK, AVL_DVBT2_CR_5_6, 520}, ++ ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_1_3, 370}, ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_2_5, 490}, ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_1_2, 620}, ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_3_5, 760}, ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_2_3, 890}, ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_3_4, 1000}, ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_4_5, 1080}, ++ {AVL_DVBT2_16QAM, AVL_DVBT2_CR_5_6, 1130}, ++ ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_1_3, 760}, ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_2_5, 920}, ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_1_2, 1050}, ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_3_5, 1230}, ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_2_3, 1360}, ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_3_4, 1510}, ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_4_5, 1610}, ++ {AVL_DVBT2_64QAM, AVL_DVBT2_CR_5_6, 1670}, ++ ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_1_3, 1110}, ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_2_5, 1290}, ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_1_2, 1440}, ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_3_5, 1670}, ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_2_3, 1810}, ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_3_4, 2000}, ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_4_5, 2130}, ++ {AVL_DVBT2_256QAM, AVL_DVBT2_CR_5_6, 2200} ++}; ++ ++ ++DVBT2_PBC_CN_Table_Element DVBT2_PCB_CN_Table[]= ++{ ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP1, 34}, ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP2, 32}, ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP3, 44}, ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP4, 42}, ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP5, 48}, ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP6, 0}, ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP7, 29}, ++ {AVL_DVBT2_FFT_1K, AVL_DVBT2_PP_PP8, 0}, ++ ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP1, 35}, ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP2, 33}, ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP3, 43}, ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP4, 42}, ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP5, 47}, ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP6, 0}, ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP7, 29}, ++ {AVL_DVBT2_FFT_2K, AVL_DVBT2_PP_PP8, 0}, ++ ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP1, 39}, ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP2, 37}, ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP3, 47}, ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP4, 45}, ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP5, 51}, ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP6, 0}, ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP7, 34}, ++ {AVL_DVBT2_FFT_4K, AVL_DVBT2_PP_PP8, 0}, ++ ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP1, 41}, ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP2, 39}, ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP3, 49}, ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP4, 48}, ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP5, 53}, ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP6, 0}, ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP7, 37}, ++ {AVL_DVBT2_FFT_8K, AVL_DVBT2_PP_PP8, 37}, ++ ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP1, 41}, ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP2, 38}, ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP3, 49}, ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP4, 47}, ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP5, 52}, ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP6, 49}, ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP7, 33}, ++ {AVL_DVBT2_FFT_16K, AVL_DVBT2_PP_PP8, 35}, ++ ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP1, 0}, ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP2, 37}, ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP3, 48}, ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP4, 45}, ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP5, 0}, ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP6, 48}, ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP7, 33}, ++ {AVL_DVBT2_FFT_32K, AVL_DVBT2_PP_PP8, 35}, ++}; ++ ++AVL_DVBT_BERSQI_List DVBT_BERSQI_Table[]= ++{ ++ {100 , 40 }, ++ {178 , 45 }, ++ {316 , 50 }, ++ {562 , 55 }, ++ {1000 , 60 }, ++ {1000 , 60 }, ++ {1778 , 65 }, ++ {3162 , 70 }, ++ {5623 , 75 }, ++ {10000 , 80 }, ++ {17783 , 85 }, ++ {31623 , 90 }, ++ {56234 , 95 }, ++ {100000 , 100 }, ++ {177828 , 105 }, ++ {316228 , 110 }, ++ {562341 , 115 }, ++ {1000000 , 120 }, ++ {1778279 , 125 }, ++ {3162278 , 130 }, ++ {5623413 , 135 }, ++ {10000000 , 140 } ++}; ++ ++ ++ ++AVL_DVBT_RF_Table_Element AVL_DVBT_RF_TABLE[]= ++{ ++ {AVL_DVBT_QPSK,AVL_DVBT_CR_1_2,-93}, ++ {AVL_DVBT_QPSK,AVL_DVBT_CR_2_3,-91}, ++ {AVL_DVBT_QPSK,AVL_DVBT_CR_3_4,-90}, ++ {AVL_DVBT_QPSK,AVL_DVBT_CR_5_6,-89}, ++ {AVL_DVBT_QPSK,AVL_DVBT_CR_7_8,-88}, ++ ++ {AVL_DVBT_16QAM,AVL_DVBT_CR_1_2,-87}, ++ {AVL_DVBT_16QAM,AVL_DVBT_CR_2_3,-85}, ++ {AVL_DVBT_16QAM,AVL_DVBT_CR_3_4,-84}, ++ {AVL_DVBT_16QAM,AVL_DVBT_CR_5_6,-83}, ++ {AVL_DVBT_16QAM,AVL_DVBT_CR_7_8,-82}, ++ ++ {AVL_DVBT_64QAM,AVL_DVBT_CR_1_2,-82}, ++ {AVL_DVBT_64QAM,AVL_DVBT_CR_2_3,-80}, ++ {AVL_DVBT_64QAM,AVL_DVBT_CR_3_4,-78}, ++ {AVL_DVBT_64QAM,AVL_DVBT_CR_5_6,-77}, ++ {AVL_DVBT_64QAM,AVL_DVBT_CR_7_8,-76} ++}; ++ ++AVL_DVBT2_RF_Table_Element AVL_DVBT2_RF_TABLE[]= ++{ ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_1_3,-101}, ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_2_5,-100}, ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_1_2,-96}, ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_3_5,-95}, ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_2_3,-94}, ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_3_4,-93}, ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_4_5,-92}, ++ {AVL_DVBT2_QPSK,AVL_DVBT2_CR_5_6,-92}, ++ ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_1_3,-96}, ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_2_5,-95}, ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_1_2,-91}, ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_3_5,-89}, ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_2_3,-88}, ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_3_4,-87}, ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_4_5,-86}, ++ {AVL_DVBT2_16QAM,AVL_DVBT2_CR_5_6,-86}, ++ ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_1_3,-93}, ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_2_5,-92}, ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_1_2,-86}, ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_3_5,-85}, ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_2_3,-83}, ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_3_4,-82}, ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_4_5,-81}, ++ {AVL_DVBT2_64QAM,AVL_DVBT2_CR_5_6,-80}, ++ ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_1_3,-89}, ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_2_5,-88}, ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_1_2,-82}, ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_3_5,-80}, ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_2_3,-78}, ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_3_4,-76}, ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_4_5,-75}, ++ {AVL_DVBT2_256QAM,AVL_DVBT2_CR_5_6,-74} ++}; ++ ++ ++ ++ ++ ++#endif ++ +diff --git a/drivers/media/dvb-frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c +index e105532..2e67aac 100644 +--- a/drivers/media/dvb-frontends/cx24116.c ++++ b/drivers/media/dvb-frontends/cx24116.c +@@ -705,6 +705,9 @@ static int cx24116_read_status(struct dvb_frontend *fe, enum fe_status *status) + if (lock & CX24116_HAS_SYNCLOCK) + *status |= FE_HAS_SYNC | FE_HAS_LOCK; + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, *status & FE_HAS_LOCK); ++ + return 0; + } + +@@ -1113,6 +1116,10 @@ static void cx24116_release(struct dvb_frontend *fe) + { + struct cx24116_state *state = fe->demodulator_priv; + dprintk("%s\n", __func__); ++ ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + kfree(state); + } + +@@ -1198,6 +1205,9 @@ static int cx24116_sleep(struct dvb_frontend *fe) + + dprintk("%s()\n", __func__); + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + /* Firmware CMD 36: Power config */ + cmd.args[0x00] = CMD_TUNERSLEEP; + cmd.args[0x01] = 1; +diff --git a/drivers/media/dvb-frontends/cx24116.h b/drivers/media/dvb-frontends/cx24116.h +index 9ff8df8d..887249a 100644 +--- a/drivers/media/dvb-frontends/cx24116.h ++++ b/drivers/media/dvb-frontends/cx24116.h +@@ -38,6 +38,9 @@ struct cx24116_config { + + /* max bytes I2C provider can write at once */ + u16 i2c_wr_max; ++ ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + }; + + #if IS_REACHABLE(CONFIG_DVB_CX24116) +diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c +index d37cb77..213d457 100644 +--- a/drivers/media/dvb-frontends/cx24117.c ++++ b/drivers/media/dvb-frontends/cx24117.c +@@ -195,7 +195,7 @@ struct cx24117_cmd { + + /* common to both fe's */ + struct cx24117_priv { +- u8 demod_address; ++ struct cx24117_config *cfg; + struct i2c_adapter *i2c; + u8 skip_fw_load; + struct mutex fe_lock; +@@ -265,11 +265,17 @@ static struct cx24117_modfec { + */ + }; + ++struct i2c_adapter *cx24117_get_i2c_adapter(struct dvb_frontend *fe) ++{ ++ struct cx24117_state *state = fe->demodulator_priv; ++ return state->priv->i2c; ++} ++EXPORT_SYMBOL_GPL(cx24117_get_i2c_adapter); + + static int cx24117_writereg(struct cx24117_state *state, u8 reg, u8 data) + { + u8 buf[] = { reg, data }; +- struct i2c_msg msg = { .addr = state->priv->demod_address, ++ struct i2c_msg msg = { .addr = state->priv->cfg->demod_address, + .flags = 0, .buf = buf, .len = 2 }; + int ret; + +@@ -301,7 +307,7 @@ static int cx24117_writecmd(struct cx24117_state *state, + buf[0] = CX24117_REG_COMMAND; + memcpy(&buf[1], cmd->args, cmd->len); + +- msg.addr = state->priv->demod_address; ++ msg.addr = state->priv->cfg->demod_address; + msg.flags = 0; + msg.len = cmd->len+1; + msg.buf = buf; +@@ -320,9 +326,9 @@ static int cx24117_readreg(struct cx24117_state *state, u8 reg) + int ret; + u8 recv = 0; + struct i2c_msg msg[] = { +- { .addr = state->priv->demod_address, .flags = 0, ++ { .addr = state->priv->cfg->demod_address, .flags = 0, + .buf = ®, .len = 1 }, +- { .addr = state->priv->demod_address, .flags = I2C_M_RD, ++ { .addr = state->priv->cfg->demod_address, .flags = I2C_M_RD, + .buf = &recv, .len = 1 } + }; + +@@ -345,9 +351,9 @@ static int cx24117_readregN(struct cx24117_state *state, + { + int ret; + struct i2c_msg msg[] = { +- { .addr = state->priv->demod_address, .flags = 0, ++ { .addr = state->priv->cfg->demod_address, .flags = 0, + .buf = ®, .len = 1 }, +- { .addr = state->priv->demod_address, .flags = I2C_M_RD, ++ { .addr = state->priv->cfg->demod_address, .flags = I2C_M_RD, + .buf = buf, .len = len } + }; + +@@ -624,7 +630,7 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, + memcpy(&buf[1], fw->data, fw->size); + + /* prepare i2c message to send */ +- msg.addr = state->priv->demod_address; ++ msg.addr = state->priv->cfg->demod_address; + msg.flags = 0; + msg.len = fw->size + 1; + msg.buf = buf; +@@ -910,7 +916,7 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, + { + struct cx24117_state *state = fe->demodulator_priv; + struct cx24117_cmd cmd; +- int ret; ++ int ret = 0; + u8 reg = (state->demod == 0) ? 0x10 : 0x20; + + dev_dbg(&state->priv->i2c->dev, "%s() demod%d %s\n", +@@ -919,6 +925,9 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, + voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : + "SEC_VOLTAGE_OFF"); + ++ if (state->priv->cfg->lnb_power) ++ state->priv->cfg->lnb_power(fe, state->demod, 1); ++ + /* Prepare a set GPIO logic level CMD */ + cmd.args[0] = CMD_SET_GPIOOUT; + cmd.args[2] = reg; /* mask */ +@@ -950,8 +959,12 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, + msleep(20); + } else { + /* power off LNB */ +- cmd.args[1] = 0x00; +- ret = cx24117_cmd_execute(fe, &cmd); ++ if (state->priv->cfg->lnb_power) { ++ state->priv->cfg->lnb_power(fe, state->demod, 0); ++ } else { ++ cmd.args[1] = 0x00; ++ ret = cx24117_cmd_execute(fe, &cmd); ++ } + } + + return ret; +@@ -1166,7 +1179,7 @@ static void cx24117_release(struct dvb_frontend *fe) + + static const struct dvb_frontend_ops cx24117_ops; + +-struct dvb_frontend *cx24117_attach(const struct cx24117_config *config, ++struct dvb_frontend *cx24117_attach(struct cx24117_config *config, + struct i2c_adapter *i2c) + { + struct cx24117_state *state = NULL; +@@ -1186,7 +1199,7 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config, + case 1: + /* new priv instance */ + priv->i2c = i2c; +- priv->demod_address = config->demod_address; ++ priv->cfg = config; + mutex_init(&priv->fe_lock); + break; + default: +diff --git a/drivers/media/dvb-frontends/cx24117.h b/drivers/media/dvb-frontends/cx24117.h +index 445f13f..d72c1f8 100644 +--- a/drivers/media/dvb-frontends/cx24117.h ++++ b/drivers/media/dvb-frontends/cx24117.h +@@ -27,15 +27,19 @@ + struct cx24117_config { + /* the demodulator's i2c address */ + u8 demod_address; ++ ++ /* lnb power control */ ++ void (*lnb_power)(struct dvb_frontend *fe, int demod, int onoff); + }; + + #if IS_REACHABLE(CONFIG_DVB_CX24117) ++struct i2c_adapter *cx24117_get_i2c_adapter(struct dvb_frontend *fe); + extern struct dvb_frontend *cx24117_attach( +- const struct cx24117_config *config, ++ struct cx24117_config *config, + struct i2c_adapter *i2c); + #else + static inline struct dvb_frontend *cx24117_attach( +- const struct cx24117_config *config, ++ struct cx24117_config *config, + struct i2c_adapter *i2c) + { + dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); +diff --git a/drivers/media/dvb-frontends/cxd2820r.h b/drivers/media/dvb-frontends/cxd2820r.h +index f3ff8f6..9bf399f 100644 +--- a/drivers/media/dvb-frontends/cxd2820r.h ++++ b/drivers/media/dvb-frontends/cxd2820r.h +@@ -57,6 +57,7 @@ struct cxd2820r_platform_data { + bool spec_inv; + int **gpio_chip_base; + ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); + /* private: For legacy media attach wrapper. Do not set value. */ + bool attach_in_use; +@@ -94,6 +95,9 @@ struct cxd2820r_config { + * Values: 0, 1 + */ + bool spec_inv; ++ ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + }; + + +diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c +index 95267c6..e887582 100644 +--- a/drivers/media/dvb-frontends/cxd2820r_core.c ++++ b/drivers/media/dvb-frontends/cxd2820r_core.c +@@ -180,6 +180,10 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, enum fe_status *status) + ret = -EINVAL; + break; + } ++ ++ if (priv->set_lock_led) ++ priv->set_lock_led(fe, *status & FE_HAS_LOCK); ++ + return ret; + } + +@@ -284,6 +288,9 @@ static int cxd2820r_sleep(struct dvb_frontend *fe) + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret; + ++ if (priv->set_lock_led) ++ priv->set_lock_led(fe, 0); ++ + dev_dbg(&client->dev, "delivery_system=%d\n", c->delivery_system); + + switch (c->delivery_system) { +@@ -415,6 +422,9 @@ static void cxd2820r_release(struct dvb_frontend *fe) + + dev_dbg(&client->dev, "\n"); + ++ if (priv->set_lock_led) ++ priv->set_lock_led(fe, 0); ++ + i2c_unregister_device(client); + + return; +@@ -536,6 +546,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *config, + pdata.ts_clk_inv = config->ts_clock_inv; + pdata.if_agc_polarity = config->if_agc_polarity; + pdata.spec_inv = config->spec_inv; ++ pdata.set_lock_led = config->set_lock_led; + pdata.gpio_chip_base = &gpio_chip_base; + pdata.attach_in_use = true; + +@@ -620,6 +631,7 @@ static int cxd2820r_probe(struct i2c_client *client, + priv->ts_clk_inv = pdata->ts_clk_inv; + priv->if_agc_polarity = pdata->if_agc_polarity; + priv->spec_inv = pdata->spec_inv; ++ priv->set_lock_led = pdata->set_lock_led; + gpio_chip_base = *pdata->gpio_chip_base; + priv->regmap[0] = regmap_init_i2c(priv->client[0], ®map_config0); + if (IS_ERR(priv->regmap[0])) { +diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h +index 0d09620..2e827d4 100644 +--- a/drivers/media/dvb-frontends/cxd2820r_priv.h ++++ b/drivers/media/dvb-frontends/cxd2820r_priv.h +@@ -47,6 +47,7 @@ struct cxd2820r_priv { + bool ts_clk_inv; + bool if_agc_polarity; + bool spec_inv; ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + + u64 post_bit_error_prev_dvbv3; + u64 post_bit_error; +diff --git a/drivers/media/dvb-frontends/isl6422.c b/drivers/media/dvb-frontends/isl6422.c +new file mode 100644 +index 0000000..4a230f0 +--- /dev/null ++++ b/drivers/media/dvb-frontends/isl6422.c +@@ -0,0 +1,317 @@ ++/* ++ Intersil ISL6422 SEC and LNB Power supply controller ++ ++ Created based on isl6423 from Manu Abraham ++ ++ Copyright (C) Luis Alves ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "isl6422.h" ++ ++static unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "Set Verbosity level"); ++ ++#define FE_ERROR 0 ++#define FE_NOTICE 1 ++#define FE_INFO 2 ++#define FE_DEBUG 3 ++#define FE_DEBUGREG 4 ++ ++#define dprintk(__y, __z, format, arg...) do { \ ++ if (__z) { \ ++ if ((verbose > FE_ERROR) && (verbose > __y)) \ ++ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ ++ else if ((verbose > FE_NOTICE) && (verbose > __y)) \ ++ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ ++ else if ((verbose > FE_INFO) && (verbose > __y)) \ ++ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ ++ else if ((verbose > FE_DEBUG) && (verbose > __y)) \ ++ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ ++ } else { \ ++ if (verbose > __y) \ ++ printk(format, ##arg); \ ++ } \ ++} while (0) ++ ++struct isl6422_dev { ++ const struct isl6422_config *config; ++ struct i2c_adapter *i2c; ++ ++ u8 reg_3; ++ u8 reg_4; ++ ++ unsigned int verbose; ++}; ++ ++static int isl6422_write(struct isl6422_dev *isl6422, u8 reg) ++{ ++ struct i2c_adapter *i2c = isl6422->i2c; ++ u8 addr = isl6422->config->addr; ++ int err = 0; ++ ++ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = ®, .len = 1 }; ++ ++ dprintk(FE_DEBUG, 1, "write reg %02X", reg); ++ err = i2c_transfer(i2c, &msg, 1); ++ if (err < 0) ++ goto exit; ++ return 0; ++ ++exit: ++ dprintk(FE_ERROR, 1, "I/O error <%d>", err); ++ return err; ++} ++ ++static int isl6422_set_modulation(struct dvb_frontend *fe) ++{ ++ struct isl6422_dev *isl6422 = (struct isl6422_dev *) fe->sec_priv; ++ const struct isl6422_config *config = isl6422->config; ++ int err = 0; ++ u8 reg_2 = 0; ++ ++ reg_2 = 0x01 << 5; ++ ++ if (config->mod_extern) ++ reg_2 |= (1 << 3); ++ else ++ reg_2 |= (1 << 4); ++ ++ err = isl6422_write(isl6422, reg_2 | ((config->id & 1) << 7)); ++ if (err < 0) ++ goto exit; ++ return 0; ++ ++exit: ++ dprintk(FE_ERROR, 1, "I/O error <%d>", err); ++ return err; ++} ++ ++static int isl6422_voltage_boost(struct dvb_frontend *fe, long arg) ++{ ++ struct isl6422_dev *isl6422 = (struct isl6422_dev *) fe->sec_priv; ++ const struct isl6422_config *config = isl6422->config; ++ u8 reg_3 = isl6422->reg_3; ++ u8 reg_4 = isl6422->reg_4; ++ int err = 0; ++ ++ if (arg) { ++ /* EN = 1, VSPEN = 1, VBOT = 1 */ ++ reg_4 |= (1 << 4); ++ reg_4 |= 0x1; ++ reg_3 |= (1 << 3); ++ } else { ++ /* EN = 1, VSPEN = 1, VBOT = 0 */ ++ reg_4 |= (1 << 4); ++ reg_4 &= ~0x1; ++ reg_3 |= (1 << 3); ++ } ++ err = isl6422_write(isl6422, reg_3 | ((config->id & 1) << 7)); ++ if (err < 0) ++ goto exit; ++ ++ err = isl6422_write(isl6422, reg_4 | ((config->id & 1) << 7)); ++ if (err < 0) ++ goto exit; ++ ++ isl6422->reg_3 = reg_3; ++ isl6422->reg_4 = reg_4; ++ ++ return 0; ++exit: ++ dprintk(FE_ERROR, 1, "I/O error <%d>", err); ++ return err; ++} ++ ++ ++static int isl6422_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ struct isl6422_dev *isl6422 = (struct isl6422_dev *) fe->sec_priv; ++ const struct isl6422_config *config = isl6422->config; ++ u8 reg_3 = isl6422->reg_3; ++ u8 reg_4 = isl6422->reg_4; ++ int err = 0; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ /* EN = 0 */ ++ reg_4 &= ~(1 << 4); ++ break; ++ ++ case SEC_VOLTAGE_13: ++ /* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */ ++ reg_4 |= (1 << 4); ++ reg_4 &= ~0x3; ++ reg_3 |= (1 << 3); ++ break; ++ ++ case SEC_VOLTAGE_18: ++ /* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */ ++ reg_4 |= (1 << 4); ++ reg_4 |= 0x2; ++ reg_4 &= ~0x1; ++ reg_3 |= (1 << 3); ++ break; ++ ++ default: ++ break; ++ } ++ err = isl6422_write(isl6422, reg_3 | ((config->id & 1) << 7)); ++ if (err < 0) ++ goto exit; ++ ++ err = isl6422_write(isl6422, reg_4 | ((config->id & 1) << 7)); ++ if (err < 0) ++ goto exit; ++ ++ isl6422->reg_3 = reg_3; ++ isl6422->reg_4 = reg_4; ++ ++ return 0; ++exit: ++ dprintk(FE_ERROR, 1, "I/O error <%d>", err); ++ return err; ++} ++ ++static int isl6422_set_current(struct dvb_frontend *fe) ++{ ++ struct isl6422_dev *isl6422 = (struct isl6422_dev *) fe->sec_priv; ++ u8 reg_3 = isl6422->reg_3; ++ const struct isl6422_config *config = isl6422->config; ++ int err = 0; ++ ++ reg_3 &= ~0x7; ++ ++ switch (config->current_max) { ++ case SEC_CURRENT_305m: ++ /* 305mA */ ++ /* ISELR = 0, ISELH = X, ISELL = X */ ++ break; ++ ++ case SEC_CURRENT_388m: ++ /* 388mA */ ++ /* ISELR = 1, ISELH = 0, ISELL = 0 */ ++ reg_3 |= 0x4; ++ break; ++ ++ case SEC_CURRENT_570m: ++ /* 570mA */ ++ /* ISELR = 1, ISELH = 0, ISELL = 1 */ ++ reg_3 |= 0x5; ++ break; ++ ++ case SEC_CURRENT_705m: ++ /* 705mA */ ++ /* ISELR = 1, ISELH = 1, ISELL = 0 */ ++ reg_3 |= 0x6; ++ break; ++ ++ case SEC_CURRENT_890m: ++ /* 890mA */ ++ /* ISELR = 1, ISELH = 1, ISELL = 1 */ ++ reg_3 |= 0x7; ++ break; ++ } ++ ++ err = isl6422_write(isl6422, reg_3 | ((config->id & 1) << 7)); ++ if (err < 0) ++ goto exit; ++ ++ switch (config->curlim) { ++ case SEC_CURRENT_LIM_ON: ++ /* DCL = 0 */ ++ reg_3 &= ~0x10; ++ break; ++ ++ case SEC_CURRENT_LIM_OFF: ++ /* DCL = 1 */ ++ reg_3 |= 0x10; ++ break; ++ } ++ ++ err = isl6422_write(isl6422, reg_3 | ((config->id & 1) << 7)); ++ if (err < 0) ++ goto exit; ++ ++ isl6422->reg_3 = reg_3; ++ ++ return 0; ++exit: ++ dprintk(FE_ERROR, 1, "I/O error <%d>", err); ++ return err; ++} ++ ++static void isl6422_release(struct dvb_frontend *fe) ++{ ++ isl6422_set_voltage(fe, SEC_VOLTAGE_OFF); ++ ++ kfree(fe->sec_priv); ++ fe->sec_priv = NULL; ++} ++ ++struct dvb_frontend *isl6422_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct isl6422_config *config) ++{ ++ struct isl6422_dev *isl6422; ++ ++ isl6422 = kzalloc(sizeof(struct isl6422_dev), GFP_KERNEL); ++ if (!isl6422) ++ return NULL; ++ ++ isl6422->config = config; ++ isl6422->i2c = i2c; ++ fe->sec_priv = isl6422; ++ ++ /* SR3H = 0, SR3M = 1, SR3L = 0 */ ++ isl6422->reg_3 = 0x02 << 5; ++ /* SR4H = 0, SR4M = 1, SR4L = 1 */ ++ isl6422->reg_4 = 0x03 << 5; ++ ++ if (isl6422_set_current(fe)) ++ goto exit; ++ ++ if (isl6422_set_modulation(fe)) ++ goto exit; ++ ++ fe->ops.release_sec = isl6422_release; ++ fe->ops.set_voltage = isl6422_set_voltage; ++ fe->ops.enable_high_lnb_voltage = isl6422_voltage_boost; ++ isl6422->verbose = verbose; ++ ++ return fe; ++ ++exit: ++ kfree(isl6422); ++ fe->sec_priv = NULL; ++ return NULL; ++} ++EXPORT_SYMBOL(isl6422_attach); ++ ++MODULE_DESCRIPTION("ISL6422 SEC"); ++MODULE_AUTHOR("Luis Alves"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/dvb-frontends/isl6422.h b/drivers/media/dvb-frontends/isl6422.h +new file mode 100644 +index 0000000..3ce414c +--- /dev/null ++++ b/drivers/media/dvb-frontends/isl6422.h +@@ -0,0 +1,67 @@ ++/* ++ Intersil ISL6422 SEC and LNB Power supply controller ++ ++ Created based on isl6423 from Manu Abraham ++ ++ Copyright (C) Luis Alves ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef __ISL_6422_H ++#define __ISL_6422_H ++ ++#include ++ ++enum isl6422_current { ++ SEC_CURRENT_305m = 0, ++ SEC_CURRENT_388m, ++ SEC_CURRENT_570m, ++ SEC_CURRENT_705m, ++ SEC_CURRENT_890m, ++}; ++ ++enum isl6422_curlim { ++ SEC_CURRENT_LIM_ON = 1, ++ SEC_CURRENT_LIM_OFF ++}; ++ ++struct isl6422_config { ++ enum isl6422_current current_max; ++ enum isl6422_curlim curlim; ++ u8 addr; ++ u8 mod_extern; ++ int id; ++}; ++ ++#if IS_ENABLED(CONFIG_DVB_ISL6422) ++ ++ ++extern struct dvb_frontend *isl6422_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct isl6422_config *config); ++ ++#else ++static inline struct dvb_frontend *isl6422_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct isl6422_config *config) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++#endif /* CONFIG_DVB_ISL6422 */ ++ ++#endif /* __ISL_6422_H */ +diff --git a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h +index 04b355a..f2d3566 100644 +--- a/drivers/media/dvb-frontends/m88ds3103.h ++++ b/drivers/media/dvb-frontends/m88ds3103.h +@@ -168,6 +168,8 @@ struct m88ds3103_config { + * 0: pin high to disable, pin low to enable. + */ + u8 lnb_en_pol:1; ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + }; + + #if defined(CONFIG_DVB_M88DS3103) || \ +diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c +index ce6c21d..131f9fe 100644 +--- a/drivers/media/dvb-frontends/m88rs2000.c ++++ b/drivers/media/dvb-frontends/m88rs2000.c +@@ -459,6 +459,10 @@ static int m88rs2000_sleep(struct dvb_frontend *fe) + { + struct m88rs2000_state *state = fe->demodulator_priv; + int ret; ++ ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + /* Shutdown the frondend */ + ret = m88rs2000_tab_set(state, m88rs2000_shutdown); + return ret; +@@ -478,6 +482,10 @@ static int m88rs2000_read_status(struct dvb_frontend *fe, + if (state->config->set_ts_params) + state->config->set_ts_params(fe, CALL_IS_READ); + } ++ ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, *status & FE_HAS_LOCK); ++ + return 0; + } + +@@ -749,6 +757,10 @@ static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) + static void m88rs2000_release(struct dvb_frontend *fe) + { + struct m88rs2000_state *state = fe->demodulator_priv; ++ ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + kfree(state); + } + +diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h +index 1a313b0..1e487f4 100644 +--- a/drivers/media/dvb-frontends/m88rs2000.h ++++ b/drivers/media/dvb-frontends/m88rs2000.h +@@ -33,6 +33,9 @@ struct m88rs2000_config { + int min_delay_ms; + + int (*set_ts_params)(struct dvb_frontend *, int); ++ ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + }; + + enum { +diff --git a/drivers/media/dvb-frontends/mn88436.c b/drivers/media/dvb-frontends/mn88436.c +new file mode 100644 +index 0000000..91de093 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mn88436.c +@@ -0,0 +1,1467 @@ ++#include "mn88436_priv.h" ++ ++static u8 DMD_REG_ATSC[]={ ++0 ,0x0 ,0x50 , ++0 ,0x1 ,0x0 , ++0 ,0x2 ,0xC0 , ++0 ,0x3 ,0x0 , ++0 ,0x4 ,0x0 , ++0 ,0x5 ,0x0 , ++0 ,0x6 ,0x0 , ++0 ,0x7 ,0x0 , ++0 ,0x8 ,0x0 , ++0 ,0x9 ,0x0 , ++0 ,0xA ,0x1E , ++0 ,0xB ,0x35 , ++0 ,0xC ,0x56 , ++0 ,0xD ,0x8E , ++0 ,0xE ,0xB9 , ++0 ,0xF ,0x72 , ++0 ,0x10 ,0x0 , ++0 ,0x11 ,0x14 , ++0 ,0x12 ,0xE3 , ++0 ,0x13 ,0x4E , ++0 ,0x14 ,0x8 , ++0 ,0x15 ,0x5 , ++0 ,0x16 ,0x63 , ++0 ,0x17 ,0x0 , ++0 ,0x18 ,0x0 , ++0 ,0x19 ,0x0 , ++0 ,0x1A ,0x0 , ++0 ,0x1B ,0x0 , ++0 ,0x1C ,0x0 , ++0 ,0x1D ,0x0 , ++0 ,0x1E ,0x0 , ++0 ,0x1F ,0x0 , ++0 ,0x20 ,0x0 , ++0 ,0x21 ,0x50 , ++0 ,0x22 ,0x60 , ++0 ,0x23 ,0x36 , ++0 ,0x24 ,0x2 , ++0 ,0x25 ,0x0 , ++0 ,0x26 ,0x0 , ++0 ,0x27 ,0x0 , ++0 ,0x28 ,0x0 , ++0 ,0x29 ,0x0 , ++0 ,0x2A ,0x20 , ++0 ,0x2B ,0xC0 , ++0 ,0x2C ,0x23 , ++0 ,0x2D ,0x3F , ++0 ,0x2E ,0x3F , ++0 ,0x2F ,0x0 , ++0 ,0x30 ,0x2E , ++0 ,0x31 ,0x0 , ++0 ,0x32 ,0x0 , ++0 ,0x33 ,0x81 , ++0 ,0x34 ,0x0 , ++0 ,0x35 ,0x26 , ++0 ,0x36 ,0x21 , ++0 ,0x37 ,0x88 , ++0 ,0x38 ,0x3 , ++0 ,0x39 ,0x19 , ++0 ,0x3A ,0x85 , ++0 ,0x3B ,0x5 , ++0 ,0x3C ,0xC9 , ++0 ,0x3D ,0x2 , ++0 ,0x3E ,0x30 , ++0 ,0x3F ,0x69 , ++0 ,0x40 ,0x1F , ++0 ,0x41 ,0xF0 , ++0 ,0x42 ,0x0 , ++0 ,0x43 ,0x96 , ++0 ,0x44 ,0x72 , ++0 ,0x45 ,0x1B , ++0 ,0x46 ,0x2D , ++0 ,0x47 ,0x1A , ++0 ,0x48 ,0x31 , ++0 ,0x49 ,0xFE , ++0 ,0x4A ,0x96 , ++0 ,0x4B ,0x7 , ++0 ,0x4C ,0x26 , ++0 ,0x4D ,0xE3 , ++0 ,0x4E ,0x22 , ++0 ,0x4F ,0x1B , ++0 ,0x50 ,0x26 , ++0 ,0x51 ,0x12 , ++0 ,0x52 ,0x40 , ++0 ,0x53 ,0x50 , ++0 ,0x54 ,0x60 , ++0 ,0x55 ,0x40 , ++0 ,0x56 ,0xED , ++0 ,0x57 ,0x96 , ++0 ,0x58 ,0x4A , ++0 ,0x59 ,0xDE , ++0 ,0x5A ,0x88 , ++0 ,0x5B ,0xC8 , ++0 ,0x5C ,0x2D , ++0 ,0x5D ,0x1 , ++0 ,0x5E ,0x0 , ++0 ,0x5F ,0xB8 , ++0 ,0x60 ,0x40 , ++0 ,0x61 ,0x14 , ++0 ,0x62 ,0x13 , ++0 ,0x63 ,0x30 , ++0 ,0x64 ,0x59 , ++0 ,0x65 ,0x7 , ++0 ,0x66 ,0xF0 , ++0 ,0x67 ,0x47 , ++0 ,0x68 ,0xA1 , ++0 ,0x69 ,0x80 , ++0 ,0x6A ,0x0 , ++0 ,0x6B ,0x0 , ++0 ,0x6C ,0xC0 , ++0 ,0x6D ,0x0 , ++0 ,0x6E ,0x0 , ++0 ,0x6F ,0x0 , ++0 ,0x70 ,0x0 , ++0 ,0x71 ,0x0 , ++0 ,0x72 ,0x0 , ++0 ,0x73 ,0x0 , ++0 ,0x74 ,0x2F , ++0 ,0x75 ,0x0 , ++0 ,0x76 ,0x0 , ++0 ,0x77 ,0x0 , ++0 ,0x78 ,0x0 , ++0 ,0x79 ,0x40 , ++0 ,0x7A ,0x20 , ++0 ,0x7B ,0x40 , ++0 ,0x7C ,0x80 , ++0 ,0x7D ,0xFF , ++0 ,0x7E ,0x20 , ++0 ,0x7F ,0x40 , ++0 ,0x80 ,0x10 , ++0 ,0x81 ,0x0 , ++0 ,0x82 ,0xE5 , ++0 ,0x83 ,0xC4 , ++0 ,0x84 ,0xE9 , ++0 ,0x85 ,0x52 , ++0 ,0x86 ,0x5F , ++0 ,0x87 ,0x53 , ++0 ,0x88 ,0x20 , ++0 ,0x89 ,0x43 , ++0 ,0x8A ,0x11 , ++0 ,0x8B ,0x8 , ++0 ,0x8C ,0x43 , ++0 ,0x8D ,0x11 , ++0 ,0x8E ,0x8 , ++0 ,0x8F ,0x0 , ++0 ,0x90 ,0x60 , ++0 ,0x91 ,0x5B , ++0 ,0x92 ,0x80 , ++0 ,0x93 ,0xE4 , ++0 ,0x94 ,0x34 , ++0 ,0x95 ,0x0 , ++0 ,0x96 ,0x0 , ++0 ,0x97 ,0x7 , ++0 ,0x98 ,0x0 , ++0 ,0x99 ,0xB0 , ++0 ,0x9A ,0x68 , ++0 ,0x9B ,0x50 , ++0 ,0x9C ,0x84 , ++0 ,0x9D ,0xA9 , ++0 ,0x9E ,0x11 , ++0 ,0x9F ,0x4 , ++0 ,0xA0 ,0x44 , ++0 ,0xA1 ,0x14 , ++0 ,0xA2 ,0x9C , ++0 ,0xA3 ,0x15 , ++0 ,0xA4 ,0xF6 , ++0 ,0xA5 ,0x36 , ++0 ,0xA6 ,0x16 , ++0 ,0xA7 ,0x3F , ++0 ,0xA8 ,0x1 , ++0 ,0xA9 ,0x8 , ++0 ,0xAA ,0x0 , ++0 ,0xAB ,0x0 , ++0 ,0xAC ,0x0 , ++0 ,0xAD ,0x65 , ++0 ,0xAE ,0x87 , ++0 ,0xAF ,0x56 , ++0 ,0xB0 ,0x52 , ++0 ,0xB1 ,0x55 , ++0 ,0xB2 ,0x35 , ++0 ,0xB3 ,0x13 , ++0 ,0xB4 ,0x88 , ++0 ,0xB5 ,0x23 , ++0 ,0xB6 ,0x28 , ++0 ,0xB7 ,0x3C , ++0 ,0xB8 ,0x1 , ++0 ,0xB9 ,0x5B , ++0 ,0xBA ,0x0 , ++0 ,0xBB ,0x0 , ++0 ,0xBC ,0x0 , ++0 ,0xBD ,0x0 , ++0 ,0xBE ,0x0 , ++0 ,0xBF ,0x0 , ++0 ,0xC0 ,0x0 , ++0 ,0xC1 ,0x0 , ++0 ,0xC2 ,0x0 , ++0 ,0xC3 ,0x0 , ++0 ,0xC4 ,0x0 , ++0 ,0xC5 ,0x0 , ++0 ,0xC6 ,0x0 , ++0 ,0xC7 ,0x0 , ++0 ,0xC8 ,0x0 , ++0 ,0xC9 ,0x0 , ++0 ,0xCA ,0x0 , ++0 ,0xCB ,0x0 , ++0 ,0xCC ,0x0 , ++0 ,0xCD ,0x0 , ++0 ,0xCE ,0x0 , ++0 ,0xCF ,0x0 , ++0 ,0xD0 ,0x0 , ++0 ,0xD1 ,0x0 , ++0 ,0xD2 ,0x0 , ++0 ,0xD3 ,0x0 , ++0 ,0xD4 ,0x0 , ++0 ,0xD5 ,0x0 , ++0 ,0xD6 ,0x0 , ++0 ,0xD7 ,0x0 , ++0 ,0xD8 ,0x0 , ++0 ,0xD9 ,0xA0 , ++0 ,0xDA ,0x0 , ++0 ,0xDB ,0x0 , ++0 ,0xDC ,0x0 , ++0 ,0xDD ,0x0 , ++0 ,0xDE ,0x0 , ++0 ,0xDF ,0x9 , ++0 ,0xE0 ,0x8 , ++0 ,0xE1 ,0x8 , ++0 ,0xE2 ,0xA8 , ++0 ,0xE3 ,0x0 , ++0 ,0xE4 ,0x0 , ++0 ,0xE5 ,0x0 , ++0 ,0xE6 ,0x0 , ++0 ,0xE7 ,0xB4 , ++0 ,0xE8 ,0xA , ++0 ,0xE9 ,0x0 , ++0 ,0xEA ,0x0 , ++0 ,0xEB ,0x0 , ++0 ,0xEC ,0x0 , ++0 ,0xED ,0x0 , ++0 ,0xEE ,0x0 , ++0 ,0xEF ,0xB4 , ++0 ,0xF0 ,0x91 , ++0 ,0xF1 ,0x0 , ++0 ,0xF2 ,0x0 , ++0 ,0xF3 ,0x0 , ++0 ,0xF4 ,0x0 , ++0 ,0xF5 ,0x0 , ++0 ,0xF6 ,0x0 , ++0 ,0xF7 ,0x0 , ++0 ,0xF8 ,0x0 , ++0 ,0xF9 ,0x0 , ++0 ,0xFA ,0x0 , ++0 ,0xFB ,0x80 , ++0 ,0xFC ,0x10 , ++0 ,0xFD ,0x2 , ++0 ,0xFE ,0x20 , ++0 ,0xFF ,0xAA , ++1 ,0x9 ,0x0 , ++1 ,0xA ,0x0 , ++1 ,0xB ,0x0 , ++1 ,0xC ,0x8 , ++1 ,0xD ,0x0 , ++1 ,0x14 ,0x8 , ++1 ,0x5A ,0x3C , ++1 ,0x5B ,0x0 , ++1 ,0x5C ,0x0 , ++1 ,0x5D ,0x0 , ++1 ,0x5E ,0x0 , ++1 ,0x5F ,0x0 , ++1 ,0x60 ,0x0 , ++1 ,0x61 ,0xAC , ++1 ,0x62 ,0x24 , ++1 ,0x63 ,0x0 , ++1 ,0x64 ,0x0 , ++1 ,0x65 ,0x0 , ++1 ,0x66 ,0x0 , ++1 ,0x67 ,0x0 , ++1 ,0x68 ,0x0 , ++1 ,0x69 ,0x0 , ++1 ,0x6A ,0x0 , ++1 ,0x6B ,0x0 , ++1 ,0x74 ,0x0 , ++1 ,0x79 ,0x0 , ++1 ,0x80 ,0x5 , ++1 ,0x81 ,0x0 , ++1 ,0x82 ,0x40 , ++1 ,0x83 ,0x0 , ++1 ,0x84 ,0x40 , ++1 ,0x85 ,0x37 , ++1 ,0x86 ,0x2 , ++1 ,0x87 ,0x20 , ++1 ,0x88 ,0x0 , ++1 ,0x89 ,0x20 , ++1 ,0x8A ,0x0 , ++1 ,0x8B ,0x3 , ++1 ,0x8C ,0x60 , ++1 ,0x8D ,0x30 , ++1 ,0x8E ,0x88 , ++1 ,0x8F ,0x11 , ++1 ,0x90 ,0x0 , ++1 ,0x91 ,0x0 , ++1 ,0x92 ,0x76 , ++1 ,0x93 ,0xA6 , ++1 ,0x94 ,0x19 , ++1 ,0x95 ,0x52 , ++1 ,0x96 ,0x73 , ++1 ,0x97 ,0x96 , ++1 ,0x98 ,0x9E , ++1 ,0x99 ,0x69 , ++1 ,0x9A ,0xFA , ++1 ,0x9B ,0x8F , ++1 ,0x9C ,0x2E , ++1 ,0x9D ,0x8E , ++1 ,0x9E ,0x0 , ++1 ,0x9F ,0x0 , ++1 ,0xA0 ,0xFD , ++1 ,0xA1 ,0x6D , ++1 ,0xA2 ,0x63 , ++1 ,0xA3 ,0x52 , ++1 ,0xFF ,0x55 , ++0xff,0xff,0xff}; ++ ++// Mode : QAM_B_64QAM ++static u8 DMD_REG_QAM_64QAM[]={ ++0 ,0x0 ,0x51 , ++0 ,0x1 ,0x0 , ++0 ,0x2 ,0xC0 , ++0 ,0x3 ,0x0 , ++0 ,0x4 ,0x0 , ++0 ,0x5 ,0x0 , ++0 ,0x6 ,0x0 , ++0 ,0x7 ,0x0 , ++0 ,0x8 ,0x0 , ++0 ,0x9 ,0x0 , ++0 ,0xA ,0x16 , ++0 ,0xB ,0x35 , ++0 ,0xC ,0x56 , ++0 ,0xD ,0x97 , ++0 ,0xE ,0xDE , ++0 ,0xF ,0xD8 , ++0 ,0x10 ,0x0 , ++0 ,0x11 ,0x14 , ++0 ,0x12 ,0xE4 , ++0 ,0x13 ,0x74 , ++0 ,0x14 ,0x8 , ++0 ,0x15 ,0x5 , ++0 ,0x16 ,0x63 , ++0 ,0x17 ,0x0 , ++0 ,0x18 ,0x0 , ++0 ,0x19 ,0x0 , ++0 ,0x1A ,0x0 , ++0 ,0x1B ,0x0 , ++0 ,0x1C ,0x0 , ++0 ,0x1D ,0x0 , ++0 ,0x1E ,0x0 , ++0 ,0x1F ,0x0 , ++0 ,0x20 ,0x0 , ++0 ,0x21 ,0x50 , ++0 ,0x22 ,0x60 , ++0 ,0x23 ,0x36 , ++0 ,0x24 ,0x2 , ++0 ,0x25 ,0x0 , ++0 ,0x26 ,0x0 , ++0 ,0x27 ,0x0 , ++0 ,0x28 ,0x0 , ++0 ,0x29 ,0x0 , ++0 ,0x2A ,0x20 , ++0 ,0x2B ,0xC0 , ++0 ,0x2C ,0x23 , ++0 ,0x2D ,0x3F , ++0 ,0x2E ,0x3F , ++0 ,0x2F ,0x0 , ++0 ,0x30 ,0x2E , ++0 ,0x31 ,0x0 , ++0 ,0x32 ,0x0 , ++0 ,0x33 ,0x81 , ++0 ,0x34 ,0x0 , ++0 ,0x35 ,0x26 , ++0 ,0x36 ,0x21 , ++0 ,0x37 ,0x88 , ++0 ,0x38 ,0x3 , ++0 ,0x39 ,0x19 , ++0 ,0x3A ,0x85 , ++0 ,0x3B ,0x5 , ++0 ,0x3C ,0xC9 , ++0 ,0x3D ,0x2 , ++0 ,0x3E ,0x30 , ++0 ,0x3F ,0x69 , ++0 ,0x40 ,0x1F , ++0 ,0x41 ,0xF0 , ++0 ,0x42 ,0x0 , ++0 ,0x43 ,0x96 , ++0 ,0x44 ,0x72 , ++0 ,0x45 ,0x1B , ++0 ,0x46 ,0x2D , ++0 ,0x47 ,0x1A , ++0 ,0x48 ,0x31 , ++0 ,0x49 ,0xFE , ++0 ,0x4A ,0x96 , ++0 ,0x4B ,0x7 , ++0 ,0x4C ,0x26 , ++0 ,0x4D ,0xE3 , ++0 ,0x4E ,0x22 , ++0 ,0x4F ,0x1B , ++0 ,0x50 ,0x26 , ++0 ,0x51 ,0x12 , ++0 ,0x52 ,0x40 , ++0 ,0x53 ,0x50 , ++0 ,0x54 ,0x60 , ++0 ,0x55 ,0x40 , ++0 ,0x56 ,0xED , ++0 ,0x57 ,0x96 , ++0 ,0x58 ,0x4A , ++0 ,0x59 ,0xDE , ++0 ,0x5A ,0x88 , ++0 ,0x5B ,0xC8 , ++0 ,0x5C ,0x2D , ++0 ,0x5D ,0x1 , ++0 ,0x5E ,0x0 , ++0 ,0x5F ,0xB8 , ++0 ,0x60 ,0x40 , ++0 ,0x61 ,0x14 , ++0 ,0x62 ,0x13 , ++0 ,0x63 ,0x30 , ++0 ,0x64 ,0x59 , ++0 ,0x65 ,0x7 , ++0 ,0x66 ,0xF0 , ++0 ,0x67 ,0x47 , ++0 ,0x68 ,0xA1 , ++0 ,0x69 ,0x80 , ++0 ,0x6A ,0x0 , ++0 ,0x6B ,0x0 , ++0 ,0x6C ,0xC0 , ++0 ,0x6D ,0x0 , ++0 ,0x6E ,0x0 , ++0 ,0x6F ,0x0 , ++0 ,0x70 ,0x0 , ++0 ,0x71 ,0x0 , ++0 ,0x72 ,0x0 , ++0 ,0x73 ,0x0 , ++0 ,0x74 ,0x2F , ++0 ,0x75 ,0x0 , ++0 ,0x76 ,0x0 , ++0 ,0x77 ,0x0 , ++0 ,0x78 ,0x0 , ++0 ,0x79 ,0x40 , ++0 ,0x7A ,0x20 , ++0 ,0x7B ,0x40 , ++0 ,0x7C ,0x80 , ++0 ,0x7D ,0xFF , ++0 ,0x7E ,0x20 , ++0 ,0x7F ,0x40 , ++0 ,0x80 ,0x10 , ++0 ,0x81 ,0x0 , ++0 ,0x82 ,0xE5 , ++0 ,0x83 ,0xC4 , ++0 ,0x84 ,0xE9 , ++0 ,0x85 ,0x52 , ++0 ,0x86 ,0x5F , ++0 ,0x87 ,0x53 , ++0 ,0x88 ,0x20 , ++0 ,0x89 ,0x43 , ++0 ,0x8A ,0x11 , ++0 ,0x8B ,0x8 , ++0 ,0x8C ,0x43 , ++0 ,0x8D ,0x11 , ++0 ,0x8E ,0x8 , ++0 ,0x8F ,0x0 , ++0 ,0x90 ,0x60 , ++0 ,0x91 ,0x5B , ++0 ,0x92 ,0x80 , ++0 ,0x93 ,0xE4 , ++0 ,0x94 ,0x34 , ++0 ,0x95 ,0x0 , ++0 ,0x96 ,0x0 , ++0 ,0x97 ,0x7 , ++0 ,0x98 ,0x0 , ++0 ,0x99 ,0xB0 , ++0 ,0x9A ,0x68 , ++0 ,0x9B ,0x50 , ++0 ,0x9C ,0x84 , ++0 ,0x9D ,0xA9 , ++0 ,0x9E ,0x11 , ++0 ,0x9F ,0x4 , ++0 ,0xA0 ,0x44 , ++0 ,0xA1 ,0x14 , ++0 ,0xA2 ,0x9C , ++0 ,0xA3 ,0x15 , ++0 ,0xA4 ,0xF6 , ++0 ,0xA5 ,0x36 , ++0 ,0xA6 ,0x16 , ++0 ,0xA7 ,0x3F , ++0 ,0xA8 ,0x1 , ++0 ,0xA9 ,0x8 , ++0 ,0xAA ,0x0 , ++0 ,0xAB ,0x0 , ++0 ,0xAC ,0x0 , ++0 ,0xAD ,0x65 , ++0 ,0xAE ,0x87 , ++0 ,0xAF ,0x56 , ++0 ,0xB0 ,0x52 , ++0 ,0xB1 ,0x55 , ++0 ,0xB2 ,0x35 , ++0 ,0xB3 ,0x13 , ++0 ,0xB4 ,0x88 , ++0 ,0xB5 ,0x23 , ++0 ,0xB6 ,0x28 , ++0 ,0xB7 ,0x3C , ++0 ,0xB8 ,0x1 , ++0 ,0xB9 ,0x5B , ++0 ,0xBA ,0x0 , ++0 ,0xBB ,0x0 , ++0 ,0xBC ,0x0 , ++0 ,0xBD ,0x0 , ++0 ,0xBE ,0x0 , ++0 ,0xBF ,0x0 , ++0 ,0xC0 ,0x0 , ++0 ,0xC1 ,0x0 , ++0 ,0xC2 ,0x0 , ++0 ,0xC3 ,0x0 , ++0 ,0xC4 ,0x0 , ++0 ,0xC5 ,0x0 , ++0 ,0xC6 ,0x0 , ++0 ,0xC7 ,0x0 , ++0 ,0xC8 ,0x0 , ++0 ,0xC9 ,0x0 , ++0 ,0xCA ,0x0 , ++0 ,0xCB ,0x0 , ++0 ,0xCC ,0x0 , ++0 ,0xCD ,0x0 , ++0 ,0xCE ,0x0 , ++0 ,0xCF ,0x0 , ++0 ,0xD0 ,0x0 , ++0 ,0xD1 ,0x0 , ++0 ,0xD2 ,0x0 , ++0 ,0xD3 ,0x0 , ++0 ,0xD4 ,0x0 , ++0 ,0xD5 ,0x0 , ++0 ,0xD6 ,0x0 , ++0 ,0xD7 ,0x0 , ++0 ,0xD8 ,0x0 , ++0 ,0xD9 ,0xA0 , ++0 ,0xDA ,0x0 , ++0 ,0xDB ,0x0 , ++0 ,0xDC ,0x0 , ++0 ,0xDD ,0x0 , ++0 ,0xDE ,0x0 , ++0 ,0xDF ,0x9 , ++0 ,0xE0 ,0x8 , ++0 ,0xE1 ,0x8 , ++0 ,0xE2 ,0xA8 , ++0 ,0xE3 ,0x0 , ++0 ,0xE4 ,0x0 , ++0 ,0xE5 ,0x0 , ++0 ,0xE6 ,0x0 , ++0 ,0xE7 ,0xB4 , ++0 ,0xE8 ,0xA , ++0 ,0xE9 ,0x0 , ++0 ,0xEA ,0x0 , ++0 ,0xEB ,0x0 , ++0 ,0xEC ,0x0 , ++0 ,0xED ,0x0 , ++0 ,0xEE ,0x0 , ++0 ,0xEF ,0xB4 , ++0 ,0xF0 ,0x91 , ++0 ,0xF1 ,0x0 , ++0 ,0xF2 ,0x0 , ++0 ,0xF3 ,0x0 , ++0 ,0xF4 ,0x0 , ++0 ,0xF5 ,0x0 , ++0 ,0xF6 ,0x0 , ++0 ,0xF7 ,0x0 , ++0 ,0xF8 ,0x0 , ++0 ,0xF9 ,0x0 , ++0 ,0xFA ,0x0 , ++0 ,0xFB ,0x80 , ++0 ,0xFC ,0x10 , ++0 ,0xFD ,0x2 , ++0 ,0xFE ,0x20 , ++0 ,0xFF ,0xAA , ++1 ,0x9 ,0x0 , ++1 ,0xA ,0x0 , ++1 ,0xB ,0x0 , ++1 ,0xC ,0x8 , ++1 ,0xD ,0x0 , ++1 ,0x14 ,0x8 , ++1 ,0x5A ,0x3C , ++1 ,0x5B ,0x0 , ++1 ,0x5C ,0x0 , ++1 ,0x5D ,0x0 , ++1 ,0x5E ,0x0 , ++1 ,0x5F ,0x0 , ++1 ,0x60 ,0x0 , ++1 ,0x61 ,0xAC , ++1 ,0x62 ,0x24 , ++1 ,0x63 ,0x0 , ++1 ,0x64 ,0x0 , ++1 ,0x65 ,0x0 , ++1 ,0x66 ,0x0 , ++1 ,0x67 ,0x0 , ++1 ,0x68 ,0x0 , ++1 ,0x69 ,0x0 , ++1 ,0x6A ,0x0 , ++1 ,0x6B ,0x0 , ++1 ,0x74 ,0x0 , ++1 ,0x79 ,0x0 , ++1 ,0x80 ,0x5 , ++1 ,0x81 ,0x0 , ++1 ,0x82 ,0x40 , ++1 ,0x83 ,0x0 , ++1 ,0x84 ,0x40 , ++1 ,0x85 ,0x37 , ++1 ,0x86 ,0x2 , ++1 ,0x87 ,0x20 , ++1 ,0x88 ,0x0 , ++1 ,0x89 ,0x20 , ++1 ,0x8A ,0x0 , ++1 ,0x8B ,0x3 , ++1 ,0x8C ,0x60 , ++1 ,0x8D ,0x30 , ++1 ,0x8E ,0x88 , ++1 ,0x8F ,0x11 , ++1 ,0x90 ,0x0 , ++1 ,0x91 ,0x0 , ++1 ,0x92 ,0x71 , ++1 ,0x93 ,0xE7 , ++1 ,0x94 ,0x23 , ++1 ,0x95 ,0x52 , ++1 ,0x96 ,0x73 , ++1 ,0x97 ,0x96 , ++1 ,0x98 ,0xA5 , ++1 ,0x99 ,0x3 , ++1 ,0x9A ,0xBA , ++1 ,0x9B ,0x95 , ++1 ,0x9C ,0x25 , ++1 ,0x9D ,0xD4 , ++1 ,0x9E ,0x0 , ++1 ,0x9F ,0x0 , ++1 ,0xA0 ,0xFD , ++1 ,0xA1 ,0x6D , ++1 ,0xA2 ,0x63 , ++1 ,0xA3 ,0x52 , ++1 ,0xFF ,0x55 , ++0xff,0xff,0xff}; ++ ++ ++// Mode : QAM_B_256QAM ++static u8 DMD_REG_QAM_256QAM[]={ ++0 ,0x0 ,0x53 , ++0 ,0x1 ,0x0 , ++0 ,0x2 ,0xC0 , ++0 ,0x3 ,0x0 , ++0 ,0x4 ,0x0 , ++0 ,0x5 ,0x0 , ++0 ,0x6 ,0x0 , ++0 ,0x7 ,0x0 , ++0 ,0x8 ,0x0 , ++0 ,0x9 ,0x0 , ++0 ,0xA ,0x16 , ++0 ,0xB ,0x35 , ++0 ,0xC ,0x56 , ++0 ,0xD ,0x8F , ++0 ,0xE ,0x44 , ++0 ,0xF ,0xED , ++0 ,0x10 ,0x0 , ++0 ,0x11 ,0x14 , ++0 ,0x12 ,0xE4 , ++0 ,0x13 ,0x74 , ++0 ,0x14 ,0x8 , ++0 ,0x15 ,0x5 , ++0 ,0x16 ,0x63 , ++0 ,0x17 ,0x0 , ++0 ,0x18 ,0x0 , ++0 ,0x19 ,0x0 , ++0 ,0x1A ,0x0 , ++0 ,0x1B ,0x0 , ++0 ,0x1C ,0x0 , ++0 ,0x1D ,0x0 , ++0 ,0x1E ,0x0 , ++0 ,0x1F ,0x0 , ++0 ,0x20 ,0x0 , ++0 ,0x21 ,0x50 , ++0 ,0x22 ,0x60 , ++0 ,0x23 ,0x36 , ++0 ,0x24 ,0x2 , ++0 ,0x25 ,0x0 , ++0 ,0x26 ,0x0 , ++0 ,0x27 ,0x0 , ++0 ,0x28 ,0x0 , ++0 ,0x29 ,0x0 , ++0 ,0x2A ,0x20 , ++0 ,0x2B ,0xC0 , ++0 ,0x2C ,0x23 , ++0 ,0x2D ,0x3F , ++0 ,0x2E ,0x3F , ++0 ,0x2F ,0x0 , ++0 ,0x30 ,0x2E , ++0 ,0x31 ,0x0 , ++0 ,0x32 ,0x0 , ++0 ,0x33 ,0x81 , ++0 ,0x34 ,0x0 , ++0 ,0x35 ,0x26 , ++0 ,0x36 ,0x21 , ++0 ,0x37 ,0x88 , ++0 ,0x38 ,0x3 , ++0 ,0x39 ,0x19 , ++0 ,0x3A ,0x85 , ++0 ,0x3B ,0x5 , ++0 ,0x3C ,0xC9 , ++0 ,0x3D ,0x2 , ++0 ,0x3E ,0x30 , ++0 ,0x3F ,0x69 , ++0 ,0x40 ,0x1F , ++0 ,0x41 ,0xF0 , ++0 ,0x42 ,0x0 , ++0 ,0x43 ,0x96 , ++0 ,0x44 ,0x72 , ++0 ,0x45 ,0x1B , ++0 ,0x46 ,0x2D , ++0 ,0x47 ,0x1A , ++0 ,0x48 ,0x31 , ++0 ,0x49 ,0xFE , ++0 ,0x4A ,0x96 , ++0 ,0x4B ,0x7 , ++0 ,0x4C ,0x26 , ++0 ,0x4D ,0xE3 , ++0 ,0x4E ,0x22 , ++0 ,0x4F ,0x1B , ++0 ,0x50 ,0x26 , ++0 ,0x51 ,0x12 , ++0 ,0x52 ,0x40 , ++0 ,0x53 ,0x50 , ++0 ,0x54 ,0x60 , ++0 ,0x55 ,0x40 , ++0 ,0x56 ,0xED , ++0 ,0x57 ,0x96 , ++0 ,0x58 ,0x4A , ++0 ,0x59 ,0xDE , ++0 ,0x5A ,0x88 , ++0 ,0x5B ,0xC8 , ++0 ,0x5C ,0x2D , ++0 ,0x5D ,0x1 , ++0 ,0x5E ,0x0 , ++0 ,0x5F ,0xB8 , ++0 ,0x60 ,0x40 , ++0 ,0x61 ,0x14 , ++0 ,0x62 ,0x13 , ++0 ,0x63 ,0x30 , ++0 ,0x64 ,0x59 , ++0 ,0x65 ,0x7 , ++0 ,0x66 ,0xF0 , ++0 ,0x67 ,0x47 , ++0 ,0x68 ,0xA1 , ++0 ,0x69 ,0x80 , ++0 ,0x6A ,0x0 , ++0 ,0x6B ,0x0 , ++0 ,0x6C ,0xC0 , ++0 ,0x6D ,0x0 , ++0 ,0x6E ,0x0 , ++0 ,0x6F ,0x0 , ++0 ,0x70 ,0x0 , ++0 ,0x71 ,0x0 , ++0 ,0x72 ,0x0 , ++0 ,0x73 ,0x0 , ++0 ,0x74 ,0x2F , ++0 ,0x75 ,0x0 , ++0 ,0x76 ,0x0 , ++0 ,0x77 ,0x0 , ++0 ,0x78 ,0x0 , ++0 ,0x79 ,0x40 , ++0 ,0x7A ,0x20 , ++0 ,0x7B ,0x40 , ++0 ,0x7C ,0x80 , ++0 ,0x7D ,0xFF , ++0 ,0x7E ,0x20 , ++0 ,0x7F ,0x40 , ++0 ,0x80 ,0x10 , ++0 ,0x81 ,0x0 , ++0 ,0x82 ,0xE5 , ++0 ,0x83 ,0xC4 , ++0 ,0x84 ,0xE9 , ++0 ,0x85 ,0x52 , ++0 ,0x86 ,0x5F , ++0 ,0x87 ,0x53 , ++0 ,0x88 ,0x20 , ++0 ,0x89 ,0x43 , ++0 ,0x8A ,0x11 , ++0 ,0x8B ,0x8 , ++0 ,0x8C ,0x43 , ++0 ,0x8D ,0x11 , ++0 ,0x8E ,0x8 , ++0 ,0x8F ,0x0 , ++0 ,0x90 ,0x60 , ++0 ,0x91 ,0x5B , ++0 ,0x92 ,0x80 , ++0 ,0x93 ,0xE4 , ++0 ,0x94 ,0x34 , ++0 ,0x95 ,0x0 , ++0 ,0x96 ,0x0 , ++0 ,0x97 ,0x7 , ++0 ,0x98 ,0x0 , ++0 ,0x99 ,0xB0 , ++0 ,0x9A ,0x68 , ++0 ,0x9B ,0x50 , ++0 ,0x9C ,0x84 , ++0 ,0x9D ,0xA9 , ++0 ,0x9E ,0x11 , ++0 ,0x9F ,0x4 , ++0 ,0xA0 ,0x44 , ++0 ,0xA1 ,0x14 , ++0 ,0xA2 ,0x9C , ++0 ,0xA3 ,0x15 , ++0 ,0xA4 ,0xF6 , ++0 ,0xA5 ,0x36 , ++0 ,0xA6 ,0x16 , ++0 ,0xA7 ,0x3F , ++0 ,0xA8 ,0x1 , ++0 ,0xA9 ,0x8 , ++0 ,0xAA ,0x0 , ++0 ,0xAB ,0x0 , ++0 ,0xAC ,0x0 , ++0 ,0xAD ,0x65 , ++0 ,0xAE ,0x87 , ++0 ,0xAF ,0x56 , ++0 ,0xB0 ,0x52 , ++0 ,0xB1 ,0x55 , ++0 ,0xB2 ,0x35 , ++0 ,0xB3 ,0x13 , ++0 ,0xB4 ,0x88 , ++0 ,0xB5 ,0x23 , ++0 ,0xB6 ,0x28 , ++0 ,0xB7 ,0x3C , ++0 ,0xB8 ,0x1 , ++0 ,0xB9 ,0x5B , ++0 ,0xBA ,0x0 , ++0 ,0xBB ,0x0 , ++0 ,0xBC ,0x0 , ++0 ,0xBD ,0x0 , ++0 ,0xBE ,0x0 , ++0 ,0xBF ,0x0 , ++0 ,0xC0 ,0x0 , ++0 ,0xC1 ,0x0 , ++0 ,0xC2 ,0x0 , ++0 ,0xC3 ,0x0 , ++0 ,0xC4 ,0x0 , ++0 ,0xC5 ,0x0 , ++0 ,0xC6 ,0x0 , ++0 ,0xC7 ,0x0 , ++0 ,0xC8 ,0x0 , ++0 ,0xC9 ,0x0 , ++0 ,0xCA ,0x0 , ++0 ,0xCB ,0x0 , ++0 ,0xCC ,0x0 , ++0 ,0xCD ,0x0 , ++0 ,0xCE ,0x0 , ++0 ,0xCF ,0x0 , ++0 ,0xD0 ,0x0 , ++0 ,0xD1 ,0x0 , ++0 ,0xD2 ,0x0 , ++0 ,0xD3 ,0x0 , ++0 ,0xD4 ,0x0 , ++0 ,0xD5 ,0x0 , ++0 ,0xD6 ,0x0 , ++0 ,0xD7 ,0x0 , ++0 ,0xD8 ,0x0 , ++0 ,0xD9 ,0xA0 , ++0 ,0xDA ,0x0 , ++0 ,0xDB ,0x0 , ++0 ,0xDC ,0x0 , ++0 ,0xDD ,0x0 , ++0 ,0xDE ,0x0 , ++0 ,0xDF ,0x9 , ++0 ,0xE0 ,0x8 , ++0 ,0xE1 ,0x8 , ++0 ,0xE2 ,0xA8 , ++0 ,0xE3 ,0x0 , ++0 ,0xE4 ,0x0 , ++0 ,0xE5 ,0x0 , ++0 ,0xE6 ,0x0 , ++0 ,0xE7 ,0xB4 , ++0 ,0xE8 ,0xA , ++0 ,0xE9 ,0x0 , ++0 ,0xEA ,0x0 , ++0 ,0xEB ,0x0 , ++0 ,0xEC ,0x0 , ++0 ,0xED ,0x0 , ++0 ,0xEE ,0x0 , ++0 ,0xEF ,0xB4 , ++0 ,0xF0 ,0x91 , ++0 ,0xF1 ,0x0 , ++0 ,0xF2 ,0x0 , ++0 ,0xF3 ,0x0 , ++0 ,0xF4 ,0x0 , ++0 ,0xF5 ,0x0 , ++0 ,0xF6 ,0x0 , ++0 ,0xF7 ,0x0 , ++0 ,0xF8 ,0x0 , ++0 ,0xF9 ,0x0 , ++0 ,0xFA ,0x0 , ++0 ,0xFB ,0x80 , ++0 ,0xFC ,0x10 , ++0 ,0xFD ,0x2 , ++0 ,0xFE ,0x20 , ++0 ,0xFF ,0xAA , ++1 ,0x9 ,0x0 , ++1 ,0xA ,0x0 , ++1 ,0xB ,0x0 , ++1 ,0xC ,0x8 , ++1 ,0xD ,0x0 , ++1 ,0x14 ,0x8 , ++1 ,0x5A ,0x3C , ++1 ,0x5B ,0x0 , ++1 ,0x5C ,0x0 , ++1 ,0x5D ,0x0 , ++1 ,0x5E ,0x0 , ++1 ,0x5F ,0x0 , ++1 ,0x60 ,0x0 , ++1 ,0x61 ,0xAC , ++1 ,0x62 ,0x24 , ++1 ,0x63 ,0x0 , ++1 ,0x64 ,0x0 , ++1 ,0x65 ,0x0 , ++1 ,0x66 ,0x0 , ++1 ,0x67 ,0x0 , ++1 ,0x68 ,0x0 , ++1 ,0x69 ,0x0 , ++1 ,0x6A ,0x0 , ++1 ,0x6B ,0x0 , ++1 ,0x74 ,0x0 , ++1 ,0x79 ,0x0 , ++1 ,0x80 ,0x5 , ++1 ,0x81 ,0x0 , ++1 ,0x82 ,0x40 , ++1 ,0x83 ,0x0 , ++1 ,0x84 ,0x40 , ++1 ,0x85 ,0x37 , ++1 ,0x86 ,0x2 , ++1 ,0x87 ,0x20 , ++1 ,0x88 ,0x0 , ++1 ,0x89 ,0x20 , ++1 ,0x8A ,0x0 , ++1 ,0x8B ,0x3 , ++1 ,0x8C ,0x60 , ++1 ,0x8D ,0x30 , ++1 ,0x8E ,0x88 , ++1 ,0x8F ,0x11 , ++1 ,0x90 ,0x0 , ++1 ,0x91 ,0x0 , ++1 ,0x92 ,0x76 , ++1 ,0x93 ,0xA6 , ++1 ,0x94 ,0x19 , ++1 ,0x95 ,0x4F , ++1 ,0x96 ,0x27 , ++1 ,0x97 ,0x49 , ++1 ,0x98 ,0xA5 , ++1 ,0x99 ,0x3 , ++1 ,0x9A ,0xBA , ++1 ,0x9B ,0x95 , ++1 ,0x9C ,0x25 , ++1 ,0x9D ,0xD4 , ++1 ,0x9E ,0x0 , ++1 ,0x9F ,0x0 , ++1 ,0xA0 ,0xFD , ++1 ,0xA1 ,0x6D , ++1 ,0xA2 ,0x63 , ++1 ,0xA3 ,0x52 , ++1 ,0xFF ,0x55 , ++0xff,0xff,0xff}; ++ ++static u32 MN88436_REG_AUTOCTRL_SIZE = 673; ++ ++static u8 MN88436_REG_AUTOCTRL[] = { ++ 0x10 ,0x00 ,0xc0 ,0x02 ,0xa1 ,0x10 ,0x25 ,0x20 ++ ,0x4b ,0x10 ,0x1b ,0x20 ,0x51 ,0x10 ,0x64 ,0x20 ++ ,0xf7 ,0x10 ,0x0a ,0x20 ,0xeb ,0x30 ,0xc4 ,0x70 ++ ,0x60 ,0x90 ,0x00 ,0x78 ,0x82 ,0x00 ,0x1f ,0x10 ++ ,0x0c ,0x20 ,0xeb ,0x30 ,0xec ,0x70 ,0xbf ,0x20 ++ ,0xec ,0x30 ,0x5b ,0x70 ,0x40 ,0x14 ,0x30 ,0xec ++ ,0x75 ,0x20 ,0xec ,0x30 ,0xc4 ,0x70 ,0x02 ,0x90 ++ ,0x00 ,0x05 ,0x0d ,0x82 ,0x00 ,0x73 ,0x82 ,0x00 ++ ,0x41 ,0x30 ,0xc4 ,0x70 ,0x01 ,0xb0 ,0x00 ,0x1f ++ ,0xc4 ,0x02 ,0xa5 ,0x68 ,0x88 ,0x90 ,0x00 ,0x63 ++ ,0x80 ,0x00 ,0x53 ,0x10 ,0x88 ,0xc0 ,0x02 ,0xa5 ++ ,0x20 ,0x5b ,0x30 ,0xec ,0x70 ,0xbf ,0x20 ,0xec ++ ,0x80 ,0x00 ,0x1f ,0x10 ,0xc8 ,0xc0 ,0x02 ,0xa5 ++ ,0x20 ,0x5b ,0x30 ,0xec ,0x74 ,0x40 ,0x20 ,0xec ++ ,0x80 ,0x00 ,0x1f ,0x08 ,0xb0 ,0x00 ,0x73 ,0x01 ++ ,0x10 ,0x58 ,0x20 ,0xb9 ,0x30 ,0xed ,0x70 ,0xfc ++ ,0x20 ,0xed ,0x82 ,0x01 ,0x54 ,0x10 ,0x07 ,0x20 ++ ,0x4b ,0x10 ,0x12 ,0x20 ,0x51 ,0x10 ,0x5b ,0x20 ++ ,0xb9 ,0x10 ,0x01 ,0x20 ,0xeb ,0x10 ,0x00 ,0xc0 ++ ,0x02 ,0xa0 ,0x20 ,0x5e ,0x10 ,0x94 ,0x20 ,0x5d ++ ,0x10 ,0x00 ,0xc0 ,0x02 ,0xa4 ,0x82 ,0x02 ,0x3c ++ ,0x0c ,0x82 ,0x02 ,0x2c ,0x09 ,0x82 ,0x01 ,0x77 ++ ,0xc4 ,0x02 ,0xa4 ,0x40 ,0xc0 ,0x02 ,0xa4 ,0x14 ++ ,0x10 ,0x3c ,0x69 ,0xb0 ,0x00 ,0xa5 ,0x82 ,0x01 ++ ,0x2a ,0x10 ,0x02 ,0x20 ,0xeb ,0xc4 ,0x02 ,0xa0 ++ ,0x68 ,0x0f ,0xc0 ,0x02 ,0xa0 ,0x20 ,0x5e ,0x10 ++ ,0x94 ,0x20 ,0x5d ,0x10 ,0x00 ,0xc0 ,0x02 ,0xa4 ++ ,0x82 ,0x02 ,0x3c ,0x0c ,0x82 ,0x02 ,0x2c ,0x09 ++ ,0x82 ,0x01 ,0x77 ,0xc4 ,0x02 ,0xa4 ,0x40 ,0xc0 ++ ,0x02 ,0xa4 ,0x14 ,0x10 ,0x3c ,0x69 ,0xb0 ,0x00 ++ ,0xd8 ,0x82 ,0x01 ,0x2a ,0x10 ,0x04 ,0x20 ,0xeb ++ ,0xc4 ,0x02 ,0xa0 ,0x60 ,0x1e ,0xc0 ,0x02 ,0xa0 ++ ,0x20 ,0x5e ,0x10 ,0x94 ,0x20 ,0x5d ,0x10 ,0x00 ++ ,0xc0 ,0x02 ,0xa4 ,0x82 ,0x02 ,0x3c ,0x0c ,0x82 ++ ,0x02 ,0x2c ,0x09 ,0x82 ,0x01 ,0x77 ,0xc4 ,0x02 ++ ,0xa4 ,0x40 ,0xc0 ,0x02 ,0xa4 ,0x14 ,0x10 ,0x3c ++ ,0x69 ,0xb0 ,0x01 ,0x0b ,0x82 ,0x01 ,0x2a ,0x80 ++ ,0x00 ,0x91 ,0x30 ,0xea ,0xc0 ,0x02 ,0xa2 ,0x10 ++ ,0x04 ,0x20 ,0xba ,0x10 ,0x47 ,0x20 ,0x60 ,0x10 ++ ,0x05 ,0x20 ,0xba ,0x30 ,0xbd ,0x70 ,0x20 ,0xc0 ++ ,0x02 ,0xa3 ,0x30 ,0xea ,0xc5 ,0x02 ,0xa2 ,0x69 ++ ,0xb0 ,0x01 ,0x2a ,0xc4 ,0x02 ,0xa3 ,0x60 ,0x00 ++ ,0xb0 ,0x01 ,0xed ,0x01 ,0x10 ,0x05 ,0x20 ,0xeb ++ ,0x10 ,0x10 ,0x20 ,0xac ,0x10 ,0xf4 ,0x20 ,0xe7 ++ ,0x10 ,0x04 ,0x20 ,0xaa ,0x10 ,0x0 ,0xc0 ,0x02 ++ ,0xa0 ,0x20 ,0x5e ,0x10 ,0x94 ,0x20 ,0x5d ,0x30 ++ ,0xc4 ,0x70 ,0x01 ,0x90 ,0x00 ,0x05 ,0x01 ,0x82 ++ ,0x01 ,0x7f ,0x08 ,0xb0 ,0x01 ,0x77 ,0x01 ,0x30 ++ ,0xea ,0xc0 ,0x02 ,0xa2 ,0x10 ,0x5b ,0x20 ,0xb9 ++ ,0x10 ,0x04 ,0x20 ,0xba ,0x10 ,0x47 ,0x20 ,0x60 ++ ,0x10 ,0x05 ,0x20 ,0xba ,0x30 ,0xbd ,0x70 ,0x20 ++ ,0xc0 ,0x02 ,0xa3 ,0x30 ,0xea ,0xc5 ,0x02 ,0xa2 ++ ,0x69 ,0xb0 ,0x01 ,0x7f ,0xc4 ,0x02 ,0xa3 ,0x60 ++ ,0x00 ,0x90 ,0x01 ,0xaf ,0xb0 ,0x01 ,0xce ,0x10 ++ ,0x10 ,0x20 ,0xac ,0x10 ,0xf4 ,0x20 ,0xe7 ,0x10 ++ ,0x04 ,0x20 ,0xaa ,0x30 ,0xc6 ,0xc0 ,0x02 ,0xa1 ++ ,0x70 ,0x04 ,0x90 ,0x00 ,0x05 ,0x30 ,0xed ,0x70 ++ ,0xfb ,0x74 ,0x00 ,0x20 ,0xed ,0x01 ,0x10 ,0x10 ++ ,0x20 ,0xac ,0x10 ,0x90 ,0x20 ,0xe7 ,0x10 ,0x04 ++ ,0x20 ,0xaa ,0x30 ,0xc6 ,0xc0 ,0x02 ,0xa1 ,0x70 ++ ,0x04 ,0x90 ,0x00 ,0x05 ,0x30 ,0xed ,0x70 ,0xfb ++ ,0x74 ,0x04 ,0x20 ,0xed ,0x01 ,0x30 ,0x5e ,0x70 ++ ,0xff ,0x92 ,0x02 ,0x11 ,0x30 ,0x5e ,0x70 ,0x80 ++ ,0xb2 ,0x02 ,0x1a ,0x30 ,0x5e ,0x68 ,0x0f ,0x92 ++ ,0x02 ,0x23 ,0x30 ,0xeb ,0x74 ,0xf0 ,0x20 ,0xeb ++ ,0x82 ,0x01 ,0x7f ,0x82 ,0x02 ,0x3c ,0x80 ,0x02 ++ ,0x02 ,0x30 ,0xed ,0x70 ,0xfc ,0x74 ,0x01 ,0x20 ++ ,0xed ,0x01 ,0x30 ,0xed ,0x70 ,0xfc ,0x74 ,0x02 ++ ,0x20 ,0xed ,0x01 ,0x30 ,0xed ,0x70 ,0xfc ,0x74 ++ ,0x03 ,0x20 ,0xed ,0x01 ,0x30 ,0xc6 ,0xc0 ,0x02 ++ ,0xa1 ,0x70 ,0x04 ,0x90 ,0x00 ,0x05 ,0x08 ,0xb0 ++ ,0x02 ,0x2c ,0x09 ,0x01 ,0x30 ,0xeb ,0x74 ,0x10 ++ ,0x20 ,0xeb ,0x30 ,0xd8 ,0x14 ,0x70 ,0x07 ,0x90 ++ ,0x02 ,0x51 ,0x11 ,0x68 ,0x05 ,0x90 ,0x02 ,0x51 ++ ,0x01 ,0x30 ,0xcf ,0xc0 ,0x02 ,0xa6 ,0xc4 ,0x02 ++ ,0xa6 ,0x70 ,0xf8 ,0x90 ,0x02 ,0x61 ,0xb0 ,0x02 ++ ,0x7e ,0xc4 ,0x02 ,0xa6 ,0x4c ,0x4c ,0x4c ,0x4c ++ ,0x4c ,0xc0 ,0x02 ,0xa6 ,0x30 ,0xd0 ,0x48 ,0x48 ++ ,0x48 ,0x14 ,0xc4 ,0x02 ,0xa6 ,0x61 ,0xc0 ,0x02 ++ ,0xa6 ,0x20 ,0xee ,0x80 ,0x02 ,0x88 ,0x10 ,0xff ++ ,0xc0 ,0x02 ,0xa6 ,0x20 ,0xee ,0x80 ,0x02 ,0x88 ++ ,0xc4 ,0x02 ,0xa6 ,0x14 ,0x30 ,0xef ,0x69 ,0x88 ++ ,0x02 ,0x93 ,0x01 ,0x30 ,0xa3 ,0x70 ,0x07 ,0x74 ++ ,0x28 ,0x20 ,0xa3 ,0x70 ,0x07 ,0x20 ,0xa3 ,0x01 ++ ,0x72}; ++ ++static const struct dvb_frontend_ops mn88436_ops; ++ ++static int log10_easy( u32 cnr ) ++{ ++ u32 c; ++ s32 ret; ++ s32 logtbl[] = { ++ 0 ,-1000,-699 ,-523,-398, ++ -301,-222 ,-155 ,-97 ,-46 , ++ 0 ,41 ,79 ,114 ,146 , ++ 176 ,204 ,230 ,255 , ++ 279 ,301 ,322 ,342 , ++ 362 ,380 ,398 ,415 , ++ 431 ,447 ,462 ,477 , ++ 491 ,505 ,519 ,531 , ++ 544 ,556 ,568 ,580 , ++ 591 ,602 ,613 ,623 , ++ 633 ,643 ,653 ,663 , ++ 672 ,681 ,690 ,699 , ++ 708 ,716 ,724 ,732 , ++ 740 ,748 ,756 ,763 , ++ 771 ,778 ,785 ,792 , ++ 799 ,806 ,813 ,820 , ++ 826 ,833 ,839 ,845 , ++ 851 ,857 ,863 ,869 , ++ 875 ,881 ,886 ,892 , ++ 898 ,903 ,908 ,914 , ++ 919 ,924 ,929 ,934 , ++ 940 ,944 ,949 ,954 , ++ 959 ,964 ,968 ,973 , ++ 978 ,982 ,987 ,991 , ++ 996 ,1000}; ++ c = 0; ++ ++ while( cnr > 100 ){ ++ cnr = cnr / 10; ++ c++; ++ } ++ ret = logtbl[cnr] + c*1000 + 1000; ++ ++ return ret; ++} ++ ++static int DMD_send_registers(struct i2c_client *client,u8*regset) ++{ ++ struct mn88436_dev*dev = i2c_get_clientdata(client); ++ int ret; ++ u32 i; ++ for(i=0;;) ++ { ++ if(regset[i]==0xff)break; ++ ret=regmap_write(dev->regmap[regset[i]],regset[i+1],regset[i+2]); ++ i=i+3; ++ } ++ return ret; ++} ++ ++static int mn88436_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct mn88436_dev *dev = i2c_get_clientdata(client); ++ u32 ifagc = 0; ++ int IF1,IF2; ++ ++ regmap_read(dev->regmap[1], DMD_USR_IFAGCMON1 , &IF1 ); ++ regmap_read(dev->regmap[1], DMD_USR_IFAGCMON2 , &IF2 ); ++ ++ ifagc = IF1 * 256 + IF2; ++ if ( ifagc < AGC_MIN ) ++ { ++ *strength = 0; ++ } ++ else if ( ifagc > AGC_MAX ) ++ { ++ *strength = 100; ++ } ++ else ++ { ++ *strength = (ifagc-AGC_MIN)*100/AGC_RANGE; ++ } ++ ++ ++ return 0; ++} ++ ++static int mn88436_read_status(struct dvb_frontend *fe,enum fe_status *status) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct mn88436_dev *dev = i2c_get_clientdata(client); ++ ++ int ret; ++ int utemp; ++ int i =0; ++ for(i=0;i<50;i++) ++ { ++ ret = regmap_read(dev->regmap[0],DMD_MAIN_STSMON1,&utemp); ++ if(utemp&0x1){ ++ *status = FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ break; ++ } ++ else ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; ++ ++ msleep(1); ++ } ++ ++ return ret; ++ ++} ++static int mn88436_init(struct dvb_frontend *fe) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct mn88436_dev *dev = i2c_get_clientdata(client); ++ int ret; ++ int utemp; ++ u32 i; ++ /*Demod LSI init*/ ++ ret = DMD_send_registers(client,DMD_REG_ATSC); ++ if(ret) ++ goto err; ++ ret = regmap_write(dev->regmap[0],DMD_MAIN_PSEQSET,0x03); ++ if(ret) ++ goto err; ++ for(i=0;iregmap[0],DMD_MAIN_PSEQPRG,MN88436_REG_AUTOCTRL[i]); ++ ++ ++ ret |= regmap_read(dev->regmap[0],DMD_MAIN_PSEQSET,&utemp); ++ if(utemp&0x20) ++ { ++ printk("ERROR : PSEQ Parity \n"); ++ } ++ else ++ ret |= regmap_write(dev->regmap[0],DMD_MAIN_PSEQSET,0x00); ++ ++ if(ret) ++ goto err; ++ ++ ret = regmap_read(dev->regmap[0],DMD_MAIN_TCBSET,&utemp); ++ utemp |=0x7f &0x53; ++ utemp &=(0x7f^0xff)|0x53; ++ ret = regmap_write(dev->regmap[0],DMD_MAIN_TCBSET,utemp); ++ ++ ret = regmap_write(dev->regmap[0],DMD_MAIN_TCBADR,0x00); ++ if(ret) ++ goto err; ++ ++ ++ /*set TS mode*/ ++ utemp = dev->ts_mode ?0xc0 :0xc1; ++ ret = regmap_write(dev->regmap[0],DMD_MAIN_CPOSET2,utemp); ++ ++ utemp = dev->ts_mode ?0xc0 :0xff; ++ ret |= regmap_write(dev->regmap[0],DMD_MAIN_GPSET1,utemp); ++ ++ if(!dev->ts_mode) ++ ret |= regmap_write(dev->regmap[0],DMD_MAIN_CPOSET1,0x01); ++ ++ if(ret) ++ goto err; ++ ++ dev_dbg(&client->dev,"mn88436 init successfully."); ++ ++ return ret; ++err: ++ dev_err(&client->dev,"failed =%d",ret); ++ return ret; ++ ++} ++static int mn88436_set_frontend(struct dvb_frontend *fe) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct mn88436_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ int utemp; ++ u32 tuner_status; ++ ++ dev_dbg(&client->dev,"delivery_system=%u modulation=%u ,frequency=%d \n",c->delivery_system, ++ c->modulation,c->frequency); ++ switch(c->modulation){ ++ default: ++ case VSB_8: ++ ret = DMD_send_registers(client,DMD_REG_ATSC); ++ dev->mode = DMD_E_ATSC; ++ break; ++ case QAM_64: ++ ret = DMD_send_registers(client,DMD_REG_QAM_64QAM); ++ dev->mode = DMD_E_QAMB_64QAM; ++ break; ++ case QAM_256: ++ ret = DMD_send_registers(client,DMD_REG_QAM_256QAM); ++ dev->mode = DMD_E_QAMB_256QAM; ++ break; ++ } ++ /*set TS again*/ ++ utemp = dev->ts_mode ?0xc0 :0xc1; ++ ret = regmap_write(dev->regmap[0],DMD_MAIN_CPOSET2,utemp); ++ ++ utemp = dev->ts_mode ?0xc0 :0xff; ++ ret |= regmap_write(dev->regmap[0],DMD_MAIN_GPSET1,utemp); ++ ++ if(!dev->ts_mode) ++ ret |= regmap_write(dev->regmap[0],DMD_MAIN_CPOSET1,0x01); ++ ++ ret |= regmap_write(dev->regmap[0],DMD_MAIN_VEQSET2,0xe0); ++ if(ret) ++ goto err; ++ ++ /*set tuner*/ ++ if(fe->ops.tuner_ops.set_params){ ++ ret = fe->ops.tuner_ops.set_params(fe); ++ if(ret) ++ goto err; ++ } ++ if(fe->ops.tuner_ops.get_status){ ++ ret = fe->ops.tuner_ops.get_status(fe,&tuner_status); ++ } ++ msleep(5); ++ ++ ret = regmap_write(dev->regmap[0],DMD_MAIN_RSTSET1,0x77); ++ if(ret) ++ goto err; ++ ++ return ret; ++err: ++ dev_err(&client->dev,"failed = %d" ,ret); ++ return ret; ++} ++static int mn88436_read_snr(struct dvb_frontend* fe, u16* snr) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct mn88436_dev *dev = i2c_get_clientdata(client); ++ int rd; ++ u32 cni,cnd; ++ u32 x,y; ++ ++ regmap_read(dev->regmap[1], DMD_USR_CNMON1 , &rd ); ++ x = 0x100 * rd; ++ regmap_read(dev->regmap[1], DMD_USR_CNMON2 , &rd ); ++ x += rd; ++ regmap_read(dev->regmap[1], DMD_USR_CNMON3 , &rd ); ++ y = 0x100 * rd; ++ regmap_read(dev->regmap[1], DMD_USR_CNMON4 , &rd ); ++ y += rd; ++ if( dev->mode == DMD_E_ATSC ) ++ { ++ //after EQ ++ *snr = 4634 - log10_easy( y ); ++ ++ } ++ else ++ { ++ if( y != 0 ) ++ *snr = log10_easy( (8*x) / y ); ++ else ++ *snr = 0; ++ ++ } ++ ++ return 0; ++} ++ ++static const struct dvb_frontend_ops mn88436_ops = { ++ .delsys = {SYS_ATSC,SYS_DVBC_ANNEX_B}, ++ .info = { ++ .name = "MN88436 ATSC/QAMB frontend", ++ .frequency_min = 44000000, ++ .frequency_max = 1002000000, ++ .frequency_stepsize = 62500, ++ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB ++ ++ }, ++ .init = mn88436_init, ++ .set_frontend = mn88436_set_frontend, ++ .read_status = mn88436_read_status, ++ .read_signal_strength = mn88436_read_signal_strength, ++ .read_snr = mn88436_read_snr, ++}; ++static int mn88436_probe(struct i2c_client *client , ++ const struct i2c_device_id *id) ++{ ++ struct mn88436_config *cfg = client->dev.platform_data; ++ struct mn88436_dev *dev; ++ int ret; ++ int utmp; ++ static const struct regmap_config regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ }; ++ dev = kzalloc(sizeof(*dev),GFP_KERNEL); ++ if(!dev){ ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ dev->i2c_write_max = cfg->i2c_wr_max ?cfg->i2c_wr_max : ~0; ++ dev->ts_mode = cfg->ts_mode; ++ dev->mode = DMD_E_ATSC; ++ dev->client[0] = client; ++ dev->regmap[0] = regmap_init_i2c(dev->client[0],®map_config); ++ if(IS_ERR(dev->regmap[0])){ ++ ret = PTR_ERR(dev->regmap[0]); ++ goto err_kfree; ++ } ++ /*check demod i2c*/ ++ ret = regmap_read(dev->regmap[0],0xff,&utmp); ++ if(ret) ++ goto err_regmap_0_regmap_exit; ++ ++ ret = regmap_write(dev->regmap[0],0xff,0x99); ++ if(ret) ++ goto err_regmap_0_regmap_exit; ++ ++ ret = regmap_read(dev->regmap[0],0xff,&utmp); ++ if(utmp!=0x99) ++ goto err_regmap_0_regmap_exit; ++ ++ /*chip has two IIC address for different register bank, 0x18 and 0x10,so we need register a dummy clients */ ++ dev->client[1] = i2c_new_dummy(client->adapter,0x10); ++ if(!dev->client[1]){ ++ ret = -ENODEV; ++ dev_err(&client->dev,"I2C registeration failed\n"); ++ if(ret) ++ goto err_regmap_0_regmap_exit; ++ } ++ ++ ++ dev->regmap[1] = regmap_init_i2c(dev->client[1],®map_config); ++ if(IS_ERR(dev->regmap[1])){ ++ ret = PTR_ERR(dev->regmap[1]); ++ goto err_client_1_i2c_unregister_device; ++ } ++ i2c_set_clientdata(dev->client[1],dev); ++ ++ /*test the dummy i2c*/ ++ ret = regmap_write(dev->regmap[1],0xff,0x88); ++ if(ret) ++ goto err_regmap_1_regmap_exit; ++ ret = regmap_read(dev->regmap[1],0xff,&utmp); ++ if(ret) ++ goto err_regmap_1_regmap_exit; ++ if(utmp!=0x88) ++ goto err_regmap_1_regmap_exit; ++ ++ /*Create dvb frontend*/ ++ ++ memcpy(&dev->fe.ops,&mn88436_ops,sizeof(struct dvb_frontend_ops)); ++ dev->fe.demodulator_priv = client; ++ *cfg->fe = &dev->fe; ++ i2c_set_clientdata(client,dev); ++ ++ dev_info(&client->dev, "Panasonic MN88436 successfully identified\n"); ++ ++ return 0; ++ ++err_regmap_1_regmap_exit: ++ regmap_exit(dev->regmap[1]); ++err_client_1_i2c_unregister_device : ++ i2c_unregister_device(dev->client[1]); ++err_regmap_0_regmap_exit: ++ regmap_exit(dev->regmap[0]); ++ ++err_kfree: ++ kfree(dev); ++err : ++ dev_err(&client->dev,"__failed = %d___\n",ret); ++ return ret; ++} ++static int mn88436_remove(struct i2c_client *client) ++{ ++ struct mn88436_dev *dev = i2c_get_clientdata(client); ++ ++ regmap_exit(dev->regmap[1]); ++ i2c_unregister_device(dev->client[1]); ++ ++ regmap_exit(dev->regmap[0]); ++ ++ kfree(dev); ++ ++ return 0; ++ ++} ++static const struct i2c_device_id mn88436_id_table[] = { ++ {"mn88436",0}, ++ {} ++ ++}; ++ ++MODULE_DEVICE_TABLE(i2c,mn88436_id_table); ++ ++static struct i2c_driver mn88436_driver = { ++ .driver ={ ++ .name = "mn88436", ++ }, ++ .probe = mn88436_probe, ++ .remove = mn88436_remove, ++ .id_table = mn88436_id_table, ++ ++}; ++ ++module_i2c_driver(mn88436_driver); ++ ++MODULE_AUTHOR("Davin "); ++MODULE_DESCRIPTION("Panasonic MN88436 ATSC/QAMB demodulator driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/media/dvb-frontends/mn88436.h b/drivers/media/dvb-frontends/mn88436.h +new file mode 100644 +index 0000000..ae9922f +--- /dev/null ++++ b/drivers/media/dvb-frontends/mn88436.h +@@ -0,0 +1,14 @@ ++#ifndef MN88436_H ++#define MN88436_H ++#include ++ ++struct mn88436_config{ ++#define DMD_E_TSOUT_PARALLEL_FIXED_CLOCK 0 ++#define DMD_E_TSOUT_SERIAL_VARIABLE_CLOCK 1 ++ int ts_mode; ++ ++ u16 i2c_wr_max; ++ ++ struct dvb_frontend **fe; ++}; ++#endif +diff --git a/drivers/media/dvb-frontends/mn88436_priv.h b/drivers/media/dvb-frontends/mn88436_priv.h +new file mode 100644 +index 0000000..6ceee47 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mn88436_priv.h +@@ -0,0 +1,370 @@ ++#ifndef MN88436_PRIV_H ++#define MN88436_PRIV_H ++ ++#include "dvb_frontend.h" ++#include "mn88436.h" ++#include ++ ++typedef enum{ ++ DMD_E_ATSC, ++ DMD_E_QAMB_64QAM, ++ DMD_E_QAMB_256QAM, ++ ++}DMD_SYSTEM_t; ++ ++struct mn88436_dev { ++ struct i2c_client *client[2]; ++ struct regmap *regmap[2]; ++ struct dvb_frontend fe; ++ u16 i2c_write_max; ++ ++ unsigned int ts_mode; ++ ++ DMD_SYSTEM_t mode; ++ ++}; ++ ++#define AGC_MIN 801 //-90dBm ++#define AGC_MAX 3338 //0dBm ++#define AGC_RANGE (AGC_MAX - AGC_MIN) ++ ++ ++#define DMD_INFORMATION_MAX 512 ++#define DMD_INFO_VALUE_MAX 32 ++ ++#define DMD_MAX_DEVICE 4 ++#define DMD_REG_BANK 2 ++ ++#define DMD_NOT_SUPPORT 0 ++#define DMD_SYSTEM_MAX 15 ++#define DMD_TCB_DATA_MAX 256 ++#define DMD_REGISTER_MAX 2048 ++#define DMD_I2C_MAXSIZE 127 ++ ++ ++ ++//For Main ++#define DMD_MAIN_IBMOD 0x0 ++#define DMD_MAIN_CPOSET1 0x1 ++#define DMD_MAIN_CPOSET2 0x2 ++#define DMD_MAIN_HIZSET 0x3 ++#define DMD_MAIN_INVSET 0x4 ++#define DMD_MAIN_GPSET1 0x5 ++#define DMD_MAIN_GPSET2 0x6 ++#define DMD_MAIN_GPSET3 0x7 ++#define DMD_MAIN_MDADATL 0x8 ++#define DMD_MAIN_MDADATU 0x9 ++#define DMD_MAIN_IQDSET 0xA ++#define DMD_MAIN_FOFFSET1U 0xB ++#define DMD_MAIN_FOFFSET1L 0xC ++#define DMD_MAIN_SRATEIN1 0xD ++#define DMD_MAIN_SRATEIN2 0xE ++#define DMD_MAIN_SRATEIN3 0xF ++#define DMD_MAIN_RSTSET1 0x10 ++#define DMD_MAIN_RSTSET2 0x11 ++#define DMD_MAIN_FOFFSET2U 0x12 ++#define DMD_MAIN_FOFFSET2L 0x13 ++#define DMD_MAIN_I2CSET 0x14 ++#define DMD_MAIN_TCBSET 0x15 ++#define DMD_MAIN_TCBRT 0x16 ++#define DMD_MAIN_TCBADR 0x17 ++#define DMD_MAIN_TCBDT0 0x18 ++#define DMD_MAIN_TCBDT1 0x19 ++#define DMD_MAIN_TCBDT2 0x1A ++#define DMD_MAIN_TCBDT3 0x1B ++#define DMD_MAIN_TCBDT4 0x1C ++#define DMD_MAIN_TCBDT5 0x1D ++#define DMD_MAIN_TCBDT6 0x1E ++#define DMD_MAIN_TCBDT7 0x1F ++#define DMD_MAIN_TCBCOM 0x20 ++#define DMD_MAIN_VAGCREF 0x21 ++#define DMD_MAIN_QAGCREF 0x22 ++#define DMD_MAIN_AGCCO1 0x23 ++#define DMD_MAIN_AGCSET1 0x24 ++#define DMD_MAIN_VAGCDLY1L 0x25 ++#define DMD_MAIN_VQAGCDLY1U 0x26 ++#define DMD_MAIN_QAGCDLY1L 0x27 ++#define DMD_MAIN_ERRCNTTHU 0x28 ++#define DMD_MAIN_ERRCNTTHL 0x29 ++#define DMD_MAIN_ALCSET1 0x2A ++#define DMD_MAIN_ALCSET2 0x2B ++#define DMD_MAIN_ALCSET3 0x2C ++#define DMD_MAIN_CLIPVUL 0x2D ++#define DMD_MAIN_CLIPVL 0x2E ++#define DMD_MAIN_PIRETH2U 0x2F ++#define DMD_MAIN_PIRETH2L 0x30 ++#define DMD_MAIN_PIRETH3U 0x31 ++#define DMD_MAIN_PIRETH3L 0x32 ++#define DMD_MAIN_PAFCSGSET1 0x33 ++#define DMD_MAIN_PAFCSGSET2 0x34 ++#define DMD_MAIN_PAFCLPFSET1 0x35 ++#define DMD_MAIN_PAFCLPFSETA2 0x36 ++#define DMD_MAIN_PAFCLPFSETA3 0x37 ++#define DMD_MAIN_PAFCLPFSETA4 0x38 ++#define DMD_MAIN_PAFCLPFSETB2 0x39 ++#define DMD_MAIN_PAFCLPFSETB3 0x3A ++#define DMD_MAIN_PAFCLPFSETB4 0x3B ++#define DMD_MAIN_AFCSET1 0x3C ++#define DMD_MAIN_AFCCO 0x3D ++#define DMD_MAIN_AFCADD 0x3E ++#define DMD_MAIN_APCSET1 0x3F ++#define DMD_MAIN_APCSET2 0x40 ++#define DMD_MAIN_APCSET4 0x41 ++#define DMD_MAIN_APCSET5 0x42 ++#define DMD_MAIN_APCCO1 0x43 ++#define DMD_MAIN_APCCO2 0x44 ++#define DMD_MAIN_APCCO3 0x45 ++#define DMD_MAIN_APCCO4 0x46 ++#define DMD_MAIN_VCKRSET1 0x47 ++#define DMD_MAIN_VCKRSET2 0x48 ++#define DMD_MAIN_VCKRCOUL 0x49 ++#define DMD_MAIN_VCKRCOL 0x4A ++#define DMD_MAIN_VFCKSET1 0x4B ++#define DMD_MAIN_VFCKSET2 0x4C ++#define DMD_MAIN_VFCKBWUL 0x4D ++#define DMD_MAIN_VFCKBWLK 0x4E ++#define DMD_MAIN_VFCKATUL 0x4F ++#define DMD_MAIN_VFCKATLK 0x50 ++#define DMD_MAIN_VTCKSET1 0x51 ++#define DMD_MAIN_VTCKSET2 0x52 ++#define DMD_MAIN_VDAGCREF 0x53 ++#define DMD_MAIN_QDAGCREF 0x54 ++#define DMD_MAIN_GMIN 0x55 ++#define DMD_MAIN_DAGCCO 0x56 ++#define DMD_MAIN_CKRCO1 0x57 ++#define DMD_MAIN_CKRCO2 0x58 ++#define DMD_MAIN_CKRSET1 0x59 ++#define DMD_MAIN_CKRSET2 0x5A ++#define DMD_MAIN_PNTSET 0x5B ++#define DMD_MAIN_PNTCO 0x5C ++#define DMD_MAIN_NRFMODE 0x5D ++#define DMD_MAIN_FDATSC 0x5E ++#define DMD_MAIN_FLTBW1 0x5F ++#define DMD_MAIN_NRFRSEL 0x60 ++#define DMD_MAIN_SYNCSET1 0x61 ++#define DMD_MAIN_SYNCSET2 0x62 ++#define DMD_MAIN_SYNCSET6 0x63 ++#define DMD_MAIN_QDETREF 0x64 ++#define DMD_MAIN_QDETSET1 0x65 ++#define DMD_MAIN_QDETSET2 0x66 ++#define DMD_MAIN_EQSET 0x67 ++#define DMD_MAIN_VEQSET1 0x68 ++#define DMD_MAIN_VEQSET2 0x69 ++#define DMD_MAIN_VEQSET3 0x6A ++#define DMD_MAIN_VEQSET4 0x6B ++#define DMD_MAIN_VEQSET5 0x6C ++#define DMD_MAIN_VEQSET6 0x6D ++#define DMD_MAIN_VEQSET7 0x6E ++#define DMD_MAIN_VEQSET8 0x6F ++#define DMD_MAIN_VEQSET9 0x70 ++#define DMD_MAIN_AGCMON 0x71 ++#define DMD_MAIN_CKRFEMON 0x72 ++#define DMD_MAIN_DAGCMON 0x73 ++#define DMD_MAIN_QEQSET 0x74 ++#define DMD_MAIN_PAFCPILOT 0x75 ++#define DMD_MAIN_VCKRSYM 0x76 ++#define DMD_MAIN_APCMON 0x77 ++#define DMD_MAIN_PNTMON 0x78 ++#define DMD_MAIN_VEQSET10 0x79 ++#define DMD_MAIN_VEQSET11 0x7A ++#define DMD_MAIN_VEQSET12 0x7B ++#define DMD_MAIN_VEQSET13 0x7C ++#define DMD_MAIN_VEQSET14 0x7D ++#define DMD_MAIN_VEQSET15 0x7E ++#define DMD_MAIN_VEQSET16 0x7F ++#define DMD_MAIN_VEQSET17 0x80 ++#define DMD_MAIN_VEQSET18 0x81 ++#define DMD_MAIN_VEQSET19 0x82 ++#define DMD_MAIN_VEQSET20 0x83 ++#define DMD_MAIN_VEQSET21 0x84 ++#define DMD_MAIN_VEQSET22 0x85 ++#define DMD_MAIN_PLOCKTH1 0x86 ++#define DMD_MAIN_PLOCKTH2 0x87 ++#define DMD_MAIN_PLOCKTH3 0x88 ++#define DMD_MAIN_CRCDIVASET1 0x89 ++#define DMD_MAIN_CRCDIVASET2 0x8A ++#define DMD_MAIN_CRCDIVASET3 0x8B ++#define DMD_MAIN_CRCDIVBSET1 0x8C ++#define DMD_MAIN_CRCDIVBSET2 0x8D ++#define DMD_MAIN_CRCDIVBSET3 0x8E ++#define DMD_MAIN_CRCDIVSMV 0x8F ++#define DMD_MAIN_CRCDIVTIM 0x90 ++#define DMD_MAIN_PNDETSET1 0x91 ++#define DMD_MAIN_PNDETSET2 0x92 ++#define DMD_MAIN_PREIDETSET1 0x93 ++#define DMD_MAIN_PREQDETSET1 0x94 ++#define DMD_MAIN_PNDETSET3 0x95 ++#define DMD_MAIN_PNDETSET4 0x96 ++#define DMD_MAIN_PNSMSET1 0x97 ++#define DMD_MAIN_PNSMSET2 0x98 ++#define DMD_MAIN_PNSMSET3 0x99 ++#define DMD_MAIN_PNSMSET4 0x9A ++#define DMD_MAIN_PNSMSET5 0x9B ++#define DMD_MAIN_PNSMSET6 0x9C ++#define DMD_MAIN_PNSMSET7 0x9D ++#define DMD_MAIN_PNSMSET8 0x9E ++#define DMD_MAIN_PNSMSET9 0x9F ++#define DMD_MAIN_PNSMSET10 0xA0 ++#define DMD_MAIN_PNSMSET11 0xA1 ++#define DMD_MAIN_PNSMSET12 0xA2 ++#define DMD_MAIN_PNSMSET13 0xA3 ++#define DMD_MAIN_PNREGSET1 0xA4 ++#define DMD_MAIN_PNREGSET2 0xA5 ++#define DMD_MAIN_PNREGSET3 0xA6 ++#define DMD_MAIN_PNREGSET4 0xA7 ++#define DMD_MAIN_PNREGSET5 0xA8 ++#define DMD_MAIN_PNREGSET6 0xA9 ++#define DMD_MAIN_FREQSET 0xAA ++#define DMD_MAIN_FREQU 0xAB ++#define DMD_MAIN_FREQL 0xAC ++#define DMD_MAIN_PNREGSET10 0xAD ++#define DMD_MAIN_PNREGSET11 0xAE ++#define DMD_MAIN_PNREGSET12 0xAF ++#define DMD_MAIN_PNREGSET13 0xB0 ++#define DMD_MAIN_PNREGSET14 0xB1 ++#define DMD_MAIN_PNREGSET15 0xB2 ++#define DMD_MAIN_PNREGSET16 0xB3 ++#define DMD_MAIN_PNREGSET17 0xB4 ++#define DMD_MAIN_PNREGSET18 0xB5 ++#define DMD_MAIN_PNREGSET19 0xB6 ++#define DMD_MAIN_PNREGSET20 0xB7 ++#define DMD_MAIN_PNREGSET21 0xB8 ++#define DMD_MAIN_NTCWTH1 0xB9 ++#define DMD_MAIN_IBTGSET 0xBA ++#define DMD_MAIN_AFCMON 0xBB ++#define DMD_MAIN_CKRMON 0xBC ++#define DMD_MAIN_NRFRDAT 0xBD ++#define DMD_MAIN_MEANFERR 0xBE ++#define DMD_MAIN_MEANMAGERR 0xBF ++#define DMD_MAIN_PAFCSGGATE 0xC0 ++#define DMD_MAIN_AFCMONB 0xC1 ++#define DMD_MAIN_PLOCKMONAU 0xC2 ++#define DMD_MAIN_PLOCKMONAL 0xC3 ++#define DMD_MAIN_STSMON1 0xC4 ++#define DMD_MAIN_STSMON2 0xC5 ++#define DMD_MAIN_SYNCRD2 0xC6 ++#define DMD_MAIN_SYNCRD3 0xC7 ++#define DMD_MAIN_PLOCKMONBU 0xC8 ++#define DMD_MAIN_PLOCKMONBL 0xC9 ++#define DMD_MAIN_PNDETU 0xCA ++#define DMD_MAIN_PNDETL 0xCB ++#define DMD_MAIN_PIBETAU 0xCC ++#define DMD_MAIN_PIBETAL 0xCD ++#define DMD_MAIN_EQMNSET 0xCE ++#define DMD_MAIN_EQERR1 0xCF ++#define DMD_MAIN_EQERR2 0xD0 ++#define DMD_MAIN_RFAGCMON1P 0xD1 ++#define DMD_MAIN_RFAGCMON2P 0xD2 ++#define DMD_MAIN_IFAGCMON1P 0xD3 ++#define DMD_MAIN_IFAGCMON2P 0xD4 ++#define DMD_MAIN_PLOCKSTATE 0xD5 ++#define DMD_MAIN_PIBETAQU 0xD6 ++#define DMD_MAIN_PIBETAQL 0xD7 ++#define DMD_MAIN_PNDETSTATE 0xD8 ++#define DMD_MAIN_CNSETP 0xD9 ++#define DMD_MAIN_CNFLGP 0xDA ++#define DMD_MAIN_CNMON1P 0xDB ++#define DMD_MAIN_CNMON2P 0xDC ++#define DMD_MAIN_CNMON3P 0xDD ++#define DMD_MAIN_CNMON4P 0xDE ++#define DMD_MAIN_FECSET 0xDF ++#define DMD_MAIN_BERDSETP 0xE0 ++#define DMD_MAIN_BERTSET1P 0xE1 ++#define DMD_MAIN_BERTSET2P 0xE2 ++#define DMD_MAIN_BERFLGP 0xE3 ++#define DMD_MAIN_BERMON1P 0xE4 ++#define DMD_MAIN_BERMON2P 0xE5 ++#define DMD_MAIN_BERMON3P 0xE6 ++#define DMD_MAIN_NTCWTH2 0xE7 ++#define DMD_MAIN_PWDSET1 0xE8 ++#define DMD_MAIN_PWDSET2 0xE9 ++#define DMD_MAIN_PSEQOP1 0xEA ++#define DMD_MAIN_PSEQOP2 0xEB ++#define DMD_MAIN_PSEQOP3 0xEC ++#define DMD_MAIN_PSEQOP4 0xED ++#define DMD_MAIN_PSEQOP5 0xEE ++#define DMD_MAIN_PSEQOP6 0xEF ++#define DMD_MAIN_PSEQSET 0xF0 ++#define DMD_MAIN_PSEQPRG 0xF1 ++#define DMD_MAIN_PSEQSEL 0xF2 ++#define DMD_MAIN_PSEQDBG 0xF3 ++#define DMD_MAIN_PSEQOP7 0xF4 ++#define DMD_MAIN_PSEQOP8 0xF5 ++#define DMD_MAIN_PSEQOP9 0xF6 ++#define DMD_MAIN_PSEQOP10 0xF7 ++#define DMD_MAIN_PSEQADRU 0xF8 ++#define DMD_MAIN_PSEQADRL 0xF9 ++#define DMD_MAIN_PSEQDT 0xFA ++#define DMD_MAIN_TESTSET3 0xFB ++#define DMD_MAIN_CLKGSET 0xFC ++#define DMD_MAIN_TPLLSET1 0xFD ++#define DMD_MAIN_TPLLSET2 0xFE ++#define DMD_MAIN_RDCHK 0xFF ++ ++ ++//For USR ++#define DMD_USR_INTDEFR 0x9 ++#define DMD_USR_INTDEFF 0xA ++#define DMD_USR_INTSET 0xB ++#define DMD_USR_INTCNT 0xC ++#define DMD_USR_INTCND 0xD ++#define DMD_USR_I2CSET 0x14 ++#define DMD_USR_CNSET 0x5A ++#define DMD_USR_CNFLG 0x5B ++#define DMD_USR_CNMON1 0x5C ++#define DMD_USR_CNMON2 0x5D ++#define DMD_USR_CNMON3 0x5E ++#define DMD_USR_CNMON4 0x5F ++#define DMD_USR_BERTSET1 0x60 ++#define DMD_USR_BERTSET2 0x61 ++#define DMD_USR_BERPSET1 0x62 ++#define DMD_USR_BERPSET2 0x63 ++#define DMD_USR_BERFLG 0x64 ++#define DMD_USR_BERMON1 0x65 ++#define DMD_USR_BERMON2 0x66 ++#define DMD_USR_BERMON3 0x67 ++#define DMD_USR_RFAGCMON1 0x68 ++#define DMD_USR_RFAGCMON2 0x69 ++#define DMD_USR_IFAGCMON1 0x6A ++#define DMD_USR_IFAGCMON2 0x6B ++#define DMD_USR_IMON 0x74 ++#define DMD_USR_QMON 0x79 ++#define DMD_USR_SDCC 0x80 ++#define DMD_USR_VSAGCREFU 0x81 ++#define DMD_USR_VSAGCREFL 0x82 ++#define DMD_USR_QSAGCREFU 0x83 ++#define DMD_USR_QSAGCREFL 0x84 ++#define DMD_USR_SAGCCO 0x85 ++#define DMD_USR_SAGCSET 0x86 ++#define DMD_USR_VPWMSET1 0x87 ++#define DMD_USR_VPWMDAT1 0x88 ++#define DMD_USR_QPWMSET1 0x89 ++#define DMD_USR_QPWMDAT1 0x8A ++#define DMD_USR_QFECSET1 0x8B ++#define DMD_USR_QFECSET4 0x8C ++#define DMD_USR_QFECSET5 0x8D ++#define DMD_USR_TSCSETV1 0x8E ++#define DMD_USR_TSCSETQ1 0x8F ++#define DMD_USR_TSCSET2 0x90 ++#define DMD_USR_TSCSET4 0x91 ++#define DMD_USR_FAD064U 0x92 ++#define DMD_USR_FAD064M 0x93 ++#define DMD_USR_FAD064L 0x94 ++#define DMD_USR_FAD256U 0x95 ++#define DMD_USR_FAD256M 0x96 ++#define DMD_USR_FAD256L 0x97 ++#define DMD_USR_FAD188U 0x98 ++#define DMD_USR_FAD188M 0x99 ++#define DMD_USR_FAD188L 0x9A ++#define DMD_USR_FAD208U 0x9B ++#define DMD_USR_FAD208M 0x9C ++#define DMD_USR_FAD208L 0x9D ++#define DMD_USR_TESTSET1 0x9E ++#define DMD_USR_TESTSET2 0x9F ++#define DMD_USR_AD10SET1 0xA0 ++#define DMD_USR_AD10SET2 0xA1 ++#define DMD_USR_AD10SET3 0xA2 ++#define DMD_USR_AD10SET4 0xA3 ++#define DMD_USR_RDCHK 0xFF ++ ++#endif +diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c +index 961b9a2..8ce8682 100644 +--- a/drivers/media/dvb-frontends/mt312.c ++++ b/drivers/media/dvb-frontends/mt312.c +@@ -471,6 +471,9 @@ static int mt312_read_status(struct dvb_frontend *fe, enum fe_status *s) + if (status[0] & 0x01) + *s |= FE_HAS_LOCK; /* qpsk lock */ + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, *s & FE_HAS_LOCK); ++ + return 0; + } + +@@ -703,6 +706,9 @@ static int mt312_sleep(struct dvb_frontend *fe) + int ret; + u8 config; + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + /* reset all registers to defaults */ + ret = mt312_reset(state, 1); + if (ret < 0) +@@ -744,6 +750,10 @@ static int mt312_get_tune_settings(struct dvb_frontend *fe, + static void mt312_release(struct dvb_frontend *fe) + { + struct mt312_state *state = fe->demodulator_priv; ++ ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + kfree(state); + } + +diff --git a/drivers/media/dvb-frontends/mt312.h b/drivers/media/dvb-frontends/mt312.h +index 386939a..aef92c0 100644 +--- a/drivers/media/dvb-frontends/mt312.h ++++ b/drivers/media/dvb-frontends/mt312.h +@@ -34,6 +34,9 @@ struct mt312_config { + + /* inverted voltage setting */ + unsigned int voltage_inverted:1; ++ ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + }; + + #if IS_REACHABLE(CONFIG_DVB_MT312) +diff --git a/drivers/media/dvb-frontends/mtv23x.c b/drivers/media/dvb-frontends/mtv23x.c +new file mode 100644 +index 0000000..06a2555 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mtv23x.c +@@ -0,0 +1,2294 @@ ++#include "mtv23x_priv.h" ++ ++static unsigned int GetSNR_LP_Mode(u8 mod, int val) ++{ ++ unsigned int cn_a = 0; ++ unsigned int cn_b = 0; ++ ++ if (mod == 1) { ++ /* QPSK */ ++ if (val > 270000) { ++ cn_a = 0; ++ cn_b = 0; ++ return 0; ++ } else if (val > 258000) { /* 0~ */ ++ cn_a = 0; ++ cn_b = (270000 - val)/1300; ++ } else if (val > 246000) { /* 1~ */ ++ cn_a = 1; ++ cn_b = (258000 - val)/1300; ++ } else if (val > 226000) { /* 2~ */ ++ cn_a = 2; ++ cn_b = (246000 - val)/2100; ++ } else if (val > 206500) { /* 3~ */ ++ cn_a = 3; ++ cn_b = (226000 - val)/2100; ++ } else if (val > 186500) { /* 4~ */ ++ cn_a = 4; ++ cn_b = (206500 - val)/2200; ++ } else if (val > 163500) { /* 5~ */ ++ cn_a = 5; ++ cn_b = (186500 - val)/2400; ++ } else if (val > 142000) { /* 6~ */ ++ cn_a = 6; ++ cn_b = (163500 - val)/2300; ++ } else if (val > 121000) { /* 7~ */ ++ cn_a = 7; ++ cn_b = (142000 - val)/2300; ++ } else if (val > 100500) { /* 8~ */ ++ cn_a = 8; ++ cn_b = (121000 - val)/2200; ++ } else if (val > 83500) { ++ cn_a = 9; ++ cn_b = (100500 - val)/1800; ++ } else if (val > 69000) { ++ cn_a = 10; ++ cn_b = (83500 - val)/1550; ++ } else if (val > 57200) { ++ cn_a = 11; ++ cn_b = (69000 - val)/1250; ++ } else if (val > 47900) { ++ cn_a = 12; ++ cn_b = (57200 - val)/1000; ++ } else if (val > 40100) { ++ cn_a = 13; ++ cn_b = (47900 - val)/830; ++ } else if (val > 33700) { ++ cn_a = 14; ++ cn_b = (40100 - val)/680; ++ } else if (val > 29000) { ++ cn_a = 15; ++ cn_b = (33700 - val)/500; ++ } else if (val > 25600) { ++ cn_a = 16; ++ cn_b = (29000 - val)/360; ++ } else if (val > 22200) { ++ cn_a = 17; ++ cn_b = (25600 - val)/360; ++ } else if (val > 19700) { ++ cn_a = 18; ++ cn_b = (22200 - val)/265; ++ } else if (val > 18000) { ++ cn_a = 19; ++ cn_b = (19700 - val)/180; ++ } else if (val > 16500) { ++ cn_a = 20; ++ cn_b = (18000 - val)/160; ++ } else if (val > 15200) { ++ cn_a = 21; ++ cn_b = (16500 - val)/140; ++ } else if (val > 14100) { ++ cn_a = 22; ++ cn_b = (15200 - val)/120; ++ } else if (val > 13550) { ++ cn_a = 23; ++ cn_b = (14100 - val)/60; ++ } else if (val > 12800) { ++ cn_a = 24; ++ cn_b = (13550 - val)/80; ++ } else if (val > 12300) { ++ cn_a = 25; ++ cn_b = (12800 - val)/53; ++ } else if (val > 11900) { ++ cn_a = 26; ++ cn_b = (12300 - val)/42; ++ } else if (val > 11600) { ++ cn_a = 27; ++ cn_b = (11900 - val)/31; ++ } else if (val > 11300) { ++ cn_a = 28; ++ cn_b = (11600 - val)/31; ++ } else if (val > 11000) { ++ cn_a = 29; ++ cn_b = (11300 - val)/31; ++ } else if (val > 0) { ++ cn_a = 30; ++ cn_b = 0; ++ } ++ } else if (mod == 2) { ++ /* 16 QAM */ ++ if (val > 353500) { ++ cn_a = 0; ++ cn_b = 0; ++ } else if (val > 353500) { /* 0~ */ ++ cn_a = 0; ++ cn_b = (365000 - val)/124; ++ } else if (val > 344200) { /* 1~ */ ++ cn_a = 1; ++ cn_b = (353500 - val)/101; ++ } else if (val > 333200) { /* 2~ */ ++ cn_a = 2; ++ cn_b = (344200 - val)/120; ++ } else if (val > 325000) { /* 3~ */ ++ cn_a = 3; ++ cn_b = (333200 - val)/90; ++ } else if (val > 316700) { /* 4~ */ ++ cn_a = 4; ++ cn_b = (325000 - val)/91; ++ } else if (val > 308200) { /* 5~ */ ++ cn_a = 5; ++ cn_b = (316700 - val)/93; ++ } else if (val > 299000) { /* 6~ */ ++ cn_a = 6; ++ cn_b = (308200 - val)/98; ++ } else if (val > 295000) { /* 7~ */ ++ cn_a = 7; ++ cn_b = (299000 - val)/1050; ++ } else if (val > 280500) { /* 8~ */ ++ cn_a = 8; ++ cn_b = (295000 - val)/1550; ++ } else if (val > 264000) { ++ cn_a = 9; ++ cn_b = (280500 - val)/1750; ++ } else if (val > 245000) { ++ cn_a = 10; ++ cn_b = (264000 - val)/2050; ++ } else if (val > 222000) { ++ cn_a = 11; ++ cn_b = (245000 - val)/2450; ++ } else if (val > 197000) { ++ cn_a = 12; ++ cn_b = (222000 - val)/2650; ++ } else if (val > 172000) { ++ cn_a = 13; ++ cn_b = (197000 - val)/2650; ++ } else if (val > 147000) { ++ cn_a = 14; ++ cn_b = (172000 - val)/2650; ++ } else if (val > 125000) { ++ cn_a = 15; ++ cn_b = (147000 - val)/2350; ++ } else if (val > 105000) { ++ cn_a = 16; ++ cn_b = (125000 - val)/2150; ++ } else if (val > 88000) { ++ cn_a = 17; ++ cn_b = (105000 - val)/1800; ++ } else if (val > 75000) { ++ cn_a = 18; ++ cn_b = (88000 - val)/1400; ++ } else if (val > 64000) { ++ cn_a = 19; ++ cn_b = (75000 - val)/1180; ++ } else if (val > 55000) { ++ cn_a = 20; ++ cn_b = (64000 - val)/980; ++ } else if (val > 48000) { ++ cn_a = 21; ++ cn_b = (55000 - val)/750; ++ } else if (val > 42000) { ++ cn_a = 22; ++ cn_b = (48000 - val)/640; ++ } else if (val > 38000) { ++ cn_a = 23; ++ cn_b = (42000 - val)/420; ++ } else if (val > 34900) { ++ cn_a = 24; ++ cn_b = (38000 - val)/330; ++ } else if (val > 32000) { ++ cn_a = 25; ++ cn_b = (34900 - val)/310; ++ } else if (val > 29500) { ++ cn_a = 26; ++ cn_b = (32000 - val)/265; ++ } else if (val > 27100) { ++ cn_a = 27; ++ cn_b = (29500 - val)/250; ++ } else if (val > 26000) { ++ cn_a = 28; ++ cn_b = (27100 - val)/118; ++ } else if (val > 25200) { ++ cn_a = 29; ++ cn_b = (26000 - val)/85; ++ } else if (val > 0) { ++ cn_a = 30; ++ cn_b = 0; ++ } ++ } else { ++ cn_a = 0; ++ cn_b = 0; ++ return 0; ++ } ++ ++ if (cn_b > 1000) ++ return (cn_a*1000) + cn_b; ++ else if (cn_b > 100) ++ return (cn_a*1000) + (cn_b*10); ++ else ++ return (cn_a*1000) + (cn_b*100); ++} ++static unsigned int GetSNR_FULL_Mode(u8 mod, int val) ++{ ++ unsigned int cn_a = 0; ++ unsigned int cn_b = 0; ++ ++ if (mod == 1) { ++ /* QPSK */ ++ if (val > 32500) { ++ cn_a = 0; ++ cn_b = 0; ++ return 0; ++ } else if (val > 31400) { /* 0~ */ ++ cn_a = 0; ++ cn_b = (32500 - val)/118; ++ } else if (val > 29800) { /* 1~ */ ++ cn_a = 1; ++ cn_b = (31400 - val)/170; ++ } else if (val > 27900) { /* 2~ */ ++ cn_a = 2; ++ cn_b = (29800 - val)/205; ++ } else if (val > 25500) { /* 3~ */ ++ cn_a = 3; ++ cn_b = (27900 - val)/258; ++ } else if (val > 23000) { /* 4~ */ ++ cn_a = 4; ++ cn_b = (25500 - val)/268; ++ } else if (val > 20300) { /* 5~ */ ++ cn_a = 5; ++ cn_b = (23000 - val)/290; ++ } else if (val > 17500) { /* 6~ */ ++ cn_a = 6; ++ cn_b = (20300 - val)/300; ++ } else if (val > 14600) { /* 7~ */ ++ cn_a = 7; ++ cn_b = (17500 - val)/310; ++ } else if (val > 12000) { /* 8~ */ ++ cn_a = 8; ++ cn_b = (14600 - val)/280; ++ } else if (val > 9750) { ++ cn_a = 9; ++ cn_b = (12000 - val)/240; ++ } else if (val > 7600) { ++ cn_a = 10; ++ cn_b = (9750 - val)/230; ++ } else if (val > 6100) { ++ cn_a = 11; ++ cn_b = (7600 - val)/160; ++ } else if (val > 5000) { ++ cn_a = 12; ++ cn_b = (6100 - val)/118; ++ } else if (val > 3950) { ++ cn_a = 13; ++ cn_b = (5000 - val)/112; ++ } else if (val > 3200) { ++ cn_a = 14; ++ cn_b = (3950 - val)/80; ++ } else if (val > 2580) { ++ cn_a = 15; ++ cn_b = (3200 - val)/65; ++ } else if (val > 2100) { ++ cn_a = 16; ++ cn_b = (2580 - val)/51; ++ } else if (val > 1720) { ++ cn_a = 17; ++ cn_b = (2100 - val)/40; ++ } else if (val > 1390) { ++ cn_a = 18; ++ cn_b = (1720 - val)/35; ++ } else if (val > 1160) { ++ cn_a = 19; ++ cn_b = (1390 - val)/24; ++ } else if (val > 980) { ++ cn_a = 20; ++ cn_b = (1160 - val)/19; ++ } else if (val > 820) { ++ cn_a = 21; ++ cn_b = (980 - val)/17; ++ } else if (val > 700) { ++ cn_a = 22; ++ cn_b = (820 - val)/13; ++ } else if (val > 600) { ++ cn_a = 23; ++ cn_b = (700 - val)/11; ++ } else if (val > 520) { ++ cn_a = 24; ++ cn_b = (600 - val)/8; ++ } else if (val > 450) { ++ cn_a = 25; ++ cn_b = (520 - val)/7; ++ } else if (val > 410) { ++ cn_a = 26; ++ cn_b = (450 - val)/4; ++ } else if (val > 380) { ++ cn_a = 27; ++ cn_b = (410 - val)/3; ++ } else if (val > 350) { ++ cn_a = 28; ++ cn_b = (380 - val)/3; ++ } else if (val > 330) { ++ cn_a = 29; ++ cn_b = (350 - val)/2; ++ } else if (val > 0) { ++ cn_a = 30; ++ cn_b = 0; ++ } ++ } else if (mod == 2) { ++ /* 16 QAM */ ++ if (val > 42000) { ++ cn_a = 0; ++ cn_b = 0; ++ } else if (val > 40500) { /* 0~ */ ++ cn_a = 0; ++ cn_b = (42000 - val)/160; ++ } else if (val > 39000) { /* 1~ */ ++ cn_a = 1; ++ cn_b = (40500 - val)/160; ++ } else if (val > 38000) { /* 2~ */ ++ cn_a = 2; ++ cn_b = (39000 - val)/108; ++ } else if (val > 37000) { ++ cn_a = 3; ++ cn_b = (38000 - val)/108; ++ } else if (val > 36000) { ++ cn_a = 4; ++ cn_b = (37000 - val)/108; ++ } else if (val > 35000) { ++ cn_a = 5; ++ cn_b = (36000 - val)/108; ++ } else if (val > 34000) { ++ cn_a = 6; ++ cn_b = (35000 - val)/108; ++ } else if (val > 32900) { ++ cn_a = 7; ++ cn_b = (34000 - val)/118; ++ } else if (val > 31800) { ++ cn_a = 8; ++ cn_b = (32900 - val)/118; ++ } else if (val > 29500) { ++ cn_a = 9; ++ cn_b = (31800 - val)/248; ++ } else if (val > 27000) { ++ cn_a = 10; ++ cn_b = (29500 - val)/270; ++ } else if (val > 24300) { ++ cn_a = 11; ++ cn_b = (27000 - val)/290; ++ } else if (val > 21400) { ++ cn_a = 12; ++ cn_b = (24300 - val)/315; ++ } else if (val > 18500) { ++ cn_a = 13; ++ cn_b = (21400 - val)/315; ++ } else if (val > 15600) { ++ cn_a = 14; ++ cn_b = (18500 - val)/315; ++ } else if (val > 13000) { ++ cn_a = 15; ++ cn_b = (15600 - val)/280; ++ } else if (val > 10600) { ++ cn_a = 16; ++ cn_b = (13000 - val)/260; ++ } else if (val > 8700) { ++ cn_a = 17; ++ cn_b = (10600 - val)/206; ++ } else if (val > 7200) { ++ cn_a = 18; ++ cn_b = (8700 - val)/160; ++ } else if (val > 6100) { ++ cn_a = 19; ++ cn_b = (7200 - val)/118; ++ } else if (val > 5050) { ++ cn_a = 20; ++ cn_b = (6100 - val)/112; ++ } else if (val > 4100) { ++ cn_a = 21; ++ cn_b = (5050 - val)/102; ++ } else if (val > 3600) { ++ cn_a = 22; ++ cn_b = (4100 - val)/53; ++ } else if (val > 3100) { ++ cn_a = 23; ++ cn_b = (3600 - val)/53; ++ } else if (val > 2650) { ++ cn_a = 24; ++ cn_b = (3100 - val)/48; ++ } else if (val > 2400) { ++ cn_a = 25; ++ cn_b = (2650 - val)/27; ++ } else if (val > 2200) { ++ cn_a = 26; ++ cn_b = (2400 - val)/22; ++ } else if (val > 2000) { ++ cn_a = 27; ++ cn_b = (2200 - val)/22; ++ } else if (val > 1820) { ++ cn_a = 28; ++ cn_b = (2000 - val)/19; ++ } else if (val > 1750) { ++ cn_a = 29; ++ cn_b = (1820 - val)/7; ++ } else if (val > 0) { ++ cn_a = 30; ++ cn_b = 0; ++ } ++ } else if (mod == 3) { ++ /* 64 QAM */ ++ if (val > 43000) { ++ cn_a = 0; ++ cn_b = 0; ++ } else if (val > 40700) { /* 0~ */ ++ cn_a = 0; ++ cn_b = (43000 - val)/250; ++ } else if (val > 40000) { /* 1~ */ ++ cn_a = 1; ++ cn_b = (40700 - val)/75; ++ } else if (val > 38600) { ++ cn_a = 2; ++ cn_b = (40000 - val)/150; ++ } else if (val > 37500) { ++ cn_a = 3; ++ cn_b = (38600 - val)/118; ++ } else if (val > 36800) { ++ cn_a = 4; ++ cn_b = (37500 - val)/74; ++ } else if (val > 36100) { ++ cn_a = 5; ++ cn_b = (36800 - val)/74; ++ } else if (val > 35500) { ++ cn_a = 6; ++ cn_b = (36100 - val)/64; ++ } else if (val > 35000) { ++ cn_a = 7; ++ cn_b = (35500 - val)/53; ++ } else if (val > 34600) { ++ cn_a = 8; ++ cn_b = (35000 - val)/43; ++ } else if (val > 34050) { ++ cn_a = 9; ++ cn_b = (34600 - val)/59; ++ } else if (val > 33500) { ++ cn_a = 10; ++ cn_b = (34050 - val)/59; ++ } else if (val > 32900) { ++ cn_a = 11; ++ cn_b = (33500 - val)/64; ++ } else if (val > 32100) { ++ cn_a = 12; ++ cn_b = (32900 - val)/85; ++ } else if (val > 31200) { ++ cn_a = 13; ++ cn_b = (32100 - val)/96; ++ } else if (val > 30400) { ++ cn_a = 14; ++ cn_b = (31200 - val)/85; ++ } else if (val > 29200) { ++ cn_a = 15; ++ cn_b = (30400 - val)/128; ++ } else if (val > 27800) { ++ cn_a = 16; ++ cn_b = (29200 - val)/150; ++ } else if (val > 25900) { ++ cn_a = 17; ++ cn_b = (27800 - val)/205; ++ } else if (val > 23800) { ++ cn_a = 18; ++ cn_b = (25900 - val)/228; ++ } else if (val > 21500) { ++ cn_a = 19; ++ cn_b = (23800 - val)/248; ++ } else if (val > 19300) { ++ cn_a = 20; ++ cn_b = (21500 - val)/235; ++ } else if (val > 17300) { ++ cn_a = 21; ++ cn_b = (19300 - val)/215; ++ } else if (val > 15300) { ++ cn_a = 22; ++ cn_b = (17300 - val)/215; ++ } else if (val > 13500) { ++ cn_a = 23; ++ cn_b = (15300 - val)/190; ++ } else if (val > 11800) { ++ cn_a = 24; ++ cn_b = (13500 - val)/182; ++ } else if (val > 10500) { ++ cn_a = 25; ++ cn_b = (11800 - val)/140; ++ } else if (val > 9300) { ++ cn_a = 26; ++ cn_b = (10500 - val)/130; ++ } else if (val > 8500) { ++ cn_a = 27; ++ cn_b = (9300 - val)/86; ++ } else if (val > 8000) { ++ cn_a = 28; ++ cn_b = (8500 - val)/53; ++ } else if (val > 7500) { ++ cn_a = 29; ++ cn_b = (8000 - val)/53; ++ } else if (val > 0) { ++ cn_a = 30; ++ cn_b = 0; ++ } ++ } else { ++ cn_a = 0; ++ cn_b = 0; ++ return 0; ++ } ++ ++ if (cn_b > 1000) ++ return (cn_a*1000) + cn_b; ++ else if (cn_b > 100) ++ return (cn_a*1000) + (cn_b*10); ++ else ++ return (cn_a*1000) + (cn_b*100); ++} ++ ++ ++static int mtv_rf_init(struct mtv23x_dev*dev) ++{ ++ int ret,nNumTbalEntry = 0,i=0; ++ struct RTV_REG_INIT_INFO t_mtv23x_INIT[] = { ++ {0x25, 0xF8}, ++ {0x26, 0x00}, ++ {0x28, 0xDD}, ++ {0x29, 0xC4}, ++ {0x2C, 0x1D}, ++ {0x2D, 0x90}, ++ {0x2F, 0x06}, ++ {0x30, 0xDF}, ++ {0x33, 0x11}, ++ {0x36, 0x09}, ++ {0x38, 0xF0}, ++ {0x39, 0x00}, ++ {0x3A, 0xAA}, ++ {0x3E, 0x2D}, ++ {0x47, 0x59}, ++ {0x48, 0x28}, ++ {0x49, 0x41}, ++ {0x4A, 0x70}, ++ {0x4B, 0x65}, ++ {0x4E, 0x4B}, ++ {0x50, 0x6F}, ++ {0x51, 0x3C}, ++ {0x53, 0x65}, ++ {0x54, 0xC0}, ++ {0x5D, 0x01}, ++ {0x5E, 0x70}, ++ {0x5F, 0x75}, ++ {0x60, 0x62}, ++ {0x61, 0x80}, ++ {0x69, 0x0E}, ++ {0x6A, 0x14}, ++ {0x6B, 0x18}, ++ {0x6C, 0xFF}, ++ {0x6D, 0xFD}, ++ {0x6E, 0x19}, ++ {0x70, 0x80}, ++ {0x71, 0x6E}, ++ {0x74, 0x15}, ++ {0x75, 0xA4}, ++ {0x77, 0x69}, ++ {0x78, 0x3D}, ++ {0x7D, 0x28}, ++ {0x81, 0x9C}, ++ {0x83, 0x9F}, ++ {0x85, 0x40}, ++ {0x86, 0x87}, ++ {0x87, 0x84}, ++ {0x88, 0x22}, ++ {0x89, 0x20}, ++ {0x8A, 0xF6}, ++ {0x8B, 0xB5}, ++ {0x8C, 0xFC}, ++ {0x8D, 0xFF}, ++ {0x8E, 0xFE}, ++ {0x8F, 0xFD}, ++ {0x90, 0xFD}, ++ {0x91, 0xFC}, ++ {0x92, 0x0E}, ++ {0x93, 0x0D}, ++ {0x94, 0x09}, ++ {0x95, 0xA3}, ++ {0x96, 0xF0}, ++ {0x97, 0x19}, ++ {0x99, 0x42}, ++ {0x9A, 0x6C}, ++ {0x9B, 0x10}, ++ {0x9C, 0x8E}, ++ {0x9D, 0x3C}, ++ {0x9E, 0x30}, ++ {0x9F, 0x63}, ++ {0xA1, 0x40}, ++ {0xA2, 0x5C}, ++ {0xA3, 0x1C}, ++ {0xA4, 0x85}, ++ {0xA5, 0xB4}, ++ {0xA6, 0x30}, ++ {0xA7, 0x00}, ++ {0xA9, 0x00}, ++ {0xAA, 0x04}, ++ {0xAB, 0x30}, ++ {0xAC, 0x00}, ++ {0xAD, 0x14}, ++ {0xAE, 0x30}, ++ {0xAF, 0x00}, ++ {0xB1, 0x00}, ++ {0xB2, 0x04}, ++ {0xB3, 0x30}, ++ {0xB4, 0x00}, ++ {0xB5, 0xB1}, ++ {0xB7, 0x05}, ++ {0xBC, 0x1F}, ++ {0xBD, 0x1F}, ++ {0xBE, 0x5F}, ++ {0xBF, 0x1F}, ++ {0xC0, 0x1F}, ++ {0xC1, 0x5F}, ++ {0xC2, 0x1F}, ++ {0xC3, 0x1F}, ++ {0xC4, 0x5F}, ++ {0xC6, 0x4A}, ++ {0xC7, 0x4A}, ++ {0xCA, 0xCA}, ++ {0xCB, 0x4A}, ++ {0xCC, 0x4F}, ++ {0xCF, 0x80}, ++ {0xD0, 0x20}, ++ {0xD4, 0x1F}, ++ {0xD7, 0x80}, ++ {0xD8, 0x00}, ++ {0xDA, 0xA4}, ++ {0xDF, 0x01}, ++ {0xE2, 0x24}, ++ {0xE5, 0xA8}, ++ {0xE6, 0xA6}, ++ {0xE7, 0x64} ++ }; ++ nNumTbalEntry = sizeof(t_mtv23x_INIT)/sizeof(struct RTV_REG_INIT_INFO ); ++ ++ do { ++ ret = regmap_write(dev->regmap,t_mtv23x_INIT[i].bReg,t_mtv23x_INIT[i].bVal); ++ i++; ++ } ++ while(--nNumTbalEntry); ++ ++ ++ return ret; ++ ++} ++static int mtv_configTS(struct mtv23x_dev*dev) ++{ ++ u8 REG9F; ++ int temp; ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_read(dev->regmap,0x9F,&temp); ++ REG9F = temp & 0x55; ++ switch(dev->ts_mode){ ++ case 0: /* EN_high, CLK_rising */ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x00)); ++ regmap_write(dev->regmap,0xA6, 0x88); ++ regmap_write(dev->regmap,0xA7, 0x48); ++ break; ++ case 1: /* EN_high, CLK_falling */ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x00)); ++ regmap_write(dev->regmap,0xA6, 0x88); ++ regmap_write(dev->regmap,0xA7, 0x40); ++ break; ++ case 2: /* EN_low, CLK_rising */ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x20)); ++ regmap_write(dev->regmap,0xA6, 0x88); ++ regmap_write(dev->regmap,0xA7, 0x48); ++ break; ++ case 3: /* EN_low, CLK_falling */ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x20)); ++ regmap_write(dev->regmap,0xA6, 0x88); ++ regmap_write(dev->regmap,0xA7, 0x40); ++ break; ++ case 4: /* EN_high, CLK_rising + 1CLK add */ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x00)); ++ regmap_write(dev->regmap,0xA6, 0x88); ++ regmap_write(dev->regmap,0xA7, 0x4C); ++ break; ++ case 5: /* EN_high, CLK_falling + 1CLK add */ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x00)); ++ regmap_write(dev->regmap,0xA6, 0x88); ++ regmap_write(dev->regmap,0xA7, 0x44); ++ break; ++ case 6: /* Parallel: EN_high, CLK_rising*/ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x00)); ++ regmap_write(dev->regmap,0xA6, 0x80); ++ regmap_write(dev->regmap,0xA7, 0x48); ++ break; ++ case 7: /* Parallel: EN_high, CLK_falling */ ++ regmap_write(dev->regmap,0x9F, (REG9F | 0x00)); ++ regmap_write(dev->regmap,0xA6, 0x80); ++ regmap_write(dev->regmap,0xA7, 0x40); ++ break; ++ default: ++ printk("Code not present\n"); ++ break; ++ } ++ regmap_update_bits(dev->regmap,0xA4, 0x01, 0x01); /* TEI Enable */ ++ ++ regmap_write(dev->regmap,0xA8, 0x87); ++ regmap_write(dev->regmap,0xA9, (0xB8|0x01/*TS speed*/)); //set TS speed 1:30M 0:60M ++ ++ regmap_write(dev->regmap,0xAB, 0x87); ++ ++ return 0; ++} ++static int rtv_softReset(struct mtv23x_dev*dev) ++{ ++ if(dev->rtv_1seglpmode) ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ else ++ regmap_write(dev->regmap,MAP_SEL_REG,OFDM_PAGE); ++ ++ regmap_update_bits(dev->regmap,0x10, 0x01, 0x01); ++ regmap_update_bits(dev->regmap,0x10, 0x01, 0x00); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_update_bits(dev->regmap,0xFB, 0x01, 0x01); ++ regmap_update_bits(dev->regmap,0xFB, 0x01, 0x00); ++ ++ return 0; ++ ++} ++static int mtv23x_init(struct dvb_frontend *fe) ++{ ++ struct i2c_client*client = fe->demodulator_priv; ++ struct mtv23x_dev*dev = i2c_get_clientdata(client); ++ int ret,i,temp,read0,read1 ; ++ enum E_RTV_BANDWIDTH_TYPE bandwidth = RTV_BW_MODE_6MHZ; ++ u8 rev_num; ++ u8 ALDO_OUT = 6,DLDO_OUT = 1; ++ ++ ret = regmap_write(dev->regmap,MAP_SEL_REG,TOP_PAGE); ++ ret |= regmap_write(dev->regmap,0x0C,0xC3); ++ for(i = 0; i < 100 ; i++){ ++ regmap_read(dev->regmap,0x00,&read0); ++ regmap_read(dev->regmap,0x01,&read1); ++ ++ if(read0 == 0xC6) ++ goto RTV_POWER_ON_SUCCESS; ++ msleep(5); ++ } ++ dev_err(&client->dev,"MTV23x Power on failed!!\n"); ++ return -1; ++ ++RTV_POWER_ON_SUCCESS: ++ ret = regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ ret |= regmap_read(dev->regmap,0x10,&temp); ++ rev_num = (temp&0xF0)>>4; ++ if(rev_num>=0x05){ ++ regmap_update_bits(dev->regmap,0x3B, 0x01, 0x01); ++ regmap_update_bits(dev->regmap,0x32, 0x01, 0x01); ++ } ++ ret = regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ ret |= regmap_update_bits(dev->regmap,0xC8, 0x80, ((ALDO_OUT & 0x04) << 5)); ++ ret |= regmap_update_bits(dev->regmap,0xD1, 0x80, ((ALDO_OUT & 0x02) << 6)); ++ ret |= regmap_update_bits(dev->regmap,0xD2, 0x80, ((ALDO_OUT & 0x01) << 7)); ++ ret |= regmap_update_bits(dev->regmap,0xD3, 0x80, ((DLDO_OUT & 0x04) << 5)); ++ ret |= regmap_update_bits(dev->regmap,0xD5, 0x80, ((DLDO_OUT & 0x02) << 6)); ++ ret |= regmap_update_bits(dev->regmap,0xD6, 0x80, ((DLDO_OUT & 0x01) << 7)); ++ if(ret) ++ goto err; ++ ++ msleep(10); ++ regmap_update_bits(dev->regmap,0xC9, 0x80, 0x80); ++ ++ /*Internal LDO mode*/ ++ ret = regmap_write(dev->regmap,0xCD, 0x4F); ++ ret = regmap_write(dev->regmap,0xCE, 0x35); ++ if(ret) ++ goto err; ++ ++ /*init mtv_RF*/ ++ ret = mtv_rf_init(dev); ++ if(ret) ++ goto err; ++ /*init demod*/ ++ regmap_write(dev->regmap,MAP_SEL_REG,TOP_PAGE); ++ regmap_write(dev->regmap,0x09, 0x00); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,HOST_PAGE); ++ regmap_write(dev->regmap,0x28, 0x70); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++// regmap_write(dev->regmap,0x71, 0xAA); ++// regmap_write(dev->regmap,0x8E, 0x0A); ++ ++ regmap_write(dev->regmap,0x34, 0x9F); ++ regmap_write(dev->regmap,0x35, 0xFF); ++ regmap_write(dev->regmap,0x36, 0x01); ++ ++ regmap_write(dev->regmap,0x71, 0xAA); ++ regmap_write(dev->regmap,0x8E, 0x15); ++ ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,OFDM_PAGE); ++ ++ regmap_write(dev->regmap,0xB3, 0x31); ++ regmap_write(dev->regmap,0xCA, 0x10); ++ regmap_update_bits(dev->regmap,0x7E, 0x60, 0x60); ++ ++ regmap_write(dev->regmap,0x81, 0xFF); ++ regmap_write(dev->regmap,0x82, 0xFF); ++ ++ regmap_write(dev->regmap,0x6D, 0x4A); ++ regmap_write(dev->regmap,0xB8, 0xA8); ++// regmap_write(dev->regmap,0xC6, 0x78); ++ regmap_write(dev->regmap,0xC6, 0xFF); ++ ++ ++ regmap_write(dev->regmap,0x6F, 0x21); ++ regmap_write(dev->regmap,0xC9, 0x80); ++ regmap_write(dev->regmap,0x5F, 0x10); ++ ++ regmap_write(dev->regmap,0x58, 0x5A); ++ regmap_write(dev->regmap,0x5E, 0x10); ++ regmap_write(dev->regmap,0xCB, 0x02); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,DATA_PAGE); ++ regmap_write(dev->regmap,0x8C, 0x80); ++ regmap_write(dev->regmap,0x8F, 0x40); ++ regmap_write(dev->regmap,0xDB, 0x01); ++ regmap_write(dev->regmap,0xD8, 0x10); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_write(dev->regmap,0x44, 0x68); ++ regmap_write(dev->regmap,0x47, 0x40); ++ ++ regmap_write(dev->regmap,0x16, 0xFF); ++ regmap_write(dev->regmap,0x17, 0xFF); ++ regmap_write(dev->regmap,0x18, 0xFF); ++ regmap_write(dev->regmap,0x19, 0xFF); ++ regmap_write(dev->regmap,0xA7, 0x40); ++ regmap_write(dev->regmap,0xA8, 0x80); ++ regmap_write(dev->regmap,0xA9, 0xB9); ++ regmap_write(dev->regmap,0xAA, 0x80); ++ regmap_write(dev->regmap,0xAB, 0x80); ++ ++ regmap_write(dev->regmap,0x5C, 0x10); ++ regmap_write(dev->regmap,0x5F, 0x10); ++ ++ regmap_write(dev->regmap,0xFC, 0x83); ++ regmap_write(dev->regmap,0xFF, 0x03); ++ ++ mtv_configTS(dev); ++ rtv_softReset(dev); ++ ++ return 0; ++ ++ ++err: ++ dev_err(&client->dev,"Failed = %d\n",ret); ++ return ret; ++ ++} ++ ++static int rtvRF_LockCheck(struct mtv23x_dev*dev,u8 bCheckBlock) ++{ ++ int temp, i = 0,ret = 0; ++ ++ u8 nLockCheck = 0; ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ ++ switch (bCheckBlock) { ++ case 0: /* O == RF Lock Check */ ++ for (i = 0; i < 10; i++) { ++ regmap_read(dev->regmap,0x1B,&temp); ++ nLockCheck = temp & 0x02; ++ if (nLockCheck) ++ break; ++ else ++ printk("[rtvRF_LockCheck]VCheck(%d)\n", i); ++ ++ msleep(1); ++ } ++ ++ if (i == 10) { ++ printk("[rtvRF_LockCheck] VCO Pll unlocked!\n"); ++ ret = -3; ++ } ++ break; ++ ++ case 1: /* CLK Synth Lock Check */ ++ for (i = 0; i < 10; i++) { ++ regmap_read(dev->regmap,0x1B,&temp); ++ nLockCheck = temp & 0x01; ++ if (nLockCheck) ++ break; ++ else ++ printk("[rtvRF_LockCheck]SCheck(%d)\n", i); ++ msleep(1); ++ } ++ ++ if (i == 10) { ++ printk("[rtvRF_LockCheck] ADC clock unlocked!\n"); ++ ret = -2; ++ } ++ break; ++ } ++ ++ return ret; ++} ++ ++static int rtvRF_SetOfdmPara(struct mtv23x_dev*dev,enum E_RTV_SERVICE_TYPE eServiceType, ++ enum E_RTV_BANDWIDTH_TYPE eLpfBwType, u32 dwChFreqKHz) ++{ ++ int nRet = 0; ++ int nNumAdcType = 0; ++ const struct RTV_ADC_CFG_INFO *ptOfdmCfgTbl = NULL; ++ ++ struct RTV_ADC_CFG_INFO g_atAdcCfgTbl_ISDBT_6MHz[] = { ++ /*8*/ {0x00, 0x06, 0x48, 0x2E, 0x29,0x10410410,0x1B6C8B43,0x208208,0x41}, ++ /*9*/ {0x00, 0x04, 0x36, 0x2E, 0x29,0x0E72AE47,0x18607BCA,0x1CE55C,0x39}, ++ /*19.2*/ {0x08, 0x05, 0x48, 0x2E, 0x29,0x6C5C1B17,0x00000000,0x0D8B83,0x1B}, ++ /*20.0*/ {0x08, 0x05, 0x4B, 0x2E, 0x29,0x68068068,0x00000000,0x0D00D0,0x1A}, ++ /*20.48*/{0x08, 0x19, 0x80, 0x6E, 0x29,0x65965965,0x00000000,0x0CB2CB,0x19} ++ }; ++ struct RTV_ADC_CFG_INFO g_atAdcCfgTbl_ISDBT_7MHz[] = { ++ /*8*/ {0x00, 0x06, 0x48, 0x2E, 0x29,0x12F684BD,0x1B6C8B43,0x25ED09,0x4B}, ++ /*9*/ {0x00, 0x04, 0x36, 0x2E, 0x29,0x10DB20A8,0x18607BCA,0x21B641,0x43}, ++ /*19.2*/ {0x08, 0x05, 0x48, 0x2E, 0x29,0x7E6B74F0,0x00000000,0x0FCD6E,0x1F}, ++ /*20.0*/ {0x08, 0x05, 0x4B, 0x2E, 0x29,0x795CEB24,0x00000000,0x0F2B9D,0x1E}, ++ /*20.48*/{0x08, 0x19, 0x80, 0x6E, 0x29,0x7684BDA1,0x00000000,0x0ED097,0x1D} ++ }; ++ struct RTV_ADC_CFG_INFO g_atAdcCfgTbl_ISDBT_8MHz[] = { ++ /*8*/ {0x00, 0x06, 0x48, 0x2E, 0x29,0x15AC056B,0x1B6C8B43,0x2B580A,0x56}, ++ /*9*/ {0x00, 0x04, 0x36, 0x2E, 0x29,0x13439309,0x18607BCA,0x268726,0x4D}, ++ /*19.2*/ {0x08, 0x05, 0x48, 0x2E, 0x29,0x907ACEC9,0x00000000,0x120F59,0x24}, ++ /*20.0*/ {0x08, 0x05, 0x4B, 0x2E, 0x29,0x8AB355E0,0x00000000,0x11566A,0x22}, ++ /*20.48*/{0x08, 0x19, 0x80, 0x6E, 0x29,0x877321DC,0x00000000,0x10EE64,0x21} ++ }; ++ switch (eServiceType) { ++ case RTV_SERVICE_UHF_ISDBT_1seg: ++ nNumAdcType = 1; /* ADC 9MHz */ ++ switch (eLpfBwType) { ++ case RTV_BW_MODE_6MHZ: ++ case RTV_BW_MODE_430KHZ: ++ if ((dwChFreqKHz == 485143) || (dwChFreqKHz == 503143) ++ || (dwChFreqKHz == 539143) || (dwChFreqKHz == 647143) ++ || (dwChFreqKHz == 665143) || (dwChFreqKHz == 683143) ++ || (dwChFreqKHz == 755143)) ++ nNumAdcType = 0; /* ADC 8MHz */ ++ ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_6MHz[nNumAdcType]; ++ break; ++ ++ case RTV_BW_MODE_7MHZ: ++ case RTV_BW_MODE_500KHZ: ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_7MHz[nNumAdcType]; ++ break; ++ ++ case RTV_BW_MODE_8MHZ: ++ case RTV_BW_MODE_571KHZ: ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_8MHz[nNumAdcType]; ++ break; ++ default: ++ printk("[rtvRF_SetOfdmPara] Unsupport 1seg BW\n"); ++ return -9; ++ } ++ break; ++ ++ case RTV_SERVICE_VHF_ISDBTmm_1seg: ++ nNumAdcType = 0; /* ADC 8MHz */ ++ switch (eLpfBwType) { ++ case RTV_BW_MODE_6MHZ: ++ case RTV_BW_MODE_430KHZ: ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_6MHz[nNumAdcType]; ++ break; ++ default: ++ printk("[rtvRF_SetOfdmPara] Unsupport Tmm1seg\n"); ++ return -9; ++ } ++ break; ++ ++ case RTV_SERVICE_VHF_ISDBTsb_1seg: ++ nNumAdcType = 1; /* ADC 9MHz */ ++ switch (eLpfBwType) { ++ case RTV_BW_MODE_6MHZ: ++ case RTV_BW_MODE_430KHZ: ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_6MHz[nNumAdcType]; ++ break; ++ default: ++ printk("[rtvRF_SetOfdmPara] Unsupport Tsb1seg\n"); ++ return -9; ++ } ++ break; ++ ++ case RTV_SERVICE_VHF_ISDBTsb_3seg: ++ printk("[rtvRF_SetOfdmPara] Unsupport Tsb3seg\n"); ++ return -9; ++ ++ case RTV_SERVICE_VHF_ISDBTmm_13seg: ++ nNumAdcType = 4; /* ADC 20.48MHz */ ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_6MHz[nNumAdcType]; ++ break; ++ ++ case RTV_SERVICE_UHF_ISDBT_13seg: ++ if ((dwChFreqKHz == 551143) || (dwChFreqKHz == 581143) || ++ (dwChFreqKHz == 611143) || (dwChFreqKHz == 617143) || ++ (dwChFreqKHz == 647143) || (dwChFreqKHz == 677143) || ++ (dwChFreqKHz == 707143) || (dwChFreqKHz == 737143) || ++ (dwChFreqKHz == 767143) || (dwChFreqKHz == 797143)) ++ nNumAdcType = 2; /* ADC 19.2MHz */ ++ else if ((dwChFreqKHz == 491143) || (dwChFreqKHz == 521143)) ++ nNumAdcType = 3; /* ADC 20.0MHz */ ++ else ++ nNumAdcType = 4; /* ADC 20.48MHz */ ++ ++ switch (eLpfBwType) { ++ case RTV_BW_MODE_6MHZ: ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_6MHz[nNumAdcType]; ++ break; ++ case RTV_BW_MODE_7MHZ: ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_7MHz[nNumAdcType]; ++ break; ++ case RTV_BW_MODE_8MHZ: ++ ptOfdmCfgTbl = &g_atAdcCfgTbl_ISDBT_8MHz[nNumAdcType]; ++ break; ++ default: ++ printk("[rtvRF_SetOfdmPara] Unsupport 13seg\n"); ++ return -9; ++ } ++ break; ++ default: ++ printk("[rtvRF_SetOfdmPara] Invaild Service Type\n"); ++ return -9; ++ } ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ regmap_write(dev->regmap,0x2A, ptOfdmCfgTbl->bData2A); ++ regmap_write(dev->regmap,0x6E, ptOfdmCfgTbl->bData6E); ++ regmap_write(dev->regmap,0x70, ptOfdmCfgTbl->bData70); ++ regmap_write(dev->regmap,0x71, ptOfdmCfgTbl->bData71); ++ regmap_update_bits(dev->regmap,0x75, 0xFC, (ptOfdmCfgTbl->bData75 << 2)); ++ ++ if (rtvRF_LockCheck(dev,1) != 0) ++ return -2; ++ ++ if ((eServiceType == RTV_SERVICE_UHF_ISDBT_1seg) || ++ (eServiceType == RTV_SERVICE_VHF_ISDBTmm_1seg) || ++ (eServiceType == RTV_SERVICE_VHF_ISDBTsb_1seg) || ++ (eServiceType == RTV_SERVICE_VHF_ISDBTsb_3seg)) { ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ regmap_write(dev->regmap,0x14, (u8)((ptOfdmCfgTbl->dwTNCO >> 0) & 0xFF)); ++ regmap_write(dev->regmap,0x15, (u8)((ptOfdmCfgTbl->dwTNCO >> 8) & 0xFF)); ++ regmap_write(dev->regmap,0x16, (u8)((ptOfdmCfgTbl->dwTNCO >> 16) & 0xFF)); ++ regmap_write(dev->regmap,0x17, (u8)((ptOfdmCfgTbl->dwTNCO >> 24) & 0xFF)); ++ ++ regmap_write(dev->regmap,0x18, (u8)((ptOfdmCfgTbl->dwPNCO >> 0) & 0xFF)); ++ regmap_write(dev->regmap,0x19, (u8)((ptOfdmCfgTbl->dwPNCO >> 8) & 0xFF)); ++ regmap_write(dev->regmap,0x1A, (u8)((ptOfdmCfgTbl->dwPNCO >> 16) & 0xFF)); ++ regmap_write(dev->regmap,0x1B, (u8)((ptOfdmCfgTbl->dwPNCO >> 24) & 0xFF)); ++ ++ regmap_write(dev->regmap,0x1C, (u8)((ptOfdmCfgTbl->dwGAIN) & 0xFF)); ++ ++ regmap_write(dev->regmap,0x1D, (u8)((ptOfdmCfgTbl->dwCFREQGAIN>>0) & 0xFF)); ++ regmap_write(dev->regmap,0x1E, (u8)((ptOfdmCfgTbl->dwCFREQGAIN>>8) & 0xFF)); ++ regmap_write(dev->regmap,0x1F, (u8)((ptOfdmCfgTbl->dwCFREQGAIN>>16) & 0xFF)); ++ } else { ++ regmap_write(dev->regmap,MAP_SEL_REG,OFDM_PAGE); ++ switch (eLpfBwType) { ++ case RTV_BW_MODE_5MHZ: ++ regmap_update_bits(dev->regmap,0x11, 0x01, 0x00); ++ regmap_update_bits(dev->regmap,0x10, 0xE0, 0xB0); ++ regmap_update_bits(dev->regmap,0x1F, 0xC0, 0xC0); ++ break; ++ case RTV_BW_MODE_6MHZ: ++ regmap_update_bits(dev->regmap,0x11, 0x01, 0x00); ++ regmap_update_bits(dev->regmap,0x10, 0xE0, 0xC0); ++ regmap_update_bits(dev->regmap,0x1F, 0xC0, 0x80); ++ break; ++ case RTV_BW_MODE_7MHZ: ++ regmap_update_bits(dev->regmap,0x11, 0x01, 0x00); ++ regmap_update_bits(dev->regmap,0x10, 0xE0, 0xE0); ++ regmap_update_bits(dev->regmap,0x1F, 0xC0, 0x40); ++ break; ++ case RTV_BW_MODE_8MHZ: ++ regmap_update_bits(dev->regmap,0x11, 0x01, 0x01); ++ regmap_update_bits(dev->regmap,0x10, 0xE0, 0x00); ++ regmap_update_bits(dev->regmap,0x1F, 0xC0, 0x00); ++ break; ++ default: ++ printk("[rtvRF_SetFrequency] Unsupported BW\n"); ++ return -9; ++ break; ++ } ++ ++ regmap_write(dev->regmap,0x34, (u8)((ptOfdmCfgTbl->dwTNCO>>0) & 0xFF)); ++ regmap_write(dev->regmap,0x35, (u8)((ptOfdmCfgTbl->dwTNCO>>8) & 0xFF)); ++ regmap_write(dev->regmap,0x36, (u8)((ptOfdmCfgTbl->dwTNCO>>16) & 0xFF)); ++ regmap_write(dev->regmap,0x37, (u8)((ptOfdmCfgTbl->dwTNCO>>24) & 0xFF)); ++ ++ regmap_write(dev->regmap,0x38, (u8) (ptOfdmCfgTbl->dwPNCO>>0)); ++ regmap_write(dev->regmap,0x39, (u8) (ptOfdmCfgTbl->dwPNCO>>8)); ++ regmap_write(dev->regmap,0x3A, (u8) (ptOfdmCfgTbl->dwPNCO>>16)); ++ regmap_write(dev->regmap,0x3B, (u8) (ptOfdmCfgTbl->dwPNCO>>24)); ++ ++ regmap_write(dev->regmap,0x3D, (u8)((ptOfdmCfgTbl->dwCFREQGAIN>>0) & 0xFF)); ++ regmap_write(dev->regmap,0x3E, (u8)((ptOfdmCfgTbl->dwCFREQGAIN>>8) & 0xFF)); ++ regmap_write(dev->regmap,0x3F, (u8)((ptOfdmCfgTbl->dwCFREQGAIN>>16) & 0xFF)); ++ ++ regmap_update_bits(dev->regmap,0x55, 0xC0, (ptOfdmCfgTbl->dwGAIN & 0x03)); ++ regmap_write(dev->regmap,0x56, (ptOfdmCfgTbl->dwGAIN>>2) & 0xFF); ++ } ++ ++ return nRet; ++} ++ ++static int rtvRF_ConfigureClkCKSYN(struct mtv23x_dev*dev,enum E_RTV_BANDWIDTH_TYPE eBwType) ++{ ++ int temp; ++ u8 WR6D = 0, WR6E = 0, WR70 = 0, WR71 = 0; ++ u8 WR2A = 0, WR72 = 0, WR73 = 0, WR74 = 0, WR75 = 0; ++ ++ const u16 g_atBW_TABLE_CKSYN[MAX_NUM_RTV_BW_MODE_TYPE][9] = ++ { ++ /*RTV_BW_MODE_5MHZ*/ {0x19,0x180,0x01,0x01,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_6MHZ*/ {0x19,0x180,0x01,0x01,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_7MHZ*/ {0x19,0x180,0x01,0x01,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_8MHZ*/ {0x19,0x180,0x01,0x01,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_430KHZ*/ {0x04,0x36, 0x01,0x00,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_500KHZ*/ {0x0A,0x7B, 0x01,0x00,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_571KHZ*/ {0x14,0xAB, 0x00,0x00,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_768KHZ*/ {0x06,0x48, 0x01,0x00,0x2E,0x13,0x0E,0x01,0x29}, ++ /*RTV_BW_MODE_1290KHZ*/ {0x05,0x24, 0x00,0x00,0x2E,0x13,0x0E,0x01,0x29} ++ }; ++ ++ ++ regmap_read(dev->regmap,0x6D,&temp); ++ WR6D = temp & 0xFC; ++ regmap_read(dev->regmap,0x6E,&temp); ++ WR6E = temp & 0x00; ++ regmap_read(dev->regmap,0x70,&temp); ++ WR70 = temp & 0x00; ++ regmap_read(dev->regmap,0x2A,&temp); ++ WR2A = temp & 0xF7; ++ regmap_read(dev->regmap,0x71,&temp); ++ WR71 = temp & 0x00; ++ regmap_read(dev->regmap,0x72,&temp); ++ WR72 = temp & 0x03; ++ regmap_read(dev->regmap,0x73,&temp); ++ WR73 = temp & 0x03; ++ regmap_read(dev->regmap,0x74,&temp); ++ WR74 = temp & 0x0F; ++ regmap_read(dev->regmap,0x75,&temp); ++ WR75 = temp & 0x03; ++ ++ regmap_write(dev->regmap,0x6D, WR6D | (u8)g_atBW_TABLE_CKSYN[eBwType][2]); ++ regmap_write(dev->regmap,0x6E, WR6E | (u8)g_atBW_TABLE_CKSYN[eBwType][0]); ++ regmap_write(dev->regmap,0x70, WR70 | (u8)(g_atBW_TABLE_CKSYN[eBwType][1] & 0xFF)); ++ regmap_write(dev->regmap,0x2A, WR2A | (u8)(g_atBW_TABLE_CKSYN[eBwType][3] << 3)); ++ regmap_write(dev->regmap,0x71, WR71 | (u8)(((g_atBW_TABLE_CKSYN[eBwType][1] & 0x300) >> 2) ++ | g_atBW_TABLE_CKSYN[eBwType][4])); ++ regmap_write(dev->regmap,0x72, WR72 | (u8)(g_atBW_TABLE_CKSYN[eBwType][6] << 2)); ++ regmap_write(dev->regmap,0x73, WR73 | (u8)(g_atBW_TABLE_CKSYN[eBwType][5] << 2)); ++ regmap_write(dev->regmap,0x74, WR74 | (u8)(g_atBW_TABLE_CKSYN[eBwType][7] << 4)); ++ regmap_write(dev->regmap,0x75, WR75 | (u8)(g_atBW_TABLE_CKSYN[eBwType][8] << 2)); ++ ++ if (rtvRF_LockCheck(dev,1) != 0) ++ return 1; ++ ++ return 0; ++} ++ ++static rtvRF_ConfigureIIRFilter(struct mtv23x_dev*dev,enum E_RTV_BANDWIDTH_TYPE eBwType) ++{ ++ int temp; ++ u8 WR95 = 0; ++ int g_atBW_TABLE_IIR[MAX_NUM_RTV_BW_MODE_TYPE][14] = ++ { ++ /*RTV_BW_MODE_5MHZ*/ {0x02,0xBB83E,0x436A1,0xC12C0,0xC3472,0x43762,0xC1CD3,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x398FD}, ++ /*RTV_BW_MODE_6MHZ*/ {0x02,0x3F019,0x43426,0xC108E,0xC3063,0x43405,0xC1C85,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x3B1B1}, ++ /*RTV_BW_MODE_7MHZ*/ {0x02,0x416DF,0x43084,0xBFBDC,0xC1331,0x41CF0,0xC1C18,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x3B78B}, //19.2MHz ++ /*RTV_BW_MODE_8MHZ*/ {0x02,0x41F50,0x41B43,0xBF8A5,0xBF1E8,0x413E4,0xC1BEC,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x3BDB2}, //19.2MHz IIR ++ /*RTV_BW_MODE_430KHZ*/ {0x02,0x43721,0x43400,0xBFDE1,0x3D238,0x4329D,0xC1965,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x371E2}, ++ /*RTV_BW_MODE_500KHZ*/ {0x03,0x435CF,0x43466,0xC1185,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x3B27E}, ++ /*RTV_BW_MODE_571KHZ*/ {0x02,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000}, ++ /*RTV_BW_MODE_768KHZ*/ {0x02,0xC17A9,0x437A7,0xC1414,0xC38C3,0x439AA,0xC1DD4,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x3B394}, ++ /*RTV_BW_MODE_1290KHZ*/ {0x02,0xC37D0,0x43989,0xC1523,0xBF6D4,0x43B26,0xC1DFB,0x43000,0x43000,0x43000,0x43000,0x43000,0x43000,0x3732E} ++ }; ++ ++ regmap_read(dev->regmap,0x95,&temp); ++ WR95 = temp & 0xC0; ++ ++ regmap_write(dev->regmap,0x95, (WR95 | (u8)((g_atBW_TABLE_IIR[eBwType][0]<<4) | ((g_atBW_TABLE_IIR[eBwType][1]&0xF0000)>>16)))); ++ regmap_write(dev->regmap,0x96, ((g_atBW_TABLE_IIR[eBwType][1] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0x97, ((g_atBW_TABLE_IIR[eBwType][1] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0x98, ((g_atBW_TABLE_IIR[eBwType][2] & 0xFF000)>>12)); ++ regmap_write(dev->regmap,0x99, ((g_atBW_TABLE_IIR[eBwType][2] & 0x00FF0)>>4)); ++ regmap_write(dev->regmap,0x9A, (u8)((((g_atBW_TABLE_IIR[eBwType][2] & 0x0000F)>>0) << 4) | ++ ((g_atBW_TABLE_IIR[eBwType][3] & 0xF0000)>>16))); ++ regmap_write(dev->regmap,0x9B, (u8)((g_atBW_TABLE_IIR[eBwType][3] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0x9C, (u8)((g_atBW_TABLE_IIR[eBwType][3] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0x9D, (u8)((((g_atBW_TABLE_IIR[eBwType][13] & 0xF0000)>>16) << 4) | ++ (u8)((g_atBW_TABLE_IIR[eBwType][4] & 0xF0000)>>16))); ++ regmap_write(dev->regmap,0x9E, (u8)((g_atBW_TABLE_IIR[eBwType][4] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0x9F, (u8)((g_atBW_TABLE_IIR[eBwType][4] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0xA0, (u8)((g_atBW_TABLE_IIR[eBwType][5] & 0xFF000)>>12)); ++ regmap_write(dev->regmap,0xA1, (u8)((g_atBW_TABLE_IIR[eBwType][5] & 0x00FF0)>>4)); ++ regmap_write(dev->regmap,0xA2, (u8)((((g_atBW_TABLE_IIR[eBwType][5] & 0x0000F)>>0) << 4) | ++ ((g_atBW_TABLE_IIR[eBwType][6] & 0xF0000)>>16))); ++ regmap_write(dev->regmap,0xA3, (u8)((g_atBW_TABLE_IIR[eBwType][6] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0xA4, (u8)((g_atBW_TABLE_IIR[eBwType][6] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0xA5, (u8)((((g_atBW_TABLE_IIR[eBwType][13] & 0x0F000)>>12) << 4) | ++ (u8)((g_atBW_TABLE_IIR[eBwType][7] & 0xF0000)>>16))); ++ regmap_write(dev->regmap,0xA6, (u8)((g_atBW_TABLE_IIR[eBwType][7] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0xA7, (u8)((g_atBW_TABLE_IIR[eBwType][7] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0xA8, (u8)((g_atBW_TABLE_IIR[eBwType][8] & 0xFF000)>>12)); ++ regmap_write(dev->regmap,0xA9, (u8)((g_atBW_TABLE_IIR[eBwType][8] & 0x00FF0)>>4)); ++ regmap_write(dev->regmap,0xAA, (u8)((((g_atBW_TABLE_IIR[eBwType][8] & 0x0000F)>>0) << 4) | ++ ((g_atBW_TABLE_IIR[eBwType][9] & 0xF0000)>>16))); ++ regmap_write(dev->regmap,0xAB, (u8)((g_atBW_TABLE_IIR[eBwType][9] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0xAC, (u8)((g_atBW_TABLE_IIR[eBwType][9] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0xAD, (u8)((((g_atBW_TABLE_IIR[eBwType][13] & 0x00F00)>>8) << 4) | ++ (u8)((g_atBW_TABLE_IIR[eBwType][10] & 0xF0000)>>16))); ++ regmap_write(dev->regmap,0xAE, (u8)((g_atBW_TABLE_IIR[eBwType][10] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0xAF, (u8)((g_atBW_TABLE_IIR[eBwType][10] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0xB0, (u8)((g_atBW_TABLE_IIR[eBwType][11] & 0xFF000)>>12)); ++ regmap_write(dev->regmap,0xB1, (u8)((g_atBW_TABLE_IIR[eBwType][11] & 0x00FF0)>>4)); ++ regmap_write(dev->regmap,0xB2, (u8)((((g_atBW_TABLE_IIR[eBwType][11] & 0x0000F)>>0) << 4) | ++ ((g_atBW_TABLE_IIR[eBwType][12] & 0xF0000)>>16))); ++ regmap_write(dev->regmap,0xB3, (u8)((g_atBW_TABLE_IIR[eBwType][12] & 0x0FF00)>>8)); ++ regmap_write(dev->regmap,0xB4, (u8)((g_atBW_TABLE_IIR[eBwType][12] & 0x000FF)>>0)); ++ regmap_write(dev->regmap,0xB5, (u8)((g_atBW_TABLE_IIR[eBwType][13] & 0x000FF)>>0)); ++ ++ return 0; ++ ++ ++} ++static int rtvRF_ConfigureBBA(struct mtv23x_dev*dev,enum E_RTV_BANDWIDTH_TYPE eBwType) ++{ ++ int temp; ++ u8 WR3E = 0, WR3F = 0, WR50 = 0, WR51 = 0, WR4F = 0, WR4E = 0, WR77 = 0; ++ int g_atBW_TABLE_BBA[MAX_NUM_RTV_BW_MODE_TYPE][7] = ++ { ++ /*RTV_BW_MODE_5MHZ*/ {0x2D,0x20,0x03,0x03,0x02,0x02,0x01}, ++ /*RTV_BW_MODE_6MHZ*/ {0x2D,0x20,0x03,0x03,0x02,0x02,0x01}, ++ /*RTV_BW_MODE_7MHZ*/ {0x28,0x19,0x03,0x03,0x02,0x02,0x02}, ++ /*RTV_BW_MODE_8MHZ*/ {0x22,0x13,0x03,0x03,0x02,0x02,0x03}, ++ /*RTV_BW_MODE_430KHZ*/ {0x9C,0x15,0x00,0x03,0x00,0x00,0x00}, ++ /*RTV_BW_MODE_500KHZ*/ {0xBF,0x20,0x03,0x03,0x02,0x02,0x00}, ++ /*RTV_BW_MODE_571KHZ*/ {0xBF,0x20,0x03,0x03,0x02,0x02,0x00}, ++ /*RTV_BW_MODE_768KHZ*/ {0xBF,0x20,0x03,0x03,0x02,0x02,0x00}, ++ /*RTV_BW_MODE_1290KHZ*/ {0xBF,0x20,0x03,0x03,0x02,0x02,0x00} ++ }; ++ regmap_read(dev->regmap,0x3E,&temp); ++ WR3E = temp & 0x00; ++ regmap_read(dev->regmap,0x3F,&temp); ++ WR3F = temp & 0x03; ++ regmap_read(dev->regmap,0x50,&temp); ++ WR50 = temp & 0x1F; ++ regmap_read(dev->regmap,0x51,&temp); ++ WR51 = temp & 0x8F; ++ regmap_read(dev->regmap,0x4F,&temp); ++ WR4F = temp & 0x1F; ++ regmap_read(dev->regmap,0x4E,&temp); ++ WR4E = temp & 0x1F; ++ regmap_read(dev->regmap,0x77,&temp); ++ WR77 = temp & 0xFC; ++ ++ regmap_write(dev->regmap,0x3E, WR3E | g_atBW_TABLE_BBA[eBwType][0]); ++ regmap_write(dev->regmap,0x3F, WR3F | (u8)(g_atBW_TABLE_BBA[eBwType][1] << 2)); ++ regmap_write(dev->regmap,0x50, WR50 | (u8)(g_atBW_TABLE_BBA[eBwType][2] << 5)); ++ regmap_write(dev->regmap,0x51, WR51 | (u8)(g_atBW_TABLE_BBA[eBwType][3] << 4)); ++ regmap_write(dev->regmap,0x4F, WR4F | (u8)(g_atBW_TABLE_BBA[eBwType][4] << 5)); ++ regmap_write(dev->regmap,0x4E, WR4E | (u8)(g_atBW_TABLE_BBA[eBwType][5] << 5)); ++ regmap_write(dev->regmap,0x77, WR77 | (u8)(g_atBW_TABLE_BBA[eBwType][6] << 0)); ++ ++ return 0; ++} ++ ++static int rtvRF_ConfigureADC(struct mtv23x_dev*dev,enum E_RTV_BANDWIDTH_TYPE eBwType) ++{ ++ int temp; ++ u8 WRB7 = 0, WRC8 = 0, WRC9 = 0, WRCA = 0, WRCB = 0, WRCC = 0; ++ u8 WRCD = 0, WRCE = 0; ++ u8 WRD1 = 0, WRD2 = 0, WRD3 = 0, WRD5 = 0, WRD6 = 0, WRD7 = 0; ++ u8 WRD8 = 0, WRD9 = 0, WRDA = 0; ++ u8 g_atBW_TABLE_ADC[MAX_NUM_RTV_BW_MODE_TYPE][47] = ++ { ++ /*RTV_BW_MODE_5MHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x0A,0x20,0x1F,0x12,0x20,0x13,0x20,0x00,0x00,0x00,0x02,0x35,0x49,0x49,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x12,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_6MHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x0A,0x20,0x1F,0x12,0x20,0x13,0x20,0x00,0x00,0x00,0x02,0x35,0x4F,0x4F,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x12,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_7MHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x0A,0x20,0x1F,0x12,0x20,0x13,0x20,0x00,0x00,0x00,0x02,0x35,0x4F,0x4F,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x12,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_8MHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x0A,0x20,0x1F,0x12,0x20,0x13,0x20,0x00,0x00,0x00,0x02,0x35,0x4F,0x4F,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x12,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x10,0x1F,0x1F,0x1F,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_430KHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x08,0x20,0x03,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x09,0x23,0x23,0x21,0x21,0x21,0x21,0x21,0x21,0x12,0x10,0x0E,0x0E,0x0E,0x10,0x0E,0x0E,0x0E,0x10,0x0E,0x0E,0x0E,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_500KHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x08,0x20,0x03,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x06,0x20,0x20,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x12,0x10,0x0D,0x0D,0x0D,0x10,0x0D,0x0D,0x0D,0x10,0x0D,0x0D,0x0D,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_571KHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x0B,0x20,0x05,0x0B,0x20,0x0B,0x20,0x00,0x00,0x00,0x00,0x0F,0x2B,0x2B,0x29,0x29,0x29,0x29,0x29,0x29,0x12,0x10,0x11,0x11,0x11,0x10,0x11,0x11,0x11,0x10,0x11,0x11,0x11,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_768KHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x08,0x20,0x03,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x06,0x20,0x20,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x12,0x10,0x0D,0x0D,0x0D,0x10,0x0D,0x0D,0x0D,0x10,0x0D,0x0D,0x0D,0x30,0x30,0x30,0x18,0x00,0x00}, ++ /*RTV_BW_MODE_1290KHZ*/ {0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x08,0x20,0x04,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x03,0x1F,0x1F,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x12,0x10,0x0C,0x0C,0x0C,0x10,0x0C,0x0C,0x0C,0x10,0x0C,0x0C,0x0C,0x30,0x30,0x30,0x18,0x00,0x00} ++ }; ++ regmap_read(dev->regmap,0xB7,&temp); ++ WRB7 = temp& 0x07; ++ regmap_read(dev->regmap,0xC8,&temp); ++ WRC8 = temp & 0x80; ++ regmap_read(dev->regmap,0xC9,&temp); ++ WRC9 = temp & 0x80; ++ regmap_read(dev->regmap,0xCA,&temp); ++ WRCA = temp & 0x80; ++ regmap_read(dev->regmap,0xCB,&temp); ++ WRCB = temp & 0x80; ++ regmap_read(dev->regmap,0xCC,&temp); ++ WRCC = temp & 0x80; ++ regmap_read(dev->regmap,0xCD,&temp); ++ WRCD = temp & 0x80; ++ regmap_read(dev->regmap,0xCE,&temp); ++ WRCE = temp & 0x80; ++ regmap_read(dev->regmap,0xD1,&temp); ++ WRD1 = temp & 0x80; ++ regmap_read(dev->regmap,0xD2,&temp); ++ WRD2 = temp & 0x80; ++ regmap_read(dev->regmap,0xD3,&temp); ++ WRD3 = temp & 0x80; ++ regmap_read(dev->regmap,0xD5,&temp); ++ WRD5 = temp & 0x80; ++ regmap_read(dev->regmap,0xD6,&temp); ++ WRD6 = temp & 0x80; ++ regmap_read(dev->regmap,0xD7,&temp); ++ WRD7 = temp & 0x80; ++ regmap_read(dev->regmap,0xD8,&temp); ++ WRD8 = temp & 0x80; ++ regmap_read(dev->regmap,0xD9,&temp); ++ WRD9 = temp & 0xC0; ++ regmap_read(dev->regmap,0xDA,&temp); ++ WRDA = temp & 0xC0; ++ ++ regmap_write(dev->regmap,0xB7, (WRB7 | (g_atBW_TABLE_ADC[eBwType][45] << 6) | ++ (g_atBW_TABLE_ADC[eBwType][46] << 5))); ++ regmap_write(dev->regmap,0xB8, (g_atBW_TABLE_ADC[eBwType][44])); ++ regmap_write(dev->regmap,0xB9, (g_atBW_TABLE_ADC[eBwType][43])); ++ regmap_write(dev->regmap,0xBA, (g_atBW_TABLE_ADC[eBwType][42])); ++ regmap_write(dev->regmap,0xBB, (g_atBW_TABLE_ADC[eBwType][41])); ++ regmap_write(dev->regmap,0xBC, ((g_atBW_TABLE_ADC[eBwType][37] & 0x03) << 6) | ++ g_atBW_TABLE_ADC[eBwType][40]); ++ regmap_write(dev->regmap,0xBD, (((g_atBW_TABLE_ADC[eBwType][37] & 0x0C) >> 2) << 6) | ++ g_atBW_TABLE_ADC[eBwType][39]); ++ regmap_write(dev->regmap,0xBE, (((g_atBW_TABLE_ADC[eBwType][37] & 0x30) >> 4) << 6) | ++ g_atBW_TABLE_ADC[eBwType][38]); ++ regmap_write(dev->regmap,0xBF, ((g_atBW_TABLE_ADC[eBwType][33] & 0x03) << 6) | ++ (g_atBW_TABLE_ADC[eBwType][36])); ++ regmap_write(dev->regmap,0xC0, (((g_atBW_TABLE_ADC[eBwType][33] & 0x0C) >> 2) << 6) | ++ (g_atBW_TABLE_ADC[eBwType][35])); ++ regmap_write(dev->regmap,0xC1, (((g_atBW_TABLE_ADC[eBwType][33] & 0x30) >> 4) << 6) | ++ (g_atBW_TABLE_ADC[eBwType][34])); ++ regmap_write(dev->regmap,0xC2, ((g_atBW_TABLE_ADC[eBwType][29] & 0x03) << 6) | ++ (g_atBW_TABLE_ADC[eBwType][32])); ++ regmap_write(dev->regmap,0xC3, (((g_atBW_TABLE_ADC[eBwType][29] & 0x0C) >> 2) << 6) | ++ (g_atBW_TABLE_ADC[eBwType][31])); ++ regmap_write(dev->regmap,0xC4, (((g_atBW_TABLE_ADC[eBwType][29] & 0x30) >> 4) << 6) | ++ (g_atBW_TABLE_ADC[eBwType][30])); ++ regmap_write(dev->regmap,0xC5, (g_atBW_TABLE_ADC[eBwType][28])); ++ regmap_write(dev->regmap,0xC6, (g_atBW_TABLE_ADC[eBwType][27])); ++ regmap_write(dev->regmap,0xC7, (g_atBW_TABLE_ADC[eBwType][26])); ++ regmap_write(dev->regmap,0xC8, (WRC8 | (g_atBW_TABLE_ADC[eBwType][25]))); ++ regmap_write(dev->regmap,0xC9, (WRC9 | (g_atBW_TABLE_ADC[eBwType][24]))); ++ regmap_write(dev->regmap,0xCA, (WRCA | (g_atBW_TABLE_ADC[eBwType][23]))); ++ regmap_write(dev->regmap,0xCB, (WRCB | (g_atBW_TABLE_ADC[eBwType][22]))); ++ regmap_write(dev->regmap,0xCC, (WRCC | (g_atBW_TABLE_ADC[eBwType][21]))); ++ regmap_write(dev->regmap,0xCD, (WRCD | (g_atBW_TABLE_ADC[eBwType][20]))); ++ regmap_write(dev->regmap,0xCE, (WRCE | (g_atBW_TABLE_ADC[eBwType][19]))); ++ regmap_write(dev->regmap,0xCF, (g_atBW_TABLE_ADC[eBwType][18] << 6) | ++ (g_atBW_TABLE_ADC[eBwType][17] << 4) | ++ (g_atBW_TABLE_ADC[eBwType][16] << 2) | ++ (g_atBW_TABLE_ADC[eBwType][15] << 0)); ++ regmap_write(dev->regmap,0xD0, (g_atBW_TABLE_ADC[eBwType][14])); ++ regmap_write(dev->regmap,0xD1, (WRD1 | (g_atBW_TABLE_ADC[eBwType][13]))); ++ regmap_write(dev->regmap,0xD2, (WRD2 | (g_atBW_TABLE_ADC[eBwType][12]))); ++ regmap_write(dev->regmap,0xD3, (WRD3 | (g_atBW_TABLE_ADC[eBwType][11]))); ++ regmap_write(dev->regmap,0xD4, (g_atBW_TABLE_ADC[eBwType][10])); ++ regmap_write(dev->regmap,0xD5, (WRD5 | (g_atBW_TABLE_ADC[eBwType][9]))); ++ regmap_write(dev->regmap,0xD6, (WRD6 | (g_atBW_TABLE_ADC[eBwType][8]))); ++ regmap_write(dev->regmap,0xD7, (WRD7 | (g_atBW_TABLE_ADC[eBwType][7]))); ++ regmap_write(dev->regmap,0xD8, (WRD8 | (g_atBW_TABLE_ADC[eBwType][6]))); ++ regmap_write(dev->regmap,0xD9, (WRD9 | (g_atBW_TABLE_ADC[eBwType][5]))); ++ regmap_write(dev->regmap,0xDA, (WRDA | (g_atBW_TABLE_ADC[eBwType][4]))); ++ regmap_write(dev->regmap,0xDB, ((g_atBW_TABLE_ADC[eBwType][3]) << 4) | ++ (g_atBW_TABLE_ADC[eBwType][2])); ++ regmap_write(dev->regmap,0xDC, ((g_atBW_TABLE_ADC[eBwType][1]) << 4) | ++ (g_atBW_TABLE_ADC[eBwType][0])); ++ ++ return 0; ++} ++ ++static int rtvRF_Lna_Tuning(struct mtv23x_dev*dev,u32 dwLoFreq) ++{ ++ u8 nidx = 0; ++ u8 WR50 = 0, WR73 = 0, WR4E = 0, WR69 = 0, WR88 = 0, WR89 = 0; ++ u8 WR8A = 0, WR8B = 0; ++ u8 WR6C = 0, WR6D = 0, WR6A = 0, WR6B = 0, WR8C = 0, WR8D = 0; ++ u8 WR8E = 0, WR8F = 0; ++ u8 WR90 = 0, WR91 = 0, WR92 = 0, WR87 = 0, WR93 = 0, WR94 = 0; ++ int temp; ++ const u8 g_atLNA_TABLE[20][29] = ++ { ++ /* 80 - 90*/ {0x07,0x02,0x0A,0x03,0x03,0x07,0x00,0x00,0x0F,0x00,0x03,0x03,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00}, ++ /* 90 - 100*/{0x07,0x02,0x0A,0x03,0x02,0x07,0x00,0x00,0x0F,0x00,0x03,0x03,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00}, ++ /*100 - 110*/{0x07,0x02,0x0A,0x03,0x02,0x07,0x00,0x00,0x0F,0x00,0x02,0x03,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00}, ++ /*170 - 180*/{0x0B,0x02,0x10,0x03,0x05,0x00,0x05,0x02,0x07,0x00,0x03,0x04,0x3F,0x08,0x1F,0x2F,0x3F,0x12,0x14,0x02,0x3F,0x0C,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*180 - 190*/{0x0B,0x02,0x10,0x03,0x04,0x00,0x04,0x02,0x06,0x00,0x03,0x04,0x3F,0x08,0x1F,0x14,0x3F,0x12,0x14,0x02,0x3F,0x0C,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*190 - 200*/{0x0B,0x02,0x10,0x03,0x04,0x00,0x03,0x01,0x04,0x00,0x02,0x04,0x3F,0x08,0x1F,0x14,0x1F,0x0F,0x0F,0x02,0x14,0x07,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*200 - 210*/{0x0B,0x02,0x10,0x03,0x03,0x00,0x03,0x01,0x02,0x00,0x02,0x04,0x3F,0x0A,0x1F,0x11,0x1F,0x0F,0x0F,0x02,0x14,0x07,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*210 - 220*/{0x09,0x02,0x10,0x03,0x03,0x00,0x02,0x01,0x00,0x00,0x01,0x04,0x1E,0x0C,0x1F,0x0D,0x19,0x0C,0x03,0x02,0x14,0x07,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*220 - 230*/{0x09,0x02,0x10,0x03,0x03,0x00,0x02,0x01,0x00,0x00,0x01,0x04,0x1E,0x0C,0x1F,0x0D,0x19,0x0C,0x03,0x02,0x14,0x07,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*230 - 240*/{0x09,0x02,0x10,0x03,0x02,0x00,0x01,0x01,0x0F,0x00,0x01,0x04,0x12,0x0C,0x1F,0x0C,0x19,0x0C,0x03,0x02,0x14,0x07,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*240 - 250*/{0x09,0x02,0x10,0x03,0x02,0x00,0x01,0x01,0x0E,0x00,0x01,0x04,0x12,0x0C,0x1F,0x0C,0x19,0x0C,0x03,0x02,0x14,0x07,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*250 - 320*/{0x09,0x02,0x10,0x03,0x02,0x00,0x00,0x01,0x0E,0x00,0x01,0x04,0x12,0x0C,0x1F,0x0C,0x19,0x0C,0x03,0x02,0x14,0x07,0x1F,0x0F,0x03,0x3F,0x0F,0x0F,0x01}, ++ /*470 - 510*/{0x1F/*0x0F*/,0x02,0x0B,0x03,0x01,0x00,0x01,0x00,0x00/*0x0F*/,0x06,0x0B,0x05,0x3F,0x3F,0x00/*0x0A*/,0x00/*0x06*/,0x3F,0x3F,0x07,0x03,0x3F,0x3F,0x05,0x03,0x3F,0x3F,0x05,0x02,0x02}, ++ /*510 - 540*/{0x1F/*0x0F*/,0x02,0x0B,0x03,0x00,0x00,0x00,0x00,0x00/*0x07*/,0x06,0x07,0x05,0x3F,0x2F,0x00/*0x0A*/,0x00/*0x05*/,0x3F,0x3F,0x07,0x03,0x3F,0x3F,0x04,0x03,0x3F,0x3F,0x04,0x02,0x02}, ++ /*540 - 560*/{0x1F/*0x0F*/,0x02,0x0B,0x03,0x00,0x00,0x00,0x00,0x00/*0x05*/,0x06,0x03,0x05,0x3F,0x1F,0x00/*0x0A*/,0x00/*0x04*/,0x3F,0x0F,0x03,0x02,0x3F,0x3F,0x04,0x03,0x0F,0x0F,0x03,0x01,0x02}, ++ /*560 - 600*/{0x1F/*0x0D*/,0x02,0x0B,0x03,0x00,0x00,0x00,0x00,0x00/*0x03*/,0x06,0x03,0x05,0x2F,0x16,0x00/*0x09*/,0x00/*0x02*/,0x3F,0x0F,0x03,0x02,0x1F,0x08,0x02,0x00,0x0F,0x0F,0x02,0x00,0x02}, ++ /*600 - 630*/{0x1F/*0x0D*/,0x02,0x0B,0x03,0x00,0x00,0x00,0x00,0x00/*0x01*/,0x06,0x00,0x05,0x1F,0x0C,0x00/*0x08*/,0x00/*0x00*/,0x3F,0x00,0x00,0x00,0x1F,0x08,0x02,0x00,0x00,0x10,0x01,0x00,0x02}, ++ /*630 - 710*/{0x1F/*0x0D*/,0x02,0x10,0x03,0x00,0x00,0x00,0x00,0x00/*0x00*/,0x06,0x00,0x05,0x15,0x00,0x00/*0x06*/,0x00/*0x00*/,0x3F,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x02}, ++ /*710 - 810*/{0x1F/*0x0F*/,0x02,0x10,0x03,0x00,0x00,0x00,0x00,0x00/*0x00*/,0x06,0x00,0x05,0x15,0x00,0x00/*0x00*/,0x00/*0x00*/,0x3F,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x02}, ++ /*810 - 880*/{0x1F/*0x14*/,0x02,0x16,0x03,0x00,0x00,0x00,0x00,0x00/*0x00*/,0x06,0x00,0x05,0x09,0x00,0x00/*0x00*/,0x00/*0x00*/,0x3F,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x02} ++ }; ++ ++ if (75000 < dwLoFreq && 90000 >= dwLoFreq) ++ nidx = 0; ++ else if (90000 < dwLoFreq && 100000 >= dwLoFreq) ++ nidx = 1; ++ else if (100000 < dwLoFreq && 115000 >= dwLoFreq) ++ nidx = 2; ++ else if (115000 < dwLoFreq && 180000 >= dwLoFreq) ++ nidx = 3; ++ else if (180000 < dwLoFreq && 190000 >= dwLoFreq) ++ nidx = 4; ++ else if (190000 < dwLoFreq && 200000 >= dwLoFreq) ++ nidx = 5; ++ else if (200000 < dwLoFreq && 210000 >= dwLoFreq) ++ nidx = 6; ++ else if (210000 < dwLoFreq && 220000 >= dwLoFreq) ++ nidx = 7; ++ else if (220000 < dwLoFreq && 230000 >= dwLoFreq) ++ nidx = 8; ++ else if (230000 < dwLoFreq && 240000 >= dwLoFreq) ++ nidx = 9; ++ else if (240000 < dwLoFreq && 250000 >= dwLoFreq) ++ nidx = 10; ++ else if (250000 < dwLoFreq && 320000 >= dwLoFreq) ++ nidx = 11; ++ else if (320000 < dwLoFreq && 510000 >= dwLoFreq) ++ nidx = 12; ++ else if (510000 < dwLoFreq && 540000 >= dwLoFreq) ++ nidx = 13; ++ else if (540000 < dwLoFreq && 560000 >= dwLoFreq) ++ nidx = 14; ++ else if (560000 < dwLoFreq && 600000 >= dwLoFreq) ++ nidx = 15; ++ else if (600000 < dwLoFreq && 630000 >= dwLoFreq) ++ nidx = 16; ++ else if (630000 < dwLoFreq && 710000 >= dwLoFreq) ++ nidx = 17; ++ else if (710000 < dwLoFreq && 810000 >= dwLoFreq) ++ nidx = 18; ++ else if (810000 < dwLoFreq && 880000 >= dwLoFreq) ++ nidx = 19; ++ else ++ return -5; ++ ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ regmap_read(dev->regmap,0x50,&temp); ++ WR50 = temp & 0xE0; ++ regmap_read(dev->regmap,0x73,&temp); ++ WR73 = temp & 0xFC; ++ regmap_read(dev->regmap,0x4E,&temp); ++ WR4E = temp & 0xE0; ++ regmap_read(dev->regmap,0x69,&temp); ++ WR69 = temp & 0x80; ++ regmap_read(dev->regmap,0x88,&temp); ++ WR88 = temp & 0x03; ++ regmap_read(dev->regmap,0x89,&temp); ++ WR89 = temp & 0x03; ++ regmap_read(dev->regmap,0x8A,&temp); ++ WR8A = temp & 0x00; ++ regmap_read(dev->regmap,0x8B,&temp); ++ WR8B = temp & 0x00; ++ regmap_read(dev->regmap,0x6C,&temp); ++ WR6C = temp & 0x03; ++ regmap_read(dev->regmap,0x6D,&temp); ++ WR6D = temp & 0x03; ++ regmap_read(dev->regmap,0x6A,&temp); ++ WR6A = temp & 0xC1; ++ regmap_read(dev->regmap,0x6B,&temp); ++ WR6B = temp & 0x03; ++ regmap_read(dev->regmap,0x8C,&temp); ++ WR8C = temp & 0x00; ++ regmap_read(dev->regmap,0x8D,&temp); ++ WR8D = temp & 0x00; ++ regmap_read(dev->regmap,0x8E,&temp); ++ WR8E = temp & 0x00; ++ regmap_read(dev->regmap,0x8F,&temp); ++ WR8F = temp & 0x00; ++ regmap_read(dev->regmap,0x90,&temp); ++ WR90 = temp & 0x00; ++ regmap_read(dev->regmap,0x91,&temp); ++ WR91 = temp & 0x00; ++ regmap_read(dev->regmap,0x92,&temp); ++ WR92 = temp & 0x00; ++ regmap_read(dev->regmap,0x87,&temp); ++ WR87 = temp & 0xFB; ++ regmap_read(dev->regmap,0x93,&temp); ++ WR93 = temp & 0x03; ++ regmap_read(dev->regmap,0x94,&temp); ++ WR94 = temp & 0x03; ++ ++ regmap_write(dev->regmap,0x50, WR50 | g_atLNA_TABLE[nidx][0]); ++ regmap_write(dev->regmap,0x73, WR73 | g_atLNA_TABLE[nidx][1]); ++ regmap_write(dev->regmap,0x4E, WR4E | g_atLNA_TABLE[nidx][2]); ++ regmap_write(dev->regmap,0x69, WR69 | (g_atLNA_TABLE[nidx][3] << 2) ++ | g_atLNA_TABLE[nidx][28]); ++ ++ regmap_write(dev->regmap,0x88, WR88 | (g_atLNA_TABLE[nidx][4] << 5) ++ | (g_atLNA_TABLE[nidx][5] << 2)); ++ ++ regmap_write(dev->regmap,0x89, WR89 | (g_atLNA_TABLE[nidx][6] << 5) ++ | (g_atLNA_TABLE[nidx][7] << 2)); ++ ++ regmap_write(dev->regmap,0x8A, WR8A | (g_atLNA_TABLE[nidx][8] << 4) ++ | g_atLNA_TABLE[nidx][9]); ++ ++ regmap_write(dev->regmap,0x8B, WR8B | (g_atLNA_TABLE[nidx][10] << 4) ++ | g_atLNA_TABLE[nidx][11]); ++ ++ regmap_write(dev->regmap,0x6C, WR6C | (g_atLNA_TABLE[nidx][12] << 2)); ++ regmap_write(dev->regmap,0x6D, WR6D | (g_atLNA_TABLE[nidx][13] << 2)); ++ regmap_write(dev->regmap,0x6A, WR6A | (g_atLNA_TABLE[nidx][14] << 1)); ++ regmap_write(dev->regmap,0x6B, WR6B | (g_atLNA_TABLE[nidx][15] << 2)); ++ regmap_write(dev->regmap,0x8C, WR8C | (g_atLNA_TABLE[nidx][16] << 2) ++ | ((g_atLNA_TABLE[nidx][18] & 0x18) >> 3)); ++ ++ regmap_write(dev->regmap,0x8D, WR8D | (g_atLNA_TABLE[nidx][20] << 2) ++ | ((g_atLNA_TABLE[nidx][18] & 0x06) >> 1)); ++ ++ regmap_write(dev->regmap,0x8E, WR8E | (g_atLNA_TABLE[nidx][24] << 2) ++ | ((g_atLNA_TABLE[nidx][18] & 0x01) << 1) ++ | ((g_atLNA_TABLE[nidx][22] & 0x10) >> 4)); ++ ++ regmap_write(dev->regmap,0x8F, WR8F | (g_atLNA_TABLE[nidx][17] << 2) ++ | ((g_atLNA_TABLE[nidx][22] & 0x0C) >> 2)); ++ ++ regmap_write(dev->regmap,0x90, WR90 | (g_atLNA_TABLE[nidx][21] << 2) ++ | ((g_atLNA_TABLE[nidx][22] & 0x03) >> 0)); ++ ++ regmap_write(dev->regmap,0x91, WR91 | (g_atLNA_TABLE[nidx][25] << 2) ++ | ((g_atLNA_TABLE[nidx][26] & 0x18) >> 3)); ++ ++ regmap_write(dev->regmap,0x92, WR92 | (g_atLNA_TABLE[nidx][19] << 2) ++ | ((g_atLNA_TABLE[nidx][26] & 0x06) >> 1)); ++ ++ regmap_write(dev->regmap,0x87, WR87 | ((g_atLNA_TABLE[nidx][26] & 0x01) << 2)); ++ regmap_write(dev->regmap,0x93, WR93 | (g_atLNA_TABLE[nidx][23] << 2)); ++ regmap_write(dev->regmap,0x94, WR94 | (g_atLNA_TABLE[nidx][27] << 2)); ++ ++ ++ ++ return 0; ++} ++ ++static int rtvRF_SetUpVCO(struct mtv23x_dev*dev,u32 dwLoFreq, u32 *dwPllfreq) ++{ ++ int nRet = 0; ++ int nVcoDivRate = 0; ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ ++ if (dwLoFreq < 107500) { ++ nVcoDivRate = 5; ++ regmap_update_bits(dev->regmap,0x78, 0x0F, 0x0F); ++ } else if (dwLoFreq >= 107500 && dwLoFreq < 215000) { ++ nVcoDivRate = 4; ++ regmap_update_bits(dev->regmap,0x78, 0x0F, 0x0E); ++ } else if (dwLoFreq >= 215000 && dwLoFreq < 430000) { ++ nVcoDivRate = 3; ++ regmap_update_bits(dev->regmap,0x78, 0x0F, 0x0E); ++ } else { ++ nVcoDivRate = 2; ++ regmap_update_bits(dev->regmap,0x78, 0x0F, 0x0D); ++ } ++ ++ *dwPllfreq = dwLoFreq * (1<regmap,0x28, 0x03, ((nVcoDivRate & 0x06)>>1)); ++ regmap_update_bits(dev->regmap,0x29, 0x08, (nVcoDivRate & 0x01)<<3); ++ ++ if (*dwPllfreq >= 1720000 && *dwPllfreq < 1892000) { ++ regmap_update_bits(dev->regmap,0x94, 0x02, 0x00); ++ regmap_update_bits(dev->regmap,0x78, 0x70, 0x40); ++ regmap_update_bits(dev->regmap,0xEA, 0x60, 0x00); ++ } else if (*dwPllfreq >= 1892000 && *dwPllfreq < 3440000) { ++ regmap_update_bits(dev->regmap,0x94, 0x02, 0x00); ++ regmap_update_bits(dev->regmap,0x78, 0x70, 0x30); ++ regmap_update_bits(dev->regmap,0xEA, 0x60, 0x00); ++ } else ++ nRet = -5; ++ ++ return nRet; ++} ++ ++static int rtvRF_SelectService(struct mtv23x_dev*dev,enum E_RTV_SERVICE_TYPE eServiceType) ++{ ++ int nRet = 0; ++ ++ switch (eServiceType) { ++ case RTV_SERVICE_UHF_ISDBT_1seg: ++ case RTV_SERVICE_VHF_ISDBTmm_1seg: ++ case RTV_SERVICE_VHF_ISDBTsb_1seg: ++ regmap_write(dev->regmap,MAP_SEL_REG,HOST_PAGE); ++ regmap_write(dev->regmap,0x0B, 0x36); ++ ++ regmap_write(dev->regmap,0x12, 0x08); ++ regmap_write(dev->regmap,0x21, 0x01); ++ regmap_write(dev->regmap,0x26, 0x00); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_write(dev->regmap,0x20, 0x0C); ++ ++ regmap_write(dev->regmap,0x23, 0xF0); /* Layer A */ ++ regmap_write(dev->regmap,0x24, 0x31); ++ regmap_write(dev->regmap,0x4F, 0x1F); ++ regmap_write(dev->regmap,0x44, 0x68); ++ regmap_write(dev->regmap,0x47, 0x40); ++ ++ regmap_write(dev->regmap,0x53, 0x3E); ++ regmap_write(dev->regmap,0x21, 0x00); ++ regmap_write(dev->regmap,0x22, 0x00); ++ regmap_write(dev->regmap,0x5C, 0x10); ++ regmap_write(dev->regmap,0x5F, 0x10); ++ regmap_write(dev->regmap,0x77, 0x40); ++ regmap_write(dev->regmap,0x7A, 0x20); ++ regmap_write(dev->regmap,0x83, 0x10); ++ regmap_write(dev->regmap,0x96, 0x00); ++ regmap_write(dev->regmap,0xAE, 0x00); ++ ++ regmap_write(dev->regmap,0xFC, 0x83); ++ regmap_write(dev->regmap,0xFF, 0x03); ++ ++#if 0 ++ regmap_write(dev->regmap,0x44, 0x48); ++ regmap_write(dev->regmap,0x47, 0x00); ++#endif ++ dev->rtv_1seglpmode= 1; ++ break; ++ case RTV_SERVICE_VHF_ISDBTsb_3seg: ++ printk("[rtvRF_SelectService] 3seg is not implemented\n"); ++ break; ++ ++ case RTV_SERVICE_UHF_ISDBT_13seg: ++ case RTV_SERVICE_VHF_ISDBTmm_13seg: ++ regmap_write(dev->regmap,MAP_SEL_REG,HOST_PAGE); ++ regmap_write(dev->regmap,0x0B, 0x96); ++ ++ regmap_write(dev->regmap,0x12, 0x00); ++ regmap_write(dev->regmap,0x21, 0x00); ++ regmap_write(dev->regmap,0x26, 0xB8); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,OFDM_PAGE); ++ regmap_write(dev->regmap,0x10, 0xD4); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_write(dev->regmap,0x20, 0x00); ++ regmap_write(dev->regmap,0x21, 0x21); ++ regmap_write(dev->regmap,0x22, 0x21); ++ ++#if 0 ++ regmap_write(dev->regmap,0x23, 0x84); ++ regmap_write(dev->regmap,0x24, 0x31); ++ regmap_write(dev->regmap,0x4F, 0x1F); ++#endif ++ ++ regmap_write(dev->regmap,0x23, 0x90); ++ regmap_write(dev->regmap,0x24, 0x01); ++ regmap_write(dev->regmap,0x4F, 0x00); ++ regmap_write(dev->regmap,0x44, 0x68); ++ regmap_write(dev->regmap,0x47, 0x40); ++ ++ regmap_write(dev->regmap,0x53, 0x1E); ++ regmap_write(dev->regmap,0x5C, 0x11); ++ regmap_write(dev->regmap,0x5F, 0x11); ++ regmap_write(dev->regmap,0x77, 0x00); ++ regmap_write(dev->regmap,0x7A, 0x00); ++ regmap_write(dev->regmap,0x83, 0x00); ++ regmap_write(dev->regmap,0x96, 0x20); ++ regmap_write(dev->regmap,0xAE, 0x02); ++ ++ regmap_write(dev->regmap,0xFC, 0x83); ++ regmap_write(dev->regmap,0xFF, 0x03); ++ ++#if 0 ++ regmap_write(dev->regmap,0x44, 0xE8); ++ regmap_write(dev->regmap,0x47, 0x40); ++#endif ++ dev->rtv_1seglpmode= 0; ++ break; ++ ++ case RTV_SERVICE_DVBT: ++ regmap_write(dev->regmap,MAP_SEL_REG,HOST_PAGE); ++ regmap_write(dev->regmap,0x0B, 0x96); ++ regmap_write(dev->regmap,0x12, 0x00); ++ regmap_write(dev->regmap,0x21, 0x00); ++ regmap_write(dev->regmap,0x26, 0xB8); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,DATA_PAGE); ++ regmap_write(dev->regmap,0xA2, 0x0E); ++ regmap_write(dev->regmap,0xA3, 0x0E); ++ regmap_write(dev->regmap,0xA7, 0x0D); ++ regmap_write(dev->regmap,0xA6, 0x0D); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,OFDM_PAGE); ++ regmap_write(dev->regmap,0x10, 0xD6); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_write(dev->regmap,0x20, 0x00); ++ regmap_write(dev->regmap,0x21, 0x21); ++ regmap_write(dev->regmap,0x22, 0x21); ++ regmap_write(dev->regmap,0x53, 0x1E); ++ ++ regmap_write(dev->regmap,0x23, 0xF0); /* Layer A */ ++#if !defined(RTV_IF_SPI) && !defined(RTV_IF_EBI2) ++ regmap_write(dev->regmap,0x24, 0x11); ++ regmap_write(dev->regmap,0x4F, 0x07); ++#endif ++ regmap_write(dev->regmap,0x44, 0xE8); ++ regmap_write(dev->regmap,0x47, 0x40); ++ ++ regmap_write(dev->regmap,0x5C, 0x10); ++ regmap_write(dev->regmap,0x5F, 0x10); ++ regmap_write(dev->regmap,0x77, 0x00); ++ regmap_write(dev->regmap,0x7A, 0x00); ++ regmap_write(dev->regmap,0x83, 0x00); ++ regmap_write(dev->regmap,0x96, 0x20); ++ regmap_write(dev->regmap,0xAE, 0x02); ++ ++ regmap_write(dev->regmap,0xFC, 0x83); ++ regmap_write(dev->regmap,0xFF, 0x03); ++ ++#if 0 ++ regmap_write(dev->regmap,0x44, 0xE8); ++ regmap_write(dev->regmap,0x47, 0x40); ++#endif ++ dev->rtv_1seglpmode= 0; ++ break; ++ default: ++ nRet = -9; ++ } ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ ++ switch (eServiceType) { ++ case RTV_SERVICE_UHF_ISDBT_1seg: ++ regmap_write(dev->regmap,0x49, 0x21); ++ regmap_write(dev->regmap,0x4A, 0x60); ++ regmap_write(dev->regmap,0x4B, 0x50); ++ regmap_write(dev->regmap,0x5E, 0x70); ++ regmap_write(dev->regmap,0x5F, 0x75); ++ break; ++ case RTV_SERVICE_VHF_ISDBTmm_1seg: ++ regmap_write(dev->regmap,0x49, 0x21); ++ regmap_write(dev->regmap,0x4A, 0x30); ++ regmap_write(dev->regmap,0x4B, 0x20); ++ regmap_write(dev->regmap,0x5E, 0x70); ++ regmap_write(dev->regmap,0x5F, 0x75); ++ break; ++ case RTV_SERVICE_VHF_ISDBTsb_1seg: ++ regmap_write(dev->regmap,0x49, 0x21); ++ regmap_write(dev->regmap,0x4A, 0x60); ++ regmap_write(dev->regmap,0x4B, 0x50); ++ regmap_write(dev->regmap,0x5E, 0x70); ++ regmap_write(dev->regmap,0x5F, 0x75); ++ break; ++ case RTV_SERVICE_VHF_ISDBTsb_3seg: ++ printk("[rtvRF_SelectService] Unsupported 3seg\n"); ++ break; ++ case RTV_SERVICE_UHF_ISDBT_13seg: ++ regmap_write(dev->regmap,0x49, 0x41); ++ regmap_write(dev->regmap,0x4A, 0x70); ++ regmap_write(dev->regmap,0x4B, 0x65); ++ regmap_write(dev->regmap,0x5E, 0x70); ++ regmap_write(dev->regmap,0x5F, 0x75); ++ break; ++ case RTV_SERVICE_VHF_ISDBTmm_13seg: ++ regmap_write(dev->regmap,0x49, 0x41); ++ regmap_write(dev->regmap,0x4A, 0x70); ++ regmap_write(dev->regmap,0x4B, 0x65); ++ regmap_write(dev->regmap,0x5E, 0x70); ++ regmap_write(dev->regmap,0x5F, 0x75); ++ break; ++ case RTV_SERVICE_DVBT: ++ regmap_write(dev->regmap,0x49, 0x41); ++ regmap_write(dev->regmap,0x4A, 0x70); ++ regmap_write(dev->regmap,0x4B, 0x65); ++ regmap_write(dev->regmap,0x5E, 0x70); ++ regmap_write(dev->regmap,0x5F, 0x75); ++ break; ++ ++ default: ++ nRet = -9; ++ } ++ ++ ++ return nRet; ++} ++ ++static int rtvRF_SetFrequency(struct mtv23x_dev*dev,enum E_RTV_SERVICE_TYPE eServiceType, ++ enum E_RTV_BANDWIDTH_TYPE eBwType,u32 dwChFreqKHz) ++{ ++ u8 pllf_mul = 0, r_div = 4; ++ u32 dwPLLN = 0, dwPLLF = 0, dwPLLNF = 0; ++ u32 dwPllFreq = 0, dwLoFreq = 0; ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ rtvRF_ConfigureClkCKSYN(dev,eBwType); ++ rtvRF_ConfigureIIRFilter(dev,eBwType); ++ rtvRF_ConfigureBBA(dev,eBwType); ++ rtvRF_ConfigureADC(dev,eBwType); ++ rtvRF_SetOfdmPara(dev,eServiceType, eBwType, dwChFreqKHz); ++ rtvRF_SelectService(dev,eServiceType); ++ ++ if (dev->rtv_1seglpmode) { ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ ++ if (eServiceType == RTV_SERVICE_VHF_ISDBTmm_1seg) { ++ regmap_write(dev->regmap,0x10, 0xFA); ++ dwLoFreq = dwChFreqKHz - 857; ++ } else { ++ regmap_write(dev->regmap,0x10, 0xF8); ++ dwLoFreq = dwChFreqKHz + 857; ++ } ++ } else ++ dwLoFreq = dwChFreqKHz; ++ rtvRF_Lna_Tuning(dev,dwLoFreq); ++ rtvRF_SetUpVCO(dev,dwLoFreq, &dwPllFreq); ++ ++ dwPLLN = dwPllFreq / dev->clk_freq; ++ dwPLLF = dwPllFreq - (dwPLLN * dev->clk_freq); ++ if (dev->clk_freq == 13000 || dev->clk_freq == 27000) { ++ pllf_mul = 1; ++ r_div = 3; ++ } ++ ++ dwPLLNF = (dwPLLN<<20) ++ + (((dwPLLF<<16) / (dev->clk_freq>>r_div)) << pllf_mul); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ regmap_write(dev->regmap,0x20, ((dwPLLNF>>22)&0xFF)); ++ regmap_write(dev->regmap,0x21, ((dwPLLNF>>14)&0xFF)); ++ regmap_update_bits(dev->regmap,0x28, 0xFC, ((dwPLLNF&0x3F)<<2)); ++ regmap_write(dev->regmap,0x22, ((dwPLLNF>>6)&0xFF)); ++ ++ msleep(1); ++ ++ if (rtvRF_LockCheck(dev,0) != 0) ++ return -1; ++ ++ if (dwPllFreq >= 2140000 && dwPllFreq < 2950000) { ++ regmap_update_bits(dev->regmap,0x94, 0x02, 0x02); ++ regmap_update_bits(dev->regmap,0x78, 0x70, 0x50); ++ regmap_update_bits(dev->regmap,0xEA, 0x60, 0x40); ++ } else if (dwPllFreq >= 2950000 && dwPllFreq < 3440000) { ++ regmap_update_bits(dev->regmap,0x94, 0x02, 0x02); ++ regmap_update_bits(dev->regmap,0x78, 0x70, 0x40); ++ regmap_update_bits(dev->regmap,0xEA, 0x60, 0x00); ++ } ++ ++ return 0; ++} ++static int mtv23x_set_frontend(struct dvb_frontend *fe) ++{ ++ struct i2c_client*client = fe->demodulator_priv; ++ struct mtv23x_dev*dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ enum E_RTV_BANDWIDTH_TYPE bandwidth ; ++ enum E_RTV_SERVICE_TYPE svc_type = RTV_SERVICE_VHF_ISDBTmm_13seg; ++ int ret; ++ ++ const u8 g_atSubChNum[] = { ++ 0x00, 0x00, 0x10, 0x10, 0x10, 0x20, /*0 ~ 5 */ ++ 0x20, 0x20, 0x30, 0x30, 0x30, 0x40, /*6 ~ 11 */ ++ 0x40, 0x40, 0x50, 0x50, 0x50, 0x60, /*12 ~ 17 */ ++ 0x60, 0x60, 0x70, 0x70, 0x70, 0x80, /*18 ~ 23 */ ++ 0x80, 0x80, 0x90, 0x90, 0x90, 0xA0, /*24 ~ 29 */ ++ 0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xC0, /*30 ~ 35 */ ++ 0xC0, 0xC0, 0xD0, 0xD0, 0xD0, 0x00 /*31 ~ 41 */ ++ }; ++ if (c->bandwidth_hz == 0) { ++ ret = -EINVAL; ++ goto err; ++ }else if(c->bandwidth_hz<=435000){ ++ bandwidth = RTV_BW_MODE_430KHZ; ++ svc_type = RTV_SERVICE_UHF_ISDBT_1seg|RTV_SERVICE_VHF_ISDBTsb_1seg ++ |RTV_SERVICE_VHF_ISDBTmm_1seg; ++ } ++ else if (c->bandwidth_hz <= 505000){ ++ bandwidth = RTV_BW_MODE_500KHZ; ++ svc_type = RTV_SERVICE_UHF_ISDBT_1seg|RTV_SERVICE_VHF_ISDBTsb_1seg ++ |RTV_SERVICE_VHF_ISDBTmm_1seg; ++ } ++ else if (c->bandwidth_hz <= 575000){ ++ bandwidth = RTV_BW_MODE_571KHZ; ++ svc_type = RTV_SERVICE_UHF_ISDBT_1seg|RTV_SERVICE_VHF_ISDBTsb_1seg| ++ RTV_SERVICE_VHF_ISDBTmm_1seg; ++ } ++ else if (c->bandwidth_hz <= 860000){ ++ bandwidth = RTV_BW_MODE_857KHZ; ++ svc_type = RTV_SERVICE_UHF_ISDBT_1seg|RTV_SERVICE_VHF_ISDBTsb_1seg| ++ RTV_SERVICE_VHF_ISDBTmm_1seg; ++ } ++ else if (c->bandwidth_hz <= 1295000){ ++ bandwidth = RTV_BW_MODE_1290KHZ; ++ svc_type = RTV_SERVICE_VHF_ISDBTsb_3seg; ++ } ++ else if(c->bandwidth_hz <= 5000000) ++ bandwidth = RTV_BW_MODE_5MHZ; ++ else if (c->bandwidth_hz <= 6000000) ++ bandwidth = RTV_BW_MODE_6MHZ; ++ else if (c->bandwidth_hz <= 7000000) ++ bandwidth = RTV_BW_MODE_7MHZ; ++ else if(c->bandwidth_hz <= 8000000) ++ bandwidth = RTV_BW_MODE_8MHZ; ++ else ++ bandwidth = RTV_BW_MODE_6MHZ; ++ ++ ++ rtvRF_SetFrequency(dev,svc_type,bandwidth,c->frequency/1000); ++ ++ if ((svc_type == RTV_SERVICE_VHF_ISDBTmm_1seg) || ++ (svc_type == RTV_SERVICE_VHF_ISDBTsb_1seg) || ++ (svc_type == RTV_SERVICE_VHF_ISDBTsb_3seg)) { ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ regmap_write(dev->regmap,0x31, g_atSubChNum[0]); ++ regmap_write(dev->regmap,0x34, 0xD1); ++ regmap_write(dev->regmap,0x36, 0x00); ++ } else if (svc_type == RTV_SERVICE_UHF_ISDBT_1seg) { ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ regmap_write(dev->regmap,0x31, 0x70); ++ regmap_write(dev->regmap,0x34, 0x9F); ++ regmap_write(dev->regmap,0x36, 0x01); ++ } ++ ++ msleep(20); ++ rtv_softReset(dev); ++ msleep(20); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_write(dev->regmap,0xA8, 0x87); ++ regmap_write(dev->regmap,0xAB, 0x87); ++ ++ dev->svc_type = svc_type; ++ return 0; ++err: ++ dev_dbg(&client->dev,"Failed =%d\n",ret); ++ return ret; ++ ++} ++static void rtv_UpdateMon(struct mtv23x_dev*dev) ++{ ++ if (dev->rtv_1seglpmode) { ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ regmap_update_bits(dev->regmap,0x13, 0x80, 0x80); ++ regmap_update_bits(dev->regmap,0x13, 0x80, 0x00); ++ } else { ++ regmap_write(dev->regmap,MAP_SEL_REG,OFDM_PAGE); ++ regmap_update_bits(dev->regmap,0x1B, 0x80, 0x80); ++ regmap_update_bits(dev->regmap,0x1B, 0x80, 0x00); ++ } ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_update_bits(dev->regmap,0x11, 0x04, 0x04); ++ regmap_update_bits(dev->regmap,0x11, 0x04, 0x00); ++} ++ ++static int mtv23x_read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct i2c_client*client = fe->demodulator_priv; ++ struct mtv23x_dev*dev = i2c_get_clientdata(client); ++ ++ int OFDMREG = 0, TMCCL = 0, OFDML = 0; ++ int lock_st = 0; ++ ++ if (dev->rtv_1seglpmode) { ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ regmap_read(dev->regmap,0xC0,&OFDMREG); ++ OFDML = OFDMREG & 0x07; ++ } else { ++ regmap_write(dev->regmap,MAP_SEL_REG,SHAD_PAGE); ++ regmap_read(dev->regmap,0x81,&OFDMREG); ++ OFDML = (OFDMREG & 0x04) >> 2; ++ } ++ ++ if (OFDML & 0x01) ++ lock_st = RTV_ISDBT_OFDM_LOCK_MASK; ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,FEC_PAGE); ++ regmap_read(dev->regmap,0x10,&TMCCL); ++ ++ if (TMCCL & 0x01) ++ lock_st |= RTV_ISDBT_TMCC_LOCK_MASK; ++ ++ printk("DVB: lock status is 0%x\n",lock_st); ++ ++ if (RTV_ISDBT_CHANNEL_LOCK_OK == lock_st) { ++ *status = FE_HAS_LOCK|FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|FE_HAS_SYNC; ++ } else if (lock_st & RTV_ISDBT_TMCC_LOCK_MASK) { ++ printk("TMCC lock \n"); ++ } else if (lock_st & RTV_ISDBT_OFDM_LOCK_MASK) { ++ printk("OFDM lock \n"); ++ } else { ++ *status = FE_TIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static u32 rtvMTV23x_GetCNR(struct mtv23x_dev*dev) ++{ ++ u32 data = 0, cnr = 0; ++ u8 Mod = 0xFF, Cd = 0xFF; ++ int temp,temp1,temp2; ++ ++ rtv_UpdateMon(dev); ++ ++ regmap_update_bits(dev->regmap,0x76, 0x18, 0x00); ++ ++ if (dev->rtv_1seglpmode) { ++ regmap_read(dev->regmap,0x7B,&temp); ++ Mod = temp & 0x07; ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,LPOFDM_PAGE); ++ regmap_update_bits(dev->regmap,0x25, 0x70, 0x10); ++ regmap_update_bits(dev->regmap,0x13, 0x80, 0x80); ++ regmap_update_bits(dev->regmap,0x13, 0x80, 0x00); ++ ++ regmap_read(dev->regmap,0xCA,&temp); ++ regmap_read(dev->regmap,0xC9,&temp1); ++ regmap_read(dev->regmap,0xC8,&temp2); ++ data = ((temp &0xff)<<16) ++ | ((temp1 &0xff)<<8) ++ | (temp2 &0xff); ++ ++ cnr = GetSNR_LP_Mode(Mod, data); ++ } else { ++ regmap_read(dev->regmap,0x7C,&temp); ++ Cd = (temp >> 3) & 0x0F; ++ ++ if (Cd < 2) ++ regmap_update_bits(dev->regmap,0x76, 0x18, 0x08); ++ ++ ++ if (dev->svc_type == RTV_SERVICE_DVBT){ ++ regmap_read(dev->regmap,0x6F,&temp); ++ Mod = ((temp >> 2) & 0x03) + 1; ++ } ++ else ++ { ++ regmap_read(dev->regmap,0x7B,&temp); ++ Mod = (temp & 0x07); ++ } ++ regmap_write(dev->regmap,MAP_SEL_REG,OFDM_PAGE); ++ regmap_update_bits(dev->regmap,0x1B, 0x80, 0x80); ++ regmap_update_bits(dev->regmap,0x1B, 0x80, 0x00); ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,SHAD_PAGE); ++ ++ regmap_read(dev->regmap,0xde,&temp); ++ regmap_read(dev->regmap,0xdd,&temp1); ++ regmap_read(dev->regmap,0xdc,&temp2); ++ data = ((temp << 16) ++ | (temp1 << 8) ++ | (temp2 << 0)); ++ ++ cnr = GetSNR_FULL_Mode(Mod, data); ++ } ++ ++ return cnr; ++} ++ ++static s32 rtvMTV23x_GetRSSI(struct mtv23x_dev*dev) ++{ ++ u8 RD11 = 0, GVBB = 0, LNAGAIN = 0, RFAGC = 0, CH_FLAG = 0; ++ s32 nRssi = 0; ++ s32 nRssiAppDelta = 4*10; ++ ++ if (dev->rtv_1seglpmode) ++ nRssiAppDelta = 0; ++ ++ regmap_write(dev->regmap,MAP_SEL_REG,RF_PAGE); ++ regmap_read(dev->regmap,0x11,(int)&RD11); ++ regmap_read(dev->regmap,0x14,(int)&GVBB); ++// RD11 = RTV_REG_GET(0x11); ++// GVBB = RTV_REG_GET(0x14); ++ ++ CH_FLAG = ((RD11 & 0xC0) >> 6); ++ LNAGAIN = ((RD11 & 0x18) >> 3); ++ RFAGC = (RD11 & 0x07); ++ ++ switch (LNAGAIN) { ++ case 0: ++ nRssi = -(RSSI_RFAGC_VAL(RFAGC, 2.8) ++ + RSSI_GVBB_VAL(GVBB, 0.44) + 0) ++ + 5*10; ++ break; ++ ++ case 1: ++ nRssi = -(RSSI_RFAGC_VAL(RFAGC, 3) ++ + RSSI_GVBB_VAL(GVBB, 0.3) ++ + (19*10)) ++ + 0*10; ++ break; ++ ++ case 2: ++ nRssi = -(RSSI_RFAGC_VAL(RFAGC, 3) ++ + RSSI_GVBB_VAL(GVBB, 0.3) ++ + (16*2*10)) ++ + 0*10; ++ break; ++ ++ case 3: ++ nRssi = -(RSSI_RFAGC_VAL(RFAGC, 2.6) ++ + RSSI_GVBB_VAL(GVBB, 0.4) ++ + (11*3*10)) ++ + 0*10; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (dev->rtv_1seglpmode) ++ nRssiAppDelta = 0; ++ else if (CH_FLAG == 0) ++ nRssiAppDelta += (7 * 10); ++ ++ return nRssi + nRssiAppDelta; ++} ++ ++static int mtv23x_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct i2c_client*client = fe->demodulator_priv; ++ struct mtv23x_dev*dev = i2c_get_clientdata(client); ++ *snr = (u16)rtvMTV23x_GetCNR(dev); ++ return 0; ++} ++static int mtv23x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct i2c_client*client = fe->demodulator_priv; ++ struct mtv23x_dev*dev = i2c_get_clientdata(client); ++ ++ *strength = (u16)rtvMTV23x_GetRSSI(dev); ++ return 0; ++} ++ ++static struct dvb_frontend_ops mtv23x_ops = { ++ .delsys = {SYS_ISDBT}, ++ .info = { ++ .name = "RAONTECH MTV23X", ++ .type = FE_OFDM, ++ .frequency_min = 76000000, ++ .frequency_max = 858000000, ++ .frequency_stepsize = 166667, ++ .frequency_tolerance = 0, ++ .caps = 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 | FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS ++ }, ++ ++ .init = mtv23x_init, ++ .set_frontend = mtv23x_set_frontend, ++ .read_status = mtv23x_read_status, ++ .read_signal_strength = mtv23x_read_signal_strength, ++ .read_snr = mtv23x_read_snr, ++ ++}; ++static int mtv23x_probe(struct i2c_client*client, ++ const struct i2c_device_id *id) ++{ ++ struct mtv23x_config *cfg = client->dev.platform_data; ++ struct mtv23x_dev *dev ; ++ int ret,temp; ++ ++ static const struct regmap_config regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ }; ++ dev = kzalloc(sizeof(*dev),GFP_KERNEL); ++ if(!dev){ ++ ret = -ENOMEM; ++ goto err; ++ } ++ dev->i2c_wr_max = cfg->i2c_wr_max?cfg->i2c_wr_max:~0; ++ dev->client = client; ++ dev->clk_freq = cfg->clk_freq; ++ dev->ts_mode = cfg->ts_mode; ++ dev->rtv_1seglpmode = 0; ++ dev->regmap = regmap_init_i2c(dev->client,®map_config); ++ if(IS_ERR(dev->regmap)){ ++ ret = PTR_ERR(dev->regmap); ++ goto err_kfree; ++ } ++ ++ /*check the i2c */ ++ ret = regmap_read(dev->regmap,0x20,&temp); ++ if(ret) ++ goto err_regmap_exit; ++ ret = regmap_write(dev->regmap,0x20,0xAA); ++ if(ret) ++ goto err_regmap_exit; ++ ret = regmap_read(dev->regmap,0x20,&temp); ++ if(temp!=0xAA) ++ goto err_regmap_exit; ++ ++ /* create a dvb frontend*/ ++ memcpy(&dev->fe.ops,&mtv23x_ops,sizeof(struct dvb_frontend_ops)); ++ dev->fe.demodulator_priv = client; ++ *cfg->fe = &dev->fe; ++ i2c_set_clientdata(client,dev); ++ ++ dev_info(&client->dev, "RAONTECH MTV23X successfully identified\n"); ++ ++ return 0; ++ ++err_regmap_exit: ++ regmap_exit(dev->regmap); ++err_kfree: ++ kfree(dev); ++err: ++ dev_dbg(&client->dev,"failed = %d\n",ret); ++ return ret; ++} ++static int mtv23x_remove(struct i2c_client*client) ++{ ++ struct mtv23x_dev*dev = i2c_get_clientdata(client); ++ ++ regmap_exit(dev->regmap); ++ kfree(dev); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id mtv23x_id_table[] ={ ++ {"mtv23x",0}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(i2c,mtv23x_id_table); ++ ++static struct i2c_driver mtv23x_driver = { ++ ++ .driver = { ++ .name = "mtv23x", ++ }, ++ .probe = mtv23x_probe, ++ .remove = mtv23x_remove, ++ .id_table = mtv23x_id_table, ++ ++}; ++ ++module_i2c_driver(mtv23x_driver); ++ ++ ++MODULE_AUTHOR("Davin "); ++MODULE_DESCRIPTION(" ISDB-T Demodulator driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/media/dvb-frontends/mtv23x.h b/drivers/media/dvb-frontends/mtv23x.h +new file mode 100644 +index 0000000..cc52ca4 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mtv23x.h +@@ -0,0 +1,24 @@ ++#ifndef MTV23X_H ++#define MTV23X_H ++#include ++ ++ ++/*TS mode*/ ++//#define RTV_TSIF_FORMAT_0 /* Serial: EN_high, CLK_rising */ ++//#define RTV_TSIF_FORMAT_1 /* Serial: EN_high, CLK_falling */ // ++//#define RTV_TSIF_FORMAT_2 /* Serial: EN_low, CLK_rising */ ++//#define RTV_TSIF_FORMAT_3 /* Serial: EN_low, CLK_falling */ ++//#define RTV_TSIF_FORMAT_4 /* Serial: EN_high, CLK_rising + 1CLK add */ ++//#define RTV_TSIF_FORMAT_5 /* Serial: EN_high, CLK_falling + 1CLK add */ ++//#define RTV_TSIF_FORMAT_6 /* Parallel: EN_high, CLK_rising */ ++//#define RTV_TSIF_FORMAT_7 /* Parallel: EN_high, CLK_falling */ ++ ++struct mtv23x_config{ ++ int ts_mode; // 0:serial 1:parallel ++ int clk_freq; //32000khz , 19200khz ++ u16 i2c_wr_max; ++ ++ struct dvb_frontend **fe; ++}; ++ ++#endif +diff --git a/drivers/media/dvb-frontends/mtv23x_priv.h b/drivers/media/dvb-frontends/mtv23x_priv.h +new file mode 100644 +index 0000000..ae62737 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mtv23x_priv.h +@@ -0,0 +1,95 @@ ++#ifndef MTV23X_PRIV_H ++#define MTV23X_PRIV_H ++ ++#include "dvb_frontend.h" ++#include "mtv23x.h" ++#include ++ ++/* Do not modify the order and value! */ ++enum E_RTV_SERVICE_TYPE { ++ RTV_SERVICE_INVALID = -1, ++ RTV_SERVICE_UHF_ISDBT_1seg = 0, /* ISDB-T 1seg */ ++ RTV_SERVICE_UHF_ISDBT_13seg = 1, /* ISDB-T fullseg */ ++ RTV_SERVICE_VHF_ISDBTmm_1seg = 2, /* ISDB-Tmm 1seg */ ++ RTV_SERVICE_VHF_ISDBTmm_13seg = 3, /* ISDB-Tmm 13seg */ ++ RTV_SERVICE_VHF_ISDBTsb_1seg = 4, /* ISDB-Tsb 1seg */ ++ RTV_SERVICE_VHF_ISDBTsb_3seg = 5, /* ISDB-Tsb 3seg */ ++ RTV_SERVICE_DVBT = 6, /* DVB-T */ ++ MAX_NUM_RTV_SERVICE ++}; ++ ++ ++struct mtv23x_dev { ++ struct i2c_client *client; ++ struct regmap *regmap; ++ struct dvb_frontend fe; ++ u16 i2c_wr_max; ++ ++ int ts_mode; ++ int clk_freq;//u:KHZ ++ ++ bool rtv_1seglpmode; ++ ++ enum E_RTV_SERVICE_TYPE svc_type; ++}; ++ ++#define TOP_PAGE 0x00 ++#define HOST_PAGE 0x00 ++#define OFDM_PAGE 0x01 ++#define SHAD_PAGE 0x02 ++#define FEC_PAGE 0x03 ++#define DATA_PAGE 0x04 ++#define FEC2_PAGE 0x06 ++#define LPOFDM_PAGE 0x07 ++#define SPI_CTRL_PAGE 0x0E ++#define RF_PAGE 0x0F ++ ++#define MAP_SEL_REG 0x03 ++ ++enum E_RTV_BANDWIDTH_TYPE { ++ RTV_BW_MODE_5MHZ = 0, /* DVB_T */ ++ RTV_BW_MODE_6MHZ, /* DVB_T, FULLSEG, ISDB-Tmm */ ++ RTV_BW_MODE_7MHZ, /* DVB_T, FULLSEG */ ++ RTV_BW_MODE_8MHZ, /* DVB_T, FULLSEG */ ++ RTV_BW_MODE_430KHZ, /* 1SEG at 6MHz BW */ ++ RTV_BW_MODE_500KHZ, /* 1SEG at 7MHz BW */ ++ RTV_BW_MODE_571KHZ, /* 1SEG at 8MHz BW */ ++ RTV_BW_MODE_857KHZ, /* DAB */ ++ RTV_BW_MODE_1290KHZ, /* 3SEG */ ++ MAX_NUM_RTV_BW_MODE_TYPE ++}; ++ ++ ++ ++struct RTV_REG_INIT_INFO { ++ u8 bReg; ++ u8 bVal; ++}; ++ ++struct RTV_ADC_CFG_INFO { ++ u8 bData2A; ++ u8 bData6E; ++ u8 bData70; ++ u8 bData71; ++ u8 bData75; ++ u32 dwTNCO; ++ u32 dwPNCO; ++ u32 dwCFREQGAIN; ++ u16 dwGAIN; ++}; ++ ++#define RTV_ISDBT_OFDM_LOCK_MASK 0x1 ++#define RTV_ISDBT_TMCC_LOCK_MASK 0x2 ++#define RTV_ISDBT_CHANNEL_LOCK_OK \ ++ (RTV_ISDBT_OFDM_LOCK_MASK|RTV_ISDBT_TMCC_LOCK_MASK) ++ ++ ++#define RSSI_UINT(val) (s32)((val)*10) ++ ++#define RSSI_RFAGC_VAL(rfagc, coeffi)\ ++ ((rfagc) * RSSI_UINT(coeffi)) ++ ++#define RSSI_GVBB_VAL(gvbb, coeffi)\ ++ ((gvbb) * RSSI_UINT(coeffi)) ++ ++#endif +diff --git a/drivers/media/dvb-frontends/mxl5xx.c b/drivers/media/dvb-frontends/mxl5xx.c +new file mode 100644 +index 0000000..cb6eb22 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mxl5xx.c +@@ -0,0 +1,1594 @@ ++/* ++ * Driver for the Maxlinear MX58x family of tuners/demods ++ * ++ * Copyright (C) 2014-2015 Ralph Metzler ++ * Marcus Metzler ++ * developed for Digital Devices GmbH ++ * ++ * based on code: ++ * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved ++ * which was released under GPL V2 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "mxl5xx.h" ++#include "mxl5xx_regs.h" ++#include "mxl5xx_defs.h" ++ ++ ++#define BYTE0(v) ((v >> 0) & 0xff) ++#define BYTE1(v) ((v >> 8) & 0xff) ++#define BYTE2(v) ((v >> 16) & 0xff) ++#define BYTE3(v) ((v >> 24) & 0xff) ++ ++#define MXL5XX_DEFAULT_FIRMWARE "dvb-fe-mxl5xx.fw" ++ ++static int mode = 0; ++module_param(mode, int, 0444); ++MODULE_PARM_DESC(mode, ++ "Multi-switch mode: 0=quattro/quad 1=normal direct connection"); ++ ++LIST_HEAD(mxllist); ++ ++struct mxl_base { ++ struct list_head mxllist; ++ ++ u8 adr; ++ struct i2c_adapter *i2c; ++ u32 count; ++ u32 type; ++ u32 chipversion; ++ u32 clock; ++ ++ struct mutex i2c_lock; ++ struct mutex status_lock; ++ u8 buf[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; ++ ++ u32 cmd_size; ++ u8 cmd_data[MAX_CMD_DATA]; ++ ++ struct mxl5xx_cfg *cfg; ++}; ++ ++struct mxl { ++ struct mxl_base *base; ++ struct dvb_frontend fe; ++ u32 demod; ++ u32 rf_in; ++ bool diseqcsign; // ++ MXL_HYDRA_DISEQC_TX_MSG_T diseqcMsg; ++}; ++ ++static void convert_endian(u8 flag, u32 size, u8 *d) ++{ ++ u32 i; ++ ++ if (!flag) ++ return; ++ for (i = 0; i < (size & ~3); i += 4) { ++ d[i + 0] ^= d[i + 3]; ++ d[i + 3] ^= d[i + 0]; ++ d[i + 0] ^= d[i + 3]; ++ ++ d[i + 1] ^= d[i + 2]; ++ d[i + 2] ^= d[i + 1]; ++ d[i + 1] ^= d[i + 2]; ++ } ++} ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, ++ u8 *data, u32 len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; ++} ++ ++static int i2c_read(struct i2c_adapter *adap, u8 adr, ++ u8 *data, u32 len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = I2C_M_RD, ++ .buf = data, .len = len}; ++ ++ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; ++} ++ ++static int i2cread(struct mxl *state, u8 *data, int len) ++{ ++ return i2c_read(state->base->i2c, state->base->adr, data, len); ++} ++ ++static int i2cwrite(struct mxl *state, u8 *data, int len) ++{ ++ return i2c_write(state->base->i2c, state->base->adr, data, len); ++} ++ ++static int send_command(struct mxl *state, u32 size, u8 *buf) ++{ ++ int stat; ++ ++ mutex_lock(&state->base->i2c_lock); ++ stat = i2cwrite(state, buf, size); ++ mutex_unlock(&state->base->i2c_lock); ++ return stat; ++} ++ ++static int write_register(struct mxl *state, u32 reg, u32 val) ++{ ++ int stat; ++ u8 data[MXL_HYDRA_REG_WRITE_LEN] = { ++ MXL_HYDRA_PLID_REG_WRITE, 0x08, ++ BYTE0(reg), BYTE1(reg), BYTE2(reg), BYTE3(reg), ++ BYTE0(val), BYTE1(val), BYTE2(val), BYTE3(val), ++ }; ++ mutex_lock(&state->base->i2c_lock); ++ stat = i2cwrite(state, data, sizeof(data)); ++ mutex_unlock(&state->base->i2c_lock); ++ if (stat) ++ pr_err("i2c write error\n"); ++ return stat; ++} ++ ++static int write_register_block(struct mxl *state, u32 reg, u32 size, u8 *data) ++{ ++ int stat; ++ u8 *buf = state->base->buf; ++ ++ mutex_lock(&state->base->i2c_lock); ++ ++ buf[0] = MXL_HYDRA_PLID_REG_WRITE; ++ buf[1] = size + 4; ++ buf[2] = GET_BYTE(reg, 0); ++ buf[3] = GET_BYTE(reg, 1); ++ buf[4] = GET_BYTE(reg, 2); ++ buf[5] = GET_BYTE(reg, 3); ++ memcpy(&buf[6], data, size); ++ ++ convert_endian(MXL_ENABLE_BIG_ENDIAN, size, &buf[6]); ++ stat = i2cwrite(state, buf, ++ MXL_HYDRA_I2C_HDR_SIZE + ++ MXL_HYDRA_REG_SIZE_IN_BYTES + size); ++ mutex_unlock(&state->base->i2c_lock); ++ return stat; ++} ++ ++static int write_firmware_block(struct mxl *state, ++ u32 reg, u32 size, u8 *regDataPtr) ++{ ++ int stat; ++ u8 *buf = state->base->buf; ++ ++ mutex_lock(&state->base->i2c_lock); ++ buf[0] = MXL_HYDRA_PLID_REG_WRITE; ++ buf[1] = size + 4; ++ buf[2] = GET_BYTE(reg, 0); ++ buf[3] = GET_BYTE(reg, 1); ++ buf[4] = GET_BYTE(reg, 2); ++ buf[5] = GET_BYTE(reg, 3); ++ memcpy(&buf[6], regDataPtr, size); ++ stat = i2cwrite(state, buf, ++ MXL_HYDRA_I2C_HDR_SIZE + ++ MXL_HYDRA_REG_SIZE_IN_BYTES + size); ++ mutex_unlock(&state->base->i2c_lock); ++ if (stat) ++ pr_err("fw block write failed\n"); ++ return stat; ++} ++ ++static int read_register(struct mxl *state, u32 reg, u32 *val) ++{ ++ int stat; ++ u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = { ++ MXL_HYDRA_PLID_REG_READ, 0x04, ++ GET_BYTE(reg, 0), GET_BYTE(reg, 1), ++ GET_BYTE(reg, 2), GET_BYTE(reg, 3), ++ }; ++ ++ mutex_lock(&state->base->i2c_lock); ++ stat = i2cwrite(state, data, ++ MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE); ++ if (stat) ++ pr_err("i2c read error 1\n"); ++ if (!stat) ++ stat = i2cread(state, (u8 *) val, MXL_HYDRA_REG_SIZE_IN_BYTES); ++ mutex_unlock(&state->base->i2c_lock); ++ le32_to_cpus(val); ++ if (stat) ++ pr_err("i2c read error 2\n"); ++ return stat; ++} ++ ++static int read_register_block(struct mxl *state, u32 reg, u32 size, u8 *data) ++{ ++ int stat; ++ u8 *buf = state->base->buf; ++ ++ mutex_lock(&state->base->i2c_lock); ++ ++ buf[0] = MXL_HYDRA_PLID_REG_READ; ++ buf[1] = size + 4; ++ buf[2] = GET_BYTE(reg, 0); ++ buf[3] = GET_BYTE(reg, 1); ++ buf[4] = GET_BYTE(reg, 2); ++ buf[5] = GET_BYTE(reg, 3); ++ stat = i2cwrite(state, buf, ++ MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES); ++ if (!stat) { ++ stat = i2cread(state, data, size); ++ convert_endian(MXL_ENABLE_BIG_ENDIAN, size, data); ++ } ++ mutex_unlock(&state->base->i2c_lock); ++ return stat; ++} ++ ++static int read_by_mnemonic(struct mxl *state, ++ u32 reg, u8 lsbloc, u8 numofbits, u32 *val) ++{ ++ u32 data = 0, mask = 0; ++ int stat; ++ ++ stat = read_register(state, reg, &data); ++ if (stat) ++ return stat; ++ mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); ++ data &= mask; ++ data >>= lsbloc; ++ *val = data; ++ return 0; ++} ++ ++ ++static int update_by_mnemonic(struct mxl *state, ++ u32 reg, u8 lsbloc, u8 numofbits, u32 val) ++{ ++ u32 data, mask; ++ int stat; ++ ++ stat = read_register(state, reg, &data); ++ if (stat) ++ return stat; ++ mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); ++ data = (data & ~mask) | ((val << lsbloc) & mask); ++ stat = write_register(state, reg, data); ++ return stat; ++} ++ ++static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width, ++ u32 *toAddr, u8 *toLsbPos, u8 *toWidth) ++{ ++ if (toAddr) ++ *toAddr = regAddr; ++ if (toLsbPos) ++ *toLsbPos = lsbPos; ++ if (toWidth) ++ *toWidth = width; ++} ++ ++static int firmware_is_alive(struct mxl *state) ++{ ++ u32 hb0, hb1; ++ ++ if (read_register(state, HYDRA_HEAR_BEAT, &hb0)) ++ return 0; ++ msleep(20); ++ if (read_register(state, HYDRA_HEAR_BEAT, &hb1)) ++ return 0; ++ if (hb1 == hb0) ++ return 0; ++ return 1; ++} ++ ++static int init(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++ ++static void release(struct dvb_frontend *fe) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ ++ state->base->count--; ++ if (state->base->count == 0) { ++ list_del(&state->base->mxllist); ++ kfree(state->base); ++ } ++ kfree(state); ++} ++ ++static int get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++static int CfgDemodAbortTune(struct mxl *state) ++{ ++ MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd; ++ u8 cmdSize = sizeof(abortTuneCmd); ++ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; ++ ++ abortTuneCmd.demodId = state->demod; ++ BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, cmdSize, &abortTuneCmd, cmdBuff); ++ return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); ++} ++ ++static int send_master_cmd(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *cmd) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ MXL_HYDRA_DISEQC_TX_MSG_T diseqcMsgPtr; ++ u8 cmdSize = sizeof(MXL_HYDRA_DISEQC_TX_MSG_T); ++ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; ++ int i = 0,ret = 0; ++ ++ ++ diseqcMsgPtr.diseqcId = state->rf_in; ++ diseqcMsgPtr.nbyte = cmd->msg_len; ++ diseqcMsgPtr.toneBurst = MXL_HYDRA_DISEQC_TONE_NONE; ++ ++ for( i =0;i < cmd->msg_len;i++) ++ diseqcMsgPtr.bufMsg[i] = cmd->msg[i]; ++ ++ if(!mode){ ++ state->diseqcsign= true; ++ memcpy(&state->diseqcMsg,&diseqcMsgPtr,sizeof(MXL_HYDRA_DISEQC_TX_MSG_T)); ++ return 0; ++ ++ } ++ ++ BUILD_HYDRA_CMD(MXL_HYDRA_DISEQC_MSG_CMD, MXL_CMD_WRITE, cmdSize, &diseqcMsgPtr, cmdBuff); ++ mutex_lock(&state->base->status_lock); ++ ret=send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); ++ mutex_unlock(&state->base->status_lock); ++ ++ return ret; ++} ++ ++static int send_burst(struct dvb_frontend *fe, ++ enum fe_sec_mini_cmd burst) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ MXL_HYDRA_DISEQC_TX_MSG_T diseqcMsgPtr; ++ u8 cmdSize = sizeof(MXL_HYDRA_DISEQC_TX_MSG_T); ++ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; ++ int i = 0,ret = 0; ++ ++ ++ diseqcMsgPtr.diseqcId = state->rf_in; ++ diseqcMsgPtr.nbyte = 0; ++ diseqcMsgPtr.toneBurst = burst == SEC_MINI_B ? MXL_HYDRA_DISEQC_TONE_SB : MXL_HYDRA_DISEQC_TONE_SA; ++ ++ if(!mode){ ++ state->diseqcsign= true; ++ memcpy(&state->diseqcMsg,&diseqcMsgPtr,sizeof(MXL_HYDRA_DISEQC_TX_MSG_T)); ++ return 0; ++ ++ } ++ ++ BUILD_HYDRA_CMD(MXL_HYDRA_DISEQC_MSG_CMD, MXL_CMD_WRITE, cmdSize, &diseqcMsgPtr, cmdBuff); ++ mutex_lock(&state->base->status_lock); ++ ret=send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); ++ mutex_unlock(&state->base->status_lock); ++ ++ return ret; ++} ++ ++static void senddiseqcAbortTune(struct dvb_frontend *fe) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ u8 cmdSize = sizeof(MXL_HYDRA_DISEQC_TX_MSG_T); ++ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; ++ ++ if(state->diseqcsign){ ++ state->diseqcMsg.diseqcId = state->rf_in; ++ state->diseqcMsg.bufMsg[0] = 0xe0; ++ BUILD_HYDRA_CMD(MXL_HYDRA_DISEQC_MSG_CMD, MXL_CMD_WRITE, cmdSize, &state->diseqcMsg, cmdBuff); ++ mutex_lock(&state->base->status_lock); ++ send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); ++ mutex_unlock(&state->base->status_lock); ++ ++ state->diseqcsign = false; ++ } ++ msleep(100); ++} ++ ++static int set_parameters(struct dvb_frontend *fe) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ int ret; ++ ++ MXL_HYDRA_DEMOD_PARAM_T demodChanCfg; ++ u8 cmdSize = sizeof(demodChanCfg); ++ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; ++ //MXL_HYDRA_DEMOD_ID_E demodId = state->demod; ++#if 0 ++ MXL_REG_FIELD_T xpt_enable_dss_input[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_INP_MODE_DSS0}, {XPT_INP_MODE_DSS1}, ++ {XPT_INP_MODE_DSS2}, {XPT_INP_MODE_DSS3}, ++ {XPT_INP_MODE_DSS4}, {XPT_INP_MODE_DSS5}, ++ {XPT_INP_MODE_DSS6}, {XPT_INP_MODE_DSS7} }; ++#endif ++ ++ if (p->frequency < 950000 || p->frequency > 2150000) ++ return -EINVAL; ++ if (p->symbol_rate < 1000000 || p->symbol_rate > 45000000) ++ return -EINVAL; ++ ++ if(!mode) ++ senddiseqcAbortTune(fe); ++ ++ //CfgDemodAbortTune(state); ++ ++ switch (p->delivery_system) { ++ case SYS_DSS: ++ demodChanCfg.standard = MXL_HYDRA_DSS; ++ break; ++ case SYS_DVBS: ++ demodChanCfg.standard = MXL_HYDRA_DVBS; ++ demodChanCfg.rollOff = MXL_HYDRA_ROLLOFF_AUTO; ++ demodChanCfg.modulationScheme = MXL_HYDRA_MOD_QPSK; ++ break; ++ case SYS_DVBS2: ++ demodChanCfg.standard = MXL_HYDRA_DVBS2; ++ demodChanCfg.rollOff = MXL_HYDRA_ROLLOFF_AUTO; ++ demodChanCfg.modulationScheme = MXL_HYDRA_MOD_AUTO; ++ demodChanCfg.pilots = MXL_HYDRA_PILOTS_AUTO; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ demodChanCfg.tunerIndex = state->rf_in; ++ demodChanCfg.demodIndex = state->demod; ++ demodChanCfg.frequencyInHz = p->frequency * 1000; ++ demodChanCfg.symbolRateInHz = p->symbol_rate; ++ demodChanCfg.maxCarrierOffsetInMHz = 10; ++ demodChanCfg.spectrumInversion = MXL_HYDRA_SPECTRUM_AUTO; ++ demodChanCfg.fecCodeRate = MXL_HYDRA_FEC_AUTO; ++ ++ //printk("std %u freq %u\n", demodChanCfg.standard, demodChanCfg.symbolRateInHz); ++ ++#if 0 ++ if (p->delivery_system == SYS_DSS) ++ update_by_mnemonic(state, ++ xpt_enable_dss_input[demodId].regAddr, ++ xpt_enable_dss_input[demodId].lsbPos, ++ xpt_enable_dss_input[demodId].numOfBits, ++ MXL_TRUE); ++ else ++ update_by_mnemonic(state, ++ xpt_enable_dss_input[demodId].regAddr, ++ xpt_enable_dss_input[demodId].lsbPos, ++ xpt_enable_dss_input[demodId].numOfBits, ++ MXL_FALSE); ++#endif ++ ++ BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE, ++ cmdSize, &demodChanCfg, cmdBuff); ++ ++ mutex_lock(&state->base->status_lock); ++ ret = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); ++ mutex_unlock(&state->base->status_lock); ++ ++ return ret; ++} ++ ++static int read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ int stat; ++ u32 reg[8]; ++ ++ ++ *status = FE_HAS_SIGNAL; ++ ++ /* Read RF level */ ++ mutex_lock(&state->base->status_lock); ++ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); ++ stat = read_register(state, (HYDRA_DMD_STATUS_INPUT_POWER_ADDR + ++ HYDRA_DMD_STATUS_OFFSET(state->demod)), ++ reg); ++ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); ++ mutex_unlock(&state->base->status_lock); ++ ++ p->strength.len = 1; ++ p->strength.stat[0].scale = FE_SCALE_DECIBEL; ++ p->strength.stat[0].svalue = (s16)reg[0] * 10; ++ ++ /* Read demod lock status */ ++ mutex_lock(&state->base->status_lock); ++ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); ++ stat = read_register(state, (HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET + ++ HYDRA_DMD_STATUS_OFFSET(state->demod)), ++ reg); ++ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); ++ mutex_unlock(&state->base->status_lock); ++ ++ if (reg[0] == 1) ++ *status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ else ++ { ++ p->cnr.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; ++ return 0; ++ } ++ ++ /* Read SNR */ ++ mutex_lock(&state->base->status_lock); ++ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); ++ stat = read_register(state, (HYDRA_DMD_SNR_ADDR_OFFSET + ++ HYDRA_DMD_STATUS_OFFSET(state->demod)), ++ reg); ++ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); ++ mutex_unlock(&state->base->status_lock); ++ ++ p->cnr.len = 1; ++ p->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ p->cnr.stat[0].svalue = (s16)reg[0] * 10; ++ ++ /* Read BER */ ++ mutex_lock(&state->base->status_lock); ++ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); ++ ++ stat = read_register_block(state, ++ (HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET + ++ HYDRA_DMD_STATUS_OFFSET(state->demod)), ++ (4 * sizeof(u32)), ++ (u8 *) reg); ++ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); ++ ++ switch (p->delivery_system) { ++ case SYS_DSS: ++ case SYS_DVBS: ++ p->pre_bit_error.len = 1; ++ p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ p->pre_bit_error.stat[0].uvalue = reg[2]; ++ p->pre_bit_count.len = 1; ++ p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ p->pre_bit_count.stat[0].uvalue = reg[3]; ++ /* pr_warn("mxl5xx: pre_bit_error=%u pre_bit_count=%u\n", p->pre_bit_error.stat[0].uvalue, p->pre_bit_count.stat[0].uvalue); */ ++ break; ++ default: ++ break; ++ } ++ ++ stat = read_register_block(state, ++ (HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET + ++ HYDRA_DMD_STATUS_OFFSET(state->demod)), ++ (7 * sizeof(u32)), ++ (u8 *) reg); ++ ++ mutex_unlock(&state->base->status_lock); ++ ++ switch (p->delivery_system) { ++ case SYS_DSS: ++ case SYS_DVBS: ++ p->post_bit_error.len = 1; ++ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_error.stat[0].uvalue = reg[5]; ++ p->post_bit_count.len = 1; ++ p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_count.stat[0].uvalue = reg[6]; ++ break; ++ case SYS_DVBS2: ++ p->post_bit_error.len = 1; ++ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_error.stat[0].uvalue = reg[1]; ++ p->post_bit_count.len = 1; ++ p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_count.stat[0].uvalue = reg[2]; ++ break; ++ default: ++ break; ++ } ++ /* pr_warn("mxl5xx: post_bit_error=%u post_bit_count=%u\n", p->post_bit_error.stat[0].uvalue, p->post_bit_count.stat[0].uvalue); */ ++ ++ return 0; ++} ++ ++static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ *strength = p->strength.stat[0].scale == FE_SCALE_DECIBEL ? ((100000 + (s32)p->strength.stat[0].svalue) / 1000) * 656 : 0; ++ ++ return 0; ++ ++} ++ ++static int read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ if (p->cnr.stat[0].scale == FE_SCALE_DECIBEL) { ++ *snr = (s32)p->cnr.stat[0].svalue / 100; ++ if (*snr > 200) ++ *snr = 0xffff; ++ else ++ *snr *= 328; ++ } else *snr = 0; ++ ++ return 0; ++} ++ ++static int read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ if ( p->post_bit_error.stat[0].scale == FE_SCALE_COUNTER && ++ p->post_bit_count.stat[0].scale == FE_SCALE_COUNTER ) ++ *ber = (u32)p->post_bit_count.stat[0].uvalue ? (u32)p->post_bit_error.stat[0].uvalue / (u32)p->post_bit_count.stat[0].uvalue : 0; ++ ++ return 0; ++} ++ ++static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ *ucblocks = 0; ++ return 0; ++} ++ ++static int tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, ++ unsigned int *delay, enum fe_status *status) ++{ ++ //struct mxl *state = fe->demodulator_priv; ++ int r = 0; ++ ++ *delay = HZ / 2; ++ if (re_tune) { ++ r = set_parameters(fe); ++ if (r) ++ return r; ++ } ++ ++ r = read_status(fe, status); ++ return r; ++} ++ ++static int sleep(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++ ++static enum fe_code_rate conv_fec(MXL_HYDRA_FEC_E fec) ++{ ++ enum fe_code_rate fec2fec[11] = { ++ FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3, ++ FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, ++ FEC_7_8, FEC_8_9, FEC_9_10 ++ }; ++ ++ if (fec > MXL_HYDRA_FEC_9_10) ++ return FEC_NONE; ++ return fec2fec[fec]; ++} ++ ++static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ u32 regData[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE]; ++ u32 freq; ++ int stat; ++ ++ mutex_lock(&state->base->status_lock); ++ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); ++ stat = read_register_block(state, ++ (HYDRA_DMD_STANDARD_ADDR_OFFSET + ++ HYDRA_DMD_STATUS_OFFSET(state->demod)), ++ (MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), // 25 * 4 bytes ++ (u8 *) ®Data[0]); ++ // read demod channel parameters ++ stat = read_register_block(state, ++ (HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR + ++ HYDRA_DMD_STATUS_OFFSET(state->demod)), ++ (4), // 4 bytes ++ (u8 *) &freq); ++ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); ++ mutex_unlock(&state->base->status_lock); ++ ++#if 0 ++ pr_warn("mxl5xx: freq=%u delsys=%u srate=%u\n", freq * 1000, ++ regData[DMD_STANDARD_ADDR], regData[DMD_SYMBOL_RATE_ADDR]); ++#endif ++ ++ p->symbol_rate = regData[DMD_SYMBOL_RATE_ADDR]; ++ p->frequency = freq; ++ //p->delivery_system = (MXL_HYDRA_BCAST_STD_E )regData[DMD_STANDARD_ADDR]; ++ //p->inversion = (MXL_HYDRA_SPECTRUM_E )regData[DMD_SPECTRUM_INVERSION_ADDR]; ++ //freqSearchRangeKHz = (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]); ++ ++ p->fec_inner = conv_fec(regData[DMD_FEC_CODE_RATE_ADDR]); ++ switch (p->delivery_system) { ++ case SYS_DSS: ++ break; ++ case SYS_DVBS2: ++ switch ((MXL_HYDRA_PILOTS_E ) regData[DMD_DVBS2_PILOT_ON_OFF_ADDR]) { ++ case MXL_HYDRA_PILOTS_OFF: ++ p->pilot = PILOT_OFF; ++ break; ++ case MXL_HYDRA_PILOTS_ON: ++ p->pilot = PILOT_ON; ++ break; ++ default: ++ break; ++ } ++ case SYS_DVBS: ++ switch ((MXL_HYDRA_MODULATION_E) regData[DMD_MODULATION_SCHEME_ADDR]) { ++ case MXL_HYDRA_MOD_QPSK: ++ p->modulation = QPSK; ++ break; ++ case MXL_HYDRA_MOD_8PSK: ++ p->modulation = PSK_8; ++ break; ++ default: ++ break; ++ } ++ switch ((MXL_HYDRA_ROLLOFF_E) regData[DMD_SPECTRUM_ROLL_OFF_ADDR]) { ++ case MXL_HYDRA_ROLLOFF_0_20: ++ p->rolloff = ROLLOFF_20; ++ break; ++ case MXL_HYDRA_ROLLOFF_0_35: ++ p->rolloff = ROLLOFF_35; ++ break; ++ case MXL_HYDRA_ROLLOFF_0_25: ++ p->rolloff = ROLLOFF_25; ++ break; ++ default: ++ break; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int set_input_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone, int rf_in) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ u8 buf[14] = { ++ MXL_HYDRA_PLID_CMD_WRITE, ++ 12, 8, ++ MXL_HYDRA_DISEQC_CONT_TONE_CFG, 0, 0, ++ rf_in, 0, 0, 0, ++ (tone == SEC_TONE_ON) ? 1 : 0, 0, 0, 0 ++ }; ++ return send_command(state, sizeof(buf), buf); ++} ++ ++ ++ ++static int set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ struct i2c_adapter *i2c = state->base->i2c; ++ struct mxl5xx_cfg *cfg = state->base->cfg; ++ ++ switch (mode) { ++ case 1: ++ cfg->set_voltage(i2c, voltage, state->rf_in); ++ break; ++ case 0: ++ default: ++ if (voltage == SEC_VOLTAGE_18) ++ state->rf_in &= ~2; ++ else ++ state->rf_in |= 2; ++ break; ++ } ++ ++ return 0; //state->base->cfg->set_voltage(fe, voltage, 0); ++} ++ ++ ++static int set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) ++{ ++ struct mxl *state = fe->demodulator_priv; ++ ++ switch (mode) { ++ case 1: ++ set_input_tone(fe, tone, state->rf_in); ++ break; ++ case 0: ++ default: ++ if (tone == SEC_TONE_ON) ++ state->rf_in &= ~1; ++ else ++ state->rf_in |= 1; ++ break; ++ } ++ ++ return 0; ++} ++ ++static struct dvb_frontend_ops mxl_ops = { ++ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, ++ .info = { ++ .name = "MXL5XX", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 0, ++ .frequency_tolerance = 0, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 70000000, ++ .caps = FE_CAN_INVERSION_AUTO | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_2G_MODULATION ++ }, ++ .init = init, ++ .release = release, ++ .get_frontend_algo = get_algo, ++ .tune = tune, ++ .read_status = read_status, ++ .sleep = sleep, ++ .read_snr = read_snr, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_ucblocks = read_ucblocks, ++ .get_frontend = get_frontend, ++ .diseqc_send_master_cmd = send_master_cmd, ++ .diseqc_send_burst = send_burst, ++ ++ .set_tone = set_tone, ++ .set_voltage = set_voltage, ++}; ++ ++static struct mxl_base *match_base(struct i2c_adapter *i2c, u8 adr) ++{ ++ struct mxl_base *p; ++ ++ list_for_each_entry(p, &mxllist, mxllist) ++ if (p->i2c == i2c && p->adr == adr) ++ return p; ++ return NULL; ++} ++ ++static void cfg_dev_xtal(struct mxl *state, u32 freq, u32 cap, u32 enable) ++{ ++ SET_REG_FIELD_DATA(AFE_REG_D2A_XTAL_EN_CLKOUT_1P8, enable); ++ if (freq == 24000000) ++ write_register(state, HYDRA_CRYSTAL_SETTING, 0); ++ else ++ write_register(state, HYDRA_CRYSTAL_SETTING, 1); ++ ++ write_register(state, HYDRA_CRYSTAL_CAP, cap); ++} ++ ++static u32 get_big_endian(u8 numOfBits, const u8 buf[]) ++{ ++ u32 retValue = 0; ++ ++ switch (numOfBits) { ++ case 24: ++ retValue = (((u32) buf[0]) << 16) | ++ (((u32) buf[1]) << 8) | buf[2]; ++ break; ++ case 32: ++ retValue = (((u32) buf[0]) << 24) | ++ (((u32) buf[1]) << 16) | ++ (((u32) buf[2]) << 8) | buf[3]; ++ break; ++ default: ++ break; ++ } ++ ++ return retValue; ++} ++ ++static void flip_data_in_dword(u32 size, u8 *d) ++{ ++ u32 i; ++ u8 t; ++ ++ for (i = 0; i < size; i += 4) { ++ t = d[i + 3]; d[i + 3] = d[i]; d[i] = t; ++ t = d[i + 2]; d[i + 2] = d[i + 1]; d[i + 1] = t; ++ } ++} ++ ++static int write_fw_segment(struct mxl *state, ++ u32 MemAddr, u32 totalSize, u8 *dataPtr) ++{ ++ int status; ++ u32 dataCount = 0; ++ u32 size = 0; ++ u32 origSize = 0; ++ u8 *wBufPtr = NULL; ++ u32 blockSize = MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH; ++ u8 wMsgBuffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH]; ++ ++ //pr_info("seg %u\n", totalSize); ++ do { ++ size = origSize = (((u32)(dataCount + blockSize)) > totalSize) ? ++ (totalSize - dataCount) : blockSize; ++ wBufPtr = dataPtr; ++ ++ if (origSize & 3) { ++ size = (origSize + 4) & ~3; ++ wBufPtr = &wMsgBuffer[0]; ++ memset((void *)wBufPtr + origSize, ++ 0x00, size - origSize); ++ memcpy((void *)wBufPtr, (void *)dataPtr, origSize); ++ } ++ flip_data_in_dword(size, wBufPtr); ++ status = write_firmware_block(state, MemAddr, size, wBufPtr); ++ if (status) ++ return status; ++ dataCount += size; ++ MemAddr += size; ++ dataPtr += size; ++ } while (dataCount < totalSize); ++ ++ return status; ++} ++ ++static int do_firmware_download(struct mxl *state, ++ u32 mbinBufferSize, ++ u8 *mbinBufferPtr) ++{ ++ int status; ++ u32 index = 0; ++ u32 segLength = 0; ++ u32 segAddress = 0; ++ MBIN_FILE_T *mbinPtr = (MBIN_FILE_T *)mbinBufferPtr; ++ MBIN_SEGMENT_T *segmentPtr; ++ ++ if (mbinPtr->header.id != MBIN_FILE_HEADER_ID) { ++ pr_err("%s: Invalid file header ID (%c)\n", ++ __func__, mbinPtr->header.id); ++ return -EINVAL; ++ } ++ status = write_register(state, FW_DL_SIGN_ADDR, 0); ++ if (status) ++ return status; ++ segmentPtr = (MBIN_SEGMENT_T *) (&mbinPtr->data[0]); ++ for (index = 0; index < mbinPtr->header.numSegments; index++) { ++ if (segmentPtr->header.id != MBIN_SEGMENT_HEADER_ID) { ++ pr_err("%s: Invalid segment header ID (%c)\n", ++ __func__, segmentPtr->header.id); ++ return -EINVAL; ++ } ++ segLength = get_big_endian(24, &(segmentPtr->header.len24[0])); ++ segAddress = get_big_endian(32, &(segmentPtr->header.address[0])); ++ status = -1; ++ if (((segAddress & 0x90760000) != 0x90760000) && ++ ((segAddress & 0x90740000) != 0x90740000)) ++ status = write_fw_segment(state, segAddress, ++ segLength, (u8 *) segmentPtr->data); ++ if (status) ++ return status; ++ segmentPtr = (MBIN_SEGMENT_T *) ++ &(segmentPtr->data[((segLength + 3) / 4) * 4]); ++ } ++ return status; ++} ++ ++static int firmware_download(struct mxl *state, u32 mbinBufferSize, ++ u8 *mbinBufferPtr) ++{ ++ int status; ++ u32 regData = 0; ++ MXL_HYDRA_SKU_COMMAND_T devSkuCfg; ++ u8 cmdSize = sizeof(MXL_HYDRA_SKU_COMMAND_T); ++ u8 cmdBuff[sizeof(MXL_HYDRA_SKU_COMMAND_T) + 6]; ++ ++ /* put CPU into reset */ ++ status = SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N, 0); ++ if (status) ++ return status; ++ usleep_range(1000, 2000); ++ ++ /* Reset TX FIFO's, BBAND, XBAR */ ++ status = write_register(state, HYDRA_RESET_TRANSPORT_FIFO_REG, ++ HYDRA_RESET_TRANSPORT_FIFO_DATA); ++ if (status) ++ return status; ++ status = write_register(state, HYDRA_RESET_BBAND_REG, ++ HYDRA_RESET_BBAND_DATA); ++ if (status) ++ return status; ++ status = write_register(state, HYDRA_RESET_XBAR_REG, ++ HYDRA_RESET_XBAR_DATA); ++ if (status) ++ return status; ++ ++ // lja ++ /* Disable clock to Baseband, Wideband, SerDes, Alias ext & Transport modules */ ++ status = write_register(state, HYDRA_MODULES_CLK_2_REG, HYDRA_DISABLE_CLK_2); ++ if (status) ++ return status; ++ //write_register(state, HYDRA_MODULES_CLK_2_REG, 0x0000000b); ++ ++ ++ /* Clear Software & Host interrupt status - (Clear on read) */ ++ status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, ®Data); ++ if (status) ++ return status; ++ ++ status = do_firmware_download(state, mbinBufferSize, mbinBufferPtr); ++ if (status) ++ return status; ++ ++ if (state->base->type == MXL_HYDRA_DEVICE_568) { ++ msleep(10); ++ ++ // bring XCPU out of reset ++ status = write_register(state, 0x90720000, 1); ++ if (status) ++ return status; ++ msleep(500); ++ ++ // Enable XCPU UART message processing in MCPU ++ status = write_register(state, 0x9076B510, 1); ++ if (status) ++ return status; ++ } else { ++ /* Bring CPU out of reset */ ++ status = SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N, 1); ++ if (status) ++ return status; ++ /* Wait until FW boots */ ++ msleep(150); ++ } ++ ++ // lja ++ // Initilize XPT XBAR ++ status = write_register(state, XPT_DMD0_BASEADDR, 0x76543210); ++ if (status) ++ return status; ++ ++ if (!firmware_is_alive(state)) ++ return -1; ++ ++ pr_info("Hydra FW alive\n"); ++ ++ /* sometimes register values are wrong shortly after first heart beats */ ++ msleep(50); ++ ++ devSkuCfg.skuType = state->base->type; ++ BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE, ++ cmdSize, &devSkuCfg, cmdBuff); ++ status = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); ++ if (status) ++ return status; ++ ++ status = GET_REG_FIELD_DATA(PAD_MUX_BOND_OPTION, ®Data); ++ if (status) ++ return status; ++ pr_info("chipID=%08x\n", regData); ++ ++ status = GET_REG_FIELD_DATA(PRCM_AFE_CHIP_MMSK_VER, ®Data); ++ if (status) ++ return status; ++ pr_info("chipVer=%08x\n", regData); ++ ++ status = read_register(state, HYDRA_FIRMWARE_VERSION, ®Data); ++ if (status) ++ return status; ++ pr_info("FWVer=%08x\n", regData); ++ ++ return status; ++} ++ ++static int cfg_ts_pad_mux(struct mxl *state, MXL_BOOL_E enableSerialTS) ++{ ++ int status = 0; ++ u32 padMuxValue = 0; ++ ++ if (enableSerialTS == MXL_TRUE) ++ padMuxValue = 0; ++ else ++ padMuxValue = 3; ++ ++ switch (state->base->type) { ++ case MXL_HYDRA_DEVICE_561: ++ case MXL_HYDRA_DEVICE_581: ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL, padMuxValue); ++ break; ++ ++ case MXL_HYDRA_DEVICE_584: ++ default: ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_09_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_10_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_11_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_12_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_13_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue); ++ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue); ++ break; ++ } ++ return status; ++} ++ ++static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId, MXL_HYDRA_MPEGOUT_PARAM_T *mpegOutParamPtr) ++{ ++ int status = 0; ++ u32 ncoCountMin = 0; ++ u32 clkType = 0; ++ ++ MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_SYNC_POLARITY0}, {XPT_SYNC_POLARITY1}, ++ {XPT_SYNC_POLARITY2}, {XPT_SYNC_POLARITY3}, ++ {XPT_SYNC_POLARITY4}, {XPT_SYNC_POLARITY5}, ++ {XPT_SYNC_POLARITY6}, {XPT_SYNC_POLARITY7} }; ++ MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_CLOCK_POLARITY0}, {XPT_CLOCK_POLARITY1}, ++ {XPT_CLOCK_POLARITY2}, {XPT_CLOCK_POLARITY3}, ++ {XPT_CLOCK_POLARITY4}, {XPT_CLOCK_POLARITY5}, ++ {XPT_CLOCK_POLARITY6}, {XPT_CLOCK_POLARITY7} }; ++ MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_VALID_POLARITY0}, {XPT_VALID_POLARITY1}, ++ {XPT_VALID_POLARITY2}, {XPT_VALID_POLARITY3}, ++ {XPT_VALID_POLARITY4}, {XPT_VALID_POLARITY5}, ++ {XPT_VALID_POLARITY6}, {XPT_VALID_POLARITY7} }; ++ MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_TS_CLK_PHASE0}, {XPT_TS_CLK_PHASE1}, ++ {XPT_TS_CLK_PHASE2}, {XPT_TS_CLK_PHASE3}, ++ {XPT_TS_CLK_PHASE4}, {XPT_TS_CLK_PHASE5}, ++ {XPT_TS_CLK_PHASE6}, {XPT_TS_CLK_PHASE7} }; ++ MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_LSB_FIRST0}, {XPT_LSB_FIRST1}, {XPT_LSB_FIRST2}, {XPT_LSB_FIRST3}, ++ {XPT_LSB_FIRST4}, {XPT_LSB_FIRST5}, {XPT_LSB_FIRST6}, {XPT_LSB_FIRST7} }; ++ MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_SYNC_FULL_BYTE0}, {XPT_SYNC_FULL_BYTE1}, ++ {XPT_SYNC_FULL_BYTE2}, {XPT_SYNC_FULL_BYTE3}, ++ {XPT_SYNC_FULL_BYTE4}, {XPT_SYNC_FULL_BYTE5}, ++ {XPT_SYNC_FULL_BYTE6}, {XPT_SYNC_FULL_BYTE7} }; ++ MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_ENABLE_OUTPUT0}, {XPT_ENABLE_OUTPUT1}, ++ {XPT_ENABLE_OUTPUT2}, {XPT_ENABLE_OUTPUT3}, ++ {XPT_ENABLE_OUTPUT4}, {XPT_ENABLE_OUTPUT5}, ++ {XPT_ENABLE_OUTPUT6}, {XPT_ENABLE_OUTPUT7} }; ++ MXL_REG_FIELD_T xpt_enable_dvb_input[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_ENABLE_INPUT0}, {XPT_ENABLE_INPUT1}, ++ {XPT_ENABLE_INPUT2}, {XPT_ENABLE_INPUT3}, ++ {XPT_ENABLE_INPUT4}, {XPT_ENABLE_INPUT5}, ++ {XPT_ENABLE_INPUT6}, {XPT_ENABLE_INPUT7} }; ++ MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_ERROR_REPLACE_SYNC0}, {XPT_ERROR_REPLACE_SYNC1}, ++ {XPT_ERROR_REPLACE_SYNC2}, {XPT_ERROR_REPLACE_SYNC3}, ++ {XPT_ERROR_REPLACE_SYNC4}, {XPT_ERROR_REPLACE_SYNC5}, ++ {XPT_ERROR_REPLACE_SYNC6}, {XPT_ERROR_REPLACE_SYNC7} }; ++ MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_ERROR_REPLACE_VALID0}, {XPT_ERROR_REPLACE_VALID1}, ++ {XPT_ERROR_REPLACE_VALID2}, {XPT_ERROR_REPLACE_VALID3}, ++ {XPT_ERROR_REPLACE_VALID4}, {XPT_ERROR_REPLACE_VALID5}, ++ {XPT_ERROR_REPLACE_VALID6}, {XPT_ERROR_REPLACE_VALID7} }; ++ MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = { ++ {XPT_TS_CLK_OUT_EN0}, {XPT_TS_CLK_OUT_EN1}, ++ {XPT_TS_CLK_OUT_EN2}, {XPT_TS_CLK_OUT_EN3}, ++ {XPT_TS_CLK_OUT_EN4}, {XPT_TS_CLK_OUT_EN5}, ++ {XPT_TS_CLK_OUT_EN6}, {XPT_TS_CLK_OUT_EN7} }; ++ MXL_REG_FIELD_T mxl561_xpt_ts_sync[MXL_HYDRA_DEMOD_ID_6] = { ++ {PAD_MUX_DIGIO_25_PINMUX_SEL}, {PAD_MUX_DIGIO_20_PINMUX_SEL}, ++ {PAD_MUX_DIGIO_17_PINMUX_SEL}, {PAD_MUX_DIGIO_11_PINMUX_SEL}, ++ {PAD_MUX_DIGIO_08_PINMUX_SEL}, {PAD_MUX_DIGIO_03_PINMUX_SEL} }; ++ MXL_REG_FIELD_T mxl561_xpt_ts_valid[MXL_HYDRA_DEMOD_ID_6] = { ++ {PAD_MUX_DIGIO_26_PINMUX_SEL}, {PAD_MUX_DIGIO_19_PINMUX_SEL}, ++ {PAD_MUX_DIGIO_18_PINMUX_SEL}, {PAD_MUX_DIGIO_10_PINMUX_SEL}, ++ {PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL} }; ++ ++ if (MXL_ENABLE == mpegOutParamPtr->enable) { ++ cfg_ts_pad_mux(state, MXL_TRUE); ++ SET_REG_FIELD_DATA(XPT_ENABLE_PARALLEL_OUTPUT, MXL_FALSE); ++ } ++ ncoCountMin = (u32)(MXL_HYDRA_NCO_CLK/mpegOutParamPtr->maxMpegClkRate); ++ SET_REG_FIELD_DATA(XPT_NCO_COUNT_MIN, ncoCountMin); ++ ++ if (mpegOutParamPtr->mpegClkType == MXL_HYDRA_MPEG_CLK_CONTINUOUS) ++ clkType = 1; ++ ++ if (mpegOutParamPtr->mpegMode < MXL_HYDRA_MPEG_MODE_PARALLEL) { ++ status |= update_by_mnemonic(state, ++ xpt_continuous_clock[demodId].regAddr, ++ xpt_continuous_clock[demodId].lsbPos, ++ xpt_continuous_clock[demodId].numOfBits, ++ clkType); ++ } else ++ SET_REG_FIELD_DATA(XPT_TS_CLK_OUT_EN_PARALLEL, clkType); ++ ++ status |= update_by_mnemonic(state, ++ xpt_sync_polarity[demodId].regAddr, ++ xpt_sync_polarity[demodId].lsbPos, ++ xpt_sync_polarity[demodId].numOfBits, ++ mpegOutParamPtr->mpegSyncPol); ++ ++ status |= update_by_mnemonic(state, ++ xpt_valid_polarity[demodId].regAddr, ++ xpt_valid_polarity[demodId].lsbPos, ++ xpt_valid_polarity[demodId].numOfBits, ++ mpegOutParamPtr->mpegValidPol); ++ ++ status |= update_by_mnemonic(state, ++ xpt_clock_polarity[demodId].regAddr, ++ xpt_clock_polarity[demodId].lsbPos, ++ xpt_clock_polarity[demodId].numOfBits, ++ mpegOutParamPtr->mpegClkPol); ++ ++ status |= update_by_mnemonic(state, ++ xpt_sync_byte[demodId].regAddr, ++ xpt_sync_byte[demodId].lsbPos, ++ xpt_sync_byte[demodId].numOfBits, ++ mpegOutParamPtr->mpegSyncPulseWidth); ++ ++ status |= update_by_mnemonic(state, ++ xpt_ts_clock_phase[demodId].regAddr, ++ xpt_ts_clock_phase[demodId].lsbPos, ++ xpt_ts_clock_phase[demodId].numOfBits, ++ mpegOutParamPtr->mpegClkPhase); ++ ++ status |= update_by_mnemonic(state, ++ xpt_lsb_first[demodId].regAddr, ++ xpt_lsb_first[demodId].lsbPos, ++ xpt_lsb_first[demodId].numOfBits, ++ mpegOutParamPtr->lsbOrMsbFirst); ++ ++ switch (mpegOutParamPtr->mpegErrorIndication) { ++ case MXL_HYDRA_MPEG_ERR_REPLACE_SYNC: ++ status |= update_by_mnemonic(state, ++ xpt_err_replace_sync[demodId].regAddr, ++ xpt_err_replace_sync[demodId].lsbPos, ++ xpt_err_replace_sync[demodId].numOfBits, ++ MXL_TRUE); ++ ++ status |= update_by_mnemonic(state, ++ xpt_err_replace_valid[demodId].regAddr, ++ xpt_err_replace_valid[demodId].lsbPos, ++ xpt_err_replace_valid[demodId].numOfBits, ++ MXL_FALSE); ++ break; ++ ++ case MXL_HYDRA_MPEG_ERR_REPLACE_VALID: ++ status |= update_by_mnemonic(state, ++ xpt_err_replace_sync[demodId].regAddr, ++ xpt_err_replace_sync[demodId].lsbPos, ++ xpt_err_replace_sync[demodId].numOfBits, ++ MXL_FALSE); ++ ++ status |= update_by_mnemonic(state, ++ xpt_err_replace_valid[demodId].regAddr, ++ xpt_err_replace_valid[demodId].lsbPos, ++ xpt_err_replace_valid[demodId].numOfBits, ++ MXL_TRUE); ++ break; ++ ++ case MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED: ++ default: ++ status |= update_by_mnemonic(state, ++ xpt_err_replace_sync[demodId].regAddr, ++ xpt_err_replace_sync[demodId].lsbPos, ++ xpt_err_replace_sync[demodId].numOfBits, ++ MXL_FALSE); ++ ++ status |= update_by_mnemonic(state, ++ xpt_err_replace_valid[demodId].regAddr, ++ xpt_err_replace_valid[demodId].lsbPos, ++ xpt_err_replace_valid[demodId].numOfBits, ++ MXL_FALSE); ++ ++ break; ++ ++ } ++ ++ if (mpegOutParamPtr->mpegMode != MXL_HYDRA_MPEG_MODE_PARALLEL) { ++ status |= update_by_mnemonic(state, ++ xpt_enable_output[demodId].regAddr, ++ xpt_enable_output[demodId].lsbPos, ++ xpt_enable_output[demodId].numOfBits, ++ mpegOutParamPtr->enable); ++ ++ status |= ++ update_by_mnemonic(state, ++ xpt_enable_dvb_input[demodId].regAddr, ++ xpt_enable_dvb_input[demodId].lsbPos, ++ xpt_enable_dvb_input[demodId].numOfBits, ++ mpegOutParamPtr->enable); ++ ++ } ++ return status; ++} ++ ++static int config_mux(struct mxl *state) ++{ ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT0, 0); ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT1, 0); ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT2, 0); ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT3, 0); ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT4, 0); ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT5, 0); ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT6, 0); ++ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT7, 0); ++ SET_REG_FIELD_DATA(XPT_STREAM_MUXMODE0, 1); ++ SET_REG_FIELD_DATA(XPT_STREAM_MUXMODE1, 1); ++ return 0; ++} ++ ++static int config_dis(struct mxl *state, u32 id) ++{ ++ MXL_HYDRA_DISEQC_ID_E diseqcId = id; ++ MXL_HYDRA_DISEQC_OPMODE_E opMode = MXL_HYDRA_DISEQC_TONE_MODE; //lja MXL_HYDRA_DISEQC_ENVELOPE_MODE; ++ MXL_HYDRA_DISEQC_VER_E version = MXL_HYDRA_DISEQC_1_X; ++ MXL_HYDRA_DISEQC_CARRIER_FREQ_E carrierFreqInHz = ++ MXL_HYDRA_DISEQC_CARRIER_FREQ_22KHZ; ++ MXL58x_DSQ_OP_MODE_T diseqcMsg; ++ u8 cmdSize = sizeof(diseqcMsg); ++ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; ++ ++ diseqcMsg.diseqcId = diseqcId; ++ diseqcMsg.opMode = opMode; ++ diseqcMsg.version = version; ++ diseqcMsg.centerFreq = carrierFreqInHz; ++ ++ BUILD_HYDRA_CMD(MXL_HYDRA_DISEQC_CFG_MSG_CMD, ++ MXL_CMD_WRITE, cmdSize, &diseqcMsg, cmdBuff); ++ return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); ++} ++ ++static int load_fw(struct mxl *state) ++{ ++ struct mxl5xx_cfg *cfg = state->base->cfg; ++ int stat = 0; ++ u8 *buf; ++ ++#if 1 ++ const struct firmware *fw; ++ ++ pr_info("loading firmware, please wait...\n"); ++ ++ stat = request_firmware(&fw, MXL5XX_DEFAULT_FIRMWARE, ++ state->base->i2c->dev.parent); ++ if (stat) ++ return stat; ++ ++ stat = firmware_download(state, fw->size, fw->data); ++ ++ release_firmware(fw); ++ ++ if (stat) ++ pr_info("error loading firmware\n"); ++ ++#else ++ if (cfg->fw) ++ return firmware_download(state, cfg->fw_len, cfg->fw); ++ ++#ifdef FW_INCLUDED ++ return firmware_download(state, sizeof(hydra_fw), hydra_fw); ++#endif ++ ++ if (!cfg->fw_read) ++ return -1; ++ ++ buf = vmalloc(0x40000); ++ if (!buf) ++ return -ENOMEM; ++ ++ cfg->fw_read(cfg->fw_priv, buf, 0x40000); ++ stat = firmware_download(state, 0x40000, buf); ++ vfree(buf); ++#endif ++ return stat; ++} ++ ++static int init_multisw(struct mxl *state) ++{ ++ struct dvb_frontend *fe = &state->fe; ++ struct i2c_adapter *i2c = state->base->i2c; ++ struct mxl5xx_cfg *cfg = state->base->cfg; ++ ++ switch (mode) { ++ case 0: ++ default: ++ cfg->set_voltage(i2c, SEC_VOLTAGE_13, 3); ++ cfg->set_voltage(i2c, SEC_VOLTAGE_13, 2); ++ cfg->set_voltage(i2c, SEC_VOLTAGE_18, 1); ++ cfg->set_voltage(i2c, SEC_VOLTAGE_18, 0); ++ set_input_tone(fe, SEC_TONE_OFF, 3); ++ set_input_tone(fe, SEC_TONE_ON, 2); ++ set_input_tone(fe, SEC_TONE_OFF, 1); ++ set_input_tone(fe, SEC_TONE_ON, 0); ++ break; ++ case 1: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int probe(struct mxl *state) ++{ ++ struct mxl5xx_cfg *cfg = state->base->cfg; ++ u32 chipver; ++ int fw, status, j; ++ MXL_HYDRA_MPEGOUT_PARAM_T mpegInterfaceCfg; ++ ++ fw = firmware_is_alive(state); ++ ++ if (!fw) { ++ // lja ++ SET_REG_FIELD_DATA(PRCM_AFE_REG_CLOCK_ENABLE, 1); ++ //write_register(state, HYDRA_MODULES_CLK_1_REG, 0x0000020b); ++ ++ SET_REG_FIELD_DATA(PRCM_PRCM_AFE_REG_SOFT_RST_N, 1); ++ status = GET_REG_FIELD_DATA(PRCM_CHIP_VERSION, &chipver); ++ if (status) ++ state->base->chipversion = 0; ++ else ++ state->base->chipversion = (chipver == 2) ? 2 : 1; ++ pr_info("Hydra chip version %u\n", state->base->chipversion); ++ ++ ++ ++ cfg_dev_xtal(state, cfg->clk, cfg->cap, 0); ++ ++ status = load_fw(state); ++ if (status) ++ return status; ++ ++ config_dis(state, 0); ++ config_dis(state, 1); ++ config_dis(state, 2); ++ config_dis(state, 3); ++ ++#if 0 ++ config_mux(state); ++ ++ mpegInterfaceCfg.enable = MXL_ENABLE; ++ mpegInterfaceCfg.lsbOrMsbFirst = MXL_HYDRA_MPEG_SERIAL_MSB_1ST; ++ /* supports only (0-104&139)MHz */ ++ mpegInterfaceCfg.maxMpegClkRate = 139; ++ mpegInterfaceCfg.mpegClkPhase = MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_180_DEG; //MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG; ++ mpegInterfaceCfg.mpegClkPol = MXL_HYDRA_MPEG_CLK_IN_PHASE; ++ /* MXL_HYDRA_MPEG_CLK_GAPPED; */ ++ mpegInterfaceCfg.mpegClkType = MXL_HYDRA_MPEG_CLK_CONTINUOUS; ++ mpegInterfaceCfg.mpegErrorIndication = ++ MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED; ++ mpegInterfaceCfg.mpegMode = MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE; ++ mpegInterfaceCfg.mpegSyncPol = MXL_HYDRA_MPEG_ACTIVE_HIGH; ++ mpegInterfaceCfg.mpegSyncPulseWidth = MXL_HYDRA_MPEG_SYNC_WIDTH_BIT; ++ mpegInterfaceCfg.mpegValidPol = MXL_HYDRA_MPEG_ACTIVE_HIGH; ++ ++ for (j = 0; j < 8; j++) { ++ status = config_ts(state, (MXL_HYDRA_DEMOD_ID_E) j, ++ &mpegInterfaceCfg); ++ if (status) ++ return status; ++ } ++#endif ++ ++ // lja ++ write_register(state, 0x90700008, 0x00000005); ++ write_register(state, 0x90000170, 0); ++ write_register(state, 0x90000174, 0); ++ write_register(state, 0x90700044, 0x00030000); ++ write_register(state, 0x90700238, 0x03030303); ++ write_register(state, 0x9070023C, 0x00030303); ++ write_register(state, 0x907001D4, 0x000000ff); ++ write_register(state, 0x90700010, 0x0000ff00); ++ write_register(state, 0x90700014, 0x000000ff); ++ write_register(state, 0x90700018, 0x22222222); ++ write_register(state, 0x9070000C, 0x000000ff); ++ write_register(state, 0x90700000, 0x000000ff); ++ ++ } ++ ++ ++ return 0; ++} ++ ++struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, ++ struct mxl5xx_cfg *cfg, ++ u32 demod) ++{ ++ struct mxl *state; ++ struct mxl_base *base; ++ ++ state = kzalloc(sizeof(struct mxl), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ ++ state->demod = demod; ++ state->rf_in = 0; ++ if(mode) ++ { ++ if((demod ==0)||(demod ==1)) ++ state->rf_in = 3; ++ if((demod ==2)||(demod ==3)) ++ state->rf_in = 2; ++ if((demod ==4)||(demod ==5)) ++ state->rf_in = 1; ++ if((demod ==6)||(demod ==7)) ++ state->rf_in = 0; ++ } ++ state->fe.ops = mxl_ops; ++ state->fe.demodulator_priv = state; ++ ++ base = match_base(i2c, cfg->adr); ++ if (base) { ++ base->count++; ++ state->base = base; ++ } else { ++ base = kzalloc(sizeof(struct mxl_base), GFP_KERNEL); ++ if (!base) ++ goto fail; ++ base->i2c = i2c; ++ base->cfg = cfg; ++ base->adr = cfg->adr; ++ base->type = cfg->type; ++ base->count = 1; ++ mutex_init(&base->i2c_lock); ++ mutex_init(&base->status_lock); ++ state->base = base; ++ if (probe(state) < 0) { ++ kfree(base); ++ goto fail; ++ } ++ ++ init_multisw(state); ++ ++ list_add(&base->mxllist, &mxllist); ++ } ++ ++ ++ return &state->fe; ++ ++fail: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(mxl5xx_attach); ++ ++MODULE_DESCRIPTION("MXL5XX driver"); ++MODULE_AUTHOR("Ralph Metzler"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/dvb-frontends/mxl5xx.h b/drivers/media/dvb-frontends/mxl5xx.h +new file mode 100644 +index 0000000..e4d54e5 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mxl5xx.h +@@ -0,0 +1,41 @@ ++#ifndef _MXL5XX_H_ ++#define _MXL5XX_H_ ++ ++#include ++#include ++ ++struct mxl5xx_cfg { ++ u8 adr; ++ u8 type; ++ u32 cap; ++ u32 clk; ++ ++ u8 *fw; ++ u32 fw_len; ++ ++ int (*fw_read)(void *priv, u8 *buf, u32 len); ++ void *fw_priv; ++ ++ int (*set_voltage)(struct i2c_adapter *i2c, ++ enum fe_sec_voltage voltage, u8 rf_in); ++}; ++ ++#if defined(CONFIG_DVB_MXL5XX) || \ ++ (defined(CONFIG_DVB_MXL5XX_MODULE) && defined(MODULE)) ++ ++extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, ++ struct mxl5xx_cfg *cfg, ++ u32 demod); ++#else ++ ++static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, ++ struct mxl5xx_cfg *cfg, ++ u32 demod) ++{ ++ pr_warn("%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++#endif ++ ++#endif +diff --git a/drivers/media/dvb-frontends/mxl5xx_defs.h b/drivers/media/dvb-frontends/mxl5xx_defs.h +new file mode 100644 +index 0000000..bd13372 +--- /dev/null ++++ b/drivers/media/dvb-frontends/mxl5xx_defs.h +@@ -0,0 +1,836 @@ ++/* ++ * Defines for the Maxlinear MX58x family of tuners/demods ++ * ++ * Copyright (C) 2014 Digital Devices GmbH ++ * ++ * based on code: ++ * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved ++ * which was released under GPL V2 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2, as published by the Free Software Foundation. ++ */ ++ ++typedef enum ++{ ++ MXL_DISABLE = 0, ++ MXL_ENABLE = 1, ++ ++ MXL_FALSE = 0, ++ MXL_TRUE = 1, ++ ++ MXL_INVALID = 0, ++ MXL_VALID = 1, ++ ++ MXL_NO = 0, ++ MXL_YES = 1, ++ ++ MXL_OFF = 0, ++ MXL_ON = 1 ++} MXL_BOOL_E; ++ ++// Firmware-Host Command IDs ++typedef enum ++{ ++ //--Device command IDs-- ++ MXL_HYDRA_DEV_NO_OP_CMD = 0, //No OP ++ ++ MXL_HYDRA_DEV_SET_POWER_MODE_CMD = 1, ++ MXL_HYDRA_DEV_SET_OVERWRITE_DEF_CMD = 2, ++ ++ // Host-used CMD, not used by firmware ++ MXL_HYDRA_DEV_FIRMWARE_DOWNLOAD_CMD = 3, ++ ++ // Additional CONTROL types from DTV ++ MXL_HYDRA_DEV_SET_BROADCAST_PID_STB_ID_CMD = 4, ++ MXL_HYDRA_DEV_GET_PMM_SLEEP_CMD = 5, ++ ++ //--Tuner command IDs-- ++ MXL_HYDRA_TUNER_TUNE_CMD = 6, ++ MXL_HYDRA_TUNER_GET_STATUS_CMD = 7, ++ ++ //--Demod command IDs-- ++ MXL_HYDRA_DEMOD_SET_PARAM_CMD = 8, ++ MXL_HYDRA_DEMOD_GET_STATUS_CMD = 9, ++ ++ MXL_HYDRA_DEMOD_RESET_FEC_COUNTER_CMD = 10, ++ ++ MXL_HYDRA_DEMOD_SET_PKT_NUM_CMD = 11, ++ ++ MXL_HYDRA_DEMOD_SET_IQ_SOURCE_CMD = 12, ++ MXL_HYDRA_DEMOD_GET_IQ_DATA_CMD = 13, ++ ++ MXL_HYDRA_DEMOD_GET_M68HC05_VER_CMD = 14, ++ ++ MXL_HYDRA_DEMOD_SET_ERROR_COUNTER_MODE_CMD = 15, ++ ++ //--- ABORT channel tune ++ MXL_HYDRA_ABORT_TUNE_CMD = 16, // Abort current tune command. ++ ++ //--SWM/FSK command IDs-- ++ MXL_HYDRA_FSK_RESET_CMD = 17, ++ MXL_HYDRA_FSK_MSG_CMD = 18, ++ MXL_HYDRA_FSK_SET_OP_MODE_CMD = 19, ++ ++ //--DiSeqC command IDs-- ++ MXL_HYDRA_DISEQC_MSG_CMD = 20, ++ MXL_HYDRA_DISEQC_COPY_MSG_TO_MAILBOX = 21, ++ MXL_HYDRA_DISEQC_CFG_MSG_CMD = 22, ++ ++ //--- FFT Debug Command IDs-- ++ MXL_HYDRA_REQ_FFT_SPECTRUM_CMD = 23, ++ ++ // -- Demod scramblle code ++ MXL_HYDRA_DEMOD_SCRAMBLE_CODE_CMD = 24, ++ ++ //---For host to know how many commands in total--- ++ MXL_HYDRA_LAST_HOST_CMD = 25, ++ ++ MXL_HYDRA_DEMOD_INTR_TYPE_CMD = 47, ++ MXL_HYDRA_DEV_INTR_CLEAR_CMD = 48, ++ MXL_HYDRA_TUNER_SPECTRUM_REQ_CMD = 53, ++ MXL_HYDRA_TUNER_ACTIVATE_CMD = 55, ++ MXL_HYDRA_DEV_CFG_POWER_MODE_CMD = 56, ++ MXL_HYDRA_DEV_XTAL_CAP_CMD = 57, ++ MXL_HYDRA_DEV_CFG_SKU_CMD = 58, ++ MXL_HYDRA_TUNER_SPECTRUM_MIN_GAIN_CMD = 59, ++ MXL_HYDRA_DISEQC_CONT_TONE_CFG = 60, ++ MXL_HYDRA_DEV_RF_WAKE_UP_CMD = 61, ++ MXL_HYDRA_DEMOD_CFG_EQ_CTRL_PARAM_CMD = 62, ++ MXL_HYDRA_DEMOD_FREQ_OFFSET_SEARCH_RANGE_CMD = 63, ++ MXL_HYDRA_DEV_REQ_PWR_FROM_ADCRSSI_CMD = 64, ++ ++ MXL_XCPU_PID_FLT_CFG_CMD = 65, ++ MXL_XCPU_SHMEM_TEST_CMD = 66, ++ MXL_XCPU_ABORT_TUNE_CMD = 67, ++ MXL_XCPU_CHAN_TUNE_CMD = 68, ++ MXL_XCPU_FLT_BOND_HDRS_CMD = 69, ++ ++ MXL_HYDRA_DEV_BROADCAST_WAKE_UP_CMD = 70, ++ MXL_HYDRA_FSK_CFG_FSK_FREQ_CMD = 71, ++ MXL_HYDRA_FSK_POWER_DOWN_CMD = 72, ++ MXL_XCPU_CLEAR_CB_STATS_CMD = 73, ++ MXL_XCPU_CHAN_BOND_RESTART_CMD = 74 ++} MXL_HYDRA_HOST_CMD_ID_E; ++ ++#define MXL_ENABLE_BIG_ENDIAN (0) ++ ++#define MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH 248 ++ ++#define MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN (248) ++ ++#define MXL_HYDRA_CAP_MIN 10 ++#define MXL_HYDRA_CAP_MAX 33 ++ ++#define MXL_HYDRA_PLID_REG_READ 0xFB // Read register PLID ++#define MXL_HYDRA_PLID_REG_WRITE 0xFC // Write register PLID ++ ++#define MXL_HYDRA_PLID_CMD_READ 0xFD // Command Read PLID ++#define MXL_HYDRA_PLID_CMD_WRITE 0xFE // Command Write PLID ++ ++#define MXL_HYDRA_REG_SIZE_IN_BYTES 4 // Hydra register size in bytes ++#define MXL_HYDRA_I2C_HDR_SIZE (2 * sizeof(u8)) // PLID + LEN(0xFF) ++#define MXL_HYDRA_CMD_HEADER_SIZE (MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE) ++ ++#define MXL_HYDRA_SKU_ID_581 0 ++#define MXL_HYDRA_SKU_ID_584 1 ++#define MXL_HYDRA_SKU_ID_585 2 ++#define MXL_HYDRA_SKU_ID_544 3 ++#define MXL_HYDRA_SKU_ID_561 4 ++#define MXL_HYDRA_SKU_ID_582 5 ++#define MXL_HYDRA_SKU_ID_568 6 ++ ++// macro for register write data buffer size (PLID + LEN (0xFF) + RegAddr + RegData) ++#define MXL_HYDRA_REG_WRITE_LEN (MXL_HYDRA_I2C_HDR_SIZE + (2 * MXL_HYDRA_REG_SIZE_IN_BYTES)) ++ ++// maro to extract a single byte from 4-byte(32-bit) data ++#define GET_BYTE(x,n) (((x) >> (8*(n))) & 0xFF) ++ ++#define MAX_CMD_DATA 512 ++ ++#define MXL_GET_REG_MASK_32(lsbLoc,numOfBits) ((0xFFFFFFFF >> (32 - (numOfBits))) << (lsbLoc)) ++ ++#define GET_REG_FIELD_DATA(fieldName, dataPtr) read_by_mnemonic(state, fieldName, dataPtr); ++#define SET_REG_FIELD_DATA(fieldName, data) update_by_mnemonic(state, fieldName, data); ++ ++#define FW_DL_SIGN (0xDEADBEEF) ++ ++#define MBIN_FORMAT_VERSION '1' ++#define MBIN_FILE_HEADER_ID 'M' ++#define MBIN_SEGMENT_HEADER_ID 'S' ++#define MBIN_MAX_FILE_LENGTH (1<<23) ++ ++typedef struct ++{ ++ u8 id; ++ u8 fmtVersion; ++ u8 headerLen; ++ u8 numSegments; ++ u8 entryAddress[4]; ++ u8 imageSize24[3]; ++ u8 imageChecksum; ++ u8 reserved[4]; ++} MBIN_FILE_HEADER_T; ++ ++typedef struct ++{ ++ MBIN_FILE_HEADER_T header; ++ u8 data[1]; ++} MBIN_FILE_T; ++ ++typedef struct ++{ ++ u8 id; ++ u8 len24[3]; ++ u8 address[4]; ++} MBIN_SEGMENT_HEADER_T; ++ ++ ++typedef struct ++{ ++ MBIN_SEGMENT_HEADER_T header; ++ u8 data[1]; ++} MBIN_SEGMENT_T; ++ ++ ++typedef enum { MXL_CMD_WRITE = 0, MXL_CMD_READ} MXL_CMD_TYPE_E; ++ ++#define BUILD_HYDRA_CMD(cmdID, reqType, size, dataPtr, cmdBuff) \ ++ do { \ ++ cmdBuff[0] = ((reqType == MXL_CMD_WRITE) ? MXL_HYDRA_PLID_CMD_WRITE : MXL_HYDRA_PLID_CMD_READ); \ ++ cmdBuff[1] = (size > 251) ? 0xff : (u8) (size + 4); \ ++ cmdBuff[2] = size; \ ++ cmdBuff[3] = cmdID; \ ++ cmdBuff[4] = 0x00; \ ++ cmdBuff[5] = 0x00; \ ++ convert_endian(MXL_ENABLE_BIG_ENDIAN, size, (u8 *)dataPtr); \ ++ memcpy((void *)&cmdBuff[6], dataPtr, size); \ ++ } while(0) //; ++ ++typedef struct { ++ u32 regAddr; ++ u8 lsbPos; ++ u8 numOfBits; ++} MXL_REG_FIELD_T; ++ ++typedef struct { ++ u32 dataSize; ++ u8 data[MAX_CMD_DATA]; ++} MXL_DEV_CMD_DATA_T; ++ ++typedef enum ++{ ++ MXL_HYDRA_SKU_TYPE_MIN = 0x00, ++ MXL_HYDRA_SKU_TYPE_581 = 0x00, ++ MXL_HYDRA_SKU_TYPE_584 = 0x01, ++ MXL_HYDRA_SKU_TYPE_585 = 0x02, ++ MXL_HYDRA_SKU_TYPE_544 = 0x03, ++ MXL_HYDRA_SKU_TYPE_561 = 0x04, ++ MXL_HYDRA_SKU_TYPE_5xx = 0x05, ++ MXL_HYDRA_SKU_TYPE_5yy = 0x06, ++ MXL_HYDRA_SKU_TYPE_511 = 0x07, ++ MXL_HYDRA_SKU_TYPE_561_DE = 0x08, ++ MXL_HYDRA_SKU_TYPE_582 = 0x09, ++ MXL_HYDRA_SKU_TYPE_541 = 0x0A, ++ MXL_HYDRA_SKU_TYPE_568 = 0x0B, ++ MXL_HYDRA_SKU_TYPE_542 = 0x0C, ++ MXL_HYDRA_SKU_TYPE_MAX = 0x0D, ++} MXL_HYDRA_SKU_TYPE_E; ++ ++typedef struct ++{ ++ MXL_HYDRA_SKU_TYPE_E skuType; ++} MXL_HYDRA_SKU_COMMAND_T; ++ ++ ++typedef enum ++{ ++ MXL_HYDRA_DEMOD_ID_0 = 0, ++ MXL_HYDRA_DEMOD_ID_1, ++ MXL_HYDRA_DEMOD_ID_2, ++ MXL_HYDRA_DEMOD_ID_3, ++ MXL_HYDRA_DEMOD_ID_4, ++ MXL_HYDRA_DEMOD_ID_5, ++ MXL_HYDRA_DEMOD_ID_6, ++ MXL_HYDRA_DEMOD_ID_7, ++ MXL_HYDRA_DEMOD_MAX ++} MXL_HYDRA_DEMOD_ID_E; ++ ++#define MXL_DEMOD_SCRAMBLE_SEQ_LEN 12 ++ ++#define MAX_STEP_SIZE_24_XTAL_102_05_KHZ 195 ++#define MAX_STEP_SIZE_24_XTAL_204_10_KHZ 215 ++#define MAX_STEP_SIZE_24_XTAL_306_15_KHZ 203 ++#define MAX_STEP_SIZE_24_XTAL_408_20_KHZ 177 ++ ++#define MAX_STEP_SIZE_27_XTAL_102_05_KHZ 195 ++#define MAX_STEP_SIZE_27_XTAL_204_10_KHZ 215 ++#define MAX_STEP_SIZE_27_XTAL_306_15_KHZ 203 ++#define MAX_STEP_SIZE_27_XTAL_408_20_KHZ 177 ++ ++#define MXL_HYDRA_SPECTRUM_MIN_FREQ_KHZ 300000 ++#define MXL_HYDRA_SPECTRUM_MAX_FREQ_KHZ 2350000 ++ ++typedef enum ++{ ++ DMD_STANDARD_ADDR = 0, ++ DMD_SPECTRUM_INVERSION_ADDR, ++ DMD_SPECTRUM_ROLL_OFF_ADDR, ++ DMD_SYMBOL_RATE_ADDR, ++ DMD_MODULATION_SCHEME_ADDR, ++ DMD_FEC_CODE_RATE_ADDR, ++ DMD_SNR_ADDR, ++ DMD_FREQ_OFFSET_ADDR, ++ DMD_CTL_FREQ_OFFSET_ADDR, ++ DMD_STR_FREQ_OFFSET_ADDR, ++ DMD_FTL_FREQ_OFFSET_ADDR, ++ DMD_STR_NBC_SYNC_LOCK_ADDR, ++ DMD_CYCLE_SLIP_COUNT_ADDR, ++ DMD_DISPLAY_IQ_ADDR, ++ DMD_DVBS2_CRC_ERRORS_ADDR, ++ DMD_DVBS2_PER_COUNT_ADDR, ++ DMD_DVBS2_PER_WINDOW_ADDR, ++ DMD_DVBS_CORR_RS_ERRORS_ADDR, ++ DMD_DVBS_UNCORR_RS_ERRORS_ADDR, ++ DMD_DVBS_BER_COUNT_ADDR, ++ DMD_DVBS_BER_WINDOW_ADDR, ++ DMD_TUNER_ID_ADDR, ++ DMD_DVBS2_PILOT_ON_OFF_ADDR, ++ DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR, ++ ++ MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE, ++} MXL_DEMOD_CHAN_PARAMS_OFFSET_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TUNER_ID_0 = 0, ++ MXL_HYDRA_TUNER_ID_1, ++ MXL_HYDRA_TUNER_ID_2, ++ MXL_HYDRA_TUNER_ID_3, ++ MXL_HYDRA_TUNER_MAX ++} MXL_HYDRA_TUNER_ID_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_DSS = 0, ++ MXL_HYDRA_DVBS, ++ MXL_HYDRA_DVBS2, ++} MXL_HYDRA_BCAST_STD_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_FEC_AUTO = 0, ++ MXL_HYDRA_FEC_1_2, ++ MXL_HYDRA_FEC_3_5, ++ MXL_HYDRA_FEC_2_3, ++ MXL_HYDRA_FEC_3_4, ++ MXL_HYDRA_FEC_4_5, ++ MXL_HYDRA_FEC_5_6, ++ MXL_HYDRA_FEC_6_7, ++ MXL_HYDRA_FEC_7_8, ++ MXL_HYDRA_FEC_8_9, ++ MXL_HYDRA_FEC_9_10, ++} MXL_HYDRA_FEC_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_MOD_AUTO = 0, ++ MXL_HYDRA_MOD_QPSK, ++ MXL_HYDRA_MOD_8PSK ++} MXL_HYDRA_MODULATION_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_SPECTRUM_AUTO = 0, ++ MXL_HYDRA_SPECTRUM_INVERTED, ++ MXL_HYDRA_SPECTRUM_NON_INVERTED, ++} MXL_HYDRA_SPECTRUM_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_ROLLOFF_AUTO = 0, ++ MXL_HYDRA_ROLLOFF_0_20, ++ MXL_HYDRA_ROLLOFF_0_25, ++ MXL_HYDRA_ROLLOFF_0_35 ++} MXL_HYDRA_ROLLOFF_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_PILOTS_OFF = 0, ++ MXL_HYDRA_PILOTS_ON, ++ MXL_HYDRA_PILOTS_AUTO ++} MXL_HYDRA_PILOTS_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_FORMATTER = 0, ++ MXL_HYDRA_LEGACY_FEC, ++ MXL_HYDRA_FREQ_RECOVERY, ++ MXL_HYDRA_NBC, ++ MXL_HYDRA_CTL, ++ MXL_HYDRA_EQ, ++} MXL_HYDRA_CONSTELLATION_SRC_E; ++ ++typedef struct ++{ ++ int agcLock; // AGC lock info ++ int fecLock; // Demod FEC block lock info ++} MXL_HYDRA_DEMOD_LOCK_T; ++ ++typedef struct ++{ ++ u32 rsErrors; // RS decoder err counter ++ u32 berWindow; // Ber Windows ++ u32 berCount; // BER count ++ u32 berWindow_Iter1; // Ber Windows - post viterbi ++ u32 berCount_Iter1; // BER count - post viterbi ++} MXL_HYDRA_DEMOD_STATUS_DVBS_T; ++ ++typedef struct ++{ ++ u32 rsErrors; // RS decoder err counter ++ u32 berWindow; // Ber Windows ++ u32 berCount; // BER count ++} MXL_HYDRA_DEMOD_STATUS_DSS_T; ++ ++typedef struct ++{ ++ u32 crcErrors; // CRC error counter ++ u32 packetErrorCount; // Number of packet errors ++ u32 totalPackets; // Total packets ++} MXL_HYDRA_DEMOD_STATUS_DVBS2_T; ++ ++typedef struct ++{ ++ MXL_HYDRA_BCAST_STD_E standardMask; // Standard DVB-S, DVB-S2 or DSS ++ ++ union ++ { ++ MXL_HYDRA_DEMOD_STATUS_DVBS_T demodStatus_DVBS; // DVB-S demod status ++ MXL_HYDRA_DEMOD_STATUS_DVBS2_T demodStatus_DVBS2; // DVB-S2 demod status ++ MXL_HYDRA_DEMOD_STATUS_DSS_T demodStatus_DSS; // DSS demod status ++ } u; ++ ++} MXL_HYDRA_DEMOD_STATUS_T; ++ ++typedef struct ++{ ++ s32 carrierOffsetInHz; // CRL offset info ++ s32 symbolOffsetInSymbol; // SRL offset info ++} MXL_HYDRA_DEMOD_SIG_OFFSET_INFO_T; ++ ++typedef struct ++{ ++ u8 scrambleSequence[MXL_DEMOD_SCRAMBLE_SEQ_LEN]; // scramble sequence ++ u32 scrambleCode; // scramble gold code ++} MXL_HYDRA_DEMOD_SCRAMBLE_INFO_T; ++ ++typedef enum ++{ ++ MXL_HYDRA_STEP_SIZE_24_XTAL_102_05KHZ, // 102.05 KHz for 24 MHz XTAL ++ MXL_HYDRA_STEP_SIZE_24_XTAL_204_10KHZ, // 204.10 KHz for 24 MHz XTAL ++ MXL_HYDRA_STEP_SIZE_24_XTAL_306_15KHZ, // 306.15 KHz for 24 MHz XTAL ++ MXL_HYDRA_STEP_SIZE_24_XTAL_408_20KHZ, // 408.20 KHz for 24 MHz XTAL ++ ++ MXL_HYDRA_STEP_SIZE_27_XTAL_102_05KHZ, // 102.05 KHz for 27 MHz XTAL ++ MXL_HYDRA_STEP_SIZE_27_XTAL_204_35KHZ, // 204.35 KHz for 27 MHz XTAL ++ MXL_HYDRA_STEP_SIZE_27_XTAL_306_52KHZ, // 306.52 KHz for 27 MHz XTAL ++ MXL_HYDRA_STEP_SIZE_27_XTAL_408_69KHZ, // 408.69 KHz for 27 MHz XTAL ++ ++} MXL_HYDRA_SPECTRUM_STEP_SIZE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_SPECTRUM_RESOLUTION_00_1_DB, // 0.1 dB ++ MXL_HYDRA_SPECTRUM_RESOLUTION_01_0_DB, // 1.0 dB ++ MXL_HYDRA_SPECTRUM_RESOLUTION_05_0_DB, // 5.0 dB ++ MXL_HYDRA_SPECTRUM_RESOLUTION_10_0_DB, // 10 dB ++} MXL_HYDRA_SPECTRUM_RESOLUTION_E; ++ ++typedef enum ++{ ++ MXL_SPECTRUM_NO_ERROR, ++ MXL_SPECTRUM_INVALID_PARAMETER, ++ MXL_SPECTRUM_INVALID_STEP_SIZE, ++ MXL_SPECTRUM_BW_CANNOT_BE_COVERED, ++ MXL_SPECTRUM_DEMOD_BUSY, ++ MXL_SPECTRUM_TUNER_NOT_ENABLED, ++ ++} MXL_HYDRA_SPECTRUM_ERROR_CODE_E; ++ ++typedef struct ++{ ++ u32 tunerIndex; // TUNER Ctrl: one of MXL58x_TUNER_ID_E ++ u32 demodIndex; // DEMOD Ctrl: one of MXL58x_DEMOD_ID_E ++ MXL_HYDRA_SPECTRUM_STEP_SIZE_E stepSizeInKHz; ++ u32 startingFreqInkHz; ++ u32 totalSteps; ++ MXL_HYDRA_SPECTRUM_RESOLUTION_E spectrumDivision; ++} MXL_HYDRA_SPECTRUM_REQ_T; ++ ++typedef enum ++{ ++ MXL_HYDRA_SEARCH_MAX_OFFSET = 0, // DMD searches for max freq offset (i.e. 5MHz) ++ MXL_HYDRA_SEARCH_BW_PLUS_ROLLOFF, // DMD searches for BW + ROLLOFF/2 ++} MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E; ++ ++typedef struct ++{ ++ u32 demodIndex; ++ MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E searchType; ++} MXL58x_CFG_FREQ_OFF_SEARCH_RANGE_T; ++ ++ ++ ++ ++// there are two slices ++// slice0 - TS0, TS1, TS2 & TS3 ++// slice1 - TS4, TS5, TS6 & TS7 ++#define MXL_HYDRA_TS_SLICE_MAX 2 ++ ++#define MAX_FIXED_PID_NUM 32 ++ ++#define MXL_HYDRA_NCO_CLK 418 // 418 MHz ++ ++#define MXL_HYDRA_MAX_TS_CLOCK 139 // 139 MHz ++ ++#define MXL_HYDRA_TS_FIXED_PID_FILT_SIZE 32 ++ ++#define MXL_HYDRA_SHARED_PID_FILT_SIZE_DEFAULT 33 // Shared PID filter size in 1-1 mux mode ++#define MXL_HYDRA_SHARED_PID_FILT_SIZE_2_TO_1 66 // Shared PID filter size in 2-1 mux mode ++#define MXL_HYDRA_SHARED_PID_FILT_SIZE_4_TO_1 132 // Shared PID filter size in 4-1 mux mode ++ ++typedef enum ++{ ++ MXL_HYDRA_SOFTWARE_PID_BANK = 0, ++ MXL_HYDRA_HARDWARE_PID_BANK, ++} MXL_HYDRA_PID_BANK_TYPE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TS_MUX_PID_REMAP = 0, ++ MXL_HYDRA_TS_MUX_PREFIX_EXTRA_HEADER = 1, ++} MXL_HYDRA_TS_MUX_MODE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TS_MUX_DISABLE = 0, // No Mux ( 1 TSIF to 1 TSIF) ++ MXL_HYDRA_TS_MUX_2_TO_1, // Mux 2 TSIF to 1 TSIF ++ MXL_HYDRA_TS_MUX_4_TO_1, // Mux 4 TSIF to 1 TSIF ++} MXL_HYDRA_TS_MUX_TYPE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TS_GROUP_0_3 = 0, // TS group 0 to 3 (TS0, TS1, TS2 & TS3) ++ MXL_HYDRA_TS_GROUP_4_7, // TS group 0 to 3 (TS4, TS5, TS6 & TS7) ++} MXL_HYDRA_TS_GROUP_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TS_PIDS_ALLOW_ALL = 0, // Allow all pids ++ MXL_HYDRA_TS_PIDS_DROP_ALL, // Drop all pids ++ MXL_HYDRA_TS_INVALIDATE_PID_FILTER, // Delete current PD filter in the device ++ ++} MXL_HYDRA_TS_PID_FLT_CTRL_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TS_PID_FIXED = 0, ++ MXL_HYDRA_TS_PID_REGULAR, ++} MXL_HYDRA_TS_PID_TYPE_E; ++ ++typedef struct ++{ ++ u16 originalPid; // pid from TS ++ u16 remappedPid; // remapped pid ++ MXL_BOOL_E enable; // enable or disable pid ++ MXL_BOOL_E allowOrDrop; // allow or drop pid ++ MXL_BOOL_E enablePidRemap; // enable or disable pid remap ++ u8 bondId; // Bond ID in A0 always 0 - Only for 568 Sku ++ u8 destId; // Output port ID for the PID - Only for 568 Sku ++} MXL_HYDRA_TS_PID_T; ++ ++typedef struct ++{ ++ MXL_BOOL_E enable; ++ u8 numByte; ++ u8 header[12]; ++} MXL_HYDRA_TS_MUX_PREFIX_HEADER_T; ++ ++typedef enum ++{ ++ MXL_HYDRA_PID_BANK_A = 0, ++ MXL_HYDRA_PID_BANK_B, ++} MXL_HYDRA_PID_FILTER_BANK_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_MPEG_SERIAL_MSB_1ST = 0, ++ MXL_HYDRA_MPEG_SERIAL_LSB_1ST, ++ ++ MXL_HYDRA_MPEG_SYNC_WIDTH_BIT = 0, ++ MXL_HYDRA_MPEG_SYNC_WIDTH_BYTE ++} MXL_HYDRA_MPEG_DATA_FMT_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_MPEG_MODE_SERIAL_4_WIRE = 0, // MPEG 4 Wire serial mode ++ MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE, // MPEG 3 Wire serial mode ++ MXL_HYDRA_MPEG_MODE_SERIAL_2_WIRE, // MPEG 2 Wire serial mode ++ MXL_HYDRA_MPEG_MODE_PARALLEL // MPEG parallel mode - valid only for MxL581 ++} MXL_HYDRA_MPEG_MODE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_MPEG_CLK_CONTINUOUS = 0, // Continuous MPEG clock ++ MXL_HYDRA_MPEG_CLK_GAPPED, // Gapped (gated) MPEG clock ++} MXL_HYDRA_MPEG_CLK_TYPE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_MPEG_ACTIVE_LOW = 0, ++ MXL_HYDRA_MPEG_ACTIVE_HIGH, ++ ++ MXL_HYDRA_MPEG_CLK_NEGATIVE = 0, ++ MXL_HYDRA_MPEG_CLK_POSITIVE, ++ ++ MXL_HYDRA_MPEG_CLK_IN_PHASE = 0, ++ MXL_HYDRA_MPEG_CLK_INVERTED, ++} MXL_HYDRA_MPEG_CLK_FMT_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG = 0, ++ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_90_DEG, ++ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_180_DEG, ++ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_270_DEG ++} MXL_HYDRA_MPEG_CLK_PHASE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_MPEG_ERR_REPLACE_SYNC = 0, ++ MXL_HYDRA_MPEG_ERR_REPLACE_VALID, ++ MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED ++} MXL_HYDRA_MPEG_ERR_INDICATION_E; ++ ++typedef struct ++{ ++ int enable; // Enable or Disable MPEG OUT ++ MXL_HYDRA_MPEG_CLK_TYPE_E mpegClkType; // Continuous or gapped ++ MXL_HYDRA_MPEG_CLK_FMT_E mpegClkPol; // MPEG Clk polarity ++ u8 maxMpegClkRate; // Max MPEG Clk rate (0 – 104 MHz, 139 MHz) ++ MXL_HYDRA_MPEG_CLK_PHASE_E mpegClkPhase; // MPEG Clk phase ++ MXL_HYDRA_MPEG_DATA_FMT_E lsbOrMsbFirst; // LSB first or MSB first in TS transmission ++ MXL_HYDRA_MPEG_DATA_FMT_E mpegSyncPulseWidth; // MPEG SYNC pulse width (1-bit or 1-byte) ++ MXL_HYDRA_MPEG_CLK_FMT_E mpegValidPol; // MPEG VALID polarity ++ MXL_HYDRA_MPEG_CLK_FMT_E mpegSyncPol; // MPEG SYNC polarity ++ MXL_HYDRA_MPEG_MODE_E mpegMode; // config 4/3/2-wire serial or parallel TS out ++ MXL_HYDRA_MPEG_ERR_INDICATION_E mpegErrorIndication; // Enable or Disable MPEG error indication ++} MXL_HYDRA_MPEGOUT_PARAM_T; ++ ++typedef enum ++{ ++ MXL_HYDRA_EXT_TS_IN_0 = 0, ++ MXL_HYDRA_EXT_TS_IN_1, ++ MXL_HYDRA_EXT_TS_IN_2, ++ MXL_HYDRA_EXT_TS_IN_3, ++ MXL_HYDRA_EXT_TS_IN_MAX ++ ++} MXL_HYDRA_EXT_TS_IN_ID_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TS_OUT_0 = 0, ++ MXL_HYDRA_TS_OUT_1, ++ MXL_HYDRA_TS_OUT_2, ++ MXL_HYDRA_TS_OUT_3, ++ MXL_HYDRA_TS_OUT_4, ++ MXL_HYDRA_TS_OUT_5, ++ MXL_HYDRA_TS_OUT_6, ++ MXL_HYDRA_TS_OUT_7, ++ MXL_HYDRA_TS_OUT_MAX ++ ++} MXL_HYDRA_TS_OUT_ID_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_TS_DRIVE_STRENGTH_1x = 0, ++ MXL_HYDRA_TS_DRIVE_STRENGTH_2x, ++ MXL_HYDRA_TS_DRIVE_STRENGTH_3x, ++ MXL_HYDRA_TS_DRIVE_STRENGTH_4x, ++ MXL_HYDRA_TS_DRIVE_STRENGTH_5x, ++ MXL_HYDRA_TS_DRIVE_STRENGTH_6x, ++ MXL_HYDRA_TS_DRIVE_STRENGTH_7x, ++ MXL_HYDRA_TS_DRIVE_STRENGTH_8x ++ ++} MXL_HYDRA_TS_DRIVE_STRENGTH_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_DEVICE_581 = 0, ++ MXL_HYDRA_DEVICE_584, ++ MXL_HYDRA_DEVICE_585, ++ MXL_HYDRA_DEVICE_544, ++ MXL_HYDRA_DEVICE_561, ++ MXL_HYDRA_DEVICE_TEST, ++ MXL_HYDRA_DEVICE_582, ++ MXL_HYDRA_DEVICE_541, ++ MXL_HYDRA_DEVICE_568, ++ MXL_HYDRA_DEVICE_542, ++ MXL_HYDRA_DEVICE_541S, ++ MXL_HYDRA_DEVICE_561S, ++ MXL_HYDRA_DEVICE_581S, ++ MXL_HYDRA_DEVICE_MAX ++} MXL_HYDRA_DEVICE_E; ++ ++ ++// Demod IQ data ++typedef struct ++{ ++ u32 demodId; ++ u32 sourceOfIQ; // ==0, it means I/Q comes from Formatter ++ // ==1, Legacy FEC ++ // ==2, Frequency Recovery ++ // ==3, NBC ++ // ==4, CTL ++ // ==5, EQ ++ // ==6, FPGA ++} MXL_HYDRA_DEMOD_IQ_SRC_T; ++ ++typedef struct ++{ ++ u32 demodId; ++} MXL_HYDRA_DEMOD_ABORT_TUNE_T; ++ ++typedef struct ++{ ++ u8 tunerId; ++ u8 enable; ++} MxL_HYDRA_TUNER_CMD; ++ ++// Demod Para for Channel Tune ++typedef struct ++{ ++ u32 tunerIndex; ++ u32 demodIndex; ++ u32 frequencyInHz; // Frequency ++ u32 standard; // one of MXL_HYDRA_BCAST_STD_E ++ u32 spectrumInversion; // Input : Spectrum inversion. ++ u32 rollOff; /* rollOff (alpha) factor */ ++ u32 symbolRateInHz; /* Symbol rate */ ++ u32 pilots; /* TRUE = pilots enabled */ ++ u32 modulationScheme; // Input : Modulation Scheme is one of MXL_HYDRA_MODULATION_E ++ u32 fecCodeRate; // Input : Forward error correction rate. Is one of MXL_HYDRA_FEC_E ++ u32 maxCarrierOffsetInMHz; // Maximum carrier freq offset in MHz. Same as freqSearchRangeKHz, but in unit of MHz. ++} MXL_HYDRA_DEMOD_PARAM_T; ++ ++typedef struct ++{ ++ u32 demodIndex; ++ u8 scrambleSequence[12]; // scramble sequence ++ u32 scrambleCode; // scramble gold code ++} MXL_HYDRA_DEMOD_SCRAMBLE_CODE_T; ++ ++typedef struct ++{ ++ u32 intrType; ++ u32 intrDurationInNanoSecs; ++ u32 intrMask; ++} MXL_INTR_CFG_T; ++ ++typedef struct ++{ ++ u8 powerMode; // enumeration values are defined in MXL_HYDRA_PWR_MODE_E (device API.h) ++} MxL_HYDRA_POWER_MODE_CMD; ++ ++ ++typedef struct ++{ ++ u32 timeIntervalInSeconds; // in seconds ++ u32 tunerIndex; ++ s32 rssiThreshold; ++ ++} MXL_HYDRA_RF_WAKEUP_PARAM_T; ++ ++typedef struct ++{ ++ u32 tunerCount; ++ MXL_HYDRA_RF_WAKEUP_PARAM_T params; ++} MXL_HYDRA_RF_WAKEUP_CFG_T; ++ ++ ++typedef enum ++{ ++ MXL_HYDRA_AUX_CTRL_MODE_FSK = 0, // Select FSK controller ++ MXL_HYDRA_AUX_CTRL_MODE_DISEQC, // Select DiSEqC controller ++} MXL_HYDRA_AUX_CTRL_MODE_E; ++ ++ ++typedef enum ++{ ++ MXL_HYDRA_DISEQC_ENVELOPE_MODE = 0, ++ MXL_HYDRA_DISEQC_TONE_MODE, ++} MXL_HYDRA_DISEQC_OPMODE_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_DISEQC_1_X = 0, // Config DiSEqC 1.x mode ++ MXL_HYDRA_DISEQC_2_X, // Config DiSEqC 2.x mode ++ MXL_HYDRA_DISEQC_DISABLE // Disable DiSEqC ++} MXL_HYDRA_DISEQC_VER_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_DISEQC_CARRIER_FREQ_22KHZ= 0, // DiSEqC signal frequency of 22 KHz ++ MXL_HYDRA_DISEQC_CARRIER_FREQ_33KHZ, // DiSEqC signal frequency of 33 KHz ++ MXL_HYDRA_DISEQC_CARRIER_FREQ_44KHZ // DiSEqC signal frequency of 44 KHz ++} MXL_HYDRA_DISEQC_CARRIER_FREQ_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_DISEQC_ID_0 = 0, ++ MXL_HYDRA_DISEQC_ID_1, ++ MXL_HYDRA_DISEQC_ID_2, ++ MXL_HYDRA_DISEQC_ID_3 ++} MXL_HYDRA_DISEQC_ID_E; ++ ++typedef enum ++{ ++ MXL_HYDRA_FSK_CFG_TYPE_39KPBS = 0, // 39.0kbps ++ MXL_HYDRA_FSK_CFG_TYPE_39_017KPBS, // 39.017kbps ++ MXL_HYDRA_FSK_CFG_TYPE_115_2KPBS // 115.2kbps ++} MXL_HYDRA_FSK_OP_MODE_E; ++ ++ ++typedef struct ++{ ++ u32 diseqcId; // DSQ 0, 1, 2 or 3 ++ u32 opMode; // Envelope mode (0) or internal tone mode (1) ++ u32 version; // 0: 1.0 , 1: 1.1 , 2: Disable ++ u32 centerFreq; // 0: 22KHz, 1: 33KHz and 2: 44 KHz ++}MXL58x_DSQ_OP_MODE_T; ++ ++typedef struct ++{ ++ u32 diseqcId; ++ u32 contToneFlag; // 1: Enable , 0: Disable ++} MXL_HYDRA_DISEQC_CFG_CONT_TONE_T; ++ ++#define MXL_HYDRA_DISEQC_MAX_PKT_SIZE (32) ++ ++typedef enum ++{ ++ MXL_HYDRA_DISEQC_TONE_NONE = 0, ++ MXL_HYDRA_DISEQC_TONE_SA, ++ MXL_HYDRA_DISEQC_TONE_SB ++} MXL_HYDRA_DISEQC_TONE_CTRL_E; ++ ++typedef struct ++{ ++ u32 diseqcId; ++ u32 nbyte; ++ u8 bufMsg[MXL_HYDRA_DISEQC_MAX_PKT_SIZE]; ++ MXL_HYDRA_DISEQC_TONE_CTRL_E toneBurst; ++} MXL_HYDRA_DISEQC_TX_MSG_T; ++ +diff --git a/drivers/media/dvb-frontends/mxl5xx_regs.h b/drivers/media/dvb-frontends/mxl5xx_regs.h +new file mode 100644 +index 0000000..e983d0b +--- /dev/null ++++ b/drivers/media/dvb-frontends/mxl5xx_regs.h +@@ -0,0 +1,941 @@ ++/* ++* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved ++* ++* License type: GPLv2 ++* ++* 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. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ++* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with ++* this program; if not, write to the Free Software Foundation, Inc., ++* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ++* ++* This program may alternatively be licensed under a proprietary license from ++* MaxLinear, Inc. ++* ++* See terms and conditions defined in file 'LICENSE.txt', which is part of this ++* source code package. ++*/ ++ ++#ifndef __MXL58X_REGISTERS_H__ ++#define __MXL58X_REGISTERS_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HYDRA_INTR_STATUS_REG 0x80030008 ++#define HYDRA_INTR_MASK_REG 0x8003000C ++ ++#define HYDRA_CRYSTAL_SETTING 0x3FFFC5F0 // 0 - 24 MHz & 1 - 27 MHz ++#define HYDRA_CRYSTAL_CAP 0x3FFFEDA4 // 0 - 24 MHz & 1 - 27 MHz ++ ++#define HYDRA_CPU_RESET_REG 0x8003003C ++#define HYDRA_CPU_RESET_DATA 0x00000400 ++ ++#define HYDRA_RESET_TRANSPORT_FIFO_REG 0x80030028 ++#define HYDRA_RESET_TRANSPORT_FIFO_DATA 0x00000000 ++ ++#define HYDRA_RESET_BBAND_REG 0x80030024 ++#define HYDRA_RESET_BBAND_DATA 0x00000000 ++ ++#define HYDRA_RESET_XBAR_REG 0x80030020 ++#define HYDRA_RESET_XBAR_DATA 0x00000000 ++ ++#define HYDRA_MODULES_CLK_1_REG 0x80030014 ++#define HYDRA_DISABLE_CLK_1 0x00000000 ++ ++#define HYDRA_MODULES_CLK_2_REG 0x8003001C ++#define HYDRA_DISABLE_CLK_2 0x0000000B ++ ++#define HYDRA_PRCM_ROOT_CLK_REG 0x80030018 ++#define HYDRA_PRCM_ROOT_CLK_DISABLE 0x00000000 ++ ++#define HYDRA_CPU_RESET_CHECK_REG 0x80030008 ++#define HYDRA_CPU_RESET_CHECK_OFFSET 0x40000000 // ++ ++#define HYDRA_SKU_ID_REG 0x90000190 ++ ++#define FW_DL_SIGN_ADDR 0x3FFFEAE0 ++ ++// Register to check if FW is running or not ++#define HYDRA_HEAR_BEAT 0x3FFFEDDC ++ ++// Firmware version ++#define HYDRA_FIRMWARE_VERSION 0x3FFFEDB8 ++#define HYDRA_FW_RC_VERSION 0x3FFFCFAC ++ ++// Firmware patch version ++#define HYDRA_FIRMWARE_PATCH_VERSION 0x3FFFEDC2 ++ ++// SOC operating temperature in C ++#define HYDRA_TEMPARATURE 0x3FFFEDB4 ++ ++// Demod & Tuner status registers ++// Demod 0 status base address ++#define HYDRA_DEMOD_0_BASE_ADDR 0x3FFFC64C ++ ++// Tuner 0 status base address ++#define HYDRA_TUNER_0_BASE_ADDR 0x3FFFCE4C ++ ++#define POWER_FROM_ADCRSSI_READBACK 0x3FFFEB6C ++ ++// Macros to determine base address of respective demod or tuner ++#define HYDRA_DMD_STATUS_OFFSET(demodID) ((demodID) * 0x100) ++#define HYDRA_TUNER_STATUS_OFFSET(tunerID) ((tunerID) * 0x40) ++ ++// Demod status address offset from respective demod's base address ++#define HYDRA_DMD_AGC_DIG_LEVEL_ADDR_OFFSET 0x3FFFC64C ++#define HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET 0x3FFFC650 ++#define HYDRA_DMD_ACQ_STATUS_ADDR_OFFSET 0x3FFFC654 ++ ++#define HYDRA_DMD_STANDARD_ADDR_OFFSET 0x3FFFC658 ++#define HYDRA_DMD_SPECTRUM_INVERSION_ADDR_OFFSET 0x3FFFC65C ++#define HYDRA_DMD_SPECTRUM_ROLL_OFF_ADDR_OFFSET 0x3FFFC660 ++#define HYDRA_DMD_SYMBOL_RATE_ADDR_OFFSET 0x3FFFC664 ++#define HYDRA_DMD_MODULATION_SCHEME_ADDR_OFFSET 0x3FFFC668 ++#define HYDRA_DMD_FEC_CODE_RATE_ADDR_OFFSET 0x3FFFC66C ++ ++#define HYDRA_DMD_SNR_ADDR_OFFSET 0x3FFFC670 ++#define HYDRA_DMD_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC674 ++#define HYDRA_DMD_CTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC678 ++#define HYDRA_DMD_STR_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC67C ++#define HYDRA_DMD_FTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC680 ++#define HYDRA_DMD_STR_NBC_SYNC_LOCK_ADDR_OFFSET 0x3FFFC684 ++#define HYDRA_DMD_CYCLE_SLIP_COUNT_ADDR_OFFSET 0x3FFFC688 ++ ++#define HYDRA_DMD_DISPLAY_I_ADDR_OFFSET 0x3FFFC68C ++#define HYDRA_DMD_DISPLAY_Q_ADDR_OFFSET 0x3FFFC68E ++ ++#define HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET 0x3FFFC690 ++#define HYDRA_DMD_DVBS2_PER_COUNT_ADDR_OFFSET 0x3FFFC694 ++#define HYDRA_DMD_DVBS2_PER_WINDOW_ADDR_OFFSET 0x3FFFC698 ++ ++#define HYDRA_DMD_DVBS_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC69C ++#define HYDRA_DMD_DVBS_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6A0 ++#define HYDRA_DMD_DVBS_BER_COUNT_ADDR_OFFSET 0x3FFFC6A4 ++#define HYDRA_DMD_DVBS_BER_WINDOW_ADDR_OFFSET 0x3FFFC6A8 ++ ++// Debug-purpose DVB-S DMD 0 ++#define HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6C8 // corrected RS Errors: 1st iteration ++#define HYDRA_DMD_DVBS_1ST_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6CC // uncorrected RS Errors: 1st iteration ++#define HYDRA_DMD_DVBS_BER_COUNT_1ST_ADDR_OFFSET 0x3FFFC6D0 ++#define HYDRA_DMD_DVBS_BER_WINDOW_1ST_ADDR_OFFSET 0x3FFFC6D4 ++ ++#define HYDRA_DMD_TUNER_ID_ADDR_OFFSET 0x3FFFC6AC ++#define HYDRA_DMD_DVBS2_PILOT_ON_OFF_ADDR_OFFSET 0x3FFFC6B0 ++#define HYDRA_DMD_FREQ_SEARCH_RANGE_KHZ_ADDR_OFFSET 0x3FFFC6B4 ++#define HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET 0x3FFFC6B8 ++#define HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR 0x3FFFC704 ++#define HYDRA_DMD_STATUS_INPUT_POWER_ADDR 0x3FFFC708 ++ ++// DVB-S new scaled_BER_count for a new BER API, see HYDRA-1343 "DVB-S post viterbi information" ++#define DMD0_STATUS_DVBS_1ST_SCALED_BER_COUNT_ADDR 0x3FFFC710 // DMD 0: 1st iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR ++#define DMD0_STATUS_DVBS_SCALED_BER_COUNT_ADDR 0x3FFFC714 // DMD 0: 2nd iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR ++ ++#define DMD0_SPECTRUM_MIN_GAIN_STATUS 0x3FFFC73C ++#define DMD0_SPECTRUM_MIN_GAIN_WB_SAGC_VALUE 0x3FFFC740 ++#define DMD0_SPECTRUM_ MIN_GAIN_NB_SAGC_VALUE 0x3FFFC744 ++ ++#define HYDRA_DMD_STATUS_END_ADDR_OFFSET 0x3FFFC748 ++ ++// Tuner status address offset from respective tuners's base address ++#define HYDRA_TUNER_DEMOD_ID_ADDR_OFFSET 0x3FFFCE4C ++#define HYDRA_TUNER_AGC_LOCK_OFFSET 0x3FFFCE50 ++#define HYDRA_TUNER_SPECTRUM_STATUS_OFFSET 0x3FFFCE54 ++#define HYDRA_TUNER_SPECTRUM_BIN_SIZE_OFFSET 0x3FFFCE58 ++#define HYDRA_TUNER_SPECTRUM_ADDRESS_OFFSET 0x3FFFCE5C ++#define HYDRA_TUNER_ENABLE_COMPLETE 0x3FFFEB78 ++ ++#define HYDRA_DEMOD_STATUS_LOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_YES) ++#define HYDRA_DEMOD_STATUS_UNLOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_NO) ++ ++#define HYDRA_TUNER_STATUS_LOCK(devId,tunerId) MxLWare_HYDRA_WriteRegister(devId,(HYDRA_TUNER_STATUS_LOCK_ADDR_OFFSET + HYDRA_TUNER_STATUS_OFFSET(tunerId)), MXL_YES) ++#define HYDRA_TUNER_STATUS_UNLOCK(devId,tunerId) MxLWare_HYDRA_WriteRegister(devId,(HYDRA_TUNER_STATUS_LOCK_ADDR_OFFSET + HYDRA_TUNER_STATUS_OFFSET(tunerId)), MXL_NO) ++ ++#define HYDRA_VERSION 0x3FFFEDB8 ++#define HYDRA_DEMOD0_VERSION 0x3FFFEDBC ++#define HYDRA_DEMOD1_VERSION 0x3FFFEDC0 ++#define HYDRA_DEMOD2_VERSION 0x3FFFEDC4 ++#define HYDRA_DEMOD3_VERSION 0x3FFFEDC8 ++#define HYDRA_DEMOD4_VERSION 0x3FFFEDCC ++#define HYDRA_DEMOD5_VERSION 0x3FFFEDD0 ++#define HYDRA_DEMOD6_VERSION 0x3FFFEDD4 ++#define HYDRA_DEMOD7_VERSION 0x3FFFEDD8 ++#define HYDRA_HEAR_BEAT 0x3FFFEDDC ++#define HYDRA_SKU_MGMT 0x3FFFEBC0 ++ ++#define MXL_HYDRA_FPGA_A_ADDRESS 0x91C00000 ++#define MXL_HYDRA_FPGA_B_ADDRESS 0x91D00000 ++ ++// TS control base address ++#define HYDRA_TS_CTRL_BASE_ADDR 0x90700000 ++ ++#define MPEG_MUX_MODE_SLICE0_REG HYDRA_TS_CTRL_BASE_ADDR + 0x08 ++#define MPEG_MUX_MODE_SLICE0_OFFSET (0),(2) ++ ++#define MPEG_MUX_MODE_SLICE1_REG HYDRA_TS_CTRL_BASE_ADDR + 0x08 ++#define MPEG_MUX_MODE_SLICE1_OFFSET (2),(2) ++ ++#define PID_BANK_SEL_SLICE0_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190 ++#define PID_BANK_SEL_SLICE1_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0 ++ ++#define SW_REGULAR_PID_SW_BANK_OFFSET 0,1 ++#define SW_FIXED_PID_SW_BANK_OFFSET 1,1 ++ ++#define HW_REGULAR_PID_BANK_OFFSET 8,4 ++#define HW_FIXED_PID_BANK_OFFSET 4,4 ++ ++#define MPEG_CLK_GATED_REG HYDRA_TS_CTRL_BASE_ADDR + 0x20 ++#define MPEG_CLK_GATED_OFFSET 0,1 ++ ++#define MPEG_CLK_ALWAYS_ON_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1D4 ++#define MPEG_CLK_ALWAYS_ON_OFFSET 0,1 ++ ++#define HYDRA_REGULAR_PID_BANK_A_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190 ++#define HYDRA_REGULAR_PID_BAN K_A_OFFSET 0,1 ++ ++#define HYDRA_FIXED_PID_BANK_A_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190 ++#define HYDRA_FIXED_PID_BANK_A_OFFSET 1,1 ++ ++#define HYDRA_REGULAR_PID_BANK_B_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0 ++#define HYDRA_REGULAR_PID_BANK_B_OFFSET 0,1 ++ ++#define HYDRA_FIXED_PID_BANK_B_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0 ++#define HYDRA_FIXED_PID_BANK_B_OFFSET 1,1 ++ ++#define FIXED_PID_TBL_REG_ADDRESS_0 HYDRA_TS_CTRL_BASE_ADDR + 0x9000 ++#define FIXED_PID_TBL_REG_ADDRESS_1 HYDRA_TS_CTRL_BASE_ADDR + 0x9100 ++#define FIXED_PID_TBL_REG_ADDRESS_2 HYDRA_TS_CTRL_BASE_ADDR + 0x9200 ++#define FIXED_PID_TBL_REG_ADDRESS_3 HYDRA_TS_CTRL_BASE_ADDR + 0x9300 ++ ++#define FIXED_PID_TBL_REG_ADDRESS_4 HYDRA_TS_CTRL_BASE_ADDR + 0xB000 ++#define FIXED_PID_TBL_REG_ADDRESS_5 HYDRA_TS_CTRL_BASE_ADDR + 0xB100 ++#define FIXED_PID_TBL_REG_ADDRESS_6 HYDRA_TS_CTRL_BASE_ADDR + 0xB200 ++#define FIXED_PID_TBL_REG_ADDRESS_7 HYDRA_TS_CTRL_BASE_ADDR + 0xB300 ++ ++#define REGULAR_PID_TBL_REG_ADDRESS_0 HYDRA_TS_CTRL_BASE_ADDR + 0x8000 ++#define REGULAR_PID_TBL_REG_ADDRESS_1 HYDRA_TS_CTRL_BASE_ADDR + 0x8200 ++#define REGULAR_PID_TBL_REG_ADDRESS_2 HYDRA_TS_CTRL_BASE_ADDR + 0x8400 ++#define REGULAR_PID_TBL_REG_ADDRESS_3 HYDRA_TS_CTRL_BASE_ADDR + 0x8600 ++ ++#define REGULAR_PID_TBL_REG_ADDRESS_4 HYDRA_TS_CTRL_BASE_ADDR + 0xA000 ++#define REGULAR_PID_TBL_REG_ADDRESS_5 HYDRA_TS_CTRL_BASE_ADDR + 0xA200 ++#define REGULAR_PID_TBL_REG_ADDRESS_6 HYDRA_TS_CTRL_BASE_ADDR + 0xA400 ++#define REGULAR_PID_TBL_REG_ADDRESS_7 HYDRA_TS_CTRL_BASE_ADDR + 0xA600 ++ ++#define PID_VALID_OFFSET 0,1 ++#define PID_DROP_OFFSET 1,1 ++#define PID_REMAP_ENABLE_OFFSET 2,1 ++#define PID_VALUE_OFFSET 4,13 ++#define PID_MASK_OFFSET 19,13 ++ ++#define REGULAR_PID_REMAP_VALUE_OFFSET 0,13 ++#define FIXED_PID_REMAP_VALUE_OFFSET 0,16 ++#define PID_DEMODID_OFFSET 16,3 ++ ++ ++/////////////////////////////////////////////// ++ ++#if 0 ++#define AFE_REG_D2A_TA_ADC_CLK_OUT_FLIP 0x90200004,12,1 ++#define AFE_REG_D2A_TA_RFFE_LNACAPLOAD_1P8 0x90200028,24,4 ++#define AFE_REG_D2A_TA_RFFE_RF1_EN_1P8 0x90200028,5,1 ++#define AFE_REG_D2A_TA_RFFE_SPARE_1P8 0x90200028,8,8 ++#define AFE_REG_D2A_TB_ADC_CLK_OUT_FLIP 0x9020000C,23,1 ++#define AFE_REG_D2A_TB_RFFE_LNACAPLOAD_1P8 0x90200030,16,4 ++#define AFE_REG_D2A_TB_RFFE_RF1_EN_1P8 0x9020002C,21,1 ++#define AFE_REG_D2A_TB_RFFE_SPARE_1P8 0x90200030,0,8 ++#define AFE_REG_D2A_TC_ADC_CLK_OUT_FLIP 0x90200018,7,1 ++#define AFE_REG_D2A_TC_RFFE_LNACAPLOAD_1P8 0x90200038,2,4 ++#define AFE_REG_D2A_TC_RFFE_RF1_EN_1P8 0x90200034,14,1 ++#define AFE_REG_D2A_TC_RFFE_SPARE_1P8 0x90200034,17,8 ++#define AFE_REG_D2A_TD_ADC_CLK_OUT_FLIP 0x90200020,18,1 ++#define AFE_REG_D2A_TD_RFFE_LNACAPLOAD_1P8 0x9020003C,17,4 ++#define AFE_REG_D2A_TD_RFFE_RF1_EN_1P8 0x90200038,29,1 ++#define AFE_REG_D2A_TD_RFFE_SPARE_1P8 0x9020003C,1,8 ++#endif ++#define AFE_REG_D2A_XTAL_EN_CLKOUT_1P8 0x90200054,23,1 ++ ++#define PAD_MUX_TS0_IN_CLK_PINMUX_SEL 0x90000018,0,3 ++#define PAD_MUX_TS0_IN_DATA_PINMUX_SEL 0x90000018,4,3 ++#define PAD_MUX_TS1_IN_CLK_PINMUX_SEL 0x90000018,8,3 ++#define PAD_MUX_TS1_IN_DATA_PINMUX_SEL 0x90000018,12,3 ++#define PAD_MUX_TS2_IN_CLK_PINMUX_SEL 0x90000018,16,3 ++#define PAD_MUX_TS2_IN_DATA_PINMUX_SEL 0x90000018,20,3 ++#define PAD_MUX_TS3_IN_CLK_PINMUX_SEL 0x90000018,24,3 ++#define PAD_MUX_TS3_IN_DATA_PINMUX_SEL 0x90000018,28,3 ++ ++#define PAD_MUX_GPIO_00_SYNC_BASEADDR 0x90000188 ++#define PAD_MUX_GPIO_01_SYNC_IN PAD_MUX_GPIO_00_SYNC_BASEADDR,1,1 ++ ++#define PRCM_AFE_SOC_ID 0x80030004,24,8 ++ ++#define PAD_MUX_UART_RX_C_PINMUX_BASEADDR 0x9000001C ++#define PAD_MUX_UART_RX_C_PINMUX_SEL PAD_MUX_UART_RX_C_PINMUX_BASEADDR,0,3 ++#define PAD_MUX_UART_RX_D_PINMUX_SEL PAD_MUX_UART_RX_C_PINMUX_BASEADDR,4,3 ++#define PAD_MUX_BOND_OPTION 0x90000190,0,3 ++#define PAD_MUX_DIGIO_01_PINMUX_SEL 0x9000016C,4,3 ++#define PAD_MUX_DIGIO_02_PINMUX_SEL 0x9000016C,8,3 ++#define PAD_MUX_DIGIO_03_PINMUX_SEL 0x9000016C,12,3 ++#define PAD_MUX_DIGIO_04_PINMUX_SEL 0x9000016C,16,3 ++#define PAD_MUX_DIGIO_05_PINMUX_SEL 0x9000016C,20,3 ++#define PAD_MUX_DIGIO_06_PINMUX_SEL 0x9000016C,24,3 ++#define PAD_MUX_DIGIO_07_PINMUX_SEL 0x9000016C,28,3 ++#define PAD_MUX_DIGIO_08_PINMUX_SEL 0x90000170,0,3 ++#define PAD_MUX_DIGIO_09_PINMUX_SEL 0x90000170,4,3 ++#define PAD_MUX_DIGIO_10_PINMUX_SEL 0x90000170,8,3 ++#define PAD_MUX_DIGIO_11_PINMUX_SEL 0x90000170,12,3 ++#define PAD_MUX_DIGIO_12_PINMUX_SEL 0x90000170,16,3 ++#define PAD_MUX_DIGIO_13_PINMUX_SEL 0x90000170,20,3 ++#define PAD_MUX_DIGIO_14_PINMUX_SEL 0x90000170,24,3 ++#define PAD_MUX_DIGIO_15_PINMUX_SEL 0x90000170,28,3 ++#define PAD_MUX_DIGIO_16_PINMUX_SEL 0x90000174,0,3 ++#define PAD_MUX_DIGIO_17_PINMUX_SEL 0x90000174,4,3 ++#define PAD_MUX_DIGIO_18_PINMUX_SEL 0x90000174,8,3 ++#define PAD_MUX_DIGIO_19_PINMUX_SEL 0x90000174,12,3 ++#define PAD_MUX_DIGIO_20_PINMUX_SEL 0x90000174,16,3 ++#define PAD_MUX_DIGIO_21_PINMUX_SEL 0x90000174,20,3 ++#define PAD_MUX_DIGIO_22_PINMUX_SEL 0x90000174,24,3 ++#define PAD_MUX_DIGIO_23_PINMUX_SEL 0x90000174,28,3 ++#define PAD_MUX_DIGIO_24_PINMUX_SEL 0x90000178,0,3 ++#define PAD_MUX_DIGIO_25_PINMUX_SEL 0x90000178,4,3 ++#define PAD_MUX_DIGIO_26_PINMUX_SEL 0x90000178,8,3 ++#define PAD_MUX_DIGIO_27_PINMUX_SEL 0x90000178,12,3 ++#define PAD_MUX_DIGIO_28_PINMUX_SEL 0x90000178,16,3 ++#define PAD_MUX_DIGIO_29_PINMUX_SEL 0x90000178,20,3 ++#define PAD_MUX_DIGIO_30_PINMUX_SEL 0x90000178,24,3 ++#define PAD_MUX_DIGIO_31_PINMUX_SEL 0x90000178,28,3 ++#define PAD_MUX_DIGIO_32_PINMUX_SEL 0x9000017C,0,3 ++#define PAD_MUX_DIGIO_33_PINMUX_SEL 0x9000017C,4,3 ++#define PAD_MUX_DIGIO_34_PINMUX_SEL 0x9000017C,8,3 ++#define PAD_MUX_EJTAG_TCK_PINMUX_SEL 0x90000020,0,3 ++#define PAD_MUX_EJTAG_TDI_PINMUX_SEL 0x90000020,8,3 ++#define PAD_MUX_EJTAG_TMS_PINMUX_SEL 0x90000020,4,3 ++#define PAD_MUX_EJTAG_TRSTN_PINMUX_SEL 0x90000020,12,3 ++#define PAD_MUX_PAD_DRV_DIGIO_00 0x90000194,0,3 ++#define PAD_MUX_PAD_DRV_DIGIO_05 0x90000194,20,3 ++#define PAD_MUX_PAD_DRV_DIGIO_06 0x90000194,24,3 ++#define PAD_MUX_PAD_DRV_DIGIO_11 0x90000198,12,3 ++#define PAD_MUX_PAD_DRV_DIGIO_12 0x90000198,16,3 ++#define PAD_MUX_PAD_DRV_DIGIO_13 0x90000198,20,3 ++#define PAD_MUX_PAD_DRV_DIGIO_14 0x90000198,24,3 ++#define PAD_MUX_PAD_DRV_DIGIO_16 0x9000019C,0,3 ++#define PAD_MUX_PAD_DRV_DIGIO_17 0x9000019C,4,3 ++#define PAD_MUX_PAD_DRV_DIGIO_18 0x9000019C,8,3 ++#define PAD_MUX_PAD_DRV_DIGIO_22 0x9000019C,24,3 ++#define PAD_MUX_PAD_DRV_DIGIO_23 0x9000019C,28,3 ++#define PAD_MUX_PAD_DRV_DIGIO_24 0x900001A0,0,3 ++#define PAD_MUX_PAD_DRV_DIGIO_25 0x900001A0,4,3 ++#define PAD_MUX_PAD_DRV_DIGIO_29 0x900001A0,20,3 ++#define PAD_MUX_PAD_DRV_DIGIO_30 0x900001A0,24,3 ++#define PAD_MUX_PAD_DRV_DIGIO_31 0x900001A0,28,3 ++#define PRCM_AFE_REG_CLOCK_ENABLE 0x80030014,9,1 ++#define PRCM_CHIP_VERSION 0x80030000,12,4 ++#define PRCM_AFE_CHIP_MMSK_VER 0x80030004,8,8 ++#define PRCM_PRCM_AFE_REG_SOFT_RST_N 0x8003003C,12,1 ++#define PRCM_PRCM_CPU_SOFT_RST_N 0x8003003C,0,1 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB0 0x80030074,0,20 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB1 0x80030078,0,20 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB2 0x8003007C,0,20 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB3 0x80030080,0,20 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB4 0x80030084,0,20 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB5 0x80030088,0,20 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB6 0x8003008C,0,20 ++#define PRCM_PRCM_DIGRF_APB_DATA_BB7 0x80030090,0,20 ++#define PRCM_PRCM_DIGRF_CAPT_DONE 0x80030070,24,8 ++#define PRCM_PRCM_DIGRF_START_CAPT 0x80030064,2,1 ++#define PRCM_PRCM_PAD_MUX_SOFT_RST_N 0x8003003C,11,1 ++#define PRCM_PRCM_XPT_PARALLEL_FIFO_RST_N 0x80030028,20,1 ++#define XPT_APPEND_BYTES0 0x90700008,4,2 ++#define XPT_APPEND_BYTES1 0x90700008,6,2 ++#define XPT_CLOCK_POLARITY0 0x90700010,16,1 ++#define XPT_CLOCK_POLARITY1 0x90700010,17,1 ++#define XPT_CLOCK_POLARITY2 0x90700010,18,1 ++#define XPT_CLOCK_POLARITY3 0x90700010,19,1 ++#define XPT_CLOCK_POLARITY4 0x90700010,20,1 ++#define XPT_CLOCK_POLARITY5 0x90700010,21,1 ++#define XPT_CLOCK_POLARITY6 0x90700010,22,1 ++#define XPT_CLOCK_POLARITY7 0x90700010,23,1 ++#define XPT_DSS_DVB_ENCAP_EN0 0x90700000,16,1 ++#define XPT_DSS_DVB_ENCAP_EN1 0x90700000,17,1 ++#define XPT_DSS_DVB_ENCAP_EN2 0x90700000,18,1 ++#define XPT_DSS_DVB_ENCAP_EN3 0x90700000,19,1 ++#define XPT_DSS_DVB_ENCAP_EN4 0x90700000,20,1 ++#define XPT_DSS_DVB_ENCAP_EN5 0x90700000,21,1 ++#define XPT_DSS_DVB_ENCAP_EN6 0x90700000,22,1 ++#define XPT_DSS_DVB_ENCAP_EN7 0x90700000,23,1 ++#define XPT_DVB_MATCH_BYTE 0x9070017C,16,8 ++#define XPT_DVB_PACKET_SIZE0 0x90700180,0,8 ++#define XPT_DVB_PACKET_SIZE1 0x90700180,8,8 ++#define XPT_DVB_PACKET_SIZE2 0x90700180,16,8 ++#define XPT_DVB_PACKET_SIZE3 0x90700180,24,8 ++#define XPT_ENABLE_DVB_INPUT0 0x90700178,0,1 ++#define XPT_ENABLE_DVB_INPUT1 0x90700178,1,1 ++#define XPT_ENABLE_DVB_INPUT2 0x90700178,2,1 ++#define XPT_ENABLE_DVB_INPUT3 0x90700178,3,1 ++#define XPT_ENABLE_INPUT0 0x90700000,0,1 ++#define XPT_ENABLE_INPUT1 0x90700000,1,1 ++#define XPT_ENABLE_INPUT2 0x90700000,2,1 ++#define XPT_ENABLE_INPUT3 0x90700000,3,1 ++#define XPT_ENABLE_INPUT4 0x90700000,4,1 ++#define XPT_ENABLE_INPUT5 0x90700000,5,1 ++#define XPT_ENABLE_INPUT6 0x90700000,6,1 ++#define XPT_ENABLE_INPUT7 0x90700000,7,1 ++#define XPT_ENABLE_OUTPUT0 0x9070000C,0,1 ++#define XPT_ENABLE_OUTPUT1 0x9070000C,1,1 ++#define XPT_ENABLE_OUTPUT2 0x9070000C,2,1 ++#define XPT_ENABLE_OUTPUT3 0x9070000C,3,1 ++#define XPT_ENABLE_OUTPUT4 0x9070000C,4,1 ++#define XPT_ENABLE_OUTPUT5 0x9070000C,5,1 ++#define XPT_ENABLE_OUTPUT6 0x9070000C,6,1 ++#define XPT_ENABLE_OUTPUT7 0x9070000C,7,1 ++#define XPT_ENABLE_PARALLEL_OUTPUT 0x90700010,27,1 ++#define XPT_ENABLE_PCR_COUNT 0x90700184,1,1 ++#define XPT_ERROR_REPLACE_SYNC0 0x9070000C,24,1 ++#define XPT_ERROR_REPLACE_SYNC1 0x9070000C,25,1 ++#define XPT_ERROR_REPLACE_SYNC2 0x9070000C,26,1 ++#define XPT_ERROR_REPLACE_SYNC3 0x9070000C,27,1 ++#define XPT_ERROR_REPLACE_SYNC4 0x9070000C,28,1 ++#define XPT_ERROR_REPLACE_SYNC5 0x9070000C,29,1 ++#define XPT_ERROR_REPLACE_SYNC6 0x9070000C,30,1 ++#define XPT_ERROR_REPLACE_SYNC7 0x9070000C,31,1 ++#define XPT_ERROR_REPLACE_VALID0 0x90700014,8,1 ++#define XPT_ERROR_REPLACE_VALID1 0x90700014,9,1 ++#define XPT_ERROR_REPLACE_VALID2 0x90700014,10,1 ++#define XPT_ERROR_REPLACE_VALID3 0x90700014,11,1 ++#define XPT_ERROR_REPLACE_VALID4 0x90700014,12,1 ++#define XPT_ERROR_REPLACE_VALID5 0x90700014,13,1 ++#define XPT_ERROR_REPLACE_VALID6 0x90700014,14,1 ++#define XPT_ERROR_REPLACE_VALID7 0x90700014,15,1 ++#define XPT_INP0_MERGE_HDR0 0x90700058,0,32 ++#define XPT_INP0_MERGE_HDR1 0x9070005C,0,32 ++#define XPT_INP0_MERGE_HDR2 0x90700060,0,32 ++#define XPT_INP1_MERGE_HDR0 0x90700064,0,32 ++#define XPT_INP1_MERGE_HDR1 0x90700068,0,32 ++#define XPT_INP1_MERGE_HDR2 0x9070006C,0,32 ++#define XPT_INP2_MERGE_HDR0 0x90700070,0,32 ++#define XPT_INP2_MERGE_HDR1 0x90700074,0,32 ++#define XPT_INP2_MERGE_HDR2 0x90700078,0,32 ++#define XPT_INP3_MERGE_HDR0 0x9070007C,0,32 ++#define XPT_INP3_MERGE_HDR1 0x90700080,0,32 ++#define XPT_INP3_MERGE_HDR2 0x90700084,0,32 ++#define XPT_INP4_MERGE_HDR0 0x90700088,0,32 ++#define XPT_INP4_MERGE_HDR1 0x9070008C,0,32 ++#define XPT_INP4_MERGE_HDR2 0x90700090,0,32 ++#define XPT_INP5_MERGE_HDR0 0x90700094,0,32 ++#define XPT_INP5_MERGE_HDR1 0x90700098,0,32 ++#define XPT_INP5_MERGE_HDR2 0x9070009C,0,32 ++#define XPT_INP6_MERGE_HDR0 0x907000A0,0,32 ++#define XPT_INP6_MERGE_HDR1 0x907000A4,0,32 ++#define XPT_INP6_MERGE_HDR2 0x907000A8,0,32 ++#define XPT_INP7_MERGE_HDR0 0x907000AC,0,32 ++#define XPT_INP7_MERGE_HDR1 0x907000B0,0,32 ++#define XPT_INP7_MERGE_HDR2 0x907000B4,0,32 ++#define XPT_INP_MODE_DSS0 0x90700000,8,1 ++#define XPT_INP_MODE_DSS1 0x90700000,9,1 ++#define XPT_INP_MODE_DSS2 0x90700000,10,1 ++#define XPT_INP_MODE_DSS3 0x90700000,11,1 ++#define XPT_INP_MODE_DSS4 0x90700000,12,1 ++#define XPT_INP_MODE_DSS5 0x90700000,13,1 ++#define XPT_INP_MODE_DSS6 0x90700000,14,1 ++#define XPT_INP_MODE_DSS7 0x90700000,15,1 ++#define XPT_KNOWN_PID_MUX_SELECT0 0x90700190,8,4 ++#define XPT_KNOWN_PID_MUX_SELECT1 0x907001B0,8,4 ++#define XPT_LSB_FIRST0 0x9070000C,16,1 ++#define XPT_LSB_FIRST1 0x9070000C,17,1 ++#define XPT_LSB_FIRST2 0x9070000C,18,1 ++#define XPT_LSB_FIRST3 0x9070000C,19,1 ++#define XPT_LSB_FIRST4 0x9070000C,20,1 ++#define XPT_LSB_FIRST5 0x9070000C,21,1 ++#define XPT_LSB_FIRST6 0x9070000C,22,1 ++#define XPT_LSB_FIRST7 0x9070000C,23,1 ++#define XPT_MODE_27MHZ 0x90700184,0,1 ++#define XPT_NCO_COUNT_MIN 0x90700044,16,8 ++#define XPT_OUTPUT_MODE_DSS0 0x9070000C,8,1 ++#define XPT_OUTPUT_MODE_DSS1 0x9070000C,9,1 ++#define XPT_OUTPUT_MODE_DSS2 0x9070000C,10,1 ++#define XPT_OUTPUT_MODE_DSS3 0x9070000C,11,1 ++#define XPT_OUTPUT_MODE_DSS4 0x9070000C,12,1 ++#define XPT_OUTPUT_MODE_DSS5 0x9070000C,13,1 ++#define XPT_OUTPUT_MODE_DSS6 0x9070000C,14,1 ++#define XPT_OUTPUT_MODE_DSS7 0x9070000C,15,1 ++#define XPT_OUTPUT_MODE_MUXGATING0 0x90700020,0,1 ++#define XPT_OUTPUT_MODE_MUXGATING1 0x90700020,1,1 ++#define XPT_OUTPUT_MODE_MUXGATING2 0x90700020,2,1 ++#define XPT_OUTPUT_MODE_MUXGATING3 0x90700020,3,1 ++#define XPT_OUTPUT_MODE_MUXGATING4 0x90700020,4,1 ++#define XPT_OUTPUT_MODE_MUXGATING5 0x90700020,5,1 ++#define XPT_OUTPUT_MODE_MUXGATING6 0x90700020,6,1 ++#define XPT_OUTPUT_MODE_MUXGATING7 0x90700020,7,1 ++#define XPT_OUTPUT_MUXSELECT0 0x9070001C,0,3 ++#define XPT_OUTPUT_MUXSELECT1 0x9070001C,4,3 ++#define XPT_OUTPUT_MUXSELECT2 0x9070001C,8,3 ++#define XPT_OUTPUT_MUXSELECT3 0x9070001C,12,3 ++#define XPT_OUTPUT_MUXSELECT4 0x9070001C,16,3 ++#define XPT_OUTPUT_MUXSELECT5 0x9070001C,20,3 ++#define XPT_PCR_RTS_CORRECTION_ENABLE 0x90700008,14,1 ++#define XPT_PID_DEFAULT_DROP0 0x90700190,12,1 ++#define XPT_PID_DEFAULT_DROP1 0x90700190,13,1 ++#define XPT_PID_DEFAULT_DROP2 0x90700190,14,1 ++#define XPT_PID_DEFAULT_DROP3 0x90700190,15,1 ++#define XPT_PID_DEFAULT_DROP4 0x907001B0,12,1 ++#define XPT_PID_DEFAULT_DROP5 0x907001B0,13,1 ++#define XPT_PID_DEFAULT_DROP6 0x907001B0,14,1 ++#define XPT_PID_DEFAULT_DROP7 0x907001B0,15,1 ++#define XPT_PID_MUX_SELECT0 0x90700190,4,4 ++#define XPT_PID_MUX_SELECT1 0x907001B0,4,4 ++#define XPT_STREAM_MUXMODE0 0x90700008,0,2 ++#define XPT_STREAM_MUXMODE1 0x90700008,2,2 ++#define XPT_SYNC_FULL_BYTE0 0x90700010,0,1 ++#define XPT_SYNC_FULL_BYTE1 0x90700010,1,1 ++#define XPT_SYNC_FULL_BYTE2 0x90700010,2,1 ++#define XPT_SYNC_FULL_BYTE3 0x90700010,3,1 ++#define XPT_SYNC_FULL_BYTE4 0x90700010,4,1 ++#define XPT_SYNC_FULL_BYTE5 0x90700010,5,1 ++#define XPT_SYNC_FULL_BYTE6 0x90700010,6,1 ++#define XPT_SYNC_FULL_BYTE7 0x90700010,7,1 ++#define XPT_SYNC_LOCK_THRESHOLD 0x9070017C,0,8 ++#define XPT_SYNC_MISS_THRESHOLD 0x9070017C,8,8 ++#define XPT_SYNC_POLARITY0 0x90700010,8,1 ++#define XPT_SYNC_POLARITY1 0x90700010,9,1 ++#define XPT_SYNC_POLARITY2 0x90700010,10,1 ++#define XPT_SYNC_POLARITY3 0x90700010,11,1 ++#define XPT_SYNC_POLARITY4 0x90700010,12,1 ++#define XPT_SYNC_POLARITY5 0x90700010,13,1 ++#define XPT_SYNC_POLARITY6 0x90700010,14,1 ++#define XPT_SYNC_POLARITY7 0x90700010,15,1 ++#define XPT_TS_CLK_OUT_EN0 0x907001D4,0,1 ++#define XPT_TS_CLK_OUT_EN1 0x907001D4,1,1 ++#define XPT_TS_CLK_OUT_EN2 0x907001D4,2,1 ++#define XPT_TS_CLK_OUT_EN3 0x907001D4,3,1 ++#define XPT_TS_CLK_OUT_EN4 0x907001D4,4,1 ++#define XPT_TS_CLK_OUT_EN5 0x907001D4,5,1 ++#define XPT_TS_CLK_OUT_EN6 0x907001D4,6,1 ++#define XPT_TS_CLK_OUT_EN7 0x907001D4,7,1 ++#define XPT_TS_CLK_OUT_EN_PARALLEL 0x907001D4,8,1 ++#define XPT_TS_CLK_PHASE0 0x90700018,0,3 ++#define XPT_TS_CLK_PHASE1 0x90700018,4,3 ++#define XPT_TS_CLK_PHASE2 0x90700018,8,3 ++#define XPT_TS_CLK_PHASE3 0x90700018,12,3 ++#define XPT_TS_CLK_PHASE4 0x90700018,16,3 ++#define XPT_TS_CLK_PHASE5 0x90700018,20,3 ++#define XPT_TS_CLK_PHASE6 0x90700018,24,3 ++#define XPT_TS_CLK_PHASE7 0x90700018,28,3 ++#define XPT_VALID_POLARITY0 0x90700014,0,1 ++#define XPT_VALID_POLARITY1 0x90700014,1,1 ++#define XPT_VALID_POLARITY2 0x90700014,2,1 ++#define XPT_VALID_POLARITY3 0x90700014,3,1 ++#define XPT_VALID_POLARITY4 0x90700014,4,1 ++#define XPT_VALID_POLARITY5 0x90700014,5,1 ++#define XPT_VALID_POLARITY6 0x90700014,6,1 ++#define XPT_VALID_POLARITY7 0x90700014,7,1 ++#define XPT_ZERO_FILL_COUNT 0x90700008,8,6 ++ ++#define XPT_PACKET_GAP_MIN_BASEADDR 0x90700044 ++#define XPT_PACKET_GAP_MIN_TIMER XPT_PACKET_GAP_MIN_BASEADDR,0,16 ++#define XPT_NCO_COUNT_MIN0 XPT_PACKET_GAP_MIN_BASEADDR,16,8 ++#define XPT_NCO_COUNT_BASEADDR 0x90700238 ++#define XPT_NCO_COUNT_MIN1 XPT_NCO_COUNT_BASEADDR,0,8 ++#define XPT_NCO_COUNT_MIN2 XPT_NCO_COUNT_BASEADDR,8,8 ++#define XPT_NCO_COUNT_MIN3 XPT_NCO_COUNT_BASEADDR,16,8 ++#define XPT_NCO_COUNT_MIN4 XPT_NCO_COUNT_BASEADDR,24,8 ++ ++#define XPT_NCO_COUNT_BASEADDR1 0x9070023C ++#define XPT_NCO_COUNT_MIN5 XPT_NCO_COUNT_BASEADDR1,0,8 ++#define XPT_NCO_COUNT_MIN6 XPT_NCO_COUNT_BASEADDR1,8,8 ++#define XPT_NCO_COUNT_MIN7 XPT_NCO_COUNT_BASEADDR1,16,8 ++ ++// V2 DigRF status register ++#define BB0_DIGRF_CAPT_DONE 0x908000CC,0,1 ++#define PRCM_PRCM_CHIP_ID 0x80030000,0,12 ++ ++#define XPT_PID_BASEADDR 0x90708000 ++#define XPT_PID_VALID0 XPT_PID_BASEADDR,0,1 ++#define XPT_PID_DROP0 XPT_PID_BASEADDR,1,1 ++#define XPT_PID_REMAP0 XPT_PID_BASEADDR,2,1 ++#define XPT_PID_VALUE0 XPT_PID_BASEADDR,4,13 ++#define XPT_PID_MASK0 XPT_PID_BASEADDR,19,13 ++ ++#define XPT_PID_REMAP_BASEADDR 0x90708004 ++#define XPT_PID_REMAP_VALUE0 XPT_PID_REMAP_BASEADDR,0,13 ++#define XPT_PID_PORT_ID0 XPT_PID_REMAP_BASEADDR,16,3 ++ ++#define XPT_KNOWN_PID_BASEADDR 0x90709000 ++#define XPT_KNOWN_PID_VALID0 XPT_KNOWN_PID_BASEADDR,0,1 ++#define XPT_KNOWN_PID_DROP0 XPT_KNOWN_PID_BASEADDR,1,1 ++#define XPT_KNOWN_PID_REMAP0 XPT_KNOWN_PID_BASEADDR,2,1 ++#define XPT_KNOWN_PID_REMAP_VALUE0 XPT_KNOWN_PID_BASEADDR,16,13 ++ ++#define XPT_PID_BASEADDR1 0x9070A000 ++#define XPT_PID_VALID1 XPT_PID_BASEADDR1,0,1 ++#define XPT_PID_DROP1 XPT_PID_BASEADDR1,1,1 ++#define XPT_PID_REMAP1 XPT_PID_BASEADDR1,2,1 ++#define XPT_PID_VALUE1 XPT_PID_BASEADDR1,4,13 ++#define XPT_PID_MASK1 XPT_PID_BASEADDR1,19,13 ++ ++#define XPT_PID_REMAP_BASEADDR1 0x9070A004 ++#define XPT_PID_REMAP_VALUE1 XPT_PID_REMAP_BASEADDR1,0,13 ++ ++#define XPT_KNOWN_PID_BASEADDR1 0x9070B000 ++#define XPT_KNOWN_PID_VALID1 XPT_KNOWN_PID_BASEADDR1,0,1 ++#define XPT_KNOWN_PID_DROP1 XPT_KNOWN_PID_BASEADDR1,1,1 ++#define XPT_KNOWN_PID_REMAP1 XPT_KNOWN_PID_BASEADDR1,2,1 ++#define XPT_KNOWN_PID_REMAP_VALUE1 XPT_KNOWN_PID_BASEADDR1,16,13 ++ ++#define XPT_BERT_LOCK_BASEADDR 0x907000B8 ++#define XPT_BERT_LOCK_THRESHOLD XPT_BERT_LOCK_BASEADDR,0,8 ++#define XPT_BERT_LOCK_WINDOW XPT_BERT_LOCK_BASEADDR,8,8 ++ ++#define XPT_BERT_BASEADDR 0x907000BC ++#define XPT_BERT_ENABLE0 XPT_BERT_BASEADDR,0,1 ++#define XPT_BERT_ENABLE1 XPT_BERT_BASEADDR,1,1 ++#define XPT_BERT_ENABLE2 XPT_BERT_BASEADDR,2,1 ++#define XPT_BERT_ENABLE3 XPT_BERT_BASEADDR,3,1 ++#define XPT_BERT_ENABLE4 XPT_BERT_BASEADDR,4,1 ++#define XPT_BERT_ENABLE5 XPT_BERT_BASEADDR,5,1 ++#define XPT_BERT_ENABLE6 XPT_BERT_BASEADDR,6,1 ++#define XPT_BERT_ENABLE7 XPT_BERT_BASEADDR,7,1 ++#define XPT_BERT_SEQUENCE_PN23_0 XPT_BERT_BASEADDR,8,1 ++#define XPT_BERT_SEQUENCE_PN23_1 XPT_BERT_BASEADDR,9,1 ++#define XPT_BERT_SEQUENCE_PN23_2 XPT_BERT_BASEADDR,10,1 ++#define XPT_BERT_SEQUENCE_PN23_3 XPT_BERT_BASEADDR,11,1 ++#define XPT_BERT_SEQUENCE_PN23_4 XPT_BERT_BASEADDR,12,1 ++#define XPT_BERT_SEQUENCE_PN23_5 XPT_BERT_BASEADDR,13,1 ++#define XPT_BERT_SEQUENCE_PN23_6 XPT_BERT_BASEADDR,14,1 ++#define XPT_BERT_SEQUENCE_PN23_7 XPT_BERT_BASEADDR,15,1 ++#define XPT_LOCK_RESYNC0 XPT_BERT_BASEADDR,16,1 ++#define XPT_LOCK_RESYNC1 XPT_BERT_BASEADDR,17,1 ++#define XPT_LOCK_RESYNC2 XPT_BERT_BASEADDR,18,1 ++#define XPT_LOCK_RESYNC3 XPT_BERT_BASEADDR,19,1 ++#define XPT_LOCK_RESYNC4 XPT_BERT_BASEADDR,20,1 ++#define XPT_LOCK_RESYNC5 XPT_BERT_BASEADDR,21,1 ++#define XPT_LOCK_RESYNC6 XPT_BERT_BASEADDR,22,1 ++#define XPT_LOCK_RESYNC7 XPT_BERT_BASEADDR,23,1 ++#define XPT_BERT_DATA_POLARITY0 XPT_BERT_BASEADDR,24,1 ++#define XPT_BERT_DATA_POLARITY1 XPT_BERT_BASEADDR,25,1 ++#define XPT_BERT_DATA_POLARITY2 XPT_BERT_BASEADDR,26,1 ++#define XPT_BERT_DATA_POLARITY3 XPT_BERT_BASEADDR,27,1 ++#define XPT_BERT_DATA_POLARITY4 XPT_BERT_BASEADDR,28,1 ++#define XPT_BERT_DATA_POLARITY5 XPT_BERT_BASEADDR,29,1 ++#define XPT_BERT_DATA_POLARITY6 XPT_BERT_BASEADDR,30,1 ++#define XPT_BERT_DATA_POLARITY7 XPT_BERT_BASEADDR,31,1 ++ ++#define XPT_BERT_INVERT_BASEADDR 0x907000C0 ++#define XPT_BERT_INVERT_DATA0 XPT_BERT_INVERT_BASEADDR,0,1 ++#define XPT_BERT_INVERT_DATA1 XPT_BERT_INVERT_BASEADDR,1,1 ++#define XPT_BERT_INVERT_DATA2 XPT_BERT_INVERT_BASEADDR,2,1 ++#define XPT_BERT_INVERT_DATA3 XPT_BERT_INVERT_BASEADDR,3,1 ++#define XPT_BERT_INVERT_DATA4 XPT_BERT_INVERT_BASEADDR,4,1 ++#define XPT_BERT_INVERT_DATA5 XPT_BERT_INVERT_BASEADDR,5,1 ++#define XPT_BERT_INVERT_DATA6 XPT_BERT_INVERT_BASEADDR,6,1 ++#define XPT_BERT_INVERT_DATA7 XPT_BERT_INVERT_BASEADDR,7,1 ++#define XPT_BERT_INVERT_SEQUENCE0 XPT_BERT_INVERT_BASEADDR,8,1 ++#define XPT_BERT_INVERT_SEQUENCE1 XPT_BERT_INVERT_BASEADDR,9,1 ++#define XPT_BERT_INVERT_SEQUENCE2 XPT_BERT_INVERT_BASEADDR,10,1 ++#define XPT_BERT_INVERT_SEQUENCE3 XPT_BERT_INVERT_BASEADDR,11,1 ++#define XPT_BERT_INVERT_SEQUENCE4 XPT_BERT_INVERT_BASEADDR,12,1 ++#define XPT_BERT_INVERT_SEQUENCE5 XPT_BERT_INVERT_BASEADDR,13,1 ++#define XPT_BERT_INVERT_SEQUENCE6 XPT_BERT_INVERT_BASEADDR,14,1 ++#define XPT_BERT_INVERT_SEQUENCE7 XPT_BERT_INVERT_BASEADDR,15,1 ++#define XPT_BERT_OUTPUT_POLARITY0 XPT_BERT_INVERT_BASEADDR,16,1 ++#define XPT_BERT_OUTPUT_POLARITY1 XPT_BERT_INVERT_BASEADDR,17,1 ++#define XPT_BERT_OUTPUT_POLARITY2 XPT_BERT_INVERT_BASEADDR,18,1 ++#define XPT_BERT_OUTPUT_POLARITY3 XPT_BERT_INVERT_BASEADDR,19,1 ++#define XPT_BERT_OUTPUT_POLARITY4 XPT_BERT_INVERT_BASEADDR,20,1 ++#define XPT_BERT_OUTPUT_POLARITY5 XPT_BERT_INVERT_BASEADDR,21,1 ++#define XPT_BERT_OUTPUT_POLARITY6 XPT_BERT_INVERT_BASEADDR,22,1 ++#define XPT_BERT_OUTPUT_POLARITY7 XPT_BERT_INVERT_BASEADDR,23,1 ++ ++#define XPT_BERT_HEADER_BASEADDR 0x907000C4 ++#define XPT_BERT_HEADER_MODE0 XPT_BERT_HEADER_BASEADDR,0,2 ++#define XPT_BERT_HEADER_MODE1 XPT_BERT_HEADER_BASEADDR,2,2 ++#define XPT_BERT_HEADER_MODE2 XPT_BERT_HEADER_BASEADDR,4,2 ++#define XPT_BERT_HEADER_MODE3 XPT_BERT_HEADER_BASEADDR,6,2 ++#define XPT_BERT_HEADER_MODE4 XPT_BERT_HEADER_BASEADDR,8,2 ++#define XPT_BERT_HEADER_MODE5 XPT_BERT_HEADER_BASEADDR,10,2 ++#define XPT_BERT_HEADER_MODE6 XPT_BERT_HEADER_BASEADDR,12,2 ++#define XPT_BERT_HEADER_MODE7 XPT_BERT_HEADER_BASEADDR,14,2 ++ ++#define XPT_BERT_BASEADDR1 0x907000C8 ++#define XPT_BERT_LOCKED0 XPT_BERT_BASEADDR1,0,1 ++#define XPT_BERT_LOCKED1 XPT_BERT_BASEADDR1,1,1 ++#define XPT_BERT_LOCKED2 XPT_BERT_BASEADDR1,2,1 ++#define XPT_BERT_LOCKED3 XPT_BERT_BASEADDR1,3,1 ++#define XPT_BERT_LOCKED4 XPT_BERT_BASEADDR1,4,1 ++#define XPT_BERT_LOCKED5 XPT_BERT_BASEADDR1,5,1 ++#define XPT_BERT_LOCKED6 XPT_BERT_BASEADDR1,6,1 ++#define XPT_BERT_LOCKED7 XPT_BERT_BASEADDR1,7,1 ++#define XPT_BERT_BIT_COUNT_SAT0 XPT_BERT_BASEADDR1,8,1 ++#define XPT_BERT_BIT_COUNT_SAT1 XPT_BERT_BASEADDR1,9,1 ++#define XPT_BERT_BIT_COUNT_SAT2 XPT_BERT_BASEADDR1,10,1 ++#define XPT_BERT_BIT_COUNT_SAT3 XPT_BERT_BASEADDR1,11,1 ++#define XPT_BERT_BIT_COUNT_SAT4 XPT_BERT_BASEADDR1,12,1 ++#define XPT_BERT_BIT_COUNT_SAT5 XPT_BERT_BASEADDR1,13,1 ++#define XPT_BERT_BIT_COUNT_SAT6 XPT_BERT_BASEADDR1,14,1 ++#define XPT_BERT_BIT_COUNT_SAT7 XPT_BERT_BASEADDR1,15,1 ++ ++#define XPT_BERT_BIT_COUNT0_BASEADDR 0x907000CC ++#define XPT_BERT_BIT_COUNT0_LO XPT_BERT_BIT_COUNT0_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT0_BASEADDR1 0x907000D0 ++#define XPT_BERT_BIT_COUNT0_HI XPT_BERT_BIT_COUNT0_BASEADDR1,0,18 ++ ++#define XPT_BERT_BIT_COUNT1_BASEADDR 0x907000D4 ++#define XPT_BERT_BIT_COUNT1_LO XPT_BERT_BIT_COUNT1_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT1_BASEADDR1 0x907000D8 ++#define XPT_BERT_BIT_COUNT1_HI XPT_BERT_BIT_COUNT1_BASEADDR1,0,18 ++ ++#define XPT_BERT_BIT_COUNT2_BASEADDR 0x907000DC ++#define XPT_BERT_BIT_COUNT2_LO XPT_BERT_BIT_COUNT2_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT2_BASEADDR1 0x907000E0 ++#define XPT_BERT_BIT_COUNT2_HI XPT_BERT_BIT_COUNT2_BASEADDR1,0,18 ++ ++#define XPT_BERT_BIT_COUNT3_BASEADDR 0x907000E4 ++#define XPT_BERT_BIT_COUNT3_LO XPT_BERT_BIT_COUNT3_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT3_BASEADDR1 0x907000E8 ++#define XPT_BERT_BIT_COUNT3_HI XPT_BERT_BIT_COUNT3_BASEADDR1,0,18 ++ ++#define XPT_BERT_BIT_COUNT4_BASEADDR 0x907000EC ++#define XPT_BERT_BIT_COUNT4_LO XPT_BERT_BIT_COUNT4_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT4_BASEADDR1 0x907000F0 ++#define XPT_BERT_BIT_COUNT4_HI XPT_BERT_BIT_COUNT4_BASEADDR1,0,18 ++ ++#define XPT_BERT_BIT_COUNT5_BASEADDR 0x907000F4 ++#define XPT_BERT_BIT_COUNT5_LO XPT_BERT_BIT_COUNT5_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT5_BASEADDR1 0x907000F8 ++#define XPT_BERT_BIT_COUNT5_HI XPT_BERT_BIT_COUNT5_BASEADDR1,0,18 ++ ++#define XPT_BERT_BIT_COUNT6_BASEADDR 0x907000FC ++#define XPT_BERT_BIT_COUNT6_LO XPT_BERT_BIT_COUNT6_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT6_BASEADDR1 0x90700100 ++#define XPT_BERT_BIT_COUNT6_HI XPT_BERT_BIT_COUNT6_BASEADDR1,0,18 ++ ++#define XPT_BERT_BIT_COUNT7_BASEADDR 0x90700104 ++#define XPT_BERT_BIT_COUNT7_LO XPT_BERT_BIT_COUNT7_BASEADDR,0,32 ++ ++#define XPT_BERT_BIT_COUNT7_BASEADDR1 0x90700108 ++#define XPT_BERT_BIT_COUNT7_HI XPT_BERT_BIT_COUNT7_BASEADDR1,0,18 ++ ++#define XPT_BERT_ERR_COUNT0_BASEADDR 0x9070010C ++#define XPT_BERT_ERR_COUNT0_LO XPT_BERT_ERR_COUNT0_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT0_BASEADDR1 0x90700110 ++#define XPT_BERT_ERR_COUNT0_HI XPT_BERT_ERR_COUNT0_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERR_COUNT1_BASEADDR 0x90700114 ++#define XPT_BERT_ERR_COUNT1_LO XPT_BERT_ERR_COUNT1_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT1_BASEADDR1 0x90700118 ++#define XPT_BERT_ERR_COUNT1_HI XPT_BERT_ERR_COUNT1_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERR_COUNT2_BASEADDR 0x9070011C ++#define XPT_BERT_ERR_COUNT2_LO XPT_BERT_ERR_COUNT2_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT2_BASEADDR1 0x90700120 ++#define XPT_BERT_ERR_COUNT2_HI XPT_BERT_ERR_COUNT2_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERR_COUNT3_BASEADDR 0x90700124 ++#define XPT_BERT_ERR_COUNT3_LO XPT_BERT_ERR_COUNT3_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT3_BASEADDR1 0x90700128 ++#define XPT_BERT_ERR_COUNT3_HI XPT_BERT_ERR_COUNT3_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERR_COUNT4_BASEADDR 0x9070012C ++#define XPT_BERT_ERR_COUNT4_LO XPT_BERT_ERR_COUNT4_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT4_BASEADDR1 0x90700130 ++#define XPT_BERT_ERR_COUNT4_HI XPT_BERT_ERR_COUNT4_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERR_COUNT5_BASEADDR 0x90700134 ++#define XPT_BERT_ERR_COUNT5_LO XPT_BERT_ERR_COUNT5_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT5_BASEADDR1 0x90700138 ++#define XPT_BERT_ERR_COUNT5_HI XPT_BERT_ERR_COUNT5_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERR_COUNT6_BASEADDR 0x9070013C ++#define XPT_BERT_ERR_COUNT6_LO XPT_BERT_ERR_COUNT6_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT6_BASEADDR1 0x90700140 ++#define XPT_BERT_ERR_COUNT6_HI XPT_BERT_ERR_COUNT6_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERR_COUNT7_BASEADDR 0x90700144 ++#define XPT_BERT_ERR_COUNT7_LO XPT_BERT_ERR_COUNT7_BASEADDR,0,32 ++ ++#define XPT_BERT_ERR_COUNT7_BASEADDR1 0x90700148 ++#define XPT_BERT_ERR_COUNT7_HI XPT_BERT_ERR_COUNT7_BASEADDR1,0,8 ++ ++#define XPT_BERT_ERROR_BASEADDR 0x9070014C ++#define XPT_BERT_ERROR_INSERT XPT_BERT_ERROR_BASEADDR,0,24 ++ ++#define XPT_BERT_ANALYZER_BASEADDR 0x90700150 ++#define XPT_BERT_ANALYZER_ENABLE XPT_BERT_ANALYZER_BASEADDR,0,1 ++#define XPT_BERT_ANALYZER_PORT XPT_BERT_ANALYZER_BASEADDR,4,3 ++#define XPT_BERT_ANALYZER_ERR_THRES XPT_BERT_ANALYZER_BASEADDR,15,17 ++ ++#define XPT_BERT_ANALYZER_BASEADDR1 0x90700154 ++#define XPT_BERT_ANALYZER_START XPT_BERT_ANALYZER_BASEADDR1,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR2 0x90700158 ++#define XPT_BERT_ANALYZER_TSTAMP0 XPT_BERT_ANALYZER_BASEADDR2,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR3 0x9070015C ++#define XPT_BERT_ANALYZER_TSTAMP1 XPT_BERT_ANALYZER_BASEADDR3,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR4 0x90700160 ++#define XPT_BERT_ANALYZER_TSTAMP2 XPT_BERT_ANALYZER_BASEADDR4,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR5 0x90700164 ++#define XPT_BERT_ANALYZER_TSTAMP3 XPT_BERT_ANALYZER_BASEADDR5,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR6 0x90700168 ++#define XPT_BERT_ANALYZER_TSTAMP4 XPT_BERT_ANALYZER_BASEADDR6,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR7 0x9070016C ++#define XPT_BERT_ANALYZER_TSTAMP5 XPT_BERT_ANALYZER_BASEADDR7,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR8 0x90700170 ++#define XPT_BERT_ANALYZER_TSTAMP6 XPT_BERT_ANALYZER_BASEADDR8,0,32 ++ ++#define XPT_BERT_ANALYZER_BASEADDR9 0x90700174 ++#define XPT_BERT_ANALYZER_TSTAMP7 XPT_BERT_ANALYZER_BASEADDR9,0,32 ++ ++#define XPT_DMD0_BASEADDR 0x9070024C ++#define XPT_DMD0_SEL XPT_DMD0_BASEADDR,0,3 ++#define XPT_DMD1_SEL XPT_DMD0_BASEADDR,4,3 ++#define XPT_DMD2_SEL XPT_DMD0_BASEADDR,8,3 ++#define XPT_DMD3_SEL XPT_DMD0_BASEADDR,12,3 ++#define XPT_DMD4_SEL XPT_DMD0_BASEADDR,16,3 ++#define XPT_DMD5_SEL XPT_DMD0_BASEADDR,20,3 ++#define XPT_DMD6_SEL XPT_DMD0_BASEADDR,24,3 ++#define XPT_DMD7_SEL XPT_DMD0_BASEADDR,28,3 ++ ++// V2 AGC Gain Freeze & step ++#define DBG_ENABLE_DISABLE_AGC (0x3FFFCF60) // 1: DISABLE, 0:ENABLE ++#define WB_DFE0_DFE_FB_RF1_BASEADDR 0x903004A4 ++#define WB_DFE0_DFE_FB_RF1_BO WB_DFE0_DFE_FB_RF1_BASEADDR,0,3 ++#define WB_DFE0_DFE_FB_RF2_BO WB_DFE0_DFE_FB_RF1_BASEADDR,4,4 ++#define WB_DFE0_DFE_FB_LNA_BO WB_DFE0_DFE_FB_RF1_BASEADDR,8,2 ++ ++#define WB_DFE1_DFE_FB_RF1_BASEADDR 0x904004A4 ++#define WB_DFE1_DFE_FB_RF1_BO WB_DFE1_DFE_FB_RF1_BASEADDR,0,3 ++#define WB_DFE1_DFE_FB_RF2_BO WB_DFE1_DFE_FB_RF1_BASEADDR,4,4 ++#define WB_DFE1_DFE_FB_LNA_BO WB_DFE1_DFE_FB_RF1_BASEADDR,8,2 ++ ++#define WB_DFE2_DFE_FB_RF1_BASEADDR 0x905004A4 ++#define WB_DFE2_DFE_FB_RF1_BO WB_DFE2_DFE_FB_RF1_BASEADDR,0,3 ++#define WB_DFE2_DFE_FB_RF2_BO WB_DFE2_DFE_FB_RF1_BASEADDR,4,4 ++#define WB_DFE2_DFE_FB_LNA_BO WB_DFE2_DFE_FB_RF1_BASEADDR,8,2 ++ ++#define WB_DFE3_DFE_FB_RF1_BASEADDR 0x906004A4 ++#define WB_DFE3_DFE_FB_RF1_BO WB_DFE3_DFE_FB_RF1_BASEADDR,0,3 ++#define WB_DFE3_DFE_FB_RF2_BO WB_DFE3_DFE_FB_RF1_BASEADDR,4,4 ++#define WB_DFE3_DFE_FB_LNA_BO WB_DFE3_DFE_FB_RF1_BASEADDR,8,2 ++ ++#define AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR 0x90200104 ++#define AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,0,1 ++#define AFE_REG_D2A_TA_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,1,1 ++#define AFE_REG_D2A_TB_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,2,1 ++#define AFE_REG_D2A_TB_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,3,1 ++#define AFE_REG_D2A_TC_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,4,1 ++#define AFE_REG_D2A_TC_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,5,1 ++#define AFE_REG_D2A_TD_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,6,1 ++#define AFE_REG_D2A_TD_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,7,1 ++ ++#define AFE_REG_AFE_REG_SPARE_BASEADDR 0x902000A0 ++#define AFE_REG_D2A_TA_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR,13,5 ++ ++#define AFE_REG_AFE_REG_SPARE_BASEADDR1 0x902000B4 ++#define AFE_REG_D2A_TB_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR1,13,5 ++ ++#define AFE_REG_AFE_REG_SPARE_BASEADDR2 0x902000C4 ++#define AFE_REG_D2A_TC_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR2,13,5 ++ ++#define AFE_REG_AFE_REG_SPARE_BASEADDR3 0x902000D4 ++#define AFE_REG_D2A_TD_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR3,13,5 ++ ++#define WB_DFE0_DFE_FB_AGC_BASEADDR 0x90300498 ++#define WB_DFE0_DFE_FB_AGC_APPLY WB_DFE0_DFE_FB_AGC_BASEADDR,0,1 ++ ++#define WB_DFE1_DFE_FB_AGC_BASEADDR 0x90400498 ++#define WB_DFE1_DFE_FB_AGC_APPLY WB_DFE1_DFE_FB_AGC_BASEADDR,0,1 ++ ++#define WB_DFE2_DFE_FB_AGC_BASEADDR 0x90500498 ++#define WB_DFE2_DFE_FB_AGC_APPLY WB_DFE2_DFE_FB_AGC_BASEADDR,0,1 ++ ++#define WB_DFE3_DFE_FB_AGC_BASEADDR 0x90600498 ++#define WB_DFE3_DFE_FB_AGC_APPLY WB_DFE3_DFE_FB_AGC_BASEADDR,0,1 ++ ++#define WDT_WD_INT_BASEADDR 0x8002000C ++#define WDT_WD_INT_STATUS WDT_WD_INT_BASEADDR,0,1 ++ ++#define FSK_TX_FTM_BASEADDR 0x80090000 ++#define FSK_TX_FTM_OE FSK_TX_FTM_BASEADDR,12,1 ++#define FSK_TX_FTM_TX_EN FSK_TX_FTM_BASEADDR,10,1 ++#define FSK_TX_FTM_FORCE_CARRIER_ON FSK_TX_FTM_BASEADDR,1,1 ++#define FSK_TX_FTM_FORCE_MARK_SPACE FSK_TX_FTM_BASEADDR,0,1 ++ ++#define FSK_TX_FTM_TX_CNT_BASEADDR 0x80090018 ++#define FSK_TX_FTM_TX_CNT_INT FSK_TX_FTM_TX_CNT_BASEADDR,8,4 ++#define FSK_TX_FTM_TX_INT_EN FSK_TX_FTM_TX_CNT_BASEADDR,4,1 ++#define FSK_TX_FTM_TX_INT_SRC_SEL FSK_TX_FTM_TX_CNT_BASEADDR,0,2 ++ ++#define AFE_REG_D2A_FSK_BIAS_BASEADDR 0x90200040 ++#define AFE_REG_D2A_FSK_BIAS_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,0,1 ++#define AFE_REG_D2A_FSK_TEST_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,10,1 ++#define AFE_REG_D2A_FSK_TEST_MODE AFE_REG_D2A_FSK_BIAS_BASEADDR,11,4 ++#define AFE_REG_D2A_FSK_TERM_INT_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,15,1 ++#define AFE_REG_D2A_FSK_RESETB_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,16,1 ++#define AFE_REG_D2A_FSK_REG_EN_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,17,1 ++#define AFE_REG_D2A_FSK_REG_EN_LKG_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,18,1 ++#define AFE_REG_D2A_FSK_REG_AMP_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,19,3 ++#define AFE_REG_D2A_FSK_REG_TEST_CTRL_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,22,2 ++#define AFE_REG_D2A_DSQ_RX_MODE AFE_REG_D2A_FSK_BIAS_BASEADDR,24,1 ++#define AFE_REG_D2A_DSQ_RX_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,25,1 ++#define AFE_REG_D2A_DSQ_HYST AFE_REG_D2A_FSK_BIAS_BASEADDR,26,2 ++#define AFE_REG_D2A_DSQ_RESETB_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,28,1 ++#define AFE_REG_D2A_FSK_CLKRX_ENA AFE_REG_D2A_FSK_BIAS_BASEADDR,29,1 ++ ++#define DMD_TEI_BASEADDR 0x3FFFEBE0 ++#define DMD_TEI_ENA DMD_TEI_BASEADDR,0,1 ++ ++#define xpt_shm_input_control0 0x90700270,0,8 ++#define xpt_shm_input_control1 0x90700270,8,8 ++#define xpt_shm_input_control2 0x90700270,16,8 ++#define xpt_shm_input_control3 0x90700270,24,8 ++#define xpt_shm_input_control4 0x90700274,0,8 ++#define xpt_shm_input_control5 0x90700274,8,8 ++#define xpt_shm_input_control6 0x90700274,16,8 ++#define xpt_shm_input_control7 0x90700274,24,8 ++ ++ ++#define xpt_shm_output_control0 0x90700278,0,8 ++#define xpt_shm_output_control1 0x90700278,8,8 ++#define xpt_shm_output_control2 0x90700278,16,8 ++#define xpt_shm_output_control3 0x90700278,24,8 ++#define xpt_shm_output_control4 0x9070027C,0,8 ++#define xpt_shm_output_control5 0x9070027C,8,8 ++#define xpt_shm_output_control6 0x9070027C,16,8 ++#define xpt_shm_output_control7 0x9070027C,24,8 ++ ++#define xpt_mode_27mhz 0x90700184,0,1 ++#define xpt_enable_pcr_count 0x90700184,1,1 ++ ++#define xcpu_ctrl_003c_reg 0x9072003C,0,4 ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif //__MXL58X_REGISTERS_H__ +diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c +index 20b4a65..4b6e0bc 100644 +--- a/drivers/media/dvb-frontends/si2168.c ++++ b/drivers/media/dvb-frontends/si2168.c +@@ -95,7 +95,7 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + goto err; + } + +- switch (c->delivery_system) { ++ switch (dev->delivery_system) { + case SYS_DVBT: + memcpy(cmd.args, "\xa0\x01", 2); + cmd.wlen = 2; +@@ -106,6 +106,11 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + cmd.wlen = 2; + cmd.rlen = 9; + break; ++ case SYS_DVBC_ANNEX_B: ++ memcpy(cmd.args, "\x98\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 10; ++ break; + case SYS_DVBT2: + memcpy(cmd.args, "\x50\x01", 2); + cmd.wlen = 2; +@@ -135,7 +140,7 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + if (*status & FE_HAS_LOCK) { + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; +- c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4; ++ c->cnr.stat[0].svalue = cmd.args[3] * 250; + } else { + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +@@ -150,6 +155,75 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + return ret; + } + ++static int si2168_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ ++ *snr = c->cnr.stat[0].scale == FE_SCALE_DECIBEL ? ((s32)c->cnr.stat[0].svalue / 250) * 328 : 0; ++ ++ return 0; ++} ++ ++static int si2168_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ ++ *strength = c->strength.stat[0].scale == FE_SCALE_DECIBEL ? ((100000 + (s32)c->strength.stat[0].svalue) / 1000) * 656 : 0; ++ ++ return 0; ++} ++ ++static int si2168_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2168_dev *dev = i2c_get_clientdata(client); ++ struct si2168_cmd cmd; ++ int ret; ++ ++ if (dev->fe_status & FE_HAS_LOCK) { ++ memcpy(cmd.args, "\x82\x00", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 3; ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "read_ber fe%d cmd_exec failed=%d\n", fe->id, ret); ++ goto err; ++ } ++ *ber = (u32)cmd.args[2] * cmd.args[1] & 0xf; ++ } else *ber = 1; ++ ++ return 0; ++err: ++ dev_err(&client->dev, "read_ber failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2168_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2168_dev *dev = i2c_get_clientdata(client); ++ struct si2168_cmd cmd; ++ int ret; ++ ++ if (dev->stat_resp & 0x10) { ++ memcpy(cmd.args, "\x84\x00", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 3; ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "read_ucblocks fe%d cmd_exec failed=%d\n", fe->id, ret); ++ goto err; ++ } ++ ++ *ucblocks = (u16)cmd.args[2] << 8 | cmd.args[1]; ++ } else *ucblocks = 0; ++ ++ return 0; ++err: ++ dev_err(&client->dev, "read_ucblocks failed=%d\n", ret); ++ return ret; ++} ++ + static int si2168_set_frontend(struct dvb_frontend *fe) + { + struct i2c_client *client = fe->demodulator_priv; +@@ -171,11 +245,19 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + } + + switch (c->delivery_system) { ++ case SYS_DVBC_ANNEX_B: ++ delivery_system = 0x10; ++ break; + case SYS_DVBT: + delivery_system = 0x20; + break; + case SYS_DVBC_ANNEX_A: + delivery_system = 0x30; ++ if (c->symbol_rate < 6000000) { ++ delivery_system = 0x10; ++ c->delivery_system = SYS_DVBC_ANNEX_B; ++ c->bandwidth_hz = 6000000; ++ } + break; + case SYS_DVBT2: + delivery_system = 0x70; +@@ -212,26 +294,6 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + goto err; + } + +- memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5); +- cmd.wlen = 5; +- cmd.rlen = 5; +- ret = si2168_cmd_execute(client, &cmd); +- if (ret) +- goto err; +- +- /* that has no big effect */ +- if (c->delivery_system == SYS_DVBT) +- memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6); +- else if (c->delivery_system == SYS_DVBC_ANNEX_A) +- memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6); +- else if (c->delivery_system == SYS_DVBT2) +- memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6); +- cmd.wlen = 6; +- cmd.rlen = 3; +- ret = si2168_cmd_execute(client, &cmd); +- if (ret) +- goto err; +- + if (c->delivery_system == SYS_DVBT2) { + /* select PLP */ + cmd.args[0] = 0x52; +@@ -298,6 +360,16 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + if (ret) + goto err; + } ++ else if (c->delivery_system == SYS_DVBC_ANNEX_B) { ++ memcpy(cmd.args, "\x14\x00\x02\x16", 4); ++ cmd.args[4] = ((c->symbol_rate / 1000) >> 0) & 0xff; ++ cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff; ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ } + + memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); + cmd.wlen = 6; +@@ -314,13 +386,13 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + if (ret) + goto err; + +- memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6); +- cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; +- cmd.wlen = 6; +- cmd.rlen = 4; +- ret = si2168_cmd_execute(client, &cmd); +- if (ret) +- goto err; ++ ++ memcpy(cmd.args, "\x14\x00\x08\x10\xcf\x33", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; + + memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6); + cmd.wlen = 6; +@@ -360,6 +432,9 @@ static int si2168_init(struct dvb_frontend *fe) + struct si2168_cmd cmd; + + dev_dbg(&client->dev, "\n"); ++ ++ if (dev->active) ++ return 0; + + /* initialize */ + memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); +@@ -480,6 +555,56 @@ static int si2168_init(struct dvb_frontend *fe) + dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, + dev->version >> 8 & 0xff, dev->version >> 0 & 0xff); + ++ /* TER FEF */ ++ memcpy(cmd.args, "\x51\x00", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 12; ++ cmd.args[1] = (dev->fef_inv & 1) << 3 | (dev->fef_pin & 7); ++ dev_dbg(&client->dev, "args=%*ph\n", cmd.wlen, cmd.args); ++ ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err set fef pip\n"); ++ } ++ ++ /* MP DEFAULTS */ ++ memcpy(cmd.args, "\x88\x01\x01\x01\x01", 5); ++ cmd.wlen = 5; ++ cmd.rlen = 2; ++ switch (dev->fef_pin) ++ { ++ case SI2168_MP_A: ++ cmd.args[1] = dev->fef_inv ? 3 : 2; ++ break; ++ case SI2168_MP_B: ++ cmd.args[2] = dev->fef_inv ? 3 : 2; ++ break; ++ case SI2168_MP_C: ++ cmd.args[3] = dev->fef_inv ? 3 : 2; ++ break; ++ case SI2168_MP_D: ++ cmd.args[4] = dev->fef_inv ? 3 : 2; ++ break; ++ } ++ dev_dbg(&client->dev, "args=%*ph\n", cmd.wlen, cmd.args); ++ ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err set mp defaults\n"); ++ } ++ ++ /* AGC */ ++ memcpy(cmd.args, "\x89\x01\x06\x12\x00\x00", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 3; ++ cmd.args[1] |= (dev->agc_inv & 1) << 7 | (dev->agc_pin & 7) << 4; ++ dev_dbg(&client->dev, "args=%*ph\n", cmd.wlen, cmd.args); ++ ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err set ter agc\n"); ++ } ++ + /* set ts mode */ + memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); + cmd.args[4] |= dev->ts_mode; +@@ -581,7 +706,7 @@ static int si2168_deselect(struct i2c_mux_core *muxc, u32 chan) + } + + static const struct dvb_frontend_ops si2168_ops = { +- .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A}, ++ .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B}, + .info = { + .name = "Silicon Labs Si2168", + .symbol_rate_min = 1000000, +@@ -615,6 +740,10 @@ static const struct dvb_frontend_ops si2168_ops = { + .set_frontend = si2168_set_frontend, + + .read_status = si2168_read_status, ++ .read_signal_strength = si2168_read_signal_strength, ++ .read_snr = si2168_read_snr, ++ .read_ber = si2168_read_ber, ++ .read_ucblocks = si2168_read_ucblocks, + }; + + static int si2168_probe(struct i2c_client *client, +@@ -705,6 +834,13 @@ static int si2168_probe(struct i2c_client *client, + dev->ts_mode = config->ts_mode; + dev->ts_clock_inv = config->ts_clock_inv; + dev->ts_clock_gapped = config->ts_clock_gapped; ++ dev->fef_pin = config->fef_pin; ++ dev->fef_inv = config->fef_inv; ++ dev->agc_pin = config->agc_pin; ++ dev->agc_inv = config->agc_inv; ++ ++ if (!dev->agc_pin) dev->agc_pin = SI2168_MP_A; ++ if (!dev->fef_pin) dev->fef_pin = SI2168_MP_B; + + dev_info(&client->dev, "Silicon Labs Si2168-%c%d%d successfully identified\n", + dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, +diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h +index 3225d0c..0b411b8 100644 +--- a/drivers/media/dvb-frontends/si2168.h ++++ b/drivers/media/dvb-frontends/si2168.h +@@ -45,6 +45,17 @@ struct si2168_config { + + /* TS clock gapped */ + bool ts_clock_gapped; ++ ++ /* Tuner control pins */ ++#define SI2168_MP_NOT_USED 1 ++#define SI2168_MP_A 2 ++#define SI2168_MP_B 3 ++#define SI2168_MP_C 4 ++#define SI2168_MP_D 5 ++ int agc_pin; ++ bool agc_inv; ++ int fef_pin; ++ bool fef_inv; + }; + + #endif +diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h +index 7843ccb..bc866be 100644 +--- a/drivers/media/dvb-frontends/si2168_priv.h ++++ b/drivers/media/dvb-frontends/si2168_priv.h +@@ -34,6 +34,7 @@ struct si2168_dev { + struct dvb_frontend fe; + enum fe_delivery_system delivery_system; + enum fe_status fe_status; ++ u8 stat_resp; + #define SI2168_CHIP_ID_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0) + #define SI2168_CHIP_ID_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0) + #define SI2168_CHIP_ID_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0) +@@ -45,6 +46,10 @@ struct si2168_dev { + u8 ts_mode; + bool ts_clock_inv; + bool ts_clock_gapped; ++ int fef_pin; ++ bool fef_inv; ++ int agc_pin; ++ bool agc_inv; + }; + + /* firmware command struct */ +diff --git a/drivers/media/dvb-frontends/si2183.c b/drivers/media/dvb-frontends/si2183.c +new file mode 100644 +index 0000000..1fd154d +--- /dev/null ++++ b/drivers/media/dvb-frontends/si2183.c +@@ -0,0 +1,1541 @@ ++/* ++ * Silicon Labs Si2183(2) DVB-T/T2/C/C2/S/S2 demodulator driver ++ * ++ * 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. ++ */ ++ ++#include "si2183.h" ++#include "dvb_frontend.h" ++#include ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) ++#define SI2183_USE_I2C_MUX ++#endif ++ ++#define SI2183_B60_FIRMWARE "dvb-demod-si2183-b60-01.fw" ++ ++#define SI2183_PROP_MODE 0x100a ++#define SI2183_PROP_DVBC_CONST 0x1101 ++#define SI2183_PROP_DVBC_SR 0x1102 ++#define SI2183_PROP_DVBT_HIER 0x1201 ++#define SI2183_PROP_DVBT2_MODE 0x1304 ++#define SI2183_PROP_DVBS2_SR 0x1401 ++#define SI2183_PROP_DVBS_SR 0x1501 ++#define SI2183_PROP_MCNS_CONST 0x1601 ++#define SI2183_PROP_MCNS_SR 0x1602 ++ ++#define SI2183_ARGLEN 30 ++struct si2183_cmd { ++ u8 args[SI2183_ARGLEN]; ++ unsigned wlen; ++ unsigned rlen; ++}; ++ ++static const struct dvb_frontend_ops si2183_ops; ++ ++LIST_HEAD(silist); ++ ++struct si_base { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ struct i2c_mux_core *muxc; ++#endif ++ struct list_head silist; ++ ++ u8 adr; ++ struct i2c_adapter *i2c; ++ u32 count; ++ ++ struct i2c_adapter *tuner_adapter; ++ ++#ifndef SI2183_USE_I2C_MUX ++ struct i2c_client *i2c_gate_client; ++#endif ++}; ++ ++/* state struct */ ++struct si2183_dev { ++ struct dvb_frontend fe; ++ enum fe_delivery_system delivery_system; ++ enum fe_status fe_status; ++ u8 stat_resp; ++ u16 snr; ++ bool active; ++ bool fw_loaded; ++ u8 ts_mode; ++ bool ts_clock_inv; ++ bool ts_clock_gapped; ++ u8 agc_mode; ++ struct si_base *base; ++ void (*RF_switch)(struct i2c_adapter * i2c,u8 rf_in,u8 flag); ++ u8 rf_in; ++ u8 active_fe; ++}; ++ ++/* Own I2C adapter locking is needed because of I2C gate logic. */ ++static int si2183_i2c_master_send_unlocked(const struct i2c_client *client, ++ const char *buf, int count) ++{ ++ int ret; ++ struct i2c_msg msg = { ++ .addr = client->addr, ++ .flags = 0, ++ .len = count, ++ .buf = (char *)buf, ++ }; ++ ++ ret = __i2c_transfer(client->adapter, &msg, 1); ++ return (ret == 1) ? count : ret; ++} ++ ++static int si2183_i2c_master_recv_unlocked(const struct i2c_client *client, ++ char *buf, int count) ++{ ++ int ret; ++ struct i2c_msg msg = { ++ .addr = client->addr, ++ .flags = I2C_M_RD, ++ .len = count, ++ .buf = buf, ++ }; ++ ++ ret = __i2c_transfer(client->adapter, &msg, 1); ++ return (ret == 1) ? count : ret; ++} ++ ++/* execute firmware command */ ++static int si2183_cmd_execute_unlocked(struct i2c_client *client, ++ struct si2183_cmd *cmd) ++{ ++ int ret; ++ unsigned long timeout; ++ ++ if (cmd->wlen) { ++ /* write cmd and args for firmware */ ++ ret = si2183_i2c_master_send_unlocked(client, cmd->args, ++ cmd->wlen); ++ if (ret < 0) { ++ goto err; ++ } else if (ret != cmd->wlen) { ++ ret = -EREMOTEIO; ++ goto err; ++ } ++ } ++ ++ if (cmd->rlen) { ++ /* wait cmd execution terminate */ ++ #define TIMEOUT 500 ++ timeout = jiffies + msecs_to_jiffies(TIMEOUT); ++ while (!time_after(jiffies, timeout)) { ++ ret = si2183_i2c_master_recv_unlocked(client, cmd->args, ++ cmd->rlen); ++ if (ret < 0) { ++ goto err; ++ } else if (ret != cmd->rlen) { ++ ret = -EREMOTEIO; ++ goto err; ++ } ++ ++ /* firmware ready? */ ++ if ((cmd->args[0] >> 7) & 0x01) ++ break; ++ } ++ ++ dev_dbg(&client->dev, "cmd execution took %d ms\n", ++ jiffies_to_msecs(jiffies) - ++ (jiffies_to_msecs(timeout) - TIMEOUT)); ++ ++ /* error bit set? */ ++ if ((cmd->args[0] >> 6) & 0x01) { ++ ret = -EREMOTEIO; ++ goto err; ++ } ++ ++ if (!((cmd->args[0] >> 7) & 0x01)) { ++ ret = -ETIMEDOUT; ++ goto err; ++ } ++ } ++ ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_cmd_execute(struct i2c_client *client, struct si2183_cmd *cmd) ++{ ++ int ret; ++ ++ i2c_lock_adapter(client->adapter); ++ ret = si2183_cmd_execute_unlocked(client, cmd); ++ i2c_unlock_adapter(client->adapter); ++ ++ return ret; ++} ++ ++static int si2183_set_prop(struct i2c_client *client, u16 prop, u16 *val) ++{ ++ struct si2183_cmd cmd; ++ int ret; ++ ++ cmd.args[0] = 0x14; ++ cmd.args[1] = 0x00; ++ cmd.args[2] = (u8) prop; ++ cmd.args[3] = (u8) (prop >> 8); ++ cmd.args[4] = (u8) (*val); ++ cmd.args[5] = (u8) (*val >> 8); ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2183_cmd_execute(client, &cmd); ++ *val = (cmd.args[2] | (cmd.args[3] << 8)); ++ return ret; ++} ++#if 0 ++static int si2183_get_prop(struct i2c_client *client, u16 prop, u16 *val) ++{ ++ struct si2183_cmd cmd; ++ int ret; ++ ++ cmd.args[0] = 0x15; ++ cmd.args[1] = 0x00; ++ cmd.args[2] = (u8) prop; ++ cmd.args[3] = (u8) (prop >> 8); ++ cmd.wlen = 4; ++ cmd.rlen = 4; ++ ret = si2183_cmd_execute(client, &cmd); ++ *val = (cmd.args[2] | (cmd.args[3] << 8)); ++ return ret; ++} ++#endif ++ ++static int si2183_read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ struct si2183_cmd cmd; ++ u16 agc; ++ ++ *status = 0; ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ ++ if ((dev->delivery_system != c->delivery_system) || (dev->delivery_system == 0)) ++ return 0; ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ memcpy(cmd.args, "\xa0\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 13; ++ dev->snr = 2; ++ break; ++ case SYS_DVBC_ANNEX_A: ++ memcpy(cmd.args, "\x90\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 9; ++ dev->snr = 2; ++ break; ++ case SYS_DVBC_ANNEX_B: ++ memcpy(cmd.args, "\x98\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 10; ++ dev->snr = 2; ++ break; ++ case SYS_DVBT2: ++ memcpy(cmd.args, "\x50\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 14; ++ dev->snr = 2; ++ break; ++ case SYS_DVBS: ++ memcpy(cmd.args, "\x60\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 10; ++ dev->snr = 5; ++ break; ++ case SYS_DVBS2: ++ memcpy(cmd.args, "\x70\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 13; ++ dev->snr = 5; ++ break; ++ case SYS_ISDBT: ++ memcpy(cmd.args, "\xa4\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 14; ++ dev->snr = 2; ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "read_status fe%d cmd_exec failed=%d\n", fe->id, ret); ++ goto err; ++ } ++ ++ dev->stat_resp = cmd.args[2]; ++ switch ((dev->stat_resp >> 1) & 0x03) { ++ case 0x01: ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; ++ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ break; ++ case 0x03: ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | ++ FE_HAS_SYNC | FE_HAS_LOCK; ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ c->cnr.stat[0].svalue = (s64) cmd.args[3] * 250; ++ dev->snr *= cmd.args[3] * 164; ++ break; ++ default: ++ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ break; ++ } ++ ++ dev->fe_status = *status; ++ ++ dev_dbg(&client->dev, "status=%02x args=%*ph\n", ++ *status, cmd.rlen, cmd.args); ++ ++ if (fe->ops.tuner_ops.get_rf_strength) ++ { ++ memcpy(cmd.args, "\x8a\x00\x00\x00\x00\x00", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "read_status fe%d cmd_exec failed=%d\n", fe->id, ret); ++ goto err; ++ } ++ dev_dbg(&client->dev, "status=%02x args=%*ph\n", ++ *status, cmd.rlen, cmd.args); ++ ++ agc = cmd.args[1]; ++ fe->ops.tuner_ops.get_rf_strength(fe, &agc); ++ } ++ ++ return 0; ++err: ++ dev_err(&client->dev, "read_status failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ ++ *snr = (dev->fe_status & FE_HAS_LOCK) ? dev->snr : 0; ++ ++ return 0; ++} ++ ++static int si2183_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ ++ *strength = c->strength.stat[0].scale == FE_SCALE_DECIBEL ? ((100000 + (s32)c->strength.stat[0].svalue) / 1000) * 656 : 0; ++ ++ return 0; ++} ++ ++static int si2183_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ int ret; ++ ++ if (dev->fe_status & FE_HAS_LOCK) { ++ memcpy(cmd.args, "\x82\x00", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "read_ber fe%d cmd_exec failed=%d\n", fe->id, ret); ++ goto err; ++ } ++ *ber = (u32)cmd.args[2] * cmd.args[1] & 0xf; ++ } else *ber = 1; ++ ++ return 0; ++err: ++ dev_err(&client->dev, "read_ber failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ int ret; ++ ++ if (dev->stat_resp & 0x10) { ++ memcpy(cmd.args, "\x84\x00", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "read_ucblocks fe%d cmd_exec failed=%d\n", fe->id, ret); ++ goto err; ++ } ++ ++ *ucblocks = (u16)cmd.args[2] << 8 | cmd.args[1]; ++ } else *ucblocks = 0; ++ ++ return 0; ++err: ++ dev_err(&client->dev, "read_ucblocks failed=%d\n", ret); ++ return ret; ++} ++ ++ ++static int si2183_set_dvbc(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ int ret; ++ u16 prop; ++ ++ memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6); ++ cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1; ++ cmd.wlen = 6; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if(ret){ ++ dev_err(&client->dev, "err set agc mode\n"); ++ } ++ /* dvb-c mode */ ++ prop = 0x38; ++ ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-c mode\n"); ++ return ret; ++ } ++ ++ switch (c->modulation) { ++ default: ++ case QAM_AUTO: ++ prop = 0; ++ break; ++ case QAM_16: ++ prop = 7; ++ break; ++ case QAM_32: ++ prop = 8; ++ break; ++ case QAM_64: ++ prop = 9; ++ break; ++ case QAM_128: ++ prop = 10; ++ break; ++ case QAM_256: ++ prop = 11; ++ break; ++ } ++ ret = si2183_set_prop(client, SI2183_PROP_DVBC_CONST, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-c constelation\n"); ++ return ret; ++ } ++ ++ /* symbol rate */ ++ prop = c->symbol_rate / 1000; ++ ret = si2183_set_prop(client, SI2183_PROP_DVBC_SR, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-c symbol rate\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int si2183_set_mcns(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ int ret; ++ u16 prop,symb; ++ ++ memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6); ++ cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1; ++ cmd.wlen = 6; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if(ret){ ++ dev_err(&client->dev, "err set agc mode\n"); ++ } ++ /* mcns mode */ ++ prop = 0x18; ++ ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set mcns mode\n"); ++ return ret; ++ } ++ ++ switch (c->modulation) { ++ default: ++ case QAM_64: ++ prop = 9; ++ symb = 5057; ++ break; ++ case QAM_256: ++ prop = 11; ++ symb = 5361; ++ break; ++ } ++ ret = si2183_set_prop(client, SI2183_PROP_MCNS_CONST, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set mcns constelation\n"); ++ return ret; ++ } ++ ++ /* symbol rate */ ++ ret = si2183_set_prop(client, SI2183_PROP_MCNS_SR, &symb); ++ if (ret) { ++ dev_err(&client->dev, "err set mcns symbol rate\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int gold_code_index (int gold_sequence_index) ++{ ++ unsigned int i, k , x_init; ++ u8 GOLD_PRBS[19] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++ for (k=0; kdtv_property_cache; ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ int ret; ++ u16 prop; ++ u32 pls_mode, pls_code; ++ ++ /*set SAT agc*/ ++ memcpy(cmd.args, "\x8a\x1d\x12\x0\x0\x0", 6); ++ cmd.args[1]= dev->agc_mode|0x18; ++ cmd.wlen = 6; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if(ret){ ++ dev_err(&client->dev, "err set agc mode\n"); ++ } ++ ++ /* set mode */ ++ prop = 0x8; ++ switch (c->delivery_system) { ++ default: ++ case SYS_DVBS: ++ prop |= 0x80; ++ break; ++ case SYS_DVBS2: ++ prop |= 0x90; ++ break; ++ case SYS_DSS: ++ prop |= 0xa0; ++ break; ++ } ++ if (c->inversion) ++ prop |= 0x100; ++ ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-s/s2 mode\n"); ++ return ret; ++ } ++ ++ /* symbol rate */ ++ prop = c->symbol_rate / 1000; ++ switch (c->delivery_system) { ++ default: ++ case SYS_DSS: ++ case SYS_DVBS: ++ ret = si2183_set_prop(client, SI2183_PROP_DVBS_SR, &prop); ++ break; ++ case SYS_DVBS2: ++ ret = si2183_set_prop(client, SI2183_PROP_DVBS2_SR, &prop); ++ /* stream_id selection */ ++ cmd.args[0] = 0x71; ++ cmd.args[1] = (u8) c->stream_id; ++ cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1; ++ cmd.wlen = 3; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ dev_warn(&client->dev, "dvb-s2: err selecting stream_id\n"); ++ ++ /* pls selection */ ++ pls_mode = c->stream_id == NO_STREAM_ID_FILTER ? 0 : (c->stream_id >> 26) & 3; ++ pls_code = c->stream_id == NO_STREAM_ID_FILTER ? 0 : (c->stream_id >> 8) & 0x3FFFF; ++ if (pls_mode) ++ pls_code = gold_code_index(pls_code); ++ cmd.args[0] = 0x73; ++ cmd.args[1] = pls_code > 0; ++ cmd.args[2] = cmd.args[3] = 0; ++ cmd.args[4] = (u8) pls_code; ++ cmd.args[5] = (u8) (pls_code >> 8); ++ cmd.args[6] = (u8) (pls_code >> 16); ++ cmd.args[7] = (u8) (pls_code >> 24); ++ cmd.wlen = 8; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ dev_warn(&client->dev, "dvb-s2: err set pls\n"); ++ } ++ ++ return 0; ++} ++ ++static int si2183_set_dvbt(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ int ret; ++ u16 prop; ++ ++ memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6); ++ cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1; ++ cmd.wlen = 6; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if(ret){ ++ dev_err(&client->dev, "err set agc mode\n"); ++ } ++ ++ if (c->bandwidth_hz == 0) { ++ return -EINVAL; ++ } else if (c->bandwidth_hz <= 2000000) ++ prop = 0x02; ++ else if (c->bandwidth_hz <= 5000000) ++ prop = 0x05; ++ else if (c->bandwidth_hz <= 6000000) ++ prop = 0x06; ++ else if (c->bandwidth_hz <= 7000000) ++ prop = 0x07; ++ else if (c->bandwidth_hz <= 8000000) ++ prop = 0x08; ++ else if (c->bandwidth_hz <= 9000000) ++ prop = 0x09; ++ else if (c->bandwidth_hz <= 10000000) ++ prop = 0x0a; ++ else ++ prop = 0x0f; ++ ++ switch (c->delivery_system) { ++ default: ++ case SYS_DVBT: ++ prop |= 0x20; ++ break; ++ case SYS_DVBT2: ++ prop |= 0x70; ++ break; ++ } ++ ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-t mode\n"); ++ return ret; ++ } ++ ++ /* hierarchy - HP = 0 / LP = 1 */ ++ prop = c->hierarchy == HIERARCHY_1 ? 1 : 0; ++ ret = si2183_set_prop(client, SI2183_PROP_DVBT_HIER, &prop); ++ if (ret) ++ dev_warn(&client->dev, "dvb-t: err set hierarchy\n"); ++ ++ if (c->delivery_system == SYS_DVBT2) { ++ /* stream_id selection */ ++ cmd.args[0] = 0x52; ++ cmd.args[1] = (u8) c->stream_id; ++ cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1; ++ cmd.wlen = 3; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ dev_warn(&client->dev, "dvb-t2: err selecting stream_id\n"); ++ ++ /* dvb-t2 mode - any=0 / base=1 / lite=2 */ ++ prop = 0; ++ ret = si2183_set_prop(client, SI2183_PROP_DVBT2_MODE, &prop); ++ if (ret) ++ dev_warn(&client->dev, "dvb-t2: err set mode\n"); ++ } ++ ++ return 0; ++} ++ ++static int si2183_set_isdbt(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ int ret; ++ u16 prop; ++ ++ memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6); ++ cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1; ++ cmd.wlen = 6; ++ cmd.rlen = 3; ++ ret = si2183_cmd_execute(client, &cmd); ++ if(ret){ ++ dev_err(&client->dev, "err set agc mode\n"); ++ } ++ if (c->bandwidth_hz == 0) { ++ return -EINVAL; ++ } else if (c->bandwidth_hz <= 2000000) ++ prop = 0x02; ++ else if (c->bandwidth_hz <= 5000000) ++ prop = 0x05; ++ else if (c->bandwidth_hz <= 6000000) ++ prop = 0x06; ++ else if (c->bandwidth_hz <= 7000000) ++ prop = 0x07; ++ else if (c->bandwidth_hz <= 8000000) ++ prop = 0x08; ++ else if (c->bandwidth_hz <= 9000000) ++ prop = 0x09; ++ else if (c->bandwidth_hz <= 10000000) ++ prop = 0x0a; ++ else ++ prop = 0x0f; ++ ++ /* ISDB-T mode */ ++ prop |= 0x40; ++ ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-t mode\n"); ++ return ret; ++ } ++ return 0; ++} ++ ++static int si2183_set_frontend(struct dvb_frontend *fe) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ struct si2183_cmd cmd; ++ ++ dev_dbg(&client->dev, ++ "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u stream_id=%d\n", ++ c->delivery_system, c->modulation, c->frequency, ++ c->bandwidth_hz, c->symbol_rate, c->inversion, ++ c->stream_id); ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ if(dev->RF_switch) ++ { ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_B: ++ case SYS_ISDBT: ++ dev->RF_switch(dev->base->i2c,dev->rf_in,1); ++ ++ break; ++ ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ case SYS_DSS: ++ default: ++ dev->RF_switch(dev->base->i2c,dev->rf_in,0); ++ break; ++ ++ } ++ } ++ ++ if (fe->ops.tuner_ops.set_params) { ++#ifndef SI2183_USE_I2C_MUX ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++#endif ++ ret = fe->ops.tuner_ops.set_params(fe); ++#ifndef SI2183_USE_I2C_MUX ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++#endif ++ if (ret) { ++ dev_err(&client->dev, "err setting tuner params\n"); ++ goto err; ++ } ++ } ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ ret = si2183_set_dvbt(fe); ++ break; ++ case SYS_DVBC_ANNEX_A: ++ ret = si2183_set_dvbc(fe); ++ break; ++ case SYS_DVBC_ANNEX_B: ++ ret= si2183_set_mcns(fe); ++ break; ++ case SYS_ISDBT: ++ ret = si2183_set_isdbt(fe); ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ case SYS_DSS: ++ ret = si2183_set_dvbs(fe); ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ /* dsp restart */ ++ memcpy(cmd.args, "\x85", 1); ++ cmd.wlen = 1; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err restarting dsp\n"); ++ return ret; ++ } ++ ++ dev->delivery_system = c->delivery_system; ++ return 0; ++err: ++ dev_err(&client->dev, "set_params failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_init(struct dvb_frontend *fe) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret = 0, len, remaining; ++ const struct firmware *fw; ++ const char *fw_name; ++ struct si2183_cmd cmd; ++ unsigned int chip_id; ++ u16 prop; ++ ++ dev_dbg(&client->dev, "\n"); ++ ++ if (dev->active_fe) { ++ dev->active_fe |= (1 << fe->id); ++ return 0; ++ } ++ ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ ++ /* initialize */ ++ memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); ++ cmd.wlen = 13; ++ cmd.rlen = 0; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ if (dev->fw_loaded) { ++ /* resume */ ++ memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); ++ cmd.wlen = 8; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ memcpy(cmd.args, "\x85", 1); ++ cmd.wlen = 1; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ goto warm; ++ } ++ ++ /* power up */ ++ memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); ++ cmd.wlen = 8; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ /* query chip revision */ ++ memcpy(cmd.args, "\x02", 1); ++ cmd.wlen = 1; ++ cmd.rlen = 13; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 | ++ cmd.args[4] << 0; ++ ++ #define SI2183_B60 ('B' << 24 | 83 << 16 | '6' << 8 | '0' << 0) ++ ++ switch (chip_id) { ++ case SI2183_B60: ++ fw_name = SI2183_B60_FIRMWARE; ++ break; ++ default: ++ dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", ++ cmd.args[2], cmd.args[1], ++ cmd.args[3], cmd.args[4]); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", ++ cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); ++ ++ ret = request_firmware(&fw, fw_name, &client->dev); ++ if (ret) { ++ dev_err(&client->dev, ++ "firmware file '%s' not found\n", ++ fw_name); ++ goto err; ++ } ++ ++ dev_info(&client->dev, "downloading firmware from file '%s'\n", ++ fw_name); ++ ++ for (remaining = fw->size; remaining > 0; remaining -= 17) { ++ len = fw->data[fw->size - remaining]; ++ if (len > SI2183_ARGLEN) { ++ ret = -EINVAL; ++ break; ++ } ++ memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); ++ cmd.wlen = len; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ break; ++ } ++ release_firmware(fw); ++ ++ if (ret) { ++ dev_err(&client->dev, "firmware download failed %d\n", ret); ++ goto err; ++ } ++ ++ memcpy(cmd.args, "\x01\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 1; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ /* query firmware version */ ++ memcpy(cmd.args, "\x11", 1); ++ cmd.wlen = 1; ++ cmd.rlen = 10; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ dev_info(&client->dev, "firmware version: %c.%c.%d\n", ++ cmd.args[6], cmd.args[7], cmd.args[8]); ++ ++ /* set ts mode */ ++ memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); ++ cmd.args[4] |= dev->ts_mode; ++ if (dev->ts_clock_gapped) ++ cmd.args[4] |= 0x40; ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ ++ /* FER resol */ ++ memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err set FER resol\n"); ++ return ret; ++ } ++ ++ /* DD IEN */ ++ memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err set dd ien\n"); ++ return ret; ++ } ++ ++ /* int sense */ ++ memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err set int sense\n"); ++ return ret; ++ } ++ ++/* ++ memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5); ++ cmd.wlen = 5; ++ cmd.rlen = 5; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) { ++ dev_err(&client->dev, "err set x88\n"); ++ } ++*/ ++ ++ prop = 0x10; ++ ret = si2183_set_prop(client, 0x100f, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set 0x100f\n"); ++ return ret; ++ } ++ ++// prop = 0x08e3 | (dev->ts_clock_inv ? 0x0000 : 0x1000); ++ prop = 0x1104; ++ ret = si2183_set_prop(client, 0x1009, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set par_ts\n"); ++ return ret; ++ } ++ ++ prop = 0x330C ; ++ ret = si2183_set_prop(client, 0x1008, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set ser_ts\n"); ++ return ret; ++ } ++ ++ dev->fw_loaded = true; ++warm: ++ dev->active = true; ++ dev->active_fe |= (1 << fe->id); ++ return 0; ++ ++err: ++ dev_dbg(&client->dev, "init failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_sleep(struct dvb_frontend *fe) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ int ret; ++ struct si2183_cmd cmd; ++ ++ dev_dbg(&client->dev, "\n"); ++ ++ dev->active_fe &= ~(1 << fe->id); ++ if (dev->active_fe) ++ return 0; ++ ++ dev->active = false; ++ ++ memcpy(cmd.args, "\x13", 1); ++ cmd.wlen = 1; ++ cmd.rlen = 0; ++ ret = si2183_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *s) ++{ ++ s->min_delay_ms = 900; ++ ++ return 0; ++} ++ ++#ifdef SI2183_USE_I2C_MUX ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++static int si2183_select(struct i2c_mux_core *muxc, u32 chan) ++{ ++ struct i2c_client *client = i2c_mux_priv(muxc); ++#else ++static int si2183_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) ++{ ++ struct i2c_client *client = mux_priv; ++#endif ++ int ret; ++ struct si2183_cmd cmd; ++ ++ /* open I2C gate */ ++ memcpy(cmd.args, "\xc0\x0d\x01", 3); ++ cmd.wlen = 3; ++ cmd.rlen = 0; ++ ret = si2183_cmd_execute_unlocked(client, &cmd); ++ if (ret) ++ goto err; ++ ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++static int si2183_deselect(struct i2c_mux_core *muxc, u32 chan) ++{ ++ struct i2c_client *client = i2c_mux_priv(muxc); ++#else ++static int si2183_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) ++{ ++ struct i2c_client *client = mux_priv; ++#endif ++ int ret; ++ struct si2183_cmd cmd; ++ ++ /* close I2C gate */ ++ memcpy(cmd.args, "\xc0\x0d\x00", 3); ++ cmd.wlen = 3; ++ cmd.rlen = 0; ++ ret = si2183_cmd_execute_unlocked(client, &cmd); ++ if (ret) ++ goto err; ++ ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++#else ++static int i2c_gate_ctrl(struct dvb_frontend* fe, int enable) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ struct si2183_cmd cmd; ++ ++ memcpy(cmd.args, "\xc0\x0d\x00", 3); ++ if (enable) ++ cmd.args[2] = 1; ++ cmd.wlen = 3; ++ cmd.rlen = 0; ++ return si2183_cmd_execute(dev->base->i2c_gate_client, &cmd); ++} ++#endif ++ ++static int si2183_tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, unsigned int *delay, enum fe_status *status) ++{ ++ *delay = HZ / 5; ++ if (re_tune) { ++ int ret = si2183_set_frontend(fe); ++ if (ret) ++ return ret; ++ } ++ return si2183_read_status(fe, status); ++} ++ ++static int si2183_get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++static int si2183_set_property(struct dvb_frontend *fe, ++ struct dtv_property *p) ++{ ++ int ret = 0; ++ ++ switch (p->cmd) { ++ case DTV_DELIVERY_SYSTEM: ++ switch (p->u.data) { ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ case SYS_DSS: ++ fe->ops.info.frequency_min = 950000; ++ fe->ops.info.frequency_max = 2150000; ++ fe->ops.info.frequency_stepsize = 0; ++ break; ++ case SYS_ISDBT: ++ fe->ops.info.frequency_min = 42000000; ++ fe->ops.info.frequency_max = 1002000000; ++ fe->ops.info.frequency_stepsize = 0; ++ break; ++ case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_B: ++ fe->ops.info.frequency_min = 47000000; ++ fe->ops.info.frequency_max = 862000000; ++ fe->ops.info.frequency_stepsize = 62500; ++ break; ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ fe->ops.info.frequency_min = 174000000; ++ fe->ops.info.frequency_max = 862000000; ++ fe->ops.info.frequency_stepsize = 250000; ++ break; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++ ++static int send_diseqc_cmd(struct dvb_frontend *fe, ++ u8 cont_tone, u8 tone_burst, u8 burst_sel, ++ u8 end_seq, u8 msg_len, u8 *msg) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_cmd cmd; ++ u8 enable = 1; ++ ++ cmd.args[0] = 0x8c; ++ cmd.args[1] = enable | (cont_tone << 1) ++ | (tone_burst << 2) | (burst_sel << 3) ++ | (end_seq << 4) | (msg_len << 5); ++ ++ if (msg_len > 0) ++ memcpy(&cmd.args[2], msg, msg_len); ++ ++ cmd.wlen = 8; ++ cmd.rlen = 1; ++ return si2183_cmd_execute(client, &cmd); ++} ++ ++static int si2183_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ int ret; ++ u8 cont_tone; ++ ++ switch (tone) { ++ case SEC_TONE_ON: ++ cont_tone = 1; ++ break; ++ case SEC_TONE_OFF: ++ cont_tone = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ret = send_diseqc_cmd(fe, cont_tone, 0, 0, 1, 0, NULL); ++ if (ret) ++ goto err; ++ ++ return 0; ++err: ++ dev_err(&client->dev, "set_tone failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_diseqc_send_burst(struct dvb_frontend *fe, ++ enum fe_sec_mini_cmd burst) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ int ret; ++ u8 burst_sel; ++ ++ switch (burst) { ++ case SEC_MINI_A: ++ burst_sel = 0; ++ break; ++ case SEC_MINI_B: ++ burst_sel = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ret = send_diseqc_cmd(fe, 0, 1, burst_sel, 1, 0, NULL); ++ if (ret) ++ goto err; ++ ++ return 0; ++err: ++ dev_err(&client->dev, "set_tone failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_diseqc_send_msg(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *d) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ int ret; ++ u8 remaining = d->msg_len; ++ u8 *p = d->msg; ++ u8 len = 0; ++ ++ while (remaining > 0) { ++ p += len; ++ len = (remaining > 6) ? 6 : remaining; ++ remaining -= len; ++ ret = send_diseqc_cmd(fe, 0, 0, 0, ++ (remaining == 0) ? 1 : 0, len, p); ++ if (ret) ++ goto err; ++ msleep(50); ++ } ++ ++ return 0; ++err: ++ dev_err(&client->dev, "set_tone failed=%d\n", ret); ++ return ret; ++} ++ ++static const struct dvb_frontend_ops si2183_ops = { ++ .delsys = {SYS_DVBT, SYS_DVBT2, ++ SYS_ISDBT, ++ SYS_DVBC_ANNEX_A,SYS_DVBC_ANNEX_B, ++ SYS_DVBS, SYS_DVBS2, SYS_DSS}, ++ .info = { ++ .name = "Silicon Labs Si2183", ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = 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_32 | ++ FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | ++ FE_CAN_QAM_256 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_MUTE_TS | ++ FE_CAN_2G_MODULATION | ++ FE_CAN_MULTISTREAM ++ }, ++ ++ .get_tune_settings = si2183_get_tune_settings, ++ ++ .init = si2183_init, ++ .sleep = si2183_sleep, ++ ++ .set_frontend = si2183_set_frontend, ++ ++ .read_status = si2183_read_status, ++ .read_signal_strength = si2183_read_signal_strength, ++ .read_snr = si2183_read_snr, ++ .read_ber = si2183_read_ber, ++ .read_ucblocks = si2183_read_ucblocks, ++ ++ .get_frontend_algo = si2183_get_algo, ++ .tune = si2183_tune, ++ ++ .set_property = si2183_set_property, ++ ++ .set_tone = si2183_set_tone, ++ .diseqc_send_burst = si2183_diseqc_send_burst, ++ .diseqc_send_master_cmd = si2183_diseqc_send_msg, ++#ifndef SI2183_USE_I2C_MUX ++ .i2c_gate_ctrl = i2c_gate_ctrl, ++#endif ++}; ++ ++ ++static struct si_base *match_base(struct i2c_adapter *i2c, u8 adr) ++{ ++ struct si_base *p; ++ ++ list_for_each_entry(p, &silist, silist) ++ if (p->i2c == i2c)// && p->adr == adr) lja: TO FIX ++ return p; ++ return NULL; ++} ++ ++static int si2183_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct si2183_config *config = client->dev.platform_data; ++ struct si2183_dev *dev; ++ struct si_base *base; ++ int ret; ++ ++ dev_dbg(&client->dev, "\n"); ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ if (!dev) { ++ ret = -ENOMEM; ++ dev_err(&client->dev, "kzalloc() failed\n"); ++ goto err; ++ } ++ ++ base = match_base(client->adapter, client->addr); ++ if (base) { ++ base->count++; ++ dev->base = base; ++ } else { ++ base = kzalloc(sizeof(struct si_base), GFP_KERNEL); ++ if (!base) ++ goto err_kfree; ++ base->i2c = client->adapter; ++ base->adr = client->addr; ++ base->count = 1; ++ dev->base = base; ++ list_add(&base->silist, &silist); ++ ++#ifdef SI2183_USE_I2C_MUX ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ /* create mux i2c adapter for tuner */ ++ base->muxc = i2c_mux_alloc(client->adapter, &client->adapter->dev, ++ 1, 0, I2C_MUX_LOCKED, ++ si2183_select, si2183_deselect); ++ if (!base->muxc) { ++ ret = -ENOMEM; ++ goto err_base_kfree; ++ } ++ base->muxc->priv = client; ++ ret = i2c_mux_add_adapter(base->muxc, 0, 0, 0); ++ if (ret) ++ goto err_base_kfree; ++ base->tuner_adapter = base->muxc->adapter[0]; ++#else ++ /* create mux i2c adapter for tuners */ ++ base->tuner_adapter = i2c_add_mux_adapter(client->adapter, &client->adapter->dev, ++ client, 0, 0, 0, si2183_select, si2183_deselect); ++ if (base->tuner_adapter == NULL) { ++ ret = -ENODEV; ++ goto err_base_kfree; ++ } ++#endif ++#else ++ base->tuner_adapter = client->adapter; ++ base->i2c_gate_client = client; ++#endif ++ } ++ ++ /* create dvb_frontend */ ++ memcpy(&dev->fe.ops, &si2183_ops, sizeof(struct dvb_frontend_ops)); ++ dev->fe.demodulator_priv = client; ++ *config->i2c_adapter = base->tuner_adapter; ++ *config->fe = &dev->fe; ++ dev->ts_mode = config->ts_mode; ++ dev->ts_clock_inv = config->ts_clock_inv; ++ dev->ts_clock_gapped = config->ts_clock_gapped; ++ dev->agc_mode = config->agc_mode; ++ dev->RF_switch = config->RF_switch; ++ dev->rf_in = config->rf_in; ++ dev->fw_loaded = false; ++ dev->snr = 0; ++ dev->stat_resp = 0; ++ ++ dev->active_fe = 0; ++ ++ i2c_set_clientdata(client, dev); ++ ++#ifndef SI2183_USE_I2C_MUX ++ /* leave gate open for tuner to init */ ++ i2c_gate_ctrl(&dev->fe, 1); ++#endif ++ dev_info(&client->dev, "Silicon Labs Si2183 successfully attached\n"); ++ return 0; ++err_base_kfree: ++ kfree(base); ++err_kfree: ++ kfree(dev); ++err: ++ dev_dbg(&client->dev, "probe failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2183_remove(struct i2c_client *client) ++{ ++ struct si2183_dev *dev = i2c_get_clientdata(client); ++ ++ dev_dbg(&client->dev, "\n"); ++ ++ dev->base->count--; ++ if (dev->base->count == 0) { ++#ifdef SI2183_USE_I2C_MUX ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ i2c_mux_del_adapters(dev->base->muxc); ++#else ++ i2c_del_mux_adapter(dev->base->tuner_adapter); ++#endif ++#endif ++ list_del(&dev->base->silist); ++ kfree(dev->base); ++ } ++ ++ dev->fe.ops.release = NULL; ++ dev->fe.demodulator_priv = NULL; ++ ++ kfree(dev); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id si2183_id_table[] = { ++ {"si2183", 0}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, si2183_id_table); ++ ++static struct i2c_driver si2183_driver = { ++ .driver = { ++ .name = "si2183", ++ }, ++ .probe = si2183_probe, ++ .remove = si2183_remove, ++ .id_table = si2183_id_table, ++}; ++ ++module_i2c_driver(si2183_driver); ++ ++MODULE_AUTHOR("Luis Alves "); ++MODULE_DESCRIPTION("Silicon Labs Si2183 DVB-T/T2/C/C2/S/S2 demodulator driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/dvb-frontends/si2183.h b/drivers/media/dvb-frontends/si2183.h +new file mode 100644 +index 0000000..033fe87 +--- /dev/null ++++ b/drivers/media/dvb-frontends/si2183.h +@@ -0,0 +1,55 @@ ++/* ++ * Silicon Labs Si2183(2) DVB-T/T2/C/C2/S/S2 demodulator driver ++ * ++ * 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. ++ */ ++ ++#ifndef SI2183_H ++#define SI2183_H ++ ++#include ++/* ++ * I2C address ++ * 0x64 ++ */ ++struct si2183_config { ++ /* ++ * frontend ++ * returned by driver ++ */ ++ struct dvb_frontend **fe; ++ ++ /* ++ * tuner I2C adapter ++ * returned by driver ++ */ ++ struct i2c_adapter **i2c_adapter; ++ ++ /* TS mode */ ++#define SI2183_TS_PARALLEL 0x06 ++#define SI2183_TS_SERIAL 0x03 ++ u8 ts_mode; ++ ++ /* TS clock inverted */ ++ bool ts_clock_inv; ++ ++ /* TS clock gapped */ ++ bool ts_clock_gapped; ++ /*agc*/ ++ u8 agc_mode; ++ ++ /*rf switch*/ ++ void (*RF_switch)(struct i2c_adapter * i2c,u8 rf_in,u8 flag); ++ /*rf no.*/ ++ u8 rf_in; ++}; ++ ++#endif +diff --git a/drivers/media/dvb-frontends/stv0288.c b/drivers/media/dvb-frontends/stv0288.c +index 45cbc89..2d0341d 100644 +--- a/drivers/media/dvb-frontends/stv0288.c ++++ b/drivers/media/dvb-frontends/stv0288.c +@@ -382,6 +382,9 @@ static int stv0288_read_status(struct dvb_frontend *fe, enum fe_status *status) + dprintk("stv0288 has locked\n"); + } + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, *status & FE_HAS_LOCK); ++ + return 0; + } + +@@ -416,6 +419,9 @@ static int stv0288_sleep(struct dvb_frontend *fe) + { + struct stv0288_state *state = fe->demodulator_priv; + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + stv0288_writeregI(state, 0x41, 0x84); + state->initialised = 0; + +@@ -532,6 +538,10 @@ static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) + static void stv0288_release(struct dvb_frontend *fe) + { + struct stv0288_state *state = fe->demodulator_priv; ++ ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + kfree(state); + } + +diff --git a/drivers/media/dvb-frontends/stv0288.h b/drivers/media/dvb-frontends/stv0288.h +index 803acb9..6e8263c 100644 +--- a/drivers/media/dvb-frontends/stv0288.h ++++ b/drivers/media/dvb-frontends/stv0288.h +@@ -40,6 +40,9 @@ struct stv0288_config { + int min_delay_ms; + + int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); ++ ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); + }; + + #if IS_REACHABLE(CONFIG_DVB_STV0288) +diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c +index 25bdf6e..ff4c7ef 100644 +--- a/drivers/media/dvb-frontends/stv090x.c ++++ b/drivers/media/dvb-frontends/stv090x.c +@@ -41,6 +41,10 @@ + static unsigned int verbose; + module_param(verbose, int, 0644); + ++static unsigned int ts_nosync=1; ++module_param(ts_nosync, int, 0644); ++MODULE_PARM_DESC(ts_nosync, "TS FIFO Minimum latence mode (default:on)"); ++ + /* internal params node */ + struct stv090x_dev { + /* pointer for internal params, one for each pair of demods */ +@@ -739,14 +743,8 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 + buf[1] = reg & 0xff; + memcpy(&buf[2], data, count); + +- if (unlikely(*state->verbose >= FE_DEBUGREG)) { +- int i; +- +- printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg); +- for (i = 0; i < count; i++) +- printk(" %02x", data[i]); +- printk("\n"); +- } ++ dprintk(FE_DEBUGREG, 1, "%s [0x%04x]: %*ph", ++ __func__, reg, count, data); + + ret = i2c_transfer(state->i2c, &i2c_msg, 1); + if (ret != 1) { +@@ -3435,18 +3433,40 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) + return -1; + } + ++static int stv090x_set_pls(struct stv090x_state *state, u8 pls_mode, u32 pls_code) ++{ ++ if (pls_mode == 0 && pls_code == 0) ++ pls_code = 1; ++ pls_mode &= 0x03; ++ pls_code &= 0x3FFFF; ++ ++ dprintk(FE_DEBUG, 1, "Set PLS code %d (mode %d)", pls_code, pls_mode); ++ if (STV090x_WRITE_DEMOD(state, PLROOT2, (pls_mode<<2) | (pls_code>>16)) < 0) ++ goto err; ++ if (STV090x_WRITE_DEMOD(state, PLROOT1, pls_code>>8) < 0) ++ goto err; ++ if (STV090x_WRITE_DEMOD(state, PLROOT0, pls_code) < 0) ++ goto err; ++ return 0; ++err: ++ dprintk(FE_ERROR, 1, "I/O error"); ++ return -1; ++} ++ + static int stv090x_set_mis(struct stv090x_state *state, int mis) + { + u32 reg; + +- if (mis < 0 || mis > 255) { ++ if (mis == NO_STREAM_ID_FILTER) { + dprintk(FE_DEBUG, 1, "Disable MIS filtering"); ++ stv090x_set_pls(state, 0, 0); + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + } else { + dprintk(FE_DEBUG, 1, "Enable MIS filtering - %d", mis); ++ stv090x_set_pls(state, (mis>>26) & 0x3, (mis>>8) & 0x3FFFF); + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x01); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) +@@ -3510,109 +3530,6 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe) + return DVBFE_ALGO_SEARCH_ERROR; + } + +-static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) +-{ +- struct stv090x_state *state = fe->demodulator_priv; +- u32 reg, dstatus; +- u8 search_state; +- +- *status = 0; +- +- dstatus = STV090x_READ_DEMOD(state, DSTATUS); +- if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD)) +- *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; +- +- reg = STV090x_READ_DEMOD(state, DMDSTATE); +- search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); +- +- switch (search_state) { +- case 0: /* searching */ +- case 1: /* first PLH detected */ +- default: +- dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)"); +- break; +- +- case 2: /* DVB-S2 mode */ +- dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2"); +- if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) { +- reg = STV090x_READ_DEMOD(state, PDELSTATUS1); +- if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) { +- *status |= FE_HAS_VITERBI; +- reg = STV090x_READ_DEMOD(state, TSSTATUS); +- if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) +- *status |= FE_HAS_SYNC | FE_HAS_LOCK; +- } +- } +- break; +- +- case 3: /* DVB-S1/legacy mode */ +- dprintk(FE_DEBUG, 1, "Delivery system: DVB-S"); +- if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) { +- reg = STV090x_READ_DEMOD(state, VSTATUSVIT); +- if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { +- *status |= FE_HAS_VITERBI; +- reg = STV090x_READ_DEMOD(state, TSSTATUS); +- if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) +- *status |= FE_HAS_SYNC | FE_HAS_LOCK; +- } +- } +- break; +- } +- +- return 0; +-} +- +-static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) +-{ +- struct stv090x_state *state = fe->demodulator_priv; +- +- s32 count_4, count_3, count_2, count_1, count_0, count; +- u32 reg, h, m, l; +- enum fe_status status; +- +- stv090x_read_status(fe, &status); +- if (!(status & FE_HAS_LOCK)) { +- *per = 1 << 23; /* Max PER */ +- } else { +- /* Counter 2 */ +- reg = STV090x_READ_DEMOD(state, ERRCNT22); +- h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD); +- +- reg = STV090x_READ_DEMOD(state, ERRCNT21); +- m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD); +- +- reg = STV090x_READ_DEMOD(state, ERRCNT20); +- l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD); +- +- *per = ((h << 16) | (m << 8) | l); +- +- count_4 = STV090x_READ_DEMOD(state, FBERCPT4); +- count_3 = STV090x_READ_DEMOD(state, FBERCPT3); +- count_2 = STV090x_READ_DEMOD(state, FBERCPT2); +- count_1 = STV090x_READ_DEMOD(state, FBERCPT1); +- count_0 = STV090x_READ_DEMOD(state, FBERCPT0); +- +- if ((!count_4) && (!count_3)) { +- count = (count_2 & 0xff) << 16; +- count |= (count_1 & 0xff) << 8; +- count |= count_0 & 0xff; +- } else { +- count = 1 << 24; +- } +- if (count == 0) +- *per = 1; +- } +- if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0) +- goto err; +- if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) +- goto err; +- +- return 0; +-err: +- dprintk(FE_ERROR, 1, "I/O error"); +- return -1; +-} +- + static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) + { + int res = 0; +@@ -3649,12 +3566,13 @@ static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) + return res; + } + +-static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++static int stv090x_read_rflevel(struct dvb_frontend *fe) + { + struct stv090x_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 reg; + s32 agc_0, agc_1, agc; +- s32 str; ++ s32 rflevel; + + reg = STV090x_READ_DEMOD(state, AGCIQIN1); + agc_1 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); +@@ -3662,25 +3580,27 @@ static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) + agc_0 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); + agc = MAKEWORD16(agc_1, agc_0); + +- str = stv090x_table_lookup(stv090x_rf_tab, ++ rflevel = stv090x_table_lookup(stv090x_rf_tab, + ARRAY_SIZE(stv090x_rf_tab) - 1, agc); + if (agc > stv090x_rf_tab[0].read) +- str = 0; ++ rflevel = 0; + else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read) +- str = -100; +- *strength = (str + 100) * 0xFFFF / 100; ++ rflevel = -100; ++ ++ p->strength.len = 1; ++ p->strength.stat[0].scale = FE_SCALE_DECIBEL; ++ p->strength.stat[0].svalue = rflevel * 1000; + + return 0; + } + +-static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) ++static int stv090x_read_cnr(struct dvb_frontend *fe) + { + struct stv090x_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 reg_0, reg_1, reg, i; +- s32 val_0, val_1, val = 0; ++ s32 val_0, val_1, val = 0, snr = 0; + u8 lock_f; +- s32 div; +- u32 last; + + switch (state->delsys) { + case STV090x_DVBS2: +@@ -3697,10 +3617,8 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) + msleep(1); + } + val /= 16; +- last = ARRAY_SIZE(stv090x_s2cn_tab) - 1; +- div = stv090x_s2cn_tab[0].read - +- stv090x_s2cn_tab[last].read; +- *cnr = 0xFFFF - ((val * 0xFFFF) / div); ++ snr = stv090x_table_lookup(stv090x_s2cn_tab, ++ ARRAY_SIZE(stv090x_s2cn_tab) - 1, val); + } + break; + +@@ -3719,16 +3637,195 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) + msleep(1); + } + val /= 16; +- last = ARRAY_SIZE(stv090x_s1cn_tab) - 1; +- div = stv090x_s1cn_tab[0].read - +- stv090x_s1cn_tab[last].read; +- *cnr = 0xFFFF - ((val * 0xFFFF) / div); ++ snr = stv090x_table_lookup(stv090x_s1cn_tab, ++ ARRAY_SIZE(stv090x_s1cn_tab) - 1, val); + } + break; + default: + break; + } + ++ p->cnr.len = 1; ++ p->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ p->cnr.stat[0].svalue = 100 * snr; ++ ++ return 0; ++} ++ ++static int stv090x_read_per(struct dvb_frontend *fe, enum fe_status status) ++{ ++ struct stv090x_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ s32 count_4, count_3, count_2, count_1, count_0, count; ++ u32 reg, h, m, l, per; ++ ++ if (!(status & FE_HAS_LOCK)) { ++ count = 0; ++ per = 1 << 23; /* Max PER */ ++ } else { ++ /* Counter 2 */ ++ reg = STV090x_READ_DEMOD(state, ERRCNT22); ++ h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD); ++ ++ reg = STV090x_READ_DEMOD(state, ERRCNT21); ++ m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD); ++ ++ reg = STV090x_READ_DEMOD(state, ERRCNT20); ++ l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD); ++ ++ per = ((h << 16) | (m << 8) | l); ++ ++ count_4 = STV090x_READ_DEMOD(state, FBERCPT4); ++ count_3 = STV090x_READ_DEMOD(state, FBERCPT3); ++ count_2 = STV090x_READ_DEMOD(state, FBERCPT2); ++ count_1 = STV090x_READ_DEMOD(state, FBERCPT1); ++ count_0 = STV090x_READ_DEMOD(state, FBERCPT0); ++ ++ if ((!count_4) && (!count_3)) { ++ count = (count_2 & 0xff) << 16; ++ count |= (count_1 & 0xff) << 8; ++ count |= count_0 & 0xff; ++ } else { ++ count = 1 << 24; ++ } ++ if (count == 0) ++ per = 1; ++ } ++ if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0) ++ goto err; ++ if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) ++ goto err; ++ ++ p->post_bit_error.len = 1; ++ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_error.stat[0].uvalue = per; ++ p->post_bit_count.len = 1; ++ p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_count.stat[0].uvalue = count; ++ ++ return 0; ++err: ++ dprintk(FE_ERROR, 1, "I/O error"); ++ return -1; ++} ++ ++static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct stv090x_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ u32 reg, dstatus; ++ u8 search_state; ++ ++ *status = FE_HAS_SIGNAL; ++ stv090x_read_rflevel(fe); ++ ++ dstatus = STV090x_READ_DEMOD(state, DSTATUS); ++ if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD)) ++ *status |= FE_HAS_CARRIER; ++ ++ reg = STV090x_READ_DEMOD(state, DMDSTATE); ++ search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); ++ ++ switch (search_state) { ++ case 0: /* searching */ ++ case 1: /* first PLH detected */ ++ default: ++ dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)"); ++ break; ++ ++ case 2: /* DVB-S2 mode */ ++ dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2"); ++ if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) { ++ reg = STV090x_READ_DEMOD(state, PDELSTATUS1); ++ if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) { ++ *status |= FE_HAS_VITERBI; ++ reg = STV090x_READ_DEMOD(state, TSSTATUS); ++ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) ++ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ } ++ } ++ break; ++ ++ case 3: /* DVB-S1/legacy mode */ ++ dprintk(FE_DEBUG, 1, "Delivery system: DVB-S"); ++ if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) { ++ reg = STV090x_READ_DEMOD(state, VSTATUSVIT); ++ if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { ++ *status |= FE_HAS_VITERBI; ++ reg = STV090x_READ_DEMOD(state, TSSTATUS); ++ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) ++ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ } ++ } ++ break; ++ } ++ ++ if (*status & FE_HAS_LOCK) { ++ stv090x_read_cnr(fe); ++ stv090x_read_per(fe, *status); ++ } ++ else { ++ p->cnr.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; ++ } ++ ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, *status & FE_HAS_LOCK); ++ ++ return 0; ++} ++ ++static int stv090x_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ if (p->cnr.stat[0].scale == FE_SCALE_DECIBEL) { ++ *snr = (s32)p->cnr.stat[0].svalue / 100; ++ if (*snr > 200) ++ *snr = 0xffff; ++ else ++ *snr *= 328; ++ } else *snr = 0; ++ ++ return 0; ++} ++ ++static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ if ( p->post_bit_error.stat[0].scale == FE_SCALE_COUNTER && ++ p->post_bit_count.stat[0].scale == FE_SCALE_COUNTER ) ++ *ber = (u32)p->post_bit_count.stat[0].uvalue ? (u32)p->post_bit_error.stat[0].uvalue / (u32)p->post_bit_count.stat[0].uvalue : 0; ++ ++ return 0; ++} ++ ++static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ *strength = p->strength.stat[0].scale == FE_SCALE_DECIBEL ? ((100000 + (s32)p->strength.stat[0].svalue) / 1000) * 656 : 0; ++ ++ return 0; ++} ++ ++static int stv090x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct stv090x_state *state = fe->demodulator_priv; ++ u8 err0, err1; ++ ++ *ucblocks = 0; ++ switch (state->delsys) { ++ case STV090x_DVBS2: ++ err0 = STV090x_READ_DEMOD(state, UPCRCKO0); ++ err1 = STV090x_READ_DEMOD(state, UPCRCKO1); ++ *ucblocks = (err1 << 8) | err0; ++ default: ++ break; ++ } + return 0; + } + +@@ -3907,6 +4004,9 @@ static int stv090x_sleep(struct dvb_frontend *fe) + u32 reg; + u8 full_standby = 0; + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + if (stv090x_i2c_gate_ctrl(state, 1) < 0) + goto err; + +@@ -4138,6 +4238,9 @@ static void stv090x_release(struct dvb_frontend *fe) + { + struct stv090x_state *state = fe->demodulator_priv; + ++ if (state->config->set_lock_led) ++ state->config->set_lock_led(fe, 0); ++ + state->internal->num_used--; + if (state->internal->num_used <= 0) { + +@@ -4542,6 +4645,30 @@ static int stv0900_set_tspath(struct stv090x_state *state) + goto err; + } + ++ if (ts_nosync) ++ { ++ dprintk(FE_DEBUG, 1, "TS FIFO Minimum Latence mode\n"); ++ reg = stv090x_read_reg(state, STV090x_P1_TSSTATEM); ++ STV090x_SETFIELD_Px(reg, TSOUT_NOSYNC, 1); ++ if (stv090x_write_reg(state, STV090x_P1_TSSTATEM, reg) < 0) ++ goto err; ++ ++ reg = stv090x_read_reg(state, STV090x_P2_TSSTATEM); ++ STV090x_SETFIELD_Px(reg, TSOUT_NOSYNC, 1); ++ if (stv090x_write_reg(state, STV090x_P2_TSSTATEM, reg) < 0) ++ goto err; ++ ++ reg = stv090x_read_reg(state, STV090x_P1_TSSYNC); ++ STV090x_SETFIELD_Px(reg, TSFIFO_SYNCMODE, 2); ++ if (stv090x_write_reg(state, STV090x_P1_TSSYNC, reg) < 0) ++ goto err; ++ ++ reg = stv090x_read_reg(state, STV090x_P2_TSSYNC); ++ STV090x_SETFIELD_Px(reg, TSFIFO_SYNCMODE, 2); ++ if (stv090x_write_reg(state, STV090x_P2_TSSYNC, reg) < 0) ++ goto err; ++ } ++ + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) +@@ -4665,6 +4792,20 @@ static int stv0903_set_tspath(struct stv090x_state *state) + goto err; + } + ++ if (ts_nosync) ++ { ++ dprintk(FE_DEBUG, 1, "TS FIFO Minimum Latence mode\n"); ++ reg = stv090x_read_reg(state, STV090x_P1_TSSTATEM); ++ STV090x_SETFIELD_Px(reg, TSOUT_NOSYNC, 1); ++ if (stv090x_write_reg(state, STV090x_P1_TSSTATEM, reg) < 0) ++ goto err; ++ ++ reg = stv090x_read_reg(state, STV090x_P1_TSSYNC); ++ STV090x_SETFIELD_Px(reg, TSFIFO_SYNCMODE, 2); ++ if (stv090x_write_reg(state, STV090x_P1_TSSYNC, reg) < 0) ++ goto err; ++ } ++ + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) +@@ -4886,7 +5027,7 @@ static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, + return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg); + } + +-static struct dvb_frontend_ops stv090x_ops = { ++static const struct dvb_frontend_ops stv090x_ops = { + .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, + .info = { + .name = "STV090x Multistandard", +@@ -4915,9 +5056,10 @@ static struct dvb_frontend_ops stv090x_ops = { + + .search = stv090x_search, + .read_status = stv090x_read_status, +- .read_ber = stv090x_read_per, + .read_signal_strength = stv090x_read_signal_strength, +- .read_snr = stv090x_read_cnr, ++ .read_snr = stv090x_read_snr, ++ .read_ber = stv090x_read_ber, ++ .read_ucblocks = stv090x_read_ucblocks, + }; + + +diff --git a/drivers/media/dvb-frontends/stv090x.h b/drivers/media/dvb-frontends/stv090x.h +index 012e55e..59541d1 100644 +--- a/drivers/media/dvb-frontends/stv090x.h ++++ b/drivers/media/dvb-frontends/stv090x.h +@@ -89,21 +89,23 @@ struct stv090x_config { + + bool diseqc_envelope_mode; + +- int (*tuner_init)(struct dvb_frontend *fe); +- int (*tuner_sleep)(struct dvb_frontend *fe); +- int (*tuner_set_mode)(struct dvb_frontend *fe, enum tuner_mode mode); +- int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency); +- int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency); +- int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); +- int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); +- int (*tuner_set_bbgain)(struct dvb_frontend *fe, u32 gain); +- int (*tuner_get_bbgain)(struct dvb_frontend *fe, u32 *gain); +- int (*tuner_set_refclk)(struct dvb_frontend *fe, u32 refclk); +- int (*tuner_get_status)(struct dvb_frontend *fe, u32 *status); +- void (*tuner_i2c_lock)(struct dvb_frontend *fe, int lock); ++ /* Hook for Lock LED */ ++ void (*set_lock_led) (struct dvb_frontend *fe, int offon); ++ int (*tuner_init) (struct dvb_frontend *fe); ++ int (*tuner_sleep) (struct dvb_frontend *fe); ++ int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); ++ int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); ++ int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); ++ int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth); ++ int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth); ++ int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain); ++ int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain); ++ int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk); ++ int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status); ++ void (*tuner_i2c_lock) (struct dvb_frontend *fe, int lock); + + /* dir = 0 -> output, dir = 1 -> input/open-drain */ +- int (*set_gpio)(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value, ++ int (*set_gpio) (struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value, + u8 xor_value); + }; + +diff --git a/drivers/media/dvb-frontends/stv090x_priv.h b/drivers/media/dvb-frontends/stv090x_priv.h +index 5b780c8..9f384b77 100644 +--- a/drivers/media/dvb-frontends/stv090x_priv.h ++++ b/drivers/media/dvb-frontends/stv090x_priv.h +@@ -32,16 +32,16 @@ + + #define dprintk(__y, __z, format, arg...) do { \ + if (__z) { \ +- if ((verbose > FE_ERROR) && (verbose > __y)) \ ++ if ((verbose >= FE_ERROR) && (verbose >= __y)) \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ +- else if ((verbose > FE_NOTICE) && (verbose > __y)) \ ++ else if ((verbose >= FE_NOTICE) && (verbose >= __y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ +- else if ((verbose > FE_INFO) && (verbose > __y)) \ ++ else if ((verbose >= FE_INFO) && (verbose >= __y)) \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ +- else if ((verbose > FE_DEBUG) && (verbose > __y)) \ ++ else if ((verbose >= FE_DEBUG) && (verbose >= __y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ + } else { \ +- if (verbose > __y) \ ++ if (verbose >= __y) \ + printk(format, ##arg); \ + } \ + } while (0) +diff --git a/drivers/media/dvb-frontends/stv090x_reg.h b/drivers/media/dvb-frontends/stv090x_reg.h +index 93741ee..c1dac9c 100644 +--- a/drivers/media/dvb-frontends/stv090x_reg.h ++++ b/drivers/media/dvb-frontends/stv090x_reg.h +@@ -2104,6 +2104,14 @@ + #define STV090x_WIDTH_Px_TSDIL_ON_FIELD 1 + #define STV090x_OFFST_Px_TSRS_ON_FIELD 5 + #define STV090x_WIDTH_Px_TSRS_ON_FIELD 1 ++#define STV090x_OFFST_Px_TSDESCRAMB_ON 4 ++#define STV090x_WIDTH_Px_TSDESCRAMB_ON 1 ++#define STV090x_OFFST_Px_TSFRAME_MODE 3 ++#define STV090x_WIDTH_Px_TSFRAME_MODE 1 ++#define STV090x_OFFST_Px_TS_DISABLE 2 ++#define STV090x_WIDTH_Px_TS_DISABLE 1 ++#define STV090x_OFFST_Px_TSOUT_NOSYNC 0 ++#define STV090x_WIDTH_Px_TSOUT_NOSYNC 1 + + #define STV090x_Px_TSCFGH(__x) (0xF572 - (__x - 1) * 0x200) + #define STV090x_P1_TSCFGH STV090x_Px_TSCFGH(1) +@@ -2147,6 +2155,14 @@ + #define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD 1 + #define STV090x_WIDTH_Px_TSFIFO_DPUNACT_FIELD 1 + ++#define STV090x_Px_TSSYNC(__x) (0xF575 - (__x - 1) * 0x200) ++#define STV090x_P1_TSSYNC STV090x_Px_TSSYNC(1) ++#define STV090x_P2_TSSYNC STV090x_Px_TSSYNC(2) ++#define STV090x_OFFST_Px_TSFIFO_FISCR3B 5 ++#define STV090x_WIDTH_Px_TSFIFO_FISCR3B 2 ++#define STV090x_OFFST_Px_TSFIFO_SYNCMODE 3 ++#define STV090x_WIDTH_Px_TSFIFO_SYNCMODE 2 ++ + #define STV090x_Px_TSINSDELH(__x) (0xF576 - (__x - 1) * 0x200) + #define STV090x_P1_TSINSDELH STV090x_Px_TSINSDELH(1) + #define STV090x_P2_TSINSDELH STV090x_Px_TSINSDELH(2) +diff --git a/drivers/media/dvb-frontends/stv0910.c b/drivers/media/dvb-frontends/stv0910.c +new file mode 100644 +index 0000000..033cbce +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0910.c +@@ -0,0 +1,1637 @@ ++/* ++ * Driver for the ST STV0910 DVB-S/S2 demodulator. ++ * ++ * Copyright (C) 2014-2015 Ralph Metzler ++ * Marcus Metzler ++ * developed for Digital Devices GmbH ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "stv0910.h" ++#include "stv0910_regs.h" ++ ++ ++#define TUNING_DELAY 200 ++#define BER_SRC_S 0x20 ++#define BER_SRC_S2 0x20 ++ ++LIST_HEAD(stvlist); ++ ++enum ReceiveMode { Mode_None, Mode_DVBS, Mode_DVBS2, Mode_Auto }; ++ ++enum DVBS2_FECType { DVBS2_64K, DVBS2_16K }; ++ ++enum DVBS2_ModCod { ++ DVBS2_DUMMY_PLF, DVBS2_QPSK_1_4, DVBS2_QPSK_1_3, DVBS2_QPSK_2_5, ++ DVBS2_QPSK_1_2, DVBS2_QPSK_3_5, DVBS2_QPSK_2_3, DVBS2_QPSK_3_4, ++ DVBS2_QPSK_4_5, DVBS2_QPSK_5_6, DVBS2_QPSK_8_9, DVBS2_QPSK_9_10, ++ DVBS2_8PSK_3_5, DVBS2_8PSK_2_3, DVBS2_8PSK_3_4, DVBS2_8PSK_5_6, ++ DVBS2_8PSK_8_9, DVBS2_8PSK_9_10, DVBS2_16APSK_2_3, DVBS2_16APSK_3_4, ++ DVBS2_16APSK_4_5, DVBS2_16APSK_5_6, DVBS2_16APSK_8_9, DVBS2_16APSK_9_10, ++ DVBS2_32APSK_3_4, DVBS2_32APSK_4_5, DVBS2_32APSK_5_6, DVBS2_32APSK_8_9, ++ DVBS2_32APSK_9_10 ++}; ++ ++enum FE_STV0910_ModCod { ++ FE_DUMMY_PLF, FE_QPSK_14, FE_QPSK_13, FE_QPSK_25, ++ FE_QPSK_12, FE_QPSK_35, FE_QPSK_23, FE_QPSK_34, ++ FE_QPSK_45, FE_QPSK_56, FE_QPSK_89, FE_QPSK_910, ++ FE_8PSK_35, FE_8PSK_23, FE_8PSK_34, FE_8PSK_56, ++ FE_8PSK_89, FE_8PSK_910, FE_16APSK_23, FE_16APSK_34, ++ FE_16APSK_45, FE_16APSK_56, FE_16APSK_89, FE_16APSK_910, ++ FE_32APSK_34, FE_32APSK_45, FE_32APSK_56, FE_32APSK_89, ++ FE_32APSK_910 ++}; ++ ++enum FE_STV0910_RollOff { FE_SAT_35, FE_SAT_25, FE_SAT_20, FE_SAT_15 }; ++ ++static inline u32 MulDiv32(u32 a, u32 b, u32 c) ++{ ++ u64 tmp64; ++ ++ tmp64 = (u64)a * (u64)b; ++ do_div(tmp64, c); ++ ++ return (u32) tmp64; ++} ++ ++struct stv_base { ++ struct list_head stvlist; ++ ++ u8 adr; ++ struct i2c_adapter *i2c; ++ struct mutex i2c_lock; ++ struct mutex reg_lock; ++ int count; ++ ++ u32 extclk; ++ u32 mclk; ++ ++ u8 dual_tuner; ++ ++ /* Hook for Lock LED */ ++ void (*set_lock_led) (struct dvb_frontend *fe, int offon); ++}; ++ ++struct stv { ++ struct stv_base *base; ++ struct dvb_frontend fe; ++ int nr; ++ u16 regoff; ++ u8 i2crpt; ++ u8 tscfgh; ++ u8 tsgeneral; ++ u8 tsspeed; ++ unsigned long tune_time; ++ ++ s32 SearchRange; ++ u32 Started; ++ u32 DemodLockTime; ++ enum ReceiveMode ReceiveMode; ++ u32 DemodTimeout; ++ u32 FecTimeout; ++ u32 FirstTimeLock; ++ u8 DEMOD; ++ u32 SymbolRate; ++ ++ u8 LastViterbiRate; ++ enum fe_code_rate PunctureRate; ++ enum FE_STV0910_ModCod ModCod; ++ enum DVBS2_FECType FECType; ++ u32 Pilots; ++ enum FE_STV0910_RollOff FERollOff; ++ ++ u32 LastBERNumerator; ++ u32 LastBERDenominator; ++ u8 BERScale; ++}; ++ ++struct SInitTable { ++ u16 Address; ++ u8 Data; ++}; ++ ++struct SLookup { ++ s16 Value; ++ u32 RegValue; ++}; ++ ++static inline int i2c_write(struct i2c_adapter *adap, u8 adr, ++ u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; ++} ++ ++static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, u16 reg, u8 val) ++{ ++ u8 msg[3] = {reg >> 8, reg & 0xff, val}; ++ ++ return i2c_write(adap, adr, msg, 3); ++} ++ ++static int write_reg(struct stv *state, u16 reg, u8 val) ++{ ++ return i2c_write_reg16(state->base->i2c, state->base->adr, reg, val); ++} ++ ++static inline int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, ++ u16 reg, u8 *val) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int read_reg(struct stv *state, u16 reg, u8 *val) ++{ ++ return i2c_read_reg16(state->base->i2c, state->base->adr, reg, val); ++} ++ ++ ++static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr, ++ u16 reg, u8 *val, int len) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int read_regs(struct stv *state, u16 reg, u8 *val, int len) ++{ ++ return i2c_read_regs16(state->base->i2c, state->base->adr, ++ reg, val, len); ++} ++ ++struct SLookup S1_SN_Lookup[] = { ++ { 0, 9242 }, /*C/N= 0dB*/ ++ { 05, 9105 }, /*C/N=0.5dB*/ ++ { 10, 8950 }, /*C/N=1.0dB*/ ++ { 15, 8780 }, /*C/N=1.5dB*/ ++ { 20, 8566 }, /*C/N=2.0dB*/ ++ { 25, 8366 }, /*C/N=2.5dB*/ ++ { 30, 8146 }, /*C/N=3.0dB*/ ++ { 35, 7908 }, /*C/N=3.5dB*/ ++ { 40, 7666 }, /*C/N=4.0dB*/ ++ { 45, 7405 }, /*C/N=4.5dB*/ ++ { 50, 7136 }, /*C/N=5.0dB*/ ++ { 55, 6861 }, /*C/N=5.5dB*/ ++ { 60, 6576 }, /*C/N=6.0dB*/ ++ { 65, 6330 }, /*C/N=6.5dB*/ ++ { 70, 6048 }, /*C/N=7.0dB*/ ++ { 75, 5768 }, /*C/N=7.5dB*/ ++ { 80, 5492 }, /*C/N=8.0dB*/ ++ { 85, 5224 }, /*C/N=8.5dB*/ ++ { 90, 4959 }, /*C/N=9.0dB*/ ++ { 95, 4709 }, /*C/N=9.5dB*/ ++ { 100, 4467 }, /*C/N=10.0dB*/ ++ { 105, 4236 }, /*C/N=10.5dB*/ ++ { 110, 4013 }, /*C/N=11.0dB*/ ++ { 115, 3800 }, /*C/N=11.5dB*/ ++ { 120, 3598 }, /*C/N=12.0dB*/ ++ { 125, 3406 }, /*C/N=12.5dB*/ ++ { 130, 3225 }, /*C/N=13.0dB*/ ++ { 135, 3052 }, /*C/N=13.5dB*/ ++ { 140, 2889 }, /*C/N=14.0dB*/ ++ { 145, 2733 }, /*C/N=14.5dB*/ ++ { 150, 2587 }, /*C/N=15.0dB*/ ++ { 160, 2318 }, /*C/N=16.0dB*/ ++ { 170, 2077 }, /*C/N=17.0dB*/ ++ { 180, 1862 }, /*C/N=18.0dB*/ ++ { 190, 1670 }, /*C/N=19.0dB*/ ++ { 200, 1499 }, /*C/N=20.0dB*/ ++ { 210, 1347 }, /*C/N=21.0dB*/ ++ { 220, 1213 }, /*C/N=22.0dB*/ ++ { 230, 1095 }, /*C/N=23.0dB*/ ++ { 240, 992 }, /*C/N=24.0dB*/ ++ { 250, 900 }, /*C/N=25.0dB*/ ++ { 260, 826 }, /*C/N=26.0dB*/ ++ { 270, 758 }, /*C/N=27.0dB*/ ++ { 280, 702 }, /*C/N=28.0dB*/ ++ { 290, 653 }, /*C/N=29.0dB*/ ++ { 300, 613 }, /*C/N=30.0dB*/ ++ { 310, 579 }, /*C/N=31.0dB*/ ++ { 320, 550 }, /*C/N=32.0dB*/ ++ { 330, 526 }, /*C/N=33.0dB*/ ++ { 350, 490 }, /*C/N=33.0dB*/ ++ { 400, 445 }, /*C/N=40.0dB*/ ++ { 450, 430 }, /*C/N=45.0dB*/ ++ { 500, 426 }, /*C/N=50.0dB*/ ++ { 510, 425 } /*C/N=51.0dB*/ ++}; ++ ++struct SLookup S2_SN_Lookup[] = { ++ { -30, 13950 }, /*C/N=-2.5dB*/ ++ { -25, 13580 }, /*C/N=-2.5dB*/ ++ { -20, 13150 }, /*C/N=-2.0dB*/ ++ { -15, 12760 }, /*C/N=-1.5dB*/ ++ { -10, 12345 }, /*C/N=-1.0dB*/ ++ { -05, 11900 }, /*C/N=-0.5dB*/ ++ { 0, 11520 }, /*C/N= 0dB*/ ++ { 05, 11080 }, /*C/N= 0.5dB*/ ++ { 10, 10630 }, /*C/N= 1.0dB*/ ++ { 15, 10210 }, /*C/N= 1.5dB*/ ++ { 20, 9790 }, /*C/N= 2.0dB*/ ++ { 25, 9390 }, /*C/N= 2.5dB*/ ++ { 30, 8970 }, /*C/N= 3.0dB*/ ++ { 35, 8575 }, /*C/N= 3.5dB*/ ++ { 40, 8180 }, /*C/N= 4.0dB*/ ++ { 45, 7800 }, /*C/N= 4.5dB*/ ++ { 50, 7430 }, /*C/N= 5.0dB*/ ++ { 55, 7080 }, /*C/N= 5.5dB*/ ++ { 60, 6720 }, /*C/N= 6.0dB*/ ++ { 65, 6320 }, /*C/N= 6.5dB*/ ++ { 70, 6060 }, /*C/N= 7.0dB*/ ++ { 75, 5760 }, /*C/N= 7.5dB*/ ++ { 80, 5480 }, /*C/N= 8.0dB*/ ++ { 85, 5200 }, /*C/N= 8.5dB*/ ++ { 90, 4930 }, /*C/N= 9.0dB*/ ++ { 95, 4680 }, /*C/N= 9.5dB*/ ++ { 100, 4425 }, /*C/N=10.0dB*/ ++ { 105, 4210 }, /*C/N=10.5dB*/ ++ { 110, 3980 }, /*C/N=11.0dB*/ ++ { 115, 3765 }, /*C/N=11.5dB*/ ++ { 120, 3570 }, /*C/N=12.0dB*/ ++ { 125, 3315 }, /*C/N=12.5dB*/ ++ { 130, 3140 }, /*C/N=13.0dB*/ ++ { 135, 2980 }, /*C/N=13.5dB*/ ++ { 140, 2820 }, /*C/N=14.0dB*/ ++ { 145, 2670 }, /*C/N=14.5dB*/ ++ { 150, 2535 }, /*C/N=15.0dB*/ ++ { 160, 2270 }, /*C/N=16.0dB*/ ++ { 170, 2035 }, /*C/N=17.0dB*/ ++ { 180, 1825 }, /*C/N=18.0dB*/ ++ { 190, 1650 }, /*C/N=19.0dB*/ ++ { 200, 1485 }, /*C/N=20.0dB*/ ++ { 210, 1340 }, /*C/N=21.0dB*/ ++ { 220, 1212 }, /*C/N=22.0dB*/ ++ { 230, 1100 }, /*C/N=23.0dB*/ ++ { 240, 1000 }, /*C/N=24.0dB*/ ++ { 250, 910 }, /*C/N=25.0dB*/ ++ { 260, 836 }, /*C/N=26.0dB*/ ++ { 270, 772 }, /*C/N=27.0dB*/ ++ { 280, 718 }, /*C/N=28.0dB*/ ++ { 290, 671 }, /*C/N=29.0dB*/ ++ { 300, 635 }, /*C/N=30.0dB*/ ++ { 310, 602 }, /*C/N=31.0dB*/ ++ { 320, 575 }, /*C/N=32.0dB*/ ++ { 330, 550 }, /*C/N=33.0dB*/ ++ { 350, 517 }, /*C/N=35.0dB*/ ++ { 400, 480 }, /*C/N=40.0dB*/ ++ { 450, 466 }, /*C/N=45.0dB*/ ++ { 500, 464 }, /*C/N=50.0dB*/ ++ { 510, 463 }, /*C/N=51.0dB*/ ++}; ++ ++struct SLookup PADC_Lookup[] = { ++ {-2000, 1179 }, /*PADC=-20dBm*/ ++ {-1900, 1485 }, /*PADC=-19dBm*/ ++ {-1700, 2354 }, /*PADC=-17dBm*/ ++ {-1500, 3730 }, /*PADC=-15dBm*/ ++ {-1300, 5910 }, /*PADC=-13dBm*/ ++ {-1100, 9380 }, /*PADC=-11dBm*/ ++ {- 900, 14850}, /*PADC=-9dBm*/ ++ {- 700, 23520}, /*PADC=-7dBm*/ ++ {- 600, 29650}, /*PADC=-6dBm*/ ++ {- 500, 37300}, /*PADC=-5dBm*/ ++ {- 400, 47000}, /*PADC=-4dBm*/ ++ {- 300, 59100}, /*PADC=-3dBm*/ ++ {- 200, 74500}, /*PADC=-2dBm*/ ++ {- 100, 93600}, /*PADC=-1dBm*/ ++ { 0, 118000} /*PADC=+0dBm*/ ++}; ++ ++ ++/********************************************************************* ++Tracking carrier loop carrier QPSK 1/4 to 8PSK 9/10 long Frame ++*********************************************************************/ ++static u8 S2CarLoop[] = { ++ /* Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff ++ 20MPon 20MPoff 30MPon 30MPoff*/ ++ /* FE_QPSK_14 */ ++ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x2A, 0x1C, 0x3A, 0x3B, ++ /* FE_QPSK_13 */ ++ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x3A, 0x0C, 0x3A, 0x2B, ++ /* FE_QPSK_25 */ ++ 0x1C, 0x3C, 0x1B, 0x3C, 0x3A, 0x1C, 0x3A, 0x3B, 0x3A, 0x2B, ++ /* FE_QPSK_12 */ ++ 0x0C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, ++ /* FE_QPSK_35 */ ++ 0x1C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, ++ /* FE_QPSK_23 */ ++ 0x2C, 0x2C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, ++ /* FE_QPSK_34 */ ++ 0x3C, 0x2C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, ++ /* FE_QPSK_45 */ ++ 0x0D, 0x3C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, ++ /* FE_QPSK_56 */ ++ 0x1D, 0x3C, 0x0C, 0x2C, 0x2B, 0x1C, 0x1B, 0x3B, 0x0B, 0x1B, ++ /* FE_QPSK_89 */ ++ 0x3D, 0x0D, 0x0C, 0x2C, 0x2B, 0x0C, 0x2B, 0x2B, 0x0B, 0x0B, ++ /* FE_QPSK_910 */ ++ 0x1E, 0x0D, 0x1C, 0x2C, 0x3B, 0x0C, 0x2B, 0x2B, 0x1B, 0x0B, ++ /* FE_8PSK_35 */ ++ 0x28, 0x09, 0x28, 0x09, 0x28, 0x09, 0x28, 0x08, 0x28, 0x27, ++ /* FE_8PSK_23 */ ++ 0x19, 0x29, 0x19, 0x29, 0x19, 0x29, 0x38, 0x19, 0x28, 0x09, ++ /* FE_8PSK_34 */ ++ 0x1A, 0x0B, 0x1A, 0x3A, 0x0A, 0x2A, 0x39, 0x2A, 0x39, 0x1A, ++ /* FE_8PSK_56 */ ++ 0x2B, 0x2B, 0x1B, 0x1B, 0x0B, 0x1B, 0x1A, 0x0B, 0x1A, 0x1A, ++ /* FE_8PSK_89 */ ++ 0x0C, 0x0C, 0x3B, 0x3B, 0x1B, 0x1B, 0x2A, 0x0B, 0x2A, 0x2A, ++ /* FE_8PSK_910 */ ++ 0x0C, 0x1C, 0x0C, 0x3B, 0x2B, 0x1B, 0x3A, 0x0B, 0x2A, 0x2A, ++ ++ /********************************************************************** ++ Tracking carrier loop carrier 16APSK 2/3 to 32APSK 9/10 long Frame ++ **********************************************************************/ ++ /*Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon ++ 20MPoff 30MPon 30MPoff*/ ++ /* FE_16APSK_23 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x0A, 0x39, 0x0A, 0x29, 0x0A, ++ /* FE_16APSK_34 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0A, 0x2A, 0x0A, 0x1A, 0x0A, ++ /* FE_16APSK_45 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, ++ /* FE_16APSK_56 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, ++ /* FE_16APSK_89 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, ++ /* FE_16APSK_910 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, ++ /* FE_32APSK_34 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_45 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_56 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_89 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_910 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++}; ++ ++static u8 get_optim_cloop(struct stv *state, ++ enum FE_STV0910_ModCod ModCod, u32 Pilots) ++{ ++ int i = 0; ++ if (ModCod >= FE_32APSK_910) ++ i = ((int)FE_32APSK_910 - (int)FE_QPSK_14) * 10; ++ else if (ModCod >= FE_QPSK_14) ++ i = ((int)ModCod - (int)FE_QPSK_14) * 10; ++ ++ if (state->SymbolRate <= 3000000) ++ i += 0; ++ else if (state->SymbolRate <= 7000000) ++ i += 2; ++ else if (state->SymbolRate <= 15000000) ++ i += 4; ++ else if (state->SymbolRate <= 25000000) ++ i += 6; ++ else ++ i += 8; ++ ++ if (!Pilots) ++ i += 1; ++ ++ return S2CarLoop[i]; ++} ++ ++static int GetCurSymbolRate(struct stv *state, u32 *pSymbolRate) ++{ ++ int status = 0; ++ u8 SymbFreq0; ++ u8 SymbFreq1; ++ u8 SymbFreq2; ++ u8 SymbFreq3; ++ u8 TimOffs0; ++ u8 TimOffs1; ++ u8 TimOffs2; ++ u32 SymbolRate; ++ s32 TimingOffset; ++ ++ *pSymbolRate = 0; ++ if (!state->Started) ++ return status; ++ ++ read_reg(state, RSTV0910_P2_SFR3 + state->regoff, &SymbFreq3); ++ read_reg(state, RSTV0910_P2_SFR2 + state->regoff, &SymbFreq2); ++ read_reg(state, RSTV0910_P2_SFR1 + state->regoff, &SymbFreq1); ++ read_reg(state, RSTV0910_P2_SFR0 + state->regoff, &SymbFreq0); ++ read_reg(state, RSTV0910_P2_TMGREG2 + state->regoff, &TimOffs2); ++ read_reg(state, RSTV0910_P2_TMGREG1 + state->regoff, &TimOffs1); ++ read_reg(state, RSTV0910_P2_TMGREG0 + state->regoff, &TimOffs0); ++ ++ SymbolRate = ((u32) SymbFreq3 << 24) | ((u32) SymbFreq2 << 16) | ++ ((u32) SymbFreq1 << 8) | (u32) SymbFreq0; ++ TimingOffset = ((u32) TimOffs2 << 16) | ((u32) TimOffs1 << 8) | ++ (u32) TimOffs0; ++ ++ if ((TimingOffset & (1<<23)) != 0) ++ TimingOffset |= 0xFF000000; /* Sign extent */ ++ ++ SymbolRate = (u32) (((u64) SymbolRate * state->base->mclk) >> 32); ++ TimingOffset = (s32) (((s64) SymbolRate * (s64) TimingOffset) >> 29); ++ ++ *pSymbolRate = SymbolRate + TimingOffset; ++ ++ return 0; ++} ++ ++static int GetSignalParameters(struct stv *state) ++{ ++ if (!state->Started) ++ return -1; ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ u8 tmp; ++ u8 rolloff; ++ ++ read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); ++ state->ModCod = (enum FE_STV0910_ModCod) ((tmp & 0x7c) >> 2); ++ state->Pilots = (tmp & 0x01) != 0; ++ state->FECType = (enum DVBS2_FECType) ((tmp & 0x02) >> 1); ++ ++ read_reg(state, RSTV0910_P2_TMGOBS + state->regoff, &rolloff); ++ rolloff = rolloff >> 6; ++ state->FERollOff = (enum FE_STV0910_RollOff) rolloff; ++ ++ } else if (state->ReceiveMode == Mode_DVBS) { ++ /* todo */ ++ } ++ return 0; ++} ++ ++static int TrackingOptimization(struct stv *state) ++{ ++ u32 SymbolRate = 0; ++ u8 tmp; ++ ++ GetCurSymbolRate(state, &SymbolRate); ++ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, &tmp); ++ tmp &= ~0xC0; ++ ++ switch (state->ReceiveMode) { ++ case Mode_DVBS: ++ tmp |= 0x40; break; ++ case Mode_DVBS2: ++ tmp |= 0x80; break; ++ default: ++ tmp |= 0xC0; break; ++ } ++ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, tmp); ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ /* force to PRE BCH Rate */ ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ BER_SRC_S2 | state->BERScale); ++ ++ if (state->FECType == DVBS2_64K) { ++ u8 aclc = get_optim_cloop(state, state->ModCod, ++ state->Pilots); ++ ++ if (state->ModCod <= FE_QPSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, aclc); ++ } else if (state->ModCod <= FE_8PSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, 0x2a); ++ write_reg(state, RSTV0910_P2_ACLC2S28 + ++ state->regoff, aclc); ++ } else if (state->ModCod <= FE_16APSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, 0x2a); ++ write_reg(state, RSTV0910_P2_ACLC2S216A + ++ state->regoff, aclc); ++ } else if (state->ModCod <= FE_32APSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, 0x2a); ++ write_reg(state, RSTV0910_P2_ACLC2S232A + ++ state->regoff, aclc); ++ } ++ } ++ } ++ if (state->ReceiveMode == Mode_DVBS) { ++ u8 tmp; ++ ++ read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); ++ state->PunctureRate = FEC_NONE; ++ switch (tmp & 0x1F) { ++ case 0x0d: ++ state->PunctureRate = FEC_1_2; ++ break; ++ case 0x12: ++ state->PunctureRate = FEC_2_3; ++ break; ++ case 0x15: ++ state->PunctureRate = FEC_3_4; ++ break; ++ case 0x18: ++ state->PunctureRate = FEC_5_6; ++ break; ++ case 0x1A: ++ state->PunctureRate = FEC_7_8; ++ break; ++ } ++ } ++ return 0; ++} ++ ++static s32 TableLookup(struct SLookup *Table, ++ int TableSize, u16 RegValue) ++{ ++ s32 Value; ++ int imin = 0; ++ int imax = TableSize - 1; ++ int i; ++ s32 RegDiff; ++ ++ // Assumes Table[0].RegValue > Table[imax].RegValue ++ if( RegValue >= Table[0].RegValue ) ++ Value = Table[0].Value; ++ else if( RegValue <= Table[imax].RegValue ) ++ Value = Table[imax].Value; ++ else ++ { ++ while(imax-imin > 1) ++ { ++ i = (imax + imin) / 2; ++ if( (Table[imin].RegValue >= RegValue) && (RegValue >= Table[i].RegValue) ) ++ imax = i; ++ else ++ imin = i; ++ } ++ ++ RegDiff = Table[imax].RegValue - Table[imin].RegValue; ++ Value = Table[imin].Value; ++ if( RegDiff != 0 ) ++ Value += ((s32)(RegValue - Table[imin].RegValue) * ++ (s32)(Table[imax].Value - Table[imin].Value))/(RegDiff); ++ } ++ ++ return Value; ++} ++ ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++#endif ++ ++static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise) ++{ ++ u8 Data0; ++ u8 Data1; ++ u16 Data; ++ int nLookup; ++ struct SLookup *Lookup; ++ ++ *SignalToNoise = 0; ++ ++ if (!state->Started) ++ return 0; ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ read_reg(state, RSTV0910_P2_NNOSPLHT1 + state->regoff, &Data1); ++ read_reg(state, RSTV0910_P2_NNOSPLHT0 + state->regoff, &Data0); ++ nLookup = ARRAY_SIZE(S2_SN_Lookup); ++ Lookup = S2_SN_Lookup; ++ } else { ++ read_reg(state, RSTV0910_P2_NNOSDATAT1 + state->regoff, &Data1); ++ read_reg(state, RSTV0910_P2_NNOSDATAT0 + state->regoff, &Data0); ++ nLookup = ARRAY_SIZE(S1_SN_Lookup); ++ Lookup = S1_SN_Lookup; ++ } ++ Data = (((u16)Data1) << 8) | (u16) Data0; ++ *SignalToNoise = TableLookup(Lookup, nLookup, Data); ++ return 0; ++} ++ ++static int GetBitErrorRateS(struct stv *state, u32 *BERNumerator, ++ u32 *BERDenominator) ++{ ++ u8 Regs[3]; ++ ++ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, ++ Regs, 3); ++ ++ if (status) ++ return -1; ++ ++ if ((Regs[0] & 0x80) == 0) { ++ state->LastBERDenominator = 1 << ((state->BERScale * 2) + ++ 10 + 3); ++ state->LastBERNumerator = ((u32) (Regs[0] & 0x7F) << 16) | ++ ((u32) Regs[1] << 8) | Regs[2]; ++ if (state->LastBERNumerator < 256 && state->BERScale < 6) { ++ state->BERScale += 1; ++ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + ++ state->regoff, ++ 0x20 | state->BERScale); ++ } else if (state->LastBERNumerator > 1024 && ++ state->BERScale > 2) { ++ state->BERScale -= 1; ++ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + ++ state->regoff, 0x20 | ++ state->BERScale); ++ } ++ } ++ *BERNumerator = state->LastBERNumerator; ++ *BERDenominator = state->LastBERDenominator; ++ return 0; ++} ++ ++static u32 DVBS2_nBCH(enum DVBS2_ModCod ModCod, enum DVBS2_FECType FECType) ++{ ++ static u32 nBCH[][2] = { ++ {16200, 3240}, /* QPSK_1_4, */ ++ {21600, 5400}, /* QPSK_1_3, */ ++ {25920, 6480}, /* QPSK_2_5, */ ++ {32400, 7200}, /* QPSK_1_2, */ ++ {38880, 9720}, /* QPSK_3_5, */ ++ {43200, 10800}, /* QPSK_2_3, */ ++ {48600, 11880}, /* QPSK_3_4, */ ++ {51840, 12600}, /* QPSK_4_5, */ ++ {54000, 13320}, /* QPSK_5_6, */ ++ {57600, 14400}, /* QPSK_8_9, */ ++ {58320, 16000}, /* QPSK_9_10, */ ++ {43200, 9720}, /* 8PSK_3_5, */ ++ {48600, 10800}, /* 8PSK_2_3, */ ++ {51840, 11880}, /* 8PSK_3_4, */ ++ {54000, 13320}, /* 8PSK_5_6, */ ++ {57600, 14400}, /* 8PSK_8_9, */ ++ {58320, 16000}, /* 8PSK_9_10, */ ++ {43200, 10800}, /* 16APSK_2_3, */ ++ {48600, 11880}, /* 16APSK_3_4, */ ++ {51840, 12600}, /* 16APSK_4_5, */ ++ {54000, 13320}, /* 16APSK_5_6, */ ++ {57600, 14400}, /* 16APSK_8_9, */ ++ {58320, 16000}, /* 16APSK_9_10 */ ++ {48600, 11880}, /* 32APSK_3_4, */ ++ {51840, 12600}, /* 32APSK_4_5, */ ++ {54000, 13320}, /* 32APSK_5_6, */ ++ {57600, 14400}, /* 32APSK_8_9, */ ++ {58320, 16000}, /* 32APSK_9_10 */ ++ }; ++ ++ if (ModCod >= DVBS2_QPSK_1_4 && ++ ModCod <= DVBS2_32APSK_9_10 && FECType <= DVBS2_16K) ++ return nBCH[FECType][ModCod]; ++ return 64800; ++} ++ ++static int GetBitErrorRateS2(struct stv *state, u32 *BERNumerator, ++ u32 *BERDenominator) ++{ ++ u8 Regs[3]; ++ ++ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, ++ Regs, 3); ++ ++ if (status) ++ return -1; ++ ++ if ((Regs[0] & 0x80) == 0) { ++ state->LastBERDenominator = ++ DVBS2_nBCH((enum DVBS2_ModCod) state->ModCod, ++ state->FECType) << ++ (state->BERScale * 2); ++ state->LastBERNumerator = (((u32) Regs[0] & 0x7F) << 16) | ++ ((u32) Regs[1] << 8) | Regs[2]; ++ if (state->LastBERNumerator < 256 && state->BERScale < 6) { ++ state->BERScale += 1; ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ 0x20 | state->BERScale); ++ } else if (state->LastBERNumerator > 1024 && ++ state->BERScale > 2) { ++ state->BERScale -= 1; ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ 0x20 | state->BERScale); ++ } ++ } ++ *BERNumerator = state->LastBERNumerator; ++ *BERDenominator = state->LastBERDenominator; ++ return status; ++} ++ ++static int GetBitErrorRate(struct stv *state, u32 *BERNumerator, ++ u32 *BERDenominator) ++{ ++ *BERNumerator = 0; ++ *BERDenominator = 1; ++ ++ switch (state->ReceiveMode) { ++ case Mode_DVBS: ++ return GetBitErrorRateS(state, BERNumerator, BERDenominator); ++ break; ++ case Mode_DVBS2: ++ return GetBitErrorRateS2(state, BERNumerator, BERDenominator); ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static int init(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++ ++static int set_mclock(struct stv *state, u32 MasterClock) ++{ ++ u32 idf = 1; ++ u32 odf = 4; ++ u32 quartz = state->base->extclk / 1000000; ++ u32 Fphi = MasterClock / 1000000; ++ u32 ndiv = (Fphi * odf * idf) / quartz; ++ u32 cp = 7; ++ u32 fvco; ++ ++ if (ndiv >= 7 && ndiv <= 71) ++ cp = 7; ++ else if (ndiv >= 72 && ndiv <= 79) ++ cp = 8; ++ else if (ndiv >= 80 && ndiv <= 87) ++ cp = 9; ++ else if (ndiv >= 88 && ndiv <= 95) ++ cp = 10; ++ else if (ndiv >= 96 && ndiv <= 103) ++ cp = 11; ++ else if (ndiv >= 104 && ndiv <= 111) ++ cp = 12; ++ else if (ndiv >= 112 && ndiv <= 119) ++ cp = 13; ++ else if (ndiv >= 120 && ndiv <= 127) ++ cp = 14; ++ else if (ndiv >= 128 && ndiv <= 135) ++ cp = 15; ++ else if (ndiv >= 136 && ndiv <= 143) ++ cp = 16; ++ else if (ndiv >= 144 && ndiv <= 151) ++ cp = 17; ++ else if (ndiv >= 152 && ndiv <= 159) ++ cp = 18; ++ else if (ndiv >= 160 && ndiv <= 167) ++ cp = 19; ++ else if (ndiv >= 168 && ndiv <= 175) ++ cp = 20; ++ else if (ndiv >= 176 && ndiv <= 183) ++ cp = 21; ++ else if (ndiv >= 184 && ndiv <= 191) ++ cp = 22; ++ else if (ndiv >= 192 && ndiv <= 199) ++ cp = 23; ++ else if (ndiv >= 200 && ndiv <= 207) ++ cp = 24; ++ else if (ndiv >= 208 && ndiv <= 215) ++ cp = 25; ++ else if (ndiv >= 216 && ndiv <= 223) ++ cp = 26; ++ else if (ndiv >= 224 && ndiv <= 225) ++ cp = 27; ++ ++ write_reg(state, RSTV0910_NCOARSE, (cp << 3) | idf); ++ write_reg(state, RSTV0910_NCOARSE2, odf); ++ write_reg(state, RSTV0910_NCOARSE1, ndiv); ++ ++ fvco = (quartz * 2 * ndiv) / idf; ++ state->base->mclk = fvco / (2 * odf) * 1000000; ++ ++ /*pr_info("ndiv = %d, MasterClock = %d\n", ndiv, state->base->mclk);*/ ++ return 0; ++} ++ ++static int Stop(struct stv *state) ++{ ++ if (state->Started) { ++ u8 tmp; ++ ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh | 0x01); ++ read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); ++ tmp &= ~0x01; /*release reset DVBS2 packet delin*/ ++ write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); ++ /* Blind optim*/ ++ write_reg(state, RSTV0910_P2_AGC2O + state->regoff, 0x5B); ++ /* Stop the demod */ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5c); ++ state->Started = 0; ++ } ++ state->ReceiveMode = Mode_None; ++ return 0; ++} ++ ++static int SetPLS(struct stv *state, u8 pls_mode, u32 pls_code) ++{ ++ if (pls_mode == 0 && pls_code == 0) ++ pls_code = 1; ++ pls_mode &= 0x03; ++ pls_code &= 0x3FFFF; ++ ++ //pr_warn("%s: code %d (mode %d)\n", __func__, pls_code, pls_mode); ++ write_reg(state, RSTV0910_P2_PLROOT2 + state->regoff, (pls_mode<<2) | (pls_code>>16)); ++ write_reg(state, RSTV0910_P2_PLROOT1 + state->regoff, pls_code>>8); ++ write_reg(state, RSTV0910_P2_PLROOT0 + state->regoff, pls_code); ++ return 0; ++} ++ ++static int SetMIS(struct stv *state, int mis) ++{ ++ u8 tmp; ++ ++ if (mis == NO_STREAM_ID_FILTER) { ++ //pr_warn("%s: disable MIS filtering\n", __func__); ++ SetPLS(state, 0, 0); ++ read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); ++ tmp &= ~0x20; ++ write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); ++ } else { ++ SetPLS(state, (mis>>26) & 0x3, (mis>>8) & 0x3FFFF); ++ read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); ++ tmp |= 0x20; ++ write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); ++ //pr_warn("%s: enable MIS filtering - %d\n", __func__, mis & 0xff); ++ write_reg(state, RSTV0910_P2_ISIENTRY + state->regoff, mis & 0xff ); ++ write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff, 0xff ); ++ } ++ return 0; ++} ++ ++static int Start(struct stv *state, struct dtv_frontend_properties *p) ++{ ++ s32 Freq; ++ u8 regDMDCFGMD; ++ u16 symb; ++ ++ if (p->symbol_rate < 100000 || p->symbol_rate > 70000000) ++ return -EINVAL; ++ ++ state->ReceiveMode = Mode_None; ++ state->DemodLockTime = 0; ++ ++ /* Demod Stop*/ ++ if (state->Started) ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5C); ++ ++ if (p->symbol_rate <= 1000000) { /*SR <=1Msps*/ ++ state->DemodTimeout = 3000; ++ state->FecTimeout = 2000; ++ } else if (p->symbol_rate <= 2000000) { /*1Msps < SR <=2Msps*/ ++ state->DemodTimeout = 2500; ++ state->FecTimeout = 1300; ++ } else if (p->symbol_rate <= 5000000) { /*2Msps< SR <=5Msps*/ ++ state->DemodTimeout = 1000; ++ state->FecTimeout = 650; ++ } else if (p->symbol_rate <= 10000000) { /*5Msps< SR <=10Msps*/ ++ state->DemodTimeout = 700; ++ state->FecTimeout = 350; ++ } else if (p->symbol_rate < 20000000) { /*10Msps< SR <=20Msps*/ ++ state->DemodTimeout = 400; ++ state->FecTimeout = 200; ++ } else { /*SR >=20Msps*/ ++ state->DemodTimeout = 300; ++ state->FecTimeout = 200; ++ } ++ ++ SetMIS(state, p->stream_id); ++ ++ /* Set the Init Symbol rate*/ ++ symb = MulDiv32(p->symbol_rate, 65536, state->base->mclk); ++ write_reg(state, RSTV0910_P2_SFRINIT1 + state->regoff, ++ ((symb >> 8) & 0x7F)); ++ write_reg(state, RSTV0910_P2_SFRINIT0 + state->regoff, (symb & 0xFF)); ++ ++ /*pr_info("symb = %u\n", symb);*/ ++ ++ state->DEMOD |= 0x80; ++ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, state->DEMOD); ++ ++ /* FE_STV0910_SetSearchStandard */ ++ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ®DMDCFGMD); ++ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ++ regDMDCFGMD |= 0xC0); ++ ++ /* Disable DSS */ ++ write_reg(state, RSTV0910_P2_FECM + state->regoff, 0x00); ++ write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2F); ++ ++ /* 8PSK 3/5, 8PSK 2/3 Poff tracking optimization WA*/ ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + state->regoff, 0x0B); ++ write_reg(state, RSTV0910_P2_ACLC2S28 + state->regoff, 0x0A); ++ write_reg(state, RSTV0910_P2_BCLC2S2Q + state->regoff, 0x84); ++ write_reg(state, RSTV0910_P2_BCLC2S28 + state->regoff, 0x84); ++ write_reg(state, RSTV0910_P2_CARHDR + state->regoff, 0x1C); ++ /* Reset demod */ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); ++ ++ write_reg(state, RSTV0910_P2_CARCFG + state->regoff, 0x46); ++ ++ Freq = (state->SearchRange / 2000) + 600; ++ if (p->symbol_rate <= 5000000) ++ Freq -= (600 + 80); ++ Freq = (Freq << 16) / (state->base->mclk / 1000); ++ ++ write_reg(state, RSTV0910_P2_CFRUP1 + state->regoff, ++ (Freq >> 8) & 0xff); ++ write_reg(state, RSTV0910_P2_CFRUP0 + state->regoff, (Freq & 0xff)); ++ /*CFR Low Setting*/ ++ Freq = -Freq; ++ write_reg(state, RSTV0910_P2_CFRLOW1 + state->regoff, ++ (Freq >> 8) & 0xff); ++ write_reg(state, RSTV0910_P2_CFRLOW0 + state->regoff, (Freq & 0xff)); ++ ++ /* init the demod frequency offset to 0 */ ++ write_reg(state, RSTV0910_P2_CFRINIT1 + state->regoff, 0); ++ write_reg(state, RSTV0910_P2_CFRINIT0 + state->regoff, 0); ++ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); ++ /* Trigger acq */ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x15); ++ ++ state->DemodLockTime += TUNING_DELAY; ++ state->Started = 1; ++ ++ return 0; ++} ++ ++static int init_diseqc(struct stv *state) ++{ ++ u8 Freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); ++ ++ /* Disable receiver */ ++ write_reg(state, RSTV0910_P1_DISRXCFG, 0x00); ++ write_reg(state, RSTV0910_P2_DISRXCFG, 0x00); ++ write_reg(state, RSTV0910_P1_DISTXCFG, 0x82); /* Reset = 1 */ ++ write_reg(state, RSTV0910_P1_DISTXCFG, 0x02); /* Reset = 0 */ ++ write_reg(state, RSTV0910_P2_DISTXCFG, 0x82); /* Reset = 1 */ ++ write_reg(state, RSTV0910_P2_DISTXCFG, 0x02); /* Reset = 0 */ ++ write_reg(state, RSTV0910_P1_DISTXF22, Freq); ++ write_reg(state, RSTV0910_P2_DISTXF22, Freq); ++ return 0; ++} ++ ++static int probe(struct stv *state) ++{ ++ u8 id; ++ ++ state->ReceiveMode = Mode_None; ++ state->Started = 0; ++ ++ if (read_reg(state, RSTV0910_MID, &id) < 0) ++ return -1; ++ ++ if (id != 0x51) ++ return -EINVAL; ++ /* pr_info("stv0910: found STV0910 id=0x%02x\n", id); */ ++ ++ /* Configure the I2C repeater to off */ ++ write_reg(state, RSTV0910_P1_I2CRPT, 0x24); ++ /* Configure the I2C repeater to off */ ++ write_reg(state, RSTV0910_P2_I2CRPT, 0x24); ++ /* Set the I2C to oversampling ratio */ ++ write_reg(state, RSTV0910_I2CCFG, 0x88); ++ ++ write_reg(state, RSTV0910_OUTCFG, 0x00); /* OUTCFG */ ++ write_reg(state, RSTV0910_PADCFG, 0x05); /* RF AGC Pads Dev = 05 */ ++ write_reg(state, RSTV0910_SYNTCTRL, 0x02); /* SYNTCTRL */ ++ write_reg(state, RSTV0910_TSGENERAL, state->tsgeneral); /* TSGENERAL */ ++ write_reg(state, RSTV0910_CFGEXT, 0x02); /* CFGEXT */ ++ write_reg(state, RSTV0910_GENCFG, 0x15); /* GENCFG */ ++ ++ ++ write_reg(state, RSTV0910_TSTRES0, 0x80); /* LDPC Reset */ ++ write_reg(state, RSTV0910_TSTRES0, 0x00); ++ ++ set_mclock(state, 135000000); ++ ++ /* TS output */ ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh); ++ write_reg(state, RSTV0910_P1_TSCFGM , 0xC0); /* Manual speed */ ++ write_reg(state, RSTV0910_P1_TSCFGL , 0x20); ++ ++ /* Speed = 67.5 MHz */ ++ write_reg(state, RSTV0910_P1_TSSPEED , state->tsspeed); ++ ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh); ++ write_reg(state, RSTV0910_P2_TSCFGM , 0xC0); /* Manual speed */ ++ write_reg(state, RSTV0910_P2_TSCFGL , 0x20); ++ ++ /* Speed = 67.5 MHz */ ++ write_reg(state, RSTV0910_P2_TSSPEED , state->tsspeed); ++ ++ /* Reset stream merger */ ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh); ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh); ++ ++ write_reg(state, RSTV0910_P1_I2CRPT, state->i2crpt); ++ write_reg(state, RSTV0910_P2_I2CRPT, state->i2crpt); ++ ++ init_diseqc(state); ++ return 0; ++} ++ ++ ++static int gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u8 i2crpt = state->i2crpt & ~0x86; ++ u16 reg; ++ ++ if (enable) ++ mutex_lock(&state->base->i2c_lock); ++ ++ if (enable) ++ i2crpt |= 0x80; ++ else ++ i2crpt |= 0x02; ++ ++ switch (state->base->dual_tuner) ++ { ++ case 1: ++ reg = RSTV0910_P1_I2CRPT; ++ break; ++ case 2: ++ reg = RSTV0910_P2_I2CRPT; ++ break; ++ default: ++ reg = state->nr ? RSTV0910_P2_I2CRPT : RSTV0910_P1_I2CRPT; ++ } ++ ++ /* pr_info("stv0910: gate_ctrl %d\n", enable); */ ++ ++ if (write_reg(state, reg , i2crpt) < 0) ++ return -EIO; ++ ++ state->i2crpt = i2crpt; ++ ++ if (!enable) ++ mutex_unlock(&state->base->i2c_lock); ++ return 0; ++} ++ ++static void release(struct dvb_frontend *fe) ++{ ++ struct stv *state = fe->demodulator_priv; ++ ++ if (state->base->set_lock_led) ++ state->base->set_lock_led(fe, 0); ++ ++ state->base->count--; ++ if (state->base->count == 0) { ++ list_del(&state->base->stvlist); ++ kfree(state->base); ++ } ++ kfree(state); ++} ++ ++static int set_parameters(struct dvb_frontend *fe) ++{ ++ int stat = 0; ++ struct stv *state = fe->demodulator_priv; ++ u32 IF; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ Stop(state); ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ if (fe->ops.tuner_ops.get_if_frequency) ++ fe->ops.tuner_ops.get_if_frequency(fe, &IF); ++ state->SymbolRate = p->symbol_rate; ++ stat = Start(state, p); ++ return stat; ++} ++ ++static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u8 tmp; ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ u32 mc; ++ enum fe_modulation modcod2mod[0x20] = { ++ QPSK, QPSK, QPSK, QPSK, ++ QPSK, QPSK, QPSK, QPSK, ++ QPSK, QPSK, QPSK, QPSK, ++ PSK_8, PSK_8, PSK_8, PSK_8, ++ PSK_8, PSK_8, APSK_16, APSK_16, ++ APSK_16, APSK_16, APSK_16, APSK_16, ++ APSK_32, APSK_32, APSK_32, APSK_32, ++ APSK_32, ++ }; ++ enum fe_code_rate modcod2fec[0x20] = { ++ FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5, ++ FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4, ++ FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, ++ FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6, ++ FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4, ++ FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, ++ FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9, ++ FEC_9_10 ++ }; ++ read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); ++ mc = ((tmp & 0x7c) >> 2); ++ p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF; ++ p->modulation = modcod2mod[mc]; ++ p->fec_inner = modcod2fec[mc]; ++ } else if (state->ReceiveMode == Mode_DVBS) { ++ read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); ++ switch( tmp & 0x1F ) { ++ case 0x0d: ++ p->fec_inner = FEC_1_2; ++ break; ++ case 0x12: ++ p->fec_inner = FEC_2_3; ++ break; ++ case 0x15: ++ p->fec_inner = FEC_3_4; ++ break; ++ case 0x18: ++ p->fec_inner = FEC_5_6; ++ break; ++ case 0x1a: ++ p->fec_inner = FEC_7_8; ++ break; ++ default: ++ p->fec_inner = FEC_NONE; ++ break; ++ } ++ p->rolloff = ROLLOFF_35; ++ } else { ++ ++ } ++ ++ return 0; ++} ++ ++ ++static int read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct stv *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ u8 DmdState = 0; ++ u8 DStatus = 0; ++ enum ReceiveMode CurReceiveMode = Mode_None; ++ u32 FECLock = 0; ++ s32 snr; ++ u32 n, d; ++ u8 Reg[2]; ++ u16 agc; ++ s32 power = 0, Padc = 0; ++ int i; ++ ++ read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2); ++ ++ agc = (((u32) Reg[0]) << 8) | Reg[1]; ++ ++ if (fe->ops.tuner_ops.get_rf_strength) ++ fe->ops.tuner_ops.get_rf_strength(fe, &agc); ++ else ++ agc = 0; ++ ++ for (i = 0; i < 5; i += 1) { ++ read_regs(state, RSTV0910_P2_POWERI + state->regoff, Reg, 2); ++ power += (u32) Reg[0] * (u32) Reg[0] + (u32) Reg[1] * (u32) Reg[1]; ++ msleep(3); ++ } ++ power /= 5; ++ ++ Padc = TableLookup(PADC_Lookup, ARRAY_SIZE(PADC_Lookup), power) + 352; ++ ++ /*pr_warn("%s: power = %d Padc = %d\n", __func__, power, Padc);*/ ++ ++ p->strength.len = 1; ++ p->strength.stat[0].scale = FE_SCALE_DECIBEL; ++ p->strength.stat[0].svalue = Padc - agc; ++ ++ *status = FE_HAS_SIGNAL; ++ ++ read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &DmdState); ++ ++ if (DmdState & 0x40) { ++ read_reg(state, RSTV0910_P2_DSTATUS + state->regoff, &DStatus); ++ if (DStatus & 0x80) ++ *status |= FE_HAS_CARRIER; ++ if (DStatus & 0x08) ++ CurReceiveMode = (DmdState & 0x20) ? ++ Mode_DVBS : Mode_DVBS2; ++ } ++ ++ if (CurReceiveMode == Mode_None) ++ { ++ if (state->base->set_lock_led) ++ state->base->set_lock_led(fe, 0); ++ return 0; ++ } ++ ++ if (state->ReceiveMode == Mode_None) { ++ state->ReceiveMode = CurReceiveMode; ++ state->DemodLockTime = jiffies; ++ state->FirstTimeLock = 1; ++ ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh); ++ usleep_range(3000, 4000); ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh); ++ } ++ if (DmdState & 0x40) { ++ if (state->ReceiveMode == Mode_DVBS2) { ++ u8 PDELStatus; ++ read_reg(state, ++ RSTV0910_P2_PDELSTATUS1 + state->regoff, ++ &PDELStatus); ++ FECLock = (PDELStatus & 0x02) != 0; ++ } else { ++ u8 VStatus; ++ read_reg(state, ++ RSTV0910_P2_VSTATUSVIT + state->regoff, ++ &VStatus); ++ FECLock = (VStatus & 0x08) != 0; ++ } ++ } ++ ++ if (!FECLock) ++ { ++ if (state->base->set_lock_led) ++ state->base->set_lock_led(fe, 0); ++ ++ p->cnr.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; ++ return 0; ++ } ++ ++ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ ++ if (state->base->set_lock_led) ++ state->base->set_lock_led(fe, *status & FE_HAS_LOCK); ++ ++ if (state->FirstTimeLock) { ++ u8 tmp; ++ ++ state->FirstTimeLock = 0; ++ GetSignalParameters(state); ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ /* FSTV0910_P2_MANUALSX_ROLLOFF, ++ FSTV0910_P2_MANUALS2_ROLLOFF = 0 */ ++ state->DEMOD &= ~0x84; ++ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, ++ state->DEMOD); ++ read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, ++ &tmp); ++ /*reset DVBS2 packet delinator error counter */ ++ tmp |= 0x40; ++ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, ++ tmp); ++ /*reset DVBS2 packet delinator error counter */ ++ tmp &= ~0x40; ++ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, ++ tmp); ++ ++ state->BERScale = 2; ++ state->LastBERNumerator = 0; ++ state->LastBERDenominator = 1; ++ /* force to PRE BCH Rate */ ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ BER_SRC_S2 | state->BERScale); ++ } else { ++ state->BERScale = 2; ++ state->LastBERNumerator = 0; ++ state->LastBERDenominator = 1; ++ /* force to PRE RS Rate */ ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ BER_SRC_S | state->BERScale); ++ } ++ /*Reset the Total packet counter */ ++ write_reg(state, RSTV0910_P2_FBERCPT4 + state->regoff, 0x00); ++ /*Reset the packet Error counter2 (and Set it to ++ infinit error count mode )*/ ++ write_reg(state, RSTV0910_P2_ERRCTRL2 + state->regoff, 0xc1); ++ ++ TrackingOptimization(state); ++ } ++ ++ if (GetSignalToNoise(state, &snr)) ++ return -EIO; ++ ++ p->cnr.len = 1; ++ p->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ p->cnr.stat[0].svalue = snr * 100; ++ ++ if (GetBitErrorRate(state, &n, &d)) ++ return -EIO; ++ ++ p->post_bit_error.len = 1; ++ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_error.stat[0].uvalue = n; ++ p->post_bit_count.len = 1; ++ p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ p->post_bit_count.stat[0].uvalue = d; ++ ++ return 0; ++} ++ ++static int tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, ++ unsigned int *delay, enum fe_status *status) ++{ ++ struct stv *state = fe->demodulator_priv; ++ int r; ++ ++ if (re_tune) { ++ r = set_parameters(fe); ++ if (r) ++ return r; ++ state->tune_time = jiffies; ++ } ++ ++ r = read_status(fe, status); ++ if (r) ++ return r; ++ ++ if (*status & FE_HAS_LOCK) ++ return 0; ++ ++ *delay = HZ; ++ ++ return 0; ++} ++ ++ ++static int get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++static int wait_dis(struct stv *state, u8 flag, u8 val) ++{ ++ int i; ++ u8 stat; ++ u16 offs = state->nr ? 0x40 : 0; ++ ++ for (i = 0; i < 10; i++) { ++ read_reg(state, RSTV0910_P1_DISTXSTATUS + offs, &stat); ++ if ((stat & flag) == val) ++ return 0; ++ msleep(10); ++ } ++ return -1; ++} ++ ++static int set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u16 offs = state->nr ? 0x40 : 0; ++ ++ switch (tone) { ++ case SEC_TONE_ON: ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x00); ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x80); ++ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x00); ++ case SEC_TONE_OFF: ++ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x80); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int send_master_cmd(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *cmd) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u16 offs = state->nr ? 0x40 : 0; ++ int i; ++ ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x06); ++ for (i = 0; i < cmd->msg_len; i++) { ++ wait_dis(state, 0x40, 0x00); ++ write_reg(state, RSTV0910_P1_DISTXFIFO + offs, cmd->msg[i]); ++ } ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x02); ++ wait_dis(state, 0x20, 0x20); ++ return 0; ++} ++ ++static int recv_slave_reply(struct dvb_frontend *fe, ++ struct dvb_diseqc_slave_reply *reply) ++{ ++ return 0; ++} ++ ++static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u16 offs = state->nr ? 0x40 : 0; ++ u8 value; ++ ++ if (burst == SEC_MINI_A) { ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x07); ++ value = 0x00; ++ } else { ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x06); ++ value = 0xFF; ++ } ++ wait_dis(state, 0x40, 0x00); ++ write_reg(state, RSTV0910_P1_DISTXFIFO + offs, value); ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x02); ++ wait_dis(state, 0x20, 0x20); ++ ++ return 0; ++} ++ ++static int sleep(struct dvb_frontend *fe) ++{ ++ struct stv *state = fe->demodulator_priv; ++ ++ Stop(state); ++ return 0; ++} ++ ++static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ *strength = p->strength.stat[0].scale == FE_SCALE_DECIBEL ? ((100000 + (s32)p->strength.stat[0].svalue) / 1000) * 656 : 0; ++ ++ return 0; ++} ++ ++static int read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ if (p->cnr.stat[0].scale == FE_SCALE_DECIBEL) { ++ *snr = (s32)p->cnr.stat[0].svalue / 100; ++ if (*snr > 200) ++ *snr = 0xffff; ++ else ++ *snr *= 328; ++ } else *snr = 0; ++ ++ return 0; ++} ++ ++static int read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ if ( p->post_bit_error.stat[0].scale == FE_SCALE_COUNTER && ++ p->post_bit_count.stat[0].scale == FE_SCALE_COUNTER ) ++ *ber = (u32)p->post_bit_count.stat[0].uvalue ? (u32)p->post_bit_error.stat[0].uvalue / (u32)p->post_bit_count.stat[0].uvalue : 0; ++ ++ return 0; ++} ++ ++static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ *ucblocks = 0; ++ return 0; ++} ++ ++static struct dvb_frontend_ops stv0910_ops = { ++ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, ++ .info = { ++ .name = "STV0910 Multistandard", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 0, ++ .frequency_tolerance = 0, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 70000000, ++ .caps = FE_CAN_INVERSION_AUTO | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_2G_MODULATION | ++ FE_CAN_MULTISTREAM ++ }, ++ .init = init, ++ .sleep = sleep, ++ .release = release, ++ .i2c_gate_ctrl = gate_ctrl, ++ .get_frontend_algo = get_algo, ++ .get_frontend = get_frontend, ++ .tune = tune, ++ .set_tone = set_tone, ++ ++ .diseqc_send_master_cmd = send_master_cmd, ++ .diseqc_send_burst = send_burst, ++ .diseqc_recv_slave_reply = recv_slave_reply, ++ ++ .read_status = read_status, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ber = read_ber, ++ .read_ucblocks = read_ucblocks, ++}; ++ ++static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr) ++{ ++ struct stv_base *p; ++ ++ list_for_each_entry(p, &stvlist, stvlist) ++ if (p->i2c == i2c && p->adr == adr) ++ return p; ++ return NULL; ++} ++ ++struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, ++ struct stv0910_cfg *cfg, ++ int nr) ++{ ++ struct stv *state; ++ struct stv_base *base; ++ ++ state = kzalloc(sizeof(struct stv), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ ++ state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40); ++ state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00; ++ state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4); ++ state->tsspeed = 0x28; ++ state->nr = nr; ++ state->regoff = state->nr ? 0 : 0x200; ++ state->SearchRange = 16000000; ++ state->DEMOD = 0x10; /* Inversion : Auto with reset to 0 */ ++ state->ReceiveMode = Mode_None; ++ ++ base = match_base(i2c, cfg->adr); ++ if (base) { ++ base->count++; ++ state->base = base; ++ } else { ++ base = kzalloc(sizeof(struct stv_base), GFP_KERNEL); ++ if (!base) ++ goto fail; ++ base->i2c = i2c; ++ base->adr = cfg->adr; ++ base->count = 1; ++ base->extclk = cfg->clk ? cfg->clk : 30000000; ++ base->dual_tuner = cfg->dual_tuner; ++ base->set_lock_led = cfg->set_lock_led; ++ ++ mutex_init(&base->i2c_lock); ++ mutex_init(&base->reg_lock); ++ state->base = base; ++ if (probe(state) < 0) { ++ kfree(base); ++ goto fail; ++ } ++ list_add(&base->stvlist, &stvlist); ++ } ++ state->fe.ops = stv0910_ops; ++ state->fe.demodulator_priv = state; ++ state->nr = nr; ++ ++ return &state->fe; ++ ++fail: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(stv0910_attach); ++ ++MODULE_DESCRIPTION("STV0910 driver"); ++MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/dvb-frontends/stv0910.h b/drivers/media/dvb-frontends/stv0910.h +new file mode 100644 +index 0000000..738ac57 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0910.h +@@ -0,0 +1,32 @@ ++#ifndef _STV0910_H_ ++#define _STV0910_H_ ++ ++#include ++#include ++ ++struct stv0910_cfg { ++ u32 clk; ++ u8 adr; ++ u8 parallel; ++ u8 rptlvl; ++ u8 dual_tuner; ++ ++ /* Hook for Lock LED */ ++ void (*set_lock_led) (struct dvb_frontend *fe, int offon); ++}; ++ ++#if IS_REACHABLE(CONFIG_DVB_STV0910) ++extern struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, ++ struct stv0910_cfg *cfg, int nr); ++#else ++static inline struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, ++ struct stv0910_cfg *cfg, ++ int nr) ++{ ++ pr_warn("%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++#endif ++ ++#endif +diff --git a/drivers/media/dvb-frontends/stv0910_regs.h b/drivers/media/dvb-frontends/stv0910_regs.h +new file mode 100644 +index 0000000..26f7645 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0910_regs.h +@@ -0,0 +1,4003 @@ ++/* ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*MID*/ ++#define RSTV0910_MID 0xf100 ++#define FSTV0910_MCHIP_IDENT 0xf10000f0 ++#define FSTV0910_MRELEASE 0xf100000f ++ ++/*DID*/ ++#define RSTV0910_DID 0xf101 ++#define FSTV0910_DEVICE_ID 0xf10100ff ++ ++/*DACR1*/ ++#define RSTV0910_DACR1 0xf113 ++#define FSTV0910_DAC_MODE 0xf11300e0 ++#define FSTV0910_DAC_VALUE1 0xf113000f ++ ++/*DACR2*/ ++#define RSTV0910_DACR2 0xf114 ++#define FSTV0910_DAC_VALUE0 0xf11400ff ++ ++/*PADCFG*/ ++#define RSTV0910_PADCFG 0xf11a ++#define FSTV0910_AGCRF2_OPD 0xf11a0008 ++#define FSTV0910_AGCRF2_XOR 0xf11a0004 ++#define FSTV0910_AGCRF1_OPD 0xf11a0002 ++#define FSTV0910_AGCRF1_XOR 0xf11a0001 ++ ++/*OUTCFG2*/ ++#define RSTV0910_OUTCFG2 0xf11b ++#define FSTV0910_TS2_ERROR_XOR 0xf11b0080 ++#define FSTV0910_TS2_DPN_XOR 0xf11b0040 ++#define FSTV0910_TS2_STROUT_XOR 0xf11b0020 ++#define FSTV0910_TS2_CLOCKOUT_XOR 0xf11b0010 ++#define FSTV0910_TS1_ERROR_XOR 0xf11b0008 ++#define FSTV0910_TS1_DPN_XOR 0xf11b0004 ++#define FSTV0910_TS1_STROUT_XOR 0xf11b0002 ++#define FSTV0910_TS1_CLOCKOUT_XOR 0xf11b0001 ++ ++/*OUTCFG*/ ++#define RSTV0910_OUTCFG 0xf11c ++#define FSTV0910_INV_DATA6 0xf11c0080 ++#define FSTV0910_TS2_OUTSER_HZ 0xf11c0020 ++#define FSTV0910_TS1_OUTSER_HZ 0xf11c0010 ++#define FSTV0910_TS2_OUTPAR_HZ 0xf11c0008 ++#define FSTV0910_TS1_OUTPAR_HZ 0xf11c0004 ++#define FSTV0910_TS_SERDATA0 0xf11c0002 ++ ++/*IRQSTATUS3*/ ++#define RSTV0910_IRQSTATUS3 0xf120 ++#define FSTV0910_SPLL_LOCK 0xf1200020 ++#define FSTV0910_SSTREAM_LCK_1 0xf1200010 ++#define FSTV0910_SSTREAM_LCK_2 0xf1200008 ++#define FSTV0910_SDVBS1_PRF_2 0xf1200002 ++#define FSTV0910_SDVBS1_PRF_1 0xf1200001 ++ ++/*IRQSTATUS2*/ ++#define RSTV0910_IRQSTATUS2 0xf121 ++#define FSTV0910_SSPY_ENDSIM_1 0xf1210080 ++#define FSTV0910_SSPY_ENDSIM_2 0xf1210040 ++#define FSTV0910_SPKTDEL_ERROR_2 0xf1210010 ++#define FSTV0910_SPKTDEL_LOCKB_2 0xf1210008 ++#define FSTV0910_SPKTDEL_LOCK_2 0xf1210004 ++#define FSTV0910_SPKTDEL_ERROR_1 0xf1210002 ++#define FSTV0910_SPKTDEL_LOCKB_1 0xf1210001 ++ ++/*IRQSTATUS1*/ ++#define RSTV0910_IRQSTATUS1 0xf122 ++#define FSTV0910_SPKTDEL_LOCK_1 0xf1220080 ++#define FSTV0910_SFEC_LOCKB_2 0xf1220040 ++#define FSTV0910_SFEC_LOCK_2 0xf1220020 ++#define FSTV0910_SFEC_LOCKB_1 0xf1220010 ++#define FSTV0910_SFEC_LOCK_1 0xf1220008 ++#define FSTV0910_SDEMOD_LOCKB_2 0xf1220004 ++#define FSTV0910_SDEMOD_LOCK_2 0xf1220002 ++#define FSTV0910_SDEMOD_IRQ_2 0xf1220001 ++ ++/*IRQSTATUS0*/ ++#define RSTV0910_IRQSTATUS0 0xf123 ++#define FSTV0910_SDEMOD_LOCKB_1 0xf1230080 ++#define FSTV0910_SDEMOD_LOCK_1 0xf1230040 ++#define FSTV0910_SDEMOD_IRQ_1 0xf1230020 ++#define FSTV0910_SBCH_ERRFLAG 0xf1230010 ++#define FSTV0910_SECW2_IRQ 0xf1230008 ++#define FSTV0910_SDISEQC2_IRQ 0xf1230004 ++#define FSTV0910_SECW1_IRQ 0xf1230002 ++#define FSTV0910_SDISEQC1_IRQ 0xf1230001 ++ ++/*IRQMASK3*/ ++#define RSTV0910_IRQMASK3 0xf124 ++#define FSTV0910_MPLL_LOCK 0xf1240020 ++#define FSTV0910_MSTREAM_LCK_1 0xf1240010 ++#define FSTV0910_MSTREAM_LCK_2 0xf1240008 ++#define FSTV0910_MDVBS1_PRF_2 0xf1240002 ++#define FSTV0910_MDVBS1_PRF_1 0xf1240001 ++ ++/*IRQMASK2*/ ++#define RSTV0910_IRQMASK2 0xf125 ++#define FSTV0910_MSPY_ENDSIM_1 0xf1250080 ++#define FSTV0910_MSPY_ENDSIM_2 0xf1250040 ++#define FSTV0910_MPKTDEL_ERROR_2 0xf1250010 ++#define FSTV0910_MPKTDEL_LOCKB_2 0xf1250008 ++#define FSTV0910_MPKTDEL_LOCK_2 0xf1250004 ++#define FSTV0910_MPKTDEL_ERROR_1 0xf1250002 ++#define FSTV0910_MPKTDEL_LOCKB_1 0xf1250001 ++ ++/*IRQMASK1*/ ++#define RSTV0910_IRQMASK1 0xf126 ++#define FSTV0910_MPKTDEL_LOCK_1 0xf1260080 ++#define FSTV0910_MFEC_LOCKB_2 0xf1260040 ++#define FSTV0910_MFEC_LOCK_2 0xf1260020 ++#define FSTV0910_MFEC_LOCKB_1 0xf1260010 ++#define FSTV0910_MFEC_LOCK_1 0xf1260008 ++#define FSTV0910_MDEMOD_LOCKB_2 0xf1260004 ++#define FSTV0910_MDEMOD_LOCK_2 0xf1260002 ++#define FSTV0910_MDEMOD_IRQ_2 0xf1260001 ++ ++/*IRQMASK0*/ ++#define RSTV0910_IRQMASK0 0xf127 ++#define FSTV0910_MDEMOD_LOCKB_1 0xf1270080 ++#define FSTV0910_MDEMOD_LOCK_1 0xf1270040 ++#define FSTV0910_MDEMOD_IRQ_1 0xf1270020 ++#define FSTV0910_MBCH_ERRFLAG 0xf1270010 ++#define FSTV0910_MECW2_IRQ 0xf1270008 ++#define FSTV0910_MDISEQC2_IRQ 0xf1270004 ++#define FSTV0910_MECW1_IRQ 0xf1270002 ++#define FSTV0910_MDISEQC1_IRQ 0xf1270001 ++ ++/*I2CCFG*/ ++#define RSTV0910_I2CCFG 0xf129 ++#define FSTV0910_I2C2_FASTMODE 0xf1290080 ++#define FSTV0910_STATUS_WR2 0xf1290040 ++#define FSTV0910_I2C2ADDR_INC 0xf1290030 ++#define FSTV0910_I2C_FASTMODE 0xf1290008 ++#define FSTV0910_STATUS_WR 0xf1290004 ++#define FSTV0910_I2CADDR_INC 0xf1290003 ++ ++/*P1_I2CRPT*/ ++#define RSTV0910_P1_I2CRPT 0xf12a ++#define FSTV0910_P1_I2CT_ON 0xf12a0080 ++#define FSTV0910_P1_ENARPT_LEVEL 0xf12a0070 ++#define FSTV0910_P1_SCLT_DELAY 0xf12a0008 ++#define FSTV0910_P1_STOP_ENABLE 0xf12a0004 ++#define FSTV0910_P1_STOP_SDAT2SDA 0xf12a0002 ++ ++/*P2_I2CRPT*/ ++#define RSTV0910_P2_I2CRPT 0xf12b ++#define FSTV0910_P2_I2CT_ON 0xf12b0080 ++#define FSTV0910_P2_ENARPT_LEVEL 0xf12b0070 ++#define FSTV0910_P2_SCLT_DELAY 0xf12b0008 ++#define FSTV0910_P2_STOP_ENABLE 0xf12b0004 ++#define FSTV0910_P2_STOP_SDAT2SDA 0xf12b0002 ++ ++/*GPIO0CFG*/ ++#define RSTV0910_GPIO0CFG 0xf140 ++#define FSTV0910_GPIO0_OPD 0xf1400080 ++#define FSTV0910_GPIO0_CONFIG 0xf140007e ++#define FSTV0910_GPIO0_XOR 0xf1400001 ++ ++/*GPIO1CFG*/ ++#define RSTV0910_GPIO1CFG 0xf141 ++#define FSTV0910_GPIO1_OPD 0xf1410080 ++#define FSTV0910_GPIO1_CONFIG 0xf141007e ++#define FSTV0910_GPIO1_XOR 0xf1410001 ++ ++/*GPIO2CFG*/ ++#define RSTV0910_GPIO2CFG 0xf142 ++#define FSTV0910_GPIO2_OPD 0xf1420080 ++#define FSTV0910_GPIO2_CONFIG 0xf142007e ++#define FSTV0910_GPIO2_XOR 0xf1420001 ++ ++/*GPIO3CFG*/ ++#define RSTV0910_GPIO3CFG 0xf143 ++#define FSTV0910_GPIO3_OPD 0xf1430080 ++#define FSTV0910_GPIO3_CONFIG 0xf143007e ++#define FSTV0910_GPIO3_XOR 0xf1430001 ++ ++/*GPIO4CFG*/ ++#define RSTV0910_GPIO4CFG 0xf144 ++#define FSTV0910_GPIO4_OPD 0xf1440080 ++#define FSTV0910_GPIO4_CONFIG 0xf144007e ++#define FSTV0910_GPIO4_XOR 0xf1440001 ++ ++/*GPIO5CFG*/ ++#define RSTV0910_GPIO5CFG 0xf145 ++#define FSTV0910_GPIO5_OPD 0xf1450080 ++#define FSTV0910_GPIO5_CONFIG 0xf145007e ++#define FSTV0910_GPIO5_XOR 0xf1450001 ++ ++/*GPIO6CFG*/ ++#define RSTV0910_GPIO6CFG 0xf146 ++#define FSTV0910_GPIO6_OPD 0xf1460080 ++#define FSTV0910_GPIO6_CONFIG 0xf146007e ++#define FSTV0910_GPIO6_XOR 0xf1460001 ++ ++/*GPIO7CFG*/ ++#define RSTV0910_GPIO7CFG 0xf147 ++#define FSTV0910_GPIO7_OPD 0xf1470080 ++#define FSTV0910_GPIO7_CONFIG 0xf147007e ++#define FSTV0910_GPIO7_XOR 0xf1470001 ++ ++/*GPIO8CFG*/ ++#define RSTV0910_GPIO8CFG 0xf148 ++#define FSTV0910_GPIO8_OPD 0xf1480080 ++#define FSTV0910_GPIO8_CONFIG 0xf148007e ++#define FSTV0910_GPIO8_XOR 0xf1480001 ++ ++/*GPIO9CFG*/ ++#define RSTV0910_GPIO9CFG 0xf149 ++#define FSTV0910_GPIO9_OPD 0xf1490080 ++#define FSTV0910_GPIO9_CONFIG 0xf149007e ++#define FSTV0910_GPIO9_XOR 0xf1490001 ++ ++/*GPIO10CFG*/ ++#define RSTV0910_GPIO10CFG 0xf14a ++#define FSTV0910_GPIO10_OPD 0xf14a0080 ++#define FSTV0910_GPIO10_CONFIG 0xf14a007e ++#define FSTV0910_GPIO10_XOR 0xf14a0001 ++ ++/*GPIO11CFG*/ ++#define RSTV0910_GPIO11CFG 0xf14b ++#define FSTV0910_GPIO11_OPD 0xf14b0080 ++#define FSTV0910_GPIO11_CONFIG 0xf14b007e ++#define FSTV0910_GPIO11_XOR 0xf14b0001 ++ ++/*GPIO12CFG*/ ++#define RSTV0910_GPIO12CFG 0xf14c ++#define FSTV0910_GPIO12_OPD 0xf14c0080 ++#define FSTV0910_GPIO12_CONFIG 0xf14c007e ++#define FSTV0910_GPIO12_XOR 0xf14c0001 ++ ++/*GPIO13CFG*/ ++#define RSTV0910_GPIO13CFG 0xf14d ++#define FSTV0910_GPIO13_OPD 0xf14d0080 ++#define FSTV0910_GPIO13_CONFIG 0xf14d007e ++#define FSTV0910_GPIO13_XOR 0xf14d0001 ++ ++/*GPIO14CFG*/ ++#define RSTV0910_GPIO14CFG 0xf14e ++#define FSTV0910_GPIO14_OPD 0xf14e0080 ++#define FSTV0910_GPIO14_CONFIG 0xf14e007e ++#define FSTV0910_GPIO14_XOR 0xf14e0001 ++ ++/*GPIO15CFG*/ ++#define RSTV0910_GPIO15CFG 0xf14f ++#define FSTV0910_GPIO15_OPD 0xf14f0080 ++#define FSTV0910_GPIO15_CONFIG 0xf14f007e ++#define FSTV0910_GPIO15_XOR 0xf14f0001 ++ ++/*GPIO16CFG*/ ++#define RSTV0910_GPIO16CFG 0xf150 ++#define FSTV0910_GPIO16_OPD 0xf1500080 ++#define FSTV0910_GPIO16_CONFIG 0xf150007e ++#define FSTV0910_GPIO16_XOR 0xf1500001 ++ ++/*GPIO17CFG*/ ++#define RSTV0910_GPIO17CFG 0xf151 ++#define FSTV0910_GPIO17_OPD 0xf1510080 ++#define FSTV0910_GPIO17_CONFIG 0xf151007e ++#define FSTV0910_GPIO17_XOR 0xf1510001 ++ ++/*GPIO18CFG*/ ++#define RSTV0910_GPIO18CFG 0xf152 ++#define FSTV0910_GPIO18_OPD 0xf1520080 ++#define FSTV0910_GPIO18_CONFIG 0xf152007e ++#define FSTV0910_GPIO18_XOR 0xf1520001 ++ ++/*GPIO19CFG*/ ++#define RSTV0910_GPIO19CFG 0xf153 ++#define FSTV0910_GPIO19_OPD 0xf1530080 ++#define FSTV0910_GPIO19_CONFIG 0xf153007e ++#define FSTV0910_GPIO19_XOR 0xf1530001 ++ ++/*GPIO20CFG*/ ++#define RSTV0910_GPIO20CFG 0xf154 ++#define FSTV0910_GPIO20_OPD 0xf1540080 ++#define FSTV0910_GPIO20_CONFIG 0xf154007e ++#define FSTV0910_GPIO20_XOR 0xf1540001 ++ ++/*GPIO21CFG*/ ++#define RSTV0910_GPIO21CFG 0xf155 ++#define FSTV0910_GPIO21_OPD 0xf1550080 ++#define FSTV0910_GPIO21_CONFIG 0xf155007e ++#define FSTV0910_GPIO21_XOR 0xf1550001 ++ ++/*GPIO22CFG*/ ++#define RSTV0910_GPIO22CFG 0xf156 ++#define FSTV0910_GPIO22_OPD 0xf1560080 ++#define FSTV0910_GPIO22_CONFIG 0xf156007e ++#define FSTV0910_GPIO22_XOR 0xf1560001 ++ ++/*STRSTATUS1*/ ++#define RSTV0910_STRSTATUS1 0xf16a ++#define FSTV0910_STRSTATUS_SEL2 0xf16a00f0 ++#define FSTV0910_STRSTATUS_SEL1 0xf16a000f ++ ++/*STRSTATUS2*/ ++#define RSTV0910_STRSTATUS2 0xf16b ++#define FSTV0910_STRSTATUS_SEL4 0xf16b00f0 ++#define FSTV0910_STRSTATUS_SEL3 0xf16b000f ++ ++/*STRSTATUS3*/ ++#define RSTV0910_STRSTATUS3 0xf16c ++#define FSTV0910_STRSTATUS_SEL6 0xf16c00f0 ++#define FSTV0910_STRSTATUS_SEL5 0xf16c000f ++ ++/*FSKTFC2*/ ++#define RSTV0910_FSKTFC2 0xf170 ++#define FSTV0910_FSKT_KMOD 0xf17000fc ++#define FSTV0910_FSKT_CAR2 0xf1700003 ++ ++/*FSKTFC1*/ ++#define RSTV0910_FSKTFC1 0xf171 ++#define FSTV0910_FSKT_CAR1 0xf17100ff ++ ++/*FSKTFC0*/ ++#define RSTV0910_FSKTFC0 0xf172 ++#define FSTV0910_FSKT_CAR0 0xf17200ff ++ ++/*FSKTDELTAF1*/ ++#define RSTV0910_FSKTDELTAF1 0xf173 ++#define FSTV0910_FSKT_DELTAF1 0xf173000f ++ ++/*FSKTDELTAF0*/ ++#define RSTV0910_FSKTDELTAF0 0xf174 ++#define FSTV0910_FSKT_DELTAF0 0xf17400ff ++ ++/*FSKTCTRL*/ ++#define RSTV0910_FSKTCTRL 0xf175 ++#define FSTV0910_FSKT_PINSEL 0xf1750080 ++#define FSTV0910_FSKT_EN_SGN 0xf1750040 ++#define FSTV0910_FSKT_MOD_SGN 0xf1750020 ++#define FSTV0910_FSKT_MOD_EN 0xf175001c ++#define FSTV0910_FSKT_DACMODE 0xf1750003 ++ ++/*FSKRFC2*/ ++#define RSTV0910_FSKRFC2 0xf176 ++#define FSTV0910_FSKR_DETSGN 0xf1760040 ++#define FSTV0910_FSKR_OUTSGN 0xf1760020 ++#define FSTV0910_FSKR_KAGC 0xf176001c ++#define FSTV0910_FSKR_CAR2 0xf1760003 ++ ++/*FSKRFC1*/ ++#define RSTV0910_FSKRFC1 0xf177 ++#define FSTV0910_FSKR_CAR1 0xf17700ff ++ ++/*FSKRFC0*/ ++#define RSTV0910_FSKRFC0 0xf178 ++#define FSTV0910_FSKR_CAR0 0xf17800ff ++ ++/*FSKRK1*/ ++#define RSTV0910_FSKRK1 0xf179 ++#define FSTV0910_FSKR_K1_EXP 0xf17900e0 ++#define FSTV0910_FSKR_K1_MANT 0xf179001f ++ ++/*FSKRK2*/ ++#define RSTV0910_FSKRK2 0xf17a ++#define FSTV0910_FSKR_K2_EXP 0xf17a00e0 ++#define FSTV0910_FSKR_K2_MANT 0xf17a001f ++ ++/*FSKRAGCR*/ ++#define RSTV0910_FSKRAGCR 0xf17b ++#define FSTV0910_FSKR_OUTCTL 0xf17b00c0 ++#define FSTV0910_FSKR_AGC_REF 0xf17b003f ++ ++/*FSKRAGC*/ ++#define RSTV0910_FSKRAGC 0xf17c ++#define FSTV0910_FSKR_AGC_ACCU 0xf17c00ff ++ ++/*FSKRALPHA*/ ++#define RSTV0910_FSKRALPHA 0xf17d ++#define FSTV0910_FSKR_ALPHA_EXP 0xf17d001c ++#define FSTV0910_FSKR_ALPHA_M 0xf17d0003 ++ ++/*FSKRPLTH1*/ ++#define RSTV0910_FSKRPLTH1 0xf17e ++#define FSTV0910_FSKR_BETA 0xf17e00f0 ++#define FSTV0910_FSKR_PLL_TRESH1 0xf17e000f ++ ++/*FSKRPLTH0*/ ++#define RSTV0910_FSKRPLTH0 0xf17f ++#define FSTV0910_FSKR_PLL_TRESH0 0xf17f00ff ++ ++/*FSKRDF1*/ ++#define RSTV0910_FSKRDF1 0xf180 ++#define FSTV0910_FSKR_OUT 0xf1800080 ++#define FSTV0910_FSKR_STATE 0xf1800060 ++#define FSTV0910_FSKR_DELTAF1 0xf180001f ++ ++/*FSKRDF0*/ ++#define RSTV0910_FSKRDF0 0xf181 ++#define FSTV0910_FSKR_DELTAF0 0xf18100ff ++ ++/*FSKRSTEPP*/ ++#define RSTV0910_FSKRSTEPP 0xf182 ++#define FSTV0910_FSKR_STEP_PLUS 0xf18200ff ++ ++/*FSKRSTEPM*/ ++#define RSTV0910_FSKRSTEPM 0xf183 ++#define FSTV0910_FSKR_STEP_MINUS 0xf18300ff ++ ++/*FSKRDET1*/ ++#define RSTV0910_FSKRDET1 0xf184 ++#define FSTV0910_FSKR_DETECT 0xf1840080 ++#define FSTV0910_FSKR_CARDET_ACCU1 0xf184000f ++ ++/*FSKRDET0*/ ++#define RSTV0910_FSKRDET0 0xf185 ++#define FSTV0910_FSKR_CARDET_ACCU0 0xf18500ff ++ ++/*FSKRDTH1*/ ++#define RSTV0910_FSKRDTH1 0xf186 ++#define FSTV0910_FSKR_CARLOSS_THRESH1 0xf18600f0 ++#define FSTV0910_FSKR_CARDET_THRESH1 0xf186000f ++ ++/*FSKRDTH0*/ ++#define RSTV0910_FSKRDTH0 0xf187 ++#define FSTV0910_FSKR_CARDET_THRESH0 0xf18700ff ++ ++/*FSKRLOSS*/ ++#define RSTV0910_FSKRLOSS 0xf188 ++#define FSTV0910_FSKR_CARLOSS_THRESH0 0xf18800ff ++ ++/*NCOARSE*/ ++#define RSTV0910_NCOARSE 0xf1b3 ++#define FSTV0910_CP 0xf1b300f8 ++#define FSTV0910_IDF 0xf1b30007 ++ ++/*NCOARSE1*/ ++#define RSTV0910_NCOARSE1 0xf1b4 ++#define FSTV0910_N_DIV 0xf1b400ff ++ ++/*NCOARSE2*/ ++#define RSTV0910_NCOARSE2 0xf1b5 ++#define FSTV0910_ODF 0xf1b5003f ++ ++/*SYNTCTRL*/ ++#define RSTV0910_SYNTCTRL 0xf1b6 ++#define FSTV0910_STANDBY 0xf1b60080 ++#define FSTV0910_BYPASSPLLCORE 0xf1b60040 ++#define FSTV0910_STOP_PLL 0xf1b60008 ++#define FSTV0910_OSCI_E 0xf1b60002 ++ ++/*FILTCTRL*/ ++#define RSTV0910_FILTCTRL 0xf1b7 ++#define FSTV0910_INV_CLKFSK 0xf1b70002 ++#define FSTV0910_BYPASS_APPLI 0xf1b70001 ++ ++/*PLLSTAT*/ ++#define RSTV0910_PLLSTAT 0xf1b8 ++#define FSTV0910_PLL_BIST_END 0xf1b80004 ++#define FSTV0910_PLLLOCK 0xf1b80001 ++ ++/*STOPCLK1*/ ++#define RSTV0910_STOPCLK1 0xf1c2 ++#define FSTV0910_INV_CLKADCI2 0xf1c20004 ++#define FSTV0910_INV_CLKADCI1 0xf1c20001 ++ ++/*STOPCLK2*/ ++#define RSTV0910_STOPCLK2 0xf1c3 ++#define FSTV0910_STOP_DVBS2FEC2 0xf1c30020 ++#define FSTV0910_STOP_DVBS2FEC 0xf1c30010 ++#define FSTV0910_STOP_DVBS1FEC2 0xf1c30008 ++#define FSTV0910_STOP_DVBS1FEC 0xf1c30004 ++#define FSTV0910_STOP_DEMOD2 0xf1c30002 ++#define FSTV0910_STOP_DEMOD 0xf1c30001 ++ ++/*PREGCTL*/ ++#define RSTV0910_PREGCTL 0xf1c8 ++#define FSTV0910_REG3V3TO2V5_POFF 0xf1c80080 ++ ++/*TSTTNR0*/ ++#define RSTV0910_TSTTNR0 0xf1df ++#define FSTV0910_FSK_PON 0xf1df0004 ++#define FSTV0910_FSK_OPENLOOP 0xf1df0002 ++ ++/*TSTTNR1*/ ++#define RSTV0910_TSTTNR1 0xf1e0 ++#define FSTV0910_BYPASS_ADC1 0xf1e00080 ++#define FSTV0910_INVADC1_CKOUT 0xf1e00040 ++#define FSTV0910_SELIQSRC1 0xf1e00030 ++#define FSTV0910_DEMOD2_SELADC 0xf1e00008 ++#define FSTV0910_DEMOD1_SELADC 0xf1e00004 ++#define FSTV0910_ADC1_PON 0xf1e00002 ++ ++/*TSTTNR2*/ ++#define RSTV0910_TSTTNR2 0xf1e1 ++#define FSTV0910_I2C_DISEQC_BYPASS 0xf1e10080 ++#define FSTV0910_I2C_DISEQC_ENCH 0xf1e10040 ++#define FSTV0910_I2C_DISEQC_PON 0xf1e10020 ++#define FSTV0910_DISEQC_CLKDIV 0xf1e1000f ++ ++/*TSTTNR3*/ ++#define RSTV0910_TSTTNR3 0xf1e2 ++#define FSTV0910_BYPASS_ADC2 0xf1e20080 ++#define FSTV0910_INVADC2_CKOUT 0xf1e20040 ++#define FSTV0910_SELIQSRC2 0xf1e20030 ++#define FSTV0910_ADC2_PON 0xf1e20002 ++ ++/*P2_IQCONST*/ ++#define RSTV0910_P2_IQCONST 0xf200 ++#define FSTV0910_P2_CONSTEL_SELECT 0xf2000060 ++#define FSTV0910_P2_IQSYMB_SEL 0xf200001f ++ ++/*P2_NOSCFG*/ ++#define RSTV0910_P2_NOSCFG 0xf201 ++#define FSTV0910_P2_DIS_ACMRATIO 0xf2010080 ++#define FSTV0910_P2_NOSIN_EGALSEL 0xf2010040 ++#define FSTV0910_P2_DUMMYPL_NOSDATA 0xf2010020 ++#define FSTV0910_P2_NOSPLH_BETA 0xf2010018 ++#define FSTV0910_P2_NOSDATA_BETA 0xf2010007 ++ ++/*P2_ISYMB*/ ++#define RSTV0910_P2_ISYMB 0xf202 ++#define FSTV0910_P2_I_SYMBOL 0xf20201ff ++ ++/*P2_QSYMB*/ ++#define RSTV0910_P2_QSYMB 0xf203 ++#define FSTV0910_P2_Q_SYMBOL 0xf20301ff ++ ++/*P2_AGC1CFG*/ ++#define RSTV0910_P2_AGC1CFG 0xf204 ++#define FSTV0910_P2_DC_FROZEN 0xf2040080 ++#define FSTV0910_P2_DC_CORRECT 0xf2040040 ++#define FSTV0910_P2_AMM_FROZEN 0xf2040020 ++#define FSTV0910_P2_AMM_CORRECT 0xf2040010 ++#define FSTV0910_P2_QUAD_FROZEN 0xf2040008 ++#define FSTV0910_P2_QUAD_CORRECT 0xf2040004 ++#define FSTV0910_P2_DCCOMP_SLOW 0xf2040002 ++#define FSTV0910_P2_IQMISM_SLOW 0xf2040001 ++ ++/*P2_AGC1CN*/ ++#define RSTV0910_P2_AGC1CN 0xf206 ++#define FSTV0910_P2_AGC1_LOCKED 0xf2060080 ++#define FSTV0910_P2_AGC1_OVERFLOW 0xf2060040 ++#define FSTV0910_P2_AGC1_NOSLOWLK 0xf2060020 ++#define FSTV0910_P2_AGC1_MINPOWER 0xf2060010 ++#define FSTV0910_P2_AGCOUT_FAST 0xf2060008 ++#define FSTV0910_P2_AGCIQ_BETA 0xf2060007 ++ ++/*P2_AGC1REF*/ ++#define RSTV0910_P2_AGC1REF 0xf207 ++#define FSTV0910_P2_AGCIQ_REF 0xf20700ff ++ ++/*P2_IDCCOMP*/ ++#define RSTV0910_P2_IDCCOMP 0xf208 ++#define FSTV0910_P2_IAVERAGE_ADJ 0xf20801ff ++ ++/*P2_QDCCOMP*/ ++#define RSTV0910_P2_QDCCOMP 0xf209 ++#define FSTV0910_P2_QAVERAGE_ADJ 0xf20901ff ++ ++/*P2_POWERI*/ ++#define RSTV0910_P2_POWERI 0xf20a ++#define FSTV0910_P2_POWER_I 0xf20a00ff ++ ++/*P2_POWERQ*/ ++#define RSTV0910_P2_POWERQ 0xf20b ++#define FSTV0910_P2_POWER_Q 0xf20b00ff ++ ++/*P2_AGC1AMM*/ ++#define RSTV0910_P2_AGC1AMM 0xf20c ++#define FSTV0910_P2_AMM_VALUE 0xf20c00ff ++ ++/*P2_AGC1QUAD*/ ++#define RSTV0910_P2_AGC1QUAD 0xf20d ++#define FSTV0910_P2_QUAD_VALUE 0xf20d01ff ++ ++/*P2_AGCIQIN1*/ ++#define RSTV0910_P2_AGCIQIN1 0xf20e ++#define FSTV0910_P2_AGCIQ_VALUE1 0xf20e00ff ++ ++/*P2_AGCIQIN0*/ ++#define RSTV0910_P2_AGCIQIN0 0xf20f ++#define FSTV0910_P2_AGCIQ_VALUE0 0xf20f00ff ++ ++/*P2_DEMOD*/ ++#define RSTV0910_P2_DEMOD 0xf210 ++#define FSTV0910_P2_MANUALS2_ROLLOFF 0xf2100080 ++#define FSTV0910_P2_SPECINV_CONTROL 0xf2100030 ++#define FSTV0910_P2_MANUALSX_ROLLOFF 0xf2100004 ++#define FSTV0910_P2_ROLLOFF_CONTROL 0xf2100003 ++ ++/*P2_DMDMODCOD*/ ++#define RSTV0910_P2_DMDMODCOD 0xf211 ++#define FSTV0910_P2_MANUAL_MODCOD 0xf2110080 ++#define FSTV0910_P2_DEMOD_MODCOD 0xf211007c ++#define FSTV0910_P2_DEMOD_TYPE 0xf2110003 ++ ++/*P2_DSTATUS*/ ++#define RSTV0910_P2_DSTATUS 0xf212 ++#define FSTV0910_P2_CAR_LOCK 0xf2120080 ++#define FSTV0910_P2_TMGLOCK_QUALITY 0xf2120060 ++#define FSTV0910_P2_SDVBS1_ENABLE 0xf2120010 ++#define FSTV0910_P2_LOCK_DEFINITIF 0xf2120008 ++#define FSTV0910_P2_TIMING_IS_LOCKED 0xf2120004 ++#define FSTV0910_P2_DEMOD_SYSCFG 0xf2120002 ++#define FSTV0910_P2_OVADC_DETECT 0xf2120001 ++ ++/*P2_DSTATUS2*/ ++#define RSTV0910_P2_DSTATUS2 0xf213 ++#define FSTV0910_P2_DEMOD_DELOCK 0xf2130080 ++#define FSTV0910_P2_DEMOD_TIMEOUT 0xf2130040 ++#define FSTV0910_P2_MODCODRQ_SYNCTAG 0xf2130020 ++#define FSTV0910_P2_POLYPH_SATEVENT 0xf2130010 ++#define FSTV0910_P2_AGC1_NOSIGNALACK 0xf2130008 ++#define FSTV0910_P2_AGC2_OVERFLOW 0xf2130004 ++#define FSTV0910_P2_CFR_OVERFLOW 0xf2130002 ++#define FSTV0910_P2_GAMMA_OVERUNDER 0xf2130001 ++ ++/*P2_DMDCFGMD*/ ++#define RSTV0910_P2_DMDCFGMD 0xf214 ++#define FSTV0910_P2_DVBS2_ENABLE 0xf2140080 ++#define FSTV0910_P2_DVBS1_ENABLE 0xf2140040 ++#define FSTV0910_P2_SCAN_ENABLE 0xf2140010 ++#define FSTV0910_P2_CFR_AUTOSCAN 0xf2140008 ++#define FSTV0910_P2_NOFORCE_RELOCK 0xf2140004 ++#define FSTV0910_P2_TUN_RNG 0xf2140003 ++ ++/*P2_DMDCFG2*/ ++#define RSTV0910_P2_DMDCFG2 0xf215 ++#define FSTV0910_P2_AGC1_WAITLOCK 0xf2150080 ++#define FSTV0910_P2_S1S2_SEQUENTIAL 0xf2150040 ++#define FSTV0910_P2_BLINDPEA_MODE 0xf2150020 ++#define FSTV0910_P2_INFINITE_RELOCK 0xf2150010 ++#define FSTV0910_P2_BWOFFSET_COLDWARM 0xf2150008 ++#define FSTV0910_P2_TMGLOCK_NSCANSTOP 0xf2150004 ++#define FSTV0910_P2_COARSE_LK3MODE 0xf2150002 ++#define FSTV0910_P2_COARSE_LK2MODE 0xf2150001 ++ ++/*P2_DMDISTATE*/ ++#define RSTV0910_P2_DMDISTATE 0xf216 ++#define FSTV0910_P2_I2C_NORESETDMODE 0xf2160080 ++#define FSTV0910_P2_FORCE_ETAPED 0xf2160040 ++#define FSTV0910_P2_SDMDRST_DIRCLK 0xf2160020 ++#define FSTV0910_P2_I2C_DEMOD_MODE 0xf216001f ++ ++/*P2_DMDT0M*/ ++#define RSTV0910_P2_DMDT0M 0xf217 ++#define FSTV0910_P2_DMDT0_MIN 0xf21700ff ++ ++/*P2_DMDSTATE*/ ++#define RSTV0910_P2_DMDSTATE 0xf21b ++#define FSTV0910_P2_DEMOD_LOCKED 0xf21b0080 ++#define FSTV0910_P2_HEADER_MODE 0xf21b0060 ++#define FSTV0910_P2_DEMOD_MODE 0xf21b001f ++ ++/*P2_DMDFLYW*/ ++#define RSTV0910_P2_DMDFLYW 0xf21c ++#define FSTV0910_P2_I2C_IRQVAL 0xf21c00f0 ++#define FSTV0910_P2_FLYWHEEL_CPT 0xf21c000f ++ ++/*P2_DSTATUS3*/ ++#define RSTV0910_P2_DSTATUS3 0xf21d ++#define FSTV0910_P2_CFR_ZIGZAG 0xf21d0080 ++#define FSTV0910_P2_DEMOD_CFGMODE 0xf21d0060 ++#define FSTV0910_P2_GAMMA_LOWBAUDRATE 0xf21d0010 ++#define FSTV0910_P2_RELOCK_MODE 0xf21d0008 ++#define FSTV0910_P2_DEMOD_FAIL 0xf21d0004 ++#define FSTV0910_P2_ETAPE1A_DVBXMEM 0xf21d0003 ++ ++/*P2_DMDCFG3*/ ++#define RSTV0910_P2_DMDCFG3 0xf21e ++#define FSTV0910_P2_DVBS1_TMGWAIT 0xf21e0080 ++#define FSTV0910_P2_NO_BWCENTERING 0xf21e0040 ++#define FSTV0910_P2_INV_SEQSRCH 0xf21e0020 ++#define FSTV0910_P2_DIS_SFRUPLOW_TRK 0xf21e0010 ++#define FSTV0910_P2_NOSTOP_FIFOFULL 0xf21e0008 ++#define FSTV0910_P2_LOCKTIME_MODE 0xf21e0007 ++ ++/*P2_DMDCFG4*/ ++#define RSTV0910_P2_DMDCFG4 0xf21f ++#define FSTV0910_P2_DIS_VITLOCK 0xf21f0080 ++#define FSTV0910_P2_S1S2TOUT_FAST 0xf21f0040 ++#define FSTV0910_P2_DEMOD_FASTLOCK 0xf21f0020 ++#define FSTV0910_P2_S1HIER_ENABLE 0xf21f0010 ++#define FSTV0910_P2_TUNER_NRELAUNCH 0xf21f0008 ++#define FSTV0910_P2_DIS_CLKENABLE 0xf21f0004 ++#define FSTV0910_P2_DIS_HDRDIVLOCK 0xf21f0002 ++#define FSTV0910_P2_NO_TNRWBINIT 0xf21f0001 ++ ++/*P2_CORRELMANT*/ ++#define RSTV0910_P2_CORRELMANT 0xf220 ++#define FSTV0910_P2_CORREL_MANT 0xf22000ff ++ ++/*P2_CORRELABS*/ ++#define RSTV0910_P2_CORRELABS 0xf221 ++#define FSTV0910_P2_CORREL_ABS 0xf22100ff ++ ++/*P2_CORRELEXP*/ ++#define RSTV0910_P2_CORRELEXP 0xf222 ++#define FSTV0910_P2_CORREL_ABSEXP 0xf22200f0 ++#define FSTV0910_P2_CORREL_EXP 0xf222000f ++ ++/*P2_PLHMODCOD*/ ++#define RSTV0910_P2_PLHMODCOD 0xf224 ++#define FSTV0910_P2_SPECINV_DEMOD 0xf2240080 ++#define FSTV0910_P2_PLH_MODCOD 0xf224007c ++#define FSTV0910_P2_PLH_TYPE 0xf2240003 ++ ++/*P2_DMDREG*/ ++#define RSTV0910_P2_DMDREG 0xf225 ++#define FSTV0910_P2_EXTPSK_MODE 0xf2250080 ++#define FSTV0910_P2_HIER_SHORTFRAME 0xf2250002 ++#define FSTV0910_P2_DECIM_PLFRAMES 0xf2250001 ++ ++/*P2_AGC2O*/ ++#define RSTV0910_P2_AGC2O 0xf22c ++#define FSTV0910_P2_CSTENV_MODE 0xf22c00c0 ++#define FSTV0910_P2_AGC2_LKSQRT 0xf22c0020 ++#define FSTV0910_P2_AGC2_LKMODE 0xf22c0010 ++#define FSTV0910_P2_AGC2_LKEQUA 0xf22c0008 ++#define FSTV0910_P2_AGC2_COEF 0xf22c0007 ++ ++/*P2_AGC2REF*/ ++#define RSTV0910_P2_AGC2REF 0xf22d ++#define FSTV0910_P2_AGC2_REF 0xf22d00ff ++ ++/*P2_AGC1ADJ*/ ++#define RSTV0910_P2_AGC1ADJ 0xf22e ++#define FSTV0910_P2_AGC1ADJ_MANUAL 0xf22e0080 ++#define FSTV0910_P2_AGC1_ADJUSTED 0xf22e007f ++ ++/*P2_AGC2I1*/ ++#define RSTV0910_P2_AGC2I1 0xf236 ++#define FSTV0910_P2_AGC2_INTEGRATOR1 0xf23600ff ++ ++/*P2_AGC2I0*/ ++#define RSTV0910_P2_AGC2I0 0xf237 ++#define FSTV0910_P2_AGC2_INTEGRATOR0 0xf23700ff ++ ++/*P2_CARCFG*/ ++#define RSTV0910_P2_CARCFG 0xf238 ++#define FSTV0910_P2_CFRUPLOW_AUTO 0xf2380080 ++#define FSTV0910_P2_CFRUPLOW_TEST 0xf2380040 ++#define FSTV0910_P2_WIDE_FREQDET 0xf2380020 ++#define FSTV0910_P2_CARHDR_NODIV8 0xf2380010 ++#define FSTV0910_P2_I2C_ROTA 0xf2380008 ++#define FSTV0910_P2_ROTAON 0xf2380004 ++#define FSTV0910_P2_PH_DET_ALGO 0xf2380003 ++ ++/*P2_ACLC*/ ++#define RSTV0910_P2_ACLC 0xf239 ++#define FSTV0910_P2_CARS1_ANOSAUTO 0xf2390040 ++#define FSTV0910_P2_CAR_ALPHA_MANT 0xf2390030 ++#define FSTV0910_P2_CAR_ALPHA_EXP 0xf239000f ++ ++/*P2_BCLC*/ ++#define RSTV0910_P2_BCLC 0xf23a ++#define FSTV0910_P2_CARS1_BNOSAUTO 0xf23a0040 ++#define FSTV0910_P2_CAR_BETA_MANT 0xf23a0030 ++#define FSTV0910_P2_CAR_BETA_EXP 0xf23a000f ++ ++/*P2_CARFREQ*/ ++#define RSTV0910_P2_CARFREQ 0xf23d ++#define FSTV0910_P2_KC_COARSE_EXP 0xf23d00f0 ++#define FSTV0910_P2_BETA_FREQ 0xf23d000f ++ ++/*P2_CARHDR*/ ++#define RSTV0910_P2_CARHDR 0xf23e ++#define FSTV0910_P2_K_FREQ_HDR 0xf23e00ff ++ ++/*P2_LDT*/ ++#define RSTV0910_P2_LDT 0xf23f ++#define FSTV0910_P2_CARLOCK_THRES 0xf23f01ff ++ ++/*P2_LDT2*/ ++#define RSTV0910_P2_LDT2 0xf240 ++#define FSTV0910_P2_CARLOCK_THRES2 0xf24001ff ++ ++/*P2_CFRICFG*/ ++#define RSTV0910_P2_CFRICFG 0xf241 ++#define FSTV0910_P2_CFRINIT_UNVALRNG 0xf2410080 ++#define FSTV0910_P2_CFRINIT_LUNVALCPT 0xf2410040 ++#define FSTV0910_P2_CFRINIT_ABORTDBL 0xf2410020 ++#define FSTV0910_P2_CFRINIT_ABORTPRED 0xf2410010 ++#define FSTV0910_P2_CFRINIT_UNVALSKIP 0xf2410008 ++#define FSTV0910_P2_CFRINIT_CSTINC 0xf2410004 ++#define FSTV0910_P2_CFRIROLL_GARDER 0xf2410002 ++#define FSTV0910_P2_NEG_CFRSTEP 0xf2410001 ++ ++/*P2_CFRUP1*/ ++#define RSTV0910_P2_CFRUP1 0xf242 ++#define FSTV0910_P2_CFR_UP1 0xf24201ff ++ ++/*P2_CFRUP0*/ ++#define RSTV0910_P2_CFRUP0 0xf243 ++#define FSTV0910_P2_CFR_UP0 0xf24300ff ++ ++/*P2_CFRIBASE1*/ ++#define RSTV0910_P2_CFRIBASE1 0xf244 ++#define FSTV0910_P2_CFRINIT_BASE1 0xf24400ff ++ ++/*P2_CFRIBASE0*/ ++#define RSTV0910_P2_CFRIBASE0 0xf245 ++#define FSTV0910_P2_CFRINIT_BASE0 0xf24500ff ++ ++/*P2_CFRLOW1*/ ++#define RSTV0910_P2_CFRLOW1 0xf246 ++#define FSTV0910_P2_CFR_LOW1 0xf24601ff ++ ++/*P2_CFRLOW0*/ ++#define RSTV0910_P2_CFRLOW0 0xf247 ++#define FSTV0910_P2_CFR_LOW0 0xf24700ff ++ ++/*P2_CFRINIT1*/ ++#define RSTV0910_P2_CFRINIT1 0xf248 ++#define FSTV0910_P2_CFR_INIT1 0xf24801ff ++ ++/*P2_CFRINIT0*/ ++#define RSTV0910_P2_CFRINIT0 0xf249 ++#define FSTV0910_P2_CFR_INIT0 0xf24900ff ++ ++/*P2_CFRINC1*/ ++#define RSTV0910_P2_CFRINC1 0xf24a ++#define FSTV0910_P2_MANUAL_CFRINC 0xf24a0080 ++#define FSTV0910_P2_CFR_INC1 0xf24a003f ++ ++/*P2_CFRINC0*/ ++#define RSTV0910_P2_CFRINC0 0xf24b ++#define FSTV0910_P2_CFR_INC0 0xf24b00ff ++ ++/*P2_CFR2*/ ++#define RSTV0910_P2_CFR2 0xf24c ++#define FSTV0910_P2_CAR_FREQ2 0xf24c01ff ++ ++/*P2_CFR1*/ ++#define RSTV0910_P2_CFR1 0xf24d ++#define FSTV0910_P2_CAR_FREQ1 0xf24d00ff ++ ++/*P2_CFR0*/ ++#define RSTV0910_P2_CFR0 0xf24e ++#define FSTV0910_P2_CAR_FREQ0 0xf24e00ff ++ ++/*P2_LDI*/ ++#define RSTV0910_P2_LDI 0xf24f ++#define FSTV0910_P2_LOCK_DET_INTEGR 0xf24f01ff ++ ++/*P2_TMGCFG*/ ++#define RSTV0910_P2_TMGCFG 0xf250 ++#define FSTV0910_P2_TMGLOCK_BETA 0xf25000c0 ++#define FSTV0910_P2_DO_TIMING_CORR 0xf2500010 ++#define FSTV0910_P2_MANUAL_SCAN 0xf250000c ++#define FSTV0910_P2_TMG_MINFREQ 0xf2500003 ++ ++/*P2_RTC*/ ++#define RSTV0910_P2_RTC 0xf251 ++#define FSTV0910_P2_TMGALPHA_EXP 0xf25100f0 ++#define FSTV0910_P2_TMGBETA_EXP 0xf251000f ++ ++/*P2_RTCS2*/ ++#define RSTV0910_P2_RTCS2 0xf252 ++#define FSTV0910_P2_TMGALPHAS2_EXP 0xf25200f0 ++#define FSTV0910_P2_TMGBETAS2_EXP 0xf252000f ++ ++/*P2_TMGTHRISE*/ ++#define RSTV0910_P2_TMGTHRISE 0xf253 ++#define FSTV0910_P2_TMGLOCK_THRISE 0xf25300ff ++ ++/*P2_TMGTHFALL*/ ++#define RSTV0910_P2_TMGTHFALL 0xf254 ++#define FSTV0910_P2_TMGLOCK_THFALL 0xf25400ff ++ ++/*P2_SFRUPRATIO*/ ++#define RSTV0910_P2_SFRUPRATIO 0xf255 ++#define FSTV0910_P2_SFR_UPRATIO 0xf25500ff ++ ++/*P2_SFRLOWRATIO*/ ++#define RSTV0910_P2_SFRLOWRATIO 0xf256 ++#define FSTV0910_P2_SFR_LOWRATIO 0xf25600ff ++ ++/*P2_KTTMG*/ ++#define RSTV0910_P2_KTTMG 0xf257 ++#define FSTV0910_P2_KT_TMG_EXP 0xf25700f0 ++ ++/*P2_KREFTMG*/ ++#define RSTV0910_P2_KREFTMG 0xf258 ++#define FSTV0910_P2_KREF_TMG 0xf25800ff ++ ++/*P2_SFRSTEP*/ ++#define RSTV0910_P2_SFRSTEP 0xf259 ++#define FSTV0910_P2_SFR_SCANSTEP 0xf25900f0 ++#define FSTV0910_P2_SFR_CENTERSTEP 0xf259000f ++ ++/*P2_TMGCFG2*/ ++#define RSTV0910_P2_TMGCFG2 0xf25a ++#define FSTV0910_P2_KREFTMG2_DECMODE 0xf25a00c0 ++#define FSTV0910_P2_DIS_AUTOSAMP 0xf25a0008 ++#define FSTV0910_P2_SCANINIT_QUART 0xf25a0004 ++#define FSTV0910_P2_NOTMG_DVBS1DERAT 0xf25a0002 ++#define FSTV0910_P2_SFRRATIO_FINE 0xf25a0001 ++ ++/*P2_KREFTMG2*/ ++#define RSTV0910_P2_KREFTMG2 0xf25b ++#define FSTV0910_P2_KREF_TMG2 0xf25b00ff ++ ++/*P2_TMGCFG3*/ ++#define RSTV0910_P2_TMGCFG3 0xf25d ++#define FSTV0910_P2_CFRINC_MODE 0xf25d0070 ++#define FSTV0910_P2_CONT_TMGCENTER 0xf25d0008 ++#define FSTV0910_P2_AUTO_GUP 0xf25d0004 ++#define FSTV0910_P2_AUTO_GLOW 0xf25d0002 ++#define FSTV0910_P2_SFRVAL_MINMODE 0xf25d0001 ++ ++/*P2_SFRINIT1*/ ++#define RSTV0910_P2_SFRINIT1 0xf25e ++#define FSTV0910_P2_SFR_INIT1 0xf25e00ff ++ ++/*P2_SFRINIT0*/ ++#define RSTV0910_P2_SFRINIT0 0xf25f ++#define FSTV0910_P2_SFR_INIT0 0xf25f00ff ++ ++/*P2_SFRUP1*/ ++#define RSTV0910_P2_SFRUP1 0xf260 ++#define FSTV0910_P2_SYMB_FREQ_UP1 0xf26000ff ++ ++/*P2_SFRUP0*/ ++#define RSTV0910_P2_SFRUP0 0xf261 ++#define FSTV0910_P2_SYMB_FREQ_UP0 0xf26100ff ++ ++/*P2_SFRLOW1*/ ++#define RSTV0910_P2_SFRLOW1 0xf262 ++#define FSTV0910_P2_SYMB_FREQ_LOW1 0xf26200ff ++ ++/*P2_SFRLOW0*/ ++#define RSTV0910_P2_SFRLOW0 0xf263 ++#define FSTV0910_P2_SYMB_FREQ_LOW0 0xf26300ff ++ ++/*P2_SFR3*/ ++#define RSTV0910_P2_SFR3 0xf264 ++#define FSTV0910_P2_SYMB_FREQ3 0xf26400ff ++ ++/*P2_SFR2*/ ++#define RSTV0910_P2_SFR2 0xf265 ++#define FSTV0910_P2_SYMB_FREQ2 0xf26500ff ++ ++/*P2_SFR1*/ ++#define RSTV0910_P2_SFR1 0xf266 ++#define FSTV0910_P2_SYMB_FREQ1 0xf26600ff ++ ++/*P2_SFR0*/ ++#define RSTV0910_P2_SFR0 0xf267 ++#define FSTV0910_P2_SYMB_FREQ0 0xf26700ff ++ ++/*P2_TMGREG2*/ ++#define RSTV0910_P2_TMGREG2 0xf268 ++#define FSTV0910_P2_TMGREG2 0xf26800ff ++ ++/*P2_TMGREG1*/ ++#define RSTV0910_P2_TMGREG1 0xf269 ++#define FSTV0910_P2_TMGREG1 0xf26900ff ++ ++/*P2_TMGREG0*/ ++#define RSTV0910_P2_TMGREG0 0xf26a ++#define FSTV0910_P2_TMGREG0 0xf26a00ff ++ ++/*P2_TMGLOCK1*/ ++#define RSTV0910_P2_TMGLOCK1 0xf26b ++#define FSTV0910_P2_TMGLOCK_LEVEL1 0xf26b01ff ++ ++/*P2_TMGLOCK0*/ ++#define RSTV0910_P2_TMGLOCK0 0xf26c ++#define FSTV0910_P2_TMGLOCK_LEVEL0 0xf26c00ff ++ ++/*P2_TMGOBS*/ ++#define RSTV0910_P2_TMGOBS 0xf26d ++#define FSTV0910_P2_ROLLOFF_STATUS 0xf26d00c0 ++#define FSTV0910_P2_SCAN_SIGN 0xf26d0030 ++#define FSTV0910_P2_TMG_SCANNING 0xf26d0008 ++#define FSTV0910_P2_CHCENTERING_MODE 0xf26d0004 ++#define FSTV0910_P2_TMG_SCANFAIL 0xf26d0002 ++ ++/*P2_EQUALCFG*/ ++#define RSTV0910_P2_EQUALCFG 0xf26f ++#define FSTV0910_P2_NOTMG_NEGALWAIT 0xf26f0080 ++#define FSTV0910_P2_EQUAL_ON 0xf26f0040 ++#define FSTV0910_P2_SEL_EQUALCOR 0xf26f0038 ++#define FSTV0910_P2_MU_EQUALDFE 0xf26f0007 ++ ++/*P2_EQUAI1*/ ++#define RSTV0910_P2_EQUAI1 0xf270 ++#define FSTV0910_P2_EQUA_ACCI1 0xf27001ff ++ ++/*P2_EQUAQ1*/ ++#define RSTV0910_P2_EQUAQ1 0xf271 ++#define FSTV0910_P2_EQUA_ACCQ1 0xf27101ff ++ ++/*P2_EQUAI2*/ ++#define RSTV0910_P2_EQUAI2 0xf272 ++#define FSTV0910_P2_EQUA_ACCI2 0xf27201ff ++ ++/*P2_EQUAQ2*/ ++#define RSTV0910_P2_EQUAQ2 0xf273 ++#define FSTV0910_P2_EQUA_ACCQ2 0xf27301ff ++ ++/*P2_EQUAI3*/ ++#define RSTV0910_P2_EQUAI3 0xf274 ++#define FSTV0910_P2_EQUA_ACCI3 0xf27401ff ++ ++/*P2_EQUAQ3*/ ++#define RSTV0910_P2_EQUAQ3 0xf275 ++#define FSTV0910_P2_EQUA_ACCQ3 0xf27501ff ++ ++/*P2_EQUAI4*/ ++#define RSTV0910_P2_EQUAI4 0xf276 ++#define FSTV0910_P2_EQUA_ACCI4 0xf27601ff ++ ++/*P2_EQUAQ4*/ ++#define RSTV0910_P2_EQUAQ4 0xf277 ++#define FSTV0910_P2_EQUA_ACCQ4 0xf27701ff ++ ++/*P2_EQUAI5*/ ++#define RSTV0910_P2_EQUAI5 0xf278 ++#define FSTV0910_P2_EQUA_ACCI5 0xf27801ff ++ ++/*P2_EQUAQ5*/ ++#define RSTV0910_P2_EQUAQ5 0xf279 ++#define FSTV0910_P2_EQUA_ACCQ5 0xf27901ff ++ ++/*P2_EQUAI6*/ ++#define RSTV0910_P2_EQUAI6 0xf27a ++#define FSTV0910_P2_EQUA_ACCI6 0xf27a01ff ++ ++/*P2_EQUAQ6*/ ++#define RSTV0910_P2_EQUAQ6 0xf27b ++#define FSTV0910_P2_EQUA_ACCQ6 0xf27b01ff ++ ++/*P2_EQUAI7*/ ++#define RSTV0910_P2_EQUAI7 0xf27c ++#define FSTV0910_P2_EQUA_ACCI7 0xf27c01ff ++ ++/*P2_EQUAQ7*/ ++#define RSTV0910_P2_EQUAQ7 0xf27d ++#define FSTV0910_P2_EQUA_ACCQ7 0xf27d01ff ++ ++/*P2_EQUAI8*/ ++#define RSTV0910_P2_EQUAI8 0xf27e ++#define FSTV0910_P2_EQUA_ACCI8 0xf27e01ff ++ ++/*P2_EQUAQ8*/ ++#define RSTV0910_P2_EQUAQ8 0xf27f ++#define FSTV0910_P2_EQUA_ACCQ8 0xf27f01ff ++ ++/*P2_NNOSDATAT1*/ ++#define RSTV0910_P2_NNOSDATAT1 0xf280 ++#define FSTV0910_P2_NOSDATAT_NORMED1 0xf28000ff ++ ++/*P2_NNOSDATAT0*/ ++#define RSTV0910_P2_NNOSDATAT0 0xf281 ++#define FSTV0910_P2_NOSDATAT_NORMED0 0xf28100ff ++ ++/*P2_NNOSDATA1*/ ++#define RSTV0910_P2_NNOSDATA1 0xf282 ++#define FSTV0910_P2_NOSDATA_NORMED1 0xf28200ff ++ ++/*P2_NNOSDATA0*/ ++#define RSTV0910_P2_NNOSDATA0 0xf283 ++#define FSTV0910_P2_NOSDATA_NORMED0 0xf28300ff ++ ++/*P2_NNOSPLHT1*/ ++#define RSTV0910_P2_NNOSPLHT1 0xf284 ++#define FSTV0910_P2_NOSPLHT_NORMED1 0xf28400ff ++ ++/*P2_NNOSPLHT0*/ ++#define RSTV0910_P2_NNOSPLHT0 0xf285 ++#define FSTV0910_P2_NOSPLHT_NORMED0 0xf28500ff ++ ++/*P2_NNOSPLH1*/ ++#define RSTV0910_P2_NNOSPLH1 0xf286 ++#define FSTV0910_P2_NOSPLH_NORMED1 0xf28600ff ++ ++/*P2_NNOSPLH0*/ ++#define RSTV0910_P2_NNOSPLH0 0xf287 ++#define FSTV0910_P2_NOSPLH_NORMED0 0xf28700ff ++ ++/*P2_NOSDATAT1*/ ++#define RSTV0910_P2_NOSDATAT1 0xf288 ++#define FSTV0910_P2_NOSDATAT_UNNORMED1 0xf28800ff ++ ++/*P2_NOSDATAT0*/ ++#define RSTV0910_P2_NOSDATAT0 0xf289 ++#define FSTV0910_P2_NOSDATAT_UNNORMED0 0xf28900ff ++ ++/*P2_NNOSFRAME1*/ ++#define RSTV0910_P2_NNOSFRAME1 0xf28a ++#define FSTV0910_P2_NOSFRAME_NORMED1 0xf28a00ff ++ ++/*P2_NNOSFRAME0*/ ++#define RSTV0910_P2_NNOSFRAME0 0xf28b ++#define FSTV0910_P2_NOSFRAME_NORMED0 0xf28b00ff ++ ++/*P2_NNOSRAD1*/ ++#define RSTV0910_P2_NNOSRAD1 0xf28c ++#define FSTV0910_P2_NOSRADIAL_NORMED1 0xf28c00ff ++ ++/*P2_NNOSRAD0*/ ++#define RSTV0910_P2_NNOSRAD0 0xf28d ++#define FSTV0910_P2_NOSRADIAL_NORMED0 0xf28d00ff ++ ++/*P2_NOSCFGF1*/ ++#define RSTV0910_P2_NOSCFGF1 0xf28e ++#define FSTV0910_P2_LOWNOISE_MESURE 0xf28e0080 ++#define FSTV0910_P2_NOS_DELFRAME 0xf28e0040 ++#define FSTV0910_P2_NOSDATA_MODE 0xf28e0030 ++#define FSTV0910_P2_FRAMESEL_TYPESEL 0xf28e000c ++#define FSTV0910_P2_FRAMESEL_TYPE 0xf28e0003 ++ ++/*P2_CAR2CFG*/ ++#define RSTV0910_P2_CAR2CFG 0xf290 ++#define FSTV0910_P2_DESCRAMB_OFF 0xf2900080 ++#define FSTV0910_P2_EN_PHNOSRAM 0xf2900020 ++#define FSTV0910_P2_STOP_CFR2UPDATE 0xf2900010 ++#define FSTV0910_P2_STOP_NCO2UPDATE 0xf2900008 ++#define FSTV0910_P2_ROTA2ON 0xf2900004 ++#define FSTV0910_P2_PH_DET_ALGO2 0xf2900003 ++ ++/*P2_CFR2CFR1*/ ++#define RSTV0910_P2_CFR2CFR1 0xf291 ++#define FSTV0910_P2_CFR2_S2CONTROL 0xf29100c0 ++#define FSTV0910_P2_EN_S2CAR2CENTER 0xf2910020 ++#define FSTV0910_P2_BCHERRCFR2_MODE 0xf2910018 ++#define FSTV0910_P2_CFR2TOCFR1_BETA 0xf2910007 ++ ++/*P2_CAR3CFG*/ ++#define RSTV0910_P2_CAR3CFG 0xf292 ++#define FSTV0910_P2_CARRIER23_MODE 0xf29200c0 ++#define FSTV0910_P2_CAR3INTERM_DVBS1 0xf2920020 ++#define FSTV0910_P2_ABAMPLIF_MODE 0xf2920018 ++#define FSTV0910_P2_CARRIER3_ALPHA3DL 0xf2920007 ++ ++/*P2_CFR22*/ ++#define RSTV0910_P2_CFR22 0xf293 ++#define FSTV0910_P2_CAR2_FREQ2 0xf29301ff ++ ++/*P2_CFR21*/ ++#define RSTV0910_P2_CFR21 0xf294 ++#define FSTV0910_P2_CAR2_FREQ1 0xf29400ff ++ ++/*P2_CFR20*/ ++#define RSTV0910_P2_CFR20 0xf295 ++#define FSTV0910_P2_CAR2_FREQ0 0xf29500ff ++ ++/*P2_ACLC2S2Q*/ ++#define RSTV0910_P2_ACLC2S2Q 0xf297 ++#define FSTV0910_P2_ENAB_SPSKSYMB 0xf2970080 ++#define FSTV0910_P2_CAR2S2_QANOSAUTO 0xf2970040 ++#define FSTV0910_P2_CAR2S2_Q_ALPH_M 0xf2970030 ++#define FSTV0910_P2_CAR2S2_Q_ALPH_E 0xf297000f ++ ++/*P2_ACLC2S28*/ ++#define RSTV0910_P2_ACLC2S28 0xf298 ++#define FSTV0910_P2_OLDI3Q_MODE 0xf2980080 ++#define FSTV0910_P2_CAR2S2_8ANOSAUTO 0xf2980040 ++#define FSTV0910_P2_CAR2S2_8_ALPH_M 0xf2980030 ++#define FSTV0910_P2_CAR2S2_8_ALPH_E 0xf298000f ++ ++/*P2_ACLC2S216A*/ ++#define RSTV0910_P2_ACLC2S216A 0xf299 ++#define FSTV0910_P2_CAR2S2_16ANOSAUTO 0xf2990040 ++#define FSTV0910_P2_CAR2S2_16A_ALPH_M 0xf2990030 ++#define FSTV0910_P2_CAR2S2_16A_ALPH_E 0xf299000f ++ ++/*P2_ACLC2S232A*/ ++#define RSTV0910_P2_ACLC2S232A 0xf29a ++#define FSTV0910_P2_CAR2S2_32ANOSUATO 0xf29a0040 ++#define FSTV0910_P2_CAR2S2_32A_ALPH_M 0xf29a0030 ++#define FSTV0910_P2_CAR2S2_32A_ALPH_E 0xf29a000f ++ ++/*P2_BCLC2S2Q*/ ++#define RSTV0910_P2_BCLC2S2Q 0xf29c ++#define FSTV0910_P2_DVBS2S2Q_NIP 0xf29c0080 ++#define FSTV0910_P2_CAR2S2_QBNOSAUTO 0xf29c0040 ++#define FSTV0910_P2_CAR2S2_Q_BETA_M 0xf29c0030 ++#define FSTV0910_P2_CAR2S2_Q_BETA_E 0xf29c000f ++ ++/*P2_BCLC2S28*/ ++#define RSTV0910_P2_BCLC2S28 0xf29d ++#define FSTV0910_P2_DVBS2S28_NIP 0xf29d0080 ++#define FSTV0910_P2_CAR2S2_8BNOSAUTO 0xf29d0040 ++#define FSTV0910_P2_CAR2S2_8_BETA_M 0xf29d0030 ++#define FSTV0910_P2_CAR2S2_8_BETA_E 0xf29d000f ++ ++/*P2_PLROOT2*/ ++#define RSTV0910_P2_PLROOT2 0xf2ac ++#define FSTV0910_P2_PLHAUTO_DISPLH 0xf2ac0040 ++#define FSTV0910_P2_PLHAUTO_FASTMODE 0xf2ac0020 ++#define FSTV0910_P2_PLHAUTO_ENABLE 0xf2ac0010 ++#define FSTV0910_P2_PLSCRAMB_MODE 0xf2ac000c ++#define FSTV0910_P2_PLSCRAMB_ROOT2 0xf2ac0003 ++ ++/*P2_PLROOT1*/ ++#define RSTV0910_P2_PLROOT1 0xf2ad ++#define FSTV0910_P2_PLSCRAMB_ROOT1 0xf2ad00ff ++ ++/*P2_PLROOT0*/ ++#define RSTV0910_P2_PLROOT0 0xf2ae ++#define FSTV0910_P2_PLSCRAMB_ROOT0 0xf2ae00ff ++ ++/*P2_MODCODLST7*/ ++#define RSTV0910_P2_MODCODLST7 0xf2b7 ++#define FSTV0910_P2_MODCOD_NNOSFILTER 0xf2b70080 ++#define FSTV0910_P2_MODCODLST_NOSTYPE 0xf2b70040 ++#define FSTV0910_P2_DIS_8PSK_9_10 0xf2b70030 ++#define FSTV0910_P2_DIS_8P_8_9 0xf2b7000f ++ ++/*P2_MODCODLST8*/ ++#define RSTV0910_P2_MODCODLST8 0xf2b8 ++#define FSTV0910_P2_DIS_8P_5_6 0xf2b800f0 ++#define FSTV0910_P2_DIS_8P_3_4 0xf2b8000f ++ ++/*P2_MODCODLST9*/ ++#define RSTV0910_P2_MODCODLST9 0xf2b9 ++#define FSTV0910_P2_DIS_8P_2_3 0xf2b900f0 ++#define FSTV0910_P2_DIS_8P_3_5 0xf2b9000f ++ ++/*P2_MODCODLSTA*/ ++#define RSTV0910_P2_MODCODLSTA 0xf2ba ++#define FSTV0910_P2_NOSFILTER_LIMITE 0xf2ba0080 ++#define FSTV0910_P2_NOSFILTER_MODE 0xf2ba0040 ++#define FSTV0910_P2_DIS_QPSK_9_10 0xf2ba0030 ++#define FSTV0910_P2_DIS_QP_8_9 0xf2ba000f ++ ++/*P2_MODCODLSTB*/ ++#define RSTV0910_P2_MODCODLSTB 0xf2bb ++#define FSTV0910_P2_DIS_QP_5_6 0xf2bb00f0 ++#define FSTV0910_P2_DIS_QP_4_5 0xf2bb000f ++ ++/*P2_MODCODLSTC*/ ++#define RSTV0910_P2_MODCODLSTC 0xf2bc ++#define FSTV0910_P2_DIS_QP_3_4 0xf2bc00f0 ++#define FSTV0910_P2_DIS_QP_2_3 0xf2bc000f ++ ++/*P2_MODCODLSTD*/ ++#define RSTV0910_P2_MODCODLSTD 0xf2bd ++#define FSTV0910_P2_DIS_QPSK_3_5 0xf2bd00f0 ++#define FSTV0910_P2_DIS_QPSK_1_2 0xf2bd000f ++ ++/*P2_GAUSSR0*/ ++#define RSTV0910_P2_GAUSSR0 0xf2c0 ++#define FSTV0910_P2_EN_CCIMODE 0xf2c00080 ++#define FSTV0910_P2_R0_GAUSSIEN 0xf2c0007f ++ ++/*P2_CCIR0*/ ++#define RSTV0910_P2_CCIR0 0xf2c1 ++#define FSTV0910_P2_CCIDETECT_PLHONLY 0xf2c10080 ++#define FSTV0910_P2_R0_CCI 0xf2c1007f ++ ++/*P2_CCIQUANT*/ ++#define RSTV0910_P2_CCIQUANT 0xf2c2 ++#define FSTV0910_P2_CCI_BETA 0xf2c200e0 ++#define FSTV0910_P2_CCI_QUANT 0xf2c2001f ++ ++/*P2_CCITHRES*/ ++#define RSTV0910_P2_CCITHRES 0xf2c3 ++#define FSTV0910_P2_CCI_THRESHOLD 0xf2c300ff ++ ++/*P2_CCIACC*/ ++#define RSTV0910_P2_CCIACC 0xf2c4 ++#define FSTV0910_P2_CCI_VALUE 0xf2c400ff ++ ++/*P2_DSTATUS4*/ ++#define RSTV0910_P2_DSTATUS4 0xf2c5 ++#define FSTV0910_P2_RAINFADE_DETECT 0xf2c50080 ++#define FSTV0910_P2_NOTHRES2_FAIL 0xf2c50040 ++#define FSTV0910_P2_NOTHRES1_FAIL 0xf2c50020 ++#define FSTV0910_P2_PILOT_FAILDETECT 0xf2c50010 ++#define FSTV0910_P2_HIER_DETECT 0xf2c50008 ++#define FSTV0910_P2_DMDPROG_ERROR 0xf2c50004 ++#define FSTV0910_P2_CSTENV_DETECT 0xf2c50002 ++#define FSTV0910_P2_DETECTION_TRIAX 0xf2c50001 ++ ++/*P2_DMDRESCFG*/ ++#define RSTV0910_P2_DMDRESCFG 0xf2c6 ++#define FSTV0910_P2_DMDRES_RESET 0xf2c60080 ++#define FSTV0910_P2_DMDRES_NOISESQR 0xf2c60010 ++#define FSTV0910_P2_DMDRES_STRALL 0xf2c60008 ++#define FSTV0910_P2_DMDRES_NEWONLY 0xf2c60004 ++#define FSTV0910_P2_DMDRES_NOSTORE 0xf2c60002 ++#define FSTV0910_P2_DMDRES_AGC2MEM 0xf2c60001 ++ ++/*P2_DMDRESADR*/ ++#define RSTV0910_P2_DMDRESADR 0xf2c7 ++#define FSTV0910_P2_SUSP_PREDCANAL 0xf2c70080 ++#define FSTV0910_P2_DMDRES_VALIDCFR 0xf2c70040 ++#define FSTV0910_P2_DMDRES_MEMFULL 0xf2c70030 ++#define FSTV0910_P2_DMDRES_RESNBR 0xf2c7000f ++ ++/*P2_DMDRESDATA7*/ ++#define RSTV0910_P2_DMDRESDATA7 0xf2c8 ++#define FSTV0910_P2_DMDRES_DATA7 0xf2c800ff ++ ++/*P2_DMDRESDATA6*/ ++#define RSTV0910_P2_DMDRESDATA6 0xf2c9 ++#define FSTV0910_P2_DMDRES_DATA6 0xf2c900ff ++ ++/*P2_DMDRESDATA5*/ ++#define RSTV0910_P2_DMDRESDATA5 0xf2ca ++#define FSTV0910_P2_DMDRES_DATA5 0xf2ca00ff ++ ++/*P2_DMDRESDATA4*/ ++#define RSTV0910_P2_DMDRESDATA4 0xf2cb ++#define FSTV0910_P2_DMDRES_DATA4 0xf2cb00ff ++ ++/*P2_DMDRESDATA3*/ ++#define RSTV0910_P2_DMDRESDATA3 0xf2cc ++#define FSTV0910_P2_DMDRES_DATA3 0xf2cc00ff ++ ++/*P2_DMDRESDATA2*/ ++#define RSTV0910_P2_DMDRESDATA2 0xf2cd ++#define FSTV0910_P2_DMDRES_DATA2 0xf2cd00ff ++ ++/*P2_DMDRESDATA1*/ ++#define RSTV0910_P2_DMDRESDATA1 0xf2ce ++#define FSTV0910_P2_DMDRES_DATA1 0xf2ce00ff ++ ++/*P2_DMDRESDATA0*/ ++#define RSTV0910_P2_DMDRESDATA0 0xf2cf ++#define FSTV0910_P2_DMDRES_DATA0 0xf2cf00ff ++ ++/*P2_FFEI1*/ ++#define RSTV0910_P2_FFEI1 0xf2d0 ++#define FSTV0910_P2_FFE_ACCI1 0xf2d001ff ++ ++/*P2_FFEQ1*/ ++#define RSTV0910_P2_FFEQ1 0xf2d1 ++#define FSTV0910_P2_FFE_ACCQ1 0xf2d101ff ++ ++/*P2_FFEI2*/ ++#define RSTV0910_P2_FFEI2 0xf2d2 ++#define FSTV0910_P2_FFE_ACCI2 0xf2d201ff ++ ++/*P2_FFEQ2*/ ++#define RSTV0910_P2_FFEQ2 0xf2d3 ++#define FSTV0910_P2_FFE_ACCQ2 0xf2d301ff ++ ++/*P2_FFEI3*/ ++#define RSTV0910_P2_FFEI3 0xf2d4 ++#define FSTV0910_P2_FFE_ACCI3 0xf2d401ff ++ ++/*P2_FFEQ3*/ ++#define RSTV0910_P2_FFEQ3 0xf2d5 ++#define FSTV0910_P2_FFE_ACCQ3 0xf2d501ff ++ ++/*P2_FFEI4*/ ++#define RSTV0910_P2_FFEI4 0xf2d6 ++#define FSTV0910_P2_FFE_ACCI4 0xf2d601ff ++ ++/*P2_FFEQ4*/ ++#define RSTV0910_P2_FFEQ4 0xf2d7 ++#define FSTV0910_P2_FFE_ACCQ4 0xf2d701ff ++ ++/*P2_FFECFG*/ ++#define RSTV0910_P2_FFECFG 0xf2d8 ++#define FSTV0910_P2_EQUALFFE_ON 0xf2d80040 ++#define FSTV0910_P2_EQUAL_USEDSYMB 0xf2d80030 ++#define FSTV0910_P2_MU_EQUALFFE 0xf2d80007 ++ ++/*P2_TNRCFG2*/ ++#define RSTV0910_P2_TNRCFG2 0xf2e1 ++#define FSTV0910_P2_TUN_IQSWAP 0xf2e10080 ++#define FSTV0910_P2_STB6110_STEP2MHZ 0xf2e10040 ++#define FSTV0910_P2_STB6120_DBLI2C 0xf2e10020 ++#define FSTV0910_P2_TUNER_WIDEBAND 0xf2e10010 ++#define FSTV0910_P2_TUNER_OBSPAGE 0xf2e10008 ++#define FSTV0910_P2_DIS_BWCALC 0xf2e10004 ++#define FSTV0910_P2_SHORT_WAITSTATES 0xf2e10002 ++#define FSTV0910_P2_DIS_2BWAGC1 0xf2e10001 ++ ++/*P2_SMAPCOEF7*/ ++#define RSTV0910_P2_SMAPCOEF7 0xf300 ++#define FSTV0910_P2_DIS_QSCALE 0xf3000080 ++#define FSTV0910_P2_SMAPCOEF_Q_LLR12 0xf300017f ++ ++/*P2_SMAPCOEF6*/ ++#define RSTV0910_P2_SMAPCOEF6 0xf301 ++#define FSTV0910_P2_DIS_AGC2SCALE 0xf3010080 ++#define FSTV0910_P2_DIS_16IQMULT 0xf3010040 ++#define FSTV0910_P2_OLD_16APSK47 0xf3010020 ++#define FSTV0910_P2_OLD_16APSK12 0xf3010010 ++#define FSTV0910_P2_DIS_NEWSCALE 0xf3010008 ++#define FSTV0910_P2_ADJ_8PSKLLR1 0xf3010004 ++#define FSTV0910_P2_OLD_8PSKLLR1 0xf3010002 ++#define FSTV0910_P2_DIS_AB8PSK 0xf3010001 ++ ++/*P2_SMAPCOEF5*/ ++#define RSTV0910_P2_SMAPCOEF5 0xf302 ++#define FSTV0910_P2_DIS_8SCALE 0xf3020080 ++#define FSTV0910_P2_SMAPCOEF_8P_LLR23 0xf302017f ++ ++/*P2_NOSTHRES1*/ ++#define RSTV0910_P2_NOSTHRES1 0xf309 ++#define FSTV0910_P2_NOS_THRESHOLD1 0xf30900ff ++ ++/*P2_NOSTHRES2*/ ++#define RSTV0910_P2_NOSTHRES2 0xf30a ++#define FSTV0910_P2_NOS_THRESHOLD2 0xf30a00ff ++ ++/*P2_NOSDIFF1*/ ++#define RSTV0910_P2_NOSDIFF1 0xf30b ++#define FSTV0910_P2_NOSTHRES1_DIFF 0xf30b00ff ++ ++/*P2_RAINFADE*/ ++#define RSTV0910_P2_RAINFADE 0xf30c ++#define FSTV0910_P2_NOSTHRES_DATAT 0xf30c0080 ++#define FSTV0910_P2_RAINFADE_CNLIMIT 0xf30c0070 ++#define FSTV0910_P2_RAINFADE_TIMEOUT 0xf30c0007 ++ ++/*P2_NOSRAMCFG*/ ++#define RSTV0910_P2_NOSRAMCFG 0xf30d ++#define FSTV0910_P2_NOSRAM_DVBS2DATA 0xf30d0080 ++#define FSTV0910_P2_NOSRAM_QUADRAT 0xf30d0040 ++#define FSTV0910_P2_NOSRAM_ACTIVATION 0xf30d0030 ++#define FSTV0910_P2_NOSRAM_CNRONLY 0xf30d0008 ++#define FSTV0910_P2_NOSRAM_LGNCNR1 0xf30d0007 ++ ++/*P2_NOSRAMPOS*/ ++#define RSTV0910_P2_NOSRAMPOS 0xf30e ++#define FSTV0910_P2_NOSRAM_LGNCNR0 0xf30e00f0 ++#define FSTV0910_P2_NOSRAM_VALIDE 0xf30e0004 ++#define FSTV0910_P2_NOSRAM_CNRVAL1 0xf30e0003 ++ ++/*P2_NOSRAMVAL*/ ++#define RSTV0910_P2_NOSRAMVAL 0xf30f ++#define FSTV0910_P2_NOSRAM_CNRVAL0 0xf30f00ff ++ ++/*P2_DMDPLHSTAT*/ ++#define RSTV0910_P2_DMDPLHSTAT 0xf320 ++#define FSTV0910_P2_PLH_STATISTIC 0xf32000ff ++ ++/*P2_LOCKTIME3*/ ++#define RSTV0910_P2_LOCKTIME3 0xf322 ++#define FSTV0910_P2_DEMOD_LOCKTIME3 0xf32200ff ++ ++/*P2_LOCKTIME2*/ ++#define RSTV0910_P2_LOCKTIME2 0xf323 ++#define FSTV0910_P2_DEMOD_LOCKTIME2 0xf32300ff ++ ++/*P2_LOCKTIME1*/ ++#define RSTV0910_P2_LOCKTIME1 0xf324 ++#define FSTV0910_P2_DEMOD_LOCKTIME1 0xf32400ff ++ ++/*P2_LOCKTIME0*/ ++#define RSTV0910_P2_LOCKTIME0 0xf325 ++#define FSTV0910_P2_DEMOD_LOCKTIME0 0xf32500ff ++ ++/*P2_VITSCALE*/ ++#define RSTV0910_P2_VITSCALE 0xf332 ++#define FSTV0910_P2_NVTH_NOSRANGE 0xf3320080 ++#define FSTV0910_P2_VERROR_MAXMODE 0xf3320040 ++#define FSTV0910_P2_KDIV_MODE 0xf3320030 ++#define FSTV0910_P2_NSLOWSN_LOCKED 0xf3320008 ++#define FSTV0910_P2_DELOCK_PRFLOSS 0xf3320004 ++#define FSTV0910_P2_DIS_RSFLOCK 0xf3320002 ++ ++/*P2_FECM*/ ++#define RSTV0910_P2_FECM 0xf333 ++#define FSTV0910_P2_DSS_DVB 0xf3330080 ++#define FSTV0910_P2_DEMOD_BYPASS 0xf3330040 ++#define FSTV0910_P2_CMP_SLOWMODE 0xf3330020 ++#define FSTV0910_P2_DSS_SRCH 0xf3330010 ++#define FSTV0910_P2_DIFF_MODEVIT 0xf3330004 ++#define FSTV0910_P2_SYNCVIT 0xf3330002 ++#define FSTV0910_P2_IQINV 0xf3330001 ++ ++/*P2_VTH12*/ ++#define RSTV0910_P2_VTH12 0xf334 ++#define FSTV0910_P2_VTH12 0xf33400ff ++ ++/*P2_VTH23*/ ++#define RSTV0910_P2_VTH23 0xf335 ++#define FSTV0910_P2_VTH23 0xf33500ff ++ ++/*P2_VTH34*/ ++#define RSTV0910_P2_VTH34 0xf336 ++#define FSTV0910_P2_VTH34 0xf33600ff ++ ++/*P2_VTH56*/ ++#define RSTV0910_P2_VTH56 0xf337 ++#define FSTV0910_P2_VTH56 0xf33700ff ++ ++/*P2_VTH67*/ ++#define RSTV0910_P2_VTH67 0xf338 ++#define FSTV0910_P2_VTH67 0xf33800ff ++ ++/*P2_VTH78*/ ++#define RSTV0910_P2_VTH78 0xf339 ++#define FSTV0910_P2_VTH78 0xf33900ff ++ ++/*P2_VITCURPUN*/ ++#define RSTV0910_P2_VITCURPUN 0xf33a ++#define FSTV0910_P2_CYCLESLIP_VIT 0xf33a0080 ++#define FSTV0910_P2_VIT_ROTA180 0xf33a0040 ++#define FSTV0910_P2_VIT_ROTA90 0xf33a0020 ++#define FSTV0910_P2_VIT_CURPUN 0xf33a001f ++ ++/*P2_VERROR*/ ++#define RSTV0910_P2_VERROR 0xf33b ++#define FSTV0910_P2_REGERR_VIT 0xf33b00ff ++ ++/*P2_PRVIT*/ ++#define RSTV0910_P2_PRVIT 0xf33c ++#define FSTV0910_P2_DIS_VTHLOCK 0xf33c0040 ++#define FSTV0910_P2_E7_8VIT 0xf33c0020 ++#define FSTV0910_P2_E6_7VIT 0xf33c0010 ++#define FSTV0910_P2_E5_6VIT 0xf33c0008 ++#define FSTV0910_P2_E3_4VIT 0xf33c0004 ++#define FSTV0910_P2_E2_3VIT 0xf33c0002 ++#define FSTV0910_P2_E1_2VIT 0xf33c0001 ++ ++/*P2_VAVSRVIT*/ ++#define RSTV0910_P2_VAVSRVIT 0xf33d ++#define FSTV0910_P2_AMVIT 0xf33d0080 ++#define FSTV0910_P2_FROZENVIT 0xf33d0040 ++#define FSTV0910_P2_SNVIT 0xf33d0030 ++#define FSTV0910_P2_TOVVIT 0xf33d000c ++#define FSTV0910_P2_HYPVIT 0xf33d0003 ++ ++/*P2_VSTATUSVIT*/ ++#define RSTV0910_P2_VSTATUSVIT 0xf33e ++#define FSTV0910_P2_VITERBI_ON 0xf33e0080 ++#define FSTV0910_P2_END_LOOPVIT 0xf33e0040 ++#define FSTV0910_P2_VITERBI_DEPRF 0xf33e0020 ++#define FSTV0910_P2_PRFVIT 0xf33e0010 ++#define FSTV0910_P2_LOCKEDVIT 0xf33e0008 ++#define FSTV0910_P2_VITERBI_DELOCK 0xf33e0004 ++#define FSTV0910_P2_VIT_DEMODSEL 0xf33e0002 ++#define FSTV0910_P2_VITERBI_COMPOUT 0xf33e0001 ++ ++/*P2_VTHINUSE*/ ++#define RSTV0910_P2_VTHINUSE 0xf33f ++#define FSTV0910_P2_VIT_INUSE 0xf33f00ff ++ ++/*P2_KDIV12*/ ++#define RSTV0910_P2_KDIV12 0xf340 ++#define FSTV0910_P2_KDIV12_MANUAL 0xf3400080 ++#define FSTV0910_P2_K_DIVIDER_12 0xf340007f ++ ++/*P2_KDIV23*/ ++#define RSTV0910_P2_KDIV23 0xf341 ++#define FSTV0910_P2_KDIV23_MANUAL 0xf3410080 ++#define FSTV0910_P2_K_DIVIDER_23 0xf341007f ++ ++/*P2_KDIV34*/ ++#define RSTV0910_P2_KDIV34 0xf342 ++#define FSTV0910_P2_KDIV34_MANUAL 0xf3420080 ++#define FSTV0910_P2_K_DIVIDER_34 0xf342007f ++ ++/*P2_KDIV56*/ ++#define RSTV0910_P2_KDIV56 0xf343 ++#define FSTV0910_P2_KDIV56_MANUAL 0xf3430080 ++#define FSTV0910_P2_K_DIVIDER_56 0xf343007f ++ ++/*P2_KDIV67*/ ++#define RSTV0910_P2_KDIV67 0xf344 ++#define FSTV0910_P2_KDIV67_MANUAL 0xf3440080 ++#define FSTV0910_P2_K_DIVIDER_67 0xf344007f ++ ++/*P2_KDIV78*/ ++#define RSTV0910_P2_KDIV78 0xf345 ++#define FSTV0910_P2_KDIV78_MANUAL 0xf3450080 ++#define FSTV0910_P2_K_DIVIDER_78 0xf345007f ++ ++/*P2_PDELCTRL0*/ ++#define RSTV0910_P2_PDELCTRL0 0xf34f ++#define FSTV0910_P2_ISIOBS_MODE 0xf34f0030 ++#define FSTV0910_P2_PDELDIS_BITWISE 0xf34f0004 ++ ++/*P2_PDELCTRL1*/ ++#define RSTV0910_P2_PDELCTRL1 0xf350 ++#define FSTV0910_P2_INV_MISMASK 0xf3500080 ++#define FSTV0910_P2_FORCE_ACCEPTED 0xf3500040 ++#define FSTV0910_P2_FILTER_EN 0xf3500020 ++#define FSTV0910_P2_FORCE_PKTDELINUSE 0xf3500010 ++#define FSTV0910_P2_HYSTEN 0xf3500008 ++#define FSTV0910_P2_HYSTSWRST 0xf3500004 ++#define FSTV0910_P2_EN_MIS00 0xf3500002 ++#define FSTV0910_P2_ALGOSWRST 0xf3500001 ++ ++/*P2_PDELCTRL2*/ ++#define RSTV0910_P2_PDELCTRL2 0xf351 ++#define FSTV0910_P2_FORCE_CONTINUOUS 0xf3510080 ++#define FSTV0910_P2_RESET_UPKO_COUNT 0xf3510040 ++#define FSTV0910_P2_USER_PKTDELIN_NB 0xf3510020 ++#define FSTV0910_P2_DATA_UNBBSCRAMBLED 0xf3510008 ++#define FSTV0910_P2_FORCE_LONGPKT 0xf3510004 ++#define FSTV0910_P2_FRAME_MODE 0xf3510002 ++ ++/*P2_HYSTTHRESH*/ ++#define RSTV0910_P2_HYSTTHRESH 0xf354 ++#define FSTV0910_P2_DELIN_LOCKTHRES 0xf35400f0 ++#define FSTV0910_P2_DELIN_UNLOCKTHRES 0xf354000f ++ ++/*P2_ISIENTRY*/ ++#define RSTV0910_P2_ISIENTRY 0xf35e ++#define FSTV0910_P2_ISI_ENTRY 0xf35e00ff ++ ++/*P2_ISIBITENA*/ ++#define RSTV0910_P2_ISIBITENA 0xf35f ++#define FSTV0910_P2_ISI_BIT_EN 0xf35f00ff ++ ++/*P2_MATSTR1*/ ++#define RSTV0910_P2_MATSTR1 0xf360 ++#define FSTV0910_P2_MATYPE_CURRENT1 0xf36000ff ++ ++/*P2_MATSTR0*/ ++#define RSTV0910_P2_MATSTR0 0xf361 ++#define FSTV0910_P2_MATYPE_CURRENT0 0xf36100ff ++ ++/*P2_UPLSTR1*/ ++#define RSTV0910_P2_UPLSTR1 0xf362 ++#define FSTV0910_P2_UPL_CURRENT1 0xf36200ff ++ ++/*P2_UPLSTR0*/ ++#define RSTV0910_P2_UPLSTR0 0xf363 ++#define FSTV0910_P2_UPL_CURRENT0 0xf36300ff ++ ++/*P2_DFLSTR1*/ ++#define RSTV0910_P2_DFLSTR1 0xf364 ++#define FSTV0910_P2_DFL_CURRENT1 0xf36400ff ++ ++/*P2_DFLSTR0*/ ++#define RSTV0910_P2_DFLSTR0 0xf365 ++#define FSTV0910_P2_DFL_CURRENT0 0xf36500ff ++ ++/*P2_SYNCSTR*/ ++#define RSTV0910_P2_SYNCSTR 0xf366 ++#define FSTV0910_P2_SYNC_CURRENT 0xf36600ff ++ ++/*P2_SYNCDSTR1*/ ++#define RSTV0910_P2_SYNCDSTR1 0xf367 ++#define FSTV0910_P2_SYNCD_CURRENT1 0xf36700ff ++ ++/*P2_SYNCDSTR0*/ ++#define RSTV0910_P2_SYNCDSTR0 0xf368 ++#define FSTV0910_P2_SYNCD_CURRENT0 0xf36800ff ++ ++/*P2_PDELSTATUS1*/ ++#define RSTV0910_P2_PDELSTATUS1 0xf369 ++#define FSTV0910_P2_PKTDELIN_DELOCK 0xf3690080 ++#define FSTV0910_P2_SYNCDUPDFL_BADDFL 0xf3690040 ++#define FSTV0910_P2_CONTINUOUS_STREAM 0xf3690020 ++#define FSTV0910_P2_UNACCEPTED_STREAM 0xf3690010 ++#define FSTV0910_P2_BCH_ERROR_FLAG 0xf3690008 ++#define FSTV0910_P2_BBHCRCKO 0xf3690004 ++#define FSTV0910_P2_PKTDELIN_LOCK 0xf3690002 ++#define FSTV0910_P2_FIRST_LOCK 0xf3690001 ++ ++/*P2_PDELSTATUS2*/ ++#define RSTV0910_P2_PDELSTATUS2 0xf36a ++#define FSTV0910_P2_PKTDEL_DEMODSEL 0xf36a0080 ++#define FSTV0910_P2_FRAME_MODCOD 0xf36a007c ++#define FSTV0910_P2_FRAME_TYPE 0xf36a0003 ++ ++/*P2_BBFCRCKO1*/ ++#define RSTV0910_P2_BBFCRCKO1 0xf36b ++#define FSTV0910_P2_BBHCRC_KOCNT1 0xf36b00ff ++ ++/*P2_BBFCRCKO0*/ ++#define RSTV0910_P2_BBFCRCKO0 0xf36c ++#define FSTV0910_P2_BBHCRC_KOCNT0 0xf36c00ff ++ ++/*P2_UPCRCKO1*/ ++#define RSTV0910_P2_UPCRCKO1 0xf36d ++#define FSTV0910_P2_PKTCRC_KOCNT1 0xf36d00ff ++ ++/*P2_UPCRCKO0*/ ++#define RSTV0910_P2_UPCRCKO0 0xf36e ++#define FSTV0910_P2_PKTCRC_KOCNT0 0xf36e00ff ++ ++/*P2_PDELCTRL3*/ ++#define RSTV0910_P2_PDELCTRL3 0xf36f ++#define FSTV0910_P2_PKTDEL_CONTFAIL 0xf36f0080 ++#define FSTV0910_P2_PKTDEL_ENLONGPKT 0xf36f0040 ++#define FSTV0910_P2_NOFIFO_BCHERR 0xf36f0020 ++#define FSTV0910_P2_PKTDELIN_DELACMERR 0xf36f0010 ++#define FSTV0910_P2_SATURATE_BBPKTKO 0xf36f0004 ++#define FSTV0910_P2_PKTDEL_BCHERRCONT 0xf36f0002 ++#define FSTV0910_P2_ETHERNET_DISFCS 0xf36f0001 ++ ++/*P2_TSSTATEM*/ ++#define RSTV0910_P2_TSSTATEM 0xf370 ++#define FSTV0910_P2_TSDIL_ON 0xf3700080 ++#define FSTV0910_P2_TSSKIPRS_ON 0xf3700040 ++#define FSTV0910_P2_TSRS_ON 0xf3700020 ++#define FSTV0910_P2_TSDESCRAMB_ON 0xf3700010 ++#define FSTV0910_P2_TSFRAME_MODE 0xf3700008 ++#define FSTV0910_P2_TS_DISABLE 0xf3700004 ++#define FSTV0910_P2_TSACM_MODE 0xf3700002 ++#define FSTV0910_P2_TSOUT_NOSYNC 0xf3700001 ++ ++/*P2_TSCFGH*/ ++#define RSTV0910_P2_TSCFGH 0xf372 ++#define FSTV0910_P2_TSFIFO_DVBCI 0xf3720080 ++#define FSTV0910_P2_TSFIFO_SERIAL 0xf3720040 ++#define FSTV0910_P2_TSFIFO_TEIUPDATE 0xf3720020 ++#define FSTV0910_P2_TSFIFO_DUTY50 0xf3720010 ++#define FSTV0910_P2_TSFIFO_HSGNLOUT 0xf3720008 ++#define FSTV0910_P2_TSFIFO_ERRMODE 0xf3720006 ++#define FSTV0910_P2_RST_HWARE 0xf3720001 ++ ++/*P2_TSCFGM*/ ++#define RSTV0910_P2_TSCFGM 0xf373 ++#define FSTV0910_P2_TSFIFO_MANSPEED 0xf37300c0 ++#define FSTV0910_P2_TSFIFO_PERMDATA 0xf3730020 ++#define FSTV0910_P2_TSFIFO_NONEWSGNL 0xf3730010 ++#define FSTV0910_P2_NPD_SPECDVBS2 0xf3730004 ++#define FSTV0910_P2_TSFIFO_DPUNACTIVE 0xf3730002 ++#define FSTV0910_P2_TSFIFO_INVDATA 0xf3730001 ++ ++/*P2_TSCFGL*/ ++#define RSTV0910_P2_TSCFGL 0xf374 ++#define FSTV0910_P2_TSFIFO_BCLKDEL1CK 0xf37400c0 ++#define FSTV0910_P2_BCHERROR_MODE 0xf3740030 ++#define FSTV0910_P2_TSFIFO_NSGNL2DATA 0xf3740008 ++#define FSTV0910_P2_TSFIFO_EMBINDVB 0xf3740004 ++#define FSTV0910_P2_TSFIFO_BITSPEED 0xf3740003 ++ ++/*P2_TSINSDELH*/ ++#define RSTV0910_P2_TSINSDELH 0xf376 ++#define FSTV0910_P2_TSDEL_SYNCBYTE 0xf3760080 ++#define FSTV0910_P2_TSDEL_XXHEADER 0xf3760040 ++#define FSTV0910_P2_TSDEL_BBHEADER 0xf3760020 ++#define FSTV0910_P2_TSDEL_DATAFIELD 0xf3760010 ++#define FSTV0910_P2_TSINSDEL_ISCR 0xf3760008 ++#define FSTV0910_P2_TSINSDEL_NPD 0xf3760004 ++#define FSTV0910_P2_TSINSDEL_RSPARITY 0xf3760002 ++#define FSTV0910_P2_TSINSDEL_CRC8 0xf3760001 ++ ++/*P2_TSDIVN*/ ++#define RSTV0910_P2_TSDIVN 0xf379 ++#define FSTV0910_P2_TSFIFO_SPEEDMODE 0xf37900c0 ++#define FSTV0910_P2_BYTE_OVERSAMPLING 0xf3790038 ++#define FSTV0910_P2_TSFIFO_RISEOK 0xf3790007 ++ ++/*P2_TSCFG4*/ ++#define RSTV0910_P2_TSCFG4 0xf37a ++#define FSTV0910_P2_TSFIFO_TSSPEEDMODE 0xf37a00c0 ++#define FSTV0910_P2_TSFIFO_HIERSEL 0xf37a0020 ++#define FSTV0910_P2_TSFIFO_SPECTOKEN 0xf37a0010 ++#define FSTV0910_P2_TSFIFO_MAXMODE 0xf37a0008 ++#define FSTV0910_P2_TSFIFO_FRFORCEPKT 0xf37a0004 ++#define FSTV0910_P2_EXT_FECSPYIN 0xf37a0002 ++#define FSTV0910_P2_TSFIFO_DELSPEEDUP 0xf37a0001 ++ ++/*P2_TSSPEED*/ ++#define RSTV0910_P2_TSSPEED 0xf380 ++#define FSTV0910_P2_TSFIFO_OUTSPEED 0xf38000ff ++ ++/*P2_TSSTATUS*/ ++#define RSTV0910_P2_TSSTATUS 0xf381 ++#define FSTV0910_P2_TSFIFO_LINEOK 0xf3810080 ++#define FSTV0910_P2_TSFIFO_ERROR 0xf3810040 ++#define FSTV0910_P2_TSFIFO_DATA7 0xf3810020 ++#define FSTV0910_P2_TSFIFO_NOSYNC 0xf3810010 ++#define FSTV0910_P2_ISCR_INITIALIZED 0xf3810008 ++#define FSTV0910_P2_TSREGUL_ERROR 0xf3810004 ++#define FSTV0910_P2_SOFFIFO_UNREGUL 0xf3810002 ++#define FSTV0910_P2_DIL_READY 0xf3810001 ++ ++/*P2_TSSTATUS2*/ ++#define RSTV0910_P2_TSSTATUS2 0xf382 ++#define FSTV0910_P2_TSFIFO_DEMODSEL 0xf3820080 ++#define FSTV0910_P2_TSFIFOSPEED_STORE 0xf3820040 ++#define FSTV0910_P2_DILXX_RESET 0xf3820020 ++#define FSTV0910_P2_TSSPEED_IMPOSSIBLE 0xf3820010 ++#define FSTV0910_P2_TSFIFO_LINENOK 0xf3820008 ++#define FSTV0910_P2_TSFIFO_MUXSTREAM 0xf3820004 ++#define FSTV0910_P2_SCRAMBDETECT 0xf3820002 ++#define FSTV0910_P2_ULDTV67_FALSELOCK 0xf3820001 ++ ++/*P2_TSBITRATE1*/ ++#define RSTV0910_P2_TSBITRATE1 0xf383 ++#define FSTV0910_P2_TSFIFO_BITRATE1 0xf38300ff ++ ++/*P2_TSBITRATE0*/ ++#define RSTV0910_P2_TSBITRATE0 0xf384 ++#define FSTV0910_P2_TSFIFO_BITRATE0 0xf38400ff ++ ++/*P2_ERRCTRL1*/ ++#define RSTV0910_P2_ERRCTRL1 0xf398 ++#define FSTV0910_P2_ERR_SOURCE1 0xf39800f0 ++#define FSTV0910_P2_NUM_EVENT1 0xf3980007 ++ ++/*P2_ERRCNT12*/ ++#define RSTV0910_P2_ERRCNT12 0xf399 ++#define FSTV0910_P2_ERRCNT1_OLDVALUE 0xf3990080 ++#define FSTV0910_P2_ERR_CNT12 0xf399007f ++ ++/*P2_ERRCNT11*/ ++#define RSTV0910_P2_ERRCNT11 0xf39a ++#define FSTV0910_P2_ERR_CNT11 0xf39a00ff ++ ++/*P2_ERRCNT10*/ ++#define RSTV0910_P2_ERRCNT10 0xf39b ++#define FSTV0910_P2_ERR_CNT10 0xf39b00ff ++ ++/*P2_ERRCTRL2*/ ++#define RSTV0910_P2_ERRCTRL2 0xf39c ++#define FSTV0910_P2_ERR_SOURCE2 0xf39c00f0 ++#define FSTV0910_P2_NUM_EVENT2 0xf39c0007 ++ ++/*P2_ERRCNT22*/ ++#define RSTV0910_P2_ERRCNT22 0xf39d ++#define FSTV0910_P2_ERRCNT2_OLDVALUE 0xf39d0080 ++#define FSTV0910_P2_ERR_CNT22 0xf39d007f ++ ++/*P2_ERRCNT21*/ ++#define RSTV0910_P2_ERRCNT21 0xf39e ++#define FSTV0910_P2_ERR_CNT21 0xf39e00ff ++ ++/*P2_ERRCNT20*/ ++#define RSTV0910_P2_ERRCNT20 0xf39f ++#define FSTV0910_P2_ERR_CNT20 0xf39f00ff ++ ++/*P2_FECSPY*/ ++#define RSTV0910_P2_FECSPY 0xf3a0 ++#define FSTV0910_P2_SPY_ENABLE 0xf3a00080 ++#define FSTV0910_P2_NO_SYNCBYTE 0xf3a00040 ++#define FSTV0910_P2_SERIAL_MODE 0xf3a00020 ++#define FSTV0910_P2_UNUSUAL_PACKET 0xf3a00010 ++#define FSTV0910_P2_BERMETER_DATAMODE 0xf3a0000c ++#define FSTV0910_P2_BERMETER_LMODE 0xf3a00002 ++#define FSTV0910_P2_BERMETER_RESET 0xf3a00001 ++ ++/*P2_FSPYCFG*/ ++#define RSTV0910_P2_FSPYCFG 0xf3a1 ++#define FSTV0910_P2_FECSPY_INPUT 0xf3a100c0 ++#define FSTV0910_P2_RST_ON_ERROR 0xf3a10020 ++#define FSTV0910_P2_ONE_SHOT 0xf3a10010 ++#define FSTV0910_P2_I2C_MODE 0xf3a1000c ++#define FSTV0910_P2_SPY_HYSTERESIS 0xf3a10003 ++ ++/*P2_FSPYDATA*/ ++#define RSTV0910_P2_FSPYDATA 0xf3a2 ++#define FSTV0910_P2_SPY_STUFFING 0xf3a20080 ++#define FSTV0910_P2_NOERROR_PKTJITTER 0xf3a20040 ++#define FSTV0910_P2_SPY_CNULLPKT 0xf3a20020 ++#define FSTV0910_P2_SPY_OUTDATA_MODE 0xf3a2001f ++ ++/*P2_FSPYOUT*/ ++#define RSTV0910_P2_FSPYOUT 0xf3a3 ++#define FSTV0910_P2_FSPY_DIRECT 0xf3a30080 ++#define FSTV0910_P2_SPY_OUTDATA_BUS 0xf3a30038 ++#define FSTV0910_P2_STUFF_MODE 0xf3a30007 ++ ++/*P2_FSTATUS*/ ++#define RSTV0910_P2_FSTATUS 0xf3a4 ++#define FSTV0910_P2_SPY_ENDSIM 0xf3a40080 ++#define FSTV0910_P2_VALID_SIM 0xf3a40040 ++#define FSTV0910_P2_FOUND_SIGNAL 0xf3a40020 ++#define FSTV0910_P2_DSS_SYNCBYTE 0xf3a40010 ++#define FSTV0910_P2_RESULT_STATE 0xf3a4000f ++ ++/*P2_FBERCPT4*/ ++#define RSTV0910_P2_FBERCPT4 0xf3a8 ++#define FSTV0910_P2_FBERMETER_CPT4 0xf3a800ff ++ ++/*P2_FBERCPT3*/ ++#define RSTV0910_P2_FBERCPT3 0xf3a9 ++#define FSTV0910_P2_FBERMETER_CPT3 0xf3a900ff ++ ++/*P2_FBERCPT2*/ ++#define RSTV0910_P2_FBERCPT2 0xf3aa ++#define FSTV0910_P2_FBERMETER_CPT2 0xf3aa00ff ++ ++/*P2_FBERCPT1*/ ++#define RSTV0910_P2_FBERCPT1 0xf3ab ++#define FSTV0910_P2_FBERMETER_CPT1 0xf3ab00ff ++ ++/*P2_FBERCPT0*/ ++#define RSTV0910_P2_FBERCPT0 0xf3ac ++#define FSTV0910_P2_FBERMETER_CPT0 0xf3ac00ff ++ ++/*P2_FBERERR2*/ ++#define RSTV0910_P2_FBERERR2 0xf3ad ++#define FSTV0910_P2_FBERMETER_ERR2 0xf3ad00ff ++ ++/*P2_FBERERR1*/ ++#define RSTV0910_P2_FBERERR1 0xf3ae ++#define FSTV0910_P2_FBERMETER_ERR1 0xf3ae00ff ++ ++/*P2_FBERERR0*/ ++#define RSTV0910_P2_FBERERR0 0xf3af ++#define FSTV0910_P2_FBERMETER_ERR0 0xf3af00ff ++ ++/*P2_FSPYBER*/ ++#define RSTV0910_P2_FSPYBER 0xf3b2 ++#define FSTV0910_P2_FSPYOBS_XORREAD 0xf3b20040 ++#define FSTV0910_P2_FSPYBER_OBSMODE 0xf3b20020 ++#define FSTV0910_P2_FSPYBER_SYNCBYTE 0xf3b20010 ++#define FSTV0910_P2_FSPYBER_UNSYNC 0xf3b20008 ++#define FSTV0910_P2_FSPYBER_CTIME 0xf3b20007 ++ ++/*P2_SFERROR*/ ++#define RSTV0910_P2_SFERROR 0xf3c1 ++#define FSTV0910_P2_SFEC_REGERR_VIT 0xf3c100ff ++ ++/*P2_SFECSTATUS*/ ++#define RSTV0910_P2_SFECSTATUS 0xf3c3 ++#define FSTV0910_P2_SFEC_ON 0xf3c30080 ++#define FSTV0910_P2_SFEC_OFF 0xf3c30040 ++#define FSTV0910_P2_LOCKEDSFEC 0xf3c30008 ++#define FSTV0910_P2_SFEC_DELOCK 0xf3c30004 ++#define FSTV0910_P2_SFEC_DEMODSEL 0xf3c30002 ++#define FSTV0910_P2_SFEC_OVFON 0xf3c30001 ++ ++/*P2_SFKDIV12*/ ++#define RSTV0910_P2_SFKDIV12 0xf3c4 ++#define FSTV0910_P2_SFECKDIV12_MAN 0xf3c40080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_12 0xf3c4007f ++ ++/*P2_SFKDIV23*/ ++#define RSTV0910_P2_SFKDIV23 0xf3c5 ++#define FSTV0910_P2_SFECKDIV23_MAN 0xf3c50080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_23 0xf3c5007f ++ ++/*P2_SFKDIV34*/ ++#define RSTV0910_P2_SFKDIV34 0xf3c6 ++#define FSTV0910_P2_SFECKDIV34_MAN 0xf3c60080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_34 0xf3c6007f ++ ++/*P2_SFKDIV56*/ ++#define RSTV0910_P2_SFKDIV56 0xf3c7 ++#define FSTV0910_P2_SFECKDIV56_MAN 0xf3c70080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_56 0xf3c7007f ++ ++/*P2_SFKDIV67*/ ++#define RSTV0910_P2_SFKDIV67 0xf3c8 ++#define FSTV0910_P2_SFECKDIV67_MAN 0xf3c80080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_67 0xf3c8007f ++ ++/*P2_SFKDIV78*/ ++#define RSTV0910_P2_SFKDIV78 0xf3c9 ++#define FSTV0910_P2_SFECKDIV78_MAN 0xf3c90080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_78 0xf3c9007f ++ ++/*P2_SFSTATUS*/ ++#define RSTV0910_P2_SFSTATUS 0xf3cc ++#define FSTV0910_P2_SFEC_LINEOK 0xf3cc0080 ++#define FSTV0910_P2_SFEC_ERROR 0xf3cc0040 ++#define FSTV0910_P2_SFEC_DATA7 0xf3cc0020 ++#define FSTV0910_P2_SFEC_PKTDNBRFAIL 0xf3cc0010 ++#define FSTV0910_P2_TSSFEC_DEMODSEL 0xf3cc0008 ++#define FSTV0910_P2_SFEC_NOSYNC 0xf3cc0004 ++#define FSTV0910_P2_SFEC_UNREGULA 0xf3cc0002 ++#define FSTV0910_P2_SFEC_READY 0xf3cc0001 ++ ++/*P2_SFDLYSET2*/ ++#define RSTV0910_P2_SFDLYSET2 0xf3d0 ++#define FSTV0910_P2_SFEC_OFFSET 0xf3d000c0 ++#define FSTV0910_P2_RST_SFEC 0xf3d00008 ++#define FSTV0910_P2_DILDLINE_ERROR 0xf3d00004 ++#define FSTV0910_P2_SFEC_DISABLE 0xf3d00002 ++#define FSTV0910_P2_SFEC_UNREGUL 0xf3d00001 ++ ++/*P2_SFERRCTRL*/ ++#define RSTV0910_P2_SFERRCTRL 0xf3d8 ++#define FSTV0910_P2_SFEC_ERR_SOURCE 0xf3d800f0 ++#define FSTV0910_P2_SFEC_NUM_EVENT 0xf3d80007 ++ ++/*P2_SFERRCNT2*/ ++#define RSTV0910_P2_SFERRCNT2 0xf3d9 ++#define FSTV0910_P2_SFERRC_OLDVALUE 0xf3d90080 ++#define FSTV0910_P2_SFEC_ERR_CNT2 0xf3d9007f ++ ++/*P2_SFERRCNT1*/ ++#define RSTV0910_P2_SFERRCNT1 0xf3da ++#define FSTV0910_P2_SFEC_ERR_CNT1 0xf3da00ff ++ ++/*P2_SFERRCNT0*/ ++#define RSTV0910_P2_SFERRCNT0 0xf3db ++#define FSTV0910_P2_SFEC_ERR_CNT0 0xf3db00ff ++ ++/*P1_IQCONST*/ ++#define RSTV0910_P1_IQCONST 0xf400 ++#define FSTV0910_P1_CONSTEL_SELECT 0xf4000060 ++#define FSTV0910_P1_IQSYMB_SEL 0xf400001f ++ ++/*P1_NOSCFG*/ ++#define RSTV0910_P1_NOSCFG 0xf401 ++#define FSTV0910_P1_DIS_ACMRATIO 0xf4010080 ++#define FSTV0910_P1_NOSIN_EGALSEL 0xf4010040 ++#define FSTV0910_P1_DUMMYPL_NOSDATA 0xf4010020 ++#define FSTV0910_P1_NOSPLH_BETA 0xf4010018 ++#define FSTV0910_P1_NOSDATA_BETA 0xf4010007 ++ ++/*P1_ISYMB*/ ++#define RSTV0910_P1_ISYMB 0xf402 ++#define FSTV0910_P1_I_SYMBOL 0xf40201ff ++ ++/*P1_QSYMB*/ ++#define RSTV0910_P1_QSYMB 0xf403 ++#define FSTV0910_P1_Q_SYMBOL 0xf40301ff ++ ++/*P1_AGC1CFG*/ ++#define RSTV0910_P1_AGC1CFG 0xf404 ++#define FSTV0910_P1_DC_FROZEN 0xf4040080 ++#define FSTV0910_P1_DC_CORRECT 0xf4040040 ++#define FSTV0910_P1_AMM_FROZEN 0xf4040020 ++#define FSTV0910_P1_AMM_CORRECT 0xf4040010 ++#define FSTV0910_P1_QUAD_FROZEN 0xf4040008 ++#define FSTV0910_P1_QUAD_CORRECT 0xf4040004 ++#define FSTV0910_P1_DCCOMP_SLOW 0xf4040002 ++#define FSTV0910_P1_IQMISM_SLOW 0xf4040001 ++ ++/*P1_AGC1CN*/ ++#define RSTV0910_P1_AGC1CN 0xf406 ++#define FSTV0910_P1_AGC1_LOCKED 0xf4060080 ++#define FSTV0910_P1_AGC1_OVERFLOW 0xf4060040 ++#define FSTV0910_P1_AGC1_NOSLOWLK 0xf4060020 ++#define FSTV0910_P1_AGC1_MINPOWER 0xf4060010 ++#define FSTV0910_P1_AGCOUT_FAST 0xf4060008 ++#define FSTV0910_P1_AGCIQ_BETA 0xf4060007 ++ ++/*P1_AGC1REF*/ ++#define RSTV0910_P1_AGC1REF 0xf407 ++#define FSTV0910_P1_AGCIQ_REF 0xf40700ff ++ ++/*P1_IDCCOMP*/ ++#define RSTV0910_P1_IDCCOMP 0xf408 ++#define FSTV0910_P1_IAVERAGE_ADJ 0xf40801ff ++ ++/*P1_QDCCOMP*/ ++#define RSTV0910_P1_QDCCOMP 0xf409 ++#define FSTV0910_P1_QAVERAGE_ADJ 0xf40901ff ++ ++/*P1_POWERI*/ ++#define RSTV0910_P1_POWERI 0xf40a ++#define FSTV0910_P1_POWER_I 0xf40a00ff ++ ++/*P1_POWERQ*/ ++#define RSTV0910_P1_POWERQ 0xf40b ++#define FSTV0910_P1_POWER_Q 0xf40b00ff ++ ++/*P1_AGC1AMM*/ ++#define RSTV0910_P1_AGC1AMM 0xf40c ++#define FSTV0910_P1_AMM_VALUE 0xf40c00ff ++ ++/*P1_AGC1QUAD*/ ++#define RSTV0910_P1_AGC1QUAD 0xf40d ++#define FSTV0910_P1_QUAD_VALUE 0xf40d01ff ++ ++/*P1_AGCIQIN1*/ ++#define RSTV0910_P1_AGCIQIN1 0xf40e ++#define FSTV0910_P1_AGCIQ_VALUE1 0xf40e00ff ++ ++/*P1_AGCIQIN0*/ ++#define RSTV0910_P1_AGCIQIN0 0xf40f ++#define FSTV0910_P1_AGCIQ_VALUE0 0xf40f00ff ++ ++/*P1_DEMOD*/ ++#define RSTV0910_P1_DEMOD 0xf410 ++#define FSTV0910_P1_MANUALS2_ROLLOFF 0xf4100080 ++#define FSTV0910_P1_SPECINV_CONTROL 0xf4100030 ++#define FSTV0910_P1_MANUALSX_ROLLOFF 0xf4100004 ++#define FSTV0910_P1_ROLLOFF_CONTROL 0xf4100003 ++ ++/*P1_DMDMODCOD*/ ++#define RSTV0910_P1_DMDMODCOD 0xf411 ++#define FSTV0910_P1_MANUAL_MODCOD 0xf4110080 ++#define FSTV0910_P1_DEMOD_MODCOD 0xf411007c ++#define FSTV0910_P1_DEMOD_TYPE 0xf4110003 ++ ++/*P1_DSTATUS*/ ++#define RSTV0910_P1_DSTATUS 0xf412 ++#define FSTV0910_P1_CAR_LOCK 0xf4120080 ++#define FSTV0910_P1_TMGLOCK_QUALITY 0xf4120060 ++#define FSTV0910_P1_SDVBS1_ENABLE 0xf4120010 ++#define FSTV0910_P1_LOCK_DEFINITIF 0xf4120008 ++#define FSTV0910_P1_TIMING_IS_LOCKED 0xf4120004 ++#define FSTV0910_P1_DEMOD_SYSCFG 0xf4120002 ++#define FSTV0910_P1_OVADC_DETECT 0xf4120001 ++ ++/*P1_DSTATUS2*/ ++#define RSTV0910_P1_DSTATUS2 0xf413 ++#define FSTV0910_P1_DEMOD_DELOCK 0xf4130080 ++#define FSTV0910_P1_DEMOD_TIMEOUT 0xf4130040 ++#define FSTV0910_P1_MODCODRQ_SYNCTAG 0xf4130020 ++#define FSTV0910_P1_POLYPH_SATEVENT 0xf4130010 ++#define FSTV0910_P1_AGC1_NOSIGNALACK 0xf4130008 ++#define FSTV0910_P1_AGC2_OVERFLOW 0xf4130004 ++#define FSTV0910_P1_CFR_OVERFLOW 0xf4130002 ++#define FSTV0910_P1_GAMMA_OVERUNDER 0xf4130001 ++ ++/*P1_DMDCFGMD*/ ++#define RSTV0910_P1_DMDCFGMD 0xf414 ++#define FSTV0910_P1_DVBS2_ENABLE 0xf4140080 ++#define FSTV0910_P1_DVBS1_ENABLE 0xf4140040 ++#define FSTV0910_P1_SCAN_ENABLE 0xf4140010 ++#define FSTV0910_P1_CFR_AUTOSCAN 0xf4140008 ++#define FSTV0910_P1_NOFORCE_RELOCK 0xf4140004 ++#define FSTV0910_P1_TUN_RNG 0xf4140003 ++ ++/*P1_DMDCFG2*/ ++#define RSTV0910_P1_DMDCFG2 0xf415 ++#define FSTV0910_P1_AGC1_WAITLOCK 0xf4150080 ++#define FSTV0910_P1_S1S2_SEQUENTIAL 0xf4150040 ++#define FSTV0910_P1_BLINDPEA_MODE 0xf4150020 ++#define FSTV0910_P1_INFINITE_RELOCK 0xf4150010 ++#define FSTV0910_P1_BWOFFSET_COLDWARM 0xf4150008 ++#define FSTV0910_P1_TMGLOCK_NSCANSTOP 0xf4150004 ++#define FSTV0910_P1_COARSE_LK3MODE 0xf4150002 ++#define FSTV0910_P1_COARSE_LK2MODE 0xf4150001 ++ ++/*P1_DMDISTATE*/ ++#define RSTV0910_P1_DMDISTATE 0xf416 ++#define FSTV0910_P1_I2C_NORESETDMODE 0xf4160080 ++#define FSTV0910_P1_FORCE_ETAPED 0xf4160040 ++#define FSTV0910_P1_SDMDRST_DIRCLK 0xf4160020 ++#define FSTV0910_P1_I2C_DEMOD_MODE 0xf416001f ++ ++/*P1_DMDT0M*/ ++#define RSTV0910_P1_DMDT0M 0xf417 ++#define FSTV0910_P1_DMDT0_MIN 0xf41700ff ++ ++/*P1_DMDSTATE*/ ++#define RSTV0910_P1_DMDSTATE 0xf41b ++#define FSTV0910_P1_DEMOD_LOCKED 0xf41b0080 ++#define FSTV0910_P1_HEADER_MODE 0xf41b0060 ++#define FSTV0910_P1_DEMOD_MODE 0xf41b001f ++ ++/*P1_DMDFLYW*/ ++#define RSTV0910_P1_DMDFLYW 0xf41c ++#define FSTV0910_P1_I2C_IRQVAL 0xf41c00f0 ++#define FSTV0910_P1_FLYWHEEL_CPT 0xf41c000f ++ ++/*P1_DSTATUS3*/ ++#define RSTV0910_P1_DSTATUS3 0xf41d ++#define FSTV0910_P1_CFR_ZIGZAG 0xf41d0080 ++#define FSTV0910_P1_DEMOD_CFGMODE 0xf41d0060 ++#define FSTV0910_P1_GAMMA_LOWBAUDRATE 0xf41d0010 ++#define FSTV0910_P1_RELOCK_MODE 0xf41d0008 ++#define FSTV0910_P1_DEMOD_FAIL 0xf41d0004 ++#define FSTV0910_P1_ETAPE1A_DVBXMEM 0xf41d0003 ++ ++/*P1_DMDCFG3*/ ++#define RSTV0910_P1_DMDCFG3 0xf41e ++#define FSTV0910_P1_DVBS1_TMGWAIT 0xf41e0080 ++#define FSTV0910_P1_NO_BWCENTERING 0xf41e0040 ++#define FSTV0910_P1_INV_SEQSRCH 0xf41e0020 ++#define FSTV0910_P1_DIS_SFRUPLOW_TRK 0xf41e0010 ++#define FSTV0910_P1_NOSTOP_FIFOFULL 0xf41e0008 ++#define FSTV0910_P1_LOCKTIME_MODE 0xf41e0007 ++ ++/*P1_DMDCFG4*/ ++#define RSTV0910_P1_DMDCFG4 0xf41f ++#define FSTV0910_P1_DIS_VITLOCK 0xf41f0080 ++#define FSTV0910_P1_S1S2TOUT_FAST 0xf41f0040 ++#define FSTV0910_P1_DEMOD_FASTLOCK 0xf41f0020 ++#define FSTV0910_P1_S1HIER_ENABLE 0xf41f0010 ++#define FSTV0910_P1_TUNER_NRELAUNCH 0xf41f0008 ++#define FSTV0910_P1_DIS_CLKENABLE 0xf41f0004 ++#define FSTV0910_P1_DIS_HDRDIVLOCK 0xf41f0002 ++#define FSTV0910_P1_NO_TNRWBINIT 0xf41f0001 ++ ++/*P1_CORRELMANT*/ ++#define RSTV0910_P1_CORRELMANT 0xf420 ++#define FSTV0910_P1_CORREL_MANT 0xf42000ff ++ ++/*P1_CORRELABS*/ ++#define RSTV0910_P1_CORRELABS 0xf421 ++#define FSTV0910_P1_CORREL_ABS 0xf42100ff ++ ++/*P1_CORRELEXP*/ ++#define RSTV0910_P1_CORRELEXP 0xf422 ++#define FSTV0910_P1_CORREL_ABSEXP 0xf42200f0 ++#define FSTV0910_P1_CORREL_EXP 0xf422000f ++ ++/*P1_PLHMODCOD*/ ++#define RSTV0910_P1_PLHMODCOD 0xf424 ++#define FSTV0910_P1_SPECINV_DEMOD 0xf4240080 ++#define FSTV0910_P1_PLH_MODCOD 0xf424007c ++#define FSTV0910_P1_PLH_TYPE 0xf4240003 ++ ++/*P1_DMDREG*/ ++#define RSTV0910_P1_DMDREG 0xf425 ++#define FSTV0910_P1_EXTPSK_MODE 0xf4250080 ++#define FSTV0910_P1_HIER_SHORTFRAME 0xf4250002 ++#define FSTV0910_P1_DECIM_PLFRAMES 0xf4250001 ++ ++/*P1_AGC2O*/ ++#define RSTV0910_P1_AGC2O 0xf42c ++#define FSTV0910_P1_CSTENV_MODE 0xf42c00c0 ++#define FSTV0910_P1_AGC2_LKSQRT 0xf42c0020 ++#define FSTV0910_P1_AGC2_LKMODE 0xf42c0010 ++#define FSTV0910_P1_AGC2_LKEQUA 0xf42c0008 ++#define FSTV0910_P1_AGC2_COEF 0xf42c0007 ++ ++/*P1_AGC2REF*/ ++#define RSTV0910_P1_AGC2REF 0xf42d ++#define FSTV0910_P1_AGC2_REF 0xf42d00ff ++ ++/*P1_AGC1ADJ*/ ++#define RSTV0910_P1_AGC1ADJ 0xf42e ++#define FSTV0910_P1_AGC1ADJ_MANUAL 0xf42e0080 ++#define FSTV0910_P1_AGC1_ADJUSTED 0xf42e007f ++ ++/*P1_AGC2I1*/ ++#define RSTV0910_P1_AGC2I1 0xf436 ++#define FSTV0910_P1_AGC2_INTEGRATOR1 0xf43600ff ++ ++/*P1_AGC2I0*/ ++#define RSTV0910_P1_AGC2I0 0xf437 ++#define FSTV0910_P1_AGC2_INTEGRATOR0 0xf43700ff ++ ++/*P1_CARCFG*/ ++#define RSTV0910_P1_CARCFG 0xf438 ++#define FSTV0910_P1_CFRUPLOW_AUTO 0xf4380080 ++#define FSTV0910_P1_CFRUPLOW_TEST 0xf4380040 ++#define FSTV0910_P1_WIDE_FREQDET 0xf4380020 ++#define FSTV0910_P1_CARHDR_NODIV8 0xf4380010 ++#define FSTV0910_P1_I2C_ROTA 0xf4380008 ++#define FSTV0910_P1_ROTAON 0xf4380004 ++#define FSTV0910_P1_PH_DET_ALGO 0xf4380003 ++ ++/*P1_ACLC*/ ++#define RSTV0910_P1_ACLC 0xf439 ++#define FSTV0910_P1_CARS1_ANOSAUTO 0xf4390040 ++#define FSTV0910_P1_CAR_ALPHA_MANT 0xf4390030 ++#define FSTV0910_P1_CAR_ALPHA_EXP 0xf439000f ++ ++/*P1_BCLC*/ ++#define RSTV0910_P1_BCLC 0xf43a ++#define FSTV0910_P1_CARS1_BNOSAUTO 0xf43a0040 ++#define FSTV0910_P1_CAR_BETA_MANT 0xf43a0030 ++#define FSTV0910_P1_CAR_BETA_EXP 0xf43a000f ++ ++/*P1_CARFREQ*/ ++#define RSTV0910_P1_CARFREQ 0xf43d ++#define FSTV0910_P1_KC_COARSE_EXP 0xf43d00f0 ++#define FSTV0910_P1_BETA_FREQ 0xf43d000f ++ ++/*P1_CARHDR*/ ++#define RSTV0910_P1_CARHDR 0xf43e ++#define FSTV0910_P1_K_FREQ_HDR 0xf43e00ff ++ ++/*P1_LDT*/ ++#define RSTV0910_P1_LDT 0xf43f ++#define FSTV0910_P1_CARLOCK_THRES 0xf43f01ff ++ ++/*P1_LDT2*/ ++#define RSTV0910_P1_LDT2 0xf440 ++#define FSTV0910_P1_CARLOCK_THRES2 0xf44001ff ++ ++/*P1_CFRICFG*/ ++#define RSTV0910_P1_CFRICFG 0xf441 ++#define FSTV0910_P1_CFRINIT_UNVALRNG 0xf4410080 ++#define FSTV0910_P1_CFRINIT_LUNVALCPT 0xf4410040 ++#define FSTV0910_P1_CFRINIT_ABORTDBL 0xf4410020 ++#define FSTV0910_P1_CFRINIT_ABORTPRED 0xf4410010 ++#define FSTV0910_P1_CFRINIT_UNVALSKIP 0xf4410008 ++#define FSTV0910_P1_CFRINIT_CSTINC 0xf4410004 ++#define FSTV0910_P1_CFRIROLL_GARDER 0xf4410002 ++#define FSTV0910_P1_NEG_CFRSTEP 0xf4410001 ++ ++/*P1_CFRUP1*/ ++#define RSTV0910_P1_CFRUP1 0xf442 ++#define FSTV0910_P1_CFR_UP1 0xf44201ff ++ ++/*P1_CFRUP0*/ ++#define RSTV0910_P1_CFRUP0 0xf443 ++#define FSTV0910_P1_CFR_UP0 0xf44300ff ++ ++/*P1_CFRIBASE1*/ ++#define RSTV0910_P1_CFRIBASE1 0xf444 ++#define FSTV0910_P1_CFRINIT_BASE1 0xf44400ff ++ ++/*P1_CFRIBASE0*/ ++#define RSTV0910_P1_CFRIBASE0 0xf445 ++#define FSTV0910_P1_CFRINIT_BASE0 0xf44500ff ++ ++/*P1_CFRLOW1*/ ++#define RSTV0910_P1_CFRLOW1 0xf446 ++#define FSTV0910_P1_CFR_LOW1 0xf44601ff ++ ++/*P1_CFRLOW0*/ ++#define RSTV0910_P1_CFRLOW0 0xf447 ++#define FSTV0910_P1_CFR_LOW0 0xf44700ff ++ ++/*P1_CFRINIT1*/ ++#define RSTV0910_P1_CFRINIT1 0xf448 ++#define FSTV0910_P1_CFR_INIT1 0xf44801ff ++ ++/*P1_CFRINIT0*/ ++#define RSTV0910_P1_CFRINIT0 0xf449 ++#define FSTV0910_P1_CFR_INIT0 0xf44900ff ++ ++/*P1_CFRINC1*/ ++#define RSTV0910_P1_CFRINC1 0xf44a ++#define FSTV0910_P1_MANUAL_CFRINC 0xf44a0080 ++#define FSTV0910_P1_CFR_INC1 0xf44a003f ++ ++/*P1_CFRINC0*/ ++#define RSTV0910_P1_CFRINC0 0xf44b ++#define FSTV0910_P1_CFR_INC0 0xf44b00ff ++ ++/*P1_CFR2*/ ++#define RSTV0910_P1_CFR2 0xf44c ++#define FSTV0910_P1_CAR_FREQ2 0xf44c01ff ++ ++/*P1_CFR1*/ ++#define RSTV0910_P1_CFR1 0xf44d ++#define FSTV0910_P1_CAR_FREQ1 0xf44d00ff ++ ++/*P1_CFR0*/ ++#define RSTV0910_P1_CFR0 0xf44e ++#define FSTV0910_P1_CAR_FREQ0 0xf44e00ff ++ ++/*P1_LDI*/ ++#define RSTV0910_P1_LDI 0xf44f ++#define FSTV0910_P1_LOCK_DET_INTEGR 0xf44f01ff ++ ++/*P1_TMGCFG*/ ++#define RSTV0910_P1_TMGCFG 0xf450 ++#define FSTV0910_P1_TMGLOCK_BETA 0xf45000c0 ++#define FSTV0910_P1_DO_TIMING_CORR 0xf4500010 ++#define FSTV0910_P1_MANUAL_SCAN 0xf450000c ++#define FSTV0910_P1_TMG_MINFREQ 0xf4500003 ++ ++/*P1_RTC*/ ++#define RSTV0910_P1_RTC 0xf451 ++#define FSTV0910_P1_TMGALPHA_EXP 0xf45100f0 ++#define FSTV0910_P1_TMGBETA_EXP 0xf451000f ++ ++/*P1_RTCS2*/ ++#define RSTV0910_P1_RTCS2 0xf452 ++#define FSTV0910_P1_TMGALPHAS2_EXP 0xf45200f0 ++#define FSTV0910_P1_TMGBETAS2_EXP 0xf452000f ++ ++/*P1_TMGTHRISE*/ ++#define RSTV0910_P1_TMGTHRISE 0xf453 ++#define FSTV0910_P1_TMGLOCK_THRISE 0xf45300ff ++ ++/*P1_TMGTHFALL*/ ++#define RSTV0910_P1_TMGTHFALL 0xf454 ++#define FSTV0910_P1_TMGLOCK_THFALL 0xf45400ff ++ ++/*P1_SFRUPRATIO*/ ++#define RSTV0910_P1_SFRUPRATIO 0xf455 ++#define FSTV0910_P1_SFR_UPRATIO 0xf45500ff ++ ++/*P1_SFRLOWRATIO*/ ++#define RSTV0910_P1_SFRLOWRATIO 0xf456 ++#define FSTV0910_P1_SFR_LOWRATIO 0xf45600ff ++ ++/*P1_KTTMG*/ ++#define RSTV0910_P1_KTTMG 0xf457 ++#define FSTV0910_P1_KT_TMG_EXP 0xf45700f0 ++ ++/*P1_KREFTMG*/ ++#define RSTV0910_P1_KREFTMG 0xf458 ++#define FSTV0910_P1_KREF_TMG 0xf45800ff ++ ++/*P1_SFRSTEP*/ ++#define RSTV0910_P1_SFRSTEP 0xf459 ++#define FSTV0910_P1_SFR_SCANSTEP 0xf45900f0 ++#define FSTV0910_P1_SFR_CENTERSTEP 0xf459000f ++ ++/*P1_TMGCFG2*/ ++#define RSTV0910_P1_TMGCFG2 0xf45a ++#define FSTV0910_P1_KREFTMG2_DECMODE 0xf45a00c0 ++#define FSTV0910_P1_DIS_AUTOSAMP 0xf45a0008 ++#define FSTV0910_P1_SCANINIT_QUART 0xf45a0004 ++#define FSTV0910_P1_NOTMG_DVBS1DERAT 0xf45a0002 ++#define FSTV0910_P1_SFRRATIO_FINE 0xf45a0001 ++ ++/*P1_KREFTMG2*/ ++#define RSTV0910_P1_KREFTMG2 0xf45b ++#define FSTV0910_P1_KREF_TMG2 0xf45b00ff ++ ++/*P1_TMGCFG3*/ ++#define RSTV0910_P1_TMGCFG3 0xf45d ++#define FSTV0910_P1_CFRINC_MODE 0xf45d0070 ++#define FSTV0910_P1_CONT_TMGCENTER 0xf45d0008 ++#define FSTV0910_P1_AUTO_GUP 0xf45d0004 ++#define FSTV0910_P1_AUTO_GLOW 0xf45d0002 ++#define FSTV0910_P1_SFRVAL_MINMODE 0xf45d0001 ++ ++/*P1_SFRINIT1*/ ++#define RSTV0910_P1_SFRINIT1 0xf45e ++#define FSTV0910_P1_SFR_INIT1 0xf45e00ff ++ ++/*P1_SFRINIT0*/ ++#define RSTV0910_P1_SFRINIT0 0xf45f ++#define FSTV0910_P1_SFR_INIT0 0xf45f00ff ++ ++/*P1_SFRUP1*/ ++#define RSTV0910_P1_SFRUP1 0xf460 ++#define FSTV0910_P1_SYMB_FREQ_UP1 0xf46000ff ++ ++/*P1_SFRUP0*/ ++#define RSTV0910_P1_SFRUP0 0xf461 ++#define FSTV0910_P1_SYMB_FREQ_UP0 0xf46100ff ++ ++/*P1_SFRLOW1*/ ++#define RSTV0910_P1_SFRLOW1 0xf462 ++#define FSTV0910_P1_SYMB_FREQ_LOW1 0xf46200ff ++ ++/*P1_SFRLOW0*/ ++#define RSTV0910_P1_SFRLOW0 0xf463 ++#define FSTV0910_P1_SYMB_FREQ_LOW0 0xf46300ff ++ ++/*P1_SFR3*/ ++#define RSTV0910_P1_SFR3 0xf464 ++#define FSTV0910_P1_SYMB_FREQ3 0xf46400ff ++ ++/*P1_SFR2*/ ++#define RSTV0910_P1_SFR2 0xf465 ++#define FSTV0910_P1_SYMB_FREQ2 0xf46500ff ++ ++/*P1_SFR1*/ ++#define RSTV0910_P1_SFR1 0xf466 ++#define FSTV0910_P1_SYMB_FREQ1 0xf46600ff ++ ++/*P1_SFR0*/ ++#define RSTV0910_P1_SFR0 0xf467 ++#define FSTV0910_P1_SYMB_FREQ0 0xf46700ff ++ ++/*P1_TMGREG2*/ ++#define RSTV0910_P1_TMGREG2 0xf468 ++#define FSTV0910_P1_TMGREG2 0xf46800ff ++ ++/*P1_TMGREG1*/ ++#define RSTV0910_P1_TMGREG1 0xf469 ++#define FSTV0910_P1_TMGREG1 0xf46900ff ++ ++/*P1_TMGREG0*/ ++#define RSTV0910_P1_TMGREG0 0xf46a ++#define FSTV0910_P1_TMGREG0 0xf46a00ff ++ ++/*P1_TMGLOCK1*/ ++#define RSTV0910_P1_TMGLOCK1 0xf46b ++#define FSTV0910_P1_TMGLOCK_LEVEL1 0xf46b01ff ++ ++/*P1_TMGLOCK0*/ ++#define RSTV0910_P1_TMGLOCK0 0xf46c ++#define FSTV0910_P1_TMGLOCK_LEVEL0 0xf46c00ff ++ ++/*P1_TMGOBS*/ ++#define RSTV0910_P1_TMGOBS 0xf46d ++#define FSTV0910_P1_ROLLOFF_STATUS 0xf46d00c0 ++#define FSTV0910_P1_SCAN_SIGN 0xf46d0030 ++#define FSTV0910_P1_TMG_SCANNING 0xf46d0008 ++#define FSTV0910_P1_CHCENTERING_MODE 0xf46d0004 ++#define FSTV0910_P1_TMG_SCANFAIL 0xf46d0002 ++ ++/*P1_EQUALCFG*/ ++#define RSTV0910_P1_EQUALCFG 0xf46f ++#define FSTV0910_P1_NOTMG_NEGALWAIT 0xf46f0080 ++#define FSTV0910_P1_EQUAL_ON 0xf46f0040 ++#define FSTV0910_P1_SEL_EQUALCOR 0xf46f0038 ++#define FSTV0910_P1_MU_EQUALDFE 0xf46f0007 ++ ++/*P1_EQUAI1*/ ++#define RSTV0910_P1_EQUAI1 0xf470 ++#define FSTV0910_P1_EQUA_ACCI1 0xf47001ff ++ ++/*P1_EQUAQ1*/ ++#define RSTV0910_P1_EQUAQ1 0xf471 ++#define FSTV0910_P1_EQUA_ACCQ1 0xf47101ff ++ ++/*P1_EQUAI2*/ ++#define RSTV0910_P1_EQUAI2 0xf472 ++#define FSTV0910_P1_EQUA_ACCI2 0xf47201ff ++ ++/*P1_EQUAQ2*/ ++#define RSTV0910_P1_EQUAQ2 0xf473 ++#define FSTV0910_P1_EQUA_ACCQ2 0xf47301ff ++ ++/*P1_EQUAI3*/ ++#define RSTV0910_P1_EQUAI3 0xf474 ++#define FSTV0910_P1_EQUA_ACCI3 0xf47401ff ++ ++/*P1_EQUAQ3*/ ++#define RSTV0910_P1_EQUAQ3 0xf475 ++#define FSTV0910_P1_EQUA_ACCQ3 0xf47501ff ++ ++/*P1_EQUAI4*/ ++#define RSTV0910_P1_EQUAI4 0xf476 ++#define FSTV0910_P1_EQUA_ACCI4 0xf47601ff ++ ++/*P1_EQUAQ4*/ ++#define RSTV0910_P1_EQUAQ4 0xf477 ++#define FSTV0910_P1_EQUA_ACCQ4 0xf47701ff ++ ++/*P1_EQUAI5*/ ++#define RSTV0910_P1_EQUAI5 0xf478 ++#define FSTV0910_P1_EQUA_ACCI5 0xf47801ff ++ ++/*P1_EQUAQ5*/ ++#define RSTV0910_P1_EQUAQ5 0xf479 ++#define FSTV0910_P1_EQUA_ACCQ5 0xf47901ff ++ ++/*P1_EQUAI6*/ ++#define RSTV0910_P1_EQUAI6 0xf47a ++#define FSTV0910_P1_EQUA_ACCI6 0xf47a01ff ++ ++/*P1_EQUAQ6*/ ++#define RSTV0910_P1_EQUAQ6 0xf47b ++#define FSTV0910_P1_EQUA_ACCQ6 0xf47b01ff ++ ++/*P1_EQUAI7*/ ++#define RSTV0910_P1_EQUAI7 0xf47c ++#define FSTV0910_P1_EQUA_ACCI7 0xf47c01ff ++ ++/*P1_EQUAQ7*/ ++#define RSTV0910_P1_EQUAQ7 0xf47d ++#define FSTV0910_P1_EQUA_ACCQ7 0xf47d01ff ++ ++/*P1_EQUAI8*/ ++#define RSTV0910_P1_EQUAI8 0xf47e ++#define FSTV0910_P1_EQUA_ACCI8 0xf47e01ff ++ ++/*P1_EQUAQ8*/ ++#define RSTV0910_P1_EQUAQ8 0xf47f ++#define FSTV0910_P1_EQUA_ACCQ8 0xf47f01ff ++ ++/*P1_NNOSDATAT1*/ ++#define RSTV0910_P1_NNOSDATAT1 0xf480 ++#define FSTV0910_P1_NOSDATAT_NORMED1 0xf48000ff ++ ++/*P1_NNOSDATAT0*/ ++#define RSTV0910_P1_NNOSDATAT0 0xf481 ++#define FSTV0910_P1_NOSDATAT_NORMED0 0xf48100ff ++ ++/*P1_NNOSDATA1*/ ++#define RSTV0910_P1_NNOSDATA1 0xf482 ++#define FSTV0910_P1_NOSDATA_NORMED1 0xf48200ff ++ ++/*P1_NNOSDATA0*/ ++#define RSTV0910_P1_NNOSDATA0 0xf483 ++#define FSTV0910_P1_NOSDATA_NORMED0 0xf48300ff ++ ++/*P1_NNOSPLHT1*/ ++#define RSTV0910_P1_NNOSPLHT1 0xf484 ++#define FSTV0910_P1_NOSPLHT_NORMED1 0xf48400ff ++ ++/*P1_NNOSPLHT0*/ ++#define RSTV0910_P1_NNOSPLHT0 0xf485 ++#define FSTV0910_P1_NOSPLHT_NORMED0 0xf48500ff ++ ++/*P1_NNOSPLH1*/ ++#define RSTV0910_P1_NNOSPLH1 0xf486 ++#define FSTV0910_P1_NOSPLH_NORMED1 0xf48600ff ++ ++/*P1_NNOSPLH0*/ ++#define RSTV0910_P1_NNOSPLH0 0xf487 ++#define FSTV0910_P1_NOSPLH_NORMED0 0xf48700ff ++ ++/*P1_NOSDATAT1*/ ++#define RSTV0910_P1_NOSDATAT1 0xf488 ++#define FSTV0910_P1_NOSDATAT_UNNORMED1 0xf48800ff ++ ++/*P1_NOSDATAT0*/ ++#define RSTV0910_P1_NOSDATAT0 0xf489 ++#define FSTV0910_P1_NOSDATAT_UNNORMED0 0xf48900ff ++ ++/*P1_NNOSFRAME1*/ ++#define RSTV0910_P1_NNOSFRAME1 0xf48a ++#define FSTV0910_P1_NOSFRAME_NORMED1 0xf48a00ff ++ ++/*P1_NNOSFRAME0*/ ++#define RSTV0910_P1_NNOSFRAME0 0xf48b ++#define FSTV0910_P1_NOSFRAME_NORMED0 0xf48b00ff ++ ++/*P1_NNOSRAD1*/ ++#define RSTV0910_P1_NNOSRAD1 0xf48c ++#define FSTV0910_P1_NOSRADIAL_NORMED1 0xf48c00ff ++ ++/*P1_NNOSRAD0*/ ++#define RSTV0910_P1_NNOSRAD0 0xf48d ++#define FSTV0910_P1_NOSRADIAL_NORMED0 0xf48d00ff ++ ++/*P1_NOSCFGF1*/ ++#define RSTV0910_P1_NOSCFGF1 0xf48e ++#define FSTV0910_P1_LOWNOISE_MESURE 0xf48e0080 ++#define FSTV0910_P1_NOS_DELFRAME 0xf48e0040 ++#define FSTV0910_P1_NOSDATA_MODE 0xf48e0030 ++#define FSTV0910_P1_FRAMESEL_TYPESEL 0xf48e000c ++#define FSTV0910_P1_FRAMESEL_TYPE 0xf48e0003 ++ ++/*P1_CAR2CFG*/ ++#define RSTV0910_P1_CAR2CFG 0xf490 ++#define FSTV0910_P1_DESCRAMB_OFF 0xf4900080 ++#define FSTV0910_P1_EN_PHNOSRAM 0xf4900020 ++#define FSTV0910_P1_STOP_CFR2UPDATE 0xf4900010 ++#define FSTV0910_P1_STOP_NCO2UPDATE 0xf4900008 ++#define FSTV0910_P1_ROTA2ON 0xf4900004 ++#define FSTV0910_P1_PH_DET_ALGO2 0xf4900003 ++ ++/*P1_CFR2CFR1*/ ++#define RSTV0910_P1_CFR2CFR1 0xf491 ++#define FSTV0910_P1_CFR2_S2CONTROL 0xf49100c0 ++#define FSTV0910_P1_EN_S2CAR2CENTER 0xf4910020 ++#define FSTV0910_P1_BCHERRCFR2_MODE 0xf4910018 ++#define FSTV0910_P1_CFR2TOCFR1_BETA 0xf4910007 ++ ++/*P1_CAR3CFG*/ ++#define RSTV0910_P1_CAR3CFG 0xf492 ++#define FSTV0910_P1_CARRIER23_MODE 0xf49200c0 ++#define FSTV0910_P1_CAR3INTERM_DVBS1 0xf4920020 ++#define FSTV0910_P1_ABAMPLIF_MODE 0xf4920018 ++#define FSTV0910_P1_CARRIER3_ALPHA3DL 0xf4920007 ++ ++/*P1_CFR22*/ ++#define RSTV0910_P1_CFR22 0xf493 ++#define FSTV0910_P1_CAR2_FREQ2 0xf49301ff ++ ++/*P1_CFR21*/ ++#define RSTV0910_P1_CFR21 0xf494 ++#define FSTV0910_P1_CAR2_FREQ1 0xf49400ff ++ ++/*P1_CFR20*/ ++#define RSTV0910_P1_CFR20 0xf495 ++#define FSTV0910_P1_CAR2_FREQ0 0xf49500ff ++ ++/*P1_ACLC2S2Q*/ ++#define RSTV0910_P1_ACLC2S2Q 0xf497 ++#define FSTV0910_P1_ENAB_SPSKSYMB 0xf4970080 ++#define FSTV0910_P1_CAR2S2_QANOSAUTO 0xf4970040 ++#define FSTV0910_P1_CAR2S2_Q_ALPH_M 0xf4970030 ++#define FSTV0910_P1_CAR2S2_Q_ALPH_E 0xf497000f ++ ++/*P1_ACLC2S28*/ ++#define RSTV0910_P1_ACLC2S28 0xf498 ++#define FSTV0910_P1_OLDI3Q_MODE 0xf4980080 ++#define FSTV0910_P1_CAR2S2_8ANOSAUTO 0xf4980040 ++#define FSTV0910_P1_CAR2S2_8_ALPH_M 0xf4980030 ++#define FSTV0910_P1_CAR2S2_8_ALPH_E 0xf498000f ++ ++/*P1_ACLC2S216A*/ ++#define RSTV0910_P1_ACLC2S216A 0xf499 ++#define FSTV0910_P1_CAR2S2_16ANOSAUTO 0xf4990040 ++#define FSTV0910_P1_CAR2S2_16A_ALPH_M 0xf4990030 ++#define FSTV0910_P1_CAR2S2_16A_ALPH_E 0xf499000f ++ ++/*P1_ACLC2S232A*/ ++#define RSTV0910_P1_ACLC2S232A 0xf49a ++#define FSTV0910_P1_CAR2S2_32ANOSUATO 0xf49a0040 ++#define FSTV0910_P1_CAR2S2_32A_ALPH_M 0xf49a0030 ++#define FSTV0910_P1_CAR2S2_32A_ALPH_E 0xf49a000f ++ ++/*P1_BCLC2S2Q*/ ++#define RSTV0910_P1_BCLC2S2Q 0xf49c ++#define FSTV0910_P1_DVBS2S2Q_NIP 0xf49c0080 ++#define FSTV0910_P1_CAR2S2_QBNOSAUTO 0xf49c0040 ++#define FSTV0910_P1_CAR2S2_Q_BETA_M 0xf49c0030 ++#define FSTV0910_P1_CAR2S2_Q_BETA_E 0xf49c000f ++ ++/*P1_BCLC2S28*/ ++#define RSTV0910_P1_BCLC2S28 0xf49d ++#define FSTV0910_P1_DVBS2S28_NIP 0xf49d0080 ++#define FSTV0910_P1_CAR2S2_8BNOSAUTO 0xf49d0040 ++#define FSTV0910_P1_CAR2S2_8_BETA_M 0xf49d0030 ++#define FSTV0910_P1_CAR2S2_8_BETA_E 0xf49d000f ++ ++/*P1_PLROOT2*/ ++#define RSTV0910_P1_PLROOT2 0xf4ac ++#define FSTV0910_P1_PLHAUTO_DISPLH 0xf4ac0040 ++#define FSTV0910_P1_PLHAUTO_FASTMODE 0xf4ac0020 ++#define FSTV0910_P1_PLHAUTO_ENABLE 0xf4ac0010 ++#define FSTV0910_P1_PLSCRAMB_MODE 0xf4ac000c ++#define FSTV0910_P1_PLSCRAMB_ROOT2 0xf4ac0003 ++ ++/*P1_PLROOT1*/ ++#define RSTV0910_P1_PLROOT1 0xf4ad ++#define FSTV0910_P1_PLSCRAMB_ROOT1 0xf4ad00ff ++ ++/*P1_PLROOT0*/ ++#define RSTV0910_P1_PLROOT0 0xf4ae ++#define FSTV0910_P1_PLSCRAMB_ROOT0 0xf4ae00ff ++ ++/*P1_MODCODLST7*/ ++#define RSTV0910_P1_MODCODLST7 0xf4b7 ++#define FSTV0910_P1_MODCOD_NNOSFILTER 0xf4b70080 ++#define FSTV0910_P1_MODCODLST_NOSTYPE 0xf4b70040 ++#define FSTV0910_P1_DIS_8PSK_9_10 0xf4b70030 ++#define FSTV0910_P1_DIS_8P_8_9 0xf4b7000f ++ ++/*P1_MODCODLST8*/ ++#define RSTV0910_P1_MODCODLST8 0xf4b8 ++#define FSTV0910_P1_DIS_8P_5_6 0xf4b800f0 ++#define FSTV0910_P1_DIS_8P_3_4 0xf4b8000f ++ ++/*P1_MODCODLST9*/ ++#define RSTV0910_P1_MODCODLST9 0xf4b9 ++#define FSTV0910_P1_DIS_8P_2_3 0xf4b900f0 ++#define FSTV0910_P1_DIS_8P_3_5 0xf4b9000f ++ ++/*P1_MODCODLSTA*/ ++#define RSTV0910_P1_MODCODLSTA 0xf4ba ++#define FSTV0910_P1_NOSFILTER_LIMITE 0xf4ba0080 ++#define FSTV0910_P1_NOSFILTER_MODE 0xf4ba0040 ++#define FSTV0910_P1_DIS_QPSK_9_10 0xf4ba0030 ++#define FSTV0910_P1_DIS_QP_8_9 0xf4ba000f ++ ++/*P1_MODCODLSTB*/ ++#define RSTV0910_P1_MODCODLSTB 0xf4bb ++#define FSTV0910_P1_DIS_QP_5_6 0xf4bb00f0 ++#define FSTV0910_P1_DIS_QP_4_5 0xf4bb000f ++ ++/*P1_MODCODLSTC*/ ++#define RSTV0910_P1_MODCODLSTC 0xf4bc ++#define FSTV0910_P1_DIS_QP_3_4 0xf4bc00f0 ++#define FSTV0910_P1_DIS_QP_2_3 0xf4bc000f ++ ++/*P1_MODCODLSTD*/ ++#define RSTV0910_P1_MODCODLSTD 0xf4bd ++#define FSTV0910_P1_DIS_QPSK_3_5 0xf4bd00f0 ++#define FSTV0910_P1_DIS_QPSK_1_2 0xf4bd000f ++ ++/*P1_GAUSSR0*/ ++#define RSTV0910_P1_GAUSSR0 0xf4c0 ++#define FSTV0910_P1_EN_CCIMODE 0xf4c00080 ++#define FSTV0910_P1_R0_GAUSSIEN 0xf4c0007f ++ ++/*P1_CCIR0*/ ++#define RSTV0910_P1_CCIR0 0xf4c1 ++#define FSTV0910_P1_CCIDETECT_PLHONLY 0xf4c10080 ++#define FSTV0910_P1_R0_CCI 0xf4c1007f ++ ++/*P1_CCIQUANT*/ ++#define RSTV0910_P1_CCIQUANT 0xf4c2 ++#define FSTV0910_P1_CCI_BETA 0xf4c200e0 ++#define FSTV0910_P1_CCI_QUANT 0xf4c2001f ++ ++/*P1_CCITHRES*/ ++#define RSTV0910_P1_CCITHRES 0xf4c3 ++#define FSTV0910_P1_CCI_THRESHOLD 0xf4c300ff ++ ++/*P1_CCIACC*/ ++#define RSTV0910_P1_CCIACC 0xf4c4 ++#define FSTV0910_P1_CCI_VALUE 0xf4c400ff ++ ++/*P1_DSTATUS4*/ ++#define RSTV0910_P1_DSTATUS4 0xf4c5 ++#define FSTV0910_P1_RAINFADE_DETECT 0xf4c50080 ++#define FSTV0910_P1_NOTHRES2_FAIL 0xf4c50040 ++#define FSTV0910_P1_NOTHRES1_FAIL 0xf4c50020 ++#define FSTV0910_P1_PILOT_FAILDETECT 0xf4c50010 ++#define FSTV0910_P1_HIER_DETECT 0xf4c50008 ++#define FSTV0910_P1_DMDPROG_ERROR 0xf4c50004 ++#define FSTV0910_P1_CSTENV_DETECT 0xf4c50002 ++#define FSTV0910_P1_DETECTION_TRIAX 0xf4c50001 ++ ++/*P1_DMDRESCFG*/ ++#define RSTV0910_P1_DMDRESCFG 0xf4c6 ++#define FSTV0910_P1_DMDRES_RESET 0xf4c60080 ++#define FSTV0910_P1_DMDRES_NOISESQR 0xf4c60010 ++#define FSTV0910_P1_DMDRES_STRALL 0xf4c60008 ++#define FSTV0910_P1_DMDRES_NEWONLY 0xf4c60004 ++#define FSTV0910_P1_DMDRES_NOSTORE 0xf4c60002 ++#define FSTV0910_P1_DMDRES_AGC2MEM 0xf4c60001 ++ ++/*P1_DMDRESADR*/ ++#define RSTV0910_P1_DMDRESADR 0xf4c7 ++#define FSTV0910_P1_SUSP_PREDCANAL 0xf4c70080 ++#define FSTV0910_P1_DMDRES_VALIDCFR 0xf4c70040 ++#define FSTV0910_P1_DMDRES_MEMFULL 0xf4c70030 ++#define FSTV0910_P1_DMDRES_RESNBR 0xf4c7000f ++ ++/*P1_DMDRESDATA7*/ ++#define RSTV0910_P1_DMDRESDATA7 0xf4c8 ++#define FSTV0910_P1_DMDRES_DATA7 0xf4c800ff ++ ++/*P1_DMDRESDATA6*/ ++#define RSTV0910_P1_DMDRESDATA6 0xf4c9 ++#define FSTV0910_P1_DMDRES_DATA6 0xf4c900ff ++ ++/*P1_DMDRESDATA5*/ ++#define RSTV0910_P1_DMDRESDATA5 0xf4ca ++#define FSTV0910_P1_DMDRES_DATA5 0xf4ca00ff ++ ++/*P1_DMDRESDATA4*/ ++#define RSTV0910_P1_DMDRESDATA4 0xf4cb ++#define FSTV0910_P1_DMDRES_DATA4 0xf4cb00ff ++ ++/*P1_DMDRESDATA3*/ ++#define RSTV0910_P1_DMDRESDATA3 0xf4cc ++#define FSTV0910_P1_DMDRES_DATA3 0xf4cc00ff ++ ++/*P1_DMDRESDATA2*/ ++#define RSTV0910_P1_DMDRESDATA2 0xf4cd ++#define FSTV0910_P1_DMDRES_DATA2 0xf4cd00ff ++ ++/*P1_DMDRESDATA1*/ ++#define RSTV0910_P1_DMDRESDATA1 0xf4ce ++#define FSTV0910_P1_DMDRES_DATA1 0xf4ce00ff ++ ++/*P1_DMDRESDATA0*/ ++#define RSTV0910_P1_DMDRESDATA0 0xf4cf ++#define FSTV0910_P1_DMDRES_DATA0 0xf4cf00ff ++ ++/*P1_FFEI1*/ ++#define RSTV0910_P1_FFEI1 0xf4d0 ++#define FSTV0910_P1_FFE_ACCI1 0xf4d001ff ++ ++/*P1_FFEQ1*/ ++#define RSTV0910_P1_FFEQ1 0xf4d1 ++#define FSTV0910_P1_FFE_ACCQ1 0xf4d101ff ++ ++/*P1_FFEI2*/ ++#define RSTV0910_P1_FFEI2 0xf4d2 ++#define FSTV0910_P1_FFE_ACCI2 0xf4d201ff ++ ++/*P1_FFEQ2*/ ++#define RSTV0910_P1_FFEQ2 0xf4d3 ++#define FSTV0910_P1_FFE_ACCQ2 0xf4d301ff ++ ++/*P1_FFEI3*/ ++#define RSTV0910_P1_FFEI3 0xf4d4 ++#define FSTV0910_P1_FFE_ACCI3 0xf4d401ff ++ ++/*P1_FFEQ3*/ ++#define RSTV0910_P1_FFEQ3 0xf4d5 ++#define FSTV0910_P1_FFE_ACCQ3 0xf4d501ff ++ ++/*P1_FFEI4*/ ++#define RSTV0910_P1_FFEI4 0xf4d6 ++#define FSTV0910_P1_FFE_ACCI4 0xf4d601ff ++ ++/*P1_FFEQ4*/ ++#define RSTV0910_P1_FFEQ4 0xf4d7 ++#define FSTV0910_P1_FFE_ACCQ4 0xf4d701ff ++ ++/*P1_FFECFG*/ ++#define RSTV0910_P1_FFECFG 0xf4d8 ++#define FSTV0910_P1_EQUALFFE_ON 0xf4d80040 ++#define FSTV0910_P1_EQUAL_USEDSYMB 0xf4d80030 ++#define FSTV0910_P1_MU_EQUALFFE 0xf4d80007 ++ ++/*P1_TNRCFG2*/ ++#define RSTV0910_P1_TNRCFG2 0xf4e1 ++#define FSTV0910_P1_TUN_IQSWAP 0xf4e10080 ++#define FSTV0910_P1_STB6110_STEP2MHZ 0xf4e10040 ++#define FSTV0910_P1_STB6120_DBLI2C 0xf4e10020 ++#define FSTV0910_P1_TUNER_WIDEBAND 0xf4e10010 ++#define FSTV0910_P1_TUNER_OBSPAGE 0xf4e10008 ++#define FSTV0910_P1_DIS_BWCALC 0xf4e10004 ++#define FSTV0910_P1_SHORT_WAITSTATES 0xf4e10002 ++#define FSTV0910_P1_DIS_2BWAGC1 0xf4e10001 ++ ++/*P1_SMAPCOEF7*/ ++#define RSTV0910_P1_SMAPCOEF7 0xf500 ++#define FSTV0910_P1_DIS_QSCALE 0xf5000080 ++#define FSTV0910_P1_SMAPCOEF_Q_LLR12 0xf500017f ++ ++/*P1_SMAPCOEF6*/ ++#define RSTV0910_P1_SMAPCOEF6 0xf501 ++#define FSTV0910_P1_DIS_AGC2SCALE 0xf5010080 ++#define FSTV0910_P1_DIS_16IQMULT 0xf5010040 ++#define FSTV0910_P1_OLD_16APSK47 0xf5010020 ++#define FSTV0910_P1_OLD_16APSK12 0xf5010010 ++#define FSTV0910_P1_DIS_NEWSCALE 0xf5010008 ++#define FSTV0910_P1_ADJ_8PSKLLR1 0xf5010004 ++#define FSTV0910_P1_OLD_8PSKLLR1 0xf5010002 ++#define FSTV0910_P1_DIS_AB8PSK 0xf5010001 ++ ++/*P1_SMAPCOEF5*/ ++#define RSTV0910_P1_SMAPCOEF5 0xf502 ++#define FSTV0910_P1_DIS_8SCALE 0xf5020080 ++#define FSTV0910_P1_SMAPCOEF_8P_LLR23 0xf502017f ++ ++/*P1_NOSTHRES1*/ ++#define RSTV0910_P1_NOSTHRES1 0xf509 ++#define FSTV0910_P1_NOS_THRESHOLD1 0xf50900ff ++ ++/*P1_NOSTHRES2*/ ++#define RSTV0910_P1_NOSTHRES2 0xf50a ++#define FSTV0910_P1_NOS_THRESHOLD2 0xf50a00ff ++ ++/*P1_NOSDIFF1*/ ++#define RSTV0910_P1_NOSDIFF1 0xf50b ++#define FSTV0910_P1_NOSTHRES1_DIFF 0xf50b00ff ++ ++/*P1_RAINFADE*/ ++#define RSTV0910_P1_RAINFADE 0xf50c ++#define FSTV0910_P1_NOSTHRES_DATAT 0xf50c0080 ++#define FSTV0910_P1_RAINFADE_CNLIMIT 0xf50c0070 ++#define FSTV0910_P1_RAINFADE_TIMEOUT 0xf50c0007 ++ ++/*P1_NOSRAMCFG*/ ++#define RSTV0910_P1_NOSRAMCFG 0xf50d ++#define FSTV0910_P1_NOSRAM_DVBS2DATA 0xf50d0080 ++#define FSTV0910_P1_NOSRAM_QUADRAT 0xf50d0040 ++#define FSTV0910_P1_NOSRAM_ACTIVATION 0xf50d0030 ++#define FSTV0910_P1_NOSRAM_CNRONLY 0xf50d0008 ++#define FSTV0910_P1_NOSRAM_LGNCNR1 0xf50d0007 ++ ++/*P1_NOSRAMPOS*/ ++#define RSTV0910_P1_NOSRAMPOS 0xf50e ++#define FSTV0910_P1_NOSRAM_LGNCNR0 0xf50e00f0 ++#define FSTV0910_P1_NOSRAM_VALIDE 0xf50e0004 ++#define FSTV0910_P1_NOSRAM_CNRVAL1 0xf50e0003 ++ ++/*P1_NOSRAMVAL*/ ++#define RSTV0910_P1_NOSRAMVAL 0xf50f ++#define FSTV0910_P1_NOSRAM_CNRVAL0 0xf50f00ff ++ ++/*P1_DMDPLHSTAT*/ ++#define RSTV0910_P1_DMDPLHSTAT 0xf520 ++#define FSTV0910_P1_PLH_STATISTIC 0xf52000ff ++ ++/*P1_LOCKTIME3*/ ++#define RSTV0910_P1_LOCKTIME3 0xf522 ++#define FSTV0910_P1_DEMOD_LOCKTIME3 0xf52200ff ++ ++/*P1_LOCKTIME2*/ ++#define RSTV0910_P1_LOCKTIME2 0xf523 ++#define FSTV0910_P1_DEMOD_LOCKTIME2 0xf52300ff ++ ++/*P1_LOCKTIME1*/ ++#define RSTV0910_P1_LOCKTIME1 0xf524 ++#define FSTV0910_P1_DEMOD_LOCKTIME1 0xf52400ff ++ ++/*P1_LOCKTIME0*/ ++#define RSTV0910_P1_LOCKTIME0 0xf525 ++#define FSTV0910_P1_DEMOD_LOCKTIME0 0xf52500ff ++ ++/*P1_VITSCALE*/ ++#define RSTV0910_P1_VITSCALE 0xf532 ++#define FSTV0910_P1_NVTH_NOSRANGE 0xf5320080 ++#define FSTV0910_P1_VERROR_MAXMODE 0xf5320040 ++#define FSTV0910_P1_KDIV_MODE 0xf5320030 ++#define FSTV0910_P1_NSLOWSN_LOCKED 0xf5320008 ++#define FSTV0910_P1_DELOCK_PRFLOSS 0xf5320004 ++#define FSTV0910_P1_DIS_RSFLOCK 0xf5320002 ++ ++/*P1_FECM*/ ++#define RSTV0910_P1_FECM 0xf533 ++#define FSTV0910_P1_DSS_DVB 0xf5330080 ++#define FSTV0910_P1_DEMOD_BYPASS 0xf5330040 ++#define FSTV0910_P1_CMP_SLOWMODE 0xf5330020 ++#define FSTV0910_P1_DSS_SRCH 0xf5330010 ++#define FSTV0910_P1_DIFF_MODEVIT 0xf5330004 ++#define FSTV0910_P1_SYNCVIT 0xf5330002 ++#define FSTV0910_P1_IQINV 0xf5330001 ++ ++/*P1_VTH12*/ ++#define RSTV0910_P1_VTH12 0xf534 ++#define FSTV0910_P1_VTH12 0xf53400ff ++ ++/*P1_VTH23*/ ++#define RSTV0910_P1_VTH23 0xf535 ++#define FSTV0910_P1_VTH23 0xf53500ff ++ ++/*P1_VTH34*/ ++#define RSTV0910_P1_VTH34 0xf536 ++#define FSTV0910_P1_VTH34 0xf53600ff ++ ++/*P1_VTH56*/ ++#define RSTV0910_P1_VTH56 0xf537 ++#define FSTV0910_P1_VTH56 0xf53700ff ++ ++/*P1_VTH67*/ ++#define RSTV0910_P1_VTH67 0xf538 ++#define FSTV0910_P1_VTH67 0xf53800ff ++ ++/*P1_VTH78*/ ++#define RSTV0910_P1_VTH78 0xf539 ++#define FSTV0910_P1_VTH78 0xf53900ff ++ ++/*P1_VITCURPUN*/ ++#define RSTV0910_P1_VITCURPUN 0xf53a ++#define FSTV0910_P1_CYCLESLIP_VIT 0xf53a0080 ++#define FSTV0910_P1_VIT_ROTA180 0xf53a0040 ++#define FSTV0910_P1_VIT_ROTA90 0xf53a0020 ++#define FSTV0910_P1_VIT_CURPUN 0xf53a001f ++ ++/*P1_VERROR*/ ++#define RSTV0910_P1_VERROR 0xf53b ++#define FSTV0910_P1_REGERR_VIT 0xf53b00ff ++ ++/*P1_PRVIT*/ ++#define RSTV0910_P1_PRVIT 0xf53c ++#define FSTV0910_P1_DIS_VTHLOCK 0xf53c0040 ++#define FSTV0910_P1_E7_8VIT 0xf53c0020 ++#define FSTV0910_P1_E6_7VIT 0xf53c0010 ++#define FSTV0910_P1_E5_6VIT 0xf53c0008 ++#define FSTV0910_P1_E3_4VIT 0xf53c0004 ++#define FSTV0910_P1_E2_3VIT 0xf53c0002 ++#define FSTV0910_P1_E1_2VIT 0xf53c0001 ++ ++/*P1_VAVSRVIT*/ ++#define RSTV0910_P1_VAVSRVIT 0xf53d ++#define FSTV0910_P1_AMVIT 0xf53d0080 ++#define FSTV0910_P1_FROZENVIT 0xf53d0040 ++#define FSTV0910_P1_SNVIT 0xf53d0030 ++#define FSTV0910_P1_TOVVIT 0xf53d000c ++#define FSTV0910_P1_HYPVIT 0xf53d0003 ++ ++/*P1_VSTATUSVIT*/ ++#define RSTV0910_P1_VSTATUSVIT 0xf53e ++#define FSTV0910_P1_VITERBI_ON 0xf53e0080 ++#define FSTV0910_P1_END_LOOPVIT 0xf53e0040 ++#define FSTV0910_P1_VITERBI_DEPRF 0xf53e0020 ++#define FSTV0910_P1_PRFVIT 0xf53e0010 ++#define FSTV0910_P1_LOCKEDVIT 0xf53e0008 ++#define FSTV0910_P1_VITERBI_DELOCK 0xf53e0004 ++#define FSTV0910_P1_VIT_DEMODSEL 0xf53e0002 ++#define FSTV0910_P1_VITERBI_COMPOUT 0xf53e0001 ++ ++/*P1_VTHINUSE*/ ++#define RSTV0910_P1_VTHINUSE 0xf53f ++#define FSTV0910_P1_VIT_INUSE 0xf53f00ff ++ ++/*P1_KDIV12*/ ++#define RSTV0910_P1_KDIV12 0xf540 ++#define FSTV0910_P1_KDIV12_MANUAL 0xf5400080 ++#define FSTV0910_P1_K_DIVIDER_12 0xf540007f ++ ++/*P1_KDIV23*/ ++#define RSTV0910_P1_KDIV23 0xf541 ++#define FSTV0910_P1_KDIV23_MANUAL 0xf5410080 ++#define FSTV0910_P1_K_DIVIDER_23 0xf541007f ++ ++/*P1_KDIV34*/ ++#define RSTV0910_P1_KDIV34 0xf542 ++#define FSTV0910_P1_KDIV34_MANUAL 0xf5420080 ++#define FSTV0910_P1_K_DIVIDER_34 0xf542007f ++ ++/*P1_KDIV56*/ ++#define RSTV0910_P1_KDIV56 0xf543 ++#define FSTV0910_P1_KDIV56_MANUAL 0xf5430080 ++#define FSTV0910_P1_K_DIVIDER_56 0xf543007f ++ ++/*P1_KDIV67*/ ++#define RSTV0910_P1_KDIV67 0xf544 ++#define FSTV0910_P1_KDIV67_MANUAL 0xf5440080 ++#define FSTV0910_P1_K_DIVIDER_67 0xf544007f ++ ++/*P1_KDIV78*/ ++#define RSTV0910_P1_KDIV78 0xf545 ++#define FSTV0910_P1_KDIV78_MANUAL 0xf5450080 ++#define FSTV0910_P1_K_DIVIDER_78 0xf545007f ++ ++/*P1_PDELCTRL0*/ ++#define RSTV0910_P1_PDELCTRL0 0xf54f ++#define FSTV0910_P1_ISIOBS_MODE 0xf54f0030 ++#define FSTV0910_P1_PDELDIS_BITWISE 0xf54f0004 ++ ++/*P1_PDELCTRL1*/ ++#define RSTV0910_P1_PDELCTRL1 0xf550 ++#define FSTV0910_P1_INV_MISMASK 0xf5500080 ++#define FSTV0910_P1_FORCE_ACCEPTED 0xf5500040 ++#define FSTV0910_P1_FILTER_EN 0xf5500020 ++#define FSTV0910_P1_FORCE_PKTDELINUSE 0xf5500010 ++#define FSTV0910_P1_HYSTEN 0xf5500008 ++#define FSTV0910_P1_HYSTSWRST 0xf5500004 ++#define FSTV0910_P1_EN_MIS00 0xf5500002 ++#define FSTV0910_P1_ALGOSWRST 0xf5500001 ++ ++/*P1_PDELCTRL2*/ ++#define RSTV0910_P1_PDELCTRL2 0xf551 ++#define FSTV0910_P1_FORCE_CONTINUOUS 0xf5510080 ++#define FSTV0910_P1_RESET_UPKO_COUNT 0xf5510040 ++#define FSTV0910_P1_USER_PKTDELIN_NB 0xf5510020 ++#define FSTV0910_P1_DATA_UNBBSCRAMBLED 0xf5510008 ++#define FSTV0910_P1_FORCE_LONGPKT 0xf5510004 ++#define FSTV0910_P1_FRAME_MODE 0xf5510002 ++ ++/*P1_HYSTTHRESH*/ ++#define RSTV0910_P1_HYSTTHRESH 0xf554 ++#define FSTV0910_P1_DELIN_LOCKTHRES 0xf55400f0 ++#define FSTV0910_P1_DELIN_UNLOCKTHRES 0xf554000f ++ ++/*P1_ISIENTRY*/ ++#define RSTV0910_P1_ISIENTRY 0xf55e ++#define FSTV0910_P1_ISI_ENTRY 0xf55e00ff ++ ++/*P1_ISIBITENA*/ ++#define RSTV0910_P1_ISIBITENA 0xf55f ++#define FSTV0910_P1_ISI_BIT_EN 0xf55f00ff ++ ++/*P1_MATSTR1*/ ++#define RSTV0910_P1_MATSTR1 0xf560 ++#define FSTV0910_P1_MATYPE_CURRENT1 0xf56000ff ++ ++/*P1_MATSTR0*/ ++#define RSTV0910_P1_MATSTR0 0xf561 ++#define FSTV0910_P1_MATYPE_CURRENT0 0xf56100ff ++ ++/*P1_UPLSTR1*/ ++#define RSTV0910_P1_UPLSTR1 0xf562 ++#define FSTV0910_P1_UPL_CURRENT1 0xf56200ff ++ ++/*P1_UPLSTR0*/ ++#define RSTV0910_P1_UPLSTR0 0xf563 ++#define FSTV0910_P1_UPL_CURRENT0 0xf56300ff ++ ++/*P1_DFLSTR1*/ ++#define RSTV0910_P1_DFLSTR1 0xf564 ++#define FSTV0910_P1_DFL_CURRENT1 0xf56400ff ++ ++/*P1_DFLSTR0*/ ++#define RSTV0910_P1_DFLSTR0 0xf565 ++#define FSTV0910_P1_DFL_CURRENT0 0xf56500ff ++ ++/*P1_SYNCSTR*/ ++#define RSTV0910_P1_SYNCSTR 0xf566 ++#define FSTV0910_P1_SYNC_CURRENT 0xf56600ff ++ ++/*P1_SYNCDSTR1*/ ++#define RSTV0910_P1_SYNCDSTR1 0xf567 ++#define FSTV0910_P1_SYNCD_CURRENT1 0xf56700ff ++ ++/*P1_SYNCDSTR0*/ ++#define RSTV0910_P1_SYNCDSTR0 0xf568 ++#define FSTV0910_P1_SYNCD_CURRENT0 0xf56800ff ++ ++/*P1_PDELSTATUS1*/ ++#define RSTV0910_P1_PDELSTATUS1 0xf569 ++#define FSTV0910_P1_PKTDELIN_DELOCK 0xf5690080 ++#define FSTV0910_P1_SYNCDUPDFL_BADDFL 0xf5690040 ++#define FSTV0910_P1_CONTINUOUS_STREAM 0xf5690020 ++#define FSTV0910_P1_UNACCEPTED_STREAM 0xf5690010 ++#define FSTV0910_P1_BCH_ERROR_FLAG 0xf5690008 ++#define FSTV0910_P1_BBHCRCKO 0xf5690004 ++#define FSTV0910_P1_PKTDELIN_LOCK 0xf5690002 ++#define FSTV0910_P1_FIRST_LOCK 0xf5690001 ++ ++/*P1_PDELSTATUS2*/ ++#define RSTV0910_P1_PDELSTATUS2 0xf56a ++#define FSTV0910_P1_PKTDEL_DEMODSEL 0xf56a0080 ++#define FSTV0910_P1_FRAME_MODCOD 0xf56a007c ++#define FSTV0910_P1_FRAME_TYPE 0xf56a0003 ++ ++/*P1_BBFCRCKO1*/ ++#define RSTV0910_P1_BBFCRCKO1 0xf56b ++#define FSTV0910_P1_BBHCRC_KOCNT1 0xf56b00ff ++ ++/*P1_BBFCRCKO0*/ ++#define RSTV0910_P1_BBFCRCKO0 0xf56c ++#define FSTV0910_P1_BBHCRC_KOCNT0 0xf56c00ff ++ ++/*P1_UPCRCKO1*/ ++#define RSTV0910_P1_UPCRCKO1 0xf56d ++#define FSTV0910_P1_PKTCRC_KOCNT1 0xf56d00ff ++ ++/*P1_UPCRCKO0*/ ++#define RSTV0910_P1_UPCRCKO0 0xf56e ++#define FSTV0910_P1_PKTCRC_KOCNT0 0xf56e00ff ++ ++/*P1_PDELCTRL3*/ ++#define RSTV0910_P1_PDELCTRL3 0xf56f ++#define FSTV0910_P1_PKTDEL_CONTFAIL 0xf56f0080 ++#define FSTV0910_P1_PKTDEL_ENLONGPKT 0xf56f0040 ++#define FSTV0910_P1_NOFIFO_BCHERR 0xf56f0020 ++#define FSTV0910_P1_PKTDELIN_DELACMERR 0xf56f0010 ++#define FSTV0910_P1_SATURATE_BBPKTKO 0xf56f0004 ++#define FSTV0910_P1_PKTDEL_BCHERRCONT 0xf56f0002 ++#define FSTV0910_P1_ETHERNET_DISFCS 0xf56f0001 ++ ++/*P1_TSSTATEM*/ ++#define RSTV0910_P1_TSSTATEM 0xf570 ++#define FSTV0910_P1_TSDIL_ON 0xf5700080 ++#define FSTV0910_P1_TSSKIPRS_ON 0xf5700040 ++#define FSTV0910_P1_TSRS_ON 0xf5700020 ++#define FSTV0910_P1_TSDESCRAMB_ON 0xf5700010 ++#define FSTV0910_P1_TSFRAME_MODE 0xf5700008 ++#define FSTV0910_P1_TS_DISABLE 0xf5700004 ++#define FSTV0910_P1_TSACM_MODE 0xf5700002 ++#define FSTV0910_P1_TSOUT_NOSYNC 0xf5700001 ++ ++/*P1_TSCFGH*/ ++#define RSTV0910_P1_TSCFGH 0xf572 ++#define FSTV0910_P1_TSFIFO_DVBCI 0xf5720080 ++#define FSTV0910_P1_TSFIFO_SERIAL 0xf5720040 ++#define FSTV0910_P1_TSFIFO_TEIUPDATE 0xf5720020 ++#define FSTV0910_P1_TSFIFO_DUTY50 0xf5720010 ++#define FSTV0910_P1_TSFIFO_HSGNLOUT 0xf5720008 ++#define FSTV0910_P1_TSFIFO_ERRMODE 0xf5720006 ++#define FSTV0910_P1_RST_HWARE 0xf5720001 ++ ++/*P1_TSCFGM*/ ++#define RSTV0910_P1_TSCFGM 0xf573 ++#define FSTV0910_P1_TSFIFO_MANSPEED 0xf57300c0 ++#define FSTV0910_P1_TSFIFO_PERMDATA 0xf5730020 ++#define FSTV0910_P1_TSFIFO_NONEWSGNL 0xf5730010 ++#define FSTV0910_P1_NPD_SPECDVBS2 0xf5730004 ++#define FSTV0910_P1_TSFIFO_DPUNACTIVE 0xf5730002 ++#define FSTV0910_P1_TSFIFO_INVDATA 0xf5730001 ++ ++/*P1_TSCFGL*/ ++#define RSTV0910_P1_TSCFGL 0xf574 ++#define FSTV0910_P1_TSFIFO_BCLKDEL1CK 0xf57400c0 ++#define FSTV0910_P1_BCHERROR_MODE 0xf5740030 ++#define FSTV0910_P1_TSFIFO_NSGNL2DATA 0xf5740008 ++#define FSTV0910_P1_TSFIFO_EMBINDVB 0xf5740004 ++#define FSTV0910_P1_TSFIFO_BITSPEED 0xf5740003 ++ ++/*P1_TSINSDELH*/ ++#define RSTV0910_P1_TSINSDELH 0xf576 ++#define FSTV0910_P1_TSDEL_SYNCBYTE 0xf5760080 ++#define FSTV0910_P1_TSDEL_XXHEADER 0xf5760040 ++#define FSTV0910_P1_TSDEL_BBHEADER 0xf5760020 ++#define FSTV0910_P1_TSDEL_DATAFIELD 0xf5760010 ++#define FSTV0910_P1_TSINSDEL_ISCR 0xf5760008 ++#define FSTV0910_P1_TSINSDEL_NPD 0xf5760004 ++#define FSTV0910_P1_TSINSDEL_RSPARITY 0xf5760002 ++#define FSTV0910_P1_TSINSDEL_CRC8 0xf5760001 ++ ++/*P1_TSDIVN*/ ++#define RSTV0910_P1_TSDIVN 0xf579 ++#define FSTV0910_P1_TSFIFO_SPEEDMODE 0xf57900c0 ++#define FSTV0910_P1_BYTE_OVERSAMPLING 0xf5790038 ++#define FSTV0910_P1_TSFIFO_RISEOK 0xf5790007 ++ ++/*P1_TSCFG4*/ ++#define RSTV0910_P1_TSCFG4 0xf57a ++#define FSTV0910_P1_TSFIFO_TSSPEEDMODE 0xf57a00c0 ++#define FSTV0910_P1_TSFIFO_HIERSEL 0xf57a0020 ++#define FSTV0910_P1_TSFIFO_SPECTOKEN 0xf57a0010 ++#define FSTV0910_P1_TSFIFO_MAXMODE 0xf57a0008 ++#define FSTV0910_P1_TSFIFO_FRFORCEPKT 0xf57a0004 ++#define FSTV0910_P1_EXT_FECSPYIN 0xf57a0002 ++#define FSTV0910_P1_TSFIFO_DELSPEEDUP 0xf57a0001 ++ ++/*P1_TSSPEED*/ ++#define RSTV0910_P1_TSSPEED 0xf580 ++#define FSTV0910_P1_TSFIFO_OUTSPEED 0xf58000ff ++ ++/*P1_TSSTATUS*/ ++#define RSTV0910_P1_TSSTATUS 0xf581 ++#define FSTV0910_P1_TSFIFO_LINEOK 0xf5810080 ++#define FSTV0910_P1_TSFIFO_ERROR 0xf5810040 ++#define FSTV0910_P1_TSFIFO_DATA7 0xf5810020 ++#define FSTV0910_P1_TSFIFO_NOSYNC 0xf5810010 ++#define FSTV0910_P1_ISCR_INITIALIZED 0xf5810008 ++#define FSTV0910_P1_TSREGUL_ERROR 0xf5810004 ++#define FSTV0910_P1_SOFFIFO_UNREGUL 0xf5810002 ++#define FSTV0910_P1_DIL_READY 0xf5810001 ++ ++/*P1_TSSTATUS2*/ ++#define RSTV0910_P1_TSSTATUS2 0xf582 ++#define FSTV0910_P1_TSFIFO_DEMODSEL 0xf5820080 ++#define FSTV0910_P1_TSFIFOSPEED_STORE 0xf5820040 ++#define FSTV0910_P1_DILXX_RESET 0xf5820020 ++#define FSTV0910_P1_TSSPEED_IMPOSSIBLE 0xf5820010 ++#define FSTV0910_P1_TSFIFO_LINENOK 0xf5820008 ++#define FSTV0910_P1_TSFIFO_MUXSTREAM 0xf5820004 ++#define FSTV0910_P1_SCRAMBDETECT 0xf5820002 ++#define FSTV0910_P1_ULDTV67_FALSELOCK 0xf5820001 ++ ++/*P1_TSBITRATE1*/ ++#define RSTV0910_P1_TSBITRATE1 0xf583 ++#define FSTV0910_P1_TSFIFO_BITRATE1 0xf58300ff ++ ++/*P1_TSBITRATE0*/ ++#define RSTV0910_P1_TSBITRATE0 0xf584 ++#define FSTV0910_P1_TSFIFO_BITRATE0 0xf58400ff ++ ++/*P1_ERRCTRL1*/ ++#define RSTV0910_P1_ERRCTRL1 0xf598 ++#define FSTV0910_P1_ERR_SOURCE1 0xf59800f0 ++#define FSTV0910_P1_NUM_EVENT1 0xf5980007 ++ ++/*P1_ERRCNT12*/ ++#define RSTV0910_P1_ERRCNT12 0xf599 ++#define FSTV0910_P1_ERRCNT1_OLDVALUE 0xf5990080 ++#define FSTV0910_P1_ERR_CNT12 0xf599007f ++ ++/*P1_ERRCNT11*/ ++#define RSTV0910_P1_ERRCNT11 0xf59a ++#define FSTV0910_P1_ERR_CNT11 0xf59a00ff ++ ++/*P1_ERRCNT10*/ ++#define RSTV0910_P1_ERRCNT10 0xf59b ++#define FSTV0910_P1_ERR_CNT10 0xf59b00ff ++ ++/*P1_ERRCTRL2*/ ++#define RSTV0910_P1_ERRCTRL2 0xf59c ++#define FSTV0910_P1_ERR_SOURCE2 0xf59c00f0 ++#define FSTV0910_P1_NUM_EVENT2 0xf59c0007 ++ ++/*P1_ERRCNT22*/ ++#define RSTV0910_P1_ERRCNT22 0xf59d ++#define FSTV0910_P1_ERRCNT2_OLDVALUE 0xf59d0080 ++#define FSTV0910_P1_ERR_CNT22 0xf59d007f ++ ++/*P1_ERRCNT21*/ ++#define RSTV0910_P1_ERRCNT21 0xf59e ++#define FSTV0910_P1_ERR_CNT21 0xf59e00ff ++ ++/*P1_ERRCNT20*/ ++#define RSTV0910_P1_ERRCNT20 0xf59f ++#define FSTV0910_P1_ERR_CNT20 0xf59f00ff ++ ++/*P1_FECSPY*/ ++#define RSTV0910_P1_FECSPY 0xf5a0 ++#define FSTV0910_P1_SPY_ENABLE 0xf5a00080 ++#define FSTV0910_P1_NO_SYNCBYTE 0xf5a00040 ++#define FSTV0910_P1_SERIAL_MODE 0xf5a00020 ++#define FSTV0910_P1_UNUSUAL_PACKET 0xf5a00010 ++#define FSTV0910_P1_BERMETER_DATAMODE 0xf5a0000c ++#define FSTV0910_P1_BERMETER_LMODE 0xf5a00002 ++#define FSTV0910_P1_BERMETER_RESET 0xf5a00001 ++ ++/*P1_FSPYCFG*/ ++#define RSTV0910_P1_FSPYCFG 0xf5a1 ++#define FSTV0910_P1_FECSPY_INPUT 0xf5a100c0 ++#define FSTV0910_P1_RST_ON_ERROR 0xf5a10020 ++#define FSTV0910_P1_ONE_SHOT 0xf5a10010 ++#define FSTV0910_P1_I2C_MODE 0xf5a1000c ++#define FSTV0910_P1_SPY_HYSTERESIS 0xf5a10003 ++ ++/*P1_FSPYDATA*/ ++#define RSTV0910_P1_FSPYDATA 0xf5a2 ++#define FSTV0910_P1_SPY_STUFFING 0xf5a20080 ++#define FSTV0910_P1_NOERROR_PKTJITTER 0xf5a20040 ++#define FSTV0910_P1_SPY_CNULLPKT 0xf5a20020 ++#define FSTV0910_P1_SPY_OUTDATA_MODE 0xf5a2001f ++ ++/*P1_FSPYOUT*/ ++#define RSTV0910_P1_FSPYOUT 0xf5a3 ++#define FSTV0910_P1_FSPY_DIRECT 0xf5a30080 ++#define FSTV0910_P1_SPY_OUTDATA_BUS 0xf5a30038 ++#define FSTV0910_P1_STUFF_MODE 0xf5a30007 ++ ++/*P1_FSTATUS*/ ++#define RSTV0910_P1_FSTATUS 0xf5a4 ++#define FSTV0910_P1_SPY_ENDSIM 0xf5a40080 ++#define FSTV0910_P1_VALID_SIM 0xf5a40040 ++#define FSTV0910_P1_FOUND_SIGNAL 0xf5a40020 ++#define FSTV0910_P1_DSS_SYNCBYTE 0xf5a40010 ++#define FSTV0910_P1_RESULT_STATE 0xf5a4000f ++ ++/*P1_FBERCPT4*/ ++#define RSTV0910_P1_FBERCPT4 0xf5a8 ++#define FSTV0910_P1_FBERMETER_CPT4 0xf5a800ff ++ ++/*P1_FBERCPT3*/ ++#define RSTV0910_P1_FBERCPT3 0xf5a9 ++#define FSTV0910_P1_FBERMETER_CPT3 0xf5a900ff ++ ++/*P1_FBERCPT2*/ ++#define RSTV0910_P1_FBERCPT2 0xf5aa ++#define FSTV0910_P1_FBERMETER_CPT2 0xf5aa00ff ++ ++/*P1_FBERCPT1*/ ++#define RSTV0910_P1_FBERCPT1 0xf5ab ++#define FSTV0910_P1_FBERMETER_CPT1 0xf5ab00ff ++ ++/*P1_FBERCPT0*/ ++#define RSTV0910_P1_FBERCPT0 0xf5ac ++#define FSTV0910_P1_FBERMETER_CPT0 0xf5ac00ff ++ ++/*P1_FBERERR2*/ ++#define RSTV0910_P1_FBERERR2 0xf5ad ++#define FSTV0910_P1_FBERMETER_ERR2 0xf5ad00ff ++ ++/*P1_FBERERR1*/ ++#define RSTV0910_P1_FBERERR1 0xf5ae ++#define FSTV0910_P1_FBERMETER_ERR1 0xf5ae00ff ++ ++/*P1_FBERERR0*/ ++#define RSTV0910_P1_FBERERR0 0xf5af ++#define FSTV0910_P1_FBERMETER_ERR0 0xf5af00ff ++ ++/*P1_FSPYBER*/ ++#define RSTV0910_P1_FSPYBER 0xf5b2 ++#define FSTV0910_P1_FSPYOBS_XORREAD 0xf5b20040 ++#define FSTV0910_P1_FSPYBER_OBSMODE 0xf5b20020 ++#define FSTV0910_P1_FSPYBER_SYNCBYTE 0xf5b20010 ++#define FSTV0910_P1_FSPYBER_UNSYNC 0xf5b20008 ++#define FSTV0910_P1_FSPYBER_CTIME 0xf5b20007 ++ ++/*P1_SFERROR*/ ++#define RSTV0910_P1_SFERROR 0xf5c1 ++#define FSTV0910_P1_SFEC_REGERR_VIT 0xf5c100ff ++ ++/*P1_SFECSTATUS*/ ++#define RSTV0910_P1_SFECSTATUS 0xf5c3 ++#define FSTV0910_P1_SFEC_ON 0xf5c30080 ++#define FSTV0910_P1_SFEC_OFF 0xf5c30040 ++#define FSTV0910_P1_LOCKEDSFEC 0xf5c30008 ++#define FSTV0910_P1_SFEC_DELOCK 0xf5c30004 ++#define FSTV0910_P1_SFEC_DEMODSEL 0xf5c30002 ++#define FSTV0910_P1_SFEC_OVFON 0xf5c30001 ++ ++/*P1_SFKDIV12*/ ++#define RSTV0910_P1_SFKDIV12 0xf5c4 ++#define FSTV0910_P1_SFECKDIV12_MAN 0xf5c40080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_12 0xf5c4007f ++ ++/*P1_SFKDIV23*/ ++#define RSTV0910_P1_SFKDIV23 0xf5c5 ++#define FSTV0910_P1_SFECKDIV23_MAN 0xf5c50080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_23 0xf5c5007f ++ ++/*P1_SFKDIV34*/ ++#define RSTV0910_P1_SFKDIV34 0xf5c6 ++#define FSTV0910_P1_SFECKDIV34_MAN 0xf5c60080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_34 0xf5c6007f ++ ++/*P1_SFKDIV56*/ ++#define RSTV0910_P1_SFKDIV56 0xf5c7 ++#define FSTV0910_P1_SFECKDIV56_MAN 0xf5c70080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_56 0xf5c7007f ++ ++/*P1_SFKDIV67*/ ++#define RSTV0910_P1_SFKDIV67 0xf5c8 ++#define FSTV0910_P1_SFECKDIV67_MAN 0xf5c80080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_67 0xf5c8007f ++ ++/*P1_SFKDIV78*/ ++#define RSTV0910_P1_SFKDIV78 0xf5c9 ++#define FSTV0910_P1_SFECKDIV78_MAN 0xf5c90080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_78 0xf5c9007f ++ ++/*P1_SFSTATUS*/ ++#define RSTV0910_P1_SFSTATUS 0xf5cc ++#define FSTV0910_P1_SFEC_LINEOK 0xf5cc0080 ++#define FSTV0910_P1_SFEC_ERROR 0xf5cc0040 ++#define FSTV0910_P1_SFEC_DATA7 0xf5cc0020 ++#define FSTV0910_P1_SFEC_PKTDNBRFAIL 0xf5cc0010 ++#define FSTV0910_P1_TSSFEC_DEMODSEL 0xf5cc0008 ++#define FSTV0910_P1_SFEC_NOSYNC 0xf5cc0004 ++#define FSTV0910_P1_SFEC_UNREGULA 0xf5cc0002 ++#define FSTV0910_P1_SFEC_READY 0xf5cc0001 ++ ++/*P1_SFDLYSET2*/ ++#define RSTV0910_P1_SFDLYSET2 0xf5d0 ++#define FSTV0910_P1_SFEC_OFFSET 0xf5d000c0 ++#define FSTV0910_P1_RST_SFEC 0xf5d00008 ++#define FSTV0910_P1_DILDLINE_ERROR 0xf5d00004 ++#define FSTV0910_P1_SFEC_DISABLE 0xf5d00002 ++#define FSTV0910_P1_SFEC_UNREGUL 0xf5d00001 ++ ++/*P1_SFERRCTRL*/ ++#define RSTV0910_P1_SFERRCTRL 0xf5d8 ++#define FSTV0910_P1_SFEC_ERR_SOURCE 0xf5d800f0 ++#define FSTV0910_P1_SFEC_NUM_EVENT 0xf5d80007 ++ ++/*P1_SFERRCNT2*/ ++#define RSTV0910_P1_SFERRCNT2 0xf5d9 ++#define FSTV0910_P1_SFERRC_OLDVALUE 0xf5d90080 ++#define FSTV0910_P1_SFEC_ERR_CNT2 0xf5d9007f ++ ++/*P1_SFERRCNT1*/ ++#define RSTV0910_P1_SFERRCNT1 0xf5da ++#define FSTV0910_P1_SFEC_ERR_CNT1 0xf5da00ff ++ ++/*P1_SFERRCNT0*/ ++#define RSTV0910_P1_SFERRCNT0 0xf5db ++#define FSTV0910_P1_SFEC_ERR_CNT0 0xf5db00ff ++ ++/*TSGENERAL*/ ++#define RSTV0910_TSGENERAL 0xf630 ++#define FSTV0910_EN_LGNERROR 0xf6300080 ++#define FSTV0910_TSFIFO_DISTS2PAR 0xf6300040 ++#define FSTV0910_MUXSTREAM_COMPMOSE 0xf6300030 ++#define FSTV0910_MUXSTREAM_OUTMODE 0xf6300008 ++#define FSTV0910_TSFIFO_PERMPARAL 0xf6300006 ++#define FSTV0910_RST_REEDSOLO 0xf6300001 ++ ++/*P1_DISIRQCFG*/ ++#define RSTV0910_P1_DISIRQCFG 0xf700 ++#define FSTV0910_P1_ENRXEND 0xf7000040 ++#define FSTV0910_P1_ENRXFIFO8B 0xf7000020 ++#define FSTV0910_P1_ENTRFINISH 0xf7000010 ++#define FSTV0910_P1_ENTIMEOUT 0xf7000008 ++#define FSTV0910_P1_ENTXEND 0xf7000004 ++#define FSTV0910_P1_ENTXFIFO64B 0xf7000002 ++#define FSTV0910_P1_ENGAPBURST 0xf7000001 ++ ++/*P1_DISIRQSTAT*/ ++#define RSTV0910_P1_DISIRQSTAT 0xf701 ++#define FSTV0910_P1_IRQRXEND 0xf7010040 ++#define FSTV0910_P1_IRQRXFIFO8B 0xf7010020 ++#define FSTV0910_P1_IRQTRFINISH 0xf7010010 ++#define FSTV0910_P1_IRQTIMEOUT 0xf7010008 ++#define FSTV0910_P1_IRQTXEND 0xf7010004 ++#define FSTV0910_P1_IRQTXFIFO64B 0xf7010002 ++#define FSTV0910_P1_IRQGAPBURST 0xf7010001 ++ ++/*P1_DISTXCFG*/ ++#define RSTV0910_P1_DISTXCFG 0xf702 ++#define FSTV0910_P1_DISTX_RESET 0xf7020080 ++#define FSTV0910_P1_TIM_OFF 0xf7020040 ++#define FSTV0910_P1_TIM_CMD 0xf7020030 ++#define FSTV0910_P1_ENVELOP 0xf7020008 ++#define FSTV0910_P1_DIS_PRECHARGE 0xf7020004 ++#define FSTV0910_P1_DISEQC_MODE 0xf7020003 ++ ++/*P1_DISTXSTATUS*/ ++#define RSTV0910_P1_DISTXSTATUS 0xf703 ++#define FSTV0910_P1_TX_FIFO_FULL 0xf7030040 ++#define FSTV0910_P1_TX_IDLE 0xf7030020 ++#define FSTV0910_P1_GAP_BURST 0xf7030010 ++#define FSTV0910_P1_TX_FIFO64B 0xf7030008 ++#define FSTV0910_P1_TX_END 0xf7030004 ++#define FSTV0910_P1_TR_TIMEOUT 0xf7030002 ++#define FSTV0910_P1_TR_FINISH 0xf7030001 ++ ++/*P1_DISTXBYTES*/ ++#define RSTV0910_P1_DISTXBYTES 0xf704 ++#define FSTV0910_P1_TXFIFO_BYTES 0xf70400ff ++ ++/*P1_DISTXFIFO*/ ++#define RSTV0910_P1_DISTXFIFO 0xf705 ++#define FSTV0910_P1_DISEQC_TX_FIFO 0xf70500ff ++ ++/*P1_DISTXF22*/ ++#define RSTV0910_P1_DISTXF22 0xf706 ++#define FSTV0910_P1_F22TX 0xf70600ff ++ ++/*P1_DISTIMEOCFG*/ ++#define RSTV0910_P1_DISTIMEOCFG 0xf708 ++#define FSTV0910_P1_RXCHOICE 0xf7080006 ++#define FSTV0910_P1_TIMEOUT_OFF 0xf7080001 ++ ++/*P1_DISTIMEOUT*/ ++#define RSTV0910_P1_DISTIMEOUT 0xf709 ++#define FSTV0910_P1_TIMEOUT_COUNT 0xf70900ff ++ ++/*P1_DISRXCFG*/ ++#define RSTV0910_P1_DISRXCFG 0xf70a ++#define FSTV0910_P1_DISRX_RESET 0xf70a0080 ++#define FSTV0910_P1_EXTENVELOP 0xf70a0040 ++#define FSTV0910_P1_PINSELECT 0xf70a0038 ++#define FSTV0910_P1_IGNORE_SHORT22K 0xf70a0004 ++#define FSTV0910_P1_SIGNED_RXIN 0xf70a0002 ++#define FSTV0910_P1_DISRX_ON 0xf70a0001 ++ ++/*P1_DISRXSTAT1*/ ++#define RSTV0910_P1_DISRXSTAT1 0xf70b ++#define FSTV0910_P1_RXEND 0xf70b0080 ++#define FSTV0910_P1_RXACTIVE 0xf70b0040 ++#define FSTV0910_P1_RXDETECT 0xf70b0020 ++#define FSTV0910_P1_CONTTONE 0xf70b0010 ++#define FSTV0910_P1_8BFIFOREADY 0xf70b0008 ++#define FSTV0910_P1_FIFOEMPTY 0xf70b0004 ++ ++/*P1_DISRXSTAT0*/ ++#define RSTV0910_P1_DISRXSTAT0 0xf70c ++#define FSTV0910_P1_RXFAIL 0xf70c0080 ++#define FSTV0910_P1_FIFOPFAIL 0xf70c0040 ++#define FSTV0910_P1_RXNONBYTE 0xf70c0020 ++#define FSTV0910_P1_FIFOOVF 0xf70c0010 ++#define FSTV0910_P1_SHORT22K 0xf70c0008 ++#define FSTV0910_P1_RXMSGLOST 0xf70c0004 ++ ++/*P1_DISRXBYTES*/ ++#define RSTV0910_P1_DISRXBYTES 0xf70d ++#define FSTV0910_P1_RXFIFO_BYTES 0xf70d001f ++ ++/*P1_DISRXPARITY1*/ ++#define RSTV0910_P1_DISRXPARITY1 0xf70e ++#define FSTV0910_P1_DISRX_PARITY1 0xf70e00ff ++ ++/*P1_DISRXPARITY0*/ ++#define RSTV0910_P1_DISRXPARITY0 0xf70f ++#define FSTV0910_P1_DISRX_PARITY0 0xf70f00ff ++ ++/*P1_DISRXFIFO*/ ++#define RSTV0910_P1_DISRXFIFO 0xf710 ++#define FSTV0910_P1_DISEQC_RX_FIFO 0xf71000ff ++ ++/*P1_DISRXDC1*/ ++#define RSTV0910_P1_DISRXDC1 0xf711 ++#define FSTV0910_P1_DC_VALUE1 0xf7110103 ++ ++/*P1_DISRXDC0*/ ++#define RSTV0910_P1_DISRXDC0 0xf712 ++#define FSTV0910_P1_DC_VALUE0 0xf71200ff ++ ++/*P1_DISRXF221*/ ++#define RSTV0910_P1_DISRXF221 0xf714 ++#define FSTV0910_P1_F22RX1 0xf714000f ++ ++/*P1_DISRXF220*/ ++#define RSTV0910_P1_DISRXF220 0xf715 ++#define FSTV0910_P1_F22RX0 0xf71500ff ++ ++/*P1_DISRXF100*/ ++#define RSTV0910_P1_DISRXF100 0xf716 ++#define FSTV0910_P1_F100RX 0xf71600ff ++ ++/*P1_DISRXSHORT22K*/ ++#define RSTV0910_P1_DISRXSHORT22K 0xf71c ++#define FSTV0910_P1_SHORT22K_LENGTH 0xf71c001f ++ ++/*P1_ACRPRESC*/ ++#define RSTV0910_P1_ACRPRESC 0xf71e ++#define FSTV0910_P1_ACR_CODFRDY 0xf71e0008 ++#define FSTV0910_P1_ACR_PRESC 0xf71e0007 ++ ++/*P1_ACRDIV*/ ++#define RSTV0910_P1_ACRDIV 0xf71f ++#define FSTV0910_P1_ACR_DIV 0xf71f00ff ++ ++/*P2_DISIRQCFG*/ ++#define RSTV0910_P2_DISIRQCFG 0xf740 ++#define FSTV0910_P2_ENRXEND 0xf7400040 ++#define FSTV0910_P2_ENRXFIFO8B 0xf7400020 ++#define FSTV0910_P2_ENTRFINISH 0xf7400010 ++#define FSTV0910_P2_ENTIMEOUT 0xf7400008 ++#define FSTV0910_P2_ENTXEND 0xf7400004 ++#define FSTV0910_P2_ENTXFIFO64B 0xf7400002 ++#define FSTV0910_P2_ENGAPBURST 0xf7400001 ++ ++/*P2_DISIRQSTAT*/ ++#define RSTV0910_P2_DISIRQSTAT 0xf741 ++#define FSTV0910_P2_IRQRXEND 0xf7410040 ++#define FSTV0910_P2_IRQRXFIFO8B 0xf7410020 ++#define FSTV0910_P2_IRQTRFINISH 0xf7410010 ++#define FSTV0910_P2_IRQTIMEOUT 0xf7410008 ++#define FSTV0910_P2_IRQTXEND 0xf7410004 ++#define FSTV0910_P2_IRQTXFIFO64B 0xf7410002 ++#define FSTV0910_P2_IRQGAPBURST 0xf7410001 ++ ++/*P2_DISTXCFG*/ ++#define RSTV0910_P2_DISTXCFG 0xf742 ++#define FSTV0910_P2_DISTX_RESET 0xf7420080 ++#define FSTV0910_P2_TIM_OFF 0xf7420040 ++#define FSTV0910_P2_TIM_CMD 0xf7420030 ++#define FSTV0910_P2_ENVELOP 0xf7420008 ++#define FSTV0910_P2_DIS_PRECHARGE 0xf7420004 ++#define FSTV0910_P2_DISEQC_MODE 0xf7420003 ++ ++/*P2_DISTXSTATUS*/ ++#define RSTV0910_P2_DISTXSTATUS 0xf743 ++#define FSTV0910_P2_TX_FIFO_FULL 0xf7430040 ++#define FSTV0910_P2_TX_IDLE 0xf7430020 ++#define FSTV0910_P2_GAP_BURST 0xf7430010 ++#define FSTV0910_P2_TX_FIFO64B 0xf7430008 ++#define FSTV0910_P2_TX_END 0xf7430004 ++#define FSTV0910_P2_TR_TIMEOUT 0xf7430002 ++#define FSTV0910_P2_TR_FINISH 0xf7430001 ++ ++/*P2_DISTXBYTES*/ ++#define RSTV0910_P2_DISTXBYTES 0xf744 ++#define FSTV0910_P2_TXFIFO_BYTES 0xf74400ff ++ ++/*P2_DISTXFIFO*/ ++#define RSTV0910_P2_DISTXFIFO 0xf745 ++#define FSTV0910_P2_DISEQC_TX_FIFO 0xf74500ff ++ ++/*P2_DISTXF22*/ ++#define RSTV0910_P2_DISTXF22 0xf746 ++#define FSTV0910_P2_F22TX 0xf74600ff ++ ++/*P2_DISTIMEOCFG*/ ++#define RSTV0910_P2_DISTIMEOCFG 0xf748 ++#define FSTV0910_P2_RXCHOICE 0xf7480006 ++#define FSTV0910_P2_TIMEOUT_OFF 0xf7480001 ++ ++/*P2_DISTIMEOUT*/ ++#define RSTV0910_P2_DISTIMEOUT 0xf749 ++#define FSTV0910_P2_TIMEOUT_COUNT 0xf74900ff ++ ++/*P2_DISRXCFG*/ ++#define RSTV0910_P2_DISRXCFG 0xf74a ++#define FSTV0910_P2_DISRX_RESET 0xf74a0080 ++#define FSTV0910_P2_EXTENVELOP 0xf74a0040 ++#define FSTV0910_P2_PINSELECT 0xf74a0038 ++#define FSTV0910_P2_IGNORE_SHORT22K 0xf74a0004 ++#define FSTV0910_P2_SIGNED_RXIN 0xf74a0002 ++#define FSTV0910_P2_DISRX_ON 0xf74a0001 ++ ++/*P2_DISRXSTAT1*/ ++#define RSTV0910_P2_DISRXSTAT1 0xf74b ++#define FSTV0910_P2_RXEND 0xf74b0080 ++#define FSTV0910_P2_RXACTIVE 0xf74b0040 ++#define FSTV0910_P2_RXDETECT 0xf74b0020 ++#define FSTV0910_P2_CONTTONE 0xf74b0010 ++#define FSTV0910_P2_8BFIFOREADY 0xf74b0008 ++#define FSTV0910_P2_FIFOEMPTY 0xf74b0004 ++ ++/*P2_DISRXSTAT0*/ ++#define RSTV0910_P2_DISRXSTAT0 0xf74c ++#define FSTV0910_P2_RXFAIL 0xf74c0080 ++#define FSTV0910_P2_FIFOPFAIL 0xf74c0040 ++#define FSTV0910_P2_RXNONBYTE 0xf74c0020 ++#define FSTV0910_P2_FIFOOVF 0xf74c0010 ++#define FSTV0910_P2_SHORT22K 0xf74c0008 ++#define FSTV0910_P2_RXMSGLOST 0xf74c0004 ++ ++/*P2_DISRXBYTES*/ ++#define RSTV0910_P2_DISRXBYTES 0xf74d ++#define FSTV0910_P2_RXFIFO_BYTES 0xf74d001f ++ ++/*P2_DISRXPARITY1*/ ++#define RSTV0910_P2_DISRXPARITY1 0xf74e ++#define FSTV0910_P2_DISRX_PARITY1 0xf74e00ff ++ ++/*P2_DISRXPARITY0*/ ++#define RSTV0910_P2_DISRXPARITY0 0xf74f ++#define FSTV0910_P2_DISRX_PARITY0 0xf74f00ff ++ ++/*P2_DISRXFIFO*/ ++#define RSTV0910_P2_DISRXFIFO 0xf750 ++#define FSTV0910_P2_DISEQC_RX_FIFO 0xf75000ff ++ ++/*P2_DISRXDC1*/ ++#define RSTV0910_P2_DISRXDC1 0xf751 ++#define FSTV0910_P2_DC_VALUE1 0xf7510103 ++ ++/*P2_DISRXDC0*/ ++#define RSTV0910_P2_DISRXDC0 0xf752 ++#define FSTV0910_P2_DC_VALUE0 0xf75200ff ++ ++/*P2_DISRXF221*/ ++#define RSTV0910_P2_DISRXF221 0xf754 ++#define FSTV0910_P2_F22RX1 0xf754000f ++ ++/*P2_DISRXF220*/ ++#define RSTV0910_P2_DISRXF220 0xf755 ++#define FSTV0910_P2_F22RX0 0xf75500ff ++ ++/*P2_DISRXF100*/ ++#define RSTV0910_P2_DISRXF100 0xf756 ++#define FSTV0910_P2_F100RX 0xf75600ff ++ ++/*P2_DISRXSHORT22K*/ ++#define RSTV0910_P2_DISRXSHORT22K 0xf75c ++#define FSTV0910_P2_SHORT22K_LENGTH 0xf75c001f ++ ++/*P2_ACRPRESC*/ ++#define RSTV0910_P2_ACRPRESC 0xf75e ++#define FSTV0910_P2_ACR_CODFRDY 0xf75e0008 ++#define FSTV0910_P2_ACR_PRESC 0xf75e0007 ++ ++/*P2_ACRDIV*/ ++#define RSTV0910_P2_ACRDIV 0xf75f ++#define FSTV0910_P2_ACR_DIV 0xf75f00ff ++ ++/*P1_NBITER_NF4*/ ++#define RSTV0910_P1_NBITER_NF4 0xfa03 ++#define FSTV0910_P1_NBITER_NF_QPSK_1_2 0xfa0300ff ++ ++/*P1_NBITER_NF5*/ ++#define RSTV0910_P1_NBITER_NF5 0xfa04 ++#define FSTV0910_P1_NBITER_NF_QPSK_3_5 0xfa0400ff ++ ++/*P1_NBITER_NF6*/ ++#define RSTV0910_P1_NBITER_NF6 0xfa05 ++#define FSTV0910_P1_NBITER_NF_QPSK_2_3 0xfa0500ff ++ ++/*P1_NBITER_NF7*/ ++#define RSTV0910_P1_NBITER_NF7 0xfa06 ++#define FSTV0910_P1_NBITER_NF_QPSK_3_4 0xfa0600ff ++ ++/*P1_NBITER_NF8*/ ++#define RSTV0910_P1_NBITER_NF8 0xfa07 ++#define FSTV0910_P1_NBITER_NF_QPSK_4_5 0xfa0700ff ++ ++/*P1_NBITER_NF9*/ ++#define RSTV0910_P1_NBITER_NF9 0xfa08 ++#define FSTV0910_P1_NBITER_NF_QPSK_5_6 0xfa0800ff ++ ++/*P1_NBITER_NF10*/ ++#define RSTV0910_P1_NBITER_NF10 0xfa09 ++#define FSTV0910_P1_NBITER_NF_QPSK_8_9 0xfa0900ff ++ ++/*P1_NBITER_NF11*/ ++#define RSTV0910_P1_NBITER_NF11 0xfa0a ++#define FSTV0910_P1_NBITER_NF_QPSK_9_10 0xfa0a00ff ++ ++/*P1_NBITER_NF12*/ ++#define RSTV0910_P1_NBITER_NF12 0xfa0b ++#define FSTV0910_P1_NBITER_NF_8PSK_3_5 0xfa0b00ff ++ ++/*P1_NBITER_NF13*/ ++#define RSTV0910_P1_NBITER_NF13 0xfa0c ++#define FSTV0910_P1_NBITER_NF_8PSK_2_3 0xfa0c00ff ++ ++/*P1_NBITER_NF14*/ ++#define RSTV0910_P1_NBITER_NF14 0xfa0d ++#define FSTV0910_P1_NBITER_NF_8PSK_3_4 0xfa0d00ff ++ ++/*P1_NBITER_NF15*/ ++#define RSTV0910_P1_NBITER_NF15 0xfa0e ++#define FSTV0910_P1_NBITER_NF_8PSK_5_6 0xfa0e00ff ++ ++/*P1_NBITER_NF16*/ ++#define RSTV0910_P1_NBITER_NF16 0xfa0f ++#define FSTV0910_P1_NBITER_NF_8PSK_8_9 0xfa0f00ff ++ ++/*P1_NBITER_NF17*/ ++#define RSTV0910_P1_NBITER_NF17 0xfa10 ++#define FSTV0910_P1_NBITER_NF_8PSK_9_10 0xfa1000ff ++ ++/*GAINLLR_NF4*/ ++#define RSTV0910_GAINLLR_NF4 0xfa43 ++#define FSTV0910_GAINLLR_NF_QPSK_1_2 0xfa43007f ++ ++/*GAINLLR_NF5*/ ++#define RSTV0910_GAINLLR_NF5 0xfa44 ++#define FSTV0910_GAINLLR_NF_QPSK_3_5 0xfa44007f ++ ++/*GAINLLR_NF6*/ ++#define RSTV0910_GAINLLR_NF6 0xfa45 ++#define FSTV0910_GAINLLR_NF_QPSK_2_3 0xfa45007f ++ ++/*GAINLLR_NF7*/ ++#define RSTV0910_GAINLLR_NF7 0xfa46 ++#define FSTV0910_GAINLLR_NF_QPSK_3_4 0xfa46007f ++ ++/*GAINLLR_NF8*/ ++#define RSTV0910_GAINLLR_NF8 0xfa47 ++#define FSTV0910_GAINLLR_NF_QPSK_4_5 0xfa47007f ++ ++/*GAINLLR_NF9*/ ++#define RSTV0910_GAINLLR_NF9 0xfa48 ++#define FSTV0910_GAINLLR_NF_QPSK_5_6 0xfa48007f ++ ++/*GAINLLR_NF10*/ ++#define RSTV0910_GAINLLR_NF10 0xfa49 ++#define FSTV0910_GAINLLR_NF_QPSK_8_9 0xfa49007f ++ ++/*GAINLLR_NF11*/ ++#define RSTV0910_GAINLLR_NF11 0xfa4a ++#define FSTV0910_GAINLLR_NF_QPSK_9_10 0xfa4a007f ++ ++/*GAINLLR_NF12*/ ++#define RSTV0910_GAINLLR_NF12 0xfa4b ++#define FSTV0910_GAINLLR_NF_8PSK_3_5 0xfa4b007f ++ ++/*GAINLLR_NF13*/ ++#define RSTV0910_GAINLLR_NF13 0xfa4c ++#define FSTV0910_GAINLLR_NF_8PSK_2_3 0xfa4c007f ++ ++/*GAINLLR_NF14*/ ++#define RSTV0910_GAINLLR_NF14 0xfa4d ++#define FSTV0910_GAINLLR_NF_8PSK_3_4 0xfa4d007f ++ ++/*GAINLLR_NF15*/ ++#define RSTV0910_GAINLLR_NF15 0xfa4e ++#define FSTV0910_GAINLLR_NF_8PSK_5_6 0xfa4e007f ++ ++/*GAINLLR_NF16*/ ++#define RSTV0910_GAINLLR_NF16 0xfa4f ++#define FSTV0910_GAINLLR_NF_8PSK_8_9 0xfa4f007f ++ ++/*GAINLLR_NF17*/ ++#define RSTV0910_GAINLLR_NF17 0xfa50 ++#define FSTV0910_GAINLLR_NF_8PSK_9_10 0xfa50007f ++ ++/*CFGEXT*/ ++#define RSTV0910_CFGEXT 0xfa80 ++#define FSTV0910_BYPFIFOBCH 0xfa800080 ++#define FSTV0910_BYPBCH 0xfa800040 ++#define FSTV0910_BYPLDPC 0xfa800020 ++#define FSTV0910_BYPFIFOBCHF 0xfa800010 ++#define FSTV0910_INVLLRSIGN 0xfa800008 ++#define FSTV0910_SHORTMULT 0xfa800004 ++#define FSTV0910_ENSTOPDEC 0xfa800002 ++ ++/*GENCFG*/ ++#define RSTV0910_GENCFG 0xfa86 ++#define FSTV0910_LEG_ITER 0xfa860040 ++#define FSTV0910_NOSHFRD1 0xfa860020 ++#define FSTV0910_BROADCAST 0xfa860010 ++#define FSTV0910_NOSHFRD2 0xfa860008 ++#define FSTV0910_BCHERRFLAG 0xfa860004 ++#define FSTV0910_CROSSINPUT 0xfa860002 ++#define FSTV0910_DDEMOD 0xfa860001 ++ ++/*LDPCERR1*/ ++#define RSTV0910_LDPCERR1 0xfa96 ++#define FSTV0910_LDPC_ERRORS1 0xfa9600ff ++ ++/*LDPCERR0*/ ++#define RSTV0910_LDPCERR0 0xfa97 ++#define FSTV0910_LDPC_ERRORS0 0xfa9700ff ++ ++/*BCHERR*/ ++#define RSTV0910_BCHERR 0xfa98 ++#define FSTV0910_ERRORFLAG 0xfa980010 ++#define FSTV0910_BCH_ERRORS_COUNTER 0xfa98000f ++ ++/*P1_MAXEXTRAITER*/ ++#define RSTV0910_P1_MAXEXTRAITER 0xfab1 ++#define FSTV0910_P1_MAX_EXTRA_ITER 0xfab100ff ++ ++/*P2_MAXEXTRAITER*/ ++#define RSTV0910_P2_MAXEXTRAITER 0xfab6 ++#define FSTV0910_P2_MAX_EXTRA_ITER 0xfab600ff ++ ++/*P1_STATUSITER*/ ++#define RSTV0910_P1_STATUSITER 0xfabc ++#define FSTV0910_P1_STATUS_ITER 0xfabc00ff ++ ++/*P1_STATUSMAXITER*/ ++#define RSTV0910_P1_STATUSMAXITER 0xfabd ++#define FSTV0910_P1_STATUS_MAX_ITER 0xfabd00ff ++ ++/*P2_STATUSITER*/ ++#define RSTV0910_P2_STATUSITER 0xfabe ++#define FSTV0910_P2_STATUS_ITER 0xfabe00ff ++ ++/*P2_STATUSMAXITER*/ ++#define RSTV0910_P2_STATUSMAXITER 0xfabf ++#define FSTV0910_P2_STATUS_MAX_ITER 0xfabf00ff ++ ++/*P2_NBITER_NF4*/ ++#define RSTV0910_P2_NBITER_NF4 0xfac3 ++#define FSTV0910_P2_NBITER_NF_QPSK_1_2 0xfac300ff ++ ++/*P2_NBITER_NF5*/ ++#define RSTV0910_P2_NBITER_NF5 0xfac4 ++#define FSTV0910_P2_NBITER_NF_QPSK_3_5 0xfac400ff ++ ++/*P2_NBITER_NF6*/ ++#define RSTV0910_P2_NBITER_NF6 0xfac5 ++#define FSTV0910_P2_NBITER_NF_QPSK_2_3 0xfac500ff ++ ++/*P2_NBITER_NF7*/ ++#define RSTV0910_P2_NBITER_NF7 0xfac6 ++#define FSTV0910_P2_NBITER_NF_QPSK_3_4 0xfac600ff ++ ++/*P2_NBITER_NF8*/ ++#define RSTV0910_P2_NBITER_NF8 0xfac7 ++#define FSTV0910_P2_NBITER_NF_QPSK_4_5 0xfac700ff ++ ++/*P2_NBITER_NF9*/ ++#define RSTV0910_P2_NBITER_NF9 0xfac8 ++#define FSTV0910_P2_NBITER_NF_QPSK_5_6 0xfac800ff ++ ++/*P2_NBITER_NF10*/ ++#define RSTV0910_P2_NBITER_NF10 0xfac9 ++#define FSTV0910_P2_NBITER_NF_QPSK_8_9 0xfac900ff ++ ++/*P2_NBITER_NF11*/ ++#define RSTV0910_P2_NBITER_NF11 0xfaca ++#define FSTV0910_P2_NBITER_NF_QPSK_9_10 0xfaca00ff ++ ++/*P2_NBITER_NF12*/ ++#define RSTV0910_P2_NBITER_NF12 0xfacb ++#define FSTV0910_P2_NBITER_NF_8PSK_3_5 0xfacb00ff ++ ++/*P2_NBITER_NF13*/ ++#define RSTV0910_P2_NBITER_NF13 0xfacc ++#define FSTV0910_P2_NBITER_NF_8PSK_2_3 0xfacc00ff ++ ++/*P2_NBITER_NF14*/ ++#define RSTV0910_P2_NBITER_NF14 0xfacd ++#define FSTV0910_P2_NBITER_NF_8PSK_3_4 0xfacd00ff ++ ++/*P2_NBITER_NF15*/ ++#define RSTV0910_P2_NBITER_NF15 0xface ++#define FSTV0910_P2_NBITER_NF_8PSK_5_6 0xface00ff ++ ++/*P2_NBITER_NF16*/ ++#define RSTV0910_P2_NBITER_NF16 0xfacf ++#define FSTV0910_P2_NBITER_NF_8PSK_8_9 0xfacf00ff ++ ++/*P2_NBITER_NF17*/ ++#define RSTV0910_P2_NBITER_NF17 0xfad0 ++#define FSTV0910_P2_NBITER_NF_8PSK_9_10 0xfad000ff ++ ++/*TSTRES0*/ ++#define RSTV0910_TSTRES0 0xff11 ++#define FSTV0910_FRESFEC 0xff110080 ++#define FSTV0910_FRESTS 0xff110040 ++#define FSTV0910_FRESVIT1 0xff110020 ++#define FSTV0910_FRESVIT2 0xff110010 ++#define FSTV0910_FRESSYM1 0xff110008 ++#define FSTV0910_FRESSYM2 0xff110004 ++#define FSTV0910_FRESMAS 0xff110002 ++#define FSTV0910_FRESINT 0xff110001 ++ ++/*P2_TCTL4*/ ++#define RSTV0910_P2_TCTL4 0xff28 ++#define FSTV0910_P2_CFR2TOCFR1_DVBS1 0xff2800c0 ++#define FSTV0910_P2_TSTINV_PHERR 0xff280020 ++#define FSTV0910_P2_EN_PLHCALC 0xff280010 ++#define FSTV0910_P2_TETA3L_RSTTETA3D 0xff280008 ++#define FSTV0910_P2_DIS_FORCEBETA2 0xff280004 ++#define FSTV0910_P2_CAR3_NOTRACEBACK 0xff280002 ++#define FSTV0910_P2_CAR3_NOFORWARD 0xff280001 ++ ++/*P1_TCTL4*/ ++#define RSTV0910_P1_TCTL4 0xff48 ++#define FSTV0910_P1_CFR2TOCFR1_DVBS1 0xff4800c0 ++#define FSTV0910_P1_TSTINV_PHERR 0xff480020 ++#define FSTV0910_P1_EN_PLHCALC 0xff480010 ++#define FSTV0910_P1_TETA3L_RSTTETA3D 0xff480008 ++#define FSTV0910_P1_DIS_FORCEBETA2 0xff480004 ++#define FSTV0910_P1_CAR3_NOTRACEBACK 0xff480002 ++#define FSTV0910_P1_CAR3_NOFORWARD 0xff480001 ++ ++#define STV0910_NBREGS 735 ++#define STV0910_NBFIELDS 1776 ++ +diff --git a/drivers/media/dvb-frontends/tas2101.c b/drivers/media/dvb-frontends/tas2101.c +new file mode 100644 +index 0000000..6e6d0b8 +--- /dev/null ++++ b/drivers/media/dvb-frontends/tas2101.c +@@ -0,0 +1,897 @@ ++/* ++ Tmax TAS2101 - DVBS/S2 Satellite demodulator driver ++ ++ Copyright (C) 2014 Luis Alves ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++ ++#include "tas2101.h" ++#include "tas2101_priv.h" ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) ++#if IS_ENABLED(CONFIG_I2C_MUX) ++#define TAS2101_USE_I2C_MUX ++#endif ++#endif ++ ++/* return i2c adapter */ ++/* bus = 0 master */ ++/* bus = 1 demod */ ++/* bus = 2 tuner */ ++struct i2c_adapter *tas2101_get_i2c_adapter(struct dvb_frontend *fe, int bus) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ switch (bus) { ++ case 0: ++ default: ++ return priv->i2c; ++ case 1: ++ return priv->i2c_demod; ++ case 2: ++ return priv->i2c_tuner; ++ } ++} ++EXPORT_SYMBOL_GPL(tas2101_get_i2c_adapter); ++ ++/* write multiple (continuous) registers */ ++/* the first value is the starting address */ ++static int tas2101_wrm(struct tas2101_priv *priv, u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg = { ++ .addr = priv->cfg->i2c_address, ++ .flags = 0, .buf = buf, .len = len }; ++ ++ dev_dbg(&priv->i2c->dev, "%s() i2c wrm @0x%02x (len=%d)\n", ++ __func__, buf[0], len); ++ ++ ret = i2c_transfer(priv->i2c_demod, &msg, 1); ++ if (ret < 0) { ++ dev_warn(&priv->i2c->dev, ++ "%s: i2c wrm err(%i) @0x%02x (len=%d)\n", ++ KBUILD_MODNAME, ret, buf[0], len); ++ return ret; ++ } ++ return 0; ++} ++ ++/* write one register */ ++static int tas2101_wr(struct tas2101_priv *priv, u8 addr, u8 data) ++{ ++ u8 buf[] = { addr, data }; ++ return tas2101_wrm(priv, buf, 2); ++} ++ ++/* read multiple (continuous) registers starting at addr */ ++static int tas2101_rdm(struct tas2101_priv *priv, u8 addr, u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg[] = { ++ { .addr = priv->cfg->i2c_address, .flags = 0, ++ .buf = &addr, .len = 1 }, ++ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, ++ .buf = buf, .len = len } ++ }; ++ ++ dev_dbg(&priv->i2c->dev, "%s() i2c rdm @0x%02x (len=%d)\n", ++ __func__, addr, len); ++ ++ ret = i2c_transfer(priv->i2c_demod, msg, 2); ++ if (ret < 0) { ++ dev_warn(&priv->i2c->dev, ++ "%s: i2c rdm err(%i) @0x%02x (len=%d)\n", ++ KBUILD_MODNAME, ret, addr, len); ++ return ret; ++ } ++ return 0; ++} ++ ++/* read one register */ ++static int tas2101_rd(struct tas2101_priv *priv, u8 addr, u8 *data) ++{ ++ return tas2101_rdm(priv, addr, data, 1); ++} ++ ++static int tas2101_regmask(struct tas2101_priv *priv, ++ u8 reg, u8 setmask, u8 clrmask) ++{ ++ int ret; ++ u8 b = 0; ++ if (clrmask != 0xff) { ++ ret = tas2101_rd(priv, reg, &b); ++ if (ret) ++ return ret; ++ b &= ~clrmask; ++ } ++ return tas2101_wr(priv, reg, b | setmask); ++} ++ ++static int tas2101_wrtable(struct tas2101_priv *priv, ++ struct tas2101_regtable *regtable, int len) ++{ ++ int ret, i; ++ ++ for (i = 0; i < len; i++) { ++ ret = tas2101_regmask(priv, regtable[i].addr, ++ regtable[i].setmask, regtable[i].clrmask); ++ if (ret) ++ return ret; ++ if (regtable[i].sleep) ++ msleep(regtable[i].sleep); ++ } ++ return 0; ++} ++ ++static int tas2101_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ u8 buf[4]; ++ ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ switch (c->delivery_system) { ++ case SYS_DVBS: ++ ret = tas2101_rdm(priv, S1_BER_0, buf, 4); ++ if (ret) ++ return ret; ++ ++ *ber = ((((u32) buf[3] & 3) << 24) | (((u32) buf[2]) << 16) ++ | (((u32) buf[1]) << 8) | ((u32) buf[0])); ++ break; ++ ++ case SYS_DVBS2: ++ ret = tas2101_rdm(priv, S2_BER_0, buf, 2); ++ if (ret) ++ return ret; ++ ++ *ber = ((((u32) buf[1]) << 8) | ((u32) buf[0])); ++ break; ++ ++ default: ++ *ber = 0; ++ break; ++ } ++ ++ dev_dbg(&priv->i2c->dev, "%s() ber = %d\n", __func__, *ber); ++ return 0; ++} ++ ++static int tas2101_read_signal_strength(struct dvb_frontend *fe, ++ u16 *signal_strength) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret, i; ++ long val, dbm_raw; ++ u8 buf[2]; ++ ++ ret = tas2101_rdm(priv, SIGSTR_0, buf, 2); ++ if (ret) ++ return ret; ++ ++ dbm_raw = (((u16)buf[1] & 0x0f) << 8) | buf[0]; ++ ++ for (i = 0; i < ARRAY_SIZE(tas2101_dbmtable) - 1; i++) ++ if (tas2101_dbmtable[i].raw < dbm_raw) ++ break; ++ ++ if( i == 0 ) ++ *signal_strength = tas2101_dbmtable[i].dbm; ++ else ++ { ++ /* linear interpolation between two calibrated values */ ++ val = (dbm_raw - tas2101_dbmtable[i].raw) * tas2101_dbmtable[i-1].dbm; ++ val += (tas2101_dbmtable[i-1].raw - dbm_raw) * tas2101_dbmtable[i].dbm; ++ val /= (tas2101_dbmtable[i-1].raw - tas2101_dbmtable[i].raw); ++ ++ *signal_strength = (u16)val; ++ } ++ ++ dev_dbg(&priv->i2c->dev, "%s() strength = 0x%04x\n", ++ __func__, *signal_strength); ++ return 0; ++} ++ ++static int tas2101_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i; ++ long val; ++ u16 snr_raw; ++ u8 buf[2]; ++ ++ ret = tas2101_rdm(priv, SNR_0, buf, 2); ++ if (ret) ++ return ret; ++ ++ snr_raw = (((u16)buf[1] & 0x0f) << 8) | buf[0]; ++ ++ for (i = 0; i < ARRAY_SIZE(tas2101_snrtable) - 1; i++) ++ if (tas2101_snrtable[i].raw < snr_raw) ++ break; ++ ++ if( i == 0 ) ++ val = tas2101_snrtable[i].snr; ++ else ++ { ++ /* linear interpolation between two calibrated values */ ++ val = (snr_raw - tas2101_snrtable[i].raw) * tas2101_snrtable[i-1].snr; ++ val += (tas2101_snrtable[i-1].raw - snr_raw) * tas2101_snrtable[i].snr; ++ val /= (tas2101_snrtable[i-1].raw - tas2101_snrtable[i].raw); ++ } ++ ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ c->cnr.stat[0].uvalue = 100 * (s64) val; ++ ++ *snr = (u16) val * 328; /* 20dB = 100% */ ++ ++ dev_dbg(&priv->i2c->dev, "%s() snr = 0x%04x\n", ++ __func__, *snr); ++ ++ return 0; ++} ++ ++/* unimplemented */ ++static int tas2101_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ *ucblocks = 0; ++ return 0; ++} ++ ++static int tas2101_read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret; ++ u8 reg; ++ u16 snr; ++ ++ *status = 0; ++ ++ ret = tas2101_rd(priv, DEMOD_STATUS, ®); ++ if (ret) ++ return ret; ++ ++ reg &= DEMOD_STATUS_MASK; ++ if (reg == DEMOD_LOCKED) { ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ ++ ret = tas2101_rd(priv, REG_04, ®); ++ if (ret) ++ return ret; ++ if (reg & 0x08) ++ ret = tas2101_wr(priv, REG_04, reg & ~0x08); ++ ++ tas2101_read_snr(fe, &snr); ++ } ++ ++ dev_dbg(&priv->i2c->dev, "%s() status = 0x%02x\n", __func__, *status); ++ return ret; ++} ++ ++static int tas2101_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret = 0; ++ ++ dev_dbg(&priv->i2c->dev, "%s() %s\n", __func__, ++ voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : ++ voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : ++ "SEC_VOLTAGE_OFF"); ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ if (priv->cfg->lnb_power) ++ priv->cfg->lnb_power(fe, LNB_ON); ++ ret = tas2101_regmask(priv, LNB_CTRL, ++ 0, VSEL13_18); ++ break; ++ case SEC_VOLTAGE_18: ++ if (priv->cfg->lnb_power) ++ priv->cfg->lnb_power(fe, LNB_ON); ++ ret = tas2101_regmask(priv, LNB_CTRL, ++ VSEL13_18, 0); ++ break; ++ default: /* OFF */ ++ if (priv->cfg->lnb_power) ++ priv->cfg->lnb_power(fe, LNB_OFF); ++ break; ++ } ++ return ret; ++} ++ ++static int tas2101_set_tone(struct dvb_frontend *fe, ++ enum fe_sec_tone_mode tone) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret = -EINVAL; ++ ++ dev_dbg(&priv->i2c->dev, "%s() %s\n", __func__, ++ tone == SEC_TONE_ON ? "SEC_TONE_ON" : "SEC_TONE_OFF"); ++ ++ switch (tone) { ++ case SEC_TONE_ON: ++ ret = tas2101_regmask(priv, LNB_CTRL, ++ TONE_ON, DISEQC_CMD_MASK); ++ break; ++ case SEC_TONE_OFF: ++ ret = tas2101_regmask(priv, LNB_CTRL, ++ TONE_OFF, DISEQC_CMD_MASK); ++ break; ++ default: ++ dev_warn(&priv->i2c->dev, "%s() invalid tone (%d)\n", ++ __func__, tone); ++ break; ++ } ++ return ret; ++} ++ ++static int tas2101_send_diseqc_msg(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *d) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret, i; ++ u8 bck, buf[9]; ++ ++ /* dump DiSEqC message */ ++ dev_dbg(&priv->i2c->dev, "%s() ( ", __func__); ++ for (i = 0; i < d->msg_len; i++) ++ dev_dbg(&priv->i2c->dev, "0x%02x ", d->msg[i]); ++ dev_dbg(&priv->i2c->dev, ")\n"); ++ ++ /* backup LNB tone state */ ++ ret = tas2101_rd(priv, LNB_CTRL, &bck); ++ if (ret) ++ return ret; ++ ++ ret = tas2101_regmask(priv, REG_34, 0, 0x40); ++ if (ret) ++ goto exit; ++ ++ /* setup DISEqC message to demod */ ++ buf[0] = DISEQC_BUFFER; ++ memcpy(&buf[1], d->msg, 8); ++ ret = tas2101_wrm(priv, buf, d->msg_len + 1); ++ if (ret) ++ goto exit; ++ ++ /* send DISEqC send command */ ++ buf[0] = (bck & ~(DISEQC_CMD_LEN_MASK | DISEQC_CMD_MASK)) | ++ DISEQC_SEND_MSG | ((d->msg_len - 1) << 3); ++ ret = tas2101_wr(priv, LNB_CTRL, buf[0]); ++ if (ret) ++ goto exit; ++ ++ /* wait at least diseqc typical tx time */ ++ msleep(54); ++ ++ /* Wait for busy flag to clear */ ++ for (i = 0; i < 10; i++) { ++ ret = tas2101_rd(priv, LNB_STATUS, &buf[0]); ++ if (ret) ++ break; ++ if (buf[0] & DISEQC_BUSY) ++ goto exit; ++ msleep(20); ++ } ++ ++ /* try to restore the tone setting but return a timeout error */ ++ ret = tas2101_wr(priv, LNB_CTRL, bck); ++ dev_warn(&priv->i2c->dev, "%s() timeout sending burst\n", __func__); ++ return -ETIMEDOUT; ++exit: ++ /* restore tone setting */ ++ return tas2101_wr(priv, LNB_CTRL, bck); ++} ++ ++static int tas2101_diseqc_send_burst(struct dvb_frontend *fe, ++ enum fe_sec_mini_cmd burst) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret, i; ++ u8 bck, r; ++ ++ if ((burst != SEC_MINI_A) && (burst != SEC_MINI_B)) { ++ dev_err(&priv->i2c->dev, "%s() invalid burst(%d)\n", ++ __func__, burst); ++ return -EINVAL; ++ } ++ ++ dev_dbg(&priv->i2c->dev, "%s() %s\n", __func__, ++ burst == SEC_MINI_A ? "SEC_MINI_A" : "SEC_MINI_B"); ++ ++ /* backup LNB tone state */ ++ ret = tas2101_rd(priv, LNB_CTRL, &bck); ++ if (ret) ++ return ret; ++ ++ ret = tas2101_regmask(priv, REG_34, 0, 0x40); ++ if (ret) ++ goto exit; ++ ++ /* set tone burst cmd */ ++ r = (bck & ~DISEQC_CMD_MASK) | ++ (burst == SEC_MINI_A) ? DISEQC_BURST_A : DISEQC_BURST_B; ++ ++ ret = tas2101_wr(priv, LNB_CTRL, r); ++ if (ret) ++ goto exit; ++ ++ /* spec = around 12.5 ms for the burst */ ++ for (i = 0; i < 10; i++) { ++ ret = tas2101_rd(priv, LNB_STATUS, &r); ++ if (ret) ++ break; ++ if (r & DISEQC_BUSY) ++ goto exit; ++ msleep(20); ++ } ++ ++ /* try to restore the tone setting but return a timeout error */ ++ ret = tas2101_wr(priv, LNB_CTRL, bck); ++ dev_warn(&priv->i2c->dev, "%s() timeout sending burst\n", __func__); ++ return -ETIMEDOUT; ++exit: ++ /* restore tone setting */ ++ return tas2101_wr(priv, LNB_CTRL, bck); ++} ++ ++static void tas2101_release(struct dvb_frontend *fe) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ ++ dev_dbg(&priv->i2c->dev, "%s\n", __func__); ++#ifdef TAS2101_USE_I2C_MUX ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ i2c_mux_del_adapters(priv->muxc); ++#else ++ i2c_del_mux_adapter(priv->i2c_demod); ++ i2c_del_mux_adapter(priv->i2c_tuner); ++#endif ++#endif ++ kfree(priv); ++} ++ ++#ifdef TAS2101_USE_I2C_MUX ++/* channel 0: demod */ ++/* channel 1: tuner */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++static int tas2101_i2c_select(struct i2c_mux_core *muxc, u32 chan_id) ++{ ++ struct tas2101_priv *priv = i2c_mux_priv(muxc); ++ struct i2c_adapter *adap = priv->i2c; ++#else ++static int tas2101_i2c_select(struct i2c_adapter *adap, ++ void *mux_priv, u32 chan_id) ++{ ++ struct tas2101_priv *priv = mux_priv; ++#endif ++ int ret; ++ u8 buf[2]; ++ struct i2c_msg msg_wr[] = { ++ { .addr = priv->cfg->i2c_address, .flags = 0, ++ .buf = buf, .len = 2 } ++ }; ++ struct i2c_msg msg_rd[] = { ++ { .addr = priv->cfg->i2c_address, .flags = 0, ++ .buf = &buf[0], .len = 1 }, ++ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, ++ .buf = &buf[1], .len = 1 } ++ }; ++ ++ dev_dbg(&priv->i2c->dev, "%s() ch=%d\n", __func__, chan_id); ++ ++ if (priv->i2c_ch == chan_id) ++ return 0; ++ ++ buf[0] = REG_06; ++ ret = __i2c_transfer(adap, msg_rd, 2); ++ if (ret != 2) ++ goto err; ++ ++ if (chan_id == 0) ++ buf[1] &= ~I2C_GATE; ++ else ++ buf[1] |= I2C_GATE; ++ ++ ret = __i2c_transfer(adap, msg_wr, 1); ++ if (ret != 1) ++ goto err; ++ ++ priv->i2c_ch = chan_id; ++ ++ return 0; ++err: ++ dev_dbg(&priv->i2c->dev, "%s() failed=%d\n", __func__, ret); ++ return -EREMOTEIO; ++} ++#endif ++ ++static struct dvb_frontend_ops tas2101_ops; ++ ++struct dvb_frontend *tas2101_attach(const struct tas2101_config *cfg, ++ struct i2c_adapter *i2c) ++{ ++ struct tas2101_priv *priv = NULL; ++ int ret; ++ u8 id[2]; ++ ++ dev_dbg(&i2c->dev, "%s: Attaching frontend\n", KBUILD_MODNAME); ++ ++ /* allocate memory for the priv data */ ++ priv = kzalloc(sizeof(struct tas2101_priv), GFP_KERNEL); ++ if (priv == NULL) ++ goto err; ++ ++ priv->cfg = cfg; ++ priv->i2c = i2c; ++ priv->i2c_ch = 0; ++ ++#ifdef TAS2101_USE_I2C_MUX ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ /* create mux i2c adapter for tuner */ ++ priv->muxc = i2c_mux_alloc(i2c, &i2c->dev, ++ 2, 0, I2C_MUX_LOCKED, ++ tas2101_i2c_select, NULL); ++ if (!priv->muxc) { ++ ret = -ENOMEM; ++ goto err1; ++ } ++ priv->muxc->priv = priv; ++ ret = i2c_mux_add_adapter(priv->muxc, 0, 0, 0); ++ if (ret) ++ goto err1; ++ ret = i2c_mux_add_adapter(priv->muxc, 0, 1, 0); ++ if (ret) ++ goto err1; ++ priv->i2c_demod = priv->muxc->adapter[0]; ++ priv->i2c_tuner = priv->muxc->adapter[1]; ++#else ++ /* create muxed i2c adapter for the demod */ ++ priv->i2c_demod = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0, ++ tas2101_i2c_select, NULL); ++ if (priv->i2c_demod == NULL) ++ goto err1; ++ ++ /* create muxed i2c adapter for the tuner */ ++ priv->i2c_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 1, 0, ++ tas2101_i2c_select, NULL); ++ if (priv->i2c_tuner == NULL) ++ goto err2; ++#endif ++#else ++ priv->i2c_demod = i2c; ++ priv->i2c_tuner = i2c; ++#endif ++ ++ /* create dvb_frontend */ ++ memcpy(&priv->fe.ops, &tas2101_ops, ++ sizeof(struct dvb_frontend_ops)); ++ priv->fe.demodulator_priv = priv; ++ ++ /* reset demod */ ++ if (cfg->reset_demod) ++ cfg->reset_demod(&priv->fe); ++ ++ msleep(100); ++ ++ /* check if demod is alive */ ++ ret = tas2101_rdm(priv, ID_0, id, 2); ++ if ((id[0] != 0x44) || (id[1] != 0x4c)) ++ ret |= -EIO; ++ if (ret) ++ goto err3; ++ ++ return &priv->fe; ++ ++err3: ++#ifdef TAS2101_USE_I2C_MUX ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ i2c_mux_del_adapters(priv->muxc); ++#else ++ i2c_del_mux_adapter(priv->i2c_tuner); ++err2: ++ i2c_del_mux_adapter(priv->i2c_demod); ++#endif ++#endif ++err1: ++ kfree(priv); ++err: ++ dev_err(&i2c->dev, "%s: Error attaching frontend\n", KBUILD_MODNAME); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(tas2101_attach); ++ ++static int tas2101_initfe(struct dvb_frontend *fe) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ struct tas2101_regtable *t; ++ u8 buf[7], size; ++ int ret; ++ ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ if (priv->cfg->id == ID_TAS2101) { ++ t = tas2101_initfe0; ++ size = ARRAY_SIZE(tas2101_initfe0); ++ } else { ++ t = tas2100_initfe0; ++ size = ARRAY_SIZE(tas2100_initfe0); ++ } ++ ret = tas2101_wrtable(priv, t, size); ++ if (ret) ++ return ret; ++ ++ buf[0] = 0xe6; ++ memcpy(&buf[1], priv->cfg->init, 6); ++ ret = tas2101_wrm(priv, buf, 7); ++ if (ret) ++ return ret; ++ ++ ret = tas2101_regmask(priv, 0xe0, priv->cfg->init[6], 0xff); ++ if (ret) ++ return ret; ++ ++ if (priv->cfg->id == ID_TAS2101) { ++ t = tas2101_initfe1; ++ size = ARRAY_SIZE(tas2101_initfe1); ++ } else { ++ t = tas2100_initfe1; ++ size = ARRAY_SIZE(tas2100_initfe1); ++ } ++ ret = tas2101_wrtable(priv, t, size); ++ if (ret) ++ return ret; ++ ++ if (priv->cfg->init2) { ++ t = tas2101_initfe2; ++ size = ARRAY_SIZE(tas2101_initfe2); ++ ret = tas2101_wrtable(priv, t, size); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int tas2101_sleep(struct dvb_frontend *fe) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ return 0; ++} ++ ++static int tas2101_set_frontend(struct dvb_frontend *fe) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ enum fe_status tunerstat; ++ int ret, i; ++ u32 s; ++ u8 buf[3]; ++ ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ /* do some basic parameter validation */ ++ switch (c->delivery_system) { ++ case SYS_DVBS: ++ dev_dbg(&priv->i2c->dev, "%s() DVB-S\n", __func__); ++ /* Only QPSK is supported for DVB-S */ ++ if (c->modulation != QPSK) { ++ dev_dbg(&priv->i2c->dev, ++ "%s() unsupported modulation (%d)\n", ++ __func__, c->modulation); ++ return -EINVAL; ++ } ++ break; ++ case SYS_DVBS2: ++ dev_dbg(&priv->i2c->dev, "%s() DVB-S2\n", __func__); ++ break; ++ default: ++ dev_warn(&priv->i2c->dev, ++ "%s() unsupported delivery system (%d)\n", ++ __func__, c->delivery_system); ++ return -EINVAL; ++ } ++ ++ ret = tas2101_wrtable(priv, tas2101_setfe, ARRAY_SIZE(tas2101_setfe)); ++ if (ret) ++ return ret; ++ ++ /* set symbol rate */ ++ s = c->symbol_rate / 1000; ++ buf[0] = SET_SRATE0; ++ buf[1] = (u8) s; ++ buf[2] = (u8) (s >> 8); ++ ret = tas2101_wrm(priv, buf, 3); ++ if (ret) ++ return ret; ++ ++ /* clear freq offset */ ++ buf[0] = FREQ_OS0; ++ buf[1] = 0; ++ buf[2] = 0; ++ ret = tas2101_wrm(priv, buf, 3); ++ if (ret) ++ return ret; ++ ++ if (fe->ops.tuner_ops.set_params) { ++#ifndef TAS2101_USE_I2C_MUX ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++#endif ++ fe->ops.tuner_ops.set_params(fe); ++#ifndef TAS2101_USE_I2C_MUX ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++#endif ++ } ++ ++ ret = tas2101_regmask(priv, REG_30, 0x01, 0); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i<15; i++) { ++ ret = tas2101_read_status(fe, &tunerstat); ++ if (tunerstat & FE_HAS_LOCK) ++ return 0; ++ msleep(20); ++ } ++ return -EINVAL; ++} ++ ++static int tas2101_get_frontend(struct dvb_frontend *fe, ++ struct dtv_frontend_properties *c) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret; ++ u8 reg, buf[2]; ++ ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ ret = tas2101_rd(priv, MODFEC_0, ®); ++ if (ret) ++ return ret; ++ ++ if ((reg >> 6) == 0) { ++ /* DVB-S */ ++ reg &= 0x07; ++ } else { ++ /* DVB-S2 */ ++ ret = tas2101_rd(priv, MODFEC_1, ®); ++ if (ret) ++ return ret; ++ reg += 5; ++ } ++ ++ if (reg > 33) { ++ dev_dbg(&priv->i2c->dev, "%s() Unable to get current delivery" ++ " system and mode.\n", __func__); ++ reg = 0; ++ } ++ ++ c->fec_inner = tas2101_modfec_modes[reg].fec; ++ c->modulation = tas2101_modfec_modes[reg].modulation; ++ c->delivery_system = tas2101_modfec_modes[reg].delivery_system; ++ c->inversion = INVERSION_AUTO; ++ ++ /* symbol rate */ ++ ret = tas2101_rdm(priv, GET_SRATE0, buf, 2); ++ if (ret) ++ return ret; ++ c->symbol_rate = ((buf[1] << 8) | buf[0]) * 1000; ++ ++ return 0; ++} ++ ++static int tas2101_tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, unsigned int *delay, enum fe_status *status) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ *delay = HZ / 5; ++ if (re_tune) { ++ int ret = tas2101_set_frontend(fe); ++ if (ret) ++ return ret; ++ } ++ return tas2101_read_status(fe, status); ++} ++ ++static int tas2101_get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++#ifndef TAS2101_USE_I2C_MUX ++static int tas2101_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) ++{ ++ struct tas2101_priv *priv = fe->demodulator_priv; ++ int ret; ++ ++ if (enable) ++ ret = tas2101_regmask(priv, REG_06, I2C_GATE, 0); ++ else ++ ret = tas2101_regmask(priv, REG_06, 0, I2C_GATE); ++ ++ return ret; ++} ++#endif ++ ++static struct dvb_frontend_ops tas2101_ops = { ++ .delsys = { SYS_DVBS, SYS_DVBS2 }, ++ .info = { ++ .name = "Tmax TAS2101", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = FE_CAN_INVERSION_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | ++ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_2G_MODULATION | ++ FE_CAN_QPSK | FE_CAN_RECOVER ++ }, ++ .release = tas2101_release, ++ ++ .init = tas2101_initfe, ++ .sleep = tas2101_sleep, ++#ifndef TAS2101_USE_I2C_MUX ++ .i2c_gate_ctrl = tas2101_i2c_gate_ctrl, ++#endif ++ .read_status = tas2101_read_status, ++ .read_ber = tas2101_read_ber, ++ .read_signal_strength = tas2101_read_signal_strength, ++ .read_snr = tas2101_read_snr, ++ .read_ucblocks = tas2101_read_ucblocks, ++ ++ .set_tone = tas2101_set_tone, ++ .set_voltage = tas2101_set_voltage, ++ .diseqc_send_master_cmd = tas2101_send_diseqc_msg, ++ .diseqc_send_burst = tas2101_diseqc_send_burst, ++ .get_frontend_algo = tas2101_get_algo, ++ .tune = tas2101_tune, ++ ++ .set_frontend = tas2101_set_frontend, ++ .get_frontend = tas2101_get_frontend, ++ ++}; ++ ++MODULE_DESCRIPTION("DVB Frontend module for Tmax TAS2101"); ++MODULE_AUTHOR("Luis Alves (ljalvs@gmail.com)"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0"); ++ +diff --git a/drivers/media/dvb-frontends/tas2101.h b/drivers/media/dvb-frontends/tas2101.h +new file mode 100644 +index 0000000..c2fcf65 +--- /dev/null ++++ b/drivers/media/dvb-frontends/tas2101.h +@@ -0,0 +1,70 @@ ++/* ++ Tmax TAS2101 - DVBS/S2 Satellite demod/tuner driver ++ ++ Copyright (C) 2014 Luis Alves ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef TAS2101_H ++#define TAS2101_H ++ ++#include ++#include ++ ++typedef enum tas210x_id { ++ ID_TAS2100, ++ ID_TAS2101, ++} tas210x_id_t; ++ ++struct tas2101_config { ++ /* demodulator i2c address */ ++ u8 i2c_address; ++ ++ /* chip id */ ++ tas210x_id_t id; ++ ++ /* demod hard reset */ ++ void (*reset_demod)(struct dvb_frontend *fe); ++ /* lnb power */ ++ void (*lnb_power)(struct dvb_frontend *fe, int onoff); ++ ++ /* frontend gpio/tuner init */ ++ u8 init[7]; ++ u8 init2; ++}; ++ ++ ++ ++#if IS_ENABLED(CONFIG_DVB_TAS2101) ++extern struct dvb_frontend *tas2101_attach( ++ const struct tas2101_config *cfg, ++ struct i2c_adapter *i2c); ++struct i2c_adapter *tas2101_get_i2c_adapter(struct dvb_frontend *fe, int bus); ++#else ++static inline struct dvb_frontend *tas2101_attach( ++ const struct tas2101_config *cfg, ++ struct i2c_adapter *i2c) ++{ ++ dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++struct i2c_adapter *tas2101_get_i2c_adapter(struct dvb_frontend *fe, int bus) ++{ ++ return NULL; ++} ++#endif ++ ++#endif /* TAS2101_H */ +diff --git a/drivers/media/dvb-frontends/tas2101_priv.h b/drivers/media/dvb-frontends/tas2101_priv.h +new file mode 100644 +index 0000000..79ed06b +--- /dev/null ++++ b/drivers/media/dvb-frontends/tas2101_priv.h +@@ -0,0 +1,325 @@ ++/* ++ Tmas TAS2101 - DVBS/S2 Satellite demod/tuner driver ++ ++ Copyright (C) 2014 Luis Alves ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef TAS2101_PRIV_H ++#define TAS2101_PRIV_H ++ ++struct tas2101_priv { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ struct i2c_mux_core *muxc; ++#endif ++ /* master i2c adapter */ ++ struct i2c_adapter *i2c; ++ /* muxed i2c adapter for the demod */ ++ struct i2c_adapter *i2c_demod; ++ /* muxed i2c adapter for the tuner */ ++ struct i2c_adapter *i2c_tuner; ++ ++ int i2c_ch; ++ ++ struct dvb_frontend fe; ++ const struct tas2101_config *cfg; ++}; ++ ++/* demod registers */ ++enum tas2101_reg_addr { ++ ID_0 = 0x00, ++ ID_1 = 0x01, ++ REG_04 = 0x04, ++ REG_06 = 0x06, ++ LNB_CTRL = 0x10, ++ LNB_STATUS = 0x16, ++ DISEQC_BUFFER = 0x20, ++ REG_30 = 0x30, ++ DEMOD_STATUS = 0x31, ++ REG_34 = 0x34, ++ SIGSTR_0 = 0x42, ++ SIGSTR_1 = 0x43, ++ GET_SRATE0 = 0x5c, ++ GET_SRATE1 = 0x5d, ++ SET_SRATE0 = 0x73, ++ SET_SRATE1 = 0x74, ++ FREQ_OS0 = 0x75, ++ FREQ_OS1 = 0x76, ++ SNR_0 = 0x92, ++ SNR_1 = 0x93, ++ S1_BER_0 = 0xd1, ++ S1_BER_1 = 0xd2, ++ S1_BER_2 = 0xd3, ++ S1_BER_3 = 0xd4, ++ S2_BER_0 = 0xec, ++ S2_BER_1 = 0xed, ++ MODFEC_0 = 0xee, ++ MODFEC_1 = 0xef, ++}; ++ ++#define I2C_GATE 0x80 ++ ++#define VSEL13_18 0x40 ++#define DISEQC_CMD_LEN_MASK 0x38 ++#define DISEQC_CMD_MASK 0x07 ++ ++ ++ ++enum tas2101_diseqc_cmd { ++ TONE_OFF = 0x00, ++ TONE_ON = 0x01, ++ DISEQC_BURST_A = 0x02, ++ DISEQC_BURST_B = 0x03, ++ DISEQC_SEND_MSG = 0x04, ++}; ++ ++#define DISEQC_BUSY 0x10 ++ ++#define DEMOD_STATUS_MASK 0x75 ++#define DEMOD_LOCKED 0x75 ++ ++ ++enum tas2101_lnb_power { ++ LNB_OFF = 0, ++ LNB_ON = 1, ++}; ++ ++struct tas2101_regtable { ++ u8 addr; ++ u8 setmask; ++ u8 clrmask; ++ int sleep; ++}; ++ ++static struct tas2101_regtable tas2101_initfe0[] = { ++ {REG_30, 0x02, 0x00, 0}, ++ {0x56, 0x00, 0x02, 0}, ++ {0x05, 0x04, 0x00, 0}, ++ {0x05, 0x00, 0x04, 60}, ++ {0x08, 0x80, 0x00, 0}, ++ {0x09, 0x3b, 0xff, 0}, ++ {0x08, 0x00, 0x80, 60}, ++ {0x0a, 0x80, 0x00, 0}, ++ {0x0b, 0x47, 0xff, 0}, ++ {0x0a, 0x00, 0x80, 40}, ++ {0x03, 0xa9, 0xff, 40}, ++ {0x0e, 0x05, 0xff, 0}, ++ {0x0f, 0x06, 0xff, 40}, ++ {0x70, 0x82, 0xff, 0}, ++ {0x71, 0x8b, 0xff, 0}, ++ {0x72, 0x01, 0xff, 0}, ++ {0x0d, 0x00, 0xc0, 40}, ++ {0x0d, 0xc0, 0x00, 0}, ++}; ++ ++static struct tas2101_regtable tas2100_initfe0[] = { ++ {REG_30, 0x02, 0x00, 0}, ++ {0x08, 0x00, 0x80, 60}, ++ {0x0b, 0x55, 0xff, 0}, ++ {0x0a, 0x00, 0x80, 40}, ++ {0x0e, 0x04, 0xff, 0}, ++ {0x0f, 0x05, 0xff, 40}, ++ {0x70, 0x98, 0xff, 0}, ++ {0x71, 0x66, 0xff, 0}, ++ {0x72, 0x01, 0xff, 0}, ++ {0x0d, 0x00, 0xc0, 40}, ++ {0x0d, 0xc0, 0x00, 0}, ++}; ++ ++static struct tas2101_regtable tas2101_initfe1[] = { ++/* {0xe0, 0x33, 0xff, 0}, depends on tsmode ( 0xb1 tsmode=1 ) */ ++ {0x56, 0x81, 0x00, 0}, ++ {0x05, 0x00, 0x08, 0}, ++ {0x36, 0x00, 0x40, 0}, ++ {0x91, 0x00, 0xf0, 0}, ++ {0x35, 0x75, 0xff, 0}, ++ {REG_04, 0x00, 0x80, 0}, ++ {0x0d, 0x80, 0x00, 0}, ++ {0x30, 0x01, 0x00, 0}, ++ {0x05, 0x00, 0x80, 0}, ++ {REG_06, 0, I2C_GATE, 0}, ++ {0x41, 0x1c, 0x3f, 0}, ++ {0x46, 0xdc, 0xff, 0}, ++ {0x11, 0x7f, 0xff, 0}, ++ {0x12, 0x04, 0x07, 0}, ++ {0x1f, 0x00, 0x01, 0}, ++ {REG_34, 0x00, 0x40, 0}, ++ {0xd0, 0x05, 0x7f, 0}, ++ {0xe3, 0x02, 0x03, 0}, ++ {0x58, 0x60, 0xe0, 0}, ++ {0x50, 0x64, 0xff, 0}, ++ {0x9e, 0x08, 0x3f, 0}, ++ {0x9d, 0x07, 0x00, 0}, ++ {0x49, 0xa0, 0xf0, 0}, ++ {0x87, 0x70, 0xf0, 0}, ++ {0x90, 0x04, 0xff, 0}, ++ {0x9d, 0x07, 0x00, 0}, ++ {0x9e, 0x20, 0x3f, 0}, ++ {REG_06, 0x00, 0x1f, 0}, ++ {0x46, 0x18, 0x1f, 0}, ++ {0x40, 0x04, 0x07, 0}, ++}; ++ ++ ++static struct tas2101_regtable tas2101_initfe2[] = { ++ {0xfa, 0x01, 0x03, 0}, ++ {0xfb, 0x02, 0xff, 0}, ++}; ++ ++static struct tas2101_regtable tas2100_initfe1[] = { ++ {0x56, 0x81, 0x00, 0}, ++ {0x05, 0x00, 0x08, 0}, ++ {0x36, 0x00, 0x40, 0}, ++ {0x91, 0x22, 0xff, 0}, ++ {0x35, 0x75, 0xff, 0}, ++ {REG_04, 0x30, 0xff, 0}, ++ {0x30, 0x01, 0x00, 0}, ++ {0x05, 0x00, 0x80, 0}, ++ {REG_06, 0, I2C_GATE, 0}, ++ {0x41, 0x1c, 0x3f, 0}, ++ {0x46, 0xdc, 0xff, 0}, ++ {0x11, 0x13, 0xff, 0}, ++ {0x12, 0x04, 0x07, 0}, ++ {REG_34, 0x00, 0x40, 0}, ++ {0xd0, 0x05, 0x7f, 0}, ++ {0xe3, 0x02, 0x03, 0}, ++ {0x58, 0x60, 0xe0, 0}, ++ {0x50, 0x64, 0xff, 0}, ++ {0x9e, 0x20, 0x3f, 0}, ++ {0x9d, 0x07, 0x00, 0}, ++ {0x49, 0x90, 0xf0, 0}, ++ {0x87, 0xd0, 0xf0, 0}, ++ {0x90, 0x10, 0xff, 0}, ++ {0x9d, 0x07, 0x00, 0}, ++ {0x9e, 0x20, 0x3f, 0}, ++ {REG_06, 0x00, 0x1f, 0}, ++}; ++ ++static struct tas2101_regtable tas2101_setfe[] = { ++ {REG_04, 0x08, 0x00, 0}, ++ {0x36, 0x01, 0x00, 0}, ++ {0x56, 0x01, 0x81, 0}, ++ {0x05, 0x08, 0x00, 0}, ++ {0x36, 0x40, 0x00, 0}, ++ {0x58, 0x60, 0xe0, 0}, ++}; ++ ++struct tas2101_snrtable_pair { ++ u16 snr; ++ u16 raw; ++}; ++ ++static struct tas2101_snrtable_pair tas2101_snrtable[] = { ++ {10, 0x65a}, /* 1.0 dB */ ++ {20, 0x50c}, ++ {30, 0x402}, ++ {40, 0x32f}, ++ {50, 0x287}, ++ {60, 0x202}, ++ {70, 0x198}, ++ {80, 0x144}, ++ {90, 0x100}, ++ {100, 0xcc}, ++ {110, 0xa2}, ++ {120, 0x81}, ++ {130, 0x66}, ++ {140, 0x51}, ++ {150, 0x40}, ++ {160, 0x33}, ++ {170, 0x28}, ++ {180, 0x20}, ++ {190, 0x19}, ++ {200, 0x14}, ++ {210, 0x10}, ++ {220, 0xc}, ++ {230, 0xa}, ++ {240, 0x8}, ++ {250, 0x6}, ++ {260, 0x5}, ++ {270, 0x4}, ++ {280, 0x3}, ++ {300, 0x2}, ++ {330, 0x1}, /* 33.0 dB */ ++ {0, 0} ++}; ++ ++struct tas2101_dbmtable_pair { ++ u16 dbm; ++ u16 raw; ++}; ++ ++static struct tas2101_dbmtable_pair tas2101_dbmtable[] = { ++ { 0x3333, 0xfff}, /* 20% */ ++ { 0x4CCC, 0x778}, ++ { 0x6666, 0x621}, ++ { 0x7FFF, 0x55c}, ++ { 0x9999, 0x40e}, ++ { 0xB332, 0x343}, ++ { 0xCCCC, 0x2b7}, ++ { 0xE665, 0x231}, ++ { 0xFFFF, 0x1a1}, /* 100% */ ++ {0, 0} ++}; ++ ++/* modfec (modulation and FEC) lookup table */ ++struct tas2101_modfec { ++ enum fe_delivery_system delivery_system; ++ enum fe_modulation modulation; ++ enum fe_code_rate fec; ++}; ++ ++static struct tas2101_modfec tas2101_modfec_modes[] = { ++ { SYS_DVBS, QPSK, FEC_AUTO }, ++ { SYS_DVBS, QPSK, FEC_1_2 }, ++ { SYS_DVBS, QPSK, FEC_2_3 }, ++ { SYS_DVBS, QPSK, FEC_3_4 }, ++ { SYS_DVBS, QPSK, FEC_4_5 }, ++ { SYS_DVBS, QPSK, FEC_5_6 }, ++ { SYS_DVBS, QPSK, FEC_6_7 }, ++ { SYS_DVBS, QPSK, FEC_7_8 }, ++ { SYS_DVBS, QPSK, FEC_8_9 }, ++ ++ { SYS_DVBS2, QPSK, FEC_1_2 }, ++ { SYS_DVBS2, QPSK, FEC_3_5 }, ++ { SYS_DVBS2, QPSK, FEC_2_3 }, ++ { SYS_DVBS2, QPSK, FEC_3_4 }, ++ { SYS_DVBS2, QPSK, FEC_4_5 }, ++ { SYS_DVBS2, QPSK, FEC_5_6 }, ++ { SYS_DVBS2, QPSK, FEC_8_9 }, ++ { SYS_DVBS2, QPSK, FEC_9_10 }, ++ ++ { SYS_DVBS2, PSK_8, FEC_3_5 }, ++ { SYS_DVBS2, PSK_8, FEC_2_3 }, ++ { SYS_DVBS2, PSK_8, FEC_3_4 }, ++ { SYS_DVBS2, PSK_8, FEC_5_6 }, ++ { SYS_DVBS2, PSK_8, FEC_8_9 }, ++ { SYS_DVBS2, PSK_8, FEC_9_10 }, ++ ++ { SYS_DVBS2, APSK_16, FEC_2_3 }, ++ { SYS_DVBS2, APSK_16, FEC_3_4 }, ++ { SYS_DVBS2, APSK_16, FEC_4_5 }, ++ { SYS_DVBS2, APSK_16, FEC_5_6 }, ++ { SYS_DVBS2, APSK_16, FEC_8_9 }, ++ { SYS_DVBS2, APSK_16, FEC_9_10 }, ++ ++ { SYS_DVBS2, APSK_32, FEC_3_4 }, ++ { SYS_DVBS2, APSK_32, FEC_4_5 }, ++ { SYS_DVBS2, APSK_32, FEC_5_6 }, ++ { SYS_DVBS2, APSK_32, FEC_8_9 }, ++ { SYS_DVBS2, APSK_32, FEC_9_10 }, ++}; ++ ++#endif /* TAS2101_PRIV_H */ +diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig +index da28e68..f6bbdb2 100644 +--- a/drivers/media/pci/Kconfig ++++ b/drivers/media/pci/Kconfig +@@ -36,6 +36,7 @@ source "drivers/media/pci/bt8xx/Kconfig" + source "drivers/media/pci/saa7134/Kconfig" + source "drivers/media/pci/saa7164/Kconfig" + source "drivers/media/pci/cobalt/Kconfig" ++source "drivers/media/pci/saa716x/Kconfig" + + endif + +@@ -52,6 +53,7 @@ source "drivers/media/pci/ngene/Kconfig" + source "drivers/media/pci/ddbridge/Kconfig" + source "drivers/media/pci/smipcie/Kconfig" + source "drivers/media/pci/netup_unidvb/Kconfig" ++source "drivers/media/pci/tbsecp3/Kconfig" + endif + + endif #MEDIA_PCI_SUPPORT +diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile +index a7e8af0..43d5896 100644 +--- a/drivers/media/pci/Makefile ++++ b/drivers/media/pci/Makefile +@@ -13,7 +13,8 @@ obj-y += ttpci/ \ + ddbridge/ \ + saa7146/ \ + smipcie/ \ +- netup_unidvb/ ++ netup_unidvb/ \ ++ tbsecp3/ + + obj-$(CONFIG_VIDEO_IVTV) += ivtv/ + obj-$(CONFIG_VIDEO_ZORAN) += zoran/ +@@ -24,6 +25,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/ + obj-$(CONFIG_VIDEO_BT848) += bt8xx/ + obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ + obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ ++obj-$(CONFIG_SAA716X_CORE) += saa716x/ + obj-$(CONFIG_VIDEO_TW68) += tw68/ + obj-$(CONFIG_VIDEO_TW686X) += tw686x/ + obj-$(CONFIG_VIDEO_DT3155) += dt3155/ +diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c +index 589a168..ae27b3d 100644 +--- a/drivers/media/pci/cx23885/cx23885-dvb.c ++++ b/drivers/media/pci/cx23885/cx23885-dvb.c +@@ -511,6 +511,7 @@ static struct cx24116_config tbs_cx24116_config = { + + static struct cx24117_config tbs_cx24117_config = { + .demod_address = 0x55, ++ .lnb_power = NULL, + }; + + static struct ds3000_config tevii_ds3000_config = { +diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c +index cdfbde2..6303938 100644 +--- a/drivers/media/pci/cx88/cx88-cards.c ++++ b/drivers/media/pci/cx88/cx88-cards.c +@@ -2079,6 +2079,19 @@ static const struct cx88_board cx88_boards[] = { + } }, + .mpeg = CX88_MPEG_DVB, + }, ++ [CX88_BOARD_TBS_8922] = { ++ .name = "TBS 8922 DVB-S/S2", ++ .tuner_type = UNSET, ++ .radio_type = UNSET, ++ .tuner_addr = ADDR_UNSET, ++ .radio_addr = ADDR_UNSET, ++ .input = { { ++ .type = CX88_VMUX_DVB, ++ .vmux = 0, ++ .gpio0 = 0x4343, ++ } }, ++ .mpeg = CX88_MPEG_DVB, ++ }, + [CX88_BOARD_PROF_6200] = { + .name = "Prof 6200 DVB-S", + .tuner_type = UNSET, +@@ -2727,6 +2740,11 @@ static const struct cx88_subid cx88_subids[] = { + .subdevice = 0x8888, + .card = CX88_BOARD_TBS_8920, + }, { ++ }, { ++ .subvendor = 0x8922, ++ .subdevice = 0x8888, ++ .card = CX88_BOARD_TBS_8922, ++ }, { + .subvendor = 0xb022, + .subdevice = 0x3022, + .card = CX88_BOARD_PROF_6200, +@@ -3547,6 +3565,14 @@ static void cx88_card_setup(struct cx88_core *core) + cx_write(MO_SRST_IO, 1); + msleep(100); + break; ++ case CX88_BOARD_TBS_8922: ++ cx_write(MO_GP0_IO, 0x4340); ++ msleep(10); ++ cx_write(MO_GP0_IO, 0x4342); ++ msleep(200); ++ cx_write(MO_GP0_IO, 0x4343); ++ msleep(100); ++ break; + } /*end switch() */ + + /* Setup tuners */ +diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c +index ddf9067..89d3b62 100644 +--- a/drivers/media/pci/cx88/cx88-dvb.c ++++ b/drivers/media/pci/cx88/cx88-dvb.c +@@ -56,6 +56,8 @@ + #include "mb86a16.h" + #include "ts2020.h" + #include "ds3000.h" ++#include "tas2101.h" ++#include "av201x.h" + + MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); + MODULE_AUTHOR("Chris Pascoe "); +@@ -996,6 +998,21 @@ static const struct stv0299_config samsung_stv0299_config = { + .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, + }; + ++static struct tas2101_config tbs8922_demod_cfg = { ++ ++ .i2c_address = 0x68, ++ .id = ID_TAS2100, ++ .init = {0x67, 0x45, 0x23, 0x01, 0xa8, 0x9b, 0x33}, // 0xb1 ++ .init2 = 0, ++ ++}; ++ ++static struct av201x_config tbs8922_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ + static int dvb_register(struct cx8802_dev *dev) + { + struct cx88_core *core = dev->core; +@@ -1541,6 +1558,20 @@ static int dvb_register(struct cx8802_dev *dev) + if (fe0->dvb.frontend) + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + break; ++ case CX88_BOARD_TBS_8922: ++ dev->ts_gen_cntrl = 0x04; ++ fe0->dvb.frontend = dvb_attach(tas2101_attach, &tbs8922_demod_cfg, &core->i2c_adap); ++ ++ if (fe0->dvb.frontend != NULL) ++ if (dvb_attach(av201x_attach, fe0->dvb.frontend, &tbs8922_av201x_cfg, ++ tas2101_get_i2c_adapter(fe0->dvb.frontend, 2)) == NULL) { ++ dvb_frontend_detach(fe0->dvb.frontend); ++ //adapter->fe = NULL; ++ //dev_err(&dev->pci_dev->dev, ++ // "TBS_PCIE frontend %d tuner attach failed\n", ++ // adapter->nr); ++ } ++ break; + case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: + fe0->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_terratec_cinergy_ht_pci_mkii_config, +diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c +index dcfea35..5314b4c 100644 +--- a/drivers/media/pci/cx88/cx88-input.c ++++ b/drivers/media/pci/cx88/cx88-input.c +@@ -396,6 +396,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) + case CX88_BOARD_OMICOM_SS4_PCI: + case CX88_BOARD_SATTRADE_ST4200: + case CX88_BOARD_TBS_8920: ++ case CX88_BOARD_TBS_8922: + case CX88_BOARD_TBS_8910: + case CX88_BOARD_PROF_7300: + case CX88_BOARD_PROF_7301: +diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h +index 115414c..cdf7f86 100644 +--- a/drivers/media/pci/cx88/cx88.h ++++ b/drivers/media/pci/cx88/cx88.h +@@ -237,6 +237,7 @@ extern const struct sram_channel cx88_sram_channels[]; + #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88 + #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89 + #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90 ++#define CX88_BOARD_TBS_8922 91 + + enum cx88_itype { + CX88_VMUX_COMPOSITE1 = 1, +diff --git a/drivers/media/pci/saa716x/Kconfig b/drivers/media/pci/saa716x/Kconfig +new file mode 100644 +index 0000000..618641c +--- /dev/null ++++ b/drivers/media/pci/saa716x/Kconfig +@@ -0,0 +1,84 @@ ++menuconfig SAA716X_SUPPORT ++ bool "Support for SAA716x family from NXP/Philips" ++ depends on PCI && I2C ++ help ++ support for saa716x ++ ++if SAA716X_SUPPORT ++config SAA716X_CORE ++ tristate "SAA7160/1/2 PCI Express bridge based devices" ++ depends on PCI && I2C ++ ++ help ++ Support for PCI cards based on the SAA7160/1/2 PCI Express bridge. ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_TBS ++ tristate "SAA7160/1/2 based Budget PCIe cards (DVB only)" ++ depends on SAA716X_CORE && DVB_CORE ++ select DVB_CX24117 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_MB86A16 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_TAS2101 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_ISL6422 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CXD2820R if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_AV201X if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT ++ ++ ++ help ++ Support for the SAA7160/1/2 based Budget PCIe DVB cards ++ Currently supported devices are: ++ ++ * KNC1 Dual S2 (DVB-S, DVB-S/S2) ++ * Twinhan/Azurewave VP-1028 (DVB-S) ++ * Twinhan/Azurewave VP-3071 (DVB-T x2) ++ * Twinhan/Azurewave VP-6002 (DVB-S) ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_HYBRID ++ tristate "SAA7160/1/2 based Hybrid PCIe cards (DVB + Analog)" ++ depends on SAA716X_CORE && DVB_CORE ++ select DVB_MB86A16 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT ++ ++ help ++ Support for the SAA7160/1/2 based Hybrid PCIe DVB cards ++ Currently supported devices are: ++ ++ * Avermedia H-788 (DVB-T) ++ * Avermedia HC-82 (DVB-T) ++ * NXP Reference (Atlantis) (DVB-T x2) ++ * NXP Reference (Nemo) (DVB-T) ++ * Twinhan/Azurewave VP-6090 (DVB-S x2, DVB-T x2) ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_FF ++ tristate "SAA7160/1/2 based Full Fledged PCIe cards" ++ depends on SAA716X_CORE && DVB_CORE ++ depends on INPUT # IR ++ ++ select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_ISL6423 if MEDIA_SUBDRV_AUTOSELECT ++ ++ help ++ Support for the SAA7160/1/2 based Full fledged PCIe DVB cards ++ These cards do feature a hardware MPEG decoder and other ++ peripherals. Also known as Premium cards. ++ Currently supported devices are: ++ ++ * Technotrend S2 6400 Dual S2 HD (DVB-S/S2 x2) ++ ++ Say Y if you own such a device and want to use it. ++ ++endif # SAA716X_SUPPORT +diff --git a/drivers/media/pci/saa716x/Makefile b/drivers/media/pci/saa716x/Makefile +new file mode 100644 +index 0000000..87c1bfa +--- /dev/null ++++ b/drivers/media/pci/saa716x/Makefile +@@ -0,0 +1,27 @@ ++saa716x_core-objs := saa716x_pci.o \ ++ saa716x_i2c.o \ ++ saa716x_cgu.o \ ++ saa716x_msi.o \ ++ saa716x_dma.o \ ++ saa716x_vip.o \ ++ saa716x_aip.o \ ++ saa716x_phi.o \ ++ saa716x_boot.o \ ++ saa716x_fgpi.o \ ++ saa716x_adap.o \ ++ saa716x_gpio.o \ ++ saa716x_greg.o \ ++ saa716x_rom.o \ ++ saa716x_spi.o ++ ++saa716x_ff-objs := saa716x_ff_main.o \ ++ saa716x_ff_cmd.o \ ++ saa716x_ff_ir.o ++ ++obj-$(CONFIG_SAA716X_CORE) += saa716x_core.o ++obj-$(CONFIG_DVB_SAA716X_TBS) += saa716x_tbs-dvb.o ++obj-$(CONFIG_DVB_SAA716X_HYBRID) += saa716x_hybrid.o ++obj-$(CONFIG_DVB_SAA716X_FF) += saa716x_ff.o ++saa716x_tbs-dvb-objs += saa716x_budget.o tbsci-i2c.o tbs-ci.o ++ ++EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/ +diff --git a/drivers/media/pci/saa716x/saa716x_adap.c b/drivers/media/pci/saa716x/saa716x_adap.c +new file mode 100644 +index 0000000..4c95a38 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_adap.c +@@ -0,0 +1,268 @@ ++#include ++ ++#include "dmxdev.h" ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dvb_frontend.h" ++ ++#include "saa716x_mod.h" ++#include "saa716x_spi.h" ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_gpio.h" ++#include "saa716x_priv.h" ++ ++ ++#define SAA716X_TS_DMA_BUF_SIZE (16 * SAA716x_PAGE_SIZE) ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++ ++void saa716x_dma_start(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ struct fgpi_stream_params params; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Start DMA engine for Adapter:%d", adapter); ++ ++ params.bits = 8; ++ params.samples = 188; ++ params.lines = SAA716X_TS_DMA_BUF_SIZE / 188; ++ params.pitch = 188; ++ params.offset = 0; ++ params.page_tables = 0; ++ params.stream_type = FGPI_TRANSPORT_STREAM; ++ params.stream_flags = 0; ++ ++ saa716x_fgpi_start(saa716x, saa716x->config->adap_config[adapter].ts_port, ¶ms); ++} ++ ++void saa716x_dma_stop(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Stop DMA engine for Adapter:%d", adapter); ++ ++ saa716x_fgpi_stop(saa716x, saa716x->config->adap_config[adapter].ts_port); ++} ++ ++static int saa716x_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Start feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds++; ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed, feeds=%d", ++ saa716x_adap->feeds); ++ ++ if (saa716x_adap->feeds == 1) { ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed & dma"); ++ saa716x_dma_start(saa716x, saa716x_adap->count); ++ } ++ ++ return saa716x_adap->feeds; ++} ++ ++static int saa716x_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Stop feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds--; ++ if (saa716x_adap->feeds == 0) { ++ dprintk(SAA716x_DEBUG, 1, "saa716x stop feed and dma"); ++ saa716x_dma_stop(saa716x, saa716x_adap->count); ++ } ++ ++ return 0; ++} ++ ++int saa716x_dvb_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct saa716x_config *config = saa716x->config; ++ int result, i; ++ ++ mutex_init(&saa716x->adap_lock); ++ ++ saa716x->num_adapters = 0; ++ for (i = 0; i < config->adapters; i++) { ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_register_adapter"); ++ if (dvb_register_adapter(&saa716x_adap->dvb_adapter, ++ "SAA716x dvb adapter", ++ saa716x->module, ++ &saa716x->pdev->dev, ++ adapter_nr) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "Error registering adapter"); ++ return -ENODEV; ++ } ++ ++ saa716x_adap->count = i; ++ ++ saa716x_adap->dvb_adapter.priv = saa716x_adap; ++ saa716x_adap->demux.dmx.capabilities = DMX_TS_FILTERING | ++ DMX_SECTION_FILTERING | ++ DMX_MEMORY_BASED_FILTERING; ++ ++ saa716x_adap->demux.priv = saa716x_adap; ++ saa716x_adap->demux.filternum = 256; ++ saa716x_adap->demux.feednum = 256; ++ saa716x_adap->demux.start_feed = saa716x_dvb_start_feed; ++ saa716x_adap->demux.stop_feed = saa716x_dvb_stop_feed; ++ saa716x_adap->demux.write_to_decoder = NULL; ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmx_init"); ++ if ((result = dvb_dmx_init(&saa716x_adap->demux)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err0; ++ } ++ ++ saa716x_adap->dmxdev.filternum = 256; ++ saa716x_adap->dmxdev.demux = &saa716x_adap->demux.dmx; ++ saa716x_adap->dmxdev.capabilities = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmxdev_init"); ++ if ((result = dvb_dmxdev_init(&saa716x_adap->dmxdev, ++ &saa716x_adap->dvb_adapter)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); ++ goto err1; ++ } ++ ++ saa716x_adap->fe_hw.source = DMX_FRONTEND_0; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err2; ++ } ++ ++ saa716x_adap->fe_mem.source = DMX_MEMORY_FE; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_mem)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err3; ++ } ++ ++ if ((result = saa716x_adap->demux.dmx.connect_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err4; ++ } ++ ++ dvb_net_init(&saa716x_adap->dvb_adapter, &saa716x_adap->dvb_net, &saa716x_adap->demux.dmx); ++// tasklet_init(&saa716x_adap->tasklet, saa716x_dma_xfer, (unsigned long) saa716x); ++ dprintk(SAA716x_DEBUG, 1, "Frontend Init"); ++ saa716x_adap->saa716x = saa716x; ++ ++ if (config->frontend_attach) { ++ result = config->frontend_attach(saa716x_adap, i); ++ if (result < 0) ++ dprintk(SAA716x_ERROR, 1, "SAA716x frontend attach failed"); ++ ++ if (saa716x_adap->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "A frontend driver was not found for [%04x:%04x] subsystem [%04x:%04x]\n", ++ saa716x->pdev->vendor, ++ saa716x->pdev->device, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ } else { ++ result = dvb_register_frontend(&saa716x_adap->dvb_adapter, saa716x_adap->fe); ++ if (result < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x register frontend failed"); ++ goto err6; ++ } ++ } ++ ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach = NULL"); ++ } ++ ++ saa716x_fgpi_init(saa716x, config->adap_config[i].ts_port, ++ SAA716X_TS_DMA_BUF_SIZE, ++ config->adap_config[i].worker); ++ ++ saa716x->num_adapters++; ++ saa716x_adap++; ++ } ++ ++ return 0; ++ ++ /* Error conditions */ ++err6: ++ dvb_frontend_detach(saa716x_adap->fe); ++err4: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++err3: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++err2: ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++err1: ++ dvb_dmx_release(&saa716x_adap->demux); ++err0: ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ return result; ++} ++EXPORT_SYMBOL(saa716x_dvb_init); ++ ++void saa716x_dvb_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct i2c_client *client; ++ int i, count = saa716x->num_adapters; ++ ++ for (i = 0; i < count; i++) { ++ ++ saa716x_fgpi_exit(saa716x, saa716x->config->adap_config[i].ts_port); ++ ++ /* remove I2C tuner */ ++ client = saa716x_adap->i2c_client_tuner; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ ++ /* remove I2C demod */ ++ client = saa716x_adap->i2c_client_demod; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ ++ if (saa716x_adap->fe) { ++ dvb_unregister_frontend(saa716x_adap->fe); ++ dvb_frontend_detach(saa716x_adap->fe); ++ } ++ ++// tasklet_kill(&saa716x->tasklet); ++ dvb_net_release(&saa716x_adap->dvb_net); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++ dvb_dmx_release(&saa716x_adap->demux); ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_unregister_adapter"); ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ saa716x->num_adapters--; ++ saa716x_adap++; ++ } ++ ++ return; ++} ++EXPORT_SYMBOL(saa716x_dvb_exit); +diff --git a/drivers/media/pci/saa716x/saa716x_adap.h b/drivers/media/pci/saa716x/saa716x_adap.h +new file mode 100644 +index 0000000..7822e36 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_adap.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_ADAP_H ++#define __SAA716x_ADAP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_dvb_init(struct saa716x_dev *saa716x); ++extern void saa716x_dvb_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ADAP_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_aip.c b/drivers/media/pci/saa716x/saa716x_aip.c +new file mode 100644 +index 0000000..3bdb265 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_aip.c +@@ -0,0 +1,20 @@ ++#include ++ ++#include "saa716x_mod.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_aip.h" ++#include "saa716x_priv.h" ++ ++int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev) ++{ ++ return SAA716x_EPRD(dev, AI_CTL) == 0 ? 0 : -1; ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_status); ++ ++void saa716x_aip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(AI0, AI_CTL, 0x00); ++ SAA716x_EPWR(AI1, AI_CTL, 0x00); ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_disable); +diff --git a/drivers/media/pci/saa716x/saa716x_aip.h b/drivers/media/pci/saa716x/saa716x_aip.h +new file mode 100644 +index 0000000..36277b7 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_aip.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_AIP_H ++#define __SAA716x_AIP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev); ++extern void saa716x_aip_disable(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_AIP_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_aip_reg.h b/drivers/media/pci/saa716x/saa716x_aip_reg.h +new file mode 100644 +index 0000000..3e0893a +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_aip_reg.h +@@ -0,0 +1,62 @@ ++#ifndef __SAA716x_AIP_REG_H ++#define __SAA716x_AIP_REG_H ++ ++/* -------------- AI Registers ---------------- */ ++ ++#define AI_STATUS 0x000 ++#define AI_BUF1_ACTIVE (0x00000001 << 4) ++#define AI_OVERRUN (0x00000001 << 3) ++#define AI_HBE (0x00000001 << 2) ++#define AI_BUF2_FULL (0x00000001 << 1) ++#define AI_BUF1_FULL (0x00000001 << 0) ++ ++#define AI_CTL 0x004 ++#define AI_RESET (0x00000001 << 31) ++#define AI_CAP_ENABLE (0x00000001 << 30) ++#define AI_CAP_MODE (0x00000003 << 28) ++#define AI_SIGN_CONVERT (0x00000001 << 27) ++#define AI_EARLYMODE (0x00000001 << 26) ++#define AI_DIAGMODE (0x00000001 << 25) ++#define AI_RAWMODE (0x00000001 << 24) ++#define AI_OVR_INTEN (0x00000001 << 7) ++#define AI_HBE_INTEN (0x00000001 << 6) ++#define AI_BUF2_INTEN (0x00000001 << 5) ++#define AI_BUF1_INTEN (0x00000001 << 4) ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_SERIAL 0x008 ++#define AI_SER_MASTER (0x00000001 << 31) ++#define AI_DATAMODE (0x00000001 << 30) ++#define AI_FRAMEMODE (0x00000003 << 28) ++#define AI_CLOCK_EDGE (0x00000001 << 27) ++#define AI_SSPOS4 (0x00000001 << 19) ++#define AI_NR_CHAN (0x00000003 << 17) ++#define AI_WSDIV (0x000001ff << 8) ++#define AI_SCKDIV (0x000000ff << 0) ++ ++#define AI_FRAMING 0x00c ++#define AI_VALIDPOS (0x000001ff << 22) ++#define AI_LEFTPOS (0x000001ff << 13) ++#define AI_RIGHTPOS (0x000001ff << 4) ++#define AI_SSPOS_3_0 (0x0000000f << 0) ++ ++#define AI_BASE1 0x014 ++#define AI_BASE2 0x018 ++#define AI_BASE (0x03ffffff << 6) ++ ++#define AI_SIZE 0x01c ++#define AI_SAMPLE_SIZE (0x03ffffff << 6) ++ ++#define AI_INT_ACK 0x020 ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_PWR_DOWN 0xff4 ++#define AI_PWR_DWN (0x00000001 << 0) ++ ++#endif /* __SAA716x_AIP_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_boot.c b/drivers/media/pci/saa716x/saa716x_boot.c +new file mode 100644 +index 0000000..21e59d0 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_boot.c +@@ -0,0 +1,319 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_cgu_reg.h" ++#include "saa716x_vip_reg.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_gpio_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dcs_reg.h" ++ ++#include "saa716x_boot.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static int saa716x_ext_boot(struct saa716x_dev *saa716x) ++{ ++ /* Write GREG boot_ready to 0 ++ * DW_0 = 0x0001_2018 ++ * DW_1 = 0x0000_0000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000000); ++ ++ /* Clear VI0 interrupt ++ * DW_2 = 0x0000_0fe8 ++ * DW_3 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x000003ff); ++ ++ /* Clear VI1 interrupt ++ * DW_4 = 0x0000_1fe8 ++ * DW_5 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x000003ff); ++ ++ /* CLear FGPI0 interrupt ++ * DW_6 = 0x0000_2fe8 ++ * DW_7 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI0, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI1 interrupt ++ * DW_8 = 0x0000_3fe8 ++ * DW_9 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI1, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI2 interrupt ++ * DW_10 = 0x0000_4fe8 ++ * DW_11 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI2, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI3 interrupt ++ * DW_12 = 0x0000_5fe8 ++ * DW_13 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI3, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear AI0 interrupt ++ * DW_14 = 0x0000_6020 ++ * DW_15 = 0x0000_000f ++ */ ++ SAA716x_EPWR(AI0, AI_INT_ACK, 0x0000000f); ++ ++ /* Clear AI1 interrupt ++ * DW_16 = 0x0000_7020 ++ * DW_17 = 0x0000_200f ++ */ ++ SAA716x_EPWR(AI1, AI_INT_ACK, 0x0000000f); ++ ++ /* Set GREG boot_ready bit to 1 ++ * DW_18 = 0x0001_2018 ++ * DW_19 = 0x0000_2000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++#if 0 ++ /* End of Boot script command ++ * DW_20 = 0x0000_0006 ++ * Where to write this value ?? ++ * This seems very odd an address to trigger the ++ * Boot Control State Machine ! ++ */ ++ SAA716x_EPWR(VI0, 0x00000006, 0xffffffff); ++#endif ++ return 0; ++} ++ ++/* Internal Bootscript configuration */ ++static void saa716x_int_boot(struct saa716x_dev *saa716x) ++{ ++ /* #1 Configure PCI COnfig space ++ * GREG_JETSTR_CONFIG_0 ++ */ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, saa716x->pdev->subsystem_vendor); ++ ++ /* GREG_JETSTR_CONFIG_1 ++ * pmcsr_scale:7 = 0x00 ++ * pmcsr_scale:6 = 0x00 ++ * pmcsr_scale:5 = 0x00 ++ * pmcsr_scale:4 = 0x00 ++ * pmcsr_scale:3 = 0x00 ++ * pmcsr_scale:2 = 0x00 ++ * pmcsr_scale:1 = 0x00 ++ * pmcsr_scale:0 = 0x00 ++ * BAR mask = 20 bit ++ * BAR prefetch = no ++ * MSI capable = 32 messages ++ */ ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, 0x00001005); ++ ++ /* GREG_JETSTR_CONFIG_2 ++ * pmcsr_data:3 = 0x0 ++ * pmcsr_data:2 = 0x0 ++ * pmcsr_data:1 = 0x0 ++ * pmcsr_data:0 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, 0x00000000); ++ ++ /* GREG_JETSTR_CONFIG_3 ++ * pmcsr_data:7 = 0x0 ++ * pmcsr_data:6 = 0x0 ++ * pmcsr_data:5 = 0x0 ++ * pmcsr_data:4 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, 0x00000000); ++ ++ /* #2 Release GREG resets ++ * ip_rst_an ++ * dpa1_rst_an ++ * jetsream_reset_an ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000e00); ++ ++ /* #3 GPIO Setup ++ * GPIO 25:24 = Output ++ * GPIO Output "0" after Reset ++ */ ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ ++ /* #4 Custom stuff goes in here */ ++ ++ /* #5 Disable CGU Clocks ++ * except for PHY, Jetstream, DPA1, DCS, Boot, GREG ++ * CGU_PCR_0_3: pss_mmu_clk:0 = 0x0 ++ */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, 0x00000006); ++ ++ /* CGU_PCR_0_4: pss_dtl2mtl_mmu_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, 0x00000006); ++ ++ /* CGU_PCR_0_5: pss_msi_ck:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, 0x00000006); ++ ++ /* CGU_PCR_0_7: pss_gpio_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, 0x00000006); ++ ++ /* CGU_PCR_2_1: spi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, 0x00000006); ++ ++ /* CGU_PCR_3_2: i2c_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, 0x00000006); ++ ++ /* CGU_PCR_4_1: phi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, 0x00000006); ++ ++ /* CGU_PCR_5: vip0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_5, 0x00000006); ++ ++ /* CGU_PCR_6: vip1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_6, 0x00000006); ++ ++ /* CGU_PCR_7: fgpi0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_7, 0x00000006); ++ ++ /* CGU_PCR_8: fgpi1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_8, 0x00000006); ++ ++ /* CGU_PCR_9: fgpi2_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_9, 0x00000006); ++ ++ /* CGU_PCR_10: fgpi3_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_10, 0x00000006); ++ ++ /* CGU_PCR_11: ai0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_11, 0x00000006); ++ ++ /* CGU_PCR_12: ai1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_12, 0x00000006); ++ ++ /* #6 Set GREG boot_ready = 0x1 */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++ ++ /* #7 Disable GREG CGU Clock */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, 0x00000006); ++ ++ /* End of Bootscript command ?? */ ++} ++ ++int saa716x_core_boot(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_config *config = saa716x->config; ++ ++ switch (config->boot_mode) { ++ case SAA716x_EXT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using External Boot from config"); ++ saa716x_ext_boot(saa716x); ++ break; ++ case SAA716x_INT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using Internal Boot from config"); ++ saa716x_int_boot(saa716x); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown configuration %d", config->boot_mode); ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_core_boot); ++ ++static void saa716x_bus_report(struct pci_dev *pdev, int enable) ++{ ++ u32 reg; ++ ++ pci_read_config_dword(pdev, 0x04, ®); ++ if (enable) ++ reg |= 0x00000100; /* enable SERR */ ++ else ++ reg &= 0xfffffeff; /* disable SERR */ ++ pci_write_config_dword(pdev, 0x04, reg); ++ ++ pci_read_config_dword(pdev, 0x58, ®); ++ reg &= 0xfffffffd; ++ pci_write_config_dword(pdev, 0x58, reg); ++} ++ ++int saa716x_jetpack_init(struct saa716x_dev *saa716x) ++{ ++ /* ++ * configure PHY through config space not to report ++ * non-fatal error messages to avoid problems with ++ * quirky BIOS'es ++ */ ++ saa716x_bus_report(saa716x->pdev, 0); ++ ++ /* ++ * create time out for blocks that have no clock ++ * helps with lower bitrates on FGPI ++ */ ++ SAA716x_EPWR(DCS, DCSC_CTRL, ENABLE_TIMEOUT); ++ ++ /* Reset all blocks */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ switch (saa716x->pdev->device) { ++ case SAA7162: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x03000000); /* Enable decoders */ ++ break; ++ case SAA7161: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfeffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x01000000); /* Enable decoder */ ++ break; ++ case SAA7160: ++ saa716x->i2c_rate = SAA716x_I2C_RATE_100; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown device (0x%02x)", saa716x->pdev->device); ++ return -ENODEV; ++ } ++ ++ /* General setup for MMU */ ++ SAA716x_EPWR(MMU, MMU_MODE, 0x14); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Jetpack Successfully initialized", saa716x->pdev->device); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_jetpack_init); ++ ++void saa716x_core_reset(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "RESET Modules"); ++ ++ /* VIP */ ++ SAA716x_EPWR(VI0, VI_MODE, SOFT_RESET); ++ SAA716x_EPWR(VI1, VI_MODE, SOFT_RESET); ++ ++ /* FGPI */ ++ SAA716x_EPWR(FGPI0, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI1, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI2, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI3, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* AIP */ ++ SAA716x_EPWR(AI0, AI_CTL, AI_RESET); ++ SAA716x_EPWR(AI1, AI_CTL, AI_RESET); ++ ++ /* BAM */ ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ /* MMU */ ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ ++ /* MSI */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++} ++EXPORT_SYMBOL_GPL(saa716x_core_reset); +diff --git a/drivers/media/pci/saa716x/saa716x_boot.h b/drivers/media/pci/saa716x/saa716x_boot.h +new file mode 100644 +index 0000000..8102853 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_boot.h +@@ -0,0 +1,18 @@ ++#ifndef __SAA716x_BOOT_H ++#define __SAA716x_BOOT_H ++ ++#define DISABLE_TIMEOUT 0x17 ++#define ENABLE_TIMEOUT 0x16 ++ ++enum saa716x_boot_mode { ++ SAA716x_EXT_BOOT = 1, ++ SAA716x_INT_BOOT, /* GPIO[31:30] = 0x01 */ ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++extern void saa716x_core_reset(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_BOOT_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_budget.c b/drivers/media/pci/saa716x/saa716x_budget.c +new file mode 100644 +index 0000000..10629d74 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_budget.c +@@ -0,0 +1,2917 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_budget.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "mb86a16.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "tas2101.h" ++#include "av201x.h" ++#include "cx24117.h" ++#include "isl6422.h" ++#include "stb6100.h" ++#include "stb6100_cfg.h" ++ ++#include "tda18212.h" ++#include "cxd2820r.h" ++ ++#include "si2168.h" ++#include "si2157.h" ++ ++#include "stv6120.h" ++#include "stv0910.h" ++#include "tbsci-i2c.h" ++#include "tbs-ci.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Budget" ++ ++static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->module = THIS_MODULE; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail2; ++ } ++ ++ saa716x_gpio_init(saa716x); ++#if 0 ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed"); ++ } ++#endif ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F0A); ++ /* enable FGPI3, FGPI2, FGPI1 and FGPI0 for TS input from Port 2 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x322); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail3; ++ } ++ ++ return 0; ++ ++fail3: ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_budget_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ int i; ++ ++ for(i = 0;iconfig->adapters; i++) ++ { ++ if(saa716x_adap->tbsci){ ++ tbsci_release(saa716x_adap); ++ tbsci_i2c_remove(saa716x_adap); ++ } ++ ++ saa716x_adap++; ++ } ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071" ++#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T" ++ ++static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp3071_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP3071, ++ .dev_type = SAA716x_DEV_TWINHAN_VP3071, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_vp3071_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028" ++#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S" ++ ++static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp1028_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp1028_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[1]; ++ ++ if (count == 0) { ++ ++ mutex_lock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count); ++ saa716x_gpio_set_output(saa716x, 10); ++ msleep(1); ++ ++ /* VP-1028 has inverted power supply control */ ++ saa716x_gpio_write(saa716x, 10, 1); /* set to standby */ ++ saa716x_gpio_write(saa716x, 10, 0); /* switch it on */ ++ msleep(100); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count); ++ saa716x_gpio_set_output(saa716x, 12); ++ msleep(1); ++ ++ /* reset demodulator (Active LOW) */ ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 0); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ ++ mutex_unlock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = dvb_attach(mb86a16_attach, ++ &vp1028_mb86a16_config, ++ &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp1028_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp1028_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP1028, ++ .dev_type = SAA716x_DEV_TWINHAN_VP1028, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp1028_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002" ++#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S" ++ ++static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp6002_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6002, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6002, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6002_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2" ++#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2" ++ ++static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_knc1_duals2_config = { ++ .model_name = SAA716x_MODEL_KNC1_DUALS2, ++ .dev_type = SAA716x_DEV_KNC1_DUALS2, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_knc1_duals2_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD" ++#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2" ++ ++static struct stv090x_config skystar2_stv090x_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 8000000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_DVBCI, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_sleep = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static int skystar2_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ int err; ++ u8 en = 0; ++ u8 sel = 0; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ en = 0; ++ break; ++ ++ case SEC_VOLTAGE_13: ++ en = 1; ++ sel = 0; ++ break; ++ ++ case SEC_VOLTAGE_18: ++ en = 1; ++ sel = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ err = skystar2_stv090x_config.set_gpio(fe, 2, 0, en, 0); ++ if (err < 0) ++ goto exit; ++ err = skystar2_stv090x_config.set_gpio(fe, 3, 0, sel, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg) ++{ ++ int err; ++ u8 value; ++ ++ if (arg) ++ value = 1; ++ else ++ value = 0; ++ ++ err = skystar2_stv090x_config.set_gpio(fe, 4, 0, value, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static struct stv6110x_config skystar2_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 16000000, ++ .clk_div = 2, ++}; ++ ++static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct stv6110x_devctl *ctl; ++ ++ if (count < saa716x->config->adapters) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ saa716x_gpio_set_output(saa716x, 26); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 26, 1); ++ saa716x_gpio_write(saa716x, 26, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 26, 1); ++ msleep(10); ++ ++ adapter->fe = dvb_attach(stv090x_attach, ++ &skystar2_stv090x_config, ++ &i2c->i2c_adapter, ++ STV090x_DEMODULATOR_0); ++ ++ if (adapter->fe) { ++ dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x", ++ skystar2_stv090x_config.address); ++ } else { ++ goto exit; ++ } ++ ++ adapter->fe->ops.set_voltage = skystar2_set_voltage; ++ adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost; ++ ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &skystar2_stv6110x_config, ++ &i2c->i2c_adapter); ++ ++ if (ctl) { ++ dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x", ++ skystar2_stv6110x_config.addr); ++ ++ skystar2_stv090x_config.tuner_init = ctl->tuner_init; ++ skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config skystar2_express_hd_config = { ++ .model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD, ++ .dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = skystar2_express_hd_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++#define SAA716x_MODEL_TBS6284 "TurboSight TBS 6284 " ++#define SAA716x_DEV_TBS6284 "DVB-T/T2/C" ++ ++static struct cxd2820r_config cxd2820r_config[] = { ++ { ++ .i2c_address = 0x6c, /* (0xd8 >> 1) */ ++ .ts_mode = 0x38, ++ }, ++ { ++ .i2c_address = 0x6d, /* (0xda >> 1) */ ++ .ts_mode = 0x38, ++ } ++}; ++ ++static struct tda18212_config tda18212_config[] = { ++ { ++ /* .i2c_address = 0x60 (0xc0 >> 1) */ ++ .if_dvbt_6 = 3550, ++ .if_dvbt_7 = 3700, ++ .if_dvbt_8 = 4150, ++ .if_dvbt2_6 = 3250, ++ .if_dvbt2_7 = 4000, ++ .if_dvbt2_8 = 4000, ++ .if_dvbc = 5000, ++ .loop_through = 1, ++ .xtout = 1 ++ }, ++ { ++ /* .i2c_address = 0x63 (0xc6 >> 1) */ ++ .if_dvbt_6 = 3550, ++ .if_dvbt_7 = 3700, ++ .if_dvbt_8 = 4150, ++ .if_dvbt2_6 = 3250, ++ .if_dvbt2_7 = 4000, ++ .if_dvbt2_8 = 4000, ++ .if_dvbc = 5000, ++ .loop_through = 0, ++ .xtout = 0 ++ }, ++}; ++ ++static int saa716x_tbs_read_mac(struct saa716x_dev *saa716x, int count, u8 *mac) ++{ ++ return saa716x_read_rombytes(saa716x, 0x2A0 + count * 16, 6, mac); ++} ++ ++static int saa716x_tbs6284_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct saa716x_i2c *i2c = &dev->i2c[1 - (count >> 1)]; ++ struct i2c_adapter *i2cadapter = &i2c->i2c_adapter; ++ u8 mac[6]; ++ ++ struct i2c_client *client; ++ ++ struct i2c_board_info board_info = { ++ .type = "tda18212", ++ .platform_data = &tda18212_config[count & 1], ++ }; ++ ++ ++ if (count > 3) ++ goto err; ++ ++ /* reset */ ++ if (count == 0) { ++ saa716x_gpio_set_output(dev, 22); ++ saa716x_gpio_write(dev, 22, 0); ++ msleep(200); ++ saa716x_gpio_write(dev, 22, 1); ++ msleep(400); ++ } else if (count == 2) { ++ saa716x_gpio_set_output(dev, 12); ++ saa716x_gpio_write(dev, 12, 0); ++ msleep(200); ++ saa716x_gpio_write(dev, 12, 1); ++ msleep(400); ++ } ++ ++ /* attach frontend */ ++ adapter->fe = dvb_attach(cxd2820r_attach, &cxd2820r_config[count & 1], ++ &i2c->i2c_adapter, NULL); ++ if (!adapter->fe) ++ goto err; ++ ++ /* attach tuner */ ++ board_info.addr = (count & 1) ? 0x63 : 0x60; ++ tda18212_config[count & 1].fe = adapter->fe; ++ request_module("tda18212"); ++ client = i2c_new_device(i2cadapter, &board_info); ++ if (client == NULL || client->dev.driver == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ goto err2; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ dvb_frontend_detach(adapter->fe); ++ goto err2; ++ } ++ adapter->i2c_client_tuner = client; ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err2: ++ dev_err(&dev->pdev->dev, "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ ++ adapter->fe = NULL; ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6284_config = { ++ .model_name = SAA716x_MODEL_TBS6284, ++ .dev_type = SAA716x_DEV_TBS6284, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 4, ++ .frontend_attach = saa716x_tbs6284_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 2 */ ++ .ts_port = 1, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 3 */ ++ .ts_port = 0, ++ .worker = demux_worker ++ } ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6280 "TurboSight TBS 6280 " ++#define SAA716x_DEV_TBS6280 "DVB-T/T2/C" ++ ++static int saa716x_tbs6280_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct saa716x_i2c *i2c = &dev->i2c[SAA716x_I2C_BUS_A]; ++ struct i2c_adapter *i2cadapter = &i2c->i2c_adapter; ++ u8 mac[6]; ++ ++ struct i2c_client *client; ++ ++ struct i2c_board_info board_info = { ++ .type = "tda18212", ++ .platform_data = &tda18212_config[count & 1], ++ }; ++ ++ if (count > 1) ++ goto err; ++ ++ /* reset */ ++ if (count == 0) { ++ saa716x_gpio_set_output(dev, 2); ++ saa716x_gpio_write(dev, 2, 0); ++ msleep(200); ++ saa716x_gpio_write(dev, 2, 1); ++ msleep(400); ++ } ++ ++ /* attach frontend */ ++ adapter->fe = dvb_attach(cxd2820r_attach, &cxd2820r_config[count], ++ &i2c->i2c_adapter, NULL); ++ if (!adapter->fe) ++ goto err; ++ ++ /* attach tuner */ ++ board_info.addr = (count & 1) ? 0x63 : 0x60; ++ tda18212_config[count & 1].fe = adapter->fe; ++ request_module("tda18212"); ++ client = i2c_new_device(i2cadapter, &board_info); ++ if (client == NULL || client->dev.driver == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ goto err2; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ dvb_frontend_detach(adapter->fe); ++ goto err2; ++ } ++ adapter->i2c_client_tuner = client; ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err2: ++ dev_err(&dev->pdev->dev, "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ ++ adapter->fe = NULL; ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6280_config = { ++ .model_name = SAA716x_MODEL_TBS6280, ++ .dev_type = SAA716x_DEV_TBS6280, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6280_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6221 "TurboSight TBS 6221 " ++#define SAA716x_DEV_TBS6221 "DVB-T/T2/C" ++ ++static int saa716x_tbs6221_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct saa716x_i2c *i2c = &dev->i2c[SAA716x_I2C_BUS_A]; ++ struct i2c_adapter *i2cadapter = &i2c->i2c_adapter; ++ struct i2c_client *client; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ u8 mac[6]; ++ ++ if (count > 0) ++ goto err; ++ ++ /* attach demod */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &i2cadapter; ++ si2168_config.fe = &adapter->fe; ++ si2168_config.ts_mode = SI2168_TS_PARALLEL; ++ si2168_config.ts_clock_gapped = true; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client = i2c_new_device(&i2c->i2c_adapter, &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ goto err; ++ } ++ adapter->i2c_client_demod = client; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client = i2c_new_device(i2cadapter, &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ adapter->i2c_client_tuner = client; ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6221_config = { ++ .model_name = SAA716x_MODEL_TBS6221, ++ .dev_type = SAA716x_DEV_TBS6221, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_tbs6221_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++#define SAA716x_MODEL_TBS7220 "TurboSight TBS 7220 " ++#define SAA716x_DEV_TBS7220 "DVB-T/T2/C" ++ ++static struct saa716x_config saa716x_tbs7220_config = { ++ .model_name = SAA716x_MODEL_TBS7220, ++ .dev_type = SAA716x_DEV_TBS7220, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_tbs6221_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ .ts_port = 1, ++ .worker = demux_worker ++ }, ++ }, ++ ++}; ++#define SAA716x_MODEL_TBS6281 "TurboSight TBS 6281 " ++#define SAA716x_DEV_TBS6281 "DVB-T/T2/C" ++ ++static int saa716x_tbs6281_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct i2c_adapter *i2cadapter; ++ struct i2c_client *client; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ u8 mac[6]; ++ ++ if (count > 1) ++ goto err; ++ ++ /* reset */ ++ saa716x_gpio_set_output(dev, count ? 2 : 16); ++ saa716x_gpio_write(dev, count ? 2 : 16, 0); ++ msleep(50); ++ saa716x_gpio_write(dev, count ? 2 : 16, 1); ++ msleep(100); ++ ++ /* attach demod */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &i2cadapter; ++ si2168_config.fe = &adapter->fe; ++ si2168_config.ts_mode = SI2168_TS_PARALLEL; ++ si2168_config.ts_clock_gapped = true; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client = i2c_new_device(&dev->i2c[1 - count].i2c_adapter, &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ goto err; ++ } ++ adapter->i2c_client_demod = client; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client = i2c_new_device(i2cadapter, &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ adapter->i2c_client_tuner = client; ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6281_config = { ++ .model_name = SAA716x_MODEL_TBS6281, ++ .dev_type = SAA716x_DEV_TBS6281, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6281_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6285 "TurboSight TBS 6285 " ++#define SAA716x_DEV_TBS6285 "DVB-T/T2/C" ++ ++static int saa716x_tbs6285_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct i2c_adapter *i2cadapter; ++ struct i2c_client *client; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ u8 mac[6]; ++ ++ if (count > 3) ++ goto err; ++ ++ /* attach demod */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &i2cadapter; ++ si2168_config.fe = &adapter->fe; ++ si2168_config.ts_mode = SI2168_TS_SERIAL; ++ si2168_config.ts_clock_gapped = true; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = ((count == 0) || (count == 2)) ? 0x64 : 0x66; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client = i2c_new_device( ((count == 0) || (count == 1)) ? ++ &dev->i2c[1].i2c_adapter : &dev->i2c[0].i2c_adapter, ++ &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ goto err; ++ } ++ ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ goto err; ++ } ++ adapter->i2c_client_demod = client; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = ((count == 0) || (count == 2)) ? 0x62 : 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client = i2c_new_device(i2cadapter, &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ adapter->i2c_client_tuner = client; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6285_config = { ++ .model_name = SAA716x_MODEL_TBS6285, ++ .dev_type = SAA716x_DEV_TBS6285, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 4, ++ .frontend_attach = saa716x_tbs6285_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 1, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 0, ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6220 "TurboSight TBS 6220 " ++#define SAA716x_DEV_TBS6220 "DVB-T/T2/C" ++ ++static int saa716x_tbs6220_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct saa716x_i2c *i2c = &dev->i2c[SAA716x_I2C_BUS_A]; ++ struct i2c_adapter *i2cadapter = &i2c->i2c_adapter; ++ u8 mac[6]; ++ ++ struct i2c_client *client; ++ ++ struct i2c_board_info board_info = { ++ .type = "tda18212", ++ .addr = 0x60, ++ .platform_data = &tda18212_config[0], ++ }; ++ ++ ++ if (count > 0) ++ goto err; ++ ++ /* attach frontend */ ++ adapter->fe = dvb_attach(cxd2820r_attach, &cxd2820r_config[0], ++ &i2c->i2c_adapter, NULL); ++ if (!adapter->fe) ++ goto err; ++ ++ /* attach tuner */ ++ tda18212_config[0].fe = adapter->fe; ++ request_module("tda18212"); ++ client = i2c_new_device(i2cadapter, &board_info); ++ if (client == NULL || client->dev.driver == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ goto err2; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ dvb_frontend_detach(adapter->fe); ++ goto err2; ++ } ++ adapter->i2c_client_tuner = client; ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err2: ++ dev_err(&dev->pdev->dev, "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ ++ adapter->fe = NULL; ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6220_config = { ++ .model_name = SAA716x_MODEL_TBS6220, ++ .dev_type = SAA716x_DEV_TBS6220, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_tbs6220_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6922 "TurboSight TBS 6922 " ++#define SAA716x_DEV_TBS6922 "DVB-S/S2" ++ ++static void tbs6922_lnb_power(struct dvb_frontend *fe, int onoff) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ int enpwr_pin = 17; ++ ++ /* lnb power, active high */ ++ saa716x_gpio_set_output(dev, enpwr_pin); ++ if (onoff) ++ saa716x_gpio_write(dev, enpwr_pin, 1); ++ else ++ saa716x_gpio_write(dev, enpwr_pin, 0); ++} ++ ++ ++static struct tas2101_config tbs6922_cfg = { ++ .i2c_address = 0x68, ++ .id = ID_TAS2100, ++ .reset_demod = NULL, ++ .lnb_power = tbs6922_lnb_power, ++ .init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33}, ++ .init2 = 0, ++}; ++ ++static struct av201x_config tbs6922_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int saa716x_tbs6922_frontend_attach( ++ struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ if (count > 0) ++ goto err; ++ ++ saa716x_gpio_set_output(dev, 2); ++ saa716x_gpio_write(dev, 2, 0); ++ msleep(60); ++ saa716x_gpio_write(dev, 2, 1); ++ msleep(120); ++ ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6922_cfg, ++ &dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6922_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6922_config = { ++ .model_name = SAA716x_MODEL_TBS6922, ++ .dev_type = SAA716x_DEV_TBS6922, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_tbs6922_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6923 "TurboSight TBS 6923 " ++#define SAA716x_DEV_TBS6923 "DVB-S/S2" ++ ++static void tbs6923_lnb_power(struct dvb_frontend *fe, int onoff) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ int enpwr_pin = 3; ++ ++ /* lnb power, active low */ ++ saa716x_gpio_set_output(dev, enpwr_pin); ++ if (onoff) ++ saa716x_gpio_write(dev, enpwr_pin, 0); ++ else ++ saa716x_gpio_write(dev, enpwr_pin, 1); ++} ++ ++static struct tas2101_config tbs6923_cfg = { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = NULL, ++ .lnb_power = tbs6923_lnb_power, ++ .init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33}, ++ .init2 = 0, ++}; ++ ++static struct av201x_config tbs6923_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int saa716x_tbs6923_frontend_attach( ++ struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ if (count > 0) ++ goto err; ++ ++ saa716x_gpio_set_output(dev, 2); ++ saa716x_gpio_write(dev, 2, 0); ++ msleep(60); ++ saa716x_gpio_write(dev, 2, 1); ++ msleep(120); ++ ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6923_cfg, ++ &dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6923_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6923_config = { ++ .model_name = SAA716x_MODEL_TBS6923, ++ .dev_type = SAA716x_DEV_TBS6923, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_tbs6923_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6925 "TurboSight TBS 6925 " ++#define SAA716x_DEV_TBS6925 "DVB-S/S2" ++ ++static struct stv090x_config tbs6925_stv090x_cfg = { ++ .device = STV0900, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 27000000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, ++ .ts2_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ .adc1_range = STV090x_ADC_1Vpp, ++ .tuner_bbgain = 6, ++ ++ .tuner_get_frequency = stb6100_get_frequency, ++ .tuner_set_frequency = stb6100_set_frequency, ++ .tuner_set_bandwidth = stb6100_set_bandwidth, ++ .tuner_get_bandwidth = stb6100_get_bandwidth, ++}; ++ ++static struct stb6100_config tbs6925_stb6100_cfg = { ++ .tuner_address = 0x60, ++ .refclock = 27000000 ++}; ++ ++static int tbs6925_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ saa716x_gpio_set_output(saa716x, 16); ++ msleep(1); ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ saa716x_gpio_write(saa716x, 16, 0); ++ break; ++ case SEC_VOLTAGE_18: ++ saa716x_gpio_write(saa716x, 16, 1); ++ break; ++ case SEC_VOLTAGE_OFF: ++ break; ++ default: ++ return -EINVAL; ++ } ++ msleep(100); ++ ++ return 0; ++} ++ ++static int tbs6925_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ ++ if (count > 0) ++ goto err; ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_set_output(dev, 2); ++ saa716x_gpio_write(dev, 2, 0); ++ msleep(50); ++ saa716x_gpio_write(dev, 2, 1); ++ msleep(100); ++ ++ adapter->fe = dvb_attach(stv090x_attach, &tbs6925_stv090x_cfg, ++ &dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter, ++ STV090x_DEMODULATOR_0); ++ ++ if (adapter->fe == NULL) ++ goto err; ++ ++ adapter->fe->ops.set_voltage = tbs6925_set_voltage; ++ ++ if (dvb_attach(stb6100_attach, adapter->fe, ++ &tbs6925_stb6100_cfg, &dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6925_config = { ++ .model_name = SAA716x_MODEL_TBS6925, ++ .dev_type = SAA716x_DEV_TBS6925, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = tbs6925_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++#define SAA716x_MODEL_TBS6982 "TurboSight TBS 6982 " ++#define SAA716x_DEV_TBS6982 "DVB-S/S2" ++ ++static void tbs6982_reset_fe(struct dvb_frontend *fe, int reset_pin) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* reset frontend, active low */ ++ saa716x_gpio_set_output(dev, reset_pin); ++ saa716x_gpio_write(dev, reset_pin, 0); ++ msleep(60); ++ saa716x_gpio_write(dev, reset_pin, 1); ++ msleep(120); ++} ++ ++static void tbs6982_reset_fe0(struct dvb_frontend *fe) ++{ ++ tbs6982_reset_fe(fe, 2); ++} ++ ++static void tbs6982_reset_fe1(struct dvb_frontend *fe) ++{ ++ tbs6982_reset_fe(fe, 17); ++} ++ ++static void tbs6982_lnb_power(struct dvb_frontend *fe, ++ int enpwr_pin, int onoff) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* lnb power, active low */ ++ saa716x_gpio_set_output(dev, enpwr_pin); ++ if (onoff) ++ saa716x_gpio_write(dev, enpwr_pin, 0); ++ else ++ saa716x_gpio_write(dev, enpwr_pin, 1); ++} ++ ++static void tbs6982_lnb0_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6982_lnb_power(fe, 5, onoff); ++} ++ ++static void tbs6982_lnb1_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6982_lnb_power(fe, 3, onoff); ++} ++ ++static struct tas2101_config tbs6982_cfg[] = { ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6982_reset_fe0, ++ .lnb_power = tbs6982_lnb0_power, ++ .init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6982_reset_fe1, ++ .lnb_power = tbs6982_lnb1_power, ++ .init = {0x8a, 0x6b, 0x13, 0x70, 0x45, 0x92, 0x33}, ++ .init2 = 0, ++ } ++}; ++ ++static struct av201x_config tbs6982_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int saa716x_tbs6982_frontend_attach( ++ struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ if (count > 1) ++ goto err; ++ ++ saa716x_gpio_set_output(dev, 16); ++ saa716x_gpio_write(dev, 16, 0); ++ msleep(60); ++ saa716x_gpio_write(dev, 16, 1); ++ msleep(120); ++ ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6982_cfg[count], ++ &dev->i2c[1 - count].i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6982_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6982_config = { ++ .model_name = SAA716x_MODEL_TBS6982, ++ .dev_type = SAA716x_DEV_TBS6982, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6982_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6982SE "TurboSight TBS 6982SE " ++#define SAA716x_DEV_TBS6982SE "DVB-S/S2" ++ ++static void tbs6982se_reset_fe(struct dvb_frontend *fe, int reset_pin) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* reset frontend, active low */ ++ saa716x_gpio_set_output(dev, reset_pin); ++ saa716x_gpio_write(dev, reset_pin, 0); ++ msleep(60); ++ saa716x_gpio_write(dev, reset_pin, 1); ++ msleep(120); ++} ++ ++static void tbs6982se_reset_fe0(struct dvb_frontend *fe) ++{ ++ tbs6982se_reset_fe(fe, 2); ++} ++ ++static void tbs6982se_reset_fe1(struct dvb_frontend *fe) ++{ ++ tbs6982se_reset_fe(fe, 17); ++} ++ ++static void tbs6982se_lnb_power(struct dvb_frontend *fe, ++ int enpwr_pin, int onoff) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* lnb power, active low */ ++ saa716x_gpio_set_output(dev, enpwr_pin); ++ if (onoff) ++ saa716x_gpio_write(dev, enpwr_pin, 0); ++ else ++ saa716x_gpio_write(dev, enpwr_pin, 1); ++} ++ ++static void tbs6982se_lnb0_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6982se_lnb_power(fe, 3, onoff); ++} ++ ++static void tbs6982se_lnb1_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6982se_lnb_power(fe, 16, onoff); ++} ++ ++static struct tas2101_config tbs6982se_cfg[] = { ++ { ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6982se_reset_fe0, ++ .lnb_power = tbs6982se_lnb0_power, ++ .init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6982se_reset_fe1, ++ .lnb_power = tbs6982se_lnb1_power, ++ .init = {0x8a, 0x6b, 0x13, 0x70, 0x45, 0x92, 0x33}, ++ .init2 = 0, ++ } ++}; ++ ++static struct av201x_config tbs6982se_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int saa716x_tbs6982se_frontend_attach( ++ struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ if (count > 1) ++ goto err; ++ ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6982se_cfg[count], ++ &dev->i2c[count].i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6982se_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6982se_config = { ++ .model_name = SAA716x_MODEL_TBS6982SE, ++ .dev_type = SAA716x_DEV_TBS6982SE, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6982se_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6984 "TurboSight TBS 6984 " ++#define SAA716x_DEV_TBS6984 "DVB-S/S2" ++ ++static void saa716x_tbs6984_init(struct saa716x_dev *saa716x) ++{ ++ int i; ++ const u8 buf[] = { ++ 0xe0, 0x06, 0x66, 0x33, 0x65, ++ 0x01, 0x17, 0x06, 0xde}; ++ ++#define TBS_CK 7 ++#define TBS_CS 8 ++#define TBS_DT 11 ++ ++ /* send init bitstream through a bitbanged spi */ ++ /* set pins as output */ ++ saa716x_gpio_set_output(saa716x, TBS_CK); ++ saa716x_gpio_set_output(saa716x, TBS_CS); ++ saa716x_gpio_set_output(saa716x, TBS_DT); ++ ++ /* set all pins high */ ++ saa716x_gpio_write(saa716x, TBS_CK, 1); ++ saa716x_gpio_write(saa716x, TBS_CS, 1); ++ saa716x_gpio_write(saa716x, TBS_DT, 1); ++ msleep(20); ++ ++ /* CS low */ ++ saa716x_gpio_write(saa716x, TBS_CS, 0); ++ msleep(20); ++ /* send bitstream */ ++ for (i = 0; i < 9 * 8; i++) { ++ /* clock low */ ++ saa716x_gpio_write(saa716x, TBS_CK, 0); ++ msleep(20); ++ /* set data pin */ ++ saa716x_gpio_write(saa716x, TBS_DT, ++ ((buf[i >> 3] >> (7 - (i & 7))) & 1)); ++ /* clock high */ ++ saa716x_gpio_write(saa716x, TBS_CK, 1); ++ msleep(20); ++ } ++ /* raise cs, clk and data */ ++ saa716x_gpio_write(saa716x, TBS_CS, 1); ++ saa716x_gpio_write(saa716x, TBS_CK, 1); ++ saa716x_gpio_write(saa716x, TBS_DT, 1); ++ ++ /* power up LNB supply and control chips */ ++ saa716x_gpio_set_output(saa716x, 19); /* a0 */ ++ saa716x_gpio_set_output(saa716x, 2); /* a1 */ ++ saa716x_gpio_set_output(saa716x, 5); /* a2 */ ++ saa716x_gpio_set_output(saa716x, 3); /* a3 */ ++ ++ /* power off */ ++ saa716x_gpio_write(saa716x, 19, 1); /* a0 */ ++ saa716x_gpio_write(saa716x, 2, 1); /* a1 */ ++ saa716x_gpio_write(saa716x, 5, 1); /* a2 */ ++ saa716x_gpio_write(saa716x, 3, 1); /* a3 */ ++} ++ ++ ++static void tbs6984_lnb_pwr(struct dvb_frontend *fe, int pin, int onoff) ++{ ++ struct i2c_adapter *adapter = cx24117_get_i2c_adapter(fe); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* lnb power, active low */ ++ if (onoff) ++ saa716x_gpio_write(dev, pin , 0); ++ else ++ saa716x_gpio_write(dev, pin, 1); ++} ++ ++void tbs6984_lnb_pwr0(struct dvb_frontend *fe, int demod, int onoff) ++{ ++ tbs6984_lnb_pwr(fe, (demod == 0) ? 19 : 2, onoff); ++} ++ ++void tbs6984_lnb_pwr1(struct dvb_frontend *fe, int demod, int onoff) ++{ ++ tbs6984_lnb_pwr(fe, (demod == 0) ? 5 : 3, onoff); ++} ++ ++static struct cx24117_config tbs6984_cx24117_cfg[] = { ++ { ++ .demod_address = 0x55, ++ .lnb_power = tbs6984_lnb_pwr0, ++ }, ++ { ++ .demod_address = 0x05, ++ .lnb_power = tbs6984_lnb_pwr1, ++ }, ++}; ++ ++static struct isl6422_config tbs6984_isl6422_cfg[] = { ++ { ++ .current_max = SEC_CURRENT_570m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x08, ++ .id = 0, ++ }, ++ { ++ .current_max = SEC_CURRENT_570m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x08, ++ .id = 1, ++ } ++ ++}; ++ ++static int saa716x_tbs6984_frontend_attach( ++ struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct saa716x_i2c *i2c = &dev->i2c[1 - (count >> 1)]; ++ u8 mac[6]; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ ++ if (count > 3) ++ goto err; ++ ++ if (count == 0) ++ saa716x_tbs6984_init(dev); ++ ++ adapter->fe = dvb_attach(cx24117_attach, &tbs6984_cx24117_cfg[count >> 1], ++ &i2c->i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(isl6422_attach, adapter->fe, &i2c->i2c_adapter, ++ &tbs6984_isl6422_cfg[count & 0x01]) == NULL) ++ dev_info(&dev->pdev->dev, ++ "%s frontend %d doesn't seem to have a isl6422b on the i2c bus.\n", ++ dev->config->model_name, count); ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6984_config = { ++ .model_name = SAA716x_MODEL_TBS6984, ++ .dev_type = SAA716x_DEV_TBS6984, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 4, ++ .frontend_attach = saa716x_tbs6984_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 2 */ ++ .ts_port = 0, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 3 */ ++ .ts_port = 1, ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6985 "TurboSight TBS 6985 " ++#define SAA716x_DEV_TBS6985 "DVB-S/S2" ++ ++static void tbs6985_reset_fe(struct dvb_frontend *fe, int reset_pin) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* reset frontend, active low */ ++ saa716x_gpio_set_output(dev, reset_pin); ++ saa716x_gpio_write(dev, reset_pin, 0); ++ msleep(60); ++ saa716x_gpio_write(dev, reset_pin, 1); ++ msleep(120); ++} ++ ++static void tbs6985_reset_fe0(struct dvb_frontend *fe) ++{ ++ tbs6985_reset_fe(fe, 5); ++} ++ ++static void tbs6985_reset_fe1(struct dvb_frontend *fe) ++{ ++ tbs6985_reset_fe(fe, 2); ++} ++ ++static void tbs6985_reset_fe2(struct dvb_frontend *fe) ++{ ++ tbs6985_reset_fe(fe, 13); ++} ++ ++static void tbs6985_reset_fe3(struct dvb_frontend *fe) ++{ ++ tbs6985_reset_fe(fe, 3); ++} ++ ++static void tbs6985_lnb_power(struct dvb_frontend *fe, ++ int enpwr_pin, int onoff) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* lnb power, active low */ ++ saa716x_gpio_set_output(dev, enpwr_pin); ++ if (onoff) ++ saa716x_gpio_write(dev, enpwr_pin, 0); ++ else ++ saa716x_gpio_write(dev, enpwr_pin, 1); ++} ++ ++static void tbs6985_lnb0_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6985_lnb_power(fe, 27, onoff); ++} ++ ++static void tbs6985_lnb1_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6985_lnb_power(fe, 22, onoff); ++} ++ ++static void tbs6985_lnb2_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6985_lnb_power(fe, 19, onoff); ++} ++ ++static void tbs6985_lnb3_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6985_lnb_power(fe, 15, onoff); ++} ++ ++#undef TBS6985_TSMODE0 ++static struct tas2101_config tbs6985_cfg[] = { ++ { ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6985_reset_fe0, ++ .lnb_power = tbs6985_lnb0_power, ++#ifdef TBS6985_TSMODE0 ++ .init = {0x01, 0x32, 0x65, 0x74, 0xab, 0x98, 0x33}, ++#else ++ .init = {0x0b, 0x8a, 0x65, 0x74, 0xab, 0x98, 0xb1}, ++#endif ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6985_reset_fe1, ++ .lnb_power = tbs6985_lnb1_power, ++#ifdef TBS6985_TSMODE0 ++ .init = {0x10, 0x32, 0x54, 0xb7, 0x86, 0x9a, 0x33}, ++#else ++ .init = {0x0a, 0x8b, 0x54, 0xb7, 0x86, 0x9a, 0xb1}, ++#endif ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6985_reset_fe2, ++ .lnb_power = tbs6985_lnb2_power, ++#ifdef TBS6985_TSMODE0 ++ .init = {0x25, 0x36, 0x40, 0xb1, 0x87, 0x9a, 0x33}, ++#else ++ .init = {0xba, 0x80, 0x40, 0xb1, 0x87, 0x9a, 0xb1}, ++#endif ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6985_reset_fe3, ++ .lnb_power = tbs6985_lnb3_power, ++#ifdef TBS6985_TSMODE0 ++ .init = {0x80, 0xba, 0x21, 0x53, 0x74, 0x96, 0x33}, ++#else ++ .init = {0xba, 0x80, 0x21, 0x53, 0x74, 0x96, 0xb1}, ++#endif ++ .init2 = 0, ++ } ++}; ++ ++static struct av201x_config tbs6985_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int saa716x_tbs6985_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ ++ if (count > 3) ++ goto err; ++ ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6985_cfg[count], ++ &dev->i2c[1 - (count >> 1)].i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6985_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6985_config = { ++ .model_name = SAA716x_MODEL_TBS6985, ++ .dev_type = SAA716x_DEV_TBS6985, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 4, ++ .frontend_attach = saa716x_tbs6985_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 2 */ ++ .ts_port = 0, ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 3 */ ++ .ts_port = 1, ++ .worker = demux_worker ++ } ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6991 "TurboSight TBS 6991 " ++#define SAA716x_DEV_TBS6991 "DVB-S/S2" ++ ++static void tbs6991_reset_fe(struct dvb_frontend *fe, int reset_pin) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* reset frontend, active low */ ++ saa716x_gpio_set_output(dev, reset_pin); ++ saa716x_gpio_write(dev, reset_pin, 0); ++ msleep(60); ++ saa716x_gpio_write(dev, reset_pin, 1); ++ msleep(120); ++} ++ ++static void tbs6991_reset_fe0(struct dvb_frontend *fe) ++{ ++ tbs6991_reset_fe(fe, 20); ++} ++ ++static void tbs6991_reset_fe1(struct dvb_frontend *fe) ++{ ++ tbs6991_reset_fe(fe, 17); ++} ++ ++static void tbs6991_lnb_power(struct dvb_frontend *fe, ++ int enpwr_pin, int onoff) ++{ ++ struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0); ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *dev = i2c->saa716x; ++ ++ /* lnb power, active low */ ++ saa716x_gpio_set_output(dev, enpwr_pin); ++ if (onoff) ++ saa716x_gpio_write(dev, enpwr_pin, 0); ++ else ++ saa716x_gpio_write(dev, enpwr_pin, 1); ++} ++ ++static void tbs6991_lnb0_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6991_lnb_power(fe, 5, onoff); ++} ++ ++static void tbs6991_lnb1_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs6991_lnb_power(fe, 26, onoff); ++} ++ ++/* ++ tbs6991 seems to have different settings depending on a value that the closed ++ source driver reads from the eeprom. This is probabbly related to card HW revisons. ++ Details: ++ eeprom i2c addr = 0x1a ++ mem addr = 0xc201 ++ if value == 0x66 or value == 0x68 then tsmode = 1 else 0 ++ ++ This needs to be tested and if needed implement a function to get that value ++ and set the proper tsmode ++*/ ++#define TBS6991_TSMODE0 (0x33) ++#define TBS6991_TSMODE1 (0x31) ++#define TBS6991_TSMODE TBS6991_TSMODE0 ++static struct tas2101_config tbs6991_cfg[] = { ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6991_reset_fe0, ++ .lnb_power = tbs6991_lnb0_power, ++ .init = {0x10, 0x32, 0x54, 0x76, 0xa8, 0x9b, TBS6991_TSMODE}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = tbs6991_reset_fe1, ++ .lnb_power = tbs6991_lnb1_power, ++ .init = {0x30, 0x21, 0x54, 0x76, 0xb8, 0x9a, TBS6991_TSMODE}, ++ .init2 = 0, ++ } ++}; ++ ++static struct av201x_config tbs6991_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int saa716x_tbs6991_frontend_attach( ++ struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ int ret; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ if (count > 1) ++ goto err; ++ ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6991_cfg[count], ++ &dev->i2c[1-count].i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6991_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ saa716x_gpio_set_input(dev,count?3:14); ++ msleep(1); ++ saa716x_gpio_set_input(dev,count?6:2); ++ msleep(1); ++ ret = tbsci_i2c_probe(adapter,count?4:3); ++ if(!ret) ++ tbsci_init(adapter,count,2); ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6991_config = { ++ .model_name = SAA716x_MODEL_TBS6991, ++ .dev_type = SAA716x_DEV_TBS6991, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6991_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 1, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 3, /* using FGPI 1 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++ ++#define SAA716x_MODEL_TBS6991SE "TurboSight TBS 6991SE " ++#define SAA716x_DEV_TBS6991SE "DVB-S/S2 " ++ ++static struct tas2101_config tbs6991se_cfg[] = { ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = NULL, ++ .lnb_power = tbs6991_lnb0_power, ++ .init = {0x10, 0x32, 0x54, 0x76, 0x8b, 0x9a, 0x33}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = NULL, ++ .lnb_power = tbs6991_lnb1_power, ++ .init = {0x10, 0x32, 0x54, 0x76, 0x8b, 0x9a, 0x33}, ++ .init2 = 0, ++ } ++}; ++ ++static int saa716x_tbs6991se_frontend_attach( ++ struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ int ret; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ if (count > 1) ++ goto err; ++ ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6991se_cfg[count], ++ &dev->i2c[1-count].i2c_adapter); ++ if (adapter->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6991_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ saa716x_gpio_set_input(dev,count ?6:2); ++ msleep(1); ++ saa716x_gpio_set_input(dev,count?3:14); ++ msleep(1); ++ saa716x_gpio_set_output(dev,count?17:20); ++ msleep(1); ++ ret = tbsci_i2c_probe(adapter,count?4:3); ++ if(!ret) ++ tbsci_init(adapter,count,8); ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6991se_config = { ++ .model_name = SAA716x_MODEL_TBS6991SE, ++ .dev_type = SAA716x_DEV_TBS6991SE, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6991se_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { ++ /* adapter 0 */ ++ .ts_port = 1, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* adapter 1 */ ++ .ts_port = 3, /* using FGPI 1 */ ++ .worker = demux_worker ++ }, ++ }, ++}; ++ ++#define SAA716x_MODEL_TBS6983 "TurboSight TBS 6983 " ++#define SAA716x_DEV_TBS6983 "DVB-S/S2" ++ ++static struct stv0910_cfg tbs6983_stv0910_cfg = { ++ .adr = 0x68, ++ .parallel = 1, ++ .rptlvl = 3, ++ .clk = 30000000, ++ .dual_tuner = 1, ++}; ++ ++static struct stv6120_cfg tbs6983_stv6120_cfg = { ++ .adr = 0x60, ++ .xtal = 30000, ++ .Rdiv = 2, ++}; ++ ++static int saa716x_tbs6983_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ u8 adapter_gpio_0 = adapter->count ? 16 : 5; ++ u8 adapter_gpio_1 = adapter->count ? 2 : 3; ++ ++ saa716x_gpio_set_output(saa716x, adapter_gpio_0); ++ saa716x_gpio_set_output(saa716x, adapter_gpio_1); ++ msleep(1); ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ saa716x_gpio_write(saa716x, adapter_gpio_0, 0); ++ saa716x_gpio_write(saa716x, adapter_gpio_1, 0); ++ break; ++ case SEC_VOLTAGE_18: ++ saa716x_gpio_write(saa716x, adapter_gpio_0, 1); ++ saa716x_gpio_write(saa716x, adapter_gpio_1, 0); ++ break; ++ case SEC_VOLTAGE_OFF: ++ saa716x_gpio_write(saa716x, adapter_gpio_0, 1); ++ saa716x_gpio_write(saa716x, adapter_gpio_1, 1); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int saa716x_tbs6983_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ u8 mac[6]; ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n", ++ dev->config->model_name, count); ++ ++ if (count == 0) { ++ saa716x_gpio_set_output(dev, 17); ++ msleep(1); ++ saa716x_gpio_write(dev, 17, 0); ++ msleep(50); ++ saa716x_gpio_write(dev, 17, 1); ++ msleep(100); ++ } ++ ++ adapter->fe = dvb_attach(stv0910_attach, ++ &dev->i2c[1].i2c_adapter, ++ &tbs6983_stv0910_cfg, ++ count & 1); ++ ++ if (adapter->fe == NULL) { ++ goto err; ++ } ++ ++ if (dvb_attach(stv6120_attach, adapter->fe, &dev->i2c[1].i2c_adapter, ++ &tbs6983_stv6120_cfg,1 - (count & 1)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_dbg(&dev->pdev->dev, ++ "%s frontend %d tuner attach failed\n", ++ dev->config->model_name, count); ++ goto err; ++ } ++ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ adapter->fe->ops.set_voltage = saa716x_tbs6983_set_voltage; ++ saa716x_gpio_write(dev, count ? 2 : 3, 1); /* LNB power off */ ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_tbs6983_config = { ++ .model_name = SAA716x_MODEL_TBS6983, ++ .dev_type = SAA716x_DEV_TBS6983, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6983_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_400, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config = { ++ { // adapter 0 ++ .ts_port = 3, ++ .worker = demux_worker ++ }, ++ { // adapter 1 ++ .ts_port = 1, ++ .worker = demux_worker ++ }, ++ } ++}; ++#define SAA716x_MODEL_TBS6290 "TurboSight TBS 6290 " ++#define SAA716x_DEV_TBS6290 "DVB-T/T2/C+2xCI" ++ ++static int saa716x_tbs6290_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *dev = adapter->saa716x; ++ struct i2c_adapter *i2cadapter; ++ struct i2c_client *client; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ u8 mac[6]; ++ int ret; ++ if (count > 1) ++ goto err; ++ ++ /* attach demod */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &i2cadapter; ++ si2168_config.fe = &adapter->fe; ++ si2168_config.ts_mode = SI2168_TS_PARALLEL; ++ si2168_config.ts_clock_gapped = true; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client = i2c_new_device(&dev->i2c[1 - count].i2c_adapter, &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ goto err; ++ } ++ adapter->i2c_client_demod = client; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client = i2c_new_device(i2cadapter, &info); ++ if (client == NULL || client->dev.driver == NULL) { ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ module_put(adapter->i2c_client_demod->dev.driver->owner); ++ i2c_unregister_device(adapter->i2c_client_demod); ++ goto err; ++ } ++ adapter->i2c_client_tuner = client; ++ ++ saa716x_gpio_set_input(dev,count?2:6); ++ msleep(1); ++ saa716x_gpio_set_input(dev,count?14:3); ++ msleep(1); ++ saa716x_gpio_set_input(dev,count?20:14); ++ msleep(1); ++ ret = tbsci_i2c_probe(adapter,count?4:3); ++ if(!ret) ++ tbsci_init(adapter,count,9); ++ ++ strlcpy(adapter->fe->ops.info.name,dev->config->model_name,52); ++ strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52); ++ ++ dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n", ++ dev->config->model_name, count); ++ ++ if (!saa716x_tbs_read_mac(dev,count,mac)) { ++ memcpy(adapter->dvb_adapter.proposed_mac, mac, 6); ++ dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac); ++ } ++ ++ return 0; ++err: ++ dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n", ++ dev->config->model_name, count); ++ return -ENODEV; ++ ++ ++} ++ ++static struct saa716x_config saa716x_tbs6290_config = { ++ .model_name = SAA716x_MODEL_TBS6290, ++ .dev_type = SAA716x_DEV_TBS6290, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_tbs6290_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_POLLING, ++ .adap_config ={ ++ { ++ .ts_port = 1, ++ .worker = demux_worker ++ }, ++ { ++ .ts_port = 3, ++ .worker = demux_worker ++ }, ++ ++ } ++ ++}; ++static struct pci_device_id saa716x_budget_pci_table[] = { ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */ ++ MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config), ++ MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6284, TBS6284, SAA7160, &saa716x_tbs6284_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6280, TBS6280, SAA7160, &saa716x_tbs6280_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6281, TBS6281, SAA7160, &saa716x_tbs6281_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6285, TBS6285, SAA7160, &saa716x_tbs6285_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6220, TBS6220, SAA7160, &saa716x_tbs6220_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6221, TBS6221, SAA7160, &saa716x_tbs6221_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6922, TBS6922, SAA7160, &saa716x_tbs6922_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6923, TBS6923, SAA7160, &saa716x_tbs6923_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6925, TBS6925, SAA7160, &saa716x_tbs6925_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6982, TBS6982, SAA7160, &saa716x_tbs6982_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6982, TBS6982SE, SAA7160, &saa716x_tbs6982se_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6984, TBS6984, SAA7160, &saa716x_tbs6984_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6985, TBS6985, SAA7160, &saa716x_tbs6985_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6985, TBS6985+1, SAA7160, &saa716x_tbs6985_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6991, TBS6991, SAA7160, &saa716x_tbs6991_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6991, TBS6991+1, SAA7160, &saa716x_tbs6991se_config), ++ MAKE_ENTRY(TECHNOTREND, TT4100, SAA7160, &saa716x_tbs6922_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6983, TBS6983, SAA7160, &saa716x_tbs6983_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6983, TBS6983+1, SAA7160, &saa716x_tbs6983_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS7220, TBS7220, SAA7160, &saa716x_tbs7220_config), ++ MAKE_ENTRY(TURBOSIGHT_TBS6290, TBS6290, SAA7160, &saa716x_tbs6290_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table); ++ ++static struct pci_driver saa716x_budget_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_budget_pci_table, ++ .probe = saa716x_budget_pci_probe, ++ .remove = saa716x_budget_pci_remove, ++}; ++ ++module_pci_driver(saa716x_budget_pci_driver); ++ ++MODULE_DESCRIPTION("SAA716x Budget driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/pci/saa716x/saa716x_budget.h b/drivers/media/pci/saa716x/saa716x_budget.h +new file mode 100644 +index 0000000..d3082fe +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_budget.h +@@ -0,0 +1,67 @@ ++#ifndef __SAA716x_BUDGET_H ++#define __SAA716x_BUDGET_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define TWINHAN_VP_3071 0x0039 ++#define TWINHAN_VP_1028 0x0044 ++#define TWINHAN_VP_6002 0x0047 ++ ++#define KNC_One 0x1894 ++#define KNC_Dual_S2 0x0110 ++ ++#define TECHNISAT 0x1AE4 ++#define SKYSTAR2_EXPRESS_HD 0x0700 ++ ++#define TURBOSIGHT_TBS6284 0x6284 ++#define TBS6284 0x0001 ++ ++#define TURBOSIGHT_TBS6280 0x6280 ++#define TBS6280 0x0011 ++ ++#define TURBOSIGHT_TBS6281 0x6281 ++#define TBS6281 0x0001 ++ ++#define TURBOSIGHT_TBS6285 0x6285 ++#define TBS6285 0x0001 ++ ++#define TURBOSIGHT_TBS6220 0x6220 ++#define TBS6220 0x0002 ++ ++#define TURBOSIGHT_TBS6221 0x6221 ++#define TBS6221 0x0001 ++ ++#define TURBOSIGHT_TBS6922 0x6922 ++#define TBS6922 0x0001 ++ ++#define TURBOSIGHT_TBS6923 0x6923 ++#define TBS6923 0x0001 ++ ++#define TURBOSIGHT_TBS6925 0x6925 ++#define TBS6925 0x0001 ++ ++#define TURBOSIGHT_TBS6982 0x6982 ++#define TBS6982 0x0001 ++#define TBS6982SE 0x0002 ++ ++#define TURBOSIGHT_TBS6984 0x6984 ++#define TBS6984 0x0013 ++ ++#define TURBOSIGHT_TBS6985 0x6985 ++#define TBS6985 0x0001 ++ ++#define TURBOSIGHT_TBS6991 0x6991 ++#define TBS6991 0x0001 ++ ++#define TURBOSIGHT_TBS6983 0x6983 ++#define TBS6983 0x0001 ++ ++#define TECHNOTREND 0x13c2 ++#define TT4100 0x3010 ++ ++#define TURBOSIGHT_TBS7220 0x7220 ++#define TBS7220 0x0001 ++ ++#define TURBOSIGHT_TBS6290 0x6290 ++#define TBS6290 0x0001 ++ ++#endif /* __SAA716x_BUDGET_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_cgu.c b/drivers/media/pci/saa716x/saa716x_cgu.c +new file mode 100644 +index 0000000..f3af28f +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_cgu.c +@@ -0,0 +1,539 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_cgu_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++u32 cgu_clk[14] = { ++ CGU_FDC_0, ++ CGU_FDC_1, ++ CGU_FDC_2, ++ CGU_FDC_3, ++ CGU_FDC_4, ++ CGU_FDC_5, ++ CGU_FDC_6, ++ CGU_FDC_7, ++ CGU_FDC_8, ++ CGU_FDC_9, ++ CGU_FDC_10, ++ CGU_FDC_11, ++ CGU_FDC_12, ++ CGU_FDC_13 ++}; ++ ++char *clk_desc[14] = { ++ "Clk PSS", ++ "Clk DCS", ++ "Clk SPI", ++ "Clk I2C/Boot", ++ "Clk PHI", ++ "Clk VI0", ++ "Clk VI1", ++ "Clk FGPI0", ++ "Clk FGPI1", ++ "Clk FGPI2", ++ "Clk FGPI3", ++ "Clk AI0", ++ "Clk AI1", ++ "Clk Phy" ++}; ++ ++int saa716x_getbootscript_setup(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 i; ++ s8 N = 0; ++ s16 M = 0; ++ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, CGU_PCR_RUN); /* GREG */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, CGU_PCR_RUN); /* PSS_MMU */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, CGU_PCR_RUN); /* PSS_DTL2MTL */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, CGU_PCR_RUN); /* MSI */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, CGU_PCR_RUN); /* I2C */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, CGU_PCR_RUN); /* PHI */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, CGU_PCR_RUN); /* GPIO */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, CGU_PCR_RUN); /* SPI */ ++ SAA716x_EPWR(CGU, CGU_PCR_1_1, CGU_PCR_RUN); /* DCS */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_1, CGU_PCR_RUN); /* BOOT */ ++ ++ /* get all dividers */ ++ for (i = 0; i < CGU_CLKS; i++) { ++ cgu->clk_boot_div[i] = SAA716x_EPRD(CGU, cgu_clk[i]); ++ cgu->clk_curr_div[i] = cgu->clk_boot_div[i]; ++ ++ N = (cgu->clk_boot_div[i] >> 11) & 0xff; ++ N *= -1; ++ M = ((cgu->clk_boot_div[i] >> 3) & 0xff) + N; ++ ++ if (M) ++ cgu->clk_freq[i] = (u32 ) N * PLL_FREQ / (u32 ) M; ++ else ++ cgu->clk_freq[i] = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain %d: %s <0x%02x> Divider: 0x%x --> N=%d, M=%d, freq=%d", ++ i, clk_desc[i], cgu_clk[i], cgu->clk_boot_div[i], N, M, cgu->clk_freq[i]); ++ } ++ /* store clock settings */ ++ cgu->clk_vi_0[0] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[1] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[2] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_1[0] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[1] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[2] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ ++ return 0; ++} ++ ++int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ SAA716x_CGU_CLKRUN(7); ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ SAA716x_CGU_CLKRUN(8); ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ SAA716x_CGU_CLKRUN(9); ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ SAA716x_CGU_CLKRUN(10); ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ SAA716x_CGU_CLKRUN(11); ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ SAA716x_CGU_CLKRUN(12); ++ break; ++ ++ case PORT_ALL: ++ SAA716x_CGU_CLKRUN(5); ++ SAA716x_CGU_CLKRUN(6); ++ SAA716x_CGU_CLKRUN(7); ++ SAA716x_CGU_CLKRUN(8); ++ SAA716x_CGU_CLKRUN(9); ++ SAA716x_CGU_CLKRUN(10); ++ SAA716x_CGU_CLKRUN(11); ++ SAA716x_CGU_CLKRUN(12); ++ ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ cgu->clk_int_port[PORT_AI0] = 1; ++ cgu->clk_int_port[PORT_AI1] = 1; ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ } ++ ++ /* wait for PLL */ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_7, 0x4); /* FGPI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_7, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_8, 0x5); /* FGPI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_8, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_9, 0x6); /* FGPI 2 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_9, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_10, 0x7); /* FGPI 3 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_10, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_11, 0x8); /* AI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_11, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_12, 0x9); /* AI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_12, 0x0); /* disable divider */ ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ ++ } ++ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_get_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 *frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_VI0: ++ case CLK_DOMAIN_VI1: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ *frequency = cgu->clk_freq[domain]; ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ *frequency = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ *frequency =cgu->clk_freq[CLK_DOMAIN_VI1]; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Error Clock domain <%02x>", domain); ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_set_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u32 M = 1, N = 1, reset, i; ++ s8 N_tmp, M_tmp, sub, add, lsb; ++ ++ ++ if (cgu->clk_freq_min > frequency) ++ frequency = cgu->clk_freq_min; ++ ++ if (cgu->clk_freq_max < frequency) ++ frequency = cgu->clk_freq_max; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ ++ if (frequency == cgu->clk_freq[domain]) ++ return 0; /* same frequency */ ++ break; ++ ++ case CLK_DOMAIN_VI0: ++ ++ if (frequency == cgu->clk_vi_0[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_0[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI1: ++ if (frequency == cgu->clk_vi_1[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_1[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ if (frequency == cgu->clk_vi_0[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_0[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI0; /* change domain */ ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ if (frequency == cgu->clk_vi_1[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_1[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI1; /* change domain */ ++ break; ++ } ++ ++ /* calculate divider */ ++ do { ++ M = (N * PLL_FREQ) / frequency; ++ if (M == 0) ++ N++; ++ ++ } while (M == 0); ++ ++ /* calculate frequency */ ++ cgu->clk_freq[domain] = (N * PLL_FREQ) / M; ++ ++ N_tmp = N & 0xff; ++ M_tmp = M & 0xff; ++ sub = -N_tmp; ++ add = M_tmp - N_tmp; ++ lsb = 4; /* run */ ++ ++ if (((10 * N) / M) <= 5) ++ lsb |= 1; /* stretch */ ++ ++ /* store new divider */ ++ cgu->clk_curr_div[domain] = sub & 0xff; ++ cgu->clk_curr_div[domain] <<= 8; ++ cgu->clk_curr_div[domain] |= add & 0xff; ++ cgu->clk_curr_div[domain] <<= 3; ++ cgu->clk_curr_div[domain] |= lsb; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain <0x%02x> Frequency <%d> Set Freq <%d> N=%d M=%d Divider <0x%02x>", ++ domain, ++ frequency, ++ cgu->clk_freq[domain], ++ N, ++ M, ++ cgu->clk_curr_div[domain]); ++ ++ reset = 0; ++ ++ /* Reset */ ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain] | 0x2); ++ ++ /* Reset disable */ ++ for (i = 0; i < 1000; i++) { ++ udelay(10); ++ reset = SAA716x_EPRD(CGU, cgu_clk[domain]); ++ ++ if (cgu->clk_curr_div[domain] == reset) ++ break; ++ } ++ ++ if (cgu->clk_curr_div[domain] != reset) ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain]); ++ ++ return 0; ++} ++ ++int saa716x_cgu_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ cgu->clk_freq_min = PLL_FREQ / 255; ++ if (PLL_FREQ > (cgu->clk_freq_min * 255)) ++ cgu->clk_freq_min++; ++ ++ cgu->clk_freq_max = PLL_FREQ; ++ ++ saa716x_getbootscript_setup(saa716x); ++ saa716x_set_clk_internal(saa716x, PORT_ALL); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_cgu_init); +diff --git a/drivers/media/pci/saa716x/saa716x_cgu.h b/drivers/media/pci/saa716x/saa716x_cgu.h +new file mode 100644 +index 0000000..5353cf2 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_cgu.h +@@ -0,0 +1,61 @@ ++#ifndef __SAA716x_CGU_H ++#define __SAA716x_CGU_H ++ ++#define PLL_FREQ 2500 ++ ++#define SAA716x_CGU_CLKRUN(__reg) do { \ ++ SAA716x_EPWR(CGU, CGU_PCR_##__reg, CGU_PCR_RUN); /* Run */ \ ++ SAA716x_EPWR(CGU, CGU_SCR_##__reg, CGU_SCR_ENF1); /* Switch */ \ ++ SAA716x_EPWR(CGU, CGU_FS1_##__reg, 0x00000000); /* PLL Clk */ \ ++ SAA716x_EPWR(CGU, CGU_ESR_##__reg, CGU_ESR_FD_EN); /* Frac div */ \ ++} while (0) ++ ++enum saa716x_clk_domain { ++ CLK_DOMAIN_PSS = 0, ++ CLK_DOMAIN_DCS = 1, ++ CLK_DOMAIN_SPI = 2, ++ CLK_DOMAIN_I2C = 3, ++ CLK_DOMAIN_PHI = 4, ++ CLK_DOMAIN_VI0 = 5, ++ CLK_DOMAIN_VI1 = 6, ++ CLK_DOMAIN_FGPI0 = 7, ++ CLK_DOMAIN_FGPI1 = 8, ++ CLK_DOMAIN_FGPI2 = 9, ++ CLK_DOMAIN_FGPI3 = 10, ++ CLK_DOMAIN_AI0 = 11, ++ CLK_DOMAIN_AI1 = 12, ++ CLK_DOMAIN_PHY = 13, ++ CLK_DOMAIN_VI0VBI = 14, ++ CLK_DOMAIN_VI1VBI = 15 ++}; ++ ++#define PORT_VI0_VIDEO 0 ++#define PORT_VI0_VBI 2 ++#define PORT_VI1_VIDEO 3 ++#define PORT_VI1_VBI 5 ++#define PORT_FGPI0 6 ++#define PORT_FGPI1 7 ++#define PORT_FGPI2 8 ++#define PORT_FGPI3 9 ++#define PORT_AI0 10 ++#define PORT_AI1 11 ++#define PORT_ALL 12 ++ ++#define CGU_CLKS 14 ++ ++struct saa716x_cgu { ++ u8 clk_int_port[12]; ++ u32 clk_vi_0[3]; ++ u32 clk_vi_1[3]; ++ u32 clk_boot_div[CGU_CLKS]; ++ u32 clk_curr_div[CGU_CLKS]; ++ u32 clk_freq[CGU_CLKS]; ++ u32 clk_freq_min; ++ u32 clk_freq_max; ++}; ++ ++extern int saa716x_cgu_init(struct saa716x_dev *saa716x); ++extern int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port); ++extern int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port); ++ ++#endif /* __SAA716x_CGU_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_cgu_reg.h b/drivers/media/pci/saa716x/saa716x_cgu_reg.h +new file mode 100644 +index 0000000..f7d82ae +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_cgu_reg.h +@@ -0,0 +1,178 @@ ++#ifndef __SAA716x_CGU_REG_H ++#define __SAA716x_CGU_REG_H ++ ++/* -------------- CGU Registers -------------- */ ++ ++#define CGU_SCR_0 0x000 ++#define CGU_SCR_1 0x004 ++#define CGU_SCR_2 0x008 ++#define CGU_SCR_3 0x00c ++#define CGU_SCR_4 0x010 ++#define CGU_SCR_5 0x014 ++#define CGU_SCR_6 0x018 ++#define CGU_SCR_7 0x01c ++#define CGU_SCR_8 0x020 ++#define CGU_SCR_9 0x024 ++#define CGU_SCR_10 0x028 ++#define CGU_SCR_11 0x02c ++#define CGU_SCR_12 0x030 ++#define CGU_SCR_13 0x034 ++#define CGU_SCR_STOP (0x00000001 << 3) ++#define CGU_SCR_RESET (0x00000001 << 2) ++#define CGU_SCR_ENF2 (0x00000001 << 1) ++#define CGU_SCR_ENF1 (0x00000001 << 0) ++ ++#define CGU_FS1_0 0x038 ++#define CGU_FS1_1 0x03c ++#define CGU_FS1_2 0x040 ++#define CGU_FS1_3 0x044 ++#define CGU_FS1_4 0x048 ++#define CGU_FS1_5 0x04c ++#define CGU_FS1_6 0x050 ++#define CGU_FS1_7 0x054 ++#define CGU_FS1_8 0x058 ++#define CGU_FS1_9 0x05c ++#define CGU_FS1_10 0x060 ++#define CGU_FS1_11 0x064 ++#define CGU_FS1_12 0x068 ++#define CGU_FS1_13 0x06c ++#define CGU_FS1_PLL (0x00000000 << 0) ++ ++ ++#define CGU_FS2_0 0x070 ++#define CGU_FS2_1 0x074 ++#define CGU_FS2_2 0x078 ++#define CGU_FS2_3 0x07c ++#define CGU_FS2_4 0x080 ++#define CGU_FS2_5 0x084 ++#define CGU_FS2_6 0x088 ++#define CGU_FS2_7 0x08c ++#define CGU_FS2_8 0x090 ++#define CGU_FS2_9 0x094 ++#define CGU_FS2_10 0x098 ++#define CGU_FS2_11 0x09c ++#define CGU_FS2_12 0x0a0 ++#define CGU_FS2_13 0x0a4 ++ ++#define CGU_SSR_0 0x0a8 ++#define CGU_SSR_1 0x0ac ++#define CGU_SSR_2 0x0b0 ++#define CGU_SSR_3 0x0b4 ++#define CGU_SSR_4 0x0b8 ++#define CGU_SSR_5 0x0bc ++#define CGU_SSR_6 0x0c0 ++#define CGU_SSR_7 0x0c4 ++#define CGU_SSR_8 0x0c8 ++#define CGU_SSR_9 0x0cc ++#define CGU_SSR_10 0x0d0 ++#define CGU_SSR_11 0x0d4 ++#define CGU_SSR_12 0x0d8 ++#define CGU_SSR_13 0x0dc ++ ++#define CGU_PCR_0_0 0x0e0 ++#define CGU_PCR_0_1 0x0e4 ++#define CGU_PCR_0_2 0x0e8 ++#define CGU_PCR_0_3 0x0ec ++#define CGU_PCR_0_4 0x0f0 ++#define CGU_PCR_0_5 0x0f4 ++#define CGU_PCR_0_6 0x0f8 ++#define CGU_PCR_0_7 0x0fc ++#define CGU_PCR_1_0 0x100 ++#define CGU_PCR_1_1 0x104 ++#define CGU_PCR_2_0 0x108 ++#define CGU_PCR_2_1 0x10c ++#define CGU_PCR_3_0 0x110 ++#define CGU_PCR_3_1 0x114 ++#define CGU_PCR_3_2 0x118 ++#define CGU_PCR_4_0 0x11c ++#define CGU_PCR_4_1 0x120 ++#define CGU_PCR_5 0x124 ++#define CGU_PCR_6 0x128 ++#define CGU_PCR_7 0x12c ++#define CGU_PCR_8 0x130 ++#define CGU_PCR_9 0x134 ++#define CGU_PCR_10 0x138 ++#define CGU_PCR_11 0x13c ++#define CGU_PCR_12 0x140 ++#define CGU_PCR_13 0x144 ++#define CGU_PCR_WAKE_EN (0x00000001 << 2) ++#define CGU_PCR_AUTO (0x00000001 << 1) ++#define CGU_PCR_RUN (0x00000001 << 0) ++ ++ ++#define CGU_PSR_0_0 0x148 ++#define CGU_PSR_0_1 0x14c ++#define CGU_PSR_0_2 0x150 ++#define CGU_PSR_0_3 0x154 ++#define CGU_PSR_0_4 0x158 ++#define CGU_PSR_0_5 0x15c ++#define CGU_PSR_0_6 0x160 ++#define CGU_PSR_0_7 0x164 ++#define CGU_PSR_1_0 0x168 ++#define CGU_PSR_1_1 0x16c ++#define CGU_PSR_2_0 0x170 ++#define CGU_PSR_2_1 0x174 ++#define CGU_PSR_3_0 0x178 ++#define CGU_PSR_3_1 0x17c ++#define CGU_PSR_3_2 0x180 ++#define CGU_PSR_4_0 0x184 ++#define CGU_PSR_4_1 0x188 ++#define CGU_PSR_5 0x18c ++#define CGU_PSR_6 0x190 ++#define CGU_PSR_7 0x194 ++#define CGU_PSR_8 0x198 ++#define CGU_PSR_9 0x19c ++#define CGU_PSR_10 0x1a0 ++#define CGU_PSR_11 0x1a4 ++#define CGU_PSR_12 0x1a8 ++#define CGU_PSR_13 0x1ac ++ ++#define CGU_ESR_0_0 0x1b0 ++#define CGU_ESR_0_1 0x1b4 ++#define CGU_ESR_0_2 0x1b8 ++#define CGU_ESR_0_3 0x1bc ++#define CGU_ESR_0_4 0x1c0 ++#define CGU_ESR_0_5 0x1c4 ++#define CGU_ESR_0_6 0x1c8 ++#define CGU_ESR_0_7 0x1cc ++#define CGU_ESR_1_0 0x1d0 ++#define CGU_ESR_1_1 0x1d4 ++#define CGU_ESR_2_0 0x1d8 ++#define CGU_ESR_2_1 0x1dc ++#define CGU_ESR_3_0 0x1e0 ++#define CGU_ESR_3_1 0x1e4 ++#define CGU_ESR_3_2 0x1e8 ++#define CGU_ESR_4_0 0x1ec ++#define CGU_ESR_4_1 0x1f0 ++#define CGU_ESR_5 0x1f4 ++#define CGU_ESR_6 0x1f8 ++#define CGU_ESR_7 0x1fc ++#define CGU_ESR_8 0x200 ++#define CGU_ESR_9 0x204 ++#define CGU_ESR_10 0x208 ++#define CGU_ESR_11 0x20c ++#define CGU_ESR_12 0x210 ++#define CGU_ESR_13 0x214 ++#define CGU_ESR_FD_EN (0x00000001 << 0) ++ ++#define CGU_FDC_0 0x218 ++#define CGU_FDC_1 0x21c ++#define CGU_FDC_2 0x220 ++#define CGU_FDC_3 0x224 ++#define CGU_FDC_4 0x228 ++#define CGU_FDC_5 0x22c ++#define CGU_FDC_6 0x230 ++#define CGU_FDC_7 0x234 ++#define CGU_FDC_8 0x238 ++#define CGU_FDC_9 0x23c ++#define CGU_FDC_10 0x240 ++#define CGU_FDC_11 0x244 ++#define CGU_FDC_12 0x248 ++#define CGU_FDC_13 0x24c ++#define CGU_FDC_STRETCH (0x00000001 << 0) ++#define CGU_FDC_RESET (0x00000001 << 1) ++#define CGU_FDC_RUN1 (0x00000001 << 2) ++#define CGU_FDC_MADD (0x000000ff << 3) ++#define CGU_FDC_MSUB (0x000000ff << 11) ++ ++#endif /* __SAA716x_CGU_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_dcs_reg.h b/drivers/media/pci/saa716x/saa716x_dcs_reg.h +new file mode 100644 +index 0000000..26dba68 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_dcs_reg.h +@@ -0,0 +1,56 @@ ++#ifndef __SAA716x_DCS_REG_H ++#define __SAA716x_DCS_REG_H ++ ++/* -------------- DCS Registers -------------- */ ++ ++#define DCSC_CTRL 0x000 ++#define DCSC_SEL_PLLDI (0x03ffffff << 5) ++#define DCSC_TOUT_SEL (0x0000000f << 1) ++#define DCSC_TOUT_OFF (0x00000001 << 0) ++ ++#define DCSC_ADDR 0x00c ++#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) ++ ++#define DCSC_STAT 0x010 ++#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) ++#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) ++#define DCSC_ERR_TOUT_READ (0x00000001 << 8) ++#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) ++#define DCSC_ERR_ACK (0x00000001 << 1) ++ ++#define DCSC_FEATURES 0x040 ++#define DCSC_UNIQUE_ID (0x00000007 << 16) ++#define DCSC_SECURITY (0x00000001 << 14) ++#define DCSC_NUM_BASE_REGS (0x00000003 << 11) ++#define DCSC_NUM_TARGETS (0x0000001f << 5) ++#define DCSC_NUM_INITIATORS (0x0000001f << 0) ++ ++#define DCSC_BASE_REG0 0x100 ++#define DCSC_BASE_N_REG (0x00000fff << 20) ++ ++#define DCSC_INT_CLR_ENABLE 0xfd8 ++#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_ENABLE 0xfdc ++#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_STATUS 0xfe0 ++#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) ++#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_ENABLE 0xfe4 ++#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_CLR_STATUS 0xfe8 ++#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_STATUS 0xfec ++#define DCSC_INT_SET_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ERROR (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_DCS_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_dma.c b/drivers/media/pci/saa716x/saa716x_dma.c +new file mode 100644 +index 0000000..5404654 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_dma.c +@@ -0,0 +1,310 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "saa716x_dma.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++/* Allocates one page of memory, which is stores the data of one ++ * 716x page table. The result gets stored in the passed DMA buffer ++ * structure. ++ */ ++static int saa716x_allocate_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "SG Page table allocate"); ++ dmabuf->mem_ptab_virt = (void *) __get_free_page(GFP_KERNEL); ++ ++ if (dmabuf->mem_ptab_virt == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Out of pages !"); ++ return -ENOMEM; ++ } ++ ++ dmabuf->mem_ptab_phys = dma_map_single(&pdev->dev, ++ dmabuf->mem_ptab_virt, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ if (dmabuf->mem_ptab_phys == 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: map memory failed !"); ++ return -ENOMEM; ++ } ++ ++ BUG_ON(!(((unsigned long) dmabuf->mem_ptab_phys % SAA716x_PAGE_SIZE) == 0)); ++ ++ return 0; ++} ++ ++static void saa716x_free_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG Page table free"); ++ ++ /* free physical PCI memory */ ++ if (dmabuf->mem_ptab_phys != 0) { ++ dma_unmap_single(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ dmabuf->mem_ptab_phys = 0; ++ } ++ ++ /* free kernel memory */ ++ if (dmabuf->mem_ptab_virt != NULL) { ++ free_page((unsigned long) dmabuf->mem_ptab_virt); ++ dmabuf->mem_ptab_virt = NULL; ++ } ++} ++ ++static void saa716x_dmabuf_sgfree(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG free"); ++ ++ dmabuf->mem_virt = NULL; ++ if (dmabuf->mem_virt_noalign != NULL) { ++ if (dmabuf->dma_type == SAA716x_DMABUF_INT) ++ vfree(dmabuf->mem_virt_noalign); ++ ++ dmabuf->mem_virt_noalign = NULL; ++ } ++ ++ if (dmabuf->sg_list != NULL) { ++ kfree(dmabuf->sg_list); ++ dmabuf->sg_list = NULL; ++ } ++} ++ ++/* ++ * Create a SG, when an allocated buffer is passed to it, ++ * otherwise the needed memory gets allocated by itself ++ */ ++static int saa716x_dmabuf_sgalloc(struct saa716x_dmabuf *dmabuf, void *buf, int size) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct scatterlist *list; ++ struct page *pg; ++ ++ int i, pages; ++ ++ BUG_ON(!(size > 0)); ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG allocate"); ++ ++ if ((size % SAA716x_PAGE_SIZE) != 0) /* calculate required pages */ ++ pages = size / SAA716x_PAGE_SIZE + 1; ++ else ++ pages = size / SAA716x_PAGE_SIZE; ++ ++ /* Allocate memory for SG list */ ++ dmabuf->sg_list = kzalloc(sizeof (struct scatterlist) * pages, GFP_KERNEL); ++ if (dmabuf->sg_list == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for scatterlist."); ++ return -ENOMEM; ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SG table"); ++ sg_init_table(dmabuf->sg_list, pages); ++ ++ if (buf == NULL) { ++ ++ /* allocate memory, unaligned */ ++ dmabuf->mem_virt_noalign = vmalloc((pages + 1) * SAA716x_PAGE_SIZE); ++ if (dmabuf->mem_virt_noalign == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for buffer"); ++ return -ENOMEM; ++ } ++ //memset(dmabuf->mem_virt_noalign, 0, (pages + 1) * SAA716x_PAGE_SIZE); ++ ++ /* align memory to page */ ++ dmabuf->mem_virt = (void *) PAGE_ALIGN (((unsigned long) dmabuf->mem_virt_noalign)); ++ ++ BUG_ON(!((((unsigned long) dmabuf->mem_virt) % SAA716x_PAGE_SIZE) == 0)); ++ } else { ++ dmabuf->mem_virt = buf; ++ } ++ ++ dmabuf->list_len = pages; /* scatterlist length */ ++ list = dmabuf->sg_list; ++ ++ dprintk(SAA716x_DEBUG, 1, "Allocating SG pages"); ++ for (i = 0; i < pages; i++) { ++ if (buf == NULL) ++ pg = vmalloc_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ else ++ pg = virt_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ ++ BUG_ON(pg == NULL); ++ sg_set_page(list, pg, SAA716x_PAGE_SIZE, 0); ++ list = sg_next(list); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Done!"); ++ return 0; ++} ++ ++/* Fill the "page table" page with the pointers to the specified SG buffer */ ++static void saa716x_dmabuf_sgpagefill(struct saa716x_dmabuf *dmabuf, struct scatterlist *sg_list, int pages, int offset) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ struct scatterlist *sg_cur; ++ ++ u32 *page; ++ int i, j, k = 0; ++ dma_addr_t addr = 0; ++ ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(sg_list == NULL); ++ BUG_ON(pages == 0); ++ dprintk(SAA716x_DEBUG, 1, "SG page fill"); ++ ++ /* make page writable for the PC */ ++ dma_sync_single_for_cpu(&pdev->dev, dmabuf->mem_ptab_phys, SAA716x_PAGE_SIZE, DMA_TO_DEVICE); ++ page = dmabuf->mem_ptab_virt; ++ ++ sg_cur = sg_list; ++ /* create page table */ ++ for (i = 0; i < pages; i++) { ++ BUG_ON(!(((sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE) == 0)); ++ ++ if (i == 0) ++ dmabuf->offset = (sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE; ++ else ++ BUG_ON(sg_cur->offset != 0); ++ ++ for (j = 0; (j * SAA716x_PAGE_SIZE) < sg_dma_len(sg_cur); j++) { ++ ++ if ((offset + sg_cur->offset) >= SAA716x_PAGE_SIZE) { ++ offset -= SAA716x_PAGE_SIZE; ++ continue; ++ } ++ ++ addr = ((u64)sg_dma_address(sg_cur)) + (j * SAA716x_PAGE_SIZE) - sg_cur->offset; ++ ++ BUG_ON(addr == 0); ++ page[k * 2] = (u32) addr; /* Low */ ++ page[k * 2 + 1] = (u32 )(((u64) addr) >> 32); /* High */ ++ BUG_ON(page[k * 2] % SAA716x_PAGE_SIZE); ++ k++; ++ } ++ sg_cur = sg_next(sg_cur); ++ } ++ ++ for (; k < (SAA716x_PAGE_SIZE / 8); k++) { ++ page[k * 2] = (u32 ) addr; ++ page[k * 2 + 1] = (u32 ) (((u64 ) addr) >> 32); ++ } ++ ++ /* make "page table" page writable for the PC */ ++ dma_sync_single_for_device(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync DEVICE"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_device(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync CPU"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_cpu(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++} ++ ++/* Allocates a DMA buffer for the specified external linear buffer. */ ++int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf, int size) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ int ret; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(! (size > 0)); ++ ++ dmabuf->dma_type = SAA716x_DMABUF_INT; ++ ++ dmabuf->mem_virt_noalign = NULL; ++ dmabuf->mem_virt = NULL; ++ dmabuf->mem_ptab_phys = 0; ++ dmabuf->mem_ptab_virt = NULL; ++ ++ dmabuf->list_len = 0; ++ dmabuf->saa716x = saa716x; ++ ++ /* Allocate page table */ ++ ret = saa716x_allocate_ptable(dmabuf); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "PT alloc failed, Out of memory"); ++ goto err1; ++ } ++ ++ /* Allocate buffer as SG */ ++ ret = saa716x_dmabuf_sgalloc(dmabuf, NULL, size); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG alloc failed"); ++ goto err2; ++ } ++ ++ ret = dma_map_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG map failed"); ++ goto err3; ++ } ++ ++ saa716x_dmabuf_sgpagefill(dmabuf, dmabuf->sg_list, ret, 0); ++ ++ return 0; ++err3: ++ saa716x_dmabuf_sgfree(dmabuf); ++err2: ++ saa716x_free_ptable(dmabuf); ++err1: ++ return ret; ++} ++ ++void saa716x_dmabuf_free(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ ++ dma_unmap_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ saa716x_dmabuf_sgfree(dmabuf); ++ saa716x_free_ptable(dmabuf); ++} +diff --git a/drivers/media/pci/saa716x/saa716x_dma.h b/drivers/media/pci/saa716x/saa716x_dma.h +new file mode 100644 +index 0000000..a56b351 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_dma.h +@@ -0,0 +1,61 @@ ++#ifndef __SAA716x_DMA_H ++#define __SAA716x_DMA_H ++ ++#define SAA716x_PAGE_SIZE 4096 ++ ++#define PTA_LSB(__mem) ((u32 ) (__mem)) ++#define PTA_MSB(__mem) ((u32 ) ((u64)(__mem) >> 32)) ++ ++#define BAM_DMA_BUF_MODE_BASE 0x00 ++#define BAM_DMA_BUF_MODE_OFFSET 0x24 ++ ++#define BAM_DMA_BUF_MODE(__ch) (BAM_DMA_BUF_MODE_BASE + (BAM_DMA_BUF_MODE_OFFSET * __ch)) ++ ++#define BAM_ADDR_OFFSET_BASE 0x04 ++#define BAM_ADDR_OFFSET_OFFSET 0x24 ++ ++#define BAM_ADDR_OFFSET(__ch) (BAM_ADDR_OFFSET_BASE + (BAM_ADDR_OFFSET_OFFSET * __ch)) ++ ++#define BAM_ADDR_OFFSET_0(__ch) (BAM_ADDR_OFFSET(__ch) + 0x00) ++#define BAM_ADDR_OFFSET_1(__ch) (BAM_ADDR_OFFSET(__ch) + 0x04) ++#define BAM_ADDR_OFFSET_2(__ch) (BAM_ADDR_OFFSET(__ch) + 0x08) ++#define BAM_ADDR_OFFSET_3(__ch) (BAM_ADDR_OFFSET(__ch) + 0x0c) ++#define BAM_ADDR_OFFSET_4(__ch) (BAM_ADDR_OFFSET(__ch) + 0x10) ++#define BAM_ADDR_OFFSET_5(__ch) (BAM_ADDR_OFFSET(__ch) + 0x14) ++#define BAM_ADDR_OFFSET_6(__ch) (BAM_ADDR_OFFSET(__ch) + 0x18) ++#define BAM_ADDR_OFFSET_7(__ch) (BAM_ADDR_OFFSET(__ch) + 0x1c) ++ ++ ++enum saa716x_dma_type { ++ SAA716x_DMABUF_EXT_LIN, /* Linear external */ ++ SAA716x_DMABUF_EXT_SG, /* SG external */ ++ SAA716x_DMABUF_INT /* Linear internal */ ++}; ++ ++struct saa716x_dev; ++ ++struct saa716x_dmabuf { ++ enum saa716x_dma_type dma_type; ++ ++ void *mem_virt_noalign; ++ void *mem_virt; /* page aligned */ ++ dma_addr_t mem_ptab_phys; ++ void *mem_ptab_virt; ++ void *sg_list; /* SG list */ ++ ++ struct saa716x_dev *saa716x; ++ ++ int list_len; /* buffer len */ ++ int offset; /* page offset */ ++}; ++ ++extern int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf, ++ int size); ++extern void saa716x_dmabuf_free(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf); ++ ++extern void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf); ++extern void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf); ++ ++#endif /* __SAA716x_DMA_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_dma_reg.h b/drivers/media/pci/saa716x/saa716x_dma_reg.h +new file mode 100644 +index 0000000..5867854 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_dma_reg.h +@@ -0,0 +1,201 @@ ++#ifndef __SAA716x_DMA_REG_H ++#define __SAA716x_DMA_REG_H ++ ++/* -------------- BAM Registers -------------- */ ++ ++#define BAM_VI0_0_DMA_BUF_MODE 0x000 ++ ++#define BAM_VI0_0_ADDR_OFFST_0 0x004 ++#define BAM_VI0_0_ADDR_OFFST_1 0x008 ++#define BAM_VI0_0_ADDR_OFFST_2 0x00c ++#define BAM_VI0_0_ADDR_OFFST_3 0x010 ++#define BAM_VI0_0_ADDR_OFFST_4 0x014 ++#define BAM_VI0_0_ADDR_OFFST_5 0x018 ++#define BAM_VI0_0_ADDR_OFFST_6 0x01c ++#define BAM_VI0_0_ADDR_OFFST_7 0x020 ++ ++#define BAM_VI0_1_DMA_BUF_MODE 0x024 ++#define BAM_VI0_1_ADDR_OFFST_0 0x028 ++#define BAM_VI0_1_ADDR_OFFST_1 0x02c ++#define BAM_VI0_1_ADDR_OFFST_2 0x030 ++#define BAM_VI0_1_ADDR_OFFST_3 0x034 ++#define BAM_VI0_1_ADDR_OFFST_4 0x038 ++#define BAM_VI0_1_ADDR_OFFST_5 0x03c ++#define BAM_VI0_1_ADDR_OFFST_6 0x040 ++#define BAM_VI0_1_ADDR_OFFST_7 0x044 ++ ++#define BAM_VI0_2_DMA_BUF_MODE 0x048 ++#define BAM_VI0_2_ADDR_OFFST_0 0x04c ++#define BAM_VI0_2_ADDR_OFFST_1 0x050 ++#define BAM_VI0_2_ADDR_OFFST_2 0x054 ++#define BAM_VI0_2_ADDR_OFFST_3 0x058 ++#define BAM_VI0_2_ADDR_OFFST_4 0x05c ++#define BAM_VI0_2_ADDR_OFFST_5 0x060 ++#define BAM_VI0_2_ADDR_OFFST_6 0x064 ++#define BAM_VI0_2_ADDR_OFFST_7 0x068 ++ ++ ++#define BAM_VI1_0_DMA_BUF_MODE 0x06c ++#define BAM_VI1_0_ADDR_OFFST_0 0x070 ++#define BAM_VI1_0_ADDR_OFFST_1 0x074 ++#define BAM_VI1_0_ADDR_OFFST_2 0x078 ++#define BAM_VI1_0_ADDR_OFFST_3 0x07c ++#define BAM_VI1_0_ADDR_OFFST_4 0x080 ++#define BAM_VI1_0_ADDR_OFFST_5 0x084 ++#define BAM_VI1_0_ADDR_OFFST_6 0x088 ++#define BAM_VI1_0_ADDR_OFFST_7 0x08c ++ ++#define BAM_VI1_1_DMA_BUF_MODE 0x090 ++#define BAM_VI1_1_ADDR_OFFST_0 0x094 ++#define BAM_VI1_1_ADDR_OFFST_1 0x098 ++#define BAM_VI1_1_ADDR_OFFST_2 0x09c ++#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 ++#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 ++#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 ++#define BAM_VI1_1_ADDR_OFFST_6 0x0ac ++#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 ++ ++#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 ++#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 ++#define BAM_VI1_2_ADDR_OFFST_1 0x0bc ++#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 ++#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 ++#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 ++#define BAM_VI1_2_ADDR_OFFST_5 0x0cc ++#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 ++#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 ++ ++ ++#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 ++#define BAM_FGPI0_ADDR_OFFST_0 0x0dc ++#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 ++#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 ++#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 ++#define BAM_FGPI0_ADDR_OFFST_4 0x0ec ++#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 ++#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 ++#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 ++ ++#define BAM_FGPI1_DMA_BUF_MODE 0x0fc ++#define BAM_FGPI1_ADDR_OFFST_0 0x100 ++#define BAM_FGPI1_ADDR_OFFST_1 0x104 ++#define BAM_FGPI1_ADDR_OFFST_2 0x108 ++#define BAM_FGPI1_ADDR_OFFST_3 0x10c ++#define BAM_FGPI1_ADDR_OFFST_4 0x110 ++#define BAM_FGPI1_ADDR_OFFST_5 0x114 ++#define BAM_FGPI1_ADDR_OFFST_6 0x118 ++#define BAM_FGPI1_ADDR_OFFST_7 0x11c ++ ++#define BAM_FGPI2_DMA_BUF_MODE 0x120 ++#define BAM_FGPI2_ADDR_OFFST_0 0x124 ++#define BAM_FGPI2_ADDR_OFFST_1 0x128 ++#define BAM_FGPI2_ADDR_OFFST_2 0x12c ++#define BAM_FGPI2_ADDR_OFFST_3 0x130 ++#define BAM_FGPI2_ADDR_OFFST_4 0x134 ++#define BAM_FGPI2_ADDR_OFFST_5 0x138 ++#define BAM_FGPI2_ADDR_OFFST_6 0x13c ++#define BAM_FGPI2_ADDR_OFFST_7 0x140 ++ ++#define BAM_FGPI3_DMA_BUF_MODE 0x144 ++#define BAM_FGPI3_ADDR_OFFST_0 0x148 ++#define BAM_FGPI3_ADDR_OFFST_1 0x14c ++#define BAM_FGPI3_ADDR_OFFST_2 0x150 ++#define BAM_FGPI3_ADDR_OFFST_3 0x154 ++#define BAM_FGPI3_ADDR_OFFST_4 0x158 ++#define BAM_FGPI3_ADDR_OFFST_5 0x15c ++#define BAM_FGPI3_ADDR_OFFST_6 0x160 ++#define BAM_FGPI3_ADDR_OFFST_7 0x164 ++ ++ ++#define BAM_AI0_DMA_BUF_MODE 0x168 ++#define BAM_AI0_ADDR_OFFST_0 0x16c ++#define BAM_AI0_ADDR_OFFST_1 0x170 ++#define BAM_AI0_ADDR_OFFST_2 0x174 ++#define BAM_AI0_ADDR_OFFST_3 0x178 ++#define BAM_AI0_ADDR_OFFST_4 0x17c ++#define BAM_AIO_ADDR_OFFST_5 0x180 ++#define BAM_AI0_ADDR_OFFST_6 0x184 ++#define BAM_AIO_ADDR_OFFST_7 0x188 ++ ++#define BAM_AI1_DMA_BUF_MODE 0x18c ++#define BAM_AI1_ADDR_OFFST_0 0x190 ++#define BAM_AI1_ADDR_OFFST_1 0x194 ++#define BAM_AI1_ADDR_OFFST_2 0x198 ++#define BAM_AI1_ADDR_OFFST_3 0x19c ++#define BAM_AI1_ADDR_OFFST_4 0x1a0 ++#define BAM_AI1_ADDR_OFFST_5 0x1a4 ++#define BAM_AI1_ADDR_OFFST_6 0x1a8 ++#define BAM_AI1_ADDR_OFFST_7 0x1ac ++ ++#define BAM_SW_RST 0xff0 ++#define BAM_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++ ++/* -------------- MMU Registers -------------- */ ++ ++#define MMU_MODE 0x000 ++ ++#define MMU_DMA_CONFIG0 0x004 ++#define MMU_DMA_CONFIG1 0x008 ++#define MMU_DMA_CONFIG2 0x00c ++#define MMU_DMA_CONFIG3 0x010 ++#define MMU_DMA_CONFIG4 0x014 ++#define MMU_DMA_CONFIG5 0x018 ++#define MMU_DMA_CONFIG6 0x01c ++#define MMU_DMA_CONFIG7 0x020 ++#define MMU_DMA_CONFIG8 0x024 ++#define MMU_DMA_CONFIG9 0x028 ++#define MMU_DMA_CONFIG10 0x02c ++#define MMU_DMA_CONFIG11 0x030 ++#define MMU_DMA_CONFIG12 0x034 ++#define MMU_DMA_CONFIG13 0x038 ++#define MMU_DMA_CONFIG14 0x03c ++#define MMU_DMA_CONFIG15 0x040 ++ ++#define MMU_DMA_CONFIG(__ch) (MMU_DMA_CONFIG0 + (4 * __ch)) ++ ++#define MMU_SW_RST 0xff0 ++#define MMU_SW_RESET (0x0001 << 0) ++ ++#define MMU_PTA_BASE0 0x044 /* DMA 0 */ ++#define MMU_PTA_BASE1 0x084 /* DMA 1 */ ++#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ ++#define MMU_PTA_BASE3 0x104 /* DMA 3 */ ++#define MMU_PTA_BASE4 0x144 /* DMA 4 */ ++#define MMU_PTA_BASE5 0x184 /* DMA 5 */ ++#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ ++#define MMU_PTA_BASE7 0x204 /* DMA 7 */ ++#define MMU_PTA_BASE8 0x244 /* DMA 8 */ ++#define MMU_PTA_BASE9 0x284 /* DMA 9 */ ++#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ ++#define MMU_PTA_BASE11 0x304 /* DMA 11 */ ++#define MMU_PTA_BASE12 0x344 /* DMA 12 */ ++#define MMU_PTA_BASE13 0x384 /* DMA 13 */ ++#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ ++#define MMU_PTA_BASE15 0x404 /* DMA 15 */ ++ ++#define MMU_PTA_OFFSET 0x40 ++ ++#define MMU_PTA_BASE(__ch) (MMU_PTA_BASE0 + (MMU_PTA_OFFSET * __ch)) ++ ++#define MMU_PTA0_LSB(__ch) MMU_PTA_BASE(__ch) + 0x00 ++#define MMU_PTA0_MSB(__ch) MMU_PTA_BASE(__ch) + 0x04 ++#define MMU_PTA1_LSB(__ch) MMU_PTA_BASE(__ch) + 0x08 ++#define MMU_PTA1_MSB(__ch) MMU_PTA_BASE(__ch) + 0x0c ++#define MMU_PTA2_LSB(__ch) MMU_PTA_BASE(__ch) + 0x10 ++#define MMU_PTA2_MSB(__ch) MMU_PTA_BASE(__ch) + 0x14 ++#define MMU_PTA3_LSB(__ch) MMU_PTA_BASE(__ch) + 0x18 ++#define MMU_PTA3_MSB(__ch) MMU_PTA_BASE(__ch) + 0x1c ++#define MMU_PTA4_LSB(__ch) MMU_PTA_BASE(__ch) + 0x20 ++#define MMU_PTA4_MSB(__ch) MMU_PTA_BASE(__ch) + 0x24 ++#define MMU_PTA5_LSB(__ch) MMU_PTA_BASE(__ch) + 0x28 ++#define MMU_PTA5_MSB(__ch) MMU_PTA_BASE(__ch) + 0x2c ++#define MMU_PTA6_LSB(__ch) MMU_PTA_BASE(__ch) + 0x30 ++#define MMU_PTA6_MSB(__ch) MMU_PTA_BASE(__ch) + 0x34 ++#define MMU_PTA7_LSB(__ch) MMU_PTA_BASE(__ch) + 0x38 ++#define MMU_PTA7_MSB(__ch) MMU_PTA_BASE(__ch) + 0x3c ++ ++#endif /* __SAA716x_DMA_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_ff.h b/drivers/media/pci/saa716x/saa716x_ff.h +new file mode 100644 +index 0000000..ed06380 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_ff.h +@@ -0,0 +1,173 @@ ++#ifndef __SAA716x_FF_H ++#define __SAA716x_FF_H ++ ++#include "dvb_filter.h" ++#include "dvb_ringbuffer.h" ++#include ++#include ++ ++#define TECHNOTREND 0x13c2 ++#define S2_6400_DUAL_S2_PREMIUM_DEVEL 0x3009 ++#define S2_6400_DUAL_S2_PREMIUM_PROD 0x300A ++ ++#define TT_PREMIUM_GPIO_POWER_ENABLE 27 ++#define TT_PREMIUM_GPIO_RESET_BACKEND 26 ++#define TT_PREMIUM_GPIO_FPGA_CS1 17 ++#define TT_PREMIUM_GPIO_FPGA_CS0 16 ++#define TT_PREMIUM_GPIO_FPGA_PROGRAMN 15 ++#define TT_PREMIUM_GPIO_FPGA_DONE 14 ++#define TT_PREMIUM_GPIO_FPGA_INITN 13 ++ ++/* fpga interrupt register addresses */ ++#define FPGA_ADDR_PHI_ICTRL 0x8000 /* PHI General control of the PC => STB interrupt controller */ ++#define FPGA_ADDR_PHI_ISR 0x8010 /* PHI Interrupt Status Register */ ++#define FPGA_ADDR_PHI_ISET 0x8020 /* PHI Interrupt Set Register */ ++#define FPGA_ADDR_PHI_ICLR 0x8030 /* PHI Interrupt Clear Register */ ++#define FPGA_ADDR_EMI_ICTRL 0x8100 /* EMI General control of the STB => PC interrupt controller */ ++#define FPGA_ADDR_EMI_ISR 0x8110 /* EMI Interrupt Status Register */ ++#define FPGA_ADDR_EMI_ISET 0x8120 /* EMI Interrupt Set Register */ ++#define FPGA_ADDR_EMI_ICLR 0x8130 /* EMI Interrupt Clear Register */ ++ ++/* fpga TS router register addresses */ ++#define FPGA_ADDR_TSR_CTRL 0x8200 /* TS router control register */ ++#define FPGA_ADDR_TSR_MUX1 0x8210 /* TS multiplexer 1 selection register */ ++#define FPGA_ADDR_TSR_MUX2 0x8220 /* TS multiplexer 2 selection register */ ++#define FPGA_ADDR_TSR_MUX3 0x8230 /* TS multiplexer 3 selection register */ ++#define FPGA_ADDR_TSR_MUXCI1 0x8240 /* TS multiplexer CI 1 selection register */ ++#define FPGA_ADDR_TSR_MUXCI2 0x8250 /* TS multiplexer CI 2 selection register */ ++ ++#define FPGA_ADDR_TSR_BRFE1 0x8280 /* bit rate for TS coming from frontend 1 */ ++#define FPGA_ADDR_TSR_BRFE2 0x8284 /* bit rate for TS coming from frontend 2 */ ++#define FPGA_ADDR_TSR_BRFF1 0x828C /* bit rate for TS coming from FIFO 1 */ ++#define FPGA_ADDR_TSR_BRO1 0x8294 /* bit rate for TS going to output 1 */ ++#define FPGA_ADDR_TSR_BRO2 0x8298 /* bit rate for TS going to output 2 */ ++#define FPGA_ADDR_TSR_BRO3 0x829C /* bit rate for TS going to output 3 */ ++ ++/* fpga TS FIFO register addresses */ ++#define FPGA_ADDR_FIFO_CTRL 0x8300 /* FIFO control register */ ++#define FPGA_ADDR_FIFO_STAT 0x8310 /* FIFO status register */ ++ ++#define FPGA_ADDR_VERSION 0x80F0 /* FPGA bitstream version register */ ++ ++#define FPGA_ADDR_PIO_CTRL 0x8500 /* FPGA GPIO control register */ ++ ++#define ISR_CMD_MASK 0x0001 /* interrupt source for normal cmds (osd, fre, av, ...) */ ++#define ISR_READY_MASK 0x0002 /* interrupt source for command acknowledge */ ++#define ISR_BLOCK_MASK 0x0004 /* interrupt source for single block transfers and acknowledge */ ++#define ISR_DATA_MASK 0x0008 /* interrupt source for data transfer acknowledge */ ++#define ISR_BOOT_FINISH_MASK 0x0010 /* interrupt source for boot finish indication */ ++#define ISR_AUDIO_PTS_MASK 0x0020 /* interrupt source for audio PTS */ ++#define ISR_VIDEO_PTS_MASK 0x0040 /* interrupt source for video PTS */ ++#define ISR_CURRENT_STC_MASK 0x0080 /* interrupt source for current system clock */ ++#define ISR_REMOTE_EVENT_MASK 0x0100 /* interrupt source for remote events */ ++#define ISR_DVO_FORMAT_MASK 0x0200 /* interrupt source for DVO format change */ ++#define ISR_OSD_CMD_MASK 0x0400 /* interrupt source for OSD cmds */ ++#define ISR_OSD_READY_MASK 0x0800 /* interrupt source for OSD command acknowledge */ ++#define ISR_FE_CMD_MASK 0x1000 /* interrupt source for frontend cmds */ ++#define ISR_FE_READY_MASK 0x2000 /* interrupt source for frontend command acknowledge */ ++#define ISR_LOG_MESSAGE_MASK 0x4000 /* interrupt source for log messages */ ++#define ISR_FIFO1_EMPTY_MASK 0x8000 /* interrupt source for FIFO1 empty */ ++ ++#define ADDR_CMD_DATA 0x0000 /* address for cmd data in fpga dpram */ ++#define ADDR_OSD_CMD_DATA 0x01A0 /* address for OSD cmd data */ ++#define ADDR_FE_CMD_DATA 0x05C0 /* address for frontend cmd data */ ++#define ADDR_BLOCK_DATA 0x0600 /* address for block data */ ++#define ADDR_AUDIO_PTS 0x3E00 /* address for audio PTS (64 Bits) */ ++#define ADDR_VIDEO_PTS 0x3E08 /* address for video PTS (64 Bits) */ ++#define ADDR_CURRENT_STC 0x3E10 /* address for system clock (64 Bits) */ ++#define ADDR_DVO_FORMAT 0x3E18 /* address for DVO format 32 Bits) */ ++#define ADDR_REMOTE_EVENT 0x3F00 /* address for remote events (32 Bits) */ ++#define ADDR_LOG_MESSAGE 0x3F80 /* address for log messages */ ++ ++#define SIZE_CMD_DATA 0x01A0 /* maximum size for command data (416 Bytes) */ ++#define SIZE_OSD_CMD_DATA 0x0420 /* maximum size for OSD command data (1056 Bytes) */ ++#define SIZE_FE_CMD_DATA 0x0040 /* maximum size for frontend command data (64 Bytes) */ ++#define SIZE_BLOCK_DATA 0x3800 /* maximum size for block data (14 kB) */ ++#define SIZE_LOG_MESSAGE_DATA 0x0080 /* maximum size for log message data (128 Bytes) */ ++ ++#define SIZE_BLOCK_HEADER 8 /* block header size */ ++ ++#define MAX_RESULT_LEN 256 ++#define MAX_DATA_LEN (1024 * 1024) ++ ++#define TSOUT_LEN (1024 * TS_SIZE) ++ ++#define TSOUT_STAT_RESET 0 ++#define TSOUT_STAT_FILL 1 ++#define TSOUT_STAT_RUN 2 ++ ++#define VIDEO_CAPTURE_OFF 0 ++#define VIDEO_CAPTURE_ONE_SHOT 1 ++ ++ ++/* place to store all the necessary device information */ ++struct sti7109_dev { ++ struct saa716x_dev *dev; ++ struct dvb_device *osd_dev; ++ struct dvb_device *video_dev; ++ struct dvb_device *audio_dev; ++ ++ void *iobuf; /* memory for all buffers */ ++ struct dvb_ringbuffer tsout; /* buffer for TS output */ ++ u32 tsout_stat; ++ ++ struct workqueue_struct *fifo_workq; ++ struct work_struct fifo_work; ++ ++ wait_queue_head_t boot_finish_wq; ++ int boot_finished; ++ ++ wait_queue_head_t cmd_ready_wq; ++ int cmd_ready; ++ u8 cmd_data[SIZE_CMD_DATA]; ++ u32 cmd_len; ++ ++ wait_queue_head_t result_avail_wq; ++ int result_avail; ++ u8 result_data[MAX_RESULT_LEN]; ++ u32 result_len; ++ u32 result_max_len; ++ ++ wait_queue_head_t osd_cmd_ready_wq; ++ int osd_cmd_ready; ++ u8 osd_cmd_data[SIZE_OSD_CMD_DATA]; ++ u32 osd_cmd_len; ++ ++ wait_queue_head_t osd_result_avail_wq; ++ int osd_result_avail; ++ u8 osd_result_data[MAX_RESULT_LEN]; ++ u32 osd_result_len; ++ u32 osd_result_max_len; ++ ++ u16 data_handle; ++ u8 *data_buffer; /* raw data transfer buffer */ ++ wait_queue_head_t data_ready_wq; ++ int data_ready; ++ wait_queue_head_t block_done_wq; ++ int block_done; ++ ++ struct mutex cmd_lock; ++ struct mutex osd_cmd_lock; ++ struct mutex data_lock; ++ struct mutex video_lock; ++ ++ u64 audio_pts; ++ u64 video_pts; ++ u64 current_stc; ++ ++ u32 video_capture; ++ u32 video_format; ++ ++ u32 int_count_enable; ++ u32 total_int_count; ++ u32 vi_int_count[2]; ++ u32 fgpi_int_count[4]; ++ u32 i2c_int_count[2]; ++ u32 ext_int_total_count; ++ u32 ext_int_source_count[16]; ++ u32 last_int_ticks; ++ ++ u16 fpga_version; ++}; ++ ++#endif /* __SAA716x_FF_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_ff_cmd.c b/drivers/media/pci/saa716x/saa716x_ff_cmd.c +new file mode 100644 +index 0000000..430dd47 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_ff_cmd.c +@@ -0,0 +1,421 @@ ++#include ++ ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_phi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++ ++int sti7109_cmd_init(struct sti7109_dev *sti7109) ++{ ++ mutex_init(&sti7109->cmd_lock); ++ mutex_init(&sti7109->osd_cmd_lock); ++ mutex_init(&sti7109->data_lock); ++ ++ init_waitqueue_head(&sti7109->boot_finish_wq); ++ sti7109->boot_finished = 0; ++ ++ init_waitqueue_head(&sti7109->cmd_ready_wq); ++ sti7109->cmd_ready = 0; ++ ++ init_waitqueue_head(&sti7109->result_avail_wq); ++ sti7109->result_avail = 0; ++ ++ init_waitqueue_head(&sti7109->osd_cmd_ready_wq); ++ sti7109->osd_cmd_ready = 0; ++ init_waitqueue_head(&sti7109->osd_result_avail_wq); ++ sti7109->osd_result_avail = 0; ++ ++ sti7109->data_handle = 0; ++ sti7109->data_buffer = (u8 *) (sti7109->iobuf + TSOUT_LEN); ++ init_waitqueue_head(&sti7109->data_ready_wq); ++ sti7109->data_ready = 0; ++ init_waitqueue_head(&sti7109->block_done_wq); ++ sti7109->block_done = 0; ++ return 0; ++} ++ ++static int sti7109_do_raw_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->cmd_ready_wq, ++ sti7109->cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command ready"); ++ return -EIO; ++ } ++ ++ sti7109->cmd_ready = 0; ++ sti7109->result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_CMD_DATA, sti7109->cmd_data, ++ sti7109->cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_CMD_MASK); ++ ++ if (sti7109->result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->result_avail_wq, ++ sti7109->result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->result_avail == 0) { ++ sti7109->result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->result_len > sti7109->result_max_len) { ++ sti7109->result_len = sti7109->result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->cmd_len = cmd->cmd_len; ++ sti7109->result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->result_len; ++ if (sti7109->result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->result_data, ++ sti7109->result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_osd_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->osd_cmd_ready_wq, ++ sti7109->osd_cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "osd cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command ready"); ++ return -EIO; ++ } ++ ++ sti7109->osd_cmd_ready = 0; ++ sti7109->osd_result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_cmd_data, ++ sti7109->osd_cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_OSD_CMD_MASK); ++ ++ if (sti7109->osd_result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->osd_result_avail_wq, ++ sti7109->osd_result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_result_avail == 0) { ++ sti7109->osd_result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, ++ "osd result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->osd_result_len > sti7109->osd_result_max_len) { ++ sti7109->osd_result_len = sti7109->osd_result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_OSD_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->osd_cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->osd_cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->osd_cmd_len = cmd->cmd_len; ++ sti7109->osd_result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_osd_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->osd_result_len; ++ if (sti7109->osd_result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->osd_result_data, ++ sti7109->osd_result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->osd_cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ u16 blockSize; ++ u16 lastBlockSize; ++ u16 numBlocks; ++ u16 blockIndex; ++ u8 blockHeader[SIZE_BLOCK_HEADER]; ++ u8 * blockPtr; ++ int activeBlock; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->data_ready_wq, ++ sti7109->data_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->data_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "data ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for data ready"); ++ return -EIO; ++ } ++ ++ sti7109->data_ready = 0; ++ ++ /* ++ * 8 bytes is the size of the block header. Block header structure is: ++ * 16 bit - block index ++ * 16 bit - number of blocks ++ * 16 bit - current block data size ++ * 16 bit - block handle. This is used to reference the data in the ++ * command that uses it. ++ */ ++ blockSize = (SIZE_BLOCK_DATA / 2) - SIZE_BLOCK_HEADER; ++ numBlocks = data->data_length / blockSize; ++ lastBlockSize = data->data_length % blockSize; ++ if (lastBlockSize > 0) ++ numBlocks++; ++ ++ blockHeader[2] = (u8) (numBlocks >> 8); ++ blockHeader[3] = (u8) numBlocks; ++ blockHeader[6] = (u8) (sti7109->data_handle >> 8); ++ blockHeader[7] = (u8) sti7109->data_handle; ++ blockPtr = sti7109->data_buffer; ++ activeBlock = 0; ++ for (blockIndex = 0; blockIndex < numBlocks; blockIndex++) { ++ u32 addr; ++ ++ if (lastBlockSize && (blockIndex == (numBlocks - 1))) ++ blockSize = lastBlockSize; ++ ++ blockHeader[0] = (uint8_t) (blockIndex >> 8); ++ blockHeader[1] = (uint8_t) blockIndex; ++ blockHeader[4] = (uint8_t) (blockSize >> 8); ++ blockHeader[5] = (uint8_t) blockSize; ++ ++ addr = ADDR_BLOCK_DATA + activeBlock * (SIZE_BLOCK_DATA / 2); ++ saa716x_phi_write(saa716x, addr, blockHeader, ++ SIZE_BLOCK_HEADER); ++ saa716x_phi_write(saa716x, addr + SIZE_BLOCK_HEADER, blockPtr, ++ blockSize); ++ activeBlock = (activeBlock + 1) & 1; ++ if (blockIndex > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for block done"); ++ /* send a data interrupt to cancel the transfer ++ and reset the data handling */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ++ ISR_DATA_MASK); ++ return -EIO; ++ } ++ } ++ sti7109->block_done = 0; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_BLOCK_MASK); ++ blockPtr += blockSize; ++ } ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for block done"); ++ /* send a data interrupt to cancel the transfer and reset the ++ data handling */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_DATA_MASK); ++ return -EIO; ++ } ++ sti7109->block_done = 0; ++ ++ data->data_handle = sti7109->data_handle; ++ sti7109->data_handle++; ++ return 0; ++} ++ ++int sti7109_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (data->data_length > MAX_DATA_LEN) { ++ dprintk(SAA716x_ERROR, 1, "data too big"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->data_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->data_buffer, ++ (void __user *)data->data_buffer, ++ data->data_length)) ++ goto out; ++ ++ err = sti7109_do_raw_data(sti7109, data); ++ if (err) ++ goto out; ++ ++out: ++ mutex_unlock(&sti7109->data_lock); ++ return err; ++} ++ ++int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, u32 *fw_version) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x04; ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x00; ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x00; ++ sti7109->cmd_len = 6; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ *fw_version = (sti7109->result_data[6] << 16) ++ | (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ ++int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, video_size_t *vs) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x05; /* command length */ ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x01; /* A/V decoder command group */ ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x10; /* get video format info command */ ++ sti7109->cmd_data[6] = 0x00; /* decoder index 0 */ ++ sti7109->cmd_len = 7; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ vs->w = (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ vs->h = (sti7109->result_data[9] << 8) ++ | sti7109->result_data[10]; ++ vs->aspect_ratio = sti7109->result_data[11] >> 4; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ +diff --git a/drivers/media/pci/saa716x/saa716x_ff_cmd.h b/drivers/media/pci/saa716x/saa716x_ff_cmd.h +new file mode 100644 +index 0000000..7798ec3 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_ff_cmd.h +@@ -0,0 +1,34 @@ ++#ifndef __SAA716x_FF_CMD_H ++#define __SAA716x_FF_CMD_H ++ ++#if !defined OSD_RAW_CMD ++typedef struct osd_raw_cmd_s { ++ const void *cmd_data; ++ int cmd_len; ++ void *result_data; ++ int result_len; ++} osd_raw_cmd_t; ++ ++typedef struct osd_raw_data_s { ++ const void *data_buffer; ++ int data_length; ++ int data_handle; ++} osd_raw_data_t; ++ ++#define OSD_RAW_CMD _IOWR('o', 162, osd_raw_cmd_t) ++#define OSD_RAW_DATA _IOWR('o', 163, osd_raw_data_t) ++#endif ++ ++extern int sti7109_cmd_init(struct sti7109_dev *sti7109); ++extern int sti7109_raw_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_data(struct sti7109_dev * sti7109, ++ osd_raw_data_t * data); ++extern int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, ++ u32 *fw_version); ++extern int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, ++ video_size_t *vs); ++ ++#endif /* __SAA716x_FF_CMD_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_ff_ir.c b/drivers/media/pci/saa716x/saa716x_ff_ir.c +new file mode 100644 +index 0000000..3562478 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_ff_ir.c +@@ -0,0 +1,265 @@ ++/* ++ * Driver for the remote control of the TT6400 DVB-S2 card ++ * ++ * Copyright (C) 2010 Oliver Endriss ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++ ++ ++/* infrared remote control */ ++struct infrared { ++ u16 key_map[128]; ++ struct input_dev *input_dev; ++ char input_phys[32]; ++ struct timer_list keyup_timer; ++ struct tasklet_struct tasklet; ++ u32 command; ++ u32 device_mask; ++ u8 protocol; ++ u16 last_key; ++ u16 last_toggle; ++ bool delay_timer_finished; ++}; ++ ++#define IR_RC5 0 ++#define UP_TIMEOUT (HZ*7/25) ++ ++ ++/* key-up timer */ ++static void ir_emit_keyup(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) ++ return; ++ ++ input_report_key(ir->input_dev, ir->last_key, 0); ++ input_sync(ir->input_dev); ++} ++ ++ ++/* tasklet */ ++static void ir_emit_key(unsigned long parm) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) parm; ++ struct infrared *ir = saa716x->ir_priv; ++ u32 ircom = ir->command; ++ u8 data; ++ u8 addr; ++ u16 toggle; ++ u16 keycode; ++ ++ /* extract device address and data */ ++ if (ircom & 0x80000000) { /* CEC remote command */ ++ addr = 0; ++ data = ircom & 0x7F; ++ toggle = 0; ++ } else { ++ switch (ir->protocol) { ++ case IR_RC5: /* extended RC5: 5 bits device address, 7 bits data */ ++ addr = (ircom >> 6) & 0x1f; ++ /* data bits 1..6 */ ++ data = ircom & 0x3f; ++ /* data bit 7 (inverted) */ ++ if (!(ircom & 0x1000)) ++ data |= 0x40; ++ toggle = ircom & 0x0800; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: invalid protocol %x\n", ++ __func__, ir->protocol); ++ return; ++ } ++ } ++ ++ input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data); ++ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); ++ ++ keycode = ir->key_map[data]; ++ ++ dprintk(SAA716x_DEBUG, 0, ++ "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", ++ __func__, ircom, addr, data, keycode); ++ ++ /* check device address */ ++ if (!(ir->device_mask & (1 << addr))) ++ return; ++ ++ if (!keycode) { ++ printk(KERN_WARNING "%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", ++ __func__, ircom, addr, data); ++ return; ++ } ++ ++ if (timer_pending(&ir->keyup_timer)) { ++ del_timer(&ir->keyup_timer); ++ if (ir->last_key != keycode || toggle != ir->last_toggle) { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, ir->last_key, 0); ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } else if (ir->delay_timer_finished) { ++ input_event(ir->input_dev, EV_KEY, keycode, 2); ++ input_sync(ir->input_dev); ++ } ++ } else { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } ++ ++ ir->last_key = keycode; ++ ir->last_toggle = toggle; ++ ++ ir->keyup_timer.expires = jiffies + UP_TIMEOUT; ++ add_timer(&ir->keyup_timer); ++ ++} ++ ++ ++/* register with input layer */ ++static void ir_register_keys(struct infrared *ir) ++{ ++ int i; ++ ++ set_bit(EV_KEY, ir->input_dev->evbit); ++ set_bit(EV_REP, ir->input_dev->evbit); ++ set_bit(EV_MSC, ir->input_dev->evbit); ++ ++ set_bit(MSC_RAW, ir->input_dev->mscbit); ++ set_bit(MSC_SCAN, ir->input_dev->mscbit); ++ ++ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); ++ ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) { ++ if (ir->key_map[i] > KEY_MAX) ++ ir->key_map[i] = 0; ++ else if (ir->key_map[i] > KEY_RESERVED) ++ set_bit(ir->key_map[i], ir->input_dev->keybit); ++ } ++ ++ ir->input_dev->keycode = ir->key_map; ++ ir->input_dev->keycodesize = sizeof(ir->key_map[0]); ++ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); ++} ++ ++ ++/* called by the input driver after rep[REP_DELAY] ms */ ++static void ir_repeat_key(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ ir->delay_timer_finished = true; ++} ++ ++ ++/* interrupt handler */ ++void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ if (!ir) ++ return; ++ ++ ir->command = ir_cmd; ++ tasklet_schedule(&ir->tasklet); ++} ++ ++ ++int saa716x_ir_init(struct saa716x_dev *saa716x) ++{ ++ struct input_dev *input_dev; ++ struct infrared *ir; ++ int rc; ++ int i; ++ ++ if (!saa716x) ++ return -ENOMEM; ++ ++ ir = kzalloc(sizeof(struct infrared), GFP_KERNEL); ++ if (!ir) ++ return -ENOMEM; ++ ++ init_timer(&ir->keyup_timer); ++ ir->keyup_timer.function = ir_emit_keyup; ++ ir->keyup_timer.data = (unsigned long) ir; ++ ++ input_dev = input_allocate_device(); ++ if (!input_dev) ++ goto err; ++ ++ ir->input_dev = input_dev; ++ input_dev->name = "TT6400 DVB IR receiver"; ++ snprintf(ir->input_phys, sizeof(ir->input_phys), ++ "pci-%s/ir0", pci_name(saa716x->pdev)); ++ input_dev->phys = ir->input_phys; ++ input_dev->id.bustype = BUS_PCI; ++ input_dev->id.version = 1; ++ input_dev->id.vendor = saa716x->pdev->subsystem_vendor; ++ input_dev->id.product = saa716x->pdev->subsystem_device; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ input_dev->dev.parent = &saa716x->pdev->dev; ++#else ++ input_dev->cdev.dev = &saa716x->pdev->dev; ++#endif ++ rc = input_register_device(input_dev); ++ if (rc) ++ goto err; ++ ++ /* TODO: fix setup/keymap */ ++ ir->protocol = IR_RC5; ++ ir->device_mask = 0xffffffff; ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) ++ ir->key_map[i] = i+1; ++ ir_register_keys(ir); ++ ++ /* override repeat timer */ ++ input_dev->timer.function = ir_repeat_key; ++ input_dev->timer.data = (unsigned long) ir; ++ ++ tasklet_init(&ir->tasklet, ir_emit_key, (unsigned long) saa716x); ++ saa716x->ir_priv = ir; ++ ++ return 0; ++ ++err: ++ if (ir->input_dev) ++ input_free_device(ir->input_dev); ++ kfree(ir); ++ return -ENOMEM; ++} ++ ++ ++void saa716x_ir_exit(struct saa716x_dev *saa716x) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ saa716x->ir_priv = NULL; ++ tasklet_kill(&ir->tasklet); ++ del_timer_sync(&ir->keyup_timer); ++ input_unregister_device(ir->input_dev); ++ kfree(ir); ++} +diff --git a/drivers/media/pci/saa716x/saa716x_ff_main.c b/drivers/media/pci/saa716x/saa716x_ff_main.c +new file mode 100644 +index 0000000..7e94302 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_ff_main.c +@@ -0,0 +1,1807 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_dma_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_phi_reg.h" ++#include "saa716x_spi_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_msi.h" ++#include "saa716x_adap.h" ++#include "saa716x_gpio.h" ++#include "saa716x_phi.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "isl6423.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++unsigned int int_count_enable; ++module_param(int_count_enable, int, 0644); ++MODULE_PARM_DESC(int_count_enable, "enable counting of interrupts"); ++ ++unsigned int video_capture; ++module_param(video_capture, int, 0644); ++MODULE_PARM_DESC(video_capture, "capture digital video coming from STi7109: 0=off, 1=one-shot. default off"); ++ ++#define DRIVER_NAME "SAA716x FF" ++ ++static int saa716x_ff_fpga_init(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ int fpgaInit; ++ int fpgaDone; ++ int rounds; ++ int ret; ++ const struct firmware *fw; ++ ++ /* request the FPGA firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-fpga-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load FPGA firmware," ++ " file not found: dvb-ttpremium-fpga-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ /* set FPGA PROGRAMN high */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN low to set it into configuration mode */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 0); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN high to start configuration process */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ ++ rounds = 0; ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ while (fpgaInit == 0 && rounds < 5000) { ++ //msleep(1); ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ rounds++; ++ } ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA INITN=%d, rounds=%d", ++ fpgaInit, rounds); ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, 0x08); ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, SPI_MODE_SELECT); ++ ++ msleep(10); ++ ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream"); ++ saa716x_spi_write(saa716x, fw->data, fw->size); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream done"); ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ if (!fpgaDone) { ++ printk(KERN_ERR "SAA716x FF FPGA is not responding, did you " ++ "connect the power supply?\n"); ++ return -EINVAL; ++ } ++ ++ sti7109->fpga_version = SAA716x_EPRD(PHI_1, FPGA_ADDR_VERSION); ++ printk(KERN_INFO "SAA716x FF FPGA version %X.%02X\n", ++ sti7109->fpga_version >> 8, sti7109->fpga_version & 0xFF); ++ ++ return 0; ++} ++ ++static int saa716x_ff_st7109_init(struct saa716x_dev *saa716x) ++{ ++ int i; ++ int length; ++ u32 requestedBlock; ++ u32 writtenBlock; ++ u32 numBlocks; ++ u32 blockSize; ++ u32 lastBlockSize; ++ u64 startTime; ++ u64 currentTime; ++ u64 waitTime; ++ int ret; ++ const struct firmware *fw; ++ u32 loaderVersion; ++ ++ /* request the st7109 loader, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-loader-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 loader," ++ " file not found: dvb-ttpremium-loader-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ loaderVersion = (fw->data[0x1385] << 8) | fw->data[0x1384]; ++ printk(KERN_INFO "SAA716x FF loader version %X.%02X\n", ++ loaderVersion >> 8, loaderVersion & 0xFF); ++ ++ saa716x_phi_write(saa716x, 0, fw->data, fw->size); ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ /* take ST out of reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 1); ++ ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == 1) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ return -1; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 ready after %llu ticks", waitTime); ++ ++ /* request the st7109 firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-st7109-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 firmware," ++ " file not found: dvb-ttpremium-st7109-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware"); ++ writtenBlock = 0; ++ blockSize = 0x3c00; ++ length = fw->size; ++ numBlocks = length / blockSize; ++ lastBlockSize = length % blockSize; ++ for (i = 0; i < length; i += blockSize) { ++ writtenBlock++; ++ /* write one block (last may differ from blockSize) */ ++ if (lastBlockSize && writtenBlock == (numBlocks + 1)) ++ saa716x_phi_write(saa716x, 0, &fw->data[i], lastBlockSize); ++ else ++ saa716x_phi_write(saa716x, 0, &fw->data[i], blockSize); ++ ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == (writtenBlock + 1)) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ release_firmware(fw); ++ return -1; ++ } ++ } ++ ++ /* disable frontend support through ST firmware */ ++ SAA716x_EPWR(PHI_1, 0x3ff4, 1); ++ ++ /* indicate end of transfer */ ++ writtenBlock++; ++ writtenBlock |= 0x80000000; ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware done"); ++ ++ release_firmware(fw); ++ ++ return 0; ++} ++ ++static int saa716x_usercopy(struct dvb_device *dvbdev, ++ unsigned int cmd, unsigned long arg, ++ int (*func)(struct dvb_device *dvbdev, ++ unsigned int cmd, void *arg)) ++{ ++ char sbuf[128]; ++ void *mbuf = NULL; ++ void *parg = NULL; ++ int err = -EINVAL; ++ ++ /* Copy arguments into temp kernel buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_NONE: ++ /* ++ * For this command, the pointer is actually an integer ++ * argument. ++ */ ++ parg = (void *) arg; ++ break; ++ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ ++ case _IOC_WRITE: ++ case (_IOC_WRITE | _IOC_READ): ++ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { ++ parg = sbuf; ++ } else { ++ /* too big to allocate from stack */ ++ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); ++ if (NULL == mbuf) ++ return -ENOMEM; ++ parg = mbuf; ++ } ++ ++ err = -EFAULT; ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto out; ++ break; ++ } ++ ++ /* call driver */ ++ if ((err = func(dvbdev, cmd, parg)) == -ENOIOCTLCMD) ++ err = -EINVAL; ++ ++ if (err < 0) ++ goto out; ++ ++ /* Copy results into user buffer */ ++ switch (_IOC_DIR(cmd)) ++ { ++ case _IOC_READ: ++ case (_IOC_WRITE | _IOC_READ): ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ break; ++ } ++ ++out: ++ kfree(mbuf); ++ return err; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_osd_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_osd_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ int err = -EINVAL; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ if (cmd == OSD_RAW_CMD) { ++ osd_raw_cmd_t raw_cmd; ++ u8 hdr[4]; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_cmd, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ if (copy_from_user(hdr, (void __user *)raw_cmd.cmd_data, 4)) ++ goto out; ++ ++ if (hdr[3] == 4) ++ err = sti7109_raw_osd_cmd(sti7109, &raw_cmd); ++ else ++ err = sti7109_raw_cmd(sti7109, &raw_cmd); ++ ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_cmd, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ else if (cmd == OSD_RAW_DATA) { ++ osd_raw_data_t raw_data; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_data, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ err = sti7109_raw_data(sti7109, &raw_data); ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_data, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ ++out: ++ return err; ++} ++ ++static struct file_operations dvb_osd_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_osd_ioctl, ++#else ++ .unlocked_ioctl = dvb_osd_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_osd = { ++ .priv = NULL, ++ .users = 2, ++ .writers = 2, ++ .fops = &dvb_osd_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_osd_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->osd_dev); ++ return 0; ++} ++ ++static int saa716x_ff_osd_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->osd_dev, ++ &dvbdev_osd, ++ sti7109, ++ DVB_DEVICE_OSD, 0); ++ ++ return 0; ++} ++ ++static int do_dvb_audio_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ //struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case AUDIO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->audio_pts; ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_audio_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_audio_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_audio_ioctl); ++} ++ ++static struct file_operations dvb_audio_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_audio_ioctl, ++#else ++ .unlocked_ioctl = dvb_audio_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_audio = { ++ .priv = NULL, ++ .users = 1, ++ .writers = 1, ++ .fops = &dvb_audio_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_audio_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->audio_dev); ++ return 0; ++} ++ ++static int saa716x_ff_audio_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->audio_dev, ++ &dvbdev_audio, ++ sti7109, ++ DVB_DEVICE_AUDIO, 0); ++ ++ return 0; ++} ++ ++static ssize_t ringbuffer_write_user(struct dvb_ringbuffer *rbuf, const u8 __user *buf, size_t len) ++{ ++ size_t todo = len; ++ size_t split; ++ ++ split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; ++ ++ if (split > 0) { ++ if (copy_from_user(rbuf->data+rbuf->pwrite, buf, split)) { ++ return -EFAULT; ++ } ++ buf += split; ++ todo -= split; ++ rbuf->pwrite = 0; ++ } ++ if (copy_from_user(rbuf->data+rbuf->pwrite, buf, todo)) { ++ return -EFAULT; ++ } ++ rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size; ++ ++ return len; ++} ++ ++static void ringbuffer_read_io32(struct dvb_ringbuffer *rbuf, u32 __iomem *buf, size_t len) ++{ ++ size_t todo = len; ++ size_t split; ++ ++ split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; ++ if (split > 0) { ++ iowrite32_rep(buf, rbuf->data+rbuf->pread, split/4); ++ buf += split; ++ todo -= split; ++ rbuf->pread = 0; ++ } ++ iowrite32_rep(buf, rbuf->data+rbuf->pread, todo/4); ++ ++ rbuf->pread = (rbuf->pread + todo) % rbuf->size; ++} ++ ++static void fifo_worker(struct work_struct *work) ++{ ++ struct sti7109_dev *sti7109 = container_of(work, struct sti7109_dev, fifo_work); ++ struct saa716x_dev *saa716x = sti7109->dev; ++ u32 fifoCtrl; ++ u32 fifoStat; ++ u16 fifoSize; ++ u16 fifoUsage; ++ u16 fifoFree; ++ int len; ++ ++ if (sti7109->tsout_stat == TSOUT_STAT_RESET) ++ return; ++ ++ fifoStat = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_STAT); ++ fifoSize = (u16) (fifoStat >> 16); ++ fifoUsage = (u16) fifoStat; ++ fifoFree = fifoSize - fifoUsage - 1; ++ len = dvb_ringbuffer_avail(&sti7109->tsout); ++ if (len > fifoFree) ++ len = fifoFree; ++ if (len < TS_SIZE) ++ return; ++ ++ while (len >= TS_SIZE) ++ { ++ ringbuffer_read_io32(&sti7109->tsout, saa716x->mmio + PHI_0 + PHI_0_0_RW_0, (size_t) TS_SIZE); ++ len -= TS_SIZE; ++ } ++ wake_up(&sti7109->tsout.queue); ++ ++ spin_lock(&sti7109->tsout.lock); ++ if (sti7109->tsout_stat != TSOUT_STAT_RESET) { ++ sti7109->tsout_stat = TSOUT_STAT_RUN; ++ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ spin_unlock(&sti7109->tsout.lock); ++} ++ ++static void video_vip_worker(unsigned long data) ++{ ++ struct saa716x_vip_stream_port *vip_entry = (struct saa716x_vip_stream_port *)data; ++ struct saa716x_dev *saa716x = vip_entry->saa716x; ++ u32 vip_index; ++ u32 write_index; ++ ++ vip_index = vip_entry->dma_channel[0]; ++ if (vip_index != 0) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, vip_entry->dma_channel[0]); ++ return; ++ } ++ ++ write_index = saa716x_vip_get_write_index(saa716x, vip_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == vip_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ vip_entry->dma_buf[0][vip_entry->read_index].sg_list, ++ vip_entry->dma_buf[0][vip_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ if (vip_entry->dual_channel) { ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ vip_entry->dma_buf[1][vip_entry->read_index].sg_list, ++ vip_entry->dma_buf[1][vip_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ } ++ ++ vip_entry->read_index = (vip_entry->read_index + 1) & 7; ++ } while (write_index != vip_entry->read_index); ++} ++ ++static int video_vip_get_stream_params(struct vip_stream_params * params, ++ u32 mode) ++{ ++ switch (mode) ++ { ++ case 4: /* 1280x720p60 */ ++ case 19: /* 1280x720p50 */ ++ params->bits = 16; ++ params->samples = 1280; ++ params->lines = 720; ++ params->pitch = 1280 * 2; ++ params->offset_x = 32; ++ params->offset_y = 30; ++ params->stream_flags = VIP_HD; ++ break; ++ ++ case 5: /* 1920x1080i60 */ ++ case 20: /* 1920x1080i50 */ ++ params->bits = 16; ++ params->samples = 1920; ++ params->lines = 1080; ++ params->pitch = 1920 * 2; ++ params->offset_x = 0; ++ params->offset_y = 20; ++ params->stream_flags = VIP_ODD_FIELD ++ | VIP_EVEN_FIELD ++ | VIP_INTERLACED ++ | VIP_HD ++ | VIP_NO_SCALER; ++ break; ++ ++ case 32: /* 1920x1080p24 */ ++ case 33: /* 1920x1080p25 */ ++ case 34: /* 1920x1080p30 */ ++ params->bits = 16; ++ params->samples = 1920; ++ params->lines = 1080; ++ params->pitch = 1920 * 2; ++ params->offset_x = 0; ++ params->offset_y = 0; ++ params->stream_flags = VIP_HD; ++ break; ++ ++ default: ++ return -1; ++ } ++ return 0; ++} ++ ++static ssize_t video_vip_read(struct sti7109_dev *sti7109, ++ struct vip_stream_params * stream_params, ++ char __user *buf, size_t count) ++{ ++ struct saa716x_dev *saa716x = sti7109->dev; ++ struct v4l2_pix_format pix_format; ++ int one_shot = 0; ++ size_t num_bytes; ++ size_t copy_bytes; ++ u32 read_index; ++ u8 *data; ++ int err = 0; ++ ++ if (sti7109->video_capture == VIDEO_CAPTURE_ONE_SHOT) ++ one_shot = 1; ++ ++ /* put a v4l2_pix_format header at the beginning of the returned data */ ++ memset(&pix_format, 0, sizeof(pix_format)); ++ pix_format.width = stream_params->samples; ++ pix_format.height = stream_params->lines; ++ pix_format.pixelformat = V4L2_PIX_FMT_UYVY; ++ pix_format.bytesperline = stream_params->pitch; ++ pix_format.sizeimage = stream_params->lines * stream_params->pitch; ++ ++ if (count > (sizeof(pix_format) + pix_format.sizeimage)) ++ count = sizeof(pix_format) + pix_format.sizeimage; ++ ++ if (count < sizeof(pix_format)) { ++ err = -EFAULT; ++ goto out; ++ } ++ ++ saa716x_vip_start(saa716x, 0, one_shot, stream_params); ++ /* Sleep long enough to be sure to capture at least one frame. ++ TODO: Change this in a way that it just waits the required time. */ ++ msleep(100); ++ saa716x_vip_stop(saa716x, 0); ++ ++ read_index = saa716x->vip[0].read_index; ++ if ((stream_params->stream_flags & VIP_INTERLACED) && ++ (stream_params->stream_flags & VIP_ODD_FIELD) && ++ (stream_params->stream_flags & VIP_EVEN_FIELD)) { ++ read_index = read_index & ~1; ++ read_index = (read_index + 7) & 7; ++ read_index = read_index / 2; ++ } else { ++ read_index = (read_index + 7) & 7; ++ } ++ ++ if (copy_to_user((void __user *)buf, &pix_format, sizeof(pix_format))) { ++ err = -EFAULT; ++ goto out; ++ } ++ num_bytes = sizeof(pix_format); ++ ++ copy_bytes = count - num_bytes; ++ if (copy_bytes > (SAA716x_PAGE_SIZE / 8 * SAA716x_PAGE_SIZE)) ++ copy_bytes = SAA716x_PAGE_SIZE / 8 * SAA716x_PAGE_SIZE; ++ data = (u8 *)saa716x->vip[0].dma_buf[0][read_index].mem_virt; ++ if (copy_to_user((void __user *)(buf + num_bytes), data, copy_bytes)) { ++ err = -EFAULT; ++ goto out; ++ } ++ num_bytes += copy_bytes; ++ if (saa716x->vip[0].dual_channel && ++ count - num_bytes > 0) { ++ copy_bytes = count - num_bytes; ++ if (copy_bytes > (SAA716x_PAGE_SIZE / 8 * SAA716x_PAGE_SIZE)) ++ copy_bytes = SAA716x_PAGE_SIZE / 8 * SAA716x_PAGE_SIZE; ++ data = (u8 *)saa716x->vip[0].dma_buf[1][read_index].mem_virt; ++ if (copy_to_user((void __user *)(buf + num_bytes), data, ++ copy_bytes)) { ++ err = -EFAULT; ++ goto out; ++ } ++ num_bytes += copy_bytes; ++ } ++ ++ return num_bytes; ++ ++out: ++ return err; ++} ++ ++static ssize_t dvb_video_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct vip_stream_params stream_params; ++ ssize_t ret = -ENODATA; ++ ++ if ((file->f_flags & O_ACCMODE) == O_WRONLY) ++ return -EPERM; ++ ++ mutex_lock(&sti7109->video_lock); ++ ++ if (sti7109->video_capture != VIDEO_CAPTURE_OFF) { ++ if (video_vip_get_stream_params(&stream_params, ++ sti7109->video_format) == 0) { ++ ret = video_vip_read(sti7109, &stream_params, ++ buf, count); ++ } ++ } ++ ++ mutex_unlock(&sti7109->video_lock); ++ return ret; ++} ++ ++#define FREE_COND_TS (dvb_ringbuffer_free(&sti7109->tsout) >= TS_SIZE) ++ ++static ssize_t dvb_video_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ unsigned long todo = count; ++ ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) ++ return -EPERM; ++/* ++ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) ++ return -EPERM; ++*/ ++ if (sti7109->tsout_stat == TSOUT_STAT_RESET) ++ return count; ++ ++ if ((file->f_flags & O_NONBLOCK) && !FREE_COND_TS) ++ return -EWOULDBLOCK; ++ ++ while (todo >= TS_SIZE) { ++ if (!FREE_COND_TS) { ++ if (file->f_flags & O_NONBLOCK) ++ break; ++ if (wait_event_interruptible(sti7109->tsout.queue, FREE_COND_TS)) ++ break; ++ } ++ ringbuffer_write_user(&sti7109->tsout, buf, TS_SIZE); ++ todo -= TS_SIZE; ++ buf += TS_SIZE; ++ } ++ ++ if ((sti7109->tsout_stat == TSOUT_STAT_RUN) || ++ (dvb_ringbuffer_avail(&sti7109->tsout) > TSOUT_LEN/3)) { ++ u32 fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ ++ return count - todo; ++} ++ ++static unsigned int dvb_video_poll(struct file *file, poll_table *wait) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ unsigned int mask = 0; ++ ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { ++ poll_wait(file, &sti7109->tsout.queue, wait); ++ ++ if (FREE_COND_TS) ++ mask |= (POLLOUT | POLLWRNORM); ++ } ++ ++ return mask; ++} ++ ++static int do_dvb_video_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case VIDEO_SELECT_SOURCE: ++ { ++ video_stream_source_t stream_source; ++ ++ stream_source = (video_stream_source_t) parg; ++ if (stream_source == VIDEO_SOURCE_DEMUX) { ++ /* stop and reset FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ sti7109->tsout_stat = TSOUT_STAT_RESET; ++ break; ++ } ++ /* fall through */ ++ } ++ case VIDEO_CLEAR_BUFFER: ++ { ++ /* reset FIFO 1 */ ++ spin_lock(&sti7109->tsout.lock); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ sti7109->tsout_stat = TSOUT_STAT_RESET; ++ spin_unlock(&sti7109->tsout.lock); ++ msleep(50); ++ cancel_work_sync(&sti7109->fifo_work); ++ /* start FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 2); ++ dvb_ringbuffer_flush(&sti7109->tsout); ++ sti7109->tsout_stat = TSOUT_STAT_FILL; ++ wake_up(&sti7109->tsout.queue); ++ break; ++ } ++ case VIDEO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->video_pts; ++ break; ++ } ++ case VIDEO_GET_SIZE: ++ { ++ ret = sti7109_cmd_get_video_format(sti7109, (video_size_t *) parg); ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_video_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_video_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_video_ioctl); ++} ++ ++static struct file_operations dvb_video_fops = { ++ .owner = THIS_MODULE, ++ .read = dvb_video_read, ++ .write = dvb_video_write, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_video_ioctl, ++#else ++ .unlocked_ioctl = dvb_video_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++ .poll = dvb_video_poll, ++}; ++ ++static struct dvb_device dvbdev_video = { ++ .priv = NULL, ++ .users = 5, ++ .readers = 5, ++ .writers = 1, ++ .fops = &dvb_video_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_video_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ if (sti7109->video_capture != VIDEO_CAPTURE_OFF) ++ saa716x_vip_exit(saa716x, 0); ++ ++ cancel_work_sync(&sti7109->fifo_work); ++ destroy_workqueue(sti7109->fifo_workq); ++ dvb_unregister_device(sti7109->video_dev); ++ return 0; ++} ++ ++static int saa716x_ff_video_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_ringbuffer_init(&sti7109->tsout, sti7109->iobuf, TSOUT_LEN); ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->video_dev, ++ &dvbdev_video, ++ sti7109, ++ DVB_DEVICE_VIDEO, 0); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) ++ sti7109->fifo_workq = create_singlethread_workqueue("saa716x_fifo_wq"); ++#else ++ sti7109->fifo_workq = alloc_workqueue("saa716x_fifo_wq%d", WQ_UNBOUND, 1, SAA716x_DEV); ++#endif ++ INIT_WORK(&sti7109->fifo_work, fifo_worker); ++ ++ if (sti7109->video_capture != VIDEO_CAPTURE_OFF) ++ saa716x_vip_init(saa716x, 0, video_vip_worker); ++ ++ return 0; ++} ++ ++static int saa716x_ff_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ struct sti7109_dev *sti7109; ++ int err = 0; ++ u32 value; ++ unsigned long timeout; ++ u32 fw_version; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->module = THIS_MODULE; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_phi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PHI Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ /* prepare the sti7109 device struct */ ++ sti7109 = kzalloc(sizeof(struct sti7109_dev), GFP_KERNEL); ++ if (!sti7109) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x: out of memory"); ++ goto fail3; ++ } ++ ++ sti7109->dev = saa716x; ++ ++ sti7109->iobuf = vmalloc(TSOUT_LEN + MAX_DATA_LEN); ++ if (!sti7109->iobuf) ++ goto fail4; ++ ++ sti7109_cmd_init(sti7109); ++ ++ sti7109->video_capture = video_capture; ++ mutex_init(&sti7109->video_lock); ++ ++ sti7109->int_count_enable = int_count_enable; ++ sti7109->total_int_count = 0; ++ memset(sti7109->vi_int_count, 0, sizeof(sti7109->vi_int_count)); ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ ++ saa716x->priv = sti7109; ++ ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS0); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS0, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS1); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS1, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ ++ /* hold ST in reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 0); ++ ++ /* enable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 1); ++ msleep(100); ++ ++ err = saa716x_ff_fpga_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF FPGA Initialization failed"); ++ goto fail5; ++ } ++ ++ /* configure TS muxer */ ++ if (sti7109->fpga_version < 0x110) { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 4); ++ } else { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 1); ++ } ++ ++ /* enable interrupts from ST7109 -> PC */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICTRL, 0x3); ++ ++ value = SAA716x_EPRD(MSI, MSI_CONFIG33); ++ value &= 0xFCFFFFFF; ++ value |= MSI_INT_POL_EDGE_FALL; ++ SAA716x_EPWR(MSI, MSI_CONFIG33, value); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_EXTINT_0); ++ ++ /* enable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 0); ++ msleep(50); ++ /* disable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 1); ++ ++ err = saa716x_ff_st7109_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF STi7109 initialization failed"); ++ goto fail5; ++ } ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable FGPI2 and FGPI3 for TS inputs */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x0689F04); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x280); ++ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, 0xC0); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail6; ++ } ++ ++ /* wait a maximum of 10 seconds for the STi7109 to boot */ ++ timeout = 10 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->boot_finish_wq, ++ sti7109->boot_finished == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->boot_finished == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ goto fail6; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for boot finish"); ++ err = -1; ++ goto fail6; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 finished booting"); ++ ++ err = saa716x_ff_video_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF VIDEO initialization failed"); ++ goto fail7; ++ } ++ ++ err = saa716x_ff_audio_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF AUDIO initialization failed"); ++ goto fail8; ++ } ++ ++ err = saa716x_ff_osd_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF OSD initialization failed"); ++ goto fail9; ++ } ++ ++ err = sti7109_cmd_get_fw_version(sti7109, &fw_version); ++ if (!err) { ++ printk(KERN_INFO "SAA716x FF firmware version %d.%d.%d\n", ++ (fw_version >> 16) & 0xFF, (fw_version >> 8) & 0xFF, ++ fw_version & 0xFF); ++ } ++ ++ err = saa716x_ir_init(saa716x); ++ if (err) ++ goto fail9; ++ ++ return 0; ++ ++fail9: ++ saa716x_ff_osd_exit(saa716x); ++fail8: ++ saa716x_ff_audio_exit(saa716x); ++fail7: ++ saa716x_ff_video_exit(saa716x); ++fail6: ++ saa716x_dvb_exit(saa716x); ++fail5: ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++fail4: ++ kfree(sti7109); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_ff_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ saa716x_ir_exit(saa716x); ++ ++ saa716x_ff_osd_exit(saa716x); ++ ++ saa716x_ff_audio_exit(saa716x); ++ ++ saa716x_ff_video_exit(saa716x); ++ ++ saa716x_dvb_exit(saa716x); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++ ++ saa716x->priv = NULL; ++ kfree(sti7109); ++ ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++static irqreturn_t saa716x_ff_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ struct sti7109_dev *sti7109; ++ u32 msiStatusL; ++ u32 msiStatusH; ++ u32 phiISR; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ sti7109 = saa716x->priv; ++ if (unlikely(sti7109 == NULL)) { ++ printk("%s: sti7109=NULL", __func__); ++ return IRQ_NONE; ++ } ++ if (sti7109->int_count_enable) ++ sti7109->total_int_count++; ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ msiStatusL = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, msiStatusL); ++ msiStatusH = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, msiStatusH); ++ ++ if (msiStatusL) { ++ if (msiStatusL & MSI_INT_TAGACK_VI0_0) { ++ if (sti7109->int_count_enable) ++ sti7109->vi_int_count[0]++; ++ tasklet_schedule(&saa716x->vip[0].tasklet); ++ } ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_2) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[2]++; ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_3) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[3]++; ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ if (msiStatusH) { ++ //dprintk(SAA716x_INFO, 1, "msiStatusH: %08X", msiStatusH); ++ } ++ ++ if (msiStatusH & MSI_INT_I2CINT_0) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[0]++; ++ saa716x->i2c[0].i2c_op = 0; ++ wake_up(&saa716x->i2c[0].i2c_wq); ++ } ++ if (msiStatusH & MSI_INT_I2CINT_1) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[1]++; ++ saa716x->i2c[1].i2c_op = 0; ++ wake_up(&saa716x->i2c[1].i2c_wq); ++ } ++ ++ if (msiStatusH & MSI_INT_EXTINT_0) { ++ ++ phiISR = SAA716x_EPRD(PHI_1, FPGA_ADDR_EMI_ISR); ++ //dprintk(SAA716x_INFO, 1, "interrupt status register: %08X", phiISR); ++ ++ if (sti7109->int_count_enable) { ++ int i; ++ sti7109->ext_int_total_count++; ++ for (i = 0; i < 16; i++) ++ if (phiISR & (1 << i)) ++ sti7109->ext_int_source_count[i]++; ++ } ++ ++ if (phiISR & ISR_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_CMD_DATA, sti7109->result_data, length); ++ sti7109->result_len = length; ++ sti7109->result_avail = 1; ++ wake_up(&sti7109->result_avail_wq); ++ ++ phiISR &= ~ISR_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "READY interrupt source");*/ ++ sti7109->cmd_ready = 1; ++ wake_up(&sti7109->cmd_ready_wq); ++ phiISR &= ~ISR_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_READY_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_OSD_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "OSD CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_result_data, length); ++ sti7109->osd_result_len = length; ++ sti7109->osd_result_avail = 1; ++ wake_up(&sti7109->osd_result_avail_wq); ++ ++ phiISR &= ~ISR_OSD_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "OSD_READY interrupt source");*/ ++ sti7109->osd_cmd_ready = 1; ++ wake_up(&sti7109->osd_cmd_ready_wq); ++ phiISR &= ~ISR_OSD_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_READY_MASK); ++ } ++ ++ if (phiISR & ISR_BLOCK_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BLOCK interrupt source");*/ ++ sti7109->block_done = 1; ++ wake_up(&sti7109->block_done_wq); ++ phiISR &= ~ISR_BLOCK_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BLOCK_MASK); ++ } ++ ++ if (phiISR & ISR_DATA_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "DATA interrupt source");*/ ++ sti7109->data_ready = 1; ++ wake_up(&sti7109->data_ready_wq); ++ phiISR &= ~ISR_DATA_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DATA_MASK); ++ } ++ ++ if (phiISR & ISR_BOOT_FINISH_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BOOT FINISH interrupt source");*/ ++ sti7109->boot_finished = 1; ++ wake_up(&sti7109->boot_finish_wq); ++ phiISR &= ~ISR_BOOT_FINISH_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BOOT_FINISH_MASK); ++ } ++ ++ if (phiISR & ISR_AUDIO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_AUDIO_PTS, data, 8); ++ sti7109->audio_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_AUDIO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_AUDIO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "AUDIO PTS: %llX", sti7109->audio_pts);*/ ++ } ++ ++ if (phiISR & ISR_VIDEO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_VIDEO_PTS, data, 8); ++ sti7109->video_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_VIDEO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_VIDEO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "VIDEO PTS: %llX", sti7109->video_pts);*/ ++ } ++ ++ if (phiISR & ISR_CURRENT_STC_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_CURRENT_STC, data, 8); ++ sti7109->current_stc = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_CURRENT_STC_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CURRENT_STC_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "CURRENT STC: %llu", sti7109->current_stc);*/ ++ } ++ ++ if (phiISR & ISR_REMOTE_EVENT_MASK) { ++ u8 data[4]; ++ u32 remote_event; ++ ++ saa716x_phi_read(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ remote_event = (data[3] << 24) ++ | (data[2] << 16) ++ | (data[1] << 8) ++ | (data[0]); ++ memset(data, 0, sizeof(data)); ++ saa716x_phi_write(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ ++ phiISR &= ~ISR_REMOTE_EVENT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_REMOTE_EVENT_MASK); ++ ++ if (remote_event == 0) { ++ dprintk(SAA716x_ERROR, 1, "REMOTE EVENT: %X ignored", remote_event); ++ } else { ++ dprintk(SAA716x_INFO, 1, "REMOTE EVENT: %X", remote_event); ++ saa716x_ir_handler(saa716x, remote_event); ++ } ++ } ++ ++ if (phiISR & ISR_DVO_FORMAT_MASK) { ++ u8 data[4]; ++ u32 format; ++ ++ saa716x_phi_read(saa716x, ADDR_DVO_FORMAT, data, 4); ++ format = (data[0] << 24) ++ | (data[1] << 16) ++ | (data[2] << 8) ++ | (data[3]); ++ ++ phiISR &= ~ISR_DVO_FORMAT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DVO_FORMAT_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "DVO FORMAT CHANGE: %u", format); ++ sti7109->video_format = format; ++ } ++ ++ if (phiISR & ISR_LOG_MESSAGE_MASK) { ++ char message[SIZE_LOG_MESSAGE_DATA]; ++ ++ saa716x_phi_read(saa716x, ADDR_LOG_MESSAGE, message, ++ SIZE_LOG_MESSAGE_DATA); ++ ++ phiISR &= ~ISR_LOG_MESSAGE_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_LOG_MESSAGE_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "LOG MESSAGE: %.*s", ++ SIZE_LOG_MESSAGE_DATA, message); ++ } ++ ++ if (phiISR & ISR_FIFO1_EMPTY_MASK) { ++ u32 fifoCtrl; ++ ++ /*dprintk(SAA716x_INFO, 1, "FIFO EMPTY interrupt source");*/ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl &= ~0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ queue_work(sti7109->fifo_workq, &sti7109->fifo_work); ++ phiISR &= ~ISR_FIFO1_EMPTY_MASK; ++ } ++ ++ if (phiISR) { ++ dprintk(SAA716x_INFO, 1, "unknown interrupt source"); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, phiISR); ++ } ++ } ++ ++ if (sti7109->int_count_enable) { ++ if (jiffies - sti7109->last_int_ticks >= HZ) { ++ dprintk(SAA716x_INFO, 1, ++ "int count: t: %d, v: %d %d, f:%d %d %d %d, i:%d %d," ++ "e: %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)", ++ sti7109->total_int_count, ++ sti7109->vi_int_count[0], ++ sti7109->vi_int_count[1], ++ sti7109->fgpi_int_count[0], ++ sti7109->fgpi_int_count[1], ++ sti7109->fgpi_int_count[2], ++ sti7109->fgpi_int_count[3], ++ sti7109->i2c_int_count[0], ++ sti7109->i2c_int_count[1], ++ sti7109->ext_int_total_count, ++ sti7109->ext_int_source_count[0], ++ sti7109->ext_int_source_count[1], ++ sti7109->ext_int_source_count[2], ++ sti7109->ext_int_source_count[3], ++ sti7109->ext_int_source_count[4], ++ sti7109->ext_int_source_count[5], ++ sti7109->ext_int_source_count[6], ++ sti7109->ext_int_source_count[7], ++ sti7109->ext_int_source_count[8], ++ sti7109->ext_int_source_count[9], ++ sti7109->ext_int_source_count[10], ++ sti7109->ext_int_source_count[11], ++ sti7109->ext_int_source_count[12], ++ sti7109->ext_int_source_count[13], ++ sti7109->ext_int_source_count[14], ++ sti7109->ext_int_source_count[15]); ++ sti7109->total_int_count = 0; ++ memset(sti7109->vi_int_count, 0, sizeof(sti7109->vi_int_count)); ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ } ++ } ++ return IRQ_HANDLED; ++} ++ ++#define SAA716x_MODEL_S2_6400_DUAL "Technotrend S2 6400 Dual S2 Premium" ++#define SAA716x_DEV_S2_6400_DUAL "2x DVB-S/S2 + Hardware decode" ++ ++static struct stv090x_config tt6400_stv090x_config = { ++ .device = STV0900, ++ .demod_mode = STV090x_DUAL, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 13500000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts1_clk = 135000000, ++ .ts2_clk = 135000000, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static struct stv6110x_config tt6400_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 27000000, ++ .clk_div = 2, ++}; ++ ++static struct isl6423_config tt6400_isl6423_config[2] = { ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x09, ++ }, ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x08, ++ } ++}; ++ ++ ++static int saa716x_s26400_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *i2c_adapter = &i2c[SAA716x_I2C_BUS_A].i2c_adapter; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ if (count == 0 || count == 1) { ++ adapter->fe = dvb_attach(stv090x_attach, ++ &tt6400_stv090x_config, ++ i2c_adapter, ++ STV090x_DEMODULATOR_0 + count); ++ ++ if (adapter->fe) { ++ struct stv6110x_devctl *ctl; ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &tt6400_stv6110x_config, ++ i2c_adapter); ++ ++ tt6400_stv090x_config.tuner_init = ctl->tuner_init; ++ tt6400_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ tt6400_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ tt6400_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ tt6400_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ tt6400_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ tt6400_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ tt6400_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ tt6400_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ tt6400_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ tt6400_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ if (count == 1) { ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ /* The second tuner drives the STV0900 so ++ call it only for adapter 1 */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } ++ ++ dvb_attach(isl6423_attach, ++ adapter->fe, ++ i2c_adapter, ++ &tt6400_isl6423_config[count]); ++ ++ } ++ } ++ return 0; ++} ++ ++static struct saa716x_config saa716x_s26400_config = { ++ .model_name = SAA716x_MODEL_S2_6400_DUAL, ++ .dev_type = SAA716x_DEV_S2_6400_DUAL, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_s26400_frontend_attach, ++ .irq_handler = saa716x_ff_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_IRQ_BUFFERED, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ },{ ++ /* Adapter 1 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++static struct pci_device_id saa716x_ff_pci_table[] = { ++ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_DEVEL, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual development version */ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_PROD, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual production version */ ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_ff_pci_table); ++ ++static struct pci_driver saa716x_ff_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_ff_pci_table, ++ .probe = saa716x_ff_pci_probe, ++ .remove = saa716x_ff_pci_remove, ++}; ++ ++module_pci_driver(saa716x_ff_pci_driver); ++ ++MODULE_DESCRIPTION("SAA716x FF driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/pci/saa716x/saa716x_fgpi.c b/drivers/media/pci/saa716x/saa716x_fgpi.c +new file mode 100644 +index 0000000..ec21dd5 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_fgpi.c +@@ -0,0 +1,386 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static const u32 fgpi_ch[] = { ++ FGPI0, ++ FGPI1, ++ FGPI2, ++ FGPI3 ++}; ++ ++static const u32 bamdma_bufmode[] = { ++ BAM_FGPI0_DMA_BUF_MODE, ++ BAM_FGPI1_DMA_BUF_MODE, ++ BAM_FGPI2_DMA_BUF_MODE, ++ BAM_FGPI3_DMA_BUF_MODE ++}; ++ ++static const u32 msi_int_tagack[] = { ++ MSI_INT_TAGACK_FGPI_0, ++ MSI_INT_TAGACK_FGPI_1, ++ MSI_INT_TAGACK_FGPI_2, ++ MSI_INT_TAGACK_FGPI_3 ++}; ++ ++static const u32 msi_int_ovrflw[] = { ++ MSI_INT_OVRFLW_FGPI_0, ++ MSI_INT_OVRFLW_FGPI_1, ++ MSI_INT_OVRFLW_FGPI_2, ++ MSI_INT_OVRFLW_FGPI_3 ++}; ++ ++static const u32 msi_int_avint[] = { ++ MSI_INT_AVINT_FGPI_0, ++ MSI_INT_AVINT_FGPI_1, ++ MSI_INT_AVINT_FGPI_2, ++ MSI_INT_AVINT_FGPI_3 ++}; ++ ++void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port; ++ ++ fgpi_port = fgpi_ch[channel]; ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0); /* disable FGPI IRQ */ ++ SAA716x_EPWR(fgpi_port, INT_CLR_STATUS, 0x7f); /* clear status */ ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpiint_disable); ++ ++int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, u32 fgpi_index) ++{ ++ u32 fgpi_base; ++ u32 buf_mode_reg; ++ u32 buf_mode; ++ ++ switch (fgpi_index) { ++ case 0: /* FGPI_0 */ ++ fgpi_base = FGPI0; ++ buf_mode_reg = BAM_FGPI0_DMA_BUF_MODE; ++ break; ++ ++ case 1: /* FGPI_1 */ ++ fgpi_base = FGPI1; ++ buf_mode_reg = BAM_FGPI1_DMA_BUF_MODE; ++ break; ++ ++ case 2: /* FGPI_2 */ ++ fgpi_base = FGPI2; ++ buf_mode_reg = BAM_FGPI2_DMA_BUF_MODE; ++ break; ++ ++ case 3: /* FGPI_3 */ ++ fgpi_base = FGPI3; ++ buf_mode_reg = BAM_FGPI3_DMA_BUF_MODE; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: unexpected fgpi %u\n", ++ __func__, fgpi_index); ++ return -1; ++ } ++ ++ buf_mode = SAA716x_EPRD(BAM, buf_mode_reg); ++ if (saa716x->revision < 2) { ++ /* workaround for revision 1: restore buffer numbers on BAM */ ++ SAA716x_EPWR(fgpi_base, INT_CLR_STATUS, 0x7F); ++ SAA716x_EPWR(BAM, buf_mode_reg, buf_mode | 7); ++ } ++ return (buf_mode >> 3) & 0x7; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_get_write_index); ++ ++static u32 saa716x_init_ptables(struct saa716x_dmabuf *dmabuf, int channel, ++ struct fgpi_stream_params *stream_params) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 config, i; ++ ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); ++ ++ config = MMU_DMA_CONFIG(channel); /* DMACONFIGx */ ++ ++ SAA716x_EPWR(MMU, config, (FGPI_BUFFERS - 1)); ++ ++ if ((stream_params->stream_flags & FGPI_INTERLACED) && ++ (stream_params->stream_flags & FGPI_ODD_FIELD) && ++ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { ++ /* In interlaced mode the same buffer is written twice, once ++ the odd field and once the even field */ ++ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ } else { ++ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ ++ } ++ ++ return 0; ++} ++ ++int saa716x_fgpi_setparams(struct saa716x_dmabuf *dmabuf, ++ struct fgpi_stream_params *stream_params, ++ int port) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port, buf_mode, val, mid; ++ u32 D1_XY_END, offst_1, offst_2; ++ int i = 0; ++ u8 dma_channel; ++ ++ fgpi_port = fgpi_ch[port]; ++ buf_mode = bamdma_bufmode[port]; ++ dma_channel = saa716x->fgpi[port].dma_channel; ++ ++ /* Reset FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* Reset DMA channel */ ++ SAA716x_EPWR(BAM, buf_mode, 0x00000040); ++ saa716x_init_ptables(dmabuf, dma_channel, stream_params); ++ ++ ++ /* monitor BAM reset */ ++ val = SAA716x_EPRD(BAM, buf_mode); ++ while (val && (i < 100)) { ++ msleep(30); ++ val = SAA716x_EPRD(BAM, buf_mode); ++ i++; ++ } ++ ++ if (val) { ++ dprintk(SAA716x_ERROR, 1, "Error: BAM FGPI Reset failed!"); ++ return -EIO; ++ } ++ ++ /* set buffer count */ ++ SAA716x_EPWR(BAM, buf_mode, FGPI_BUFFERS - 1); ++ ++ /* initialize all available address offsets */ ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_0(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_1(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_2(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_3(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_4(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_5(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_6(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_7(dma_channel), 0x0); ++ ++ /* get module ID */ ++ mid = SAA716x_EPRD(fgpi_port, FGPI_MODULE_ID); ++ if (mid != 0x14b0100) ++ dprintk(SAA716x_ERROR, 1, "FGPI Id<%04x> is not supported", mid); ++ ++ /* Initialize FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_REC_SIZE, stream_params->samples * (stream_params->bits / 8)); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); ++ ++ offst_1 = 0; ++ offst_2 = 0; ++ switch (stream_params->stream_type) { ++ case FGPI_TRANSPORT_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_RAW_STREAM: ++ case FGPI_PROGRAM_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_VIDEO_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000040); ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_START, stream_params->offset); ++ ++ if ((stream_params->stream_flags & FGPI_INTERLACED) && ++ (stream_params->stream_flags & FGPI_ODD_FIELD) && ++ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { ++ ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines / 2); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch * 2); /* interlaced stride of 2 lines */ ++ ++ D1_XY_END = (stream_params->samples << 16); ++ D1_XY_END |= (stream_params->lines / 2) + stream_params->offset; ++ ++ if (stream_params->stream_flags & FGPI_PAL) ++ offst_2 = stream_params->pitch; ++ else ++ offst_1 = stream_params->pitch; ++ ++ } else { ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); /* stride of 1 line */ ++ ++ D1_XY_END = stream_params->samples << 16; ++ D1_XY_END |= stream_params->lines + stream_params->offset; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_END, D1_XY_END); ++ break; ++ ++ default: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ break; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_1, (dma_channel << 21) + offst_1); ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_2, (dma_channel << 21) + offst_2); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params) ++{ ++ u32 fgpi_port; ++ u32 config; ++ u32 val; ++ u32 i; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(fgpi_port, FGPI_INTERFACE, 0); ++ msleep(10); ++ ++ if (saa716x_fgpi_setparams(saa716x->fgpi[port].dma_buf, stream_params, port) != 0) { ++ return -EIO; ++ } ++ ++ saa716x->fgpi[port].read_index = 0; ++ ++ config = MMU_DMA_CONFIG(saa716x->fgpi[port].dma_channel); /* DMACONFIGx */ ++ ++ val = SAA716x_EPRD(MMU, config); ++ SAA716x_EPWR(MMU, config, val & ~0x40); ++ SAA716x_EPWR(MMU, config, val | 0x40); ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0x7F); ++ ++ val = SAA716x_EPRD(MMU, config); ++ i = 0; ++ while (i < 500) { ++ if (val & 0x80) ++ break; ++ msleep(10); ++ val = SAA716x_EPRD(MMU, config); ++ i++; ++ } ++ ++ if (!(val & 0x80)) { ++ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); ++ return -EIO; ++ } ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val |= 0x3000; ++ ++ saa716x_set_clk_external(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_start); ++ ++int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port) ++{ ++ u32 fgpi_port; ++ u32 val; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val &= ~0x3000; ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ saa716x_set_clk_internal(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_stop); ++ ++int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, int dma_buf_size, ++ void (*worker)(unsigned long)) ++{ ++ int i; ++ int ret; ++ ++ saa716x->fgpi[port].dma_channel = port + 6; ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ ret = saa716x_dmabuf_alloc(saa716x, ++ &saa716x->fgpi[port].dma_buf[i], ++ dma_buf_size); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ saa716x->fgpi[port].saa716x = saa716x; ++ tasklet_init(&saa716x->fgpi[port].tasklet, worker, ++ (unsigned long)&saa716x->fgpi[port]); ++ saa716x->fgpi[port].read_index = 0; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_init); ++ ++int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port) ++{ ++ int i; ++ ++ tasklet_kill(&saa716x->fgpi[port].tasklet); ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ saa716x_dmabuf_free(saa716x, &saa716x->fgpi[port].dma_buf[i]); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_exit); +diff --git a/drivers/media/pci/saa716x/saa716x_fgpi.h b/drivers/media/pci/saa716x/saa716x_fgpi.h +new file mode 100644 +index 0000000..47f9a9c +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_fgpi.h +@@ -0,0 +1,92 @@ ++#ifndef __SAA716x_FGPI_H ++#define __SAA716x_FGPI_H ++ ++#include ++ ++#define FGPI_BUFFERS 8 ++ ++ ++/* ++ * Port supported streams ++ * ++ * FGPI_AUDIO_STREAM ++ * FGPI_VIDEO_STREAM ++ * FGPI_VBI_STREAM ++ * FGPI_TRANSPORT_STREAM ++ * FGPI_PROGRAM_STREAM ++ */ ++enum fgpi_stream_type { ++ FGPI_RAW_STREAM = 0x00, ++ FGPI_AUDIO_STREAM = 0x01, ++ FGPI_VIDEO_STREAM = 0x02, ++ FGPI_VBI_STREAM = 0x04, ++ FGPI_TRANSPORT_STREAM = 0x08, ++ FGPI_PROGRAM_STREAM = 0x10 ++}; ++ ++/* ++ * Stream port flags ++ * ++ * FGPI_ODD_FIELD ++ * FGPI_EVEN_FIELD ++ * FGPI_HD_0 ++ * FGPI_HD_1 ++ * FGPI_PAL ++ * FGPI_NTSC ++ */ ++enum fgpi_stream_flags { ++ FGPI_ODD_FIELD = 0x0001, ++ FGPI_EVEN_FIELD = 0x0002, ++ FGPI_INTERLACED = 0x0004, ++ FGPI_HD0 = 0x0010, ++ FGPI_HD1 = 0x0020, ++ FGPI_PAL = 0x0040, ++ FGPI_NTSC = 0x0080, ++ FGPI_NO_SCALER = 0x0100, ++}; ++ ++/* ++ * Stream port parameters ++ * bits: Bits per sample ++ * samples: samples perline ++ * lines: number of lines ++ * pitch: stream pitch in bytes ++ * offset: offset to first valid line ++ */ ++struct fgpi_stream_params { ++ u32 bits; ++ u32 samples; ++ u32 lines; ++ ++ s32 pitch; ++ ++ u32 offset; ++ u32 page_tables; ++ ++ enum fgpi_stream_flags stream_flags; ++ enum fgpi_stream_type stream_type; ++}; ++ ++struct saa716x_dmabuf; ++ ++struct saa716x_fgpi_stream_port { ++ u8 dma_channel; ++ struct saa716x_dmabuf dma_buf[FGPI_BUFFERS]; ++ struct saa716x_dev *saa716x; ++ struct tasklet_struct tasklet; ++ u8 read_index; ++}; ++ ++extern void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel); ++extern int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, ++ u32 fgpi_index); ++extern int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params); ++extern int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port); ++ ++extern int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, ++ int dma_buf_size, ++ void (*worker)(unsigned long)); ++extern int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port); ++ ++#endif /* __SAA716x_FGPI_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_fgpi_reg.h b/drivers/media/pci/saa716x/saa716x_fgpi_reg.h +new file mode 100644 +index 0000000..1193016 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_fgpi_reg.h +@@ -0,0 +1,74 @@ ++#ifndef __SAA716x_FGPI_REG_H ++#define __SAA716x_FGPI_REG_H ++ ++/* -------------- FGPI Registers -------------- */ ++ ++#define FGPI_CONTROL 0x000 ++#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) ++#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) ++#define FGPI_MODE (0x00000001 << 11) ++#define FGPI_SAMPLE_SIZE (0x00000003 << 8) ++#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) ++#define FGPI_REC_START_MSG_START (0x00000003 << 2) ++#define FGPI_TSTAMP_SELECT (0x00000001 << 1) ++#define FGPI_VAR_LENGTH (0x00000001 << 0) ++ ++#define FGPI_BASE_1 0x004 ++#define FGPI_BASE_2 0x008 ++#define FGPI_SIZE 0x00c ++#define FGPI_REC_SIZE 0x010 ++#define FGPI_STRIDE 0x014 ++#define FGPI_NUM_RECORD_1 0x018 ++#define FGPI_NUM_RECORD_2 0x01c ++#define FGPI_THRESHOLD_1 0x020 ++#define FGPI_THRESHOLD_2 0x024 ++#define FGPI_D1_XY_START 0x028 ++#define FGPI_D1_XY_END 0x02c ++ ++#define INT_STATUS 0xfe0 ++#define FGPI_BUF1_ACTIVE (0x00000001 << 7) ++#define FGPI_OVERFLOW (0x00000001 << 6) ++#define FGPI_MBE (0x00000001 << 5) ++#define FGPI_UNDERRUN (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED (0x00000001 << 2) ++#define FGPI_BUF2_FULL (0x00000001 << 1) ++#define FGPI_BUF1_FULL (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define FGPI_OVERFLOW_ENA (0x00000001 << 6) ++#define FGPI_MBE_ENA (0x00000001 << 5) ++#define FGPI_UNDERRUN_ENA (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) ++#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) ++#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define FGPI_OVERFLOW_ACK (0x00000001 << 6) ++#define FGPI_MBE_ACK (0x00000001 << 5) ++#define FGPI_UNDERRUN_ACK (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) ++#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) ++#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define FGPI_OVERFLOW_SET (0x00000001 << 6) ++#define FGPI_MBE_SET (0x00000001 << 5) ++#define FGPI_UNDERRUN_SET (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) ++#define FGPI_BUF2_DONE_SET (0x00000001 << 1) ++#define FGPI_BUF1_DONE_SET (0x00000001 << 0) ++ ++#define FGPI_SOFT_RESET 0xff0 ++#define FGPI_SOFTWARE_RESET (0x00000001 << 0) ++ ++#define FGPI_INTERFACE 0xff4 ++#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) ++ ++#define FGPI_MOD_ID_EXT 0xff8 ++#define FGPI_MODULE_ID 0xffc ++ ++#endif /* __SAA716x_FGPI_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_gpio.c b/drivers/media/pci/saa716x/saa716x_gpio.c +new file mode 100644 +index 0000000..62b6112 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_gpio.c +@@ -0,0 +1,140 @@ ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++ ++#include "saa716x_gpio.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++void saa716x_gpio_init(struct saa716x_dev *saa716x) ++{ ++ spin_lock_init(&saa716x->gpio_lock); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_init); ++ ++int saa716x_get_gpio_mode(struct saa716x_dev *saa716x, u32 *config) ++{ ++ *config = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ ++ return 0; ++} ++ ++int saa716x_set_gpio_mode(struct saa716x_dev *saa716x, u32 mask, u32 config) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ reg = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ reg &= ~mask; ++ reg |= (config & mask); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, reg); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++u32 saa716x_gpio_rd(struct saa716x_dev *saa716x) ++{ ++ return SAA716x_EPRD(GPIO, GPIO_RD); ++} ++ ++void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data) ++{ ++ SAA716x_EPWR(GPIO, GPIO_WR, data); ++} ++ ++void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_OEN); ++ reg &= mask; ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_OEN, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_WR); ++ reg &= ~bits; ++ /* TODO ! add maskable config bits in here */ ++ /* reg |= (config->mask & bits) */ ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_WR, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_output); ++ ++void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value |= 1 << gpio; ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_input); ++ ++void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ if (mode) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_mode); ++ ++void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set) ++{ ++ uint32_t value; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ value = SAA716x_EPRD(GPIO, GPIO_WR); ++ if (set) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR, value); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_write); ++ ++int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_RD); ++ if (value & (1 << gpio)) ++ return 1; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_read); +diff --git a/drivers/media/pci/saa716x/saa716x_gpio.h b/drivers/media/pci/saa716x/saa716x_gpio.h +new file mode 100644 +index 0000000..a82580b +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_gpio.h +@@ -0,0 +1,26 @@ ++#ifndef __SAA716x_GPIO_H ++#define __SAA716x_GPIO_H ++ ++#define BOOT_MODE GPIO_31 | GPIO_30 ++#define AV_UNIT_B GPIO_25 ++#define AV_UNIT_A GPIO_24 ++#define AV_INTR_B GPIO_01 ++#define AV_INTR_A GPIO_00 ++ ++struct saa716x_dev; ++ ++extern void saa716x_gpio_init(struct saa716x_dev *saa716x); ++ ++extern u32 saa716x_gpio_rd(struct saa716x_dev *saa716x); ++extern void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data); ++extern void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits); ++ ++extern void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits); ++ ++extern void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode); ++extern void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set); ++extern int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio); ++ ++#endif /* __SAA716x_GPIO_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_gpio_reg.h b/drivers/media/pci/saa716x/saa716x_gpio_reg.h +new file mode 100644 +index 0000000..f36184a +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_gpio_reg.h +@@ -0,0 +1,47 @@ ++#ifndef __SAA716x_GPIO_REG_H ++#define __SAA716x_GPIO_REG_H ++ ++/* -------------- GPIO Registers -------------- */ ++ ++#define GPIO_RD 0x000 ++#define GPIO_WR 0x004 ++#define GPIO_WR_MODE 0x008 ++#define GPIO_OEN 0x00c ++ ++#define GPIO_SW_RST 0xff0 ++#define GPIO_SW_RESET (0x00000001 << 0) ++ ++#define GPIO_31 (1 << 31) ++#define GPIO_30 (1 << 30) ++#define GPIO_29 (1 << 29) ++#define GPIO_28 (1 << 28) ++#define GPIO_27 (1 << 27) ++#define GPIO_26 (1 << 26) ++#define GPIO_25 (1 << 25) ++#define GPIO_24 (1 << 24) ++#define GPIO_23 (1 << 23) ++#define GPIO_22 (1 << 22) ++#define GPIO_21 (1 << 21) ++#define GPIO_20 (1 << 20) ++#define GPIO_19 (1 << 19) ++#define GPIO_18 (1 << 18) ++#define GPIO_17 (1 << 17) ++#define GPIO_16 (1 << 16) ++#define GPIO_15 (1 << 15) ++#define GPIO_14 (1 << 14) ++#define GPIO_13 (1 << 13) ++#define GPIO_12 (1 << 12) ++#define GPIO_11 (1 << 11) ++#define GPIO_10 (1 << 10) ++#define GPIO_09 (1 << 9) ++#define GPIO_08 (1 << 8) ++#define GPIO_07 (1 << 7) ++#define GPIO_06 (1 << 6) ++#define GPIO_05 (1 << 5) ++#define GPIO_04 (1 << 4) ++#define GPIO_03 (1 << 3) ++#define GPIO_02 (1 << 2) ++#define GPIO_01 (1 << 1) ++#define GPIO_00 (1 << 0) ++ ++#endif /* __SAA716x_GPIO_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_greg.c b/drivers/media/pci/saa716x/saa716x_greg.c +new file mode 100644 +index 0000000..d93a3b8 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_greg.c +@@ -0,0 +1,42 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_greg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static u32 g_save[12]; ++ ++void saa716x_greg_save(struct saa716x_dev *saa716x) ++{ ++ g_save[0] = SAA716x_EPRD(GREG, GREG_SUBSYS_CONFIG); ++ g_save[1] = SAA716x_EPRD(GREG, GREG_MSI_BAR_PMCSR); ++ g_save[2] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_1); ++ g_save[3] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_2); ++ g_save[4] = SAA716x_EPRD(GREG, GREG_VI_CTRL); ++ g_save[5] = SAA716x_EPRD(GREG, GREG_FGPI_CTRL); ++ g_save[6] = SAA716x_EPRD(GREG, GREG_RSTU_CTRL); ++ g_save[7] = SAA716x_EPRD(GREG, GREG_I2C_CTRL); ++ g_save[8] = SAA716x_EPRD(GREG, GREG_OVFLW_CTRL); ++ g_save[9] = SAA716x_EPRD(GREG, GREG_TAG_ACK_FLEN); ++ ++ g_save[10] = SAA716x_EPRD(GREG, GREG_VIDEO_IN_CTRL); ++} ++ ++void saa716x_greg_restore(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, g_save[0]); ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, g_save[1]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, g_save[2]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, g_save[3]); ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, g_save[4]); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, g_save[5]); ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, g_save[6]); ++ SAA716x_EPWR(GREG, GREG_I2C_CTRL, g_save[7]); ++ SAA716x_EPWR(GREG, GREG_OVFLW_CTRL, g_save[8]); ++ SAA716x_EPWR(GREG, GREG_TAG_ACK_FLEN, g_save[9]); ++ ++ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, g_save[10]); ++} +diff --git a/drivers/media/pci/saa716x/saa716x_greg.h b/drivers/media/pci/saa716x/saa716x_greg.h +new file mode 100644 +index 0000000..487595e +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_greg.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_GREG_H ++#define __SAA716x_GREG_H ++ ++struct saa716x_dev; ++ ++extern void saa716x_greg_save(struct saa716x_dev *saa716x); ++extern void saa716x_greg_restore(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_GREG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_greg_reg.h b/drivers/media/pci/saa716x/saa716x_greg_reg.h +new file mode 100644 +index 0000000..052e8cd +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_greg_reg.h +@@ -0,0 +1,91 @@ ++#ifndef __SAA716x_GREG_REG_H ++#define __SAA716x_GREG_REG_H ++ ++/* -------------- GREG Registers -------------- */ ++ ++#define GREG_SUBSYS_CONFIG 0x000 ++#define GREG_SUBSYS_ID (0x0000ffff << 16) ++#define GREG_SUBSYS_VID (0x0000ffff << 0) ++ ++#define GREG_MSI_BAR_PMCSR 0x004 ++#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) ++#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) ++#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) ++#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) ++#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) ++#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) ++#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) ++#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) ++ ++#define GREG_BAR_WIDTH_17 (0x0000001e << 8) ++#define GREG_BAR_WIDTH_18 (0x0000001c << 8) ++#define GREG_BAR_WIDTH_19 (0x00000018 << 8) ++#define GREG_BAR_WIDTH_20 (0x00000010 << 8) ++ ++#define GREG_BAR_PREFETCH (0x00000001 << 3) ++#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! ++#define GREG_MSI_MM_CAP2 (0x00000001 << 0) ++#define GREG_MSI_MM_CAP4 (0x00000002 << 0) ++#define GREG_MSI_MM_CAP8 (0x00000003 << 0) ++#define GREG_MSI_MM_CAP16 (0x00000004 << 0) ++#define GREG_MSI_MM_CAP32 (0x00000005 << 0) ++ ++#define GREG_PMCSR_DATA_1 0x008 ++#define GREG_PMCSR_DATA_2 0x00c ++#define GREG_VI_CTRL 0x010 ++#define GREG_FGPI_CTRL 0x014 ++ ++#define GREG_RSTU_CTRL 0x018 ++#define GREG_BOOT_READY (0x00000001 << 13) ++#define GREG_RESET_REQ (0x00000001 << 12) ++#define GREG_IP_RST_RELEASE (0x00000001 << 11) ++#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) ++#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) ++#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) ++#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) ++#define GREG_CGU_RST_RELEASE (0x00000001 << 6) ++#define GREG_IP_RST_ASSERT (0x00000001 << 5) ++#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) ++#define GREG_RST_ASSERT (0x00000001 << 3) ++#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) ++#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) ++#define GREG_CGU_RST_ASSERT (0x00000001 << 0) ++ ++#define GREG_I2C_CTRL 0x01c ++#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) ++ ++#define GREG_OVFLW_CTRL 0x020 ++#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) ++ ++#define GREG_TAG_ACK_FLEN 0x024 ++#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) ++#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) ++#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) ++#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) ++ ++#define GREG_VIDEO_IN_CTRL 0x028 ++ ++#define GREG_SPARE_1 0x02c ++#define GREG_SPARE_2 0x030 ++#define GREG_SPARE_3 0x034 ++#define GREG_SPARE_4 0x038 ++#define GREG_SPARE_5 0x03c ++#define GREG_SPARE_6 0x040 ++#define GREG_SPARE_7 0x044 ++#define GREG_SPARE_8 0x048 ++#define GREG_SPARE_9 0x04c ++#define GREG_SPARE_10 0x050 ++#define GREG_SPARE_11 0x054 ++#define GREG_SPARE_12 0x058 ++#define GREG_SPARE_13 0x05c ++#define GREG_SPARE_14 0x060 ++#define GREG_SPARE_15 0x064 ++ ++#define GREG_FAIL_DISABLE 0x068 ++#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) ++ ++#define GREG_SW_RST 0xff0 ++#define GREG_SW_RESET (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_GREG_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_hybrid.c b/drivers/media/pci/saa716x/saa716x_hybrid.c +new file mode 100644 +index 0000000..b84d7ba +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_hybrid.c +@@ -0,0 +1,718 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_hybrid.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "zl10353.h" ++#include "mb86a16.h" ++#include "tda1004x.h" ++#include "tda827x.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Hybrid" ++ ++static int saa716x_hybrid_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_hybrid_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->module = THIS_MODULE; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core Initialization failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail2; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable decoders on 7162 */ ++ if (pdev->device == SAA7162) { ++ saa716x_gpio_set_output(saa716x, 24); ++ saa716x_gpio_set_output(saa716x, 25); ++ ++ saa716x_gpio_write(saa716x, 24, 0); ++ saa716x_gpio_write(saa716x, 25, 0); ++ ++ msleep(10); ++ ++ saa716x_gpio_write(saa716x, 24, 1); ++ saa716x_gpio_write(saa716x, 25, 1); ++ } ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F44); ++ /* enable FGPI3 and FGPI0 for TS input from Port 3 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x894); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail3; ++ } ++ ++ return 0; ++ ++fail3: ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_hybrid_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_hybrid_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++/* ++ * Twinhan/Azurewave VP-6090 ++ * DVB-S Frontend: 2x MB86A16 ++ * DVB-T Frontend: 2x TDA10046 + TDA8275 ++ */ ++#define SAA716x_MODEL_TWINHAN_VP6090 "Twinhan/Azurewave VP-6090" ++#define SAA716x_DEV_TWINHAN_VP6090 "2xDVB-S + 2xDVB-T + 2xAnalog" ++ ++static int tda1004x_vp6090_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_vp6090_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_4M, ++ .agc_config = TDA10046_AGC_DEFAULT, ++ .if_freq = TDA10046_FREQ_3617, ++ .request_firmware = tda1004x_vp6090_request_firmware, ++}; ++ ++static int vp6090_dvbs_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp6090_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp6090_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp6090_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[count]; ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ saa716x_gpio_set_output(saa716x, 11); ++ saa716x_gpio_set_output(saa716x, 10); ++ saa716x_gpio_write(saa716x, 11, 1); ++ saa716x_gpio_write(saa716x, 10, 1); ++ msleep(100); ++#if 0 ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = mb86a16_attach(&vp6090_mb86a16_config, &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp6090_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++#endif ++ adapter->fe = dvb_attach(tda10046_attach, &tda1004x_vp6090_config, ++ &i2c->i2c_adapter); ++ if (adapter->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_vp6090_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6090, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6090, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6090_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++/* ++ * NXP Reference design (Atlantis) ++ * 2x DVB-T Frontend: 2x TDA10046 ++ * Analog Decoder: 2x Internal ++ */ ++#define SAA716x_MODEL_NXP_ATLANTIS "Atlantis reference board" ++#define SAA716x_DEV_NXP_ATLANTIS "2x DVB-T + 2x Analog" ++ ++static int tda1004x_atlantis_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_atlantis_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_atlantis_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_atlantis_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_atlantis_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c; ++ u8 i2c_buf[3] = { 0x05, 0x23, 0x01 }; /* activate the silent I2C bus */ ++ struct i2c_msg msg = { ++ .addr = 0x42 >> 1, ++ .flags = 0, ++ .buf = i2c_buf, ++ .len = sizeof(i2c_buf) ++ }; ++ ++ if (count < saa716x->config->adapters) { ++ u32 reset_gpio; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ if (count == 0) { ++ reset_gpio = 14; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ } else { ++ reset_gpio = 15; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ } ++ ++ /* activate the silent I2C bus */ ++ i2c_transfer(&i2c->i2c_adapter, &msg, 1); ++ ++ saa716x_gpio_set_output(saa716x, reset_gpio); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ ++ adapter->fe = dvb_attach(tda10046_attach, ++ &tda1004x_atlantis_config, ++ &i2c->i2c_adapter); ++ if (adapter->fe == NULL) ++ goto exit; ++ ++ dprintk(SAA716x_ERROR, 1, ++ "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_atlantis_config.demod_address); ++ ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_atlantis_config.tuner_address, ++ &i2c->i2c_adapter, &tda827x_atlantis_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_atlantis_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_atlantis_config = { ++ .model_name = SAA716x_MODEL_NXP_ATLANTIS, ++ .dev_type = SAA716x_DEV_NXP_ATLANTIS, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_atlantis_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* Adapter 1 */ ++ .ts_port = 0, /* using FGPI 0 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++/* ++ * NXP Reference design (NEMO) ++ * DVB-T Frontend: 1x TDA10046 + TDA8275 ++ * Analog Decoder: External SAA7136 ++ */ ++#define SAA716x_MODEL_NXP_NEMO "NEMO reference board" ++#define SAA716x_DEV_NXP_NEMO "DVB-T + Analog" ++ ++static int tda1004x_nemo_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_nemo_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_nemo_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_nemo_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_nemo_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *demod_i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct saa716x_i2c *tuner_i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ ++ ++ if (count == 0) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ /* GPIO 26 controls a +15dB gain */ ++ saa716x_gpio_set_output(saa716x, 26); ++ saa716x_gpio_write(saa716x, 26, 0); ++ ++ saa716x_gpio_set_output(saa716x, 14); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ ++ adapter->fe = dvb_attach(tda10046_attach, ++ &tda1004x_nemo_config, ++ &demod_i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_nemo_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_nemo_config.tuner_address, ++ &tuner_i2c->i2c_adapter, &tda827x_nemo_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_nemo_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_nemo_config = { ++ .model_name = SAA716x_MODEL_NXP_NEMO, ++ .dev_type = SAA716x_DEV_NXP_NEMO, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_nemo_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++#define SAA716x_MODEL_AVERMEDIA_HC82 "Avermedia HC82 Express-54" ++#define SAA716x_DEV_AVERMEDIA_HC82 "DVB-T + Analog" ++ ++#if 0 ++static struct zl10353_config saa716x_averhc82_zl10353_config = { ++ .demod_address = 0x1f, ++ .adc_clock = 450560, ++ .if2 = 361667, ++ .no_tuner = 1, ++ .parallel_ts = 1, ++}; ++#endif ++ ++static int saa716x_averhc82_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++// adapter->fe = zl10353_attach(&saa716x_averhc82_zl10353_config, &i2c->i2c_adapter); ++ ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_averhc82_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_HC82, ++ .dev_type = SAA716x_DEV_AVERMEDIA_HC82, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averhc82_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++#define SAA716x_MODEL_AVERMEDIA_H788 "Avermedia H788" ++#define SAA716x_DEV_AVERMEDIA_H788 "DVB-T + Analaog" ++ ++static int saa716x_averh88_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_averh788_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_H788, ++ .dev_type = SAA716x_DEV_AVERMEDIA_H788, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averh88_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++static struct pci_device_id saa716x_hybrid_pci_table[] = { ++ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6090, SAA7162, &saa716x_vp6090_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_HC82, SAA7160, &saa716x_averhc82_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_H788, SAA7160, &saa716x_averh788_config), ++ MAKE_ENTRY(KWORLD, KWORLD_DVB_T_PE310, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7160, &saa716x_nemo_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_hybrid_pci_table); ++ ++static struct pci_driver saa716x_hybrid_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_hybrid_pci_table, ++ .probe = saa716x_hybrid_pci_probe, ++ .remove = saa716x_hybrid_pci_remove, ++}; ++ ++module_pci_driver(saa716x_hybrid_pci_driver); ++ ++MODULE_DESCRIPTION("SAA716x Hybrid driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/pci/saa716x/saa716x_hybrid.h b/drivers/media/pci/saa716x/saa716x_hybrid.h +new file mode 100644 +index 0000000..df34a59 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_hybrid.h +@@ -0,0 +1,13 @@ ++#ifndef __SAA716x_HYBRID_H ++#define __SAA716x_HYBRID_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define AVERMEDIA 0x1461 ++#define KWORLD 0x17DE ++ ++#define TWINHAN_VP_6090 0x0027 ++#define AVERMEDIA_HC82 0x2355 ++#define AVERMEDIA_H788 0x1455 ++#define KWORLD_DVB_T_PE310 0x7521 ++ ++#endif /* __SAA716x_HYBRID_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_i2c.c b/drivers/media/pci/saa716x/saa716x_i2c.c +new file mode 100644 +index 0000000..d65edf8 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_i2c.c +@@ -0,0 +1,739 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_i2c_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_cgu_reg.h" ++ ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#define SAA716x_I2C_TXFAIL (I2C_ERROR_IBE | \ ++ I2C_ACK_INTER_MTNA | \ ++ I2C_FAILURE_INTER_MAF) ++ ++#define SAA716x_I2C_TXBUSY (I2C_TRANSMIT | \ ++ I2C_TRANSMIT_PROG) ++ ++#define SAA716x_I2C_RXBUSY (I2C_RECEIVE | \ ++ I2C_RECEIVE_CLEAR) ++ ++static const char* state[] = { ++ "Idle", ++ "DoneStop", ++ "Busy", ++ "TOscl", ++ "TOarb", ++ "DoneWrite", ++ "DoneRead", ++ "DoneWriteTO", ++ "DoneReadTO", ++ "NoDevice", ++ "NoACK", ++ "BUSErr", ++ "ArbLost", ++ "SEQErr", ++ "STErr" ++}; ++ ++int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus) ++{ ++ u32 stat, mask; ++ u32 *I2C_DEV; ++ ++ BUG_ON(saa716x == NULL); ++ I2C_DEV = saa716x->I2C_DEV; ++ ++ stat = SAA716x_EPRD(I2C_DEV[bus], INT_STATUS); ++ mask = SAA716x_EPRD(I2C_DEV[bus], INT_ENABLE); ++ saa716x->i2c[bus].i2c_stat = stat; ++ dprintk(SAA716x_DEBUG, 0, "Bus(%d) I2C event: Status=<%s> --> Stat=<%02x> Mask=<%02x>", ++ bus, state[stat], stat, mask); ++ ++ if (!(stat & mask)) ++ return -1; ++ ++ SAA716x_EPWR(I2C_DEV[bus], INT_CLR_STATUS, stat); ++ ++ if (stat & I2C_INTERRUPT_STFNF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTFNF) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_INTERRUPT_RFDA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPTE_RFF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_INTERRUPT_STDR) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MASTER_INTERRUPT_MTDR) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_ERROR_IBE) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MODE_CHANGE_INTER_MSMC) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_ACK_INTER_MTNA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_FAILURE_INTER_MAF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++ ++static irqreturn_t saa716x_i2c_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_CLR_STATUS), ++ SAA716x_EPRD(I2C_B, INT_CLR_STATUS)); ++ ++ return IRQ_HANDLED; ++} ++ ++static void saa716x_term_xfer(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); /* Start: SCL/SDA High */ ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x00); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); ++ ++ return; ++} ++ ++static void saa716x_i2c_hwdeinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_hwinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ struct i2c_adapter *adapter = &i2c->i2c_adapter; ++ ++ int i, err = 0; ++ u32 reg; ++ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed, Exiting !", ++ I2C_DEV, adapter->name); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Flush queue */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xcc); ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ /* Reset I2C Core and generate a delay */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc1); ++ ++ for (i = 0; i < 100; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_CONTROL); ++ if (reg == 0xc0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET", ++ I2C_DEV, adapter->name); ++ break; ++ } ++ msleep(1); ++ ++ if (i == 99) ++ err = -EIO; ++ } ++ ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed", ++ I2C_DEV, adapter->name); ++ ++ saa716x_term_xfer(i2c, I2C_DEV); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* I2C Rate Setup */ ++ switch (i2c->i2c_rate) { ++ case SAA716x_I2C_RATE_400: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 400k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x1a); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x21); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x10); ++ break; ++ ++ case SAA716x_I2C_RATE_100: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 100k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x68); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x87); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x60); ++ break; ++ ++ default: ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter %s Unknown Rate (Rate=0x%02x)", ++ adapter->name, ++ i2c->i2c_rate); ++ ++ break; ++ } ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Enabled interrupts: ++ * Master Transaction Done, ++ * Master Transaction Data Request ++ * (0x81) ++ */ ++ msleep(5); ++ ++ SAA716x_EPWR(I2C_DEV, INT_SET_ENABLE, ++ I2C_SET_ENABLE_MTDR | I2C_SET_ENABLE_MTD); ++ ++ /* Check interrupt enable status */ ++ reg = SAA716x_EPRD(I2C_DEV, INT_ENABLE); ++ if (reg != 0x81) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%d) %s Interrupt enable failed, Exiting !", ++ i, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++ } ++ ++ /* Check status */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%02x) %s has bad state, Exiting !", ++ I2C_DEV, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++#if 0 ++ saa716x_add_irqvector(saa716x, ++ i2c_vec[i].vector, ++ i2c_vec[i].edge, ++ i2c_vec[i].handler, ++ SAA716x_I2C_ADAPTER(i)); ++#endif ++ reg = SAA716x_EPRD(CGU, CGU_SCR_3); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%02x) Autowake <%d> Active <%d>", ++ I2C_DEV, ++ (reg >> 1) & 0x01, ++ reg & 0x01); ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ return 0; ++ } ++ ++ /* Check FIFO status before TX */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ i2c->stat_tx_prior = reg; ++ if (reg & SAA716x_I2C_TXBUSY) { ++ for (i = 0; i < 100; i++) { ++ /* TODO! check for hotplug devices */ ++ msleep(10); ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ ++ if (reg & SAA716x_I2C_TXBUSY) { ++ dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); ++ ++ err = saa716x_i2c_hwinit(i2c, I2C_DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto exit; ++ } ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ ++ /* Check for data write */ ++ for (i = 0; i < 1000; i++) { ++ /* TODO! check for hotplug devices */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (reg & I2C_TRANSMIT_CLEAR) { ++ break; ++ } ++ } ++ i2c->stat_tx_done = reg; ++ ++ if (!(reg & I2C_TRANSMIT_CLEAR)) { ++ dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); ++ err = -EIO; ++ goto exit; ++ } ++ ++ return err; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); ++ return err; ++} ++ ++static int saa716x_i2c_recv(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 *data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ /* Check FIFO status before RX */ ++ for (i = 0; i < 1000; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & SAA716x_I2C_RXBUSY)) { ++ break; ++ } ++ } ++ if (reg & SAA716x_I2C_RXBUSY) { ++ dprintk(SAA716x_INFO, 1, "FIFO empty"); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Read from FIFO */ ++ *data = SAA716x_EPRD(I2C_DEV, RX_FIFO); ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error Reading data, err=%d", err); ++ return err; ++} ++ ++static void saa716x_i2c_irq_start(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return; ++ ++ i2c->i2c_op = 1; ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_irq_wait(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ unsigned long timeout; ++ int err = 0; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return 0; ++ ++ timeout = HZ/100 + 1; /* 10ms */ ++ timeout = wait_event_interruptible_timeout(i2c->i2c_wq, i2c->i2c_op == 0, timeout); ++ if (timeout == -ERESTARTSYS || i2c->i2c_op) { ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ err = -ERESTARTSYS; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for end of xfer!"); ++ err = -EIO; ++ } ++ } ++ return err; ++} ++ ++static int saa716x_i2c_write_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1); ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now write the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = buf[i]; ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n", i, data); ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error writing data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1) | 1; ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now read the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = 0x00; /* dummy write for reading */ ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ for (i = 0; i < bytes; i++) { ++ err = saa716x_i2c_recv(i2c, I2C_DEV, &data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data receive failed"); ++ goto exit; ++ } ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n\n", i, data); ++ buf[i] = data; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) ++{ ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); ++ int i, j, err = 0; ++ int t; ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); ++ mutex_lock(&i2c->i2c_lock); ++ ++ for (t = 0; t < 3; t++) { ++ for (i = 0; i < num; i++) { ++ if (msgs[i].flags & I2C_M_RD) ++ err = saa716x_i2c_read_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ else ++ err = saa716x_i2c_write_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ if (err < 0) { ++ err = -EIO; ++ goto retry; ++ } ++ } ++ break; ++retry: ++ dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); ++ for (i = 0; i < num; i++) { ++ dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", ++ i, msgs[i].addr, msgs[i].len, msgs[i].flags); ++ if (!(msgs[i].flags & I2C_M_RD)) { ++ for (j = 0; j < msgs[i].len; j++) { ++ dprintk(SAA716x_INFO, 1, " 0x%02x", ++ j, msgs[i].buf[j]); ++ } ++ } ++ } ++ err = saa716x_i2c_hwinit(i2c, DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto bail_out; ++ } ++ } ++ ++ mutex_unlock(&i2c->i2c_lock); ++ if (t < 3) ++ return num; ++ else ++ return -EIO; ++ ++bail_out: ++ dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); ++ mutex_unlock(&i2c->i2c_lock); ++ return err; ++} ++ ++static u32 saa716x_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm saa716x_algo = { ++ .master_xfer = saa716x_i2c_xfer, ++ .functionality = saa716x_i2c_func, ++}; ++ ++struct saa716x_i2cvec { ++ u32 vector; ++ enum saa716x_edge edge; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++static const struct saa716x_i2cvec i2c_vec[] = { ++ { ++ .vector = I2CINT_0, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ }, { ++ .vector = I2CINT_1, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ } ++}; ++ ++int saa716x_i2c_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ ++ int i, err = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ mutex_init(&i2c->i2c_lock); ++ ++ init_waitqueue_head(&i2c->i2c_wq); ++ i2c->i2c_op = 0; ++ ++ i2c->i2c_dev = i; ++ i2c->i2c_rate = saa716x->config->i2c_rate; ++ i2c->i2c_mode = saa716x->config->i2c_mode; ++ adapter = &i2c->i2c_adapter; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_IRQ_BUFFERED) ++ i2c->block_size = 8; ++ else ++ i2c->block_size = 1; ++ ++ if (adapter != NULL) { ++ ++ i2c_set_adapdata(adapter, i2c); ++ ++ strcpy(adapter->name, SAA716x_I2C_ADAPTER(i)); ++ ++ adapter->owner = THIS_MODULE; ++ adapter->algo = &saa716x_algo; ++ adapter->algo_data = NULL; ++ adapter->timeout = 500; /* FIXME ! */ ++ adapter->retries = 3; /* FIXME ! */ ++ adapter->dev.parent = &pdev->dev; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing adapter (%d) %s", ++ i, ++ adapter->name); ++ ++ err = i2c_add_adapter(adapter); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s init failed", i, adapter->name); ++ goto exit; ++ } ++ ++ i2c->saa716x = saa716x; ++ saa716x_i2c_hwinit(i2c, SAA716x_I2C_BUS(i)); ++ } ++ i2c++; ++ } ++ ++ if (saa716x->config->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully initialized", ++ saa716x->pdev->device); ++ ++ return 0; ++exit: ++ /* delete already added i2c adapters */ ++ while (i > 0) { ++ i2c--; ++ adapter = &i2c->i2c_adapter; ++ i2c_del_adapter(adapter); ++ i--; ++ } ++ return err; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_init); ++ ++int saa716x_i2c_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ int i; ++ ++ dprintk(SAA716x_DEBUG, 1, "Removing SAA%02x I2C Core", saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ adapter = &i2c->i2c_adapter; ++#if 0 ++ saa716x_remove_irqvector(saa716x, i2c_vec[i].vector); ++#endif ++ saa716x_i2c_hwdeinit(i2c, SAA716x_I2C_BUS(i)); ++ dprintk(SAA716x_DEBUG, 1, "Removing adapter (%d) %s", i, adapter->name); ++ ++ i2c_del_adapter(adapter); ++ i2c++; ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_exit); +diff --git a/drivers/media/pci/saa716x/saa716x_i2c.h b/drivers/media/pci/saa716x/saa716x_i2c.h +new file mode 100644 +index 0000000..da767ac +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_i2c.h +@@ -0,0 +1,52 @@ ++#ifndef __SAA716x_I2C_H ++#define __SAA716x_I2C_H ++ ++#define SAA716x_I2C_ADAPTERS 2 ++ ++#define SAA716x_I2C_ADAPTER(__dev) (( \ ++ (__dev == 1) ? \ ++ "SAA716x I2C Core 1" : \ ++ "SAA716x I2C Core 0")) ++ ++#define SAA716x_I2C_BUS(__x) ((__x == 1) ? 0x0000c000 : 0x0000b000) ++ ++#define SAA716x_I2C_BUS_A 0x01 ++#define SAA716x_I2C_BUS_B 0x00 ++ ++struct saa716x_dev; ++ ++enum saa716x_i2c_rate { ++ SAA716x_I2C_RATE_400 = 1, ++ SAA716x_I2C_RATE_100, ++}; ++ ++enum saa716x_i2c_mode { ++ SAA716x_I2C_MODE_POLLING = 0, ++ SAA716x_I2C_MODE_IRQ, ++ SAA716x_I2C_MODE_IRQ_BUFFERED ++}; ++ ++struct saa716x_i2c { ++ struct i2c_adapter i2c_adapter; ++ struct mutex i2c_lock; ++ struct saa716x_dev *saa716x; ++ u8 i2c_dev; ++ ++ enum saa716x_i2c_rate i2c_rate; /* run time */ ++ enum saa716x_i2c_mode i2c_mode; ++ u32 block_size; /* block size for buffered ++ mode, 1 otherwise */ ++ u32 i2c_stat; ++ ++ u32 stat_tx_prior; ++ u32 stat_tx_done; ++ wait_queue_head_t i2c_wq; ++ int i2c_op; ++}; ++ ++extern int saa716x_i2c_init(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_exit(struct saa716x_dev *saa716x); ++extern void saa716x_i2cint_disable(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus); ++ ++#endif /* __SAA716x_I2C_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_i2c_reg.h b/drivers/media/pci/saa716x/saa716x_i2c_reg.h +new file mode 100644 +index 0000000..8fa992c +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_i2c_reg.h +@@ -0,0 +1,145 @@ ++#ifndef __SAA716x_I2C_REG_H ++#define __SAA716x_I2C_REG_H ++ ++/* -------------- I2C Registers -------------- */ ++ ++#define RX_FIFO 0x000 ++#define I2C_RX_BYTE (0x000000ff << 0) ++ ++#define TX_FIFO 0x000 ++#define I2C_STOP_BIT (0x00000001 << 9) ++#define I2C_START_BIT (0x00000001 << 8) ++#define I2C_TX_BYTE (0x000000ff << 0) ++ ++#define I2C_STATUS 0x008 ++#define I2C_TRANSMIT (0x00000001 << 11) ++#define I2C_RECEIVE (0x00000001 << 10) ++#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) ++#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) ++#define I2C_TRANSMIT_PROG (0x00000001 << 7) ++#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) ++#define I2C_RECEIVE_PROG (0x00000001 << 5) ++#define I2C_RECEIVE_CLEAR (0x00000001 << 4) ++#define I2C_SDA_LINE (0x00000001 << 3) ++#define I2C_SCL_LINE (0x00000001 << 2) ++#define I2C_START_STOP_FLAG (0x00000001 << 1) ++#define I2C_MODE_STATUS (0x00000001 << 0) ++ ++#define I2C_CONTROL 0x00c ++#define I2C_SCL_CONTROL (0x00000001 << 7) ++#define I2C_SDA_CONTROL (0x00000001 << 6) ++#define I2C_RECEIVE_PROTECT (0x00000001 << 5) ++#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) ++#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) ++#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) ++#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) ++#define I2C_RESET (0x00000001 << 0) ++ ++#define I2C_CLOCK_DIVISOR_HIGH 0x010 ++#define I2C_CLOCK_HIGH (0x0000ffff << 0) ++ ++#define I2C_CLOCK_DIVISOR_LOW 0x014 ++#define I2C_CLOCK_LOW (0x0000ffff << 0) ++ ++#define I2C_RX_LEVEL 0x01c ++#define I2C_RECEIVE_RANGE (0x0000007f << 0) ++ ++#define I2C_TX_LEVEL 0x020 ++#define I2C_TRANSMIT_RANGE (0x0000007f << 0) ++ ++#define I2C_SDA_HOLD 0x028 ++#define I2C_HOLD_TIME (0x0000007f << 0) ++ ++#define MODULE_CONF 0xfd4 ++#define INT_CLR_ENABLE 0xfd8 ++#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) ++#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) ++#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) ++#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) ++#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) ++#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_SET_ENABLE 0xfdc ++#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_SET_ENABLE_RFF (0x00000001 << 9) ++#define I2C_SET_ENABLE_STDR (0x00000001 << 8) ++#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_SET_ENABLE_IBE (0x00000001 << 6) ++#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_SET_ENABLE_STSD (0x00000001 << 3) ++#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_SET_ENABLE_MAF (0x00000001 << 1) ++#define I2C_SET_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_STATUS 0xfe0 ++#define I2C_INTERRUPT_STFNF (0x00000001 << 12) ++#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) ++#define I2C_INTERRUPT_RFDA (0x00000001 << 10) ++#define I2C_INTERRUPTE_RFF (0x00000001 << 9) ++#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) ++#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) ++#define I2C_ERROR_IBE (0x00000001 << 6) ++#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) ++#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) ++#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) ++#define I2C_ACK_INTER_MTNA (0x00000001 << 2) ++#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) ++#define I2C_INTERRUPT_MTD (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define I2C_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_ENABLE_RFF (0x00000001 << 9) ++#define I2C_ENABLE_STDR (0x00000001 << 8) ++#define I2C_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_ENABLE_IBE (0x00000001 << 6) ++#define I2C_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_ENABLE_STSD (0x00000001 << 3) ++#define I2C_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_ENABLE_MAF (0x00000001 << 1) ++#define I2C_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) ++#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) ++#define I2C_CLR_STATUS_RFF (0x00000001 << 9) ++#define I2C_CLR_STATUS_STDR (0x00000001 << 8) ++#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) ++#define I2C_CLR_STATUS_IBE (0x00000001 << 6) ++#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) ++#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) ++#define I2C_CLR_STATUS_STSD (0x00000001 << 3) ++#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) ++#define I2C_CLR_STATUS_MAF (0x00000001 << 1) ++#define I2C_CLR_STATIS_MTD (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define I2C_SET_STATUS_STFNF (0x00000001 << 12) ++#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_SET_STATUS_RFDA (0x00000001 << 10) ++#define I2C_SET_STATUS_RFF (0x00000001 << 9) ++#define I2C_SET_STATUS_STDR (0x00000001 << 8) ++#define I2C_SET_STATUS_MTDR (0x00000001 << 7) ++#define I2C_SET_STATUS_IBE (0x00000001 << 6) ++#define I2C_SET_STATUS_MSMC (0x00000001 << 5) ++#define I2C_SET_STATUS_SRSD (0x00000001 << 4) ++#define I2C_SET_STATUS_STSD (0x00000001 << 3) ++#define I2C_SET_STATUS_MTNA (0x00000001 << 2) ++#define I2C_SET_STATUS_MAF (0x00000001 << 1) ++#define I2C_SET_STATIS_MTD (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_I2C_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_mod.h b/drivers/media/pci/saa716x/saa716x_mod.h +new file mode 100644 +index 0000000..a059ca4b +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_mod.h +@@ -0,0 +1,50 @@ ++#ifndef __SAA716x_MOD_H ++#define __SAA716x_MOD_H ++ ++/* BAR = 17 bits */ ++/* ++ VI0 0x00000000 ++ VI1 0x00001000 ++ FGPI0 0x00002000 ++ FGPI1 0x00003000 ++ FGPI2 0x00004000 ++ FGPI3 0x00005000 ++ AI0 0x00006000 ++ AI1 0x00007000 ++ BAM 0x00008000 ++ MMU 0x00009000 ++ MSI 0x0000a000 ++ I2C_B 0x0000b000 ++ I2C_A 0x0000c000 ++ SPI 0x0000d000 ++ GPIO 0x0000e000 ++ PHI_0 0x0000f000 ++ CGU 0x00013000 ++ DCS 0x00014000 ++ GREG 0x00012000 ++ ++ PHI_1 0x00020000 ++*/ ++ ++#define VI0 0x00000000 ++#define VI1 0x00001000 ++#define FGPI0 0x00002000 ++#define FGPI1 0x00003000 ++#define FGPI2 0x00004000 ++#define FGPI3 0x00005000 ++#define AI0 0x00006000 ++#define AI1 0x00007000 ++#define BAM 0x00008000 ++#define MMU 0x00009000 ++#define MSI 0x0000a000 ++#define I2C_B 0x0000b000 ++#define I2C_A 0x0000c000 ++#define SPI 0x0000d000 ++#define GPIO 0x0000e000 ++#define PHI_0 0x0000f000 ++#define GREG 0x00012000 ++#define CGU 0x00013000 ++#define DCS 0x00014000 ++#define PHI_1 0x00020000 ++ ++#endif /* __SAA716x_MOD_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_msi.c b/drivers/media/pci/saa716x/saa716x_msi.c +new file mode 100644 +index 0000000..b0f05a2 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_msi.c +@@ -0,0 +1,479 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_msi_reg.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++ ++#include "saa716x_priv.h" ++ ++#define SAA716x_MSI_VECTORS 50 ++ ++static const char *vector_name[] = { ++ "TAGACK_VI0_0", ++ "TAGACK_VI0_1", ++ "TAGACK_VI0_2", ++ "TAGACK_VI1_0", ++ "TAGACK_VI1_1", ++ "TAGACK_VI1_2", ++ "TAGACK_FGPI_0", ++ "TAGACK_FGPI_1", ++ "TAGACK_FGPI_2", ++ "TAGACK_FGPI_3", ++ "TAGACK_AI_0", ++ "TAGACK_AI_1", ++ "OVRFLW_VI0_0", ++ "OVRFLW_VI0_1", ++ "OVRFLW_VI0_2", ++ "OVRFLW_VI1_0", ++ "OVRFLW_VI1_1", ++ "OVRFLW_VI1_2", ++ "OVRFLW_FGPI_O", ++ "OVRFLW_FGPI_1", ++ "OVRFLW_FGPI_2", ++ "OVRFLW_FGPI_3", ++ "OVRFLW_AI_0", ++ "OVRFLW_AI_1", ++ "AVINT_VI0", ++ "AVINT_VI1", ++ "AVINT_FGPI_0", ++ "AVINT_FGPI_1", ++ "AVINT_FGPI_2", ++ "AVINT_FGPI_3", ++ "AVINT_AI_0", ++ "AVINT_AI_1", ++ "UNMAPD_TC_INT", ++ "EXTINT_0", ++ "EXTINT_1", ++ "EXTINT_2", ++ "EXTINT_3", ++ "EXTINT_4", ++ "EXTINT_5", ++ "EXTINT_6", ++ "EXTINT_7", ++ "EXTINT_8", ++ "EXTINT_9", ++ "EXTINT_10", ++ "EXTINT_11", ++ "EXTINT_12", ++ "EXTINT_13", ++ "EXTINT_14", ++ "EXTINT_15", ++ "I2CINT_0", ++ "I2CINT_1" ++}; ++ ++static u32 MSI_CONFIG_REG[51] = { ++ MSI_CONFIG0, ++ MSI_CONFIG1, ++ MSI_CONFIG2, ++ MSI_CONFIG3, ++ MSI_CONFIG4, ++ MSI_CONFIG5, ++ MSI_CONFIG6, ++ MSI_CONFIG7, ++ MSI_CONFIG8, ++ MSI_CONFIG9, ++ MSI_CONFIG10, ++ MSI_CONFIG11, ++ MSI_CONFIG12, ++ MSI_CONFIG13, ++ MSI_CONFIG14, ++ MSI_CONFIG15, ++ MSI_CONFIG16, ++ MSI_CONFIG17, ++ MSI_CONFIG18, ++ MSI_CONFIG19, ++ MSI_CONFIG20, ++ MSI_CONFIG21, ++ MSI_CONFIG22, ++ MSI_CONFIG23, ++ MSI_CONFIG24, ++ MSI_CONFIG25, ++ MSI_CONFIG26, ++ MSI_CONFIG27, ++ MSI_CONFIG28, ++ MSI_CONFIG29, ++ MSI_CONFIG30, ++ MSI_CONFIG31, ++ MSI_CONFIG32, ++ MSI_CONFIG33, ++ MSI_CONFIG34, ++ MSI_CONFIG35, ++ MSI_CONFIG36, ++ MSI_CONFIG37, ++ MSI_CONFIG38, ++ MSI_CONFIG39, ++ MSI_CONFIG40, ++ MSI_CONFIG41, ++ MSI_CONFIG42, ++ MSI_CONFIG43, ++ MSI_CONFIG44, ++ MSI_CONFIG45, ++ MSI_CONFIG46, ++ MSI_CONFIG47, ++ MSI_CONFIG48, ++ MSI_CONFIG49, ++ MSI_CONFIG50 ++}; ++ ++int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h) ++{ ++ dprintk(SAA716x_DEBUG, 0, "%s: MSI event ", __func__); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[0]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[1]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[2]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[3]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[4]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[5]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[6]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[7]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[8]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[9]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[10]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[11]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[12]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[13]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[14]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[15]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[16]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[17]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[18]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[19]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[20]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[21]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[22]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[23]); ++ ++ if (stat_l & MSI_INT_AVINT_VI0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[24]); ++ ++ if (stat_l & MSI_INT_AVINT_VI1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[25]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[26]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[27]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[28]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[29]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[30]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[31]); ++ ++ if (stat_h & MSI_INT_UNMAPD_TC_INT) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[32]); ++ ++ if (stat_h & MSI_INT_EXTINT_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[33]); ++ ++ if (stat_h & MSI_INT_EXTINT_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[34]); ++ ++ if (stat_h & MSI_INT_EXTINT_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[35]); ++ ++ if (stat_h & MSI_INT_EXTINT_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[36]); ++ ++ if (stat_h & MSI_INT_EXTINT_4) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[37]); ++ ++ if (stat_h & MSI_INT_EXTINT_5) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[38]); ++ ++ if (stat_h & MSI_INT_EXTINT_6) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[39]); ++ ++ if (stat_h & MSI_INT_EXTINT_7) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[40]); ++ ++ if (stat_h & MSI_INT_EXTINT_8) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[41]); ++ ++ if (stat_h & MSI_INT_EXTINT_9) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[42]); ++ ++ if (stat_h & MSI_INT_EXTINT_10) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[43]); ++ ++ if (stat_h & MSI_INT_EXTINT_11) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[44]); ++ ++ if (stat_h & MSI_INT_EXTINT_12) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[45]); ++ ++ if (stat_h & MSI_INT_EXTINT_13) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[46]); ++ ++ if (stat_h & MSI_INT_EXTINT_14) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[47]); ++ ++ if (stat_h & MSI_INT_EXTINT_15) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[48]); ++ ++ if (stat_h & MSI_INT_I2CINT_0) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[49]); ++ saa716x_i2c_irqevent(saa716x, 0); ++ } ++ ++ if (stat_h & MSI_INT_I2CINT_1) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[50]); ++ saa716x_i2c_irqevent(saa716x, 1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_event); ++ ++int saa716x_msi_init(struct saa716x_dev *saa716x) ++{ ++ u32 ena_l, ena_h, sta_l, sta_h, mid; ++ int i; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing MSI .."); ++ saa716x->handlers = 0; ++ ++ /* get module id & version */ ++ mid = SAA716x_EPRD(MSI, MSI_MODULE_ID); ++ if (mid != 0x30100) ++ dprintk(SAA716x_ERROR, 1, "MSI Id<%04x> is not supported", mid); ++ ++ /* let HW take care of MSI race */ ++ SAA716x_EPWR(MSI, MSI_DELAY_TIMER, 0x0); ++ ++ /* INTA Polarity: Active High */ ++ SAA716x_EPWR(MSI, MSI_INTA_POLARITY, MSI_INTA_POLARITY_HIGH); ++ ++ /* ++ * IRQ Edge Rising: 25:24 = 0x01 ++ * Traffic Class: 18:16 = 0x00 ++ * MSI ID: 4:0 = 0x00 ++ */ ++ for (i = 0; i < SAA716x_MSI_VECTORS; i++) ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[i], MSI_INT_POL_EDGE_RISE); ++ ++ /* get Status */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ /* disable and clear enabled and asserted IRQ's */ ++ if (sta_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, sta_l); ++ ++ if (sta_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, sta_h); ++ ++ if (ena_l) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, ena_l); ++ ++ if (ena_h) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, ena_h); ++ ++ msleep(5); ++ ++ /* Check IRQ's really disabled */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ if ((ena_l == 0) && (ena_h == 0) && (sta_l == 0) && (sta_h == 0)) { ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x> sta_l <%02x> sta_h <%02x>", ++ ena_l, ena_h, sta_l, sta_h); ++ ++ return 0; ++ } else { ++ dprintk(SAA716x_DEBUG, 1, "I/O error"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_init); ++ ++void saa716x_msiint_disable(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "Disabling Interrupts ..."); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_L, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_H, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0xffffffff); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0x0000ffff); ++} ++EXPORT_SYMBOL_GPL(saa716x_msiint_disable); ++ ++ ++/* Map the given vector Id to the hardware bitmask. */ ++static void saa716x_map_vector(struct saa716x_dev *saa716x, int vector, u32 *mask_l, u32 *mask_h) ++{ ++ u32 tmp = 1; ++ ++ if (vector < 32) { ++ /* Bits 0 - 31 */ ++ tmp <<= vector; ++ *mask_l = tmp; ++ *mask_h = 0; ++ } else { ++ /* Bits 32 - 48 */ ++ tmp <<= vector - 32; ++ *mask_l = 0; ++ *mask_h = tmp; ++ } ++} ++ ++int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc) ++{ ++ struct saa716x_msix_entry *msix_handler = NULL; ++ ++ u32 config, mask_l, mask_h, ena_l, ena_h; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(vector > SAA716x_MSI_VECTORS); ++ dprintk(SAA716x_DEBUG, 1, "Adding Vector %d <%s>", vector, vector_name[vector]); ++ ++ if ((vector > 32) && (vector < 49)) { ++ config = SAA716x_EPRD(MSI, MSI_CONFIG_REG[vector]); ++ config &= 0xfcffffff; /* clear polarity */ ++ ++ switch (edge) { ++ default: ++ case SAA716x_EDGE_RISING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x01000000); ++ break; ++ ++ case SAA716x_EDGE_FALLING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x02000000); ++ break; ++ ++ case SAA716x_EDGE_ANY: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x03000000); ++ break; ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* add callback */ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ strcpy(msix_handler->desc, desc); ++ msix_handler->vector = vector; ++ msix_handler->handler = handler; ++ saa716x->handlers++; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, mask_h); ++ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x>", ena_l, ena_h); ++ ++ return 0; ++} ++ ++int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector) ++{ ++ struct saa716x_msix_entry *msix_handler; ++ int i; ++ u32 mask_l, mask_h; ++ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ BUG_ON(msix_handler == NULL); ++ dprintk(SAA716x_DEBUG, 1, "Removing Vector %d <%s>", vector, vector_name[vector]); ++ ++ /* loop through the registered handlers */ ++ for (i = 0; i < saa716x->handlers; i++) { ++ ++ /* we found our vector */ ++ if (msix_handler->vector == vector) { ++ BUG_ON(msix_handler->handler == NULL); /* no handler yet */ ++ dprintk(SAA716x_DEBUG, 1, "Vector %d <%s> removed", ++ msix_handler->vector, ++ msix_handler->desc); ++ ++ /* check whether it is already released */ ++ if (msix_handler->handler) { ++ msix_handler->vector = 0; ++ msix_handler->handler = NULL; ++ saa716x->handlers--; ++ } ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* disable vector */ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, mask_h); ++ ++ return 0; ++} +diff --git a/drivers/media/pci/saa716x/saa716x_msi.h b/drivers/media/pci/saa716x/saa716x_msi.h +new file mode 100644 +index 0000000..8eb72d76 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_msi.h +@@ -0,0 +1,87 @@ ++#ifndef __SAA716x_MSI_H ++#define __SAA716x_MSI_H ++ ++#define TAGACK_VI0_0 0x000 ++#define TAGACK_VI0_1 0x001 ++#define TAGACK_VI0_2 0x002 ++#define TAGACK_VI1_0 0x003 ++#define TAGACK_VI1_1 0x004 ++#define TAGACK_VI1_2 0x005 ++#define TAGACK_FGPI_0 0x006 ++#define TAGACK_FGPI_1 0x007 ++#define TAGACK_FGPI_2 0x008 ++#define TAGACK_FGPI_3 0x009 ++#define TAGACK_AI_0 0x00a ++#define TAGACK_AI_1 0x00b ++#define OVRFLW_VI0_0 0x00c ++#define OVRFLW_VI0_1 0x00d ++#define OVRFLW_VI0_2 0x00e ++#define OVRFLW_VI1_0 0x00f ++#define OVRFLW_VI1_1 0x010 ++#define OVRFLW_VI1_2 0x011 ++#define OVRFLW_FGPI_O 0x012 ++#define OVRFLW_FGPI_1 0x013 ++#define OVRFLW_FGPI_2 0x014 ++#define OVRFLW_FGPI_3 0x015 ++#define OVRFLW_AI_0 0x016 ++#define OVRFLW_AI_1 0x017 ++#define AVINT_VI0 0x018 ++#define AVINT_VI1 0x019 ++#define AVINT_FGPI_0 0x01a ++#define AVINT_FGPI_1 0x01b ++#define AVINT_FGPI_2 0x01c ++#define AVINT_FGPI_3 0x01d ++#define AVINT_AI_0 0x01e ++#define AVINT_AI_1 0x01f ++#define UNMAPD_TC_INT 0x020 ++#define EXTINT_0 0x021 ++#define EXTINT_1 0x022 ++#define EXTINT_2 0x023 ++#define EXTINT_3 0x024 ++#define EXTINT_4 0x025 ++#define EXTINT_5 0x026 ++#define EXTINT_6 0x027 ++#define EXTINT_7 0x028 ++#define EXTINT_8 0x029 ++#define EXTINT_9 0x02a ++#define EXTINT_10 0x02b ++#define EXTINT_11 0x02c ++#define EXTINT_12 0x02d ++#define EXTINT_13 0x02e ++#define EXTINT_14 0x02f ++#define EXTINT_15 0x030 ++#define I2CINT_0 0x031 ++#define I2CINT_1 0x032 ++ ++#define SAA716x_TC0 0x000 ++#define SAA716x_TC1 0x001 ++#define SAA716x_TC2 0x002 ++#define SAA716x_TC3 0x003 ++#define SAA716x_TC4 0x004 ++#define SAA716x_TC5 0x005 ++#define SAA716x_TC6 0x006 ++#define SAA716x_TC7 0x007 ++ ++ ++enum saa716x_edge { ++ SAA716x_EDGE_RISING = 1, ++ SAA716x_EDGE_FALLING = 2, ++ SAA716x_EDGE_ANY = 3 ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h); ++ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++extern int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc); ++ ++extern int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector); ++ ++#endif /* __SAA716x_MSI_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_msi_reg.h b/drivers/media/pci/saa716x/saa716x_msi_reg.h +new file mode 100644 +index 0000000..d9a12c7 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_msi_reg.h +@@ -0,0 +1,143 @@ ++#ifndef __SAA716x_MSI_REG_H ++#define __SAA716x_MSI_REG_H ++ ++/* -------------- MSI Registers -------------- */ ++ ++#define MSI_DELAY_TIMER 0x000 ++#define MSI_DELAY_1CLK (0x00000001 << 0) ++#define MSI_DELAY_2CLK (0x00000002 << 0) ++ ++#define MSI_INTA_POLARITY 0x004 ++#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) ++ ++#define MSI_CONFIG0 0x008 ++#define MSI_CONFIG1 0x00c ++#define MSI_CONFIG2 0x010 ++#define MSI_CONFIG3 0x014 ++#define MSI_CONFIG4 0x018 ++#define MSI_CONFIG5 0x01c ++#define MSI_CONFIG6 0x020 ++#define MSI_CONFIG7 0x024 ++#define MSI_CONFIG8 0x028 ++#define MSI_CONFIG9 0x02c ++#define MSI_CONFIG10 0x030 ++#define MSI_CONFIG11 0x034 ++#define MSI_CONFIG12 0x038 ++#define MSI_CONFIG13 0x03c ++#define MSI_CONFIG14 0x040 ++#define MSI_CONFIG15 0x044 ++#define MSI_CONFIG16 0x048 ++#define MSI_CONFIG17 0x04c ++#define MSI_CONFIG18 0x050 ++#define MSI_CONFIG19 0x054 ++#define MSI_CONFIG20 0x058 ++#define MSI_CONFIG21 0x05c ++#define MSI_CONFIG22 0x060 ++#define MSI_CONFIG23 0x064 ++#define MSI_CONFIG24 0x068 ++#define MSI_CONFIG25 0x06c ++#define MSI_CONFIG26 0x070 ++#define MSI_CONFIG27 0x074 ++#define MSI_CONFIG28 0x078 ++#define MSI_CONFIG29 0x07c ++#define MSI_CONFIG30 0x080 ++#define MSI_CONFIG31 0x084 ++#define MSI_CONFIG32 0x088 ++#define MSI_CONFIG33 0x08c ++#define MSI_CONFIG34 0x090 ++#define MSI_CONFIG35 0x094 ++#define MSI_CONFIG36 0x098 ++#define MSI_CONFIG37 0x09c ++#define MSI_CONFIG38 0x0a0 ++#define MSI_CONFIG39 0x0a4 ++#define MSI_CONFIG40 0x0a8 ++#define MSI_CONFIG41 0x0ac ++#define MSI_CONFIG42 0x0b0 ++#define MSI_CONFIG43 0x0b4 ++#define MSI_CONFIG44 0x0b8 ++#define MSI_CONFIG45 0x0bc ++#define MSI_CONFIG46 0x0c0 ++#define MSI_CONFIG47 0x0c4 ++#define MSI_CONFIG48 0x0c8 ++#define MSI_CONFIG49 0x0cc ++#define MSI_CONFIG50 0x0d0 ++ ++#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) ++#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) ++#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) ++#define MSI_TC (0x00000007 << 16) ++#define MSI_ID (0x0000000f << 0) ++ ++#define MSI_INT_STATUS_L 0xfc0 ++#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) ++#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) ++#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) ++#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) ++#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) ++#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) ++#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) ++#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) ++#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) ++#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) ++#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) ++#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) ++#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) ++#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) ++#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) ++#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) ++#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) ++#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) ++#define MSI_INT_OVRFLW_FGPI_0 (0x00000001 << 18) ++#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) ++#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) ++#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) ++#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) ++#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) ++#define MSI_INT_AVINT_VI0 (0x00000001 << 24) ++#define MSI_INT_AVINT_VI1 (0x00000001 << 25) ++#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) ++#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) ++#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) ++#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) ++#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) ++#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) ++ ++#define MSI_INT_STATUS_H 0xfc4 ++#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) ++#define MSI_INT_EXTINT_0 (0x00000001 << 1) ++#define MSI_INT_EXTINT_1 (0x00000001 << 2) ++#define MSI_INT_EXTINT_2 (0x00000001 << 3) ++#define MSI_INT_EXTINT_3 (0x00000001 << 4) ++#define MSI_INT_EXTINT_4 (0x00000001 << 5) ++#define MSI_INT_EXTINT_5 (0x00000001 << 6) ++#define MSI_INT_EXTINT_6 (0x00000001 << 7) ++#define MSI_INT_EXTINT_7 (0x00000001 << 8) ++#define MSI_INT_EXTINT_8 (0x00000001 << 9) ++#define MSI_INT_EXTINT_9 (0x00000001 << 10) ++#define MSI_INT_EXTINT_10 (0x00000001 << 11) ++#define MSI_INT_EXTINT_11 (0x00000001 << 12) ++#define MSI_INT_EXTINT_12 (0x00000001 << 13) ++#define MSI_INT_EXTINT_13 (0x00000001 << 14) ++#define MSI_INT_EXTINT_14 (0x00000001 << 15) ++#define MSI_INT_EXTINT_15 (0x00000001 << 16) ++#define MSI_INT_I2CINT_0 (0x00000001 << 17) ++#define MSI_INT_I2CINT_1 (0x00000001 << 18) ++ ++#define MSI_INT_STATUS_CLR_L 0xfc8 ++#define MSI_INT_STATUS_CLR_H 0xfcc ++#define MSI_INT_STATUS_SET_L 0xfd0 ++#define MSI_INT_STATUS_SET_H 0xfd4 ++#define MSI_INT_ENA_L 0xfd8 ++#define MSI_INT_ENA_H 0xfdc ++#define MSI_INT_ENA_CLR_L 0xfe0 ++#define MSI_INT_ENA_CLR_H 0xfe4 ++#define MSI_INT_ENA_SET_L 0xfe8 ++#define MSI_INT_ENA_SET_H 0xfec ++ ++#define MSI_SW_RST 0xff0 ++#define MSI_SW_RESET (0x0001 << 0) ++ ++#define MSI_MODULE_ID 0xffc ++ ++ ++#endif /* __SAA716x_MSI_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_pci.c b/drivers/media/pci/saa716x/saa716x_pci.c +new file mode 100644 +index 0000000..f97e4d3 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_pci.c +@@ -0,0 +1,278 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_msi.h" ++#include "saa716x_priv.h" ++ ++#define DRIVER_NAME "SAA716x Core" ++ ++static inline irqreturn_t saa716x_msi_handler(int irq, void *dev_id) ++{ ++ return IRQ_HANDLED; ++} ++ ++static int saa716x_enable_msi(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err; ++ ++ err = pci_enable_msi(pdev); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "MSI enable failed <%d>", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++static int saa716x_enable_msix(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, ret = 0; ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ ret = pci_enable_msix(pdev, saa716x->msix_entries, SAA716x_MSI_MAX_VECTORS); ++ if (ret < 0) ++ dprintk(SAA716x_ERROR, 1, "MSI-X request failed <%d>", ret); ++ if (ret > 0) ++ dprintk(SAA716x_ERROR, 1, "Request exceeds available IRQ's <%d>", ret); ++ ++ return ret; ++} ++ ++static int saa716x_request_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_config *config = saa716x->config; ++ int i, ret = 0; ++ ++ if (saa716x->int_type == MODE_MSI) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI mode"); ++ ret = saa716x_enable_msi(saa716x); ++ } else if (saa716x->int_type == MODE_MSI_X) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI-X mode"); ++ ret = saa716x_enable_msix(saa716x); ++ } ++ ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "INT-A Mode"); ++ saa716x->int_type = MODE_INTA; ++ } ++ ++ if (saa716x->int_type == MODE_MSI) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ 0, ++ DRIVER_NAME, ++ saa716x); ++ ++ if (ret) { ++ pci_disable_msi(pdev); ++ dprintk(SAA716x_ERROR, 1, "MSI registration failed"); ++ } ++ } ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { ++ ret = request_irq(saa716x->msix_entries[i].vector, ++ saa716x->saa716x_msix_handler[i].handler, ++ IRQF_SHARED, ++ saa716x->saa716x_msix_handler[i].desc, ++ saa716x); ++ ++ dprintk(SAA716x_ERROR, 1, "%s @ 0x%p", saa716x->saa716x_msix_handler[i].desc, saa716x->saa716x_msix_handler[i].handler); ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "%s MSI-X-%d registration failed <%d>", saa716x->saa716x_msix_handler[i].desc, i, ret); ++ break; ++ } ++ } ++ ++ /* free already allocated vectors in error case */ ++ while (ret && i > 0) { ++ --i; ++ free_irq(saa716x->msix_entries[i].vector, saa716x); ++ } ++ } ++ ++ if (saa716x->int_type == MODE_INTA) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ IRQF_SHARED, ++ DRIVER_NAME, ++ saa716x); ++ if (ret < 0) ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed <%d>", ret); ++ } ++ ++ return ret; ++} ++ ++static void saa716x_free_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, vector; ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { ++ vector = saa716x->msix_entries[i].vector; ++ free_irq(vector, saa716x); ++ } ++ ++ pci_disable_msix(pdev); ++ ++ } else { ++ free_irq(pdev->irq, saa716x); ++ if (saa716x->int_type == MODE_MSI) ++ pci_disable_msi(pdev); ++ } ++} ++ ++int saa716x_pci_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err = 0, ret = -ENODEV, i, use_dac, pm_cap; ++ u32 msi_cap; ++ u8 revision; ++ ++ dprintk(SAA716x_ERROR, 1, "found a %s PCIe card", saa716x->config->model_name); ++ ++ err = pci_enable_device(pdev); ++ if (err != 0) { ++ ret = -ENODEV; ++ dprintk(SAA716x_ERROR, 1, "ERROR: PCI enable failed (%i)", err); ++ goto fail0; ++ } ++ ++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { ++ use_dac = 1; ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 64bit DMA"); ++ goto fail1; ++ } ++ } else if ((err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 32bit DMA"); ++ goto fail1; ++ } ++ ++ pci_set_master(pdev); ++ ++ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); ++ if (pm_cap == 0) { ++ dprintk(SAA716x_ERROR, 1, "Cannot find Power Management Capability"); ++ err = -EIO; ++ goto fail1; ++ } ++ ++ if (!request_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0), ++ DRIVER_NAME)) { ++ ++ dprintk(SAA716x_ERROR, 1, "BAR0 Request failed"); ++ ret = -ENODEV; ++ goto fail1; ++ } ++ saa716x->mmio = ioremap(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++ if (!saa716x->mmio) { ++ dprintk(SAA716x_ERROR, 1, "Mem 0 remap failed"); ++ ret = -ENODEV; ++ goto fail2; ++ } ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ err = saa716x_request_irq(saa716x); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed, err=%d", err); ++ ret = -ENODEV; ++ goto fail3; ++ } ++ ++ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); ++ pci_read_config_dword(pdev, 0x40, &msi_cap); ++ ++ saa716x->revision = revision; ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x Rev %d [%04x:%04x], ", ++ saa716x->pdev->device, ++ revision, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 0, ++ "irq: %d,\n mmio: 0x%p\n", ++ saa716x->pdev->irq, ++ saa716x->mmio); ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x %sBit, MSI %s, MSI-X=%d msgs", ++ saa716x->pdev->device, ++ (((msi_cap >> 23) & 0x01) == 1 ? "64":"32"), ++ (((msi_cap >> 16) & 0x01) == 1 ? "Enabled" : "Disabled"), ++ (1 << ((msi_cap >> 17) & 0x07))); ++ ++ dprintk(SAA716x_ERROR, 0, "\n"); ++ ++ pci_set_drvdata(pdev, saa716x); ++ ++ return 0; ++ ++fail3: ++ dprintk(SAA716x_ERROR, 1, "Err: IO Unmap"); ++ if (saa716x->mmio) ++ iounmap(saa716x->mmio); ++fail2: ++ dprintk(SAA716x_ERROR, 1, "Err: Release regions"); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++fail1: ++ dprintk(SAA716x_ERROR, 1, "Err: Disabling device"); ++ pci_disable_device(pdev); ++ ++fail0: ++ pci_set_drvdata(pdev, NULL); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_init); ++ ++void saa716x_pci_exit(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ saa716x_free_irq(saa716x); ++ ++ dprintk(SAA716x_NOTICE, 1, "SAA%02x mem0: 0x%p", ++ saa716x->pdev->device, ++ saa716x->mmio); ++ ++ if (saa716x->mmio) { ++ iounmap(saa716x->mmio); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ } ++ ++ pci_disable_device(pdev); ++ pci_set_drvdata(pdev, NULL); ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_exit); ++ ++MODULE_DESCRIPTION("SAA716x bridge driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/pci/saa716x/saa716x_phi.c b/drivers/media/pci/saa716x/saa716x_phi.c +new file mode 100644 +index 0000000..7df9a98 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_phi.c +@@ -0,0 +1,152 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_spi.h" ++#include "saa716x_phi.h" ++#include "saa716x_priv.h" ++ ++u32 PHI_0_REGS[] = { ++ PHI_0_MODE, ++ PHI_0_0_CONFIG, ++ PHI_0_1_CONFIG, ++ PHI_0_2_CONFIG, ++ PHI_0_3_CONFIG ++}; ++ ++u32 PHI_1_REGS[] = { ++ PHI_1_MODE, ++ PHI_1_0_CONFIG, ++ PHI_1_1_CONFIG, ++ PHI_1_2_CONFIG, ++ PHI_1_3_CONFIG, ++ PHI_1_4_CONFIG, ++ PHI_1_5_CONFIG, ++ PHI_1_6_CONFIG, ++ PHI_1_7_CONFIG ++}; ++ ++#define PHI_BASE(__port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_BASE : \ ++ PHI_0_BASE \ ++)) ++ ++#define PHI_APERTURE(_port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_APERTURE: \ ++ PHI_0_APERTURE \ ++)) ++ ++#define PHI_REG(__port, __reg) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_REGS[__reg] : \ ++ PHI_0_REGS[__reg] \ ++)) ++ ++#define PHI_SLAVE(__port, __slave) (( \ ++ PHI_BASE(__port) + (__slave * (PHI_APERTURE(__port))) \ ++)) ++ ++/* // Read SAA716x registers ++ * SAA716x_EPRD(PHI_0, PHI_REG(__port, __reg)) ++ * SAA716x_EPWR(PHI_1, PHI_REG(__port, __reg), __data) ++ * ++ * // Read slave registers ++ * SAA716x_EPRD(PHI_0, PHI_SLAVE(__port, __slave, __offset)) ++ * SAA716x_EPWR(PHI_1, PHI_SLAVE(__port, __slave, _offset), __data) ++ */ ++ ++int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave) ++{ ++ int i; ++ ++ /* Reset */ ++ SAA716x_EPWR(PHI_0, PHI_SW_RST, 0x1); ++ ++ for (i = 0; i < 20; i++) { ++ msleep(1); ++ if (!(SAA716x_EPRD(PHI_0, PHI_SW_RST))) ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_phi_init(struct saa716x_dev *saa716x) ++{ ++ uint32_t value; ++ ++ /* init PHI 0 to FIFO mode */ ++ value = 0; ++ value |= PHI_FIFO_MODE; ++ SAA716x_EPWR(PHI_0, PHI_0_MODE, value); ++ ++ value = 0; ++ value |= 0x02; /* chip select 1 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x06 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_0_0_CONFIG, value); ++ ++ /* init PHI 1 to SRAM mode, auto increment on */ ++ value = 0; ++ value |= PHI_AUTO_INCREMENT; ++ SAA716x_EPWR(PHI_0, PHI_1_MODE, value); ++ ++ value = 0; ++ value |= 0x01; /* chip select 0 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x05 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_1_0_CONFIG, value); ++ ++ value = 0; ++ value |= PHI_ALE_POL; /* ALE is active high */ ++ SAA716x_EPWR(PHI_0, PHI_POLARITY, value); ++ ++ SAA716x_EPWR(PHI_0, PHI_TIMEOUT, 0x2a); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_init); ++ ++int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_1, address, *((u32 *) &data[i])); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write); ++ ++int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ *((u32 *) &data[i]) = SAA716x_EPRD(PHI_1, address); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_read); ++ ++int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_0, PHI_0_0_RW_0, *((u32 *) &data[i])); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write_fifo); +diff --git a/drivers/media/pci/saa716x/saa716x_phi.h b/drivers/media/pci/saa716x/saa716x_phi.h +new file mode 100644 +index 0000000..ff5cda2 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_phi.h +@@ -0,0 +1,39 @@ ++#ifndef __SAA716x_PHI_H ++#define __SAA716x_PHI_H ++ ++/* PHI SLAVE */ ++#define PHI_SLAVE_0 0 ++#define PHI_SLAVE_1 1 ++#define PHI_SLAVE_2 2 ++#define PHI_SLAVE_3 3 ++#define PHI_SLAVE_4 4 ++#define PHI_SLAVE_5 5 ++#define PHI_SLAVE_6 6 ++#define PHI_SLAVE_7 7 ++ ++/* PHI_REG */ ++#define PHI_MODE 0 ++#define PHI_CONFIG_0 1 ++#define PHI_CONFIG_1 2 ++#define PHI_CONFIG_2 3 ++#define PHI_CONFIG_3 4 ++#define PHI_CONFIG_4 5 ++#define PHI_CONFIG_5 6 ++#define PHI_CONFIG_6 7 ++#define PHI_CONFIG_7 8 ++ ++#define PHI_0_BASE 0x1000 ++#define PHI_0_APERTURE 0x0800 ++ ++#define PHI_1_BASE 0x0000 ++#define PHI_1_APERTURE 0xfffc ++ ++struct saa716x_dev; ++ ++extern int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave); ++extern int saa716x_phi_init(struct saa716x_dev *saa716x); ++extern int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 *data, int length); ++extern int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 *data, int length); ++extern int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length); ++ ++#endif /* __SAA716x_PHI_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_phi_reg.h b/drivers/media/pci/saa716x/saa716x_phi_reg.h +new file mode 100644 +index 0000000..cb9e148 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_phi_reg.h +@@ -0,0 +1,94 @@ ++#ifndef __SAA716x_PHI_REG_H ++#define __SAA716x_PHI_REG_H ++ ++/* -------------- PHI_0 Registers -------------- */ ++ ++#define PHI_0_MODE 0x0000 ++#define PHI_0_0_CONFIG 0x0008 ++#define PHI_0_1_CONFIG 0x000c ++#define PHI_0_2_CONFIG 0x0010 ++#define PHI_0_3_CONFIG 0x0014 ++ ++#define PHI_POLARITY 0x0038 ++#define PHI_TIMEOUT 0x003c ++#define PHI_SW_RST 0x0ff0 ++ ++#define PHI_0_0_RW_0 0x1000 ++#define PHI_0_0_RW_511 0x17fc ++ ++#define PHI_0_1_RW_0 0x1800 ++#define PHI_0_1_RW_511 0x1ffc ++ ++#define PHI_0_2_RW_0 0x2000 ++#define PHI_0_2_RW_511 0x27fc ++ ++#define PHI_0_3_RW_0 0x2800 ++#define PHI_0_3_RW_511 0x2ffc ++ ++#define PHI_CSN_DEASSERT (0x00000001 << 2) ++#define PHI_AUTO_INCREMENT (0x00000001 << 1) ++#define PHI_FIFO_MODE (0x00000001 << 0) ++ ++#define PHI_DELAY_RD_WR (0x0000001f << 27) ++#define PHI_EXTEND_RDY3 (0x00000003 << 25) ++#define PHI_EXTEND_RDY2 (0x00000003 << 23) ++#define PHI_EXTEND_RDY1 (0x00000003 << 21) ++#define PHI_EXTEND_RDY0 (0x00000003 << 19) ++#define PHI_RDY3_OD (0x00000001 << 18) ++#define PHI_RDY2_OD (0x00000001 << 17) ++#define PHI_RDY1_OD (0x00000001 << 16) ++#define PHI_RDY0_OD (0x00000001 << 15) ++#define PHI_ALE_POL (0x00000001 << 14) ++#define PHI_WRN_POL (0x00000001 << 13) ++#define PHI_RDN_POL (0x00000001 << 12) ++#define PHI_RDY3_POL (0x00000001 << 11) ++#define PHI_RDY2_POL (0x00000001 << 10) ++#define PHI_RDY1_POL (0x00000001 << 9) ++#define PHI_RDY0_POL (0x00000001 << 8) ++#define PHI_CSN7_POL (0x00000001 << 7) ++#define PHI_CSN6_POL (0x00000001 << 6) ++#define PHI_CSN5_POL (0x00000001 << 5) ++#define PHI_CSN4_POL (0x00000001 << 4) ++#define PHI_CSN3_POL (0x00000001 << 3) ++#define PHI_CSN2_POL (0x00000001 << 2) ++#define PHI_CSN1_POL (0x00000001 << 1) ++#define PHI_CSN0_POL (0x00000001 << 0) ++ ++/* -------------- PHI_1 Registers -------------- */ ++ ++#define PHI_1_MODE 0x00004 ++#define PHI_1_0_CONFIG 0x00018 ++#define PHI_1_1_CONFIG 0x0001c ++#define PHI_1_2_CONFIG 0x00020 ++#define PHI_1_3_CONFIG 0x00024 ++#define PHI_1_4_CONFIG 0x00028 ++#define PHI_1_5_CONFIG 0x0002c ++#define PHI_1_6_CONFIG 0x00030 ++#define PHI_1_7_CONFIG 0x00034 ++ ++#define PHI_1_0_RW_0 0x00000 ++#define PHI_1_0_RW_16383 0x0fffc ++ ++#define PHI_1_1_RW_0 0x1000 ++#define PHI_1_1_RW_16383 0x1ffc ++ ++#define PHI_1_2_RW_0 0x2000 ++#define PHI_1_2_RW_16383 0x2ffc ++ ++#define PHI_1_3_RW_0 0x3000 ++#define PHI_1_3_RW_16383 0x3ffc ++ ++#define PHI_1_4_RW_0 0x4000 ++#define PHI_1_4_RW_16383 0x4ffc ++ ++#define PHI_1_5_RW_0 0x5000 ++#define PHI_1_5_RW_16383 0x5ffc ++ ++#define PHI_1_6_RW_0 0x6000 ++#define PHI_1_6_RW_16383 0x6ffc ++ ++#define PHI_1_7_RW_0 0x7000 ++#define PHI_1_7_RW_16383 0x7ffc ++ ++ ++#endif /* __SAA716x_PHI_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_priv.h b/drivers/media/pci/saa716x/saa716x_priv.h +new file mode 100644 +index 0000000..5ae8000 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_priv.h +@@ -0,0 +1,205 @@ ++#ifndef __SAA716x_PRIV_H ++#define __SAA716x_PRIV_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "saa716x_i2c.h" ++#include "saa716x_boot.h" ++#include "saa716x_cgu.h" ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++#include "saa716x_spi.h" ++#include "saa716x_vip.h" ++ ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dmxdev.h" ++#include "dvb_frontend.h" ++#include "dvb_net.h" ++ ++#define SAA716x_ERROR 0 ++#define SAA716x_NOTICE 1 ++#define SAA716x_INFO 2 ++#define SAA716x_DEBUG 3 ++ ++#define SAA716x_DEV (saa716x)->num ++#define SAA716x_VERBOSE (saa716x)->verbose ++#define SAA716x_MAX_ADAPTERS 4 ++ ++#define dprintk(__x, __y, __fmt, __arg...) do { \ ++ if (__y) { \ ++ if ((SAA716x_VERBOSE > SAA716x_ERROR) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_ERR "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_NOTICE) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_NOTICE "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_INFO) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_INFO "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_DEBUG) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_DEBUG "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ } else { \ ++ if (SAA716x_VERBOSE > __x) \ ++ printk(__fmt , ##__arg); \ ++ } \ ++} while(0) ++ ++ ++#define NXP_SEMICONDUCTOR 0x1131 ++#define SAA7160 0x7160 ++#define SAA7161 0x7161 ++#define SAA7162 0x7162 ++ ++#define NXP_REFERENCE_BOARD 0x1131 ++ ++#define MAKE_ENTRY(__subven, __subdev, __chip, __configptr) { \ ++ .vendor = NXP_SEMICONDUCTOR, \ ++ .device = (__chip), \ ++ .subvendor = (__subven), \ ++ .subdevice = (__subdev), \ ++ .driver_data = (unsigned long) (__configptr) \ ++} ++ ++#define SAA716x_EPWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_EPRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++#define SAA716x_RCWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_RCRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++ ++#define SAA716x_MSI_MAX_VECTORS 16 ++ ++struct saa716x_msix_entry { ++ int vector; ++ u8 desc[32]; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++struct saa716x_dev; ++struct saa716x_adapter; ++struct saa716x_spi_config; ++ ++struct saa716x_adap_config { ++ u32 ts_port; ++ void (*worker)(unsigned long); ++}; ++ ++struct saa716x_config { ++ char *model_name; ++ char *dev_type; ++ ++ enum saa716x_boot_mode boot_mode; ++ ++ int adapters; ++ int frontends; ++ ++ int (*frontend_attach)(struct saa716x_adapter *adapter, int count); ++ irqreturn_t (*irq_handler)(int irq, void *dev_id); ++ ++ struct saa716x_adap_config adap_config[SAA716x_MAX_ADAPTERS]; ++ enum saa716x_i2c_rate i2c_rate; ++ enum saa716x_i2c_mode i2c_mode; ++}; ++ ++struct saa716x_adapter { ++ struct dvb_adapter dvb_adapter; ++ struct dvb_frontend *fe; ++ struct dvb_demux demux; ++ struct dmxdev dmxdev; ++ struct dmx_frontend fe_hw; ++ struct dmx_frontend fe_mem; ++ struct dvb_net dvb_net; ++ ++ struct saa716x_dev *saa716x; ++ ++ u8 feeds; ++ u8 count; ++ ++ struct i2c_client *i2c_client_demod; ++ struct i2c_client *i2c_client_tuner; ++ ++ struct tbsci_i2c_state *tbsci; ++ void*adap_priv; ++}; ++ ++struct saa716x_dev { ++ struct saa716x_config *config; ++ struct pci_dev *pdev; ++ struct module *module; ++ ++ int num_adapters; /* adapter count (adapters on this saa716x card) */ ++ int num; /* device count (saa716x based cards) */ ++ int verbose; ++ ++ u8 revision; ++ ++ /* PCI */ ++ void __iomem *mmio; ++ ++#define MODE_INTA 0 ++#define MODE_MSI 1 ++#define MODE_MSI_X 2 ++ u8 int_type; ++ ++ struct msix_entry msix_entries[SAA716x_MSI_MAX_VECTORS]; ++ struct saa716x_msix_entry saa716x_msix_handler[56]; ++ u8 handlers; /* no. of active handlers */ ++ ++ /* I2C */ ++ struct saa716x_i2c i2c[2]; ++ u32 i2c_rate; /* init time */ ++ u32 I2C_DEV[2]; ++ ++ struct saa716x_spi_state *saa716x_spi; ++ struct saa716x_spi_config spi_config; ++ ++ struct saa716x_adapter saa716x_adap[SAA716x_MAX_ADAPTERS]; ++ struct mutex adap_lock; ++ struct saa716x_cgu cgu; ++ ++ spinlock_t gpio_lock; ++ /* DMA */ ++ ++ struct saa716x_fgpi_stream_port fgpi[4]; ++ struct saa716x_vip_stream_port vip[2]; ++ ++ u32 id_offst; ++ u32 id_len; ++ void *priv; ++ ++ /* remote control */ ++ void *ir_priv; ++}; ++ ++/* PCI */ ++extern int saa716x_pci_init(struct saa716x_dev *saa716x); ++extern void saa716x_pci_exit(struct saa716x_dev *saa716x); ++ ++/* MSI */ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msi_exit(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++/* DMA */ ++extern int saa716x_dma_init(struct saa716x_dev *saa716x); ++extern void saa716x_dma_exit(struct saa716x_dev *saa716x); ++ ++/* AUDIO */ ++extern int saa716x_audio_init(struct saa716x_dev *saa716x); ++extern void saa716x_audio_exit(struct saa716x_dev *saa716x); ++ ++/* Boot */ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++ ++/* Remote control */ ++extern int saa716x_ir_init(struct saa716x_dev *saa716x); ++extern void saa716x_ir_exit(struct saa716x_dev *saa716x); ++extern void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd); ++ ++#endif /* __SAA716x_PRIV_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_rom.c b/drivers/media/pci/saa716x/saa716x_rom.c +new file mode 100644 +index 0000000..63fd061 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_rom.c +@@ -0,0 +1,1087 @@ ++#include ++#include ++ ++#include "saa716x_rom.h" ++#include "saa716x_adap.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++int i; ++ ++static int eeprom_read_bytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ ++ u8 b0[] = { MSB(reg), LSB(reg) }; ++ int ret; ++ ++ struct i2c_msg msg[] = { ++ { .addr = 0x50, .flags = 0, .buf = b0, .len = sizeof (b0) }, ++ { .addr = 0x50, .flags = I2C_M_RD, .buf = val, .len = len } ++ }; ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ struct i2c_msg msg[2]; ++ ++ u8 b0[2]; ++ int ret, count; ++ ++ count = len / DUMP_BYTES; ++ if (len % DUMP_BYTES) ++ count++; ++ ++ count *= 2; ++ ++ for (i = 0; i < count; i += 2) { ++ dprintk(SAA716x_DEBUG, 1, "Length=%d, Count=%d, Reg=0x%02x", ++ len, ++ count, ++ reg); ++ ++ b0[0] = MSB(reg); ++ b0[1] = LSB(reg); ++ ++ /* Write */ ++ msg[0].addr = 0x50; ++ msg[0].flags = 0; ++ msg[0].buf = b0; ++ msg[0].len = 2; ++ ++ /* Read */ ++ msg[1].addr = 0x50; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = val; ++ ++ if (i == (count - 2)) { ++ /* last message */ ++ if (len % DUMP_BYTES) { ++ msg[1].len = len % DUMP_BYTES; ++ dprintk(SAA716x_DEBUG, 1, "Last Message length=%d", len % DUMP_BYTES); ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ reg += DUMP_BYTES; ++ val += DUMP_BYTES; ++ } ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL_GPL(saa716x_read_rombytes); ++ ++static int saa716x_get_offset(struct saa716x_dev *saa716x, u8 *buf, u32 *offset) ++{ ++ int i; ++ ++ *offset = 0; ++ for (i = 0; i < 256; i++) { ++ if (!(strncmp("START", buf + i, 5))) ++ break; ++ } ++ dprintk(SAA716x_INFO, 1, "Offset @ %d", i); ++ *offset = i; ++ ++ return 0; ++} ++ ++static int saa716x_eeprom_header(struct saa716x_dev *saa716x, ++ struct saa716x_romhdr *rom_header, ++ u8 *buf, ++ u32 *offset) ++{ ++ memcpy(rom_header, &buf[*offset], sizeof (struct saa716x_romhdr)); ++ if (rom_header->header_size != sizeof (struct saa716x_romhdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%zd bytes, Expected=%d", ++ sizeof (struct saa716x_romhdr), ++ rom_header->header_size); ++ ++ return -1; ++ } ++ *offset += sizeof (struct saa716x_romhdr); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Data=%d bytes\n", ++ saa716x->pdev->device, ++ rom_header->data_size); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Version=%d\n", ++ saa716x->pdev->device, ++ rom_header->version); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Devices=%d\n", ++ saa716x->pdev->device, ++ rom_header->devices); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Compressed=%d\n\n", ++ saa716x->pdev->device, ++ rom_header->compression); ++ ++ return 0; ++} ++ ++int saa716x_dump_eeprom(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ u8 buf[DUMP_BYTES]; ++ int i, err = 0; ++ u32 offset = 0; ++ ++ err = eeprom_read_bytes(saa716x, DUMP_OFFST, DUMP_BYTES, buf); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "EEPROM Read error"); ++ return err; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " Card: %s\n", ++ saa716x->config->model_name); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM @ Offset 0x%02x ----------------", ++ saa716x->pdev->device, ++ DUMP_OFFST); ++ ++ for (i = 0; i < DUMP_BYTES; i++) { ++ if ((i % 16) == 0) { ++ dprintk(SAA716x_NOTICE, 0, "\n "); ++ dprintk(SAA716x_NOTICE, 0, "%04x: ", i); ++ } ++ ++ if ((i % 8) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ dprintk(SAA716x_NOTICE, 0, "%02x ", buf[i]); ++ } ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM Dump end ---------------------\n\n", ++ saa716x->pdev->device); ++ ++ err = saa716x_get_offset(saa716x, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Descriptor not found <%d>", err); ++ return err; ++ } ++ offset += 5; ++ saa716x->id_offst = offset; ++ /* Get header */ ++ err = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", err); ++ return -1; ++ } ++ saa716x->id_len = rom_header.data_size; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_dump_eeprom); ++ ++static void saa716x_descriptor_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++static int saa716x_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext Data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_gpio_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_gpio_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_gpio_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_gpio_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_gpio_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pins=%d\n", ++ saa716x->pdev->device, ++ header.pins); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ ++ return 0; ++} ++ ++static int saa716x_video_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_video_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_video_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_video_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_video_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 0=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port0); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 1=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port1); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 2=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port2); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT ID=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_id); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_audio_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_audio_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_audio_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_audio_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_audio_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_event_source_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_evsrc_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_evsrc_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_evsrc_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_evsrc_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_crossbar_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_xbar_hdr header; ++ struct saa716x_xbar_pair_info pair_info; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_xbar_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_xbar_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_xbar_hdr)); ++ ++ return -1; ++ } ++ ++ memcpy(&pair_info, &buf[*offset], sizeof (struct saa716x_xbar_pair_info)); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pairs=%d\n", ++ saa716x->pdev->device, ++ header.pair_inputs); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data + (sizeof (struct saa716x_xbar_pair_info) * header.pair_inputs); ++ return 0; ++} ++ ++static int saa716x_tuner_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_tuner_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_tuner_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_tuner_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_tuner_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_pll_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_pll_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_pll_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_pll_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_pll_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_channel_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_channel_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_channel_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_channel_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_channel_decoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_encoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_encoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_encoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_encoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_encoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_ir_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_ir_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_ir_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_ir_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_ir_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_eeprom_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_eeprom_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_eeprom_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_eeprom_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_eeprom_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_filter_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_filter_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_filter_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_filter_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_filter_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_streamdev_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_streamdev_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_streamdev_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_streamdev_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%zd", ++ header.size, ++ sizeof (struct saa716x_streamdev_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_unknown_device_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 size; ++ u8 ext_size = 0; ++ ++ size = buf[*offset]; ++ if (size > 1) ++ ext_size = buf[*offset + size -1]; ++ ++ saa716x_descriptor_dbg(saa716x, buf, offset, size, ext_size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ ext_size); ++ ++ *offset += size + ext_size; ++ return 0; ++} ++ ++ ++static void saa716x_device_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size, ++ u8 addr_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size + addr_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++ ++static int saa716x_device_info(struct saa716x_dev *saa716x, ++ struct saa716x_devinfo *device, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 address = 0; ++ ++ memcpy(device, &buf[*offset], sizeof (struct saa716x_devinfo)); ++ if (device->struct_size != sizeof (struct saa716x_devinfo)) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Device size mismatch! Read=%d bytes, expected=%zd bytes", ++ device->struct_size, ++ sizeof (struct saa716x_devinfo)); ++ ++ return -1; ++ } ++ ++ saa716x_device_dbg(saa716x, ++ buf, ++ offset, ++ device->struct_size, ++ device->extd_data_size, ++ device->addr_size); ++ ++ *offset += device->struct_size; ++ ++ if (device->addr_size) { ++ address = buf[*offset]; ++ address >>= 1; ++ *offset += device->addr_size; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device @ 0x%02x\n", ++ saa716x->pdev->device, ++ address); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ device->struct_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Master ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_devid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Bus ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_busid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device type=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_type); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Implementation ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->implem_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Path ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->path_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: GPIO ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->gpio_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Address=%d bytes\n", ++ saa716x->pdev->device, ++ device->addr_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Extended data=%d bytes\n\n", ++ saa716x->pdev->device, ++ device->extd_data_size); ++ ++ if (device->extd_data_size) { ++ u32 mask; ++ ++ mask = 0x00000001; ++ while (mask) { ++ if (device->device_type & mask) { ++ switch (mask) { ++ case DECODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case GPIO_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found GPIO device\n", ++ saa716x->pdev->device); ++ ++ saa716x_gpio_info(saa716x, buf, offset); ++ break; ++ ++ case VIDEO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Video Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_video_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case AUDIO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Audio Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_audio_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case EVENT_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Event source\n", ++ saa716x->pdev->device); ++ ++ saa716x_event_source_info(saa716x, buf, offset); ++ break; ++ ++ case CROSSBAR: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Crossbar device\n", ++ saa716x->pdev->device); ++ ++ saa716x_crossbar_info(saa716x, buf, offset); ++ break; ++ ++ case TUNER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Tuner device\n", ++ saa716x->pdev->device); ++ ++ saa716x_tuner_info(saa716x, buf, offset); ++ break; ++ ++ case PLL_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found PLL device\n", ++ saa716x->pdev->device); ++ ++ saa716x_pll_info(saa716x, buf, offset); ++ break; ++ ++ case CHANNEL_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Channel Demodulator device\n", ++ saa716x->pdev->device); ++ ++ saa716x_channel_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case RDS_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found RDS Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case ENCODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Encoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_encoder_info(saa716x, buf, offset); ++ break; ++ ++ case IR_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found IR device\n", ++ saa716x->pdev->device); ++ ++ saa716x_ir_info(saa716x, buf, offset); ++ break; ++ ++ case EEPROM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found EEPROM device\n", ++ saa716x->pdev->device); ++ ++ saa716x_eeprom_info(saa716x, buf, offset); ++ break; ++ ++ case NOISE_FILTER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Noise filter device\n", ++ saa716x->pdev->device); ++ ++ saa716x_filter_info(saa716x, buf, offset); ++ break; ++ ++ case LNx_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found LNx device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case STREAM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found streaming device\n", ++ saa716x->pdev->device); ++ ++ saa716x_streamdev_info(saa716x, buf, offset); ++ break; ++ ++ case CONFIGSPACE_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Configspace device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ default: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found unknown device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ } ++ } ++ mask <<= 1; ++ } ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ ++ return 0; ++} ++ ++int saa716x_eeprom_data(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ struct saa716x_devinfo *device; ++ ++ u8 *buf; ++ int i, ret = 0; ++ u32 offset = 0; ++ ++ buf = kmalloc(1024, GFP_KERNEL); ++ if (buf == NULL) { ++ dev_err(&saa716x->pdev->dev, ++ "%s: out of memory (buf)\n", __func__); ++ goto err; ++ } ++ ++ /* dump */ ++ ret = saa716x_read_rombytes(saa716x, ++ saa716x->id_offst, saa716x->id_len + 8, buf); ++ if (ret < 0) { ++ dev_err(&saa716x->pdev->dev, ++ "%s: EEPROM read error <%d>", __func__, ret); ++ goto err0; ++ } ++ ++ /* Get header */ ++ ret = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (ret != 0) { ++ dev_err(&saa716x->pdev->dev, ++ "%s: header read failed <%d>", __func__, ret); ++ goto err0; ++ } ++ ++ /* allocate for device info */ ++ device = kzalloc(sizeof (struct saa716x_devinfo) * rom_header.devices, ++ GFP_KERNEL); ++ if (device == NULL) { ++ dev_err(&saa716x->pdev->dev, ++ "%s: out of memory (device)", __func__); ++ goto err0; ++ } ++ ++ for (i = 0; i < rom_header.devices; i++) { ++ dev_dbg(&saa716x->pdev->dev, ++ "%s: SAA%02x ROM: ===== Device %d =====\n", ++ __func__, saa716x->pdev->device, i); ++ ++ ret = saa716x_device_info(saa716x, &device[i], buf, &offset); ++ if (ret != 0) { ++ dev_err(&saa716x->pdev->dev, ++ "%s: device info read failed <%d>", __func__, ret); ++ goto err1; ++ } ++ } ++ ++ kfree(buf); ++ kfree(device); ++ return 0; ++ ++err1: ++ kfree(device); ++err0: ++ kfree(buf); ++err: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_eeprom_data); +diff --git a/drivers/media/pci/saa716x/saa716x_rom.h b/drivers/media/pci/saa716x/saa716x_rom.h +new file mode 100644 +index 0000000..bae4e11 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_rom.h +@@ -0,0 +1,254 @@ ++#ifndef __SAA716x_ROM_H ++#define __SAA716x_ROM_H ++ ++ ++#define MSB(__x) ((__x >> 8) & 0xff) ++#define LSB(__x) (__x & 0xff) ++ ++#define DUMP_BYTES 0xf0 ++#define DUMP_OFFST 0x000 ++ ++struct saa716x_dev; ++ ++struct saa716x_romhdr { ++ u16 header_size; ++ u8 compression; ++ u8 version; ++ u16 data_size; ++ u8 devices; ++ u8 checksum; ++} __attribute__((packed)); ++ ++struct saa716x_devinfo { ++ u8 struct_size; ++ u8 device_id; ++ u8 master_devid; ++ u8 master_busid; ++ u32 device_type; ++ u16 implem_id; ++ u8 path_id; ++ u8 gpio_id; ++ u16 addr_size; ++ u16 extd_data_size; ++} __attribute__((packed)); ++ ++enum saa716x_device_types { ++ DECODER_DEVICE = 0x00000001, ++ GPIO_SOURCE = 0x00000002, ++ VIDEO_DECODER = 0x00000004, ++ AUDIO_DECODER = 0x00000008, ++ EVENT_SOURCE = 0x00000010, ++ CROSSBAR = 0x00000020, ++ TUNER_DEVICE = 0x00000040, ++ PLL_DEVICE = 0x00000080, ++ CHANNEL_DECODER = 0x00000100, ++ RDS_DECODER = 0x00000200, ++ ENCODER_DEVICE = 0x00000400, ++ IR_DEVICE = 0x00000800, ++ EEPROM_DEVICE = 0x00001000, ++ NOISE_FILTER = 0x00002000, ++ LNx_DEVICE = 0x00004000, ++ STREAM_DEVICE = 0x00010000, ++ CONFIGSPACE_DEVICE = 0x80000000 ++}; ++ ++struct saa716x_decoder_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_decoder_info { ++ struct saa716x_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_gpio_hdr { ++ u8 size; ++ u8 pins; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_gpio_info { ++ struct saa716x_gpio_hdr gpio_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_video_decoder_hdr { ++ u8 size; ++ u8 video_port0; ++ u8 video_port1; ++ u8 video_port2; ++ u8 vbi_port_id; ++ u8 video_port_type; ++ u8 vbi_port_type; ++ u8 encoder_port_type; ++ u8 video_output; ++ u8 vbi_output; ++ u8 encoder_output; ++ u8 ext_data; ++}; ++ ++struct saa716x_video_decoder_info { ++ struct saa716x_video_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_audio_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 output; ++ u8 ext_data; ++}; ++ ++struct saa716x_audio_decoder_info { ++ struct saa716x_audio_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_evsrc_hdr { ++ u8 size; ++ u8 master_devid; ++ u16 condition_id; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_evsrc_info { ++ struct saa716x_evsrc_hdr evsrc_hdr; ++ u8 *ext_data; ++}; ++ ++enum saa716x_input_pair_type { ++ TUNER_SIF = 0x00, ++ TUNER_LINE = 0x01, ++ TUNER_SPDIF = 0x02, ++ TUNER_NONE = 0x03, ++ CVBS_LINE = 0x04, ++ CVBS_SPDIF = 0x05, ++ CVBS_NONE = 0x06, ++ YC_LINE = 0x07, ++ YC_SPDIF = 0x08, ++ YC_NONE = 0x09, ++ YPbPr_LINE = 0x0a, ++ YPbPr_SPDIF = 0x0b, ++ YPbPr_NONE = 0x0c, ++ NO_LINE = 0x0d, ++ NO_SPDIF = 0x0e, ++ RGB_LINE = 0x0f, ++ RGB_SPDIF = 0x10, ++ RGB_NONE = 0x11 ++}; ++ ++struct saa716x_xbar_pair_info { ++ u8 pair_input_type; ++ u8 video_input_id; ++ u8 audio_input_id; ++}; ++ ++struct saa716x_xbar_hdr { ++ u8 size; ++ u8 pair_inputs; ++ u8 pair_route_default; ++ u8 ext_data; ++}; ++ ++struct saa716x_xbar_info { ++ struct saa716x_xbar_hdr xbar_hdr; ++ struct saa716x_xbar_pair_info *pair_info; ++ u8 *ext_data; ++}; ++ ++struct saa716x_tuner_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_tuner_info { ++ struct saa716x_tuner_hdr tuner_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_pll_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_pll_info { ++ struct saa716x_pll_hdr pll_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_channel_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 ext_data; ++}; ++ ++struct saa716x_channel_decoder_info { ++ struct saa716x_channel_decoder_hdr channel_dec_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_encoder_hdr { ++ u8 size; ++ u8 stream_port0; ++ u8 stream_port1; ++ u8 ext_data; ++}; ++ ++struct saa716x_encoder_info { ++ struct saa716x_encoder_hdr encoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_ir_hdr { ++ u8 size; ++ u8 ir_caps; ++ u8 ext_data; ++}; ++ ++struct saa716x_ir_info { ++ struct saa716x_ir_hdr ir_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_eeprom_hdr { ++ u8 size; ++ u8 rel_device; ++ u8 ext_data; ++}; ++ ++struct saa716x_eeprom_info { ++ struct saa716x_eeprom_hdr eeprom_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_filter_hdr { ++ u8 size; ++ u8 video_decoder; ++ u8 audio_decoder; ++ u8 event_source; ++ u8 ext_data; ++}; ++ ++struct saa716x_filter_info { ++ struct saa716x_filter_hdr filter_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_streamdev_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_streamdev_info { ++ struct saa716x_streamdev_hdr streamdev_hdr; ++ u8 *ext_data; ++}; ++ ++extern int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val); ++extern int saa716x_dump_eeprom(struct saa716x_dev *saa716x); ++extern int saa716x_eeprom_data(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ROM_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_spi.c b/drivers/media/pci/saa716x/saa716x_spi.c +new file mode 100644 +index 0000000..8859454 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_spi.c +@@ -0,0 +1,313 @@ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_spi_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#if 0 // not needed atm ++int saa716x_spi_irqevent(struct saa716x_dev *saa716x) ++{ ++ u32 stat, mask; ++ ++ BUG_ON(saa716x == NULL); ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ mask = SAA716x_EPRD(SPI, SPI_CONTROL_REG) & SPI_SERIAL_INTER_ENABLE; ++ if ((!stat && !mask)) ++ return -1; ++ ++ dprintk(SAA716x_DEBUG, 0, "SPI event: Stat=<%02x>", stat); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++#endif ++ ++void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ int i; ++ u32 value; ++ int rounds; ++ ++ for (i = 0; i < length; i++) { ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ rounds = 0; ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ while ((value & SPI_TRANSFER_FLAG) == 0 && rounds < 5000) { ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ rounds++; ++ } ++ } ++} ++EXPORT_SYMBOL_GPL(saa716x_spi_write); ++ ++#if 0 // not needed atm ++static int saa716x_spi_status(struct saa716x_dev *saa716x, u32 *status) ++{ ++ u32 stat; ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 1, "Transfer complete <%02x>", stat); ++ ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 1, "Write collission <%02x>", stat); ++ ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 1, "Read Overrun <%02x>", stat); ++ ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 1, "MODE fault <%02x>", stat); ++ ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 1, "SLAVE abort <%02x>", stat); ++ ++ *status = stat; ++ ++ return 0; ++} ++ ++#define SPI_CYCLE_TIMEOUT 100 ++ ++static int saa716x_spi_xfer(struct saa716x_dev *saa716x, u32 *data) ++{ ++ u32 i, status = 0; ++ ++ /* write data and wait for completion */ ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ for (i = 0; i < SPI_CYCLE_TIMEOUT; i++) { ++ msleep(10); ++ saa716x_spi_status(saa716x, &status); ++#if 0 ++ if (status & SPI_TRANSFER_FLAG) { ++ data = SAA716x_EPRD(SPI, SPI_DATA); ++ return 0; ++ } ++#endif ++ if (status & (SPI_WRITE_COLLISSION | ++ SPI_READ_OVERRUN | ++ SPI_MODE_FAULT | ++ SPI_SLAVE_ABORT)) ++ ++ return -EIO; ++ } ++ ++ return -EIO; ++} ++ ++#if 0 ++static int saa716x_spi_wr(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ struct saa716x_spi_config *config = saa716x->spi_config; ++ u32 gpio_mask; ++ int ret = 0; ++ ++ // protect against multiple access ++ spin_lock(&saa716x->gpio_lock); ++ ++ // configure the module ++ saa716x_spi_config(saa716x); ++ ++ // check input ++ ++ // change polarity of GPIO if active high ++ if (config->active_hi) { ++ select = 1; ++ release = 0; ++ } ++ ++ // configure GPIO, first set output register to low selected level ++ saa716x_gpio_write(saa716x, gpio, select); ++ ++ // set mode register to register controlled (0) ++ gpio_mask = (1 << gpio); ++ saa716x_set_gpio_mode(saa716x, gpio_mask, 0); ++ ++ // configure bit as output (0) ++ saa716x_gpio_ctl(saa716x, gpio_mask, 0); ++ ++ // wait at least 500ns before sending a byte ++ msleep(1); ++ ++ // send command ++ for (i = 0; i < dwCommandSize; i++) { ++ ucData = 0; ++// dwStatus = TransferData(pucCommand[i], &ucData); ++ ret = saa716x_spi_xfer(saa716x); ++ //tmDBGPRINTEx(4,("Info: Command 0x%x ", pucCommand[i] )); ++ ++ /* If command length > 1, disable CS at the end of each command. ++ * But after the last command byte CS must be left active! ++ */ ++ if ((dwCommandSize > 1) && (i < dwCommandSize - 1)) { ++ ++ saa716x_gpio_write(saa716x, gpio, release); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, select); ++ } ++ ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Command transfer failed"); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, release); /* release GPIO */ ++ spin_unlock(&saa716x->spi_lock); ++ return ret; ++ } ++ ++ if (config->LSB_first) ++ dwTransferByte++; ++ else ++ dwTransferByte--; ++ } ++ ++// assume that the byte order is the same as the bit order ++ ++// send read address ++ ++// send data ++ ++// wait at least 500ns before releasing slave ++ ++// release GPIO pin ++ ++ // release spinlock ++ spin_unlock(&saa716x->gpio_lock); ++} ++#endif ++ ++#define MODEBITS (SPI_CPOL | SPI_CPHA) ++ ++static int saa716x_spi_setup(struct spi_device *spi) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ struct saa716x_spi_config *config = &saa716x->spi_config; ++ ++ u8 control = 0; ++ ++ if (spi->mode & ~MODEBITS) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Unsupported MODE bits <%x>", ++ spi->mode & ~MODEBITS); ++ ++ return -EINVAL; ++ } ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, config->clk_count); ++ ++ control |= SPI_MODE_SELECT; /* SPI Master */ ++ ++ if (config->LSB_first) ++ control |= SPI_LSB_FIRST_ENABLE; ++ ++ if (config->clk_pol) ++ control |= SPI_CLOCK_POLARITY; ++ ++ if (config->clk_pha) ++ control |= SPI_CLOCK_PHASE; ++ ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, control); ++ ++ return 0; ++} ++ ++static void saa716x_spi_cleanup(struct spi_device *spi) ++{ ++ ++} ++ ++static int saa716x_spi_transfer(struct spi_device *spi, struct spi_message *msg) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++#if 0 ++ if (saa716x_spi->run == QUEUE_STOPPED) { ++ spin_unlock_irqrestore(&saa716x_spi->lock, flags); ++ return -ESHUTDOWN; ++ } ++ ++ msg->actual_length = 0; ++ msg->status = -EINPROGRESS; ++ msg->state = START_STATE; ++ ++ list_add_tail(&msg->queue, &saa716x_spi->queue); ++ ++ if (saa716x_spi->run == QUEUE_RUNNING && !saa716x_spi->busy) ++ queue_work(saa716x_spi->workqueue, &saa716x_spi->pump_messages); ++#endif ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++int saa716x_spi_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct spi_master *master; ++ struct saa716x_spi_state *saa716x_spi; ++ int ret; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ master = spi_alloc_master(&pdev->dev, sizeof (struct saa716x_spi_state)); ++ if (master == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Cannot allocate SPI Master!"); ++ return -ENOMEM; ++ } ++ ++ saa716x_spi = spi_master_get_devdata(master); ++ saa716x_spi->master = master; ++ saa716x_spi->saa716x = saa716x; ++ saa716x->saa716x_spi = saa716x_spi; ++ ++ master->bus_num = pdev->bus->number; ++ master->num_chipselect = 1; /* TODO! use config */ ++ master->cleanup = saa716x_spi_cleanup; ++ master->setup = saa716x_spi_setup; ++ master->transfer = saa716x_spi_transfer; ++ ++ ret = spi_register_master(master); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: registering SPI Master!"); ++ goto err; ++ } ++err: ++ spi_master_put(master); ++ return ret; ++} ++EXPORT_SYMBOL(saa716x_spi_init); ++ ++void saa716x_spi_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_spi_state *saa716x_spi = saa716x->saa716x_spi; ++ ++ spi_unregister_master(saa716x_spi->master); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x SPI succesfully removed", saa716x->pdev->device); ++} ++EXPORT_SYMBOL(saa716x_spi_exit); ++#endif ++ +diff --git a/drivers/media/pci/saa716x/saa716x_spi.h b/drivers/media/pci/saa716x/saa716x_spi.h +new file mode 100644 +index 0000000..0060c22 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_spi.h +@@ -0,0 +1,23 @@ ++#ifndef __SAA716x_SPI_H ++#define __SAA716x_SPI_H ++ ++struct saa716x_dev; ++ ++struct saa716x_spi_config { ++ u8 clk_count; ++ u8 clk_pol:1; ++ u8 clk_pha:1; ++ u8 LSB_first:1; ++}; ++ ++struct saa716x_spi_state { ++ struct spi_master *master; ++ struct saa716x_dev *saa716x; ++}; ++ ++extern void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length); ++ ++extern int saa716x_spi_init(struct saa716x_dev *saa716x); ++extern void saa716x_spi_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_SPI_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_spi_reg.h b/drivers/media/pci/saa716x/saa716x_spi_reg.h +new file mode 100644 +index 0000000..c51abce +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_spi_reg.h +@@ -0,0 +1,27 @@ ++#ifndef __SAA716x_SPI_REG_H ++#define __SAA716x_SPI_REG_H ++ ++/* -------------- SPI Registers -------------- */ ++ ++#define SPI_CONTROL_REG 0x000 ++#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) ++#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) ++#define SPI_MODE_SELECT (0x00000001 << 5) ++#define SPI_CLOCK_POLARITY (0x00000001 << 4) ++#define SPI_CLOCK_PHASE (0x00000001 << 3) ++ ++#define SPI_STATUS 0x004 ++#define SPI_TRANSFER_FLAG (0x00000001 << 7) ++#define SPI_WRITE_COLLISSION (0x00000001 << 6) ++#define SPI_READ_OVERRUN (0x00000001 << 5) ++#define SPI_MODE_FAULT (0x00000001 << 4) ++#define SPI_SLAVE_ABORT (0x00000001 << 3) ++ ++#define SPI_DATA 0x008 ++#define SPI_BIDI_DATA (0x000000ff << 0) ++ ++#define SPI_CLOCK_COUNTER 0x00c ++#define SPI_CLOCK (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_SPI_REG_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_vip.c b/drivers/media/pci/saa716x/saa716x_vip.c +new file mode 100644 +index 0000000..641a104 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_vip.c +@@ -0,0 +1,401 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_vip_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_priv.h" ++ ++ ++static const u32 vi_ch[] = { ++ VI0, ++ VI1 ++}; ++ ++static const u32 msi_int_tagack[] = { ++ MSI_INT_TAGACK_VI0_0, ++ MSI_INT_TAGACK_VI0_1, ++ MSI_INT_TAGACK_VI0_2, ++ MSI_INT_TAGACK_VI1_0, ++ MSI_INT_TAGACK_VI1_1, ++ MSI_INT_TAGACK_VI1_2 ++}; ++ ++static const u32 msi_int_avint[] = { ++ MSI_INT_AVINT_VI0, ++ MSI_INT_AVINT_VI1 ++}; ++ ++void saa716x_vipint_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, INT_ENABLE, 0); /* disable VI 0 IRQ */ ++ SAA716x_EPWR(VI1, INT_ENABLE, 0); /* disable VI 1 IRQ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++} ++EXPORT_SYMBOL_GPL(saa716x_vipint_disable); ++ ++void saa716x_vip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, VIP_POWER_DOWN, VI_PWR_DWN); ++ SAA716x_EPWR(VI1, VIP_POWER_DOWN, VI_PWR_DWN); ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_disable); ++ ++int saa716x_vip_get_write_index(struct saa716x_dev *saa716x, int port) ++{ ++ u32 buf_mode, val; ++ ++ buf_mode = BAM_DMA_BUF_MODE(saa716x->vip[port].dma_channel[0]); ++ ++ val = SAA716x_EPRD(BAM, buf_mode); ++ return (val >> 3) & 0x7; ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_get_write_index); ++ ++static int saa716x_vip_init_ptables(struct saa716x_dmabuf *dmabuf, int channel, ++ struct vip_stream_params *stream_params) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ u32 config, i; ++ ++ for (i = 0; i < VIP_BUFFERS; i++) ++ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); ++ ++ config = MMU_DMA_CONFIG(channel); /* DMACONFIGx */ ++ ++ SAA716x_EPWR(MMU, config, (VIP_BUFFERS - 1)); ++ ++ if ((stream_params->stream_flags & VIP_INTERLACED) && ++ (stream_params->stream_flags & VIP_ODD_FIELD) && ++ (stream_params->stream_flags & VIP_EVEN_FIELD)) { ++ /* In interlaced mode the same buffer is written twice, once ++ the odd field and once the even field */ ++ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ } else { ++ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ ++ } ++ return 0; ++} ++ ++static int saa716x_vip_setparams(struct saa716x_dev *saa716x, int port, ++ struct vip_stream_params *stream_params) ++{ ++ u32 vi_port, buf_mode, mid, val, i; ++ u8 dma_channel; ++ u32 num_pages; ++ u32 start_x, start_line, end_line, num_lines; ++ u32 base_address, base_offset, pitch; ++ u32 vin_format; ++ ++ vi_port = vi_ch[port]; ++ buf_mode = BAM_DMA_BUF_MODE(saa716x->vip[port].dma_channel[0]); ++ dma_channel = saa716x->vip[port].dma_channel[0]; ++ ++ /* number of pages needed for a buffer */ ++ num_pages = (stream_params->bits / 8 * stream_params->samples ++ * stream_params->lines) / SAA716x_PAGE_SIZE; ++ /* check if these will fit into one page table */ ++ if (num_pages > (SAA716x_PAGE_SIZE / 8)) ++ saa716x->vip[port].dual_channel = 1; ++ else ++ saa716x->vip[port].dual_channel = 0; ++ ++ /* Reset DMA channel */ ++ SAA716x_EPWR(BAM, buf_mode, 0x00000040); ++ saa716x_vip_init_ptables(saa716x->vip[port].dma_buf[0], ++ saa716x->vip[port].dma_channel[0], ++ stream_params); ++ if (saa716x->vip[port].dual_channel) ++ saa716x_vip_init_ptables(saa716x->vip[port].dma_buf[1], ++ saa716x->vip[port].dma_channel[1], ++ stream_params); ++ ++ /* get module ID */ ++ mid = SAA716x_EPRD(vi_port, VI_MODULE_ID); ++ if (mid != 0x11A5100) { ++ dprintk(SAA716x_ERROR, 1, "VIP Id<%04x> is not supported", mid); ++ return -1; ++ } ++ ++ start_x = stream_params->offset_x; ++ start_line = stream_params->offset_y + 1; ++ end_line = 0; ++ num_lines = stream_params->lines; ++ pitch = stream_params->pitch; ++ base_address = saa716x->vip[port].dma_channel[0] << 21; ++ base_offset = 0; ++ vin_format = 0x00004000; ++ ++ if ((stream_params->stream_flags & VIP_INTERLACED) && ++ (stream_params->stream_flags & VIP_ODD_FIELD) && ++ (stream_params->stream_flags & VIP_EVEN_FIELD)) { ++ num_lines /= 2; ++ pitch *= 2; ++ base_offset = stream_params->pitch; ++ } ++ if (stream_params->stream_flags & VIP_HD) { ++ if (stream_params->stream_flags & VIP_INTERLACED) { ++ vin_format |= 0x01000000; ++ } else { ++ /* suppress the windower break message */ ++ vin_format |= 0x01000200; ++ } ++ } ++ if (stream_params->stream_flags & VIP_NO_SCALER) { ++ vin_format |= 0x00000400; ++ } ++ ++ end_line = stream_params->offset_y + num_lines; ++ ++ /* set device to normal operation */ ++ SAA716x_EPWR(vi_port, VIP_POWER_DOWN, 0); ++ /* disable ANC bit detection */ ++ SAA716x_EPWR(vi_port, ANC_DID_FIELD0, 0); ++ SAA716x_EPWR(vi_port, ANC_DID_FIELD1, 0); ++ /* set line threshold to 0 (interrupt is disabled anyway)*/ ++ SAA716x_EPWR(vi_port, VI_LINE_THRESH, 0); ++ ++ vin_format |= 2; ++ SAA716x_EPWR(vi_port, VIN_FORMAT, vin_format); ++ ++ /* disable dithering */ ++ SAA716x_EPWR(vi_port, PRE_DIT_CTRL, 0); ++ SAA716x_EPWR(vi_port, POST_DIT_CTRL, 0); ++ /* set alpha value */ ++ SAA716x_EPWR(vi_port, CSM_CKEY, 0); ++ ++ SAA716x_EPWR(vi_port, WIN_XYSTART, (start_x << 16) + start_line); ++ SAA716x_EPWR(vi_port, WIN_XYEND, ++ ((start_x + stream_params->samples - 1) << 16) + end_line); ++ ++ /* enable cropping to assure that VIP does not exceed buffer boundaries */ ++ SAA716x_EPWR(vi_port, PSU_WINDOW, ++ (stream_params->samples << 16) + num_lines); ++ /* set packet YUY2 output format */ ++ SAA716x_EPWR(vi_port, PSU_FORMAT, 0x800000A1); ++ ++ SAA716x_EPWR(vi_port, PSU_BASE1, base_address); ++ SAA716x_EPWR(vi_port, PSU_PITCH1, pitch); ++ SAA716x_EPWR(vi_port, PSU_PITCH2, 0); ++ SAA716x_EPWR(vi_port, PSU_BASE2, 0); ++ SAA716x_EPWR(vi_port, PSU_BASE3, 0); ++ SAA716x_EPWR(vi_port, PSU_BASE4, base_address + base_offset); ++ SAA716x_EPWR(vi_port, PSU_BASE5, 0); ++ SAA716x_EPWR(vi_port, PSU_BASE6, 0); ++ ++ /* monitor BAM reset */ ++ i = 0; ++ val = SAA716x_EPRD(BAM, buf_mode); ++ while (val && (i < 100)) { ++ msleep(30); ++ val = SAA716x_EPRD(BAM, buf_mode); ++ i++; ++ } ++ if (val) { ++ dprintk(SAA716x_ERROR, 1, "Error: BAM VIP Reset failed!"); ++ return -EIO; ++ } ++ ++ /* set buffer count */ ++ SAA716x_EPWR(BAM, buf_mode, VIP_BUFFERS - 1); ++ /* initialize all available address offsets to 0 */ ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_0(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_1(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_2(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_3(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_4(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_5(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_6(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_7(dma_channel), 0x0); ++ ++ if (saa716x->vip[port].dual_channel) { ++ buf_mode = BAM_DMA_BUF_MODE(saa716x->vip[port].dma_channel[1]); ++ dma_channel = saa716x->vip[port].dma_channel[1]; ++ ++ /* set buffer count */ ++ SAA716x_EPWR(BAM, buf_mode, VIP_BUFFERS - 1); ++ /* initialize all available address offsets to 0 */ ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_0(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_1(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_2(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_3(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_4(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_5(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_6(dma_channel), 0x0); ++ SAA716x_EPWR(BAM, BAM_ADDR_OFFSET_7(dma_channel), 0x0); ++ } ++ ++ return 0; ++} ++ ++int saa716x_vip_start(struct saa716x_dev *saa716x, int port, int one_shot, ++ struct vip_stream_params *stream_params) ++{ ++ u32 vi_port; ++ u32 config1; ++ u32 config2; ++ u32 val; ++ u32 i; ++ ++ vi_port = vi_ch[port]; ++ config1 = MMU_DMA_CONFIG(saa716x->vip[port].dma_channel[0]); ++ config2 = MMU_DMA_CONFIG(saa716x->vip[port].dma_channel[1]); ++ ++ if (saa716x_vip_setparams(saa716x, port, stream_params) != 0) { ++ return -EIO; ++ } ++ ++ val = SAA716x_EPRD(MMU, config1); ++ SAA716x_EPWR(MMU, config1, val & ~0x40); ++ SAA716x_EPWR(MMU, config1, val | 0x40); ++ if (saa716x->vip[port].dual_channel) { ++ val = SAA716x_EPRD(MMU, config2); ++ SAA716x_EPWR(MMU, config2, val & ~0x40); ++ SAA716x_EPWR(MMU, config2, val | 0x40); ++ } ++ ++ SAA716x_EPWR(vi_port, INT_ENABLE, 0x33F); ++ ++ i = 0; ++ while (i < 500) { ++ val = SAA716x_EPRD(MMU, config1); ++ if (saa716x->vip[port].dual_channel) ++ val &= SAA716x_EPRD(MMU, config2); ++ if (val & 0x80) ++ break; ++ msleep(10); ++ i++; ++ } ++ ++ if (!(val & 0x80)) { ++ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); ++ return -EIO; ++ } ++ ++ /* enable video capture path */ ++ val = SAA716x_EPRD(vi_port, VI_MODE); ++ val &= ~(VID_CFEN | VID_FSEQ | VID_OSM); ++ ++ if ((stream_params->stream_flags & VIP_INTERLACED) && ++ (stream_params->stream_flags & VIP_ODD_FIELD) && ++ (stream_params->stream_flags & VIP_EVEN_FIELD)) { ++ val |= VID_CFEN_BOTH; /* capture both fields */ ++ val |= VID_FSEQ; /* start capture with odd field */ ++ } else { ++ val |= VID_CFEN_BOTH; /* capture both fields */ ++ } ++ ++ if (one_shot) ++ val |= VID_OSM; /* stop capture after receiving one frame */ ++ ++ saa716x_set_clk_external(saa716x, saa716x->vip[port].dma_channel[0]); ++ ++ SAA716x_EPWR(vi_port, VI_MODE, val); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_start); ++ ++int saa716x_vip_stop(struct saa716x_dev *saa716x, int port) ++{ ++ u32 val; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); ++ ++ /* disable capture */ ++ val = SAA716x_EPRD(vi_ch[port], VI_MODE); ++ val &= ~VID_CFEN; ++ SAA716x_EPWR(vi_ch[port], VI_MODE, val); ++ ++ saa716x_set_clk_internal(saa716x, saa716x->vip[port].dma_channel[0]); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_stop); ++ ++int saa716x_vip_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)) ++{ ++ int n; ++ int i; ++ int ret; ++ ++ /* reset VI */ ++ SAA716x_EPWR(vi_ch[port], VI_MODE, SOFT_RESET); ++ ++ for (n = 0; n < 2; n++) ++ { ++ saa716x->vip[port].dma_channel[n] = port * 3 + n; ++ for (i = 0; i < VIP_BUFFERS; i++) ++ { ++ ret = saa716x_dmabuf_alloc( ++ saa716x, ++ &saa716x->vip[port].dma_buf[n][i], ++ 512 * SAA716x_PAGE_SIZE); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ } ++ saa716x->vip[port].saa716x = saa716x; ++ tasklet_init(&saa716x->vip[port].tasklet, worker, ++ (unsigned long)&saa716x->vip[port]); ++ saa716x->vip[port].read_index = 0; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_init); ++ ++int saa716x_vip_exit(struct saa716x_dev *saa716x, int port) ++{ ++ int n; ++ int i; ++ ++ tasklet_kill(&saa716x->vip[port].tasklet); ++ for (n = 0; n < 2; n++) ++ { ++ for (i = 0; i < VIP_BUFFERS; i++) ++ { ++ saa716x_dmabuf_free( ++ saa716x, &saa716x->vip[port].dma_buf[n][i]); ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_exit); +diff --git a/drivers/media/pci/saa716x/saa716x_vip.h b/drivers/media/pci/saa716x/saa716x_vip.h +new file mode 100644 +index 0000000..b81da96 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_vip.h +@@ -0,0 +1,58 @@ ++#ifndef __SAA716x_VIP_H ++#define __SAA716x_VIP_H ++ ++#include "saa716x_dma.h" ++ ++#define VIP_BUFFERS 8 ++ ++/* ++ * Stream port flags ++ */ ++enum vip_stream_flags { ++ VIP_ODD_FIELD = 0x0001, ++ VIP_EVEN_FIELD = 0x0002, ++ VIP_INTERLACED = 0x0004, ++ VIP_HD = 0x0010, ++ VIP_NO_SCALER = 0x0100 ++}; ++ ++/* ++ * Stream port parameters ++ * bits: Bits per sample ++ * samples: samples perline ++ * lines: number of lines ++ * pitch: stream pitch in bytes ++ * offset_x: offset to first valid pixel ++ * offset_y: offset to first valid line ++ */ ++struct vip_stream_params { ++ u32 bits; ++ u32 samples; ++ u32 lines; ++ s32 pitch; ++ u32 offset_x; ++ u32 offset_y; ++ enum vip_stream_flags stream_flags; ++}; ++ ++struct saa716x_vip_stream_port { ++ u8 dual_channel; ++ u8 read_index; ++ u8 dma_channel[2]; ++ struct saa716x_dmabuf dma_buf[2][VIP_BUFFERS]; ++ struct saa716x_dev *saa716x; ++ struct tasklet_struct tasklet; ++}; ++ ++extern void saa716x_vipint_disable(struct saa716x_dev *saa716x); ++extern void saa716x_vip_disable(struct saa716x_dev *saa716x); ++extern int saa716x_vip_get_write_index(struct saa716x_dev *saa716x, int port); ++extern int saa716x_vip_start(struct saa716x_dev *saa716x, int port, ++ int one_shot, ++ struct vip_stream_params *stream_params); ++extern int saa716x_vip_stop(struct saa716x_dev *saa716x, int port); ++extern int saa716x_vip_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)); ++extern int saa716x_vip_exit(struct saa716x_dev *saa716x, int port); ++ ++#endif /* __SAA716x_VIP_H */ +diff --git a/drivers/media/pci/saa716x/saa716x_vip_reg.h b/drivers/media/pci/saa716x/saa716x_vip_reg.h +new file mode 100644 +index 0000000..b064c35 +--- /dev/null ++++ b/drivers/media/pci/saa716x/saa716x_vip_reg.h +@@ -0,0 +1,141 @@ ++#ifndef __SAA716x_VIP_REG_H ++#define __SAA716x_VIP_REG_H ++ ++/* -------------- VIP Registers -------------- */ ++ ++#define VI_MODE 0x000 ++#define VID_CFEN (0x00000003 << 30) ++#define VID_CFEN_ODD (0x00000001 << 30) ++#define VID_CFEN_EVEN (0x00000002 << 30) ++#define VID_CFEN_BOTH (0x00000003 << 30) ++#define VID_OSM (0x00000001 << 29) ++#define VID_FSEQ (0x00000001 << 28) ++#define AUX_CFEN (0x00000003 << 26) ++#define AUX_OSM (0x00000001 << 25) ++#define AUX_FSEQ (0x00000001 << 24) ++#define AUX_ANC_DATA (0x00000003 << 22) ++#define AUX_ANC_RAW (0x00000001 << 21) ++#define RST_ON_ERR (0x00000001 << 17) ++#define SOFT_RESET (0x00000001 << 16) ++#define IFF_CLAMP (0x00000001 << 14) ++#define IFF_MODE (0x00000003 << 12) ++#define DFF_CLAMP (0x00000001 << 10) ++#define DFF_MODE (0x00000003 << 8) ++#define HSP_CLAMP (0x00000001 << 3) ++#define HSP_RGB (0x00000001 << 2) ++#define HSP_MODE (0x00000003 << 0) ++ ++#define ANC_DID_FIELD0 0x020 ++#define VI_ID_MASK_0 (0x000000ff << 8) ++#define VI_DATA_ID_0 (0x000000ff << 0) ++ ++#define ANC_DID_FIELD1 0x024 ++#define VI_ID_MASK_1 (0x000000ff << 8) ++#define VI_DATA_ID_1 (0x000000ff << 0) ++ ++#define VI_LINE_THRESH 0x040 ++#define VI_LCTHR (0x000007ff << 0) ++ ++#define VIN_FORMAT 0x100 ++#define VI_VSRA (0x00000003 << 30) ++#define VI_SYNCHD (0x00000001 << 25) ++#define VI_DUAL_STREAM (0x00000001 << 24) ++#define VI_NHDAUX (0x00000001 << 20) ++#define VI_NPAR (0x00000001 << 19) ++#define VI_VSEL (0x00000003 << 14) ++#define VI_TWOS (0x00000001 << 13) ++#define VI_TPG (0x00000001 << 12) ++#define VI_FREF (0x00000001 << 10) ++#define VI_FTGL (0x00000001 << 9) ++#define VI_SF (0x00000001 << 3) ++#define VI_FZERO (0x00000001 << 2) ++#define VI_REVS (0x00000001 << 1) ++#define VI_REHS (0x00000001 << 0) ++ ++#define VIN_TESTPGEN 0x104 ++ ++#define WIN_XYSTART 0x140 ++#define WIN_XYEND 0x144 ++ ++#define PRE_DIT_CTRL 0x160 ++#define POST_DIT_CTRL 0x164 ++ ++#define AUX_XYSTART 0x180 ++#define AUX_XYEND 0x184 ++ ++#define CSM_CKEY 0x284 ++ ++#define PSU_FORMAT 0x300 ++#define PSU_WINDOW 0x304 ++#define PSU_BASE1 0x340 ++#define PSU_PITCH1 0x344 ++#define PSU_BASE2 0x348 ++#define PSU_PITCH2 0x34c ++#define PSU_BASE3 0x350 ++#define PSU_BASE4 0x354 ++#define PSU_BASE5 0x358 ++#define PSU_BASE6 0x35c ++ ++#define AUX_FORMAT 0x380 ++#define AUX_BASE 0x390 ++#define AUX_PITCH 0x394 ++ ++#define INT_STATUS 0xfe0 ++#define VI_STAT_FID_AUX (0x00000001 << 31) ++#define VI_STAT_FID_VID (0x00000001 << 30) ++#define VI_STAT_FID_VPI (0x00000001 << 29) ++#define VI_STAT_LINE_COUNT (0x00000fff << 16) ++#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) ++#define VI_STAT_VID_OVRFLW (0x00000001 << 8) ++#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) ++#define VI_STAT_FID_SEQBRK (0x00000001 << 6) ++#define VI_STAT_LINE_THRESH (0x00000001 << 5) ++#define VI_STAT_AUX_WRAP (0x00000001 << 4) ++#define VI_STAT_AUX_START_IN (0x00000001 << 3) ++#define VI_STAT_AUX_END_OUT (0x00000001 << 2) ++#define VI_STAT_VID_START_IN (0x00000001 << 1) ++#define VI_STAT_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) ++#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) ++#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) ++#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) ++#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) ++#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) ++#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) ++#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) ++#define VI_ENABLE_VID_START_IN (0x00000001 << 1) ++#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define VIP_POWER_DOWN 0xff4 ++#define VI_PWR_DWN (0x00000001 << 31) ++ ++#define VI_MODULE_ID 0xffc ++ ++ ++#endif /* __SAA716x_VIP_REG_H */ +diff --git a/drivers/media/pci/saa716x/tbs-ci.c b/drivers/media/pci/saa716x/tbs-ci.c +new file mode 100644 +index 0000000..c85dbbd +--- /dev/null ++++ b/drivers/media/pci/saa716x/tbs-ci.c +@@ -0,0 +1,556 @@ ++/* ++ TurboSight TBS CI driver ++ Copyright (C) 2011 Konstantin Dimitrov ++ ++ Copyright (C) 2011 TurboSight.com ++*/ ++ ++#include "tbs-ci.h" ++ ++#define TBSCI_I2C_ADDR 0x1a ++ ++struct tbsci_state { ++ struct dvb_ca_en50221 ca; ++ struct mutex ca_mutex; ++ struct i2c_adapter *i2c_adap; ++ int nr, mode; ++ void *priv; /* struct saa716x_adapter *priv; */ ++ int status; ++}; ++ ++int tbsci_i2c_read(struct tbsci_state *state) ++{ ++ int ret; ++ u8 buf = 0; ++ ++ struct i2c_msg msg = { .addr = TBSCI_I2C_ADDR, .flags = I2C_M_RD, ++ .buf = &buf, .len = 1 }; ++ ++ if (((state->mode == 2) || (state->mode == 4) || ++ (state->mode == 6) || (state->mode == 8) || (state->mode == 9)) ++ && (state->nr == 1)) ++ msg.addr += 1; ++ ++ if (state->mode == 10) ++ msg.addr += 2; ++ ++ ret = i2c_transfer(state->i2c_adap, &msg, 1); ++ ++ if (ret != 1) { ++ printk("tbsci: read error=%d\n", ret); ++ return -EREMOTEIO; ++ } ++ ++ return buf; ++}; ++ ++int tbsci_i2c_write(struct tbsci_state *state, ++ u8 addr, u8* data, int len) ++{ ++ int ret; ++ unsigned char buf[len + 1]; ++ ++ struct i2c_msg msg = { .addr = TBSCI_I2C_ADDR, .flags = 0, ++ .buf = &buf[0], .len = len + 1 }; ++ ++ if (((state->mode == 2) || (state->mode == 4) || ++ (state->mode == 6) || (state->mode == 8) || (state->mode == 9)) ++ && (state->nr == 1)) ++ msg.addr += 1; ++ ++ if (state->mode == 10) ++ msg.addr += 2; ++ ++ memcpy(&buf[1], data, len); ++ buf[0] = addr; ++ ++ ret = i2c_transfer(state->i2c_adap, &msg, 1); ++ ++ if (ret != 1) { ++ printk("tbsci: error=%d\n", ret); ++ return -EREMOTEIO; ++ } ++ ++ return 0; ++}; ++ ++int tbsci_read_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, u8 address) ++{ ++ struct tbsci_state *state = ca->data; ++ int ret; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data = (address & 3); ++ ret = tbsci_i2c_write(state, 0x80, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return data; ++} ++ ++int tbsci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct tbsci_state *state = ca->data; ++ int ret; ++ unsigned char data[2]; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data[0] = (address & 3); ++ data[1] = value; ++ ret = tbsci_i2c_write(state, 0x80, data, 2); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++int tbsci_read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct tbsci_state *state = ca->data; ++ int ret; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data = (address & 0xff); ++ ret = tbsci_i2c_write(state, ++ ((address >> 8) & 0x7f), &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return data; ++} ++ ++int tbsci_write_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address, u8 value) ++{ ++ struct tbsci_state *state = ca->data; ++ int ret; ++ unsigned char data[2]; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data[0] = (address & 0xff); ++ data[1] = value; ++ ret = tbsci_i2c_write(state, ++ ((address >> 8) & 0x7f), data, 2); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbsci_set_video_port(struct dvb_ca_en50221 *ca, ++ int slot, int enable) ++{ ++ struct tbsci_state *state = ca->data; ++ struct saa716x_adapter *adap = state->priv; ++ struct saa716x_dev *saa716x = adap->saa716x; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ switch (state->mode) { ++ case 0: ++ case 1: ++ saa716x_gpio_set_output(saa716x, ++ state->nr ? 16 : 17); ++ msleep(1); ++ saa716x_gpio_write(saa716x, ++ state->nr ? 16 : 17, (enable & 1)); ++ msleep(100); ++ break; ++ case 2: ++ saa716x_gpio_set_output(saa716x, ++ state->nr ? 6 : 16); ++ msleep(1); ++ saa716x_gpio_write(saa716x, ++ state->nr ? 6 : 16, (enable & 1)); ++ msleep(100); ++ break; ++ case 3: ++ case 4: ++ case 5: ++ case 6: ++ case 7: ++ case 8: ++ case 9: ++ data = enable & 1; ++ tbsci_i2c_write(state, 0xc0, &data, 1); ++ break; ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ printk("tbsci: Adapter %d CI slot %sabled\n", ++ adap->fe->dvb->num, ++ enable ? "en" : "dis"); ++ ++ return 0; ++} ++ ++int tbsci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbsci_set_video_port(ca, slot, /* enable */ 0); ++} ++ ++int tbsci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbsci_set_video_port(ca, slot, /* enable */ 1); ++} ++ ++int tbsci_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct tbsci_state *state = ca->data; ++ int ret; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock (&state->ca_mutex); ++ ++ data = 1; ++ ret = tbsci_i2c_write(state, 0xc1, &data, 1); ++ msleep (5); ++ ++ data = 0; ++ ret = tbsci_i2c_write(state, 0xc1, &data, 1); ++ msleep (1400); ++ ++ mutex_unlock (&state->ca_mutex); ++ ++ if (ret != 0) ++ return ret; ++ ++ return 0; ++} ++ ++int tbsci_poll_slot_status(struct dvb_ca_en50221 *ca, ++ int slot, int open) ++{ ++ struct tbsci_state *state = ca->data; ++ struct saa716x_adapter *adap = state->priv; ++ struct saa716x_dev *saa716x = adap->saa716x; ++ unsigned char data, value; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ switch (state->mode) { ++ case 0: ++ data = 0; ++ tbsci_i2c_write(state, 0xc0, &data, 1); ++ data = tbsci_i2c_read(state); ++ break; ++ case 1: ++ case 2: ++ data = 0; ++ tbsci_i2c_write(state, 0xc2, &data, 1); ++ data = tbsci_i2c_read(state); ++ break; ++ case 3: ++ data = saa716x_gpio_read(saa716x, 3); ++ if (data != saa716x_gpio_read(saa716x, 5)) ++ data = 0; ++ else ++ data ^= 1; ++ break; ++ case 4: ++ data = saa716x_gpio_read(saa716x, state->nr ? 3 : 14); ++ if (data != saa716x_gpio_read(saa716x, state->nr ? 6 : 2)) ++ data = 0; ++ else ++ data ^= 1; ++ break; ++ case 5: ++ data = saa716x_gpio_read(saa716x, 6); ++ if (data != saa716x_gpio_read(saa716x, 14)) ++ data = 0; ++ else ++ data ^= 1; ++ break; ++ case 6: ++ data = saa716x_gpio_read(saa716x, state->nr ? 17 : 5); ++ if (data != saa716x_gpio_read(saa716x, state->nr ? 16 : 6)) ++ data = 0; ++ else ++ data ^= 1; ++ break; ++ case 7: ++ data = saa716x_gpio_read(saa716x, 3); ++ if (data != saa716x_gpio_read(saa716x, 5)) { ++ data = 0; ++ } else { ++ data ^= 1; ++ } ++ ++ if (state->status != data){ ++ value = !data; ++ tbsci_i2c_write(state, 0xc3, &value, 1); ++ saa716x_gpio_write(saa716x, 6, value); ++ msleep(300); ++ state->status = data; ++ } ++ ++ break; ++ case 8: ++ case 9: ++ data = saa716x_gpio_read(saa716x, state->nr ? 6 : 2); ++ if (data != saa716x_gpio_read(saa716x, state->nr ? 3 : 14)) { ++ data = 0; ++ } else { ++ data ^= 1; ++ } ++ ++ if (state->status != data) ++ { ++ value = !data; ++ saa716x_gpio_write(saa716x, state->nr ? 17 : 20, value); ++ msleep(300); ++ state->status = data; ++ } ++ break; ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (data & 1) { ++ return (DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY); ++ } else { ++ return 0; ++ } ++} ++ ++int tbsci_init(struct saa716x_adapter *adap, int tbsci_nr, int tbsci_mode) ++{ ++ struct tbsci_state *state; ++ int ret; ++ unsigned char data; ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct tbsci_state), GFP_KERNEL); ++ if (state == NULL) { ++ ret = -ENOMEM; ++ goto error1; ++ } ++ ++ adap->adap_priv = state; ++ ++ state->nr = tbsci_nr; ++ state->mode = tbsci_mode; ++ state->status = 0; ++ ++ mutex_init(&state->ca_mutex); ++ ++ state->i2c_adap = &adap->tbsci->adap; ++ state->ca.owner = THIS_MODULE; ++ state->ca.read_attribute_mem = tbsci_read_attribute_mem; ++ state->ca.write_attribute_mem = tbsci_write_attribute_mem; ++ state->ca.read_cam_control = tbsci_read_cam_control; ++ state->ca.write_cam_control = tbsci_write_cam_control; ++ state->ca.slot_reset = tbsci_slot_reset; ++ state->ca.slot_shutdown = tbsci_slot_shutdown; ++ state->ca.slot_ts_enable = tbsci_slot_ts_enable; ++ state->ca.poll_slot_status = tbsci_poll_slot_status; ++ state->ca.data = state; ++ state->priv = adap; ++ ++ if ((state->mode != 0) && (state->mode != 10)) { ++ data = 1; ++ tbsci_i2c_write(state, 0xc2, &data, 1); ++ data = tbsci_i2c_read(state); ++ switch (data) { ++ case 0x55: ++ printk("tbsci: Initializing TBS 6928 v11 CI slot\n"); ++ break; ++ case 0x56: ++ case 0x58: ++ printk("tbsci: Initializing TBS 6991 v11 CI %d slot\n", ++ tbsci_nr); ++ break; ++ case 0x60: ++ if (state->mode != 5) { ++ printk("tbsci: Initializing TBS 6928 v12 CI slot\n"); ++ state->mode = 3; ++ ++ data = 0; ++ tbsci_i2c_write(state, 0xd0, &data, 1); ++ ++ tbsci_i2c_write(state, 0xcc, &data, 1); ++ tbsci_i2c_write(state, 0xcd, &data, 1); ++ ++ data = 2; ++ tbsci_i2c_write(state, 0xce, &data, 1); ++ } else { ++ printk("tbsci: Initializing TBS 6618 CI slot\n"); ++ } ++ break; ++ case 0x62: ++ printk("tbsci: Initializing TBS 6928SE CI slot\n"); ++ state->mode = 7; ++ break; ++ case 0x66: ++ case 0x68: ++ if (state->mode == 8){ ++ printk("tbsci: Initializing TBS 6991SE CI %d slot\n", ++ tbsci_nr); ++ //Fix Data Rate ++ data = 0; ++ tbsci_i2c_write(state, 0xd0, &data, 1); ++ ++ data = 1; ++ tbsci_i2c_write(state, 0xcd, &data, 1); ++ data = 8; ++ tbsci_i2c_write(state, 0xce, &data, 1); ++ ++ data = 0; ++ tbsci_i2c_write(state, 0xcf, &data, 1); ++ ++ }else ++ if (state->mode == 9) { ++ printk("tbsci: Initializing TBS 6290 CI %d slot\n", ++ tbsci_nr); ++ } else { ++ if (state->mode != 6) { ++ printk("tbsci: Initializing TBS 6991 v13 CI %d slot\n", ++ tbsci_nr); ++ state->mode = 4; ++ ++ data = 0; ++ tbsci_i2c_write(state, 0xd0, &data, 1); ++ data = 1; ++ tbsci_i2c_write(state, 0xcc, &data, 1); ++ data = 0; ++ tbsci_i2c_write(state, 0xcd, &data, 1); ++ ++ data = 2; ++ tbsci_i2c_write(state, 0xce, &data, 1); ++ } else { ++ printk("tbsci: Initializing TBS 6680 CI %d slot\n", ++ tbsci_nr); ++ }} ++ break; ++ default: ++ ret = -EREMOTEIO; ++ goto error2; ++ } ++ } ++ ++ if (state->mode == 10) { ++ data = 0xc0; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ data = 0x01; ++ tbsci_i2c_write(state, 0xc0, &data, 1); ++ ++ data = 0xc0; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ data = 0xc1; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ data = 0x01; ++ tbsci_i2c_write(state, 0xc1, &data, 1); ++ ++ data = 0xc1; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ data = 0xc2; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ data = 0x01; ++ tbsci_i2c_write(state, 0xc2, &data, 1); ++ ++ data = 0xc2; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ data = 0xc3; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ data = 0x01; ++ tbsci_i2c_write(state, 0xc3, &data, 1); ++ ++ data = 0xc3; ++ tbsci_i2c_write(state, 0x40, &data, 1); ++ data = tbsci_i2c_read(state); ++ ++ return 0; ++ } ++ ++ ret = dvb_ca_en50221_init(&adap->dvb_adapter, &state->ca, ++ /* flags */ 0, /* n_slots */ 1); ++ if (ret != 0) goto error2; ++ ++ printk("tbsci: Adapter %d CI slot initialized\n", adap->dvb_adapter.num); ++ ++ return 0; ++ ++error2: ++ //memset (&state->ca, 0, sizeof (state->ca)); ++ kfree(state); ++error1: ++ printk("tbsci: Adapter %d CI slot initialization failed\n", adap->dvb_adapter.num); ++ return ret; ++} ++ ++void tbsci_release(struct saa716x_adapter *adap) ++{ ++ struct tbsci_state *state; ++ ++ if (NULL == adap) return; ++ ++ state = (struct tbsci_state *)adap->adap_priv; ++ if (NULL == state) return; ++ ++ if (NULL == state->ca.data) return; ++ ++ dvb_ca_en50221_release(&state->ca); ++ //memset(&state->ca, 0, sizeof(state->ca)); ++ kfree(state); ++} +diff --git a/drivers/media/pci/saa716x/tbs-ci.h b/drivers/media/pci/saa716x/tbs-ci.h +new file mode 100644 +index 0000000..b81ecf1 +--- /dev/null ++++ b/drivers/media/pci/saa716x/tbs-ci.h +@@ -0,0 +1,37 @@ ++/* ++ TurboSight TBS CI driver ++ Copyright (C) 2011 Konstantin Dimitrov ++ ++ Copyright (C) 2011 TurboSight.com ++*/ ++ ++#ifndef TBS_CI_H ++#define TBS_CI_H ++ ++#include "saa716x_priv.h" ++#include "saa716x_gpio.h" ++#include "tbsci-i2c.h" ++ ++#include "dvb_ca_en50221.h" ++ ++extern int tbsci_read_attribute_mem(struct dvb_ca_en50221 *en50221, ++ int slot, int addr); ++extern int tbsci_write_attribute_mem(struct dvb_ca_en50221 *en50221, ++ int slot, int addr, u8 data); ++extern int tbsci_read_cam_control(struct dvb_ca_en50221 *en50221, ++ int slot, u8 addr); ++extern int tbsci_write_cam_control(struct dvb_ca_en50221 *en50221, ++ int slot, u8 addr, u8 data); ++extern int tbsci_slot_reset(struct dvb_ca_en50221 *en50221, ++ int slot); ++extern int tbsci_slot_shutdown(struct dvb_ca_en50221 *en50221, ++ int slot); ++extern int tbsci_slot_ts_enable(struct dvb_ca_en50221 *en50221, ++ int slot); ++extern int tbsci_poll_slot_status(struct dvb_ca_en50221 *en50221, ++ int slot, int open); ++extern int tbsci_init(struct saa716x_adapter *adap, int tbsci_nr, ++ int tbsci_mode); ++extern void tbsci_release(struct saa716x_adapter *adap); ++ ++#endif +diff --git a/drivers/media/pci/saa716x/tbsci-i2c.c b/drivers/media/pci/saa716x/tbsci-i2c.c +new file mode 100644 +index 0000000..f71f816 +--- /dev/null ++++ b/drivers/media/pci/saa716x/tbsci-i2c.c +@@ -0,0 +1,144 @@ ++/* ++ TurboSight TBS CI I2C over GPIO driver ++ Copyright (C) 2011 Konstantin Dimitrov ++ ++ Copyright (C) 2011 TurboSight.com ++*/ ++ ++#include "saa716x_priv.h" ++#include "saa716x_gpio.h" ++#include "tbsci-i2c.h" ++ ++static void tbsci_setscl(void *data, int state) ++{ ++ struct saa716x_adapter *adap = data; ++ struct saa716x_dev *saa716x = adap->saa716x; ++ struct tbsci_i2c_state *tbsci_i2c = adap->tbsci; ++ ++ saa716x_gpio_write(saa716x, tbsci_i2c->wscl, state); ++} ++ ++static void tbsci_setsda(void *data, int state) ++{ ++ struct saa716x_adapter *adap = data; ++ struct saa716x_dev *saa716x = adap->saa716x; ++ struct tbsci_i2c_state *tbsci_i2c = adap->tbsci; ++ ++ saa716x_gpio_write(saa716x, tbsci_i2c->wsda, state); ++} ++ ++static int tbsci_getscl(void *data) ++{ ++ struct saa716x_adapter *adap = data; ++ struct saa716x_dev *saa716x = adap->saa716x; ++ struct tbsci_i2c_state *tbsci_i2c = adap->tbsci; ++ u32 state; ++ ++ state = saa716x_gpio_read(saa716x, tbsci_i2c->wscl); ++ ++ return state ? 1 : 0; ++} ++ ++static int tbsci_getsda(void *data) ++{ ++ struct saa716x_adapter *adap = data; ++ struct saa716x_dev *saa716x = adap->saa716x; ++ struct tbsci_i2c_state *tbsci_i2c = adap->tbsci; ++ u32 state; ++ ++ state = saa716x_gpio_read(saa716x, tbsci_i2c->rsda); ++ ++ return state ? 1 : 0; ++} ++ ++static const struct i2c_algo_bit_data tbsci_i2c_algo_template = { ++ .setsda = tbsci_setsda, ++ .setscl = tbsci_setscl, ++ .getsda = tbsci_getsda, ++ .getscl = tbsci_getscl, ++ .udelay = 5, ++ .timeout = 200, ++}; ++ ++int tbsci_i2c_probe(struct saa716x_adapter *adap, int tbsci_i2c_nr) ++{ ++ struct saa716x_dev *saa716x = adap->saa716x; ++ struct saa716x_i2c *i2c0 = &saa716x->i2c[0]; ++ struct saa716x_i2c *i2c1 = &saa716x->i2c[1]; ++ struct tbsci_i2c_state *tbsci_i2c; ++ int ret; ++ ++ tbsci_i2c = kzalloc(sizeof(*tbsci_i2c), GFP_KERNEL); ++ if (tbsci_i2c == NULL) { ++ return -ENOMEM; ++ } ++ adap->tbsci = tbsci_i2c; ++ tbsci_i2c->nr = tbsci_i2c_nr; ++ ++ if (tbsci_i2c_nr == 3) { ++ tbsci_i2c->adap = i2c1->i2c_adapter; ++ return 0; ++ } ++ ++ if (tbsci_i2c_nr == 4) { ++ tbsci_i2c->adap = i2c0->i2c_adapter; ++ return 0; ++ } ++ ++ memcpy(&tbsci_i2c->algo, &tbsci_i2c_algo_template, ++ sizeof(tbsci_i2c->algo)); ++ ++ tbsci_i2c->adap.dev.parent = &saa716x->pdev->dev; ++ strlcpy(tbsci_i2c->adap.name, ++ tbsci_i2c_nr ? "TBSCI I2C Adapter 0" : "TBSCI I2C Adapter 1", ++ sizeof(tbsci_i2c->adap.name)); ++ tbsci_i2c->adap.owner = THIS_MODULE; ++ //tbsci_i2c->adap.id = I2C_HW_B_SAA716x; ++ tbsci_i2c->algo.data = adap; ++ i2c_set_adapdata(&tbsci_i2c->adap, saa716x); ++ tbsci_i2c->adap.algo_data = &tbsci_i2c->algo; ++ ++ if (tbsci_i2c->nr == 2) { ++ tbsci_i2c->wscl = 16; ++ tbsci_i2c->wsda = 3; ++ tbsci_i2c->rsda = 5; ++ } else { ++ tbsci_i2c->wscl = tbsci_i2c->nr ? 3 : 26; ++ tbsci_i2c->wsda = tbsci_i2c->nr ? 5 : 15; ++ tbsci_i2c->rsda = tbsci_i2c->nr ? 2 : 20; ++ } ++ ++ saa716x_gpio_set_output(saa716x, tbsci_i2c->wscl); ++ msleep(1); ++ saa716x_gpio_set_output(saa716x, tbsci_i2c->wsda); ++ msleep(1); ++ saa716x_gpio_set_input(saa716x, tbsci_i2c->rsda); ++ msleep(1); ++ ++ tbsci_setscl(adap, 1); ++ tbsci_setsda(adap, 1); ++ ++ ret = i2c_bit_add_bus(&tbsci_i2c->adap); ++ if (ret != 0) { ++ printk("tbsci_i2c: %s probe failed\n", ++ tbsci_i2c_nr ? "TBSCI I2C Adapter 0" : "TBSCI I2C Adapter 1"); ++ ++ kfree(adap->tbsci); ++ adap->tbsci = NULL; ++ } ++ ++ return ret; ++} ++ ++void tbsci_i2c_remove(struct saa716x_adapter *adap) ++{ ++ struct tbsci_i2c_state *tbsci_i2c = adap->tbsci; ++ ++ if (tbsci_i2c == NULL) ++ return; ++ ++ if ((tbsci_i2c->nr != 3) && (tbsci_i2c->nr != 4)) ++ i2c_del_adapter(&tbsci_i2c->adap); ++ ++ kfree(tbsci_i2c); ++} +diff --git a/drivers/media/pci/saa716x/tbsci-i2c.h b/drivers/media/pci/saa716x/tbsci-i2c.h +new file mode 100644 +index 0000000..7447aad +--- /dev/null ++++ b/drivers/media/pci/saa716x/tbsci-i2c.h +@@ -0,0 +1,26 @@ ++/* ++ TurboSight TBS CI I2C over GPIO driver ++ Copyright (C) 2011 Konstantin Dimitrov ++ ++ Copyright (C) 2011 TurboSight.com ++*/ ++ ++#ifndef TBSCI_I2C_H ++#define TBSCI_I2C_H ++ ++#include ++ ++//#define I2C_HW_B_SAA716x 0x12 ++ ++struct tbsci_i2c_state { ++ struct i2c_adapter adap; ++ struct i2c_algo_bit_data algo; ++ u8 wscl, wsda, rsda; ++ u32 state; ++ int nr; ++}; ++ ++extern int tbsci_i2c_probe(struct saa716x_adapter *adap, int tbsci_i2c_nr); ++extern void tbsci_i2c_remove(struct saa716x_adapter *adap); ++ ++#endif +diff --git a/drivers/media/pci/tbsecp3/Kconfig b/drivers/media/pci/tbsecp3/Kconfig +new file mode 100644 +index 0000000..998b343 +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/Kconfig +@@ -0,0 +1,11 @@ ++config DVB_TBSECP3 ++ tristate "TBS ECP3 FPGA based cards" ++ depends on DVB_CORE && PCI && I2C ++ select I2C_ALGOBIT ++ select DVB_TAS2101 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_AV201X if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Support for cards with TBS ECP3 FPGA based PCIe bridge. ++ ++ Say Y or M if you own such a device and want to use it. ++ If unsure say N. +diff --git a/drivers/media/pci/tbsecp3/Makefile b/drivers/media/pci/tbsecp3/Makefile +new file mode 100644 +index 0000000..20cb8e5 +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/Makefile +@@ -0,0 +1,9 @@ ++ ++tbsecp3-objs := tbsecp3-core.o tbsecp3-cards.o tbsecp3-i2c.o tbsecp3-dma.o tbsecp3-dvb.o tbsecp3-ca.o ++ ++obj-$(CONFIG_DVB_TBSECP3) += tbsecp3.o ++ ++ccflags-y += -Idrivers/media/tuners ++ccflags-y += -Idrivers/media/dvb-core ++ccflags-y += -Idrivers/media/dvb-frontends ++ +diff --git a/drivers/media/pci/tbsecp3/tbsecp3-ca.c b/drivers/media/pci/tbsecp3/tbsecp3-ca.c +new file mode 100644 +index 0000000..f8fe9ab +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3-ca.c +@@ -0,0 +1,278 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#include "tbsecp3.h" ++ ++static int tbsecp3_ca_rd_attr_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct tbsecp3_ca *tbsca = ca->data; ++ struct tbsecp3_adapter *adapter = tbsca->adapter; ++ struct tbsecp3_dev *dev = adapter->dev; ++ u32 data = 0; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&tbsca->lock); ++ ++ data |= (address >> 8) & 0x7f; ++ data |= (address & 0xff) << 8; ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x00, data); ++ udelay(150); ++ ++ data = tbs_read(TBSECP3_CA_BASE(tbsca->nr), 0x04); ++ ++ mutex_unlock(&tbsca->lock); ++ ++ return (data & 0xff); ++} ++ ++static int tbsecp3_ca_wr_attr_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address, u8 value) ++{ ++ struct tbsecp3_ca *tbsca = ca->data; ++ struct tbsecp3_adapter *adapter = ++ (struct tbsecp3_adapter *) tbsca->adapter; ++ struct tbsecp3_dev *dev = adapter->dev; ++ u32 data = 0; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&tbsca->lock); ++ ++ data |= (address >> 8) & 0x7f; ++ data |= (address & 0xff) << 8; ++ data |= 0x01 << 16; ++ data |= value << 24; ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x00, data); ++ udelay(150); ++ ++ mutex_unlock(&tbsca->lock); ++ ++ return 0; ++} ++ ++static int tbsecp3_ca_rd_cam_ctrl(struct dvb_ca_en50221 *ca, ++ int slot, u8 address) ++{ ++ struct tbsecp3_ca *tbsca = ca->data; ++ struct tbsecp3_adapter *adapter = ++ (struct tbsecp3_adapter *) tbsca->adapter; ++ struct tbsecp3_dev *dev = adapter->dev; ++ u32 data = 0; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&tbsca->lock); ++ ++ data |= (address & 3) << 8; ++ data |= 0x02 << 16; ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x00, data); ++ udelay(150); ++ ++ data = tbs_read(TBSECP3_CA_BASE(tbsca->nr), 0x08); ++ ++ mutex_unlock(&tbsca->lock); ++ ++ return (data & 0xff); ++} ++ ++static int tbsecp3_ca_wr_cam_ctrl(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct tbsecp3_ca *tbsca = ca->data; ++ struct tbsecp3_adapter *adapter = ++ (struct tbsecp3_adapter *) tbsca->adapter; ++ struct tbsecp3_dev *dev = adapter->dev; ++ u32 data = 0; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&tbsca->lock); ++ ++ data |= (address & 3) << 8; ++ data |= 0x03 << 16; ++ data |= value << 24; ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x00, data); ++ udelay(150); ++ ++ mutex_unlock(&tbsca->lock); ++ ++ return 0; ++} ++ ++static int tbsecp3_ca_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct tbsecp3_ca *tbsca = ca->data; ++ struct tbsecp3_adapter *adapter = ++ (struct tbsecp3_adapter *) tbsca->adapter; ++ struct tbsecp3_dev *dev = adapter->dev; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&tbsca->lock); ++ ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x04, 1); ++ msleep (5); ++ ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x04, 0); ++ msleep (1400); ++ ++ mutex_unlock (&tbsca->lock); ++ return 0; ++} ++ ++static int tbsecp3_ca_slot_ctrl(struct dvb_ca_en50221 *ca, ++ int slot, int enable) ++{ ++ struct tbsecp3_ca *tbsca = ca->data; ++ struct tbsecp3_adapter *adapter = ++ (struct tbsecp3_adapter *) tbsca->adapter; ++ struct tbsecp3_dev *dev = adapter->dev; ++ u32 data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&tbsca->lock); ++ ++ data = enable & 1; ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x0c, data); ++ ++ mutex_unlock(&tbsca->lock); ++ ++ dev_info(&dev->pci_dev->dev, "CA slot %sabled for adapter%d\n", ++ enable ? "en" : "dis", ++ adapter->fe->dvb->num); ++ ++ return 0; ++} ++ ++static int tbsecp3_ca_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbsecp3_ca_slot_ctrl(ca, slot, 0); ++} ++ ++static int tbsecp3_ca_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbsecp3_ca_slot_ctrl(ca, slot, 1); ++} ++ ++static int tbsecp3_ca_poll_slot_status(struct dvb_ca_en50221 *ca, ++ int slot, int open) ++{ ++ struct tbsecp3_ca *tbsca = ca->data; ++ struct tbsecp3_adapter *adapter = ++ (struct tbsecp3_adapter *) tbsca->adapter; ++ struct tbsecp3_dev *dev = adapter->dev; ++ u32 data; ++ int ret; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&tbsca->lock); ++ data = tbs_read(TBSECP3_CA_BASE(tbsca->nr), 0x0c) & 1; ++ if (tbsca->status != data){ ++ tbs_write(TBSECP3_CA_BASE(tbsca->nr), 0x08, !data); ++ msleep(300); ++ tbsca->status = data; ++ } ++ mutex_unlock(&tbsca->lock); ++ ++ if (data & 1) ++ ret = DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY; ++ else ++ ret = 0; ++ ++ return ret; ++} ++ ++ ++struct dvb_ca_en50221 ca_config = { ++ .read_attribute_mem = tbsecp3_ca_rd_attr_mem, ++ .write_attribute_mem = tbsecp3_ca_wr_attr_mem, ++ .read_cam_control = tbsecp3_ca_rd_cam_ctrl, ++ .write_cam_control = tbsecp3_ca_wr_cam_ctrl, ++ .slot_reset = tbsecp3_ca_slot_reset, ++ .slot_shutdown = tbsecp3_ca_slot_shutdown, ++ .slot_ts_enable = tbsecp3_ca_slot_ts_enable, ++ .poll_slot_status = tbsecp3_ca_poll_slot_status, ++}; ++ ++ ++int tbsecp3_ca_init(struct tbsecp3_adapter *adap, int nr) ++{ ++ struct tbsecp3_dev *dev = adap->dev; ++ struct tbsecp3_ca *tbsca; ++ int ret; ++ ++ tbsca = kzalloc(sizeof(struct tbsecp3_ca), GFP_KERNEL); ++ if (tbsca == NULL) { ++ ret = -ENOMEM; ++ goto error1; ++ } ++ ++ adap->tbsca = tbsca; ++ ++ tbsca->nr = nr; ++ tbsca->status = 0; ++ tbsca->adapter = adap; ++ mutex_init(&tbsca->lock); ++ ++ memcpy(&tbsca->ca, &ca_config, sizeof(struct dvb_ca_en50221)); ++ tbsca->ca.owner = THIS_MODULE; ++ tbsca->ca.data = tbsca; ++ ++ dev_info(&dev->pci_dev->dev, ++ "initializing CA slot %d on adapter %d\n", ++ nr, adap->dvb_adapter.num); ++ ++ ret = dvb_ca_en50221_init(&adap->dvb_adapter, &tbsca->ca, 0, 1); ++ if (ret) ++ goto error2; ++ ++ return 0; ++ ++error2: ++ kfree(tbsca); ++error1: ++ dev_err(&dev->pci_dev->dev, ++ "adapter %d CA slot initialization failed\n", ++ adap->dvb_adapter.num); ++ return ret; ++} ++ ++void tbsecp3_ca_release(struct tbsecp3_adapter *adap) ++{ ++ struct tbsecp3_ca *tbsca = adap->tbsca; ++ if (!adap) ++ return; ++ if (!tbsca) ++ return; ++ if (!tbsca->ca.data) ++ return; ++ dvb_ca_en50221_release(&tbsca->ca); ++ kfree(tbsca); ++} ++ +diff --git a/drivers/media/pci/tbsecp3/tbsecp3-cards.c b/drivers/media/pci/tbsecp3/tbsecp3-cards.c +new file mode 100644 +index 0000000..0e109f6 +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3-cards.c +@@ -0,0 +1,528 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#include "tbsecp3.h" ++ ++struct tbsecp3_board tbsecp3_boards[] = { ++ [TBSECP3_BOARD_TBS6814] = { ++ .name = "Turbosight TBS 6814 (Quad ISDB-T)", ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adapters = 4, ++ .adap_config ={ ++ ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(1, 0), ++ }, ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ }, ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 3, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(3, 0), ++ } ++ }, ++ }, ++ [TBSECP3_BOARD_TBS6209] = { ++ .name = "Turbosight TBS 6209 (Octa DVB-T/T2/C2/C(j83-a/b/c)/ISDB-T)", ++ .i2c_speed = 39, ++ .eeprom_i2c = 0, ++ .adapters = 8, ++ .adap_config ={ ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 0, ++ }, ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(1, 0), ++ }, ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 1, ++ }, ++ { ++ .ts_in = 4, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ ++ }, ++ { ++ .ts_in = 5, ++ .i2c_bus_nr = 2, ++ }, ++ { ++ .ts_in = 6, ++ .i2c_bus_nr = 3, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(3, 0), ++ ++ }, ++ { ++ .ts_in = 7, ++ .i2c_bus_nr = 3, ++ } ++ ++ } ++ }, ++ [TBSECP3_BOARD_TBS6704] = { ++ .name = "TurboSight TBS 6704(Quad ATSC/QAMB)", ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adapters = 4, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(1, 0), ++ }, ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ }, ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 3, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(3, 0), ++ } ++ } ++ }, ++ ++ [TBSECP3_BOARD_TBS6205] = { ++ .name = "TurboSight TBS 6205 DVB-T/T2/C ", ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adapters = 4, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ }, ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(1, 0), ++ }, ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 3, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(3, 0), ++ } ++ } ++ }, ++ [TBSECP3_BOARD_TBS6522] = { ++ .name = "TurboSight TBS 6522 DVB-S/S2/DVB-T/T2/C ", ++ .adapters = 2, ++ .i2c_speed = 39, ++ .eeprom_i2c = 0, ++ .adap_config = { ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(0, 1), ++ }, ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(1, 1), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6902] = { ++ .name = "TurboSight TBS 6902 DVB-S/S2 ", ++ .adapters = 2, ++ .i2c_speed = 39, ++ .eeprom_i2c = 0, ++ .adap_config = { ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(1, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ }, ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ } ++ ++ } ++ }, ++ [TBSECP3_BOARD_TBS6903] = { ++ .name = "TurboSight TBS 6903 DVB-S/S2 ", ++ .adapters = 2, ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(0, 1), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 0, ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(1, 1), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6904] = { ++ .name = "TurboSight TBS 6904 DVB-S/S2 ", ++ .adapters = 4, ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adap_config = { ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 3, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(3, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(3, 2), ++ }, ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(2, 2), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(1, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ }, ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6905] = { ++ .name = "TurboSight TBS 6905 DVB-S/S2 ", ++ .adapters = 4, ++ .i2c_speed = 39, ++ .eeprom_i2c = 2, ++ .adap_config = { ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(2, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(2, 1), ++ }, ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 2, ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(3, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(3, 1), ++ }, ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(0, 1), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 0, ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(1, 1), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6908] = { ++ .name = "TurboSight TBS 6908 DVB-S/S2 ", ++ .adapters = 4, ++ .i2c_speed = 39, ++ .eeprom_i2c = 2, ++ .adap_config = { ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(2, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(2, 1), ++ }, ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 2, ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(3, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(3, 1), ++ }, ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(0, 1), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 0, ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(1, 1), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6909] = { ++ .name = "TurboSight TBS 6909 DVB-S/S2 ", ++ .adapters = 8, ++ .i2c_speed = 39, ++ .eeprom_i2c = 0, ++ .eeprom_addr = 0x10, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 0, ++ }, ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 0, ++ }, ++ { ++ .ts_in = 3, ++ .i2c_bus_nr = 0, ++ }, ++ { ++ .ts_in = 4, ++ .i2c_bus_nr = 0, ++ }, ++ { ++ .ts_in = 5, ++ .i2c_bus_nr = 0, ++ }, ++ { ++ .ts_in = 6, ++ .i2c_bus_nr = 0, ++ }, ++ { ++ .ts_in = 7, ++ .i2c_bus_nr = 0, ++ } ++ } ++ }, ++ [TBSECP3_BOARD_TBS6910] = { ++ .name = "TurboSight TBS 6910 DVB-S/S2 + 2xCI ", ++ .adapters = 2, ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(1, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6528] = { ++ .name = "TurboSight TBS 6528 DVB-S/S2 + CI ", ++ .adapters = 1, ++ .i2c_speed = 39, ++ .eeprom_i2c = 0, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(0, 1), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6590] = { ++ .name = "TurboSight TBS 6590 DVB-S/S2 + 2xCI ", ++ .adapters = 2, ++ .i2c_speed = 39, ++ .eeprom_i2c = 0, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(0, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(0, 1), ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 0, ++ .gpio.lnb_power.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.lnb_power.nr = TBSECP3_GPIO_PIN(1, 2), ++ .gpio.lnb_voltage.lvl = TBSECP3_GPIODEF_HIGH, ++ .gpio.lnb_voltage.nr = TBSECP3_GPIO_PIN(1, 1), ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6290SE] = { ++ .name = "TurboSight TBS 6290SE DVB-T/T2/C + 2xCI ", ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adapters = 2, ++ .adap_config = { ++ { ++ .ts_in = 0, ++ .i2c_bus_nr = 0, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_NONE, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ ++ }, ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_NONE, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ ++ }, ++ } ++ }, ++ [TBSECP3_BOARD_TBS6281SE] = { ++ .name = "TurboSight TBS 6281SE DVB-T/T2/C ", ++ .i2c_speed = 39, ++ .eeprom_i2c = 1, ++ .adapters = 2, ++ .adap_config = { ++ { ++ .ts_in = 1, ++ .i2c_bus_nr = 1, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(0, 0), ++ }, ++ { ++ .ts_in = 2, ++ .i2c_bus_nr = 2, ++ .gpio.demod_reset.lvl = TBSECP3_GPIODEF_LOW, ++ .gpio.demod_reset.nr = TBSECP3_GPIO_PIN(2, 0), ++ }, ++ } ++ }, ++}; +diff --git a/drivers/media/pci/tbsecp3/tbsecp3-core.c b/drivers/media/pci/tbsecp3/tbsecp3-core.c +new file mode 100644 +index 0000000..41ff805 +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3-core.c +@@ -0,0 +1,349 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#include "tbsecp3.h" ++ ++static bool enable_msi = true; ++module_param(enable_msi, bool, 0444); ++MODULE_PARM_DESC(enable_msi, "use an msi interrupt if available"); ++ ++ ++void tbsecp3_gpio_set_pin(struct tbsecp3_dev *dev, ++ struct tbsecp3_gpio_pin *pin, int state) ++{ ++ u32 tmp, bank, bit; ++ ++ if (pin->lvl == TBSECP3_GPIODEF_NONE) ++ return; ++ ++ if (pin->lvl == TBSECP3_GPIODEF_LOW) ++ state = !state; ++ ++ bank = (pin->nr >> 3) & ~3; ++ bit = pin->nr % 32; ++ ++ tmp = tbs_read(TBSECP3_GPIO_BASE, bank); ++ if (state) ++ tmp |= 1 << bit; ++ else ++ tmp &= ~(1 << bit); ++ tbs_write(TBSECP3_GPIO_BASE, bank, tmp); ++} ++ ++static irqreturn_t tbsecp3_irq_handler(int irq, void *dev_id) ++{ ++ struct tbsecp3_dev *dev = (struct tbsecp3_dev *) dev_id; ++ struct tbsecp3_i2c *i2c; ++ int i, in; ++ u32 stat = tbs_read(TBSECP3_INT_BASE, TBSECP3_INT_STAT); ++ ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_STAT, stat); ++ ++ if (stat & 0x00000ff0) { ++ /* dma */ ++ for (i = 0; i < dev->info->adapters; i++) { ++ in = dev->adapter[i].cfg->ts_in; ++ //printk("i=%d, in=%d", i, in); ++ if (stat & TBSECP3_DMA_IF(in)) { ++ if (dev->adapter[i].dma.cnt < 2) ++ dev->adapter[i].dma.cnt++; ++ else ++ tasklet_schedule(&dev->adapter[i].tasklet); ++ //printk(" X"); ++ } ++ //printk(" | "); ++ } ++ //printk("\n"); ++ } ++ if (stat & 0x0000000f) { ++ /* i2c */ ++ for (i = 0; i < 4; i++) { ++ i2c = &dev->i2c_bus[i]; ++ if (stat & TBSECP3_I2C_IF(i)) { ++ i2c->done = 1; ++ wake_up(&i2c->wq); ++ } ++ } ++ } ++ ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_EN, 1); ++ return IRQ_HANDLED; ++} ++ ++static int tbsecp3_adapters_attach(struct tbsecp3_dev *dev) ++{ ++ int i, ret = 0; ++ for (i = 0; i < dev->info->adapters; i++) { ++ ret = tbsecp3_dvb_init(&dev->adapter[i]); ++ if (ret) { ++ dev_err(&dev->pci_dev->dev, ++ "adapter%d attach failed\n", ++ dev->adapter[i].nr); ++ dev->adapter[i].nr = -1; ++ } ++ } ++ return 0; ++} ++ ++static void tbsecp3_adapters_detach(struct tbsecp3_dev *dev) ++{ ++ struct tbsecp3_adapter *adapter; ++ int i; ++ ++ for (i = 0; i < dev->info->adapters; i++) { ++ adapter = &dev->adapter[i]; ++ ++ /* attach has failed, nothing to do */ ++ if (adapter->nr == -1) ++ continue; ++ ++ tbsecp3_i2c_remove_clients(adapter); ++ tbsecp3_dvb_exit(adapter); ++ } ++} ++ ++static void tbsecp3_adapters_init(struct tbsecp3_dev *dev) ++{ ++ struct tbsecp3_adapter *adapter = dev->adapter; ++ int i; ++ ++ for (i = 0; i < dev->info->adapters; i++) { ++ adapter = &dev->adapter[i]; ++ adapter->nr = i; ++ adapter->cfg = &dev->info->adap_config[i]; ++ adapter->dev = dev; ++ adapter->i2c = &dev->i2c_bus[adapter->cfg->i2c_bus_nr]; ++ } ++} ++ ++static void tbsecp3_adapters_release(struct tbsecp3_dev *dev) ++{ ++ struct tbsecp3_adapter *adapter; ++ int i; ++ ++ for (i = 0; i < dev->info->adapters; i++) { ++ adapter = &dev->adapter[i]; ++ tasklet_kill(&adapter->tasklet); ++ } ++} ++ ++ ++static bool tbsecp3_enable_msi(struct pci_dev *pci_dev, struct tbsecp3_dev *dev) ++{ ++ int err; ++ ++ if (!enable_msi) { ++ dev_warn(&dev->pci_dev->dev, ++ "MSI disabled by module parameter 'enable_msi'\n"); ++ return false; ++ } ++ ++ err = pci_enable_msi(pci_dev); ++ if (err) { ++ dev_err(&dev->pci_dev->dev, ++ "Failed to enable MSI interrupt." ++ " Falling back to a shared IRQ\n"); ++ return false; ++ } ++ ++ /* no error - so request an msi interrupt */ ++ err = request_irq(pci_dev->irq, tbsecp3_irq_handler, 0, ++ "tbsecp3", dev); ++ if (err) { ++ /* fall back to legacy interrupt */ ++ dev_err(&dev->pci_dev->dev, ++ "Failed to get an MSI interrupt." ++ " Falling back to a shared IRQ\n"); ++ pci_disable_msi(pci_dev); ++ return false; ++ } ++ return true; ++} ++ ++ ++static int tbsecp3_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++{ ++ struct tbsecp3_dev *dev; ++ int ret = -ENODEV; ++ ++ if (pci_enable_device(pdev) < 0) ++ return -ENODEV; ++ ++ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); ++ if (ret) { ++ dev_err(&pdev->dev, "32-bit PCI DMA not supported\n"); ++ goto err0; ++ } ++ ++ dev = kzalloc(sizeof(struct tbsecp3_dev), GFP_KERNEL); ++ if (!dev) { ++ ret = -ENOMEM; ++ goto err0; ++ } ++ ++ dev->pci_dev = pdev; ++ pci_set_drvdata(pdev, dev); ++ ++ dev->info = (struct tbsecp3_board *) id->driver_data; ++ dev_info(&pdev->dev, "%s\n", dev->info->name); ++ ++ dev->lmmio = ioremap(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ if (!dev->lmmio) { ++ ret = -ENOMEM; ++ goto err1; ++ } ++ ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_EN, 0); ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_STAT, 0xff); ++ ++ tbsecp3_adapters_init(dev); ++ ++ /* dma */ ++ ret = tbsecp3_dma_init(dev); ++ if (ret < 0) ++ goto err2; ++ ++ /* i2c */ ++ ret = tbsecp3_i2c_init(dev); ++ if (ret < 0) ++ goto err3; ++ ++ /* interrupts */ ++ if (tbsecp3_enable_msi(pdev, dev)) { ++ dev->msi = true; ++ } else { ++ ret = request_irq(pdev->irq, tbsecp3_irq_handler, ++ IRQF_SHARED, "tbsecp3", dev); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "%s: can't get IRQ %d\n", ++ dev->info->name, pdev->irq); ++ goto err4; ++ } ++ dev->msi = false; ++ } ++ /* global interrupt enable */ ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_EN, 1); ++ ++ ret = tbsecp3_adapters_attach(dev); ++ if (ret < 0) ++ goto err5; ++ ++ dev_info(&pdev->dev, "%s: PCI %s, IRQ %d, MMIO 0x%lx\n", ++ dev->info->name, pci_name(pdev), pdev->irq, ++ (unsigned long) pci_resource_start(pdev, 0)); ++ ++ //dev_info(&dev->pci_dev->dev, "%s ready\n", dev->info->name); ++ return 0; ++ ++err5: ++ tbsecp3_adapters_detach(dev); ++ ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_EN, 0); ++ free_irq(dev->pci_dev->irq, dev); ++ if (dev->msi) { ++ pci_disable_msi(pdev); ++ dev->msi = false; ++ } ++err4: ++ tbsecp3_i2c_exit(dev); ++err3: ++ tbsecp3_dma_free(dev); ++err2: ++ tbsecp3_adapters_release(dev); ++ iounmap(dev->lmmio); ++err1: ++ pci_set_drvdata(pdev, NULL); ++ kfree(dev); ++err0: ++ pci_disable_device(pdev); ++ dev_err(&pdev->dev, "probe error\n"); ++ return ret; ++} ++ ++static void tbsecp3_remove(struct pci_dev *pdev) ++{ ++ struct tbsecp3_dev *dev = pci_get_drvdata(pdev); ++ ++ /* disable interrupts */ ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_EN, 0); ++ free_irq(pdev->irq, dev); ++ if (dev->msi) { ++ pci_disable_msi(pdev); ++ dev->msi = false; ++ } ++ tbsecp3_adapters_detach(dev); ++ tbsecp3_adapters_release(dev); ++ tbsecp3_dma_free(dev); ++ tbsecp3_i2c_exit(dev); ++ iounmap(dev->lmmio); ++ pci_set_drvdata(pdev, NULL); ++ pci_disable_device(pdev); ++ kfree(dev); ++} ++ ++static int tbsecp3_resume(struct pci_dev *pdev) ++{ ++ struct tbsecp3_dev *dev = pci_get_drvdata(pdev); ++ /* re-init registers */ ++ tbsecp3_i2c_reg_init(dev); ++ tbsecp3_dma_reg_init(dev); ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_INT_EN, 1); ++ return 0; ++} ++ ++/* PCI IDs */ ++#define TBSECP3_ID(_subvend) { \ ++ .vendor = TBSECP3_VID, .device = TBSECP3_PID, \ ++ .subvendor = _subvend, .subdevice = PCI_ANY_ID, \ ++ .driver_data = (unsigned long)&tbsecp3_boards[_subvend] } ++ ++static const struct pci_device_id tbsecp3_id_table[] = { ++ TBSECP3_ID(TBSECP3_BOARD_TBS6205), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6522), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6902), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6903), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6904), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6905), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6908), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6909), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6910), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6528), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6590), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6290SE), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6281SE), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6704), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6209), ++ TBSECP3_ID(TBSECP3_BOARD_TBS6814), ++ {0} ++}; ++MODULE_DEVICE_TABLE(pci, tbsecp3_id_table); ++ ++static struct pci_driver tbsecp3_driver = { ++ .name = "TBSECP3 driver", ++ .id_table = tbsecp3_id_table, ++ .probe = tbsecp3_probe, ++ .remove = tbsecp3_remove, ++ .resume = tbsecp3_resume, ++ .suspend = NULL, ++}; ++ ++module_pci_driver(tbsecp3_driver); ++ ++MODULE_AUTHOR("Luis Alves "); ++MODULE_DESCRIPTION("TBS ECP3 driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/pci/tbsecp3/tbsecp3-dma.c b/drivers/media/pci/tbsecp3/tbsecp3-dma.c +new file mode 100644 +index 0000000..0fa90e2 +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3-dma.c +@@ -0,0 +1,145 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#include "tbsecp3.h" ++ ++#define TS_PACKET_SIZE 188 ++#define TBSECP3_DMA_PAGE_SIZE (2048 * TS_PACKET_SIZE) ++#define TBSECP3_DMA_BUF_SIZE (TBSECP3_DMA_PAGE_SIZE / TBSECP3_DMA_BUFFERS) ++#define TBSECP3_BUF_PACKETS (TBSECP3_DMA_BUF_SIZE / TS_PACKET_SIZE) ++ ++static void tbsecp3_dma_tasklet(unsigned long adap) ++{ ++ struct tbsecp3_adapter *adapter = (struct tbsecp3_adapter *) adap; ++ struct tbsecp3_dev *dev = adapter->dev; ++ u8* data; ++ u32 read_buffer; ++ int i; ++ ++ spin_lock(&adapter->adap_lock); ++ ++ /* read data from two buffers below the active one */ ++ read_buffer = (tbs_read(adapter->dma.base, TBSECP3_DMA_STAT) - 2) & 7; ++ data = adapter->dma.buf[read_buffer]; ++ ++ if (data[adapter->dma.offset] != 0x47) { ++ /* find sync byte offset */ ++ for (i = 0; i < TS_PACKET_SIZE; i++) ++ if ((data[i] == 0x47) && ++ (data[i + TS_PACKET_SIZE] == 0x47) && ++ (data[i + 2 * TS_PACKET_SIZE] == 0x47)) { ++ adapter->dma.offset = i; ++ break; ++ } ++ } ++ ++ if (adapter->dma.offset != 0) { ++ data += adapter->dma.offset; ++ /* copy the remains of the last packet from buffer 0 to end of 7 */ ++ if (read_buffer == 7) { ++ memcpy( adapter->dma.buf[8], ++ adapter->dma.buf[0], adapter->dma.offset); ++ } ++ } ++ dvb_dmx_swfilter_packets(&adapter->demux, data, TBSECP3_BUF_PACKETS); ++ spin_unlock(&adapter->adap_lock); ++} ++ ++void tbsecp3_dma_enable(struct tbsecp3_adapter *adap) ++{ ++ struct tbsecp3_dev *dev = adap->dev; ++ ++ spin_lock_irq(&adap->adap_lock); ++ adap->dma.offset = 0; ++ adap->dma.cnt = 0; ++ tbs_read(adap->dma.base, TBSECP3_DMA_STAT); ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_DMA_IE(adap->cfg->ts_in), 1); ++ tbs_write(adap->dma.base, TBSECP3_DMA_EN, 1); ++ spin_unlock_irq(&adap->adap_lock); ++} ++ ++void tbsecp3_dma_disable(struct tbsecp3_adapter *adap) ++{ ++ struct tbsecp3_dev *dev = adap->dev; ++ ++ spin_lock_irq(&adap->adap_lock); ++ tbs_read(adap->dma.base, TBSECP3_DMA_STAT); ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_DMA_IE(adap->cfg->ts_in), 0); ++ tbs_write(adap->dma.base, TBSECP3_DMA_EN, 0); ++ spin_unlock_irq(&adap->adap_lock); ++} ++ ++void tbsecp3_dma_reg_init(struct tbsecp3_dev *dev) ++{ ++ int i; ++ struct tbsecp3_adapter *adapter = dev->adapter; ++ ++ for (i = 0; i < dev->info->adapters; i++) { ++ tbs_write(adapter->dma.base, TBSECP3_DMA_EN, 0); ++ tbs_write(adapter->dma.base, TBSECP3_DMA_ADDRH, 0); ++ tbs_write(adapter->dma.base, TBSECP3_DMA_ADDRL, (u32) adapter->dma.dma_addr); ++ tbs_write(adapter->dma.base, TBSECP3_DMA_TSIZE, TBSECP3_DMA_PAGE_SIZE); ++ tbs_write(adapter->dma.base, TBSECP3_DMA_BSIZE, TBSECP3_DMA_BUF_SIZE); ++ adapter++; ++ } ++} ++ ++void tbsecp3_dma_free(struct tbsecp3_dev *dev) ++{ ++ struct tbsecp3_adapter *adapter = dev->adapter; ++ int i; ++ for (i = 0; i < dev->info->adapters; i++) { ++ if (adapter->dma.buf[0] == NULL) ++ continue; ++ ++ pci_free_consistent(dev->pci_dev, ++ TBSECP3_DMA_PAGE_SIZE + 0x100, ++ adapter->dma.buf[0], adapter->dma.dma_addr); ++ adapter->dma.buf[0] = NULL; ++ adapter++; ++ } ++} ++ ++int tbsecp3_dma_init(struct tbsecp3_dev *dev) ++{ ++ struct tbsecp3_adapter *adapter = dev->adapter; ++ int i, j; ++ ++ for (i = 0; i < dev->info->adapters; i++) { ++ adapter->dma.buf[0] = pci_alloc_consistent(dev->pci_dev, ++ TBSECP3_DMA_PAGE_SIZE + 0x100, ++ &adapter->dma.dma_addr); ++ if (!adapter->dma.buf[0]) ++ goto err; ++ ++ adapter->dma.base = TBSECP3_DMA_BASE(adapter->cfg->ts_in); ++ adapter->dma.cnt = 0; ++ for (j = 1; j < TBSECP3_DMA_BUFFERS + 1; j++) ++ adapter->dma.buf[j] = adapter->dma.buf[j-1] + TBSECP3_DMA_BUF_SIZE; ++ ++ tasklet_init(&adapter->tasklet, tbsecp3_dma_tasklet, (unsigned long) adapter); ++ spin_lock_init(&adapter->adap_lock); ++ adapter++; ++ } ++ tbsecp3_dma_reg_init(dev); ++ return 0; ++err: ++ dev_err(&dev->pci_dev->dev, "dma: memory alloc failed\n"); ++ tbsecp3_dma_free(dev); ++ return -ENOMEM; ++} ++ +diff --git a/drivers/media/pci/tbsecp3/tbsecp3-dvb.c b/drivers/media/pci/tbsecp3/tbsecp3-dvb.c +new file mode 100644 +index 0000000..6c701e1 +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3-dvb.c +@@ -0,0 +1,1118 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#include "tbsecp3.h" ++ ++#include "tas2101.h" ++#include "av201x.h" ++ ++#include "si2168.h" ++#include "si2157.h" ++ ++#include "mxl5xx.h" ++ ++#include "si2183.h" ++ ++#include "stv0910.h" ++#include "stv6120.h" ++ ++#include "mn88436.h" ++#include "mxl603.h" ++ ++#include "mtv23x.h" ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++struct sec_priv { ++ struct tbsecp3_adapter *adap; ++ int (*set_voltage)(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage); ++}; ++ ++static int tbsecp3_set_voltage(struct dvb_frontend* fe, ++ enum fe_sec_voltage voltage) ++{ ++ struct sec_priv *priv = fe->sec_priv; ++ struct tbsecp3_gpio_config *cfg = &priv->adap->cfg->gpio; ++ struct tbsecp3_dev *dev = priv->adap->dev; ++ ++ dev_dbg(&dev->pci_dev->dev, "%s() %s\n", __func__, ++ voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : ++ voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : ++ "SEC_VOLTAGE_OFF"); ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ tbsecp3_gpio_set_pin(dev, &cfg->lnb_power, 1); ++ tbsecp3_gpio_set_pin(dev, &cfg->lnb_voltage, 0); ++ break; ++ case SEC_VOLTAGE_18: ++ tbsecp3_gpio_set_pin(dev, &cfg->lnb_power, 1); ++ tbsecp3_gpio_set_pin(dev, &cfg->lnb_voltage, 1); ++ break; ++ default: /* OFF */ ++ //tbsecp3_gpio_set_pin(dev, &cfg->lnb_power, 0); ++ break; ++ } ++ ++ if (priv->set_voltage) ++ return priv->set_voltage(fe, voltage); ++ else ++ return 0; ++} ++ ++static void tbsecp3_release_sec(struct dvb_frontend* fe) ++{ ++ struct sec_priv *priv; ++ ++ if (fe == NULL) ++ return; ++ ++ priv = fe->sec_priv; ++ if (priv == NULL) ++ return; ++ ++ fe->ops.set_voltage = priv->set_voltage; ++ fe->sec_priv = NULL; ++ kfree(priv); ++} ++ ++static struct dvb_frontend *tbsecp3_attach_sec(struct tbsecp3_adapter *adap, struct dvb_frontend *fe) ++{ ++ struct sec_priv *priv; ++ ++ priv = kzalloc(sizeof(struct sec_priv), GFP_KERNEL); ++ if (!priv) ++ return NULL; ++ ++ priv->set_voltage = fe->ops.set_voltage; ++ priv->adap = adap; ++ ++// fe->ops.release_sec = tbsecp3_release_sec; ++ fe->ops.set_voltage = tbsecp3_set_voltage; ++ fe->sec_priv = priv; ++ ++ return fe; ++} ++ ++static int set_mac_address(struct tbsecp3_adapter *adap) ++{ ++ struct tbsecp3_dev *dev = adap->dev; ++ u8 eeprom_bus_nr = dev->info->eeprom_i2c; ++ struct i2c_adapter *i2c = &dev->i2c_bus[eeprom_bus_nr].i2c_adap; ++ u8 eep_addr; ++ int ret; ++ ++ struct i2c_msg msg[] = { ++ { .addr = 0x50, .flags = 0, ++ .buf = &eep_addr, .len = 1 }, ++ { .addr = 0x50, .flags = I2C_M_RD, ++ .buf = adap->dvb_adapter.proposed_mac, .len = 6 } ++ }; ++ ++ if (dev->info->eeprom_addr) ++ eep_addr = dev->info->eeprom_addr; ++ else ++ eep_addr = 0xa0; ++ eep_addr += 0x10 * adap->nr; ++ ret = i2c_transfer(i2c, msg, 2); ++ if (ret != 2) { ++ dev_warn(&dev->pci_dev->dev, ++ "error reading MAC address for adapter %d\n", ++ adap->nr); ++ } else { ++ dev_info(&dev->pci_dev->dev, ++ "MAC address %pM\n", adap->dvb_adapter.proposed_mac); ++ } ++ return 0; ++}; ++ ++static int start_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct tbsecp3_adapter *adapter = dvbdmx->priv; ++ ++ if (!adapter->feeds) ++ tbsecp3_dma_enable(adapter); ++ ++ return ++adapter->feeds; ++} ++ ++static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct tbsecp3_adapter *adapter = dvbdmx->priv; ++ ++ if (--adapter->feeds) ++ return adapter->feeds; ++ ++ tbsecp3_dma_disable(adapter); ++ return 0; ++} ++ ++static void reset_demod(struct tbsecp3_adapter *adapter) ++{ ++ struct tbsecp3_dev *dev = adapter->dev; ++ struct tbsecp3_gpio_pin *reset = &adapter->cfg->gpio.demod_reset; ++ ++ tbsecp3_gpio_set_pin(dev, reset, 1); ++ usleep_range(10000, 20000); ++ ++ tbsecp3_gpio_set_pin(dev, reset, 0); ++ usleep_range(50000, 100000); ++} ++ ++ ++static struct tas2101_config tbs6902_demod_cfg[] = { ++ { ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .init = {0xb0, 0x32, 0x81, 0x57, 0x64, 0x9a, 0x33}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .init = {0xb0, 0x32, 0x81, 0x57, 0x64, 0x9a, 0x33}, // 0xb1 ++ .init2 = 0, ++ } ++}; ++ ++static struct av201x_config tbs6902_av201x_cfg = { ++ .i2c_address = 0x62, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static struct tas2101_config tbs6904_demod_cfg[] = { ++ { ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .init = {0xb0, 0x32, 0x81, 0x57, 0x64, 0x9a, 0x33}, // 0xb1 ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .init = {0xb0, 0x32, 0x81, 0x57, 0x64, 0x9a, 0x33}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .init = {0xb0, 0x32, 0x81, 0x57, 0x64, 0x9a, 0x33}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .init = {0xb0, 0x32, 0x81, 0x57, 0x64, 0x9a, 0x33}, ++ .init2 = 0, ++ } ++}; ++ ++static struct av201x_config tbs6904_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++ ++static struct tas2101_config tbs6910_demod_cfg[] = { ++ { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .init = {0x21, 0x43, 0x65, 0xb0, 0xa8, 0x97, 0xb1}, ++ .init2 = 0, ++ }, ++ { ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .init = {0xb0, 0xa8, 0x21, 0x43, 0x65, 0x97, 0xb1}, ++ .init2 = 0, ++ }, ++}; ++ ++static struct av201x_config tbs6910_av201x_cfg = { ++ .i2c_address = 0x62, ++ .id = ID_AV2018, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int max_set_voltage(struct i2c_adapter *i2c, ++ enum fe_sec_voltage voltage, u8 rf_in) ++{ ++ struct tbsecp3_i2c *i2c_adap = i2c_get_adapdata(i2c); ++ struct tbsecp3_dev *dev = i2c_adap->dev; ++ ++ u32 val, reg; ++ ++ //printk("set voltage on %u = %d\n", rf_in, voltage); ++ ++ if (rf_in > 3) ++ return -EINVAL; ++ ++ reg = rf_in * 4; ++ val = tbs_read(TBSECP3_GPIO_BASE, reg) & ~4; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ val &= ~2; ++ break; ++ case SEC_VOLTAGE_18: ++ val |= 2; ++ break; ++ case SEC_VOLTAGE_OFF: ++ default: ++ //val |= 4; ++ break; ++ } ++ ++ tbs_write(TBSECP3_GPIO_BASE, reg, val); ++ return 0; ++} ++ ++static int max_send_master_cmd(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) ++{ ++ //printk("send master cmd\n"); ++ return 0; ++} ++static int max_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) ++{ ++ //printk("send burst: %d\n", burst); ++ return 0; ++} ++static void RF_switch(struct i2c_adapter *i2c,u8 rf_in,u8 flag)//flag : 0: dvbs/s2 signal 1:Terrestrial and cable signal ++{ ++ struct tbsecp3_i2c *i2c_adap = i2c_get_adapdata(i2c); ++ struct tbsecp3_dev *dev = i2c_adap->dev; ++ u32 val ,reg; ++ ++ reg = 0xc-rf_in*4; ++ ++ val = tbs_read(TBSECP3_GPIO_BASE, reg); ++ if(flag) ++ val |= 2; ++ else ++ val &= ~2; ++ ++ tbs_write(TBSECP3_GPIO_BASE, reg, val); ++ ++} ++ ++static struct mxl5xx_cfg tbs6909_mxl5xx_cfg = { ++ .adr = 0x60, ++ .type = 0x01, ++ .clk = 24000000, ++ .cap = 12, ++ .fw_read = NULL, ++ ++ .set_voltage = max_set_voltage, ++}; ++ ++static struct stv0910_cfg tbs6903_stv0910_cfg = { ++ .adr = 0x68, ++ .parallel = 1, ++ .rptlvl = 3, ++ .clk = 30000000, ++ .dual_tuner = 1, ++}; ++ ++struct stv6120_cfg tbs6903_stv6120_cfg = { ++ .adr = 0x60, ++ .Rdiv = 2, ++ .xtal = 30000, ++}; ++ ++ ++static struct av201x_config tbs6522_av201x_cfg[] = { ++ { ++ .i2c_address = 0x63, ++ .id = ID_AV2018, ++ .xtal_freq = 27000, ++ }, ++ { ++ .i2c_address = 0x62, ++ .id = ID_AV2018, ++ .xtal_freq = 27000, ++ }, ++}; ++ ++ ++ ++static int tbsecp3_frontend_attach(struct tbsecp3_adapter *adapter) ++{ ++ struct tbsecp3_dev *dev = adapter->dev; ++ struct pci_dev *pci = dev->pci_dev; ++ ++ struct si2168_config si2168_config; ++ struct si2183_config si2183_config; ++ struct si2157_config si2157_config; ++ struct mn88436_config mn88436_config; ++ struct mxl603_config mxl603_config; ++ struct mtv23x_config mtv23x_config; ++ //struct av201x_config av201x_config; ++ ++ struct i2c_board_info info; ++ struct i2c_adapter *i2c = &adapter->i2c->i2c_adap; ++ struct i2c_client *client_demod, *client_tuner; ++ ++ adapter->fe = NULL; ++ adapter->fe2 = NULL; ++ adapter->i2c_client_demod = NULL; ++ adapter->i2c_client_tuner = NULL; ++ ++ reset_demod(adapter); ++ ++ set_mac_address(adapter); ++ ++ switch (pci->subsystem_vendor) { ++ case 0x6814: ++ memset(&mtv23x_config, 0, sizeof(mtv23x_config)); ++ mtv23x_config.fe = &adapter->fe; ++ mtv23x_config.clk_freq = 32000; ++ mtv23x_config.ts_mode = 6; ++ mtv23x_config.i2c_wr_max = 32; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "mtv23x", I2C_NAME_SIZE); ++ info.addr = (adapter->nr%2)? 0x44 : 0x43; ++ info.platform_data = &mtv23x_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(i2c, &info); ++ if (client_demod == NULL || ++ client_demod->dev.driver == NULL) ++ goto frontend_atach_fail; ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_demod = client_demod; ++ break; ++ case 0x6209: ++ /* attach demod */ ++ memset(&si2183_config, 0, sizeof(si2183_config)); ++ si2183_config.i2c_adapter = &i2c; ++ si2183_config.fe = &adapter->fe; ++ si2183_config.ts_mode = SI2183_TS_SERIAL; ++ si2183_config.ts_clock_gapped = true; ++ si2183_config.rf_in = adapter->nr; ++ si2183_config.RF_switch = NULL; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2183", I2C_NAME_SIZE); ++ info.addr = (adapter->nr%2)? 0x67 : 0x64; ++ si2183_config.agc_mode = (adapter->nr%2)? 0x5 : 0x4; ++ info.platform_data = &si2183_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(i2c, &info); ++ if (client_demod == NULL || ++ client_demod->dev.driver == NULL) ++ goto frontend_atach_fail; ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_demod = client_demod; ++ ++ /* terrestrial tuner */ ++ memset(adapter->fe->ops.delsys, 0, MAX_DELSYS); ++ adapter->fe->ops.delsys[0] = SYS_DVBT; ++ adapter->fe->ops.delsys[1] = SYS_DVBT2; ++ adapter->fe->ops.delsys[2] = SYS_DVBC_ANNEX_A; ++ adapter->fe->ops.delsys[3] = SYS_ISDBT; ++ adapter->fe->ops.delsys[4] = SYS_DVBC_ANNEX_B; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = (adapter->nr %2)? 0x60 : 0x63; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(i2c, &info); ++ if (client_tuner == NULL || ++ client_tuner->dev.driver == NULL) ++ goto frontend_atach_fail; ++ ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_tuner = client_tuner; ++ break; ++ case 0x6704: ++ /* attach demod */ ++ memset(&mn88436_config, 0, sizeof(mn88436_config)); ++ mn88436_config.fe = &adapter->fe; ++ mn88436_config.ts_mode = 0; ++ mn88436_config.i2c_wr_max = 32; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "mn88436", I2C_NAME_SIZE); ++ info.addr = 0x18; ++ info.platform_data = &mn88436_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(i2c, &info); ++ if (client_demod == NULL || ++ client_demod->dev.driver == NULL) ++ goto frontend_atach_fail; ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_demod = client_demod; ++ ++ /* attach tuner */ ++ memset(&mxl603_config, 0, sizeof(mxl603_config)); ++ mxl603_config.fe = adapter->fe; ++ mxl603_config.xtalFreqSel= 1; //0:16M ,1:24M ++ mxl603_config.agcType = 0 ; //0:self 1:external ++ mxl603_config.ifOutFreq = MXL603_IF_5MHz; ++ mxl603_config.manualIFFreqSet = false; ++ mxl603_config.manualIFOutFreqInKHz = 0 ;//if manual set ,input the freq ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "mxl603", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &mxl603_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(i2c, &info); ++ if (client_tuner == NULL || ++ client_tuner->dev.driver == NULL) ++ goto frontend_atach_fail; ++ ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_tuner = client_tuner; ++ ++ break; ++ case 0x6205: ++ case 0x6281: ++ /* attach demod */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &i2c; ++ si2168_config.fe = &adapter->fe; ++ si2168_config.ts_mode = SI2168_TS_PARALLEL; ++ si2168_config.ts_clock_gapped = true; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(i2c, &info); ++ if (client_demod == NULL || ++ client_demod->dev.driver == NULL) ++ goto frontend_atach_fail; ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_demod = client_demod; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(i2c, &info); ++ if (client_tuner == NULL || ++ client_tuner->dev.driver == NULL) ++ goto frontend_atach_fail; ++ ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_tuner = client_tuner; ++ break; ++ case 0x6290: ++ /* attach demod */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &i2c; ++ si2168_config.fe = &adapter->fe; ++ si2168_config.ts_mode = SI2168_TS_SERIAL;//zc2016/07/20 ++ si2168_config.ts_clock_gapped = true; ++ //si2168_config.ts_clock_inv=1;//zc2016/07/20 ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(i2c, &info); ++ if (client_demod == NULL || ++ client_demod->dev.driver == NULL) ++ goto frontend_atach_fail; ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_demod = client_demod; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(i2c, &info); ++ if (client_tuner == NULL || ++ client_tuner->dev.driver == NULL) ++ goto frontend_atach_fail; ++ ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_tuner = client_tuner; ++ tbsecp3_ca_init(adapter, adapter->nr); ++ break; ++ case 0x6522: ++ /* attach demod */ ++ memset(&si2183_config, 0, sizeof(si2183_config)); ++ si2183_config.i2c_adapter = &i2c; ++ si2183_config.fe = &adapter->fe; ++ si2183_config.ts_mode = SI2183_TS_PARALLEL; ++ si2183_config.ts_clock_gapped = true; ++ si2183_config.rf_in = adapter->nr; ++ si2183_config.RF_switch = NULL; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2183", I2C_NAME_SIZE); ++ info.addr = adapter->nr ? 0x64 : 0x67; ++ si2183_config.agc_mode = adapter->nr? 0x4 : 0x5; ++ info.platform_data = &si2183_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(i2c, &info); ++ if (client_demod == NULL || ++ client_demod->dev.driver == NULL) ++ goto frontend_atach_fail; ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_demod = client_demod; ++ ++ ++ ++ /* dvb core doesn't support 2 tuners for 1 demod so ++ we split the adapter in 2 frontends */ ++ adapter->fe2 = &adapter->_fe2; ++ memcpy(adapter->fe2, adapter->fe, sizeof(struct dvb_frontend)); ++ ++ ++ /* terrestrial tuner */ ++ memset(adapter->fe->ops.delsys, 0, MAX_DELSYS); ++ adapter->fe->ops.delsys[0] = SYS_DVBT; ++ adapter->fe->ops.delsys[1] = SYS_DVBT2; ++ adapter->fe->ops.delsys[2] = SYS_DVBC_ANNEX_A; ++ adapter->fe->ops.delsys[3] = SYS_ISDBT; ++ adapter->fe->ops.delsys[4] = SYS_DVBC_ANNEX_B; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = adapter->nr ? 0x61 : 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(i2c, &info); ++ if (client_tuner == NULL || ++ client_tuner->dev.driver == NULL) ++ goto frontend_atach_fail; ++ ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_tuner = client_tuner; ++ ++ ++ /* sattelite tuner */ ++ memset(adapter->fe2->ops.delsys, 0, MAX_DELSYS); ++ adapter->fe2->ops.delsys[0] = SYS_DVBS; ++ adapter->fe2->ops.delsys[1] = SYS_DVBS2; ++ adapter->fe2->ops.delsys[2] = SYS_DSS; ++ adapter->fe2->id = 1; ++ if (dvb_attach(av201x_attach, adapter->fe2, &tbs6522_av201x_cfg[adapter->nr], ++ i2c) == NULL) { ++ dev_err(&dev->pci_dev->dev, ++ "frontend %d tuner attach failed\n", ++ adapter->nr); ++ goto frontend_atach_fail; ++ } ++ if (tbsecp3_attach_sec(adapter, adapter->fe2) == NULL) { ++ dev_warn(&dev->pci_dev->dev, ++ "error attaching lnb control on adapter %d\n", ++ adapter->nr); ++ } ++ ++ break; ++ case 0x6528: ++ case 0x6590: ++ /* attach demod */ ++ memset(&si2183_config, 0, sizeof(si2183_config)); ++ si2183_config.i2c_adapter = &i2c; ++ si2183_config.fe = &adapter->fe; ++ si2183_config.ts_clock_gapped = true; ++ si2183_config.RF_switch = RF_switch; ++ if(pci->subsystem_vendor==0x6528) ++ { ++ si2183_config.rf_in = 1; ++ si2183_config.ts_mode = SI2183_TS_PARALLEL; ++ } ++ else ++ { ++ si2183_config.rf_in = adapter->nr; ++ si2183_config.ts_mode = SI2183_TS_SERIAL; ++ } ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2183", I2C_NAME_SIZE); ++ if(pci->subsystem_vendor==0x6528) ++ { ++ info.addr = 0x67; ++ si2183_config.agc_mode = 0x5 ; ++ } ++ else{ ++ info.addr = adapter->nr ? 0x67 : 0x64; ++ si2183_config.agc_mode = adapter->nr? 0x5 : 0x4; ++ } ++ info.platform_data = &si2183_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(i2c, &info); ++ if (client_demod == NULL || ++ client_demod->dev.driver == NULL) ++ goto frontend_atach_fail; ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_demod = client_demod; ++ ++ ++ ++ /* dvb core doesn't support 2 tuners for 1 demod so ++ we split the adapter in 2 frontends */ ++ adapter->fe2 = &adapter->_fe2; ++ memcpy(adapter->fe2, adapter->fe, sizeof(struct dvb_frontend)); ++ ++ ++ /* terrestrial tuner */ ++ memset(adapter->fe->ops.delsys, 0, MAX_DELSYS); ++ adapter->fe->ops.delsys[0] = SYS_DVBT; ++ adapter->fe->ops.delsys[1] = SYS_DVBT2; ++ adapter->fe->ops.delsys[2] = SYS_DVBC_ANNEX_A; ++ adapter->fe->ops.delsys[3] = SYS_ISDBT; ++ adapter->fe->ops.delsys[4] = SYS_DVBC_ANNEX_B; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adapter->fe; ++ si2157_config.if_port = 1; ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ if(pci->subsystem_vendor==0x6528)info.addr = 0x61; ++ else ++ info.addr = adapter->nr ? 0x61 : 0x60; ++ ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(i2c, &info); ++ if (client_tuner == NULL || ++ client_tuner->dev.driver == NULL) ++ goto frontend_atach_fail; ++ ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_tuner = client_tuner; ++ ++ ++ /* sattelite tuner */ ++ memset(adapter->fe2->ops.delsys, 0, MAX_DELSYS); ++ adapter->fe2->ops.delsys[0] = SYS_DVBS; ++ adapter->fe2->ops.delsys[1] = SYS_DVBS2; ++ adapter->fe2->ops.delsys[2] = SYS_DSS; ++ adapter->fe2->id = 1; ++ if(pci->subsystem_vendor==0x6528) ++ { ++ if (dvb_attach(av201x_attach, adapter->fe2, &tbs6522_av201x_cfg[1], ++ i2c) == NULL) { ++ dev_err(&dev->pci_dev->dev, ++ "frontend %d tuner attach failed\n", ++ adapter->nr); ++ goto frontend_atach_fail; ++ } ++ } ++ else{ ++ if (dvb_attach(av201x_attach, adapter->fe2, &tbs6522_av201x_cfg[adapter->nr], ++ i2c) == NULL) { ++ dev_err(&dev->pci_dev->dev, ++ "frontend %d tuner attach failed\n", ++ adapter->nr); ++ goto frontend_atach_fail; ++ } ++ } ++ if (tbsecp3_attach_sec(adapter, adapter->fe2) == NULL) { ++ dev_warn(&dev->pci_dev->dev, ++ "error attaching lnb control on adapter %d\n", ++ adapter->nr); ++ } ++ ++ tbsecp3_ca_init(adapter, adapter->nr); ++ ++ break; ++ ++ case 0x6902: ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6902_demod_cfg[adapter->nr], i2c); ++ if (adapter->fe == NULL) ++ goto frontend_atach_fail; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6902_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_err(&dev->pci_dev->dev, ++ "frontend %d tuner attach failed\n", ++ adapter->nr); ++ goto frontend_atach_fail; ++ } ++ ++ if (tbsecp3_attach_sec(adapter, adapter->fe) == NULL) { ++ dev_warn(&dev->pci_dev->dev, ++ "error attaching lnb control on adapter %d\n", ++ adapter->nr); ++ } ++ break; ++ case 0x6903: ++ case 0x6905: ++ case 0x6908: ++ adapter->fe = dvb_attach(stv0910_attach, i2c, ++ &tbs6903_stv0910_cfg, adapter->nr & 1); ++ if (adapter->fe == NULL) ++ goto frontend_atach_fail; ++ ++ if (dvb_attach(stv6120_attach, adapter->fe, i2c, &tbs6903_stv6120_cfg, 1 - (adapter->nr & 1)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_err(&dev->pci_dev->dev, ++ "frontend %d tuner attach failed\n", ++ adapter->nr); ++ goto frontend_atach_fail; ++ } ++ if (tbsecp3_attach_sec(adapter, adapter->fe) == NULL) { ++ dev_warn(&dev->pci_dev->dev, ++ "error attaching lnb control on adapter %d\n", ++ adapter->nr); ++ } ++ ++ break; ++ case 0x6904: ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6904_demod_cfg[adapter->nr], i2c); ++ if (adapter->fe == NULL) ++ goto frontend_atach_fail; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6904_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_err(&dev->pci_dev->dev, ++ "frontend %d tuner attach failed\n", ++ adapter->nr); ++ goto frontend_atach_fail; ++ } ++ ++ if (tbsecp3_attach_sec(adapter, adapter->fe) == NULL) { ++ dev_warn(&dev->pci_dev->dev, ++ "error attaching lnb control on adapter %d\n", ++ adapter->nr); ++ } ++#if 0 ++ /* attach tuner */ ++ memset(&av201x_config, 0, sizeof(av201x_config)); ++ av201x_config.fe = adapter->fe; ++ av201x_config.xtal_freq = 27000, ++ ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "av2012", I2C_NAME_SIZE); ++ info.addr = 0x63; ++ info.platform_data = &av201x_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(i2c, &info); ++ printk("cli_tu=%p\n", client_tuner); ++ if (client_tuner != NULL) ++ printk("cli_tu.drv=%p\n", client_tuner->dev.driver); ++ if (client_tuner == NULL || ++ client_tuner->dev.driver == NULL) { ++ printk("client tunner fail 1\n"); ++ goto frontend_atach_fail; ++ } ++ ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ printk("client tunner fail 2\n"); ++ goto frontend_atach_fail; ++ } ++ adapter->i2c_client_tuner = client_tuner; ++#endif ++ break; ++ case 0x6909: ++/* ++ tmp = tbs_read(TBS_GPIO_BASE, 0x20); ++ printk("RD 0x20 = %x\n", tmp); ++ tbs_write(TBS_GPIO_BASE, 0x20, tmp & 0xfffe); ++ tmp = tbs_read(TBS_GPIO_BASE, 0x20); ++ printk("RD 0x20 = %x\n", tmp); ++ ++ tmp = tbs_read(TBS_GPIO_BASE, 0x24); ++ printk("RD 0x24 = %x\n", tmp); ++ tbs_write(TBS_GPIO_BASE, 0x24, tmp & 0xfffc); ++ tmp = tbs_read(TBS_GPIO_BASE, 0x24); ++ printk("RD 0x24 = %x\n", tmp); ++*/ ++ ++ adapter->fe = dvb_attach(mxl5xx_attach, i2c, ++ &tbs6909_mxl5xx_cfg, adapter->nr); ++ if (adapter->fe == NULL) ++ goto frontend_atach_fail; ++ ++ // adapter->fe->ops.diseqc_send_master_cmd = max_send_master_cmd; ++ // adapter->fe->ops.diseqc_send_burst = max_send_burst; ++ ++ if (tbsecp3_attach_sec(adapter, adapter->fe) == NULL) { ++ dev_warn(&dev->pci_dev->dev, ++ "error attaching lnb control on adapter %d\n", ++ adapter->nr); ++ } ++ ++ break; ++ ++ case 0x6910: ++ adapter->fe = dvb_attach(tas2101_attach, &tbs6910_demod_cfg[adapter->nr], i2c); ++ if (adapter->fe == NULL) ++ goto frontend_atach_fail; ++ ++ if (dvb_attach(av201x_attach, adapter->fe, &tbs6910_av201x_cfg, ++ tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) { ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_err(&dev->pci_dev->dev, ++ "frontend %d tuner attach failed\n", ++ adapter->nr); ++ goto frontend_atach_fail; ++ } ++ if (tbsecp3_attach_sec(adapter, adapter->fe) == NULL) { ++ dev_warn(&dev->pci_dev->dev, ++ "error attaching lnb control on adapter %d\n", ++ adapter->nr); ++ } ++ ++ tbsecp3_ca_init(adapter, adapter->nr); ++ break; ++ default: ++ dev_warn(&dev->pci_dev->dev, "unknonw card\n"); ++ return -ENODEV; ++ break; ++ } ++ strlcpy(adapter->fe->ops.info.name,tbsecp3_boards[pci->subsystem_vendor].name,52); ++ return 0; ++ ++frontend_atach_fail: ++ tbsecp3_i2c_remove_clients(adapter); ++ if (adapter->fe != NULL) ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ dev_err(&dev->pci_dev->dev, "TBSECP3 frontend %d attach failed\n", ++ adapter->nr); ++ ++ return -ENODEV; ++} ++ ++int tbsecp3_dvb_init(struct tbsecp3_adapter *adapter) ++{ ++ struct tbsecp3_dev *dev = adapter->dev; ++ struct dvb_adapter *adap = &adapter->dvb_adapter; ++ struct dvb_demux *dvbdemux = &adapter->demux; ++ struct dmxdev *dmxdev; ++ struct dmx_frontend *fe_hw; ++ struct dmx_frontend *fe_mem; ++ int ret; ++ ++ ret = dvb_register_adapter(adap, "TBSECP3 DVB Adapter", ++ THIS_MODULE, ++ &adapter->dev->pci_dev->dev, ++ adapter_nr); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "error registering adapter\n"); ++ if (ret == -ENFILE) ++ dev_err(&dev->pci_dev->dev, ++ "increase DVB_MAX_ADAPTERS (%d)\n", ++ DVB_MAX_ADAPTERS); ++ return ret; ++ } ++ ++ adap->priv = adapter; ++ dvbdemux->priv = adapter; ++ dvbdemux->filternum = 256; ++ dvbdemux->feednum = 256; ++ dvbdemux->start_feed = start_feed; ++ dvbdemux->stop_feed = stop_feed; ++ dvbdemux->write_to_decoder = NULL; ++ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | ++ DMX_SECTION_FILTERING | ++ DMX_MEMORY_BASED_FILTERING); ++ ++ ret = dvb_dmx_init(dvbdemux); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "dvb_dmx_init failed\n"); ++ goto err0; ++ } ++ ++ dmxdev = &adapter->dmxdev; ++ ++ dmxdev->filternum = 256; ++ dmxdev->demux = &dvbdemux->dmx; ++ dmxdev->capabilities = 0; ++ ++ ret = dvb_dmxdev_init(dmxdev, adap); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "dvb_dmxdev_init failed\n"); ++ goto err1; ++ } ++ ++ fe_hw = &adapter->fe_hw; ++ fe_mem = &adapter->fe_mem; ++ ++ fe_hw->source = DMX_FRONTEND_0; ++ ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, fe_hw); ++ if ( ret < 0) { ++ dev_err(&dev->pci_dev->dev, "dvb_dmx_init failed"); ++ goto err2; ++ } ++ ++ fe_mem->source = DMX_MEMORY_FE; ++ ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, fe_mem); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "dvb_dmx_init failed"); ++ goto err3; ++ } ++ ++ ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, fe_hw); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "dvb_dmx_init failed"); ++ goto err4; ++ } ++ ++ ret = dvb_net_init(adap, &adapter->dvbnet, adapter->dmxdev.demux); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "dvb_net_init failed"); ++ goto err5; ++ } ++ ++ tbsecp3_frontend_attach(adapter); ++ if (adapter->fe == NULL) { ++ dev_err(&dev->pci_dev->dev, "frontend attach failed\n"); ++ ret = -ENODEV; ++ goto err6; ++ } ++ ++ ret = dvb_register_frontend(adap, adapter->fe); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "frontend register failed\n"); ++ goto err7; ++ } ++ ++ if (adapter->fe2 != NULL) { ++ ret = dvb_register_frontend(adap, adapter->fe2); ++ if (ret < 0) { ++ dev_err(&dev->pci_dev->dev, "frontend2 register failed\n"); ++ } ++ } ++ ++ ++ return ret; ++ ++err7: ++ dvb_frontend_detach(adapter->fe); ++err6: ++ tbsecp3_release_sec(adapter->fe); ++ ++ dvb_net_release(&adapter->dvbnet); ++err5: ++ dvbdemux->dmx.close(&dvbdemux->dmx); ++err4: ++ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, fe_mem); ++err3: ++ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, fe_hw); ++err2: ++ dvb_dmxdev_release(dmxdev); ++err1: ++ dvb_dmx_release(dvbdemux); ++err0: ++ dvb_unregister_adapter(adap); ++ return ret; ++} ++ ++void tbsecp3_dvb_exit(struct tbsecp3_adapter *adapter) ++{ ++ struct dvb_adapter *adap = &adapter->dvb_adapter; ++ struct dvb_demux *dvbdemux = &adapter->demux; ++ ++ if (adapter->fe) { ++ tbsecp3_ca_release(adapter); ++ dvb_unregister_frontend(adapter->fe); ++ tbsecp3_release_sec(adapter->fe); ++ dvb_frontend_detach(adapter->fe); ++ adapter->fe = NULL; ++ ++ if (adapter->fe2 != NULL) { ++ dvb_unregister_frontend(adapter->fe2); ++ tbsecp3_release_sec(adapter->fe2); ++ dvb_frontend_detach(adapter->fe2); ++ adapter->fe2 = NULL; ++ } ++ } ++ dvb_net_release(&adapter->dvbnet); ++ dvbdemux->dmx.close(&dvbdemux->dmx); ++ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->fe_mem); ++ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->fe_hw); ++ dvb_dmxdev_release(&adapter->dmxdev); ++ dvb_dmx_release(&adapter->demux); ++ dvb_unregister_adapter(adap); ++} +diff --git a/drivers/media/pci/tbsecp3/tbsecp3-i2c.c b/drivers/media/pci/tbsecp3/tbsecp3-i2c.c +new file mode 100644 +index 0000000..2529e87 +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3-i2c.c +@@ -0,0 +1,211 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#include "tbsecp3.h" ++ ++union tbsecp3_i2c_ctrl { ++ struct { ++ u32 ctrl; ++ u32 data; ++ } raw; ++ struct { ++ u8 size:4; ++ u8 saddr:2; ++ u8 stop:1; ++ u8 start:1; ++ u8 read:1; ++ u8 addr:7; ++ u8 buf[6]; ++ } bits; ++}; ++ ++static int i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg, int num) ++{ ++ struct tbsecp3_i2c *bus = i2c_get_adapdata(adapter); ++ struct tbsecp3_dev *dev = bus->dev; ++ union tbsecp3_i2c_ctrl i2c_ctrl; ++ int i, j, retval; ++ u16 len, remaining, xfer_max; ++ u8 *b; ++ ++ mutex_lock(&bus->lock); ++ for (i = 0; i < num; i++) { ++ ++ b = msg[i].buf; ++ remaining = msg[i].len; ++ ++ i2c_ctrl.raw.ctrl = 0; ++ i2c_ctrl.bits.start = 1; ++ i2c_ctrl.bits.addr = msg[i].addr; ++ ++ if (msg[i].flags & I2C_M_RD) { ++ i2c_ctrl.bits.read = 1; ++ xfer_max = 4; ++ } else { ++ xfer_max = 6; ++ } ++ ++ do { ++ if (remaining <= xfer_max) ++ i2c_ctrl.bits.stop = 1; ++ ++ len = remaining > xfer_max ? xfer_max : remaining; ++ i2c_ctrl.bits.size = len; ++ ++ if (!(msg[i].flags & I2C_M_RD)) { ++ for (j = 0; j < len; j++) ++ i2c_ctrl.bits.buf[j] = *b++; ++ tbs_write(bus->base, TBSECP3_I2C_DATA, i2c_ctrl.raw.data); ++ } ++ bus->done = 0; ++ tbs_write(bus->base, TBSECP3_I2C_CTRL, i2c_ctrl.raw.ctrl); ++ retval = wait_event_timeout(bus->wq, bus->done == 1, HZ); ++ if (retval == 0) { ++ dev_err(&dev->pci_dev->dev, "i2c xfer timeout\n"); ++ retval = -EIO; ++ goto i2c_xfer_exit; ++ } ++ ++ j = tbs_read(bus->base, TBSECP3_I2C_CTRL); ++ if (j & 0x04) { ++ dev_err(&dev->pci_dev->dev, "i2c nack (%x)\n", j); ++ retval = -EIO; ++ goto i2c_xfer_exit; ++ } ++ ++ if (msg[i].flags & I2C_M_RD) { ++ i2c_ctrl.raw.data = tbs_read(bus->base, TBSECP3_I2C_DATA); ++ memcpy(b, &i2c_ctrl.raw.data, len); ++ b += len; ++ } ++ ++ i2c_ctrl.bits.start = 0; ++ remaining -= len; ++ } while (remaining); ++ ++ } ++ retval = num; ++i2c_xfer_exit: ++ mutex_unlock(&bus->lock); ++ return retval; ++} ++ ++static u32 i2c_functionality(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_SMBUS_EMUL; ++} ++ ++struct i2c_algorithm tbsecp3_i2c_algo_template = { ++ .master_xfer = i2c_xfer, ++ .functionality = i2c_functionality, ++}; ++ ++static int tbsecp3_i2c_register(struct tbsecp3_i2c *bus) ++{ ++ struct tbsecp3_dev *dev = bus->dev; ++ struct i2c_adapter *adap; ++ ++ init_waitqueue_head(&bus->wq); ++ mutex_init(&bus->lock); ++ ++ adap = &bus->i2c_adap; ++ strcpy(adap->name, "tbsecp3"); ++ adap->algo = &tbsecp3_i2c_algo_template; ++ adap->algo_data = (void*) bus; ++ adap->dev.parent = &dev->pci_dev->dev; ++ adap->owner = THIS_MODULE; ++ ++ strcpy(bus->i2c_client.name, "tbsecp3cli"); ++ bus->i2c_client.adapter = adap; ++ ++ i2c_set_adapdata(&bus->i2c_adap, bus); ++ return i2c_add_adapter(&bus->i2c_adap); ++} ++ ++static void tbsecp3_i2c_unregister(struct tbsecp3_i2c *bus) ++{ ++ i2c_del_adapter(&bus->i2c_adap); ++} ++ ++/* ----------------------------------------------------------------------- */ ++ ++void tbsecp3_i2c_remove_clients(struct tbsecp3_adapter *adapter) ++{ ++ struct i2c_client *client_demod, *client_tuner; ++ ++ /* remove tuner I2C client */ ++ client_tuner = adapter->i2c_client_tuner; ++ if (client_tuner) { ++ module_put(client_tuner->dev.driver->owner); ++ i2c_unregister_device(client_tuner); ++ adapter->i2c_client_tuner = NULL; ++ } ++ ++ /* remove demodulator I2C client */ ++ client_demod = adapter->i2c_client_demod; ++ if (client_demod) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ adapter->i2c_client_demod = NULL; ++ } ++} ++ ++void tbsecp3_i2c_reg_init(struct tbsecp3_dev *dev) ++{ ++ int i; ++ u32 baud = dev->info->i2c_speed; ++ ++ /* default to 400kbps */ ++ if (!baud) ++ baud = 9; ++ ++ for (i = 0; i < 4; i++) { ++ tbs_write(dev->i2c_bus[i].base, TBSECP3_I2C_BAUD, baud); ++ tbs_read(dev->i2c_bus[i].base, TBSECP3_I2C_STAT); ++ tbs_write(TBSECP3_INT_BASE, TBSECP3_I2C_IE(i), 1); ++ } ++} ++ ++int tbsecp3_i2c_init(struct tbsecp3_dev *dev) ++{ ++ int i, ret = 0; ++ ++ /* I2C Defaults / setup */ ++ for (i = 0; i < 4; i++) { ++ dev->i2c_bus[i].base = TBSECP3_I2C_BASE(i); ++ dev->i2c_bus[i].dev = dev; ++ ret = tbsecp3_i2c_register(&dev->i2c_bus[i]); ++ if (ret) ++ break; ++ } ++ if (ret) { ++ do { ++ tbsecp3_i2c_unregister(&dev->i2c_bus[i]); ++ } while (i-- > 0); ++ } else { ++ tbsecp3_i2c_reg_init(dev); ++ } ++ return ret; ++} ++ ++void tbsecp3_i2c_exit(struct tbsecp3_dev *dev) ++{ ++ int i; ++ for (i = 0; i < 4; i++) ++ tbsecp3_i2c_unregister(&dev->i2c_bus[i]); ++} ++ +diff --git a/drivers/media/pci/tbsecp3/tbsecp3-regs.h b/drivers/media/pci/tbsecp3/tbsecp3-regs.h +new file mode 100644 +index 0000000..82e81ff +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3-regs.h +@@ -0,0 +1,53 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#ifndef _TBSECP3_REGS_H_ ++#define _TBSECP3_REGS_H_ ++ ++/* GPIO */ ++#define TBSECP3_GPIO_BASE 0x0000 ++#define TBSECP3_GPIO_PIN(_bank, _pin) (((_bank) << 5) + _pin) ++ ++/* I2C */ ++#define TBSECP3_I2C_BASE(_n) (0x4000 + 0x1000 * _n) ++#define TBSECP3_I2C_STAT 0x0000 ++#define TBSECP3_I2C_CTRL 0x0000 ++#define TBSECP3_I2C_DATA 0x0004 ++#define TBSECP3_I2C_BAUD 0x0008 ++ ++/* CA */ ++#define TBSECP3_CA_BASE(_n) (0x6000 + 0x1000 * _n) ++ ++/* DMA */ ++#define TBSECP3_DMA_BASE(_n) (_n < 4) ? (0x8000 + 0x1000 * _n) : (0x8800 + 0x1000 * (_n - 4)) ++#define TBSECP3_DMA_STAT 0x0000 ++#define TBSECP3_DMA_EN 0x0000 ++#define TBSECP3_DMA_TSIZE 0x0004 ++#define TBSECP3_DMA_ADDRH 0x0008 ++#define TBSECP3_DMA_ADDRL 0x000c ++#define TBSECP3_DMA_BSIZE 0x0010 ++ ++/* INTR */ ++#define TBSECP3_INT_BASE 0xc000 ++#define TBSECP3_INT_STAT 0x0000 ++#define TBSECP3_INT_EN 0x0004 ++#define TBSECP3_I2C_IE(_n) (0x0008 + 4 * _n) ++#define TBSECP3_DMA_IE(_n) (0x0018 + 4 * _n) ++#define TBSECP3_I2C_IF(_n) (0x0001 << _n) ++#define TBSECP3_DMA_IF(_n) (0x0010 << _n) ++ ++#endif +diff --git a/drivers/media/pci/tbsecp3/tbsecp3.h b/drivers/media/pci/tbsecp3/tbsecp3.h +new file mode 100644 +index 0000000..fdfba5d +--- /dev/null ++++ b/drivers/media/pci/tbsecp3/tbsecp3.h +@@ -0,0 +1,210 @@ ++/* ++ TBS ECP3 FPGA based cards PCIe driver ++ ++ 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 3 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 . ++*/ ++ ++#ifndef _TBSECP3_H_ ++#define _TBSECP3_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "demux.h" ++#include "dmxdev.h" ++#include "dvb_demux.h" ++#include "dvb_frontend.h" ++#include "dvb_net.h" ++#include "dvbdev.h" ++#include "tbsecp3-regs.h" ++#include "dvb_ca_en50221.h" ++ ++ ++#define TBSECP3_VID 0x544d ++#define TBSECP3_PID 0x6178 ++ ++#define TBSECP3_BOARD_TBS6205 0x6205 ++#define TBSECP3_BOARD_TBS6522 0x6522 ++#define TBSECP3_BOARD_TBS6902 0x6902 ++#define TBSECP3_BOARD_TBS6903 0x6903 ++#define TBSECP3_BOARD_TBS6904 0x6904 ++#define TBSECP3_BOARD_TBS6905 0x6905 ++#define TBSECP3_BOARD_TBS6908 0x6908 ++#define TBSECP3_BOARD_TBS6909 0x6909 ++#define TBSECP3_BOARD_TBS6910 0x6910 ++#define TBSECP3_BOARD_TBS6528 0x6528 ++#define TBSECP3_BOARD_TBS6590 0x6590 ++#define TBSECP3_BOARD_TBS6290SE 0x6290 ++#define TBSECP3_BOARD_TBS6281SE 0x6281 ++#define TBSECP3_BOARD_TBS6704 0x6704 ++#define TBSECP3_BOARD_TBS6209 0x6209 ++#define TBSECP3_BOARD_TBS6814 0x6814 ++ ++#define TBSECP3_MAX_ADAPTERS (8) ++#define TBSECP3_MAX_I2C_BUS (4) ++ ++#define TBSECP3_GPIODEF_NONE (0) ++#define TBSECP3_GPIODEF_HIGH (1) ++#define TBSECP3_GPIODEF_LOW (2) ++ ++#define TBSECP3_DMA_BUFFERS 8 ++ ++ ++struct tbsecp3_dev; ++ ++ ++struct tbsecp3_gpio_pin { ++ u8 lvl; ++ u8 nr; ++}; ++ ++struct tbsecp3_gpio_config { ++ struct tbsecp3_gpio_pin lnb_power; ++ struct tbsecp3_gpio_pin lnb_voltage; ++ struct tbsecp3_gpio_pin demod_reset; ++}; ++ ++struct tbsecp3_adap_config { ++ u32 ts_in; ++ u8 i2c_bus_nr; ++ struct tbsecp3_gpio_config gpio; ++}; ++ ++struct tbsecp3_board { ++ char *name; ++ int adapters; ++ u32 i2c_speed; ++ u8 eeprom_i2c; ++ u8 eeprom_addr; ++ struct tbsecp3_adap_config adap_config[8]; ++}; ++ ++struct tbsecp3_i2c { ++ struct tbsecp3_dev *dev; ++ u32 base; ++ ++ struct i2c_adapter i2c_adap; ++ struct i2c_client i2c_client; ++ ++ struct mutex lock; ++ wait_queue_head_t wq; ++ bool done; ++}; ++ ++struct tbsecp3_dma_channel { ++ u32 base; ++ dma_addr_t dma_addr; ++ u8 *buf[TBSECP3_DMA_BUFFERS + 1]; ++ u8 offset; ++ u8 cnt; ++}; ++ ++struct tbsecp3_ca { ++ int nr; ++ u32 base; ++ struct dvb_ca_en50221 ca; ++ ++ struct tbsecp3_adapter *adapter; ++ struct mutex lock; ++ int status; ++}; ++ ++struct tbsecp3_adapter { ++ int nr; ++ struct tbsecp3_adap_config *cfg; ++ ++ /* parent device */ ++ struct tbsecp3_dev *dev; ++ ++ /* i2c */ ++ struct tbsecp3_i2c *i2c; ++ struct i2c_client *i2c_client_demod; ++ struct i2c_client *i2c_client_tuner; ++ ++ /* dvb */ ++ struct dvb_adapter dvb_adapter; ++ struct dvb_frontend *fe; ++ struct dvb_frontend *fe2; ++ struct dvb_frontend _fe2; ++ struct dvb_demux demux; ++ struct dmxdev dmxdev; ++ struct dvb_net dvbnet; ++ struct dmx_frontend fe_hw; ++ struct dmx_frontend fe_mem; ++ int feeds; ++ ++ /* dma */ ++ spinlock_t adap_lock; ++ struct tasklet_struct tasklet; ++ struct tbsecp3_dma_channel dma; ++ ++ /* ca interface */ ++ struct tbsecp3_ca *tbsca; ++}; ++ ++struct tbsecp3_dev { ++ struct tbsecp3_board *info; ++ ++ /* pcie */ ++ struct pci_dev *pci_dev; ++ void __iomem *lmmio; ++ bool msi; ++ ++ /* dvb adapters */ ++ struct tbsecp3_adapter adapter[TBSECP3_MAX_ADAPTERS]; ++ ++ /* i2c */ ++ struct tbsecp3_i2c i2c_bus[TBSECP3_MAX_I2C_BUS]; ++}; ++ ++#define tbs_read(_b, _o) readl(dev->lmmio + (_b + _o)) ++#define tbs_write(_b, _o, _v) writel((_v), dev->lmmio + (_b + _o)) ++ ++ ++/* tbsecp3-core.c */ ++void tbsecp3_gpio_set_pin(struct tbsecp3_dev *dev, ++ struct tbsecp3_gpio_pin *pin, int state); ++ ++/* tbspcie-i2c.c */ ++extern int tbsecp3_i2c_init(struct tbsecp3_dev *dev); ++extern void tbsecp3_i2c_exit(struct tbsecp3_dev *dev); ++extern void tbsecp3_i2c_reg_init(struct tbsecp3_dev *dev); ++extern void tbsecp3_i2c_remove_clients(struct tbsecp3_adapter *adapter); ++ ++/* tbspcie-cards.c */ ++extern struct tbsecp3_board tbsecp3_boards[]; ++ ++/* tbspcie-dvb.c */ ++extern int tbsecp3_dvb_init(struct tbsecp3_adapter *adapter); ++extern void tbsecp3_dvb_exit(struct tbsecp3_adapter *adapter); ++ ++/* tbsecp3-dma.c */ ++extern int tbsecp3_dma_init(struct tbsecp3_dev *dev); ++extern void tbsecp3_dma_free(struct tbsecp3_dev *dev); ++extern void tbsecp3_dma_reg_init(struct tbsecp3_dev *dev); ++extern void tbsecp3_dma_enable(struct tbsecp3_adapter *adap); ++extern void tbsecp3_dma_disable(struct tbsecp3_adapter *adap); ++ ++/* tbsecp3-ca.c */ ++int tbsecp3_ca_init(struct tbsecp3_adapter *adap, int nr); ++void tbsecp3_ca_release(struct tbsecp3_adapter *adap); ++ ++#endif +diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c +index 9bf6917..998be9c 100644 +--- a/drivers/media/rc/mceusb.c ++++ b/drivers/media/rc/mceusb.c +@@ -192,6 +192,7 @@ enum mceusb_model_type { + TIVO_KIT, + MCE_GEN2_NO_TX, + HAUPPAUGE_CX_HYBRID_TV, ++ CX231XX_TBS5280, + }; + + struct mceusb_model { +@@ -251,6 +252,10 @@ static const struct mceusb_model mceusb_model[] = { + .mce_gen2 = 1, + .rc_map = RC_MAP_TIVO, + }, ++ [CX231XX_TBS5280] = { ++ .rc_map = RC_MAP_RC6_MCE, ++ .name = "TurboSight TBS 5280 (cx231xx) MCE IR", ++ }, + }; + + static struct usb_device_id mceusb_dev_table[] = { +diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig +index 05998f0..8e40db5 100644 +--- a/drivers/media/tuners/Kconfig ++++ b/drivers/media/tuners/Kconfig +@@ -49,6 +49,13 @@ config MEDIA_TUNER_TDA18271 + help + A silicon tuner module. Say Y when you want to support this tuner. + ++config MEDIA_TUNER_TDA18273 ++ tristate "NXP TDA18273 silicon tuner" ++ depends on MEDIA_SUPPORT && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A silicon tuner module. Say Y when you want to support this tuner. ++ + config MEDIA_TUNER_TDA9887 + tristate "TDA 9885/6/7 analog IF demodulator" + depends on MEDIA_SUPPORT && I2C +@@ -277,4 +284,35 @@ config MEDIA_TUNER_QM1D1C0042 + default m if !MEDIA_SUBDRV_AUTOSELECT + help + Sharp QM1D1C0042 trellis coded 8PSK tuner driver. ++ ++config MEDIA_TUNER_AV201X ++ tristate "Airoha Technology AV201x silicon tuner" ++ depends on MEDIA_SUPPORT && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ Airoha Technology AV201x silicon tuner driver. ++ ++config MEDIA_TUNER_STV6120 ++ tristate "STV6120 silicon tuner" ++ depends on MEDIA_SUPPORT && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ STV6120 silicon tuner driver. ++ ++config MEDIA_TUNER_R848 ++ tristate "Rafael Micro R848 silicon tuner" ++ depends on MEDIA_SUPPORT && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ select BITREVERSE ++ help ++ Rafael Micro R848 silicon tuner driver. ++ ++config MEDIA_TUNER_MXL603 ++ tristate "MaxLinear mxl603 silicon tuner" ++ depends on MEDIA_SUPPORT && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ select BITREVERSE ++ help ++ A driver for the silicon tuner MXL603 from MaxLinear. ++ + endmenu +diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile +index 06a9ab6..56e7d0e 100644 +--- a/drivers/media/tuners/Makefile ++++ b/drivers/media/tuners/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_MEDIA_TUNER_TEA5761) += tea5761.o + obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o + obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o + obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o ++obj-$(CONFIG_MEDIA_TUNER_TDA18273) += tda18273.o + obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o + obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o + obj-$(CONFIG_MEDIA_TUNER_MSI001) += msi001.o +@@ -41,6 +42,10 @@ obj-$(CONFIG_MEDIA_TUNER_R820T) += r820t.o + obj-$(CONFIG_MEDIA_TUNER_MXL301RF) += mxl301rf.o + obj-$(CONFIG_MEDIA_TUNER_QM1D1C0042) += qm1d1c0042.o + obj-$(CONFIG_MEDIA_TUNER_M88RS6000T) += m88rs6000t.o ++obj-$(CONFIG_MEDIA_TUNER_AV201X) += av201x.o ++obj-$(CONFIG_MEDIA_TUNER_STV6120) += stv6120.o ++obj-$(CONFIG_MEDIA_TUNER_R848) += r848.o ++obj-$(CONFIG_MEDIA_TUNER_MXL603) += mxl603.o + + ccflags-y += -I$(srctree)/drivers/media/dvb-core + ccflags-y += -I$(srctree)/drivers/media/dvb-frontends +diff --git a/drivers/media/tuners/av201x.c b/drivers/media/tuners/av201x.c +new file mode 100644 +index 0000000..0b40cea +--- /dev/null ++++ b/drivers/media/tuners/av201x.c +@@ -0,0 +1,305 @@ ++/* ++ * AV201x Airoha Technology silicon tuner driver ++ * ++ * Copyright (C) 2014 Luis Alves ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "av201x.h" ++#include "av201x_priv.h" ++ ++/* write multiple (continuous) registers */ ++static int av201x_wrm(struct av201x_priv *priv, u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg = { ++ .addr = priv->cfg->i2c_address, ++ .flags = 0, .buf = buf, .len = len }; ++ ++ dev_dbg(&priv->i2c->dev, "%s() i2c wrm @0x%02x (len=%d) ", ++ __func__, buf[0], len); ++ ++ ret = i2c_transfer(priv->i2c, &msg, 1); ++ if (ret < 0) { ++ dev_warn(&priv->i2c->dev, ++ "%s: i2c wrm err(%i) @0x%02x (len=%d)\n", ++ KBUILD_MODNAME, ret, buf[0], len); ++ return ret; ++ } ++ return 0; ++} ++ ++/* write one register */ ++static int av201x_wr(struct av201x_priv *priv, u8 addr, u8 data) ++{ ++ u8 buf[] = { addr, data }; ++ return av201x_wrm(priv, buf, 2); ++} ++ ++/* read multiple (continuous) registers starting at addr */ ++static int av201x_rdm(struct av201x_priv *priv, u8 addr, u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg[] = { ++ { .addr = priv->cfg->i2c_address, .flags = 0, ++ .buf = &addr, .len = 1 }, ++ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, ++ .buf = buf, .len = len } ++ }; ++ ++ dev_dbg(&priv->i2c->dev, "%s() i2c rdm @0x%02x (len=%d)\n", ++ __func__, addr, len); ++ ++ ret = i2c_transfer(priv->i2c, msg, 2); ++ if (ret < 0) { ++ dev_warn(&priv->i2c->dev, ++ "%s: i2c rdm err(%i) @0x%02x (len=%d)\n", ++ KBUILD_MODNAME, ret, addr, len); ++ return ret; ++ } ++ return 0; ++} ++ ++/* read one register */ ++static int av201x_rd(struct av201x_priv *priv, u8 addr, u8 *data) ++{ ++ return av201x_rdm(priv, addr, data, 1); ++} ++ ++/* read register, apply masks, write back */ ++static int av201x_regmask(struct av201x_priv *priv, ++ u8 reg, u8 setmask, u8 clrmask) ++{ ++ int ret; ++ u8 b = 0; ++ if (clrmask != 0xff) { ++ ret = av201x_rd(priv, reg, &b); ++ if (ret) ++ return ret; ++ b &= ~clrmask; ++ } ++ return av201x_wr(priv, reg, b | setmask); ++} ++ ++static int av201x_wrtable(struct av201x_priv *priv, ++ struct av201x_regtable *regtable, int len) ++{ ++ int ret, i; ++ ++ for (i = 0; i < len; i++) { ++ ret = av201x_regmask(priv, regtable[i].addr, ++ regtable[i].setmask, regtable[i].clrmask); ++ if (ret) ++ return ret; ++ if (regtable[i].sleep) ++ msleep(regtable[i].sleep); ++ } ++ return 0; ++} ++ ++static int av201x_release(struct dvb_frontend *fe) ++{ ++ struct av201x_priv *priv = fe->tuner_priv; ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ return 0; ++} ++ ++static int av201x_init(struct dvb_frontend *fe) ++{ ++ struct av201x_priv *priv = fe->tuner_priv; ++ int ret; ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ ret = av201x_wrtable(priv, av201x_inittuner0, ++ ARRAY_SIZE(av201x_inittuner0)); ++ ++ switch (priv->cfg->id) { ++ case ID_AV2011: ++ ret |= av201x_wrtable(priv, av201x_inittuner1a, ++ ARRAY_SIZE(av201x_inittuner1a)); ++ break; ++ case ID_AV2012: ++ default: ++ ret |= av201x_wrtable(priv, av201x_inittuner1b, ++ ARRAY_SIZE(av201x_inittuner1b)); ++ break; ++ } ++ ++ ret |= av201x_wrtable(priv, av201x_inittuner2, ++ ARRAY_SIZE(av201x_inittuner2)); ++ ++ ret |= av201x_wr(priv, REG_TUNER_CTRL, 0x96); ++ ++ msleep(120); ++ ++ if (ret) ++ dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__); ++ return ret; ++} ++ ++static int av201x_sleep(struct dvb_frontend *fe) ++{ ++ struct av201x_priv *priv = fe->tuner_priv; ++ int ret; ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ ret = av201x_regmask(priv, REG_TUNER_CTRL, AV201X_SLEEP, 0); ++ if (ret) ++ dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__); ++ return ret; ++} ++ ++static int av201x_set_params(struct dvb_frontend *fe) ++{ ++ struct av201x_priv *priv = fe->tuner_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u32 n, bw, bf; ++ u8 buf[5]; ++ int ret; ++ ++ dev_dbg(&priv->i2c->dev, "%s() delivery_system=%d frequency=%d " \ ++ "symbol_rate=%d\n", __func__, ++ c->delivery_system, c->frequency, c->symbol_rate); ++ ++ /* ++ ** PLL setup ** ++ RF = (pll_N * ref_freq) / pll_M ++ pll_M = fixed 0x10000 ++ PLL output is divided by 2 ++ REG_FN = pll_M<24:0> ++ */ ++ buf[0] = REG_FN; ++ n = DIV_ROUND_CLOSEST(c->frequency, priv->cfg->xtal_freq); ++ buf[1] = (n > 0xff) ? 0xff : (u8) n; ++ n = DIV_ROUND_CLOSEST((c->frequency / 1000) << 17, priv->cfg->xtal_freq / 1000); ++ buf[2] = (u8) (n >> 9); ++ buf[3] = (u8) (n >> 1); ++ buf[4] = (u8) (((n << 7) & 0x80) | 0x50); ++ ret = av201x_wrm(priv, buf, 5); ++ if (ret) ++ goto exit; ++ ++ msleep(20); ++ ++ /* set bandwidth */ ++ bw = (c->symbol_rate / 1000) * 135/200; ++ if (c->symbol_rate < 6500000) ++ bw += 6000; ++ bw += 2000; ++ bw *= 108/100; ++ ++ /* check limits (4MHz < bw < 40MHz) */ ++ if (bw > 40000) ++ bw = 40000; ++ else if (bw < 4000) ++ bw = 4000; ++ ++ /* bandwidth step = 211kHz */ ++ bf = DIV_ROUND_CLOSEST(bw * 127, 21100); ++ ret = av201x_wr(priv, REG_BWFILTER, (u8) bf); ++ ++ /* enable fine tune agc */ ++ ret |= av201x_wr(priv, REG_FT_CTRL, AV201X_FT_EN | AV201X_FT_BLK); ++ ++ ret |= av201x_wr(priv, REG_TUNER_CTRL, 0x96); ++ msleep(20); ++exit: ++ if (ret) ++ dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__); ++ return ret; ++} ++ ++static int AV201x_agc [] = { 0, 82, 100, 116, 140, 162, 173, 187, 210, 223, 254, 255}; ++static int AV201x_level_dBm_10[] = { 90, -50, -263, -361, -463, -563, -661, -761, -861, -891, -904, -910}; ++ ++static int av201x_get_rf_strength(struct dvb_frontend *fe, u16 *st) ++{ ++ struct av201x_priv *priv = fe->tuner_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int if_agc, index, table_length, slope, *x, *y; ++ ++ if_agc = *st; ++ x = AV201x_agc; ++ y = AV201x_level_dBm_10; ++ table_length = sizeof(AV201x_agc)/sizeof(int); ++ ++ ++ /* Finding in which segment the if_agc value is */ ++ for (index = 0; index < table_length; index ++) ++ if (x[index] > if_agc ) break; ++ ++ /* Computing segment slope */ ++ slope = ((y[index]-y[index-1])*1000)/(x[index]-x[index-1]); ++ /* Linear approximation of rssi value in segment (rssi values will be in 0.1dBm unit: '-523' means -52.3 dBm) */ ++ *st = 1000 + ((y[index-1] + ((if_agc - x[index-1])*slope + 500)/1000))/10; ++ ++ c->strength.len = 1; ++ c->strength.stat[0].scale = FE_SCALE_DECIBEL; ++ c->strength.stat[0].svalue = ((y[index-1] + ((if_agc - x[index-1])*slope + 500)/1000)) * 100; ++ ++ return 0; ++} ++ ++ ++static const struct dvb_tuner_ops av201x_tuner_ops = { ++ .info = { ++ .name = "Airoha Technology AV201x", ++ ++ .frequency_min = 850000, ++ .frequency_max = 2300000, ++ .frequency_step = 206, ++ }, ++ ++ .release = av201x_release, ++ ++ .init = av201x_init, ++ .sleep = av201x_sleep, ++ .set_params = av201x_set_params, ++ .get_rf_strength = av201x_get_rf_strength, ++}; ++ ++struct dvb_frontend *av201x_attach(struct dvb_frontend *fe, ++ struct av201x_config *cfg, struct i2c_adapter *i2c) ++{ ++ struct av201x_priv *priv = NULL; ++ ++ priv = kzalloc(sizeof(struct av201x_priv), GFP_KERNEL); ++ if (priv == NULL) { ++ dev_dbg(&i2c->dev, "%s() attach failed\n", __func__); ++ return NULL; ++ } ++ ++ priv->cfg = cfg; ++ priv->i2c = i2c; ++ ++ dev_info(&priv->i2c->dev, ++ "%s: Airoha Technology AV201x successfully attached\n", ++ KBUILD_MODNAME); ++ ++ memcpy(&fe->ops.tuner_ops, &av201x_tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ ++ fe->tuner_priv = priv; ++ return fe; ++} ++EXPORT_SYMBOL(av201x_attach); ++ ++MODULE_DESCRIPTION("Airoha Technology AV201x silicon tuner driver"); ++MODULE_AUTHOR("Luis Alves "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/tuners/av201x.h b/drivers/media/tuners/av201x.h +new file mode 100644 +index 0000000..1a7b2fa +--- /dev/null ++++ b/drivers/media/tuners/av201x.h +@@ -0,0 +1,55 @@ ++/* ++ * AV201x Airoha Technology silicon tuner driver ++ * ++ * Copyright (C) 2014 Luis Alves ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AV201X_H ++#define AV201X_H ++ ++#include ++#include "dvb_frontend.h" ++ ++typedef enum av201x_id { ++ ID_AV2011, ++ ID_AV2012, ++ ID_AV2018, ++} av201x_id_t; ++ ++struct av201x_config { ++ /* tuner i2c address */ ++ u8 i2c_address; ++ /* tuner type */ ++ av201x_id_t id; ++ ++ /* crystal freq in kHz */ ++ u32 xtal_freq; ++}; ++ ++#if IS_ENABLED(CONFIG_MEDIA_TUNER_AV201X) ++extern struct dvb_frontend *av201x_attach(struct dvb_frontend *fe, ++ struct av201x_config *cfg, struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *av201x_attach(struct dvb_frontend *fe, ++ struct av201x_config *cfg, struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif ++ ++#endif /* AV201X_H */ +diff --git a/drivers/media/tuners/av201x_priv.h b/drivers/media/tuners/av201x_priv.h +new file mode 100644 +index 0000000..c56ba20 +--- /dev/null ++++ b/drivers/media/tuners/av201x_priv.h +@@ -0,0 +1,110 @@ ++/* ++ * AV201x Airoha Technology silicon tuner driver ++ * ++ * Copyright (C) 2014 Luis Alves ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AV201X_PRIV_H ++#define AV201X_PRIV_H ++ ++struct av201x_priv { ++ struct av201x_config *cfg; ++ struct i2c_adapter *i2c; ++}; ++ ++enum av201x_regs_addr { ++ REG_FN = 0x00, ++ REG_BWFILTER = 0x05, ++ REG_TUNER_STAT = 0x0b, ++ REG_TUNER_CTRL = 0x0c, ++ REG_FT_CTRL = 0x25, ++}; ++ ++/* REG_TUNER_STAT */ ++#define AV201X_PLLLOCK (1<<0) ++ ++/* REG_TUNER_CTRL */ ++#define AV201X_SLEEP (1<<5) ++#define AV201X_RFLP (1<<6) ++ ++/* REG_FT_CTRL */ ++#define AV201X_FT_EN (1<<1) ++#define AV201X_FT_BLK (1<<2) ++ ++struct av201x_regtable { ++ u8 addr; ++ u8 setmask; ++ u8 clrmask; ++ int sleep; ++}; ++ ++static struct av201x_regtable av201x_inittuner0[] = { ++ {0x00, 0x38, 0xff, 0}, ++ {0x01, 0x00, 0xff, 0}, ++ {0x02, 0x00, 0xff, 0}, ++ {0x03, 0x50, 0xff, 0}, ++ {0x04, 0x1f, 0xff, 0}, ++ {0x05, 0xa3, 0xff, 0}, ++ {0x06, 0xfd, 0xff, 0}, ++ {0x07, 0x58, 0xff, 0}, ++ {0x08, 0x36, 0xff, 0}, ++ {0x09, 0xc2, 0xff, 0}, ++ {0x0a, 0x88, 0xff, 0}, ++ {0x0b, 0xb4, 0xff, 20}, ++ {0x0d, 0x40, 0xff, 0}, ++}; ++ ++static struct av201x_regtable av201x_inittuner1a[] = { ++ {0x0e, 0x94, 0xff, 0}, ++ {0x0f, 0x9a, 0xff, 0}, ++}; ++ ++static struct av201x_regtable av201x_inittuner1b[] = { ++ {0x0e, 0x5b, 0xff, 0}, ++ {0x0f, 0x6a, 0xff, 0}, ++}; ++ ++static struct av201x_regtable av201x_inittuner2[] = { ++ {0x10, 0x66, 0xff, 0}, ++ {0x11, 0x40, 0xff, 0}, ++ {0x12, 0x80, 0xff, 0}, ++ {0x13, 0x2b, 0xff, 0}, ++ {0x14, 0x6a, 0xff, 0}, ++ {0x15, 0x50, 0xff, 0}, ++ {0x16, 0x91, 0xff, 0}, ++ {0x17, 0x27, 0xff, 0}, ++ {0x18, 0x8f, 0xff, 0}, ++ {0x19, 0xcc, 0xff, 0}, ++ {0x1a, 0x21, 0xff, 0}, ++ {0x1b, 0x10, 0xff, 0}, ++ {0x1c, 0x80, 0xff, 0}, ++ {0x1d, 0x02, 0xff, 0}, ++ {0x1e, 0xf5, 0xff, 0}, ++ {0x1f, 0x7f, 0xff, 0}, ++ {0x20, 0x4a, 0xff, 0}, ++ {0x21, 0x9b, 0xff, 0}, ++ {0x22, 0xe0, 0xff, 0}, ++ {0x23, 0xe0, 0xff, 0}, ++ {0x24, 0x36, 0xff, 0}, ++ {0x25, 0x00, 0xff, 0}, ++ {0x26, 0xab, 0xff, 0}, ++ {0x27, 0x97, 0xff, 0}, ++ {0x28, 0xc5, 0xff, 0}, ++ {0x29, 0xa8, 0xff, 20}, ++}; ++ ++#endif /* AV201X_PRIV_H */ +diff --git a/drivers/media/tuners/mxl603.c b/drivers/media/tuners/mxl603.c +new file mode 100644 +index 0000000..424658e +--- /dev/null ++++ b/drivers/media/tuners/mxl603.c +@@ -0,0 +1,586 @@ ++ ++ ++#include "mxl603_priv.h" ++ ++static const struct dvb_tuner_ops si2168_ops; ++ ++static int reg_read(struct i2c_client *client,u8 reg_addr,u8 *val) ++{ ++ int ret; ++ u8 reg_buf[2] = {0xFB,reg_addr}; ++ ++ struct i2c_msg msg[] = { ++ {.addr = client->addr,.flags = 0 , .buf = reg_buf, .len = 2}, ++ {.addr = client->addr, .flags = I2C_M_RD, .buf = val, .len = 1}, ++ ++ }; ++ ++ ret = i2c_transfer(client->adapter,msg,2); ++ ++ if(ret!=2) ++ { ++ pr_warn("i2c read reg error !!"); ++ if (ret < 0) ++ return ret; ++ else ++ return -EREMOTEIO; ++ } ++ return 0 ; ++ ++} ++static int reg_write(struct i2c_client *client,u8 reg_addr,u8 val) ++{ ++ int ret; ++ u8 buf[2]={reg_addr,val}; ++ struct i2c_msg msg ={.addr = client->addr, .flags = 0, .buf = buf, .len = 2}; ++ ++ if((ret = i2c_transfer (client->adapter,&msg,1))!=1){ ++ pr_warn("%s: i2c write error (addr 0x%02x, ret == %i)\n", ++ __func__, reg_addr, ret); ++ return -EREMOTEIO; ++ } ++ return 0; ++} ++static int mxl603_ctrl_programRegisters(struct i2c_client *client, PMXL603_REG_CTRL_INFO_T ctrlRegInfoPtr) ++{ ++ struct mxl603_dev* dev = i2c_get_clientdata(client); ++ int ret = 0; ++ u8 tmp =0 ; ++ u16 i = 0; ++ ++ while (!ret) ++ { ++ if ((ctrlRegInfoPtr[i].regAddr == 0) && (ctrlRegInfoPtr[i].mask == 0) && (ctrlRegInfoPtr[i].data == 0)) break; ++ ++ // Check if partial bits of register were updated ++ if (ctrlRegInfoPtr[i].mask != 0xFF) ++ { ++ ret = reg_read(dev->client,ctrlRegInfoPtr[i].regAddr, (int)&tmp); ++ if (ret) break;; ++ } ++ ++ tmp &= (u8) ~ctrlRegInfoPtr[i].mask; ++ tmp |= (u8) ctrlRegInfoPtr[i].data; ++ ++ ret = reg_write(dev->client,ctrlRegInfoPtr[i].regAddr, tmp); ++ if (ret) break; ++ ++ i++; ++ } ++ ++ ++ return ret; ++ ++} ++static int mxl603_init(struct dvb_frontend *fe) ++{ ++ struct i2c_client*client = fe->tuner_priv; ++ struct mxl603_dev*dev = i2c_get_clientdata(client); ++ ++ int ret; ++ u8 readData; ++ u8 dfeRegData; ++ u8 control = 0; ++ u16 ifFcw; ++ MXL603_REG_CTRL_INFO_T MxL603_OverwriteDefaults[] = ++ { ++ {0x14, 0xFF, 0x13}, ++ {0x6D, 0xFF, 0x8A}, ++ {0x6D, 0xFF, 0x0A}, ++ {0xDF, 0xFF, 0x19}, ++ {0x45, 0xFF, 0x1B}, ++ {0xA9, 0xFF, 0x59}, ++ {0xAA, 0xFF, 0x6A}, ++ {0xBE, 0xFF, 0x4C}, ++ {0xCF, 0xFF, 0x25}, ++ {0xD0, 0xFF, 0x34}, ++ {0x77, 0xFF, 0xE7}, ++ {0x78, 0xFF, 0xE3}, ++ {0x6F, 0xFF, 0x51}, ++ {0x7B, 0xFF, 0x84}, ++ {0x7C, 0xFF, 0x9F}, ++ {0x56, 0xFF, 0x41}, ++ {0xCD, 0xFF, 0x64}, ++ {0xC3, 0xFF, 0x2C}, ++ {0x9D, 0xFF, 0x61}, ++ {0xF7, 0xFF, 0x52}, ++ {0x58, 0xFF, 0x81}, ++ {0x00, 0xFF, 0x01}, ++ {0x62, 0xFF, 0x02}, ++ {0x00, 0xFF, 0x00}, ++ {0, 0, 0} ++ }; ++ ++ ++ /*reset the chip*/ ++ ret = reg_write(dev->client,AIC_RESET_REG, 0x00); ++ ++ ret = mxl603_ctrl_programRegisters(client,MxL603_OverwriteDefaults); ++ ret |= reg_write(dev->client,0x00,0x01); ++ ret |= reg_read(dev->client,0x31,&readData); ++ if(ret) ++ goto err; ++ ++ readData &= 0x2F; ++ readData |= 0xD0; ++ ++ ret = reg_write(dev->client,0x31,readData); ++ ret |= reg_write(dev->client,0x0,0x0); ++ ++ /*If Single supply 3.3v is used */ ++ ret |= reg_write(dev->client,MAIN_REG_AMP,0x04); ++ ++ /**setup xtal**/ ++ ++ control = ((dev->xtalFreqSel << 5) | (dev->xtalCap & 0x1F)); ++ control |= (1 << 7); ++ ret = reg_write(dev->client, XTAL_CAP_CTRL_REG, control); ++ ++ // program Clock out div & Xtal sharing ++ ret |= reg_write(dev->client, XTAL_ENABLE_DIV_REG, 0x40); ++ ++ // Main regulator re-program ++ ret |= reg_write(client, MAIN_REG_AMP, 0x14); ++ if(ret) ++ goto err; ++ ++ /*setup IF out*/ ++ ret = reg_read(client,IF_FREQ_SEL_REG, &readData); ++ if(dev->manualIFFreqSet) ++ { ++ // IF out manual setting : bit<5> ++ readData |= 0x20; ++ ret = reg_write(client, IF_FREQ_SEL_REG, readData); ++ ++ // Manual IF freq set ++ ifFcw = (u16)(dev->manualIFOutFreqInKHz * 8192 / 216000); ++ control = (ifFcw & 0xFF); // Get low 8 bit ++ ret |= reg_write(client, IF_FCW_LOW_REG, control); ++ ++ control = ((ifFcw >> 8) & 0x0F); // Get high 4 bit ++ ret |= reg_write(client, IF_FCW_HIGH_REG, control); ++ } ++ else ++ { ++ readData &= 0xC0; ++ // IF Freq <4:0> ++ readData |= dev->ifOutFreq; ++ ret |= reg_write(client, IF_FREQ_SEL_REG, readData); ++ } ++ ++ // Set spectrum invert, gain level and IF path ++ // Spectrum invert indication is bit<7:6> ++ ++ // Gain level is bit<3:0> ++ control = (dev->gainLevel & 0x0F); ++ control |= 0x20; // Enable IF out ++ ret |= reg_write(client, IF_PATH_GAIN_REG, control); ++ ++ if(ret) ++ goto err; ++ ++ /*5.setup AGC agctye :0 self ;1:externel */ ++ // AGC selecton <3:2> and mode setting <0> ++ ret = reg_read(dev->client, AGC_CONFIG_REG, &readData); ++ readData &= 0xF2; // Clear bits <3:2> & <0> ++ readData = (u8) (readData | (dev->agcType << 2) | 0x01); ++ ret |= reg_write(dev->client, AGC_CONFIG_REG, readData); ++ ++ // AGC set point <6:0> ++ ret |= reg_read(dev->client, AGC_SET_POINT_REG, &readData); ++ readData &= 0x80; // Clear bit <6:0> ++ readData |= dev->setagcPoint; ++ ret |= reg_write(dev->client, AGC_SET_POINT_REG, readData); ++ ++ // AGC Polarity <4> ++ ret |= reg_read(dev->client, AGC_FLIP_REG, &readData); ++ readData &= 0xEF; // Clear bit <4> ++ readData |= (0 << 4); ++ ret |= reg_write(dev->client, AGC_FLIP_REG, readData); ++ ++ if(ret) ++ goto err; ++ ++ ++ dev->active = true; ++ return ret; ++err: ++ pr_err("%s_failed = %d",__FUNCTION__,ret); ++ return ret; ++} ++static int mxl603_set_params(struct dvb_frontend *fe) ++{ ++ struct i2c_client *client =fe->tuner_priv; ++ struct mxl603_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ ++ int ret; ++ u8 signalMode,regData,agcData,dfeTuneData,dfeCdcData; ++ u32 freq = 0; ++ u8 tmp; ++ ++ pr_info("delivery_system=%d frequency=%d\n", ++ c->delivery_system, c->frequency); ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ MXL603_REG_CTRL_INFO_T MxL603_DigitalDvbc[] = ++ { ++ {0x0C, 0xFF, 0x00}, ++ {0x13, 0xFF, 0x04}, ++ {0x53, 0xFF, 0x7E}, ++ {0x57, 0xFF, 0x91}, ++ {0x5C, 0xFF, 0xB1}, ++ {0x62, 0xFF, 0xF2}, ++ {0x6E, 0xFF, 0x03}, ++ {0x6F, 0xFF, 0xD1}, ++ {0x87, 0xFF, 0x77}, ++ {0x88, 0xFF, 0x55}, ++ {0x93, 0xFF, 0x33}, ++ {0x97, 0xFF, 0x03}, ++ {0xBA, 0xFF, 0x40}, ++ {0x98, 0xFF, 0xAF}, ++ {0x9B, 0xFF, 0x20}, ++ {0x9C, 0xFF, 0x1E}, ++ {0xA0, 0xFF, 0x18}, ++ {0xA5, 0xFF, 0x09}, ++ {0xC2, 0xFF, 0xA9}, ++ {0xC5, 0xFF, 0x7C}, ++ {0xCD, 0xFF, 0x64}, ++ {0xCE, 0xFF, 0x7C}, ++ {0xD5, 0xFF, 0x05}, ++ {0xD9, 0xFF, 0x00}, ++ {0xEA, 0xFF, 0x00}, ++ {0xDC, 0xFF, 0x1C}, ++ {0, 0, 0} ++ }; ++ ++ MXL603_REG_CTRL_INFO_T MxL603_DigitalIsdbtAtsc[] = ++ { ++ {0x0C, 0xFF, 0x00}, ++ {0x13, 0xFF, 0x04}, ++ {0x53, 0xFF, 0xFE}, ++ {0x57, 0xFF, 0x91}, ++ {0x62, 0xFF, 0xC2}, ++ {0x6E, 0xFF, 0x01}, ++ {0x6F, 0xFF, 0x51}, ++ {0x87, 0xFF, 0x77}, ++ {0x88, 0xFF, 0x55}, ++ {0x93, 0xFF, 0x22}, ++ {0x97, 0xFF, 0x02}, ++ {0xBA, 0xFF, 0x30}, ++ {0x98, 0xFF, 0xAF}, ++ {0x9B, 0xFF, 0x20}, ++ {0x9C, 0xFF, 0x1E}, ++ {0xA0, 0xFF, 0x18}, ++ {0xA5, 0xFF, 0x09}, ++ {0xC2, 0xFF, 0xA9}, ++ {0xC5, 0xFF, 0x7C}, ++ {0xCD, 0xFF, 0xEB}, ++ {0xCE, 0xFF, 0x7F}, ++ {0xD5, 0xFF, 0x03}, ++ {0xD9, 0xFF, 0x04}, ++ {0, 0, 0} ++ }; ++ ++ switch (c->delivery_system) { ++ case SYS_ATSC: ++ signalMode = 1; ++ ret = mxl603_ctrl_programRegisters(client, MxL603_DigitalIsdbtAtsc); ++ ++ if (dev->ifOutFreqinKHz < HIGH_IF_35250_KHZ) ++ { ++ // Low power ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_0, 0xF9); ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_1, 0x18); ++ ret |= reg_write(dev->client, DIG_ANA_IF_PWR, 0xF1); ++ } ++ else ++ { ++ // High power ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_0, 0xD9); ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_1, 0x16); ++ ret |= reg_write(dev->client, DIG_ANA_IF_PWR, 0xB1); ++ } ++ ++ if (MXL603_XTAL_16MHz == dev->xtalFreqSel) tmp = 0x0D; ++ if (MXL603_XTAL_24MHz == dev->xtalFreqSel) tmp = 0x0E; ++ ++ ++ ret |= reg_write(dev->client, DFE_CSF_SS_SEL, tmp); ++ ++ tmp = 0; ++ switch(dev->gainLevel) ++ { ++ case 0x09: tmp = 0x44; break; ++ case 0x08: tmp = 0x43; break; ++ case 0x07: tmp = 0x42; break; ++ case 0x06: tmp = 0x41; break; ++ case 0x05: tmp = 0x40; break; ++ default: break; ++ } ++ ret |= reg_write(dev->client, DFE_DACIF_GAIN, tmp); ++ ++ break; ++ case SYS_DVBC_ANNEX_B: ++ case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_C: ++ if(c->delivery_system == SYS_DVBC_ANNEX_B)signalMode = 3; ++ else ++ signalMode = 0; ++ ret = mxl603_ctrl_programRegisters(dev->client, MxL603_DigitalDvbc); ++ ++ if (dev->ifOutFreqinKHz < HIGH_IF_35250_KHZ) ++ { ++ // Low power ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_0, 0xFE); ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_1, 0x10); ++ } ++ else ++ { ++ // High power ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_0, 0xD9); ++ ret |= reg_write(dev->client, DIG_ANA_IF_CFG_1, 0x16); ++ } ++ ++ if (dev->xtalFreqSel == MXL603_XTAL_16MHz) tmp = 0x0D; ++ if (dev->xtalFreqSel == MXL603_XTAL_24MHz) tmp = 0x0E; ++ ++ ++ ret |= reg_write(dev->client, DFE_CSF_SS_SEL, tmp); ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ // XTAL calibration ++ ret |= reg_write(dev->client, XTAL_CALI_SET_REG, 0x00); ++ ret |= reg_write(dev->client, XTAL_CALI_SET_REG, 0x01); ++ ++ msleep(50); ++ ++ ret = reg_write(dev->client, START_TUNE_REG, 0x00); ++ ++ // RF Frequency VCO Band Settings ++ if (c->frequency < 700000000) ++ { ++ ret |= reg_write(dev->client, 0x7C, 0x1F); ++ if ((signalMode == MXL603_DIG_DVB_C) || (signalMode == MXL603_DIG_J83B)) ++ regData = 0xC1; ++ else ++ regData = 0x81; ++ ++ } ++ else ++ { ++ ret |= reg_write(dev->client, 0x7C, 0x9F); ++ if ((signalMode == MXL603_DIG_DVB_C) || (signalMode == MXL603_DIG_J83B)) ++ regData = 0xD1; ++ else ++ regData = 0x91; ++ ++ } ++ ++ ret |= reg_write(dev->client, 0x00, 0x01); ++ ret |= reg_write(dev->client, 0x31, regData); ++ ret |= reg_write(dev->client, 0x00, 0x00); ++ ++ // Bandwidth <7:0> ++ ++ ret |= reg_write(dev->client, CHAN_TUNE_BW_REG, 0x20); ++ ++ /* Calculate RF Channel = DIV(64*RF(Hz), 1E6) */ ++ freq = (u32)((c->frequency/1000000)*64); ++ // Set RF ++ ret |= reg_write(dev->client, CHAN_TUNE_LOW_REG, (u8)(freq & 0xFF)); ++ ret |= reg_write(dev->client, CHAN_TUNE_HI_REG, (u8)((freq >> 8 ) & 0xFF)); ++ ++ ++ // Power up tuner module ++ ret |= reg_write(dev->client, TUNER_ENABLE_REG, 0x01); ++ ++ // Start Sequencer settings ++ ret |= reg_write(dev->client, PAGE_CHANGE_REG, 0x01); ++ ret |= reg_read(dev->client, DIG_ANA_GINJO_LT_REG, ®Data); ++ ret |= reg_write(dev->client, PAGE_CHANGE_REG, 0x00); ++ ++ ret |= reg_read(dev->client, 0xB6, &agcData); ++ ret |= reg_write(dev->client, PAGE_CHANGE_REG, 0x01); ++ ret |= reg_read(dev->client, 0x60, &dfeTuneData); ++ ret |= reg_read(dev->client, 0x5F, &dfeCdcData); ++ ++ // Check if LT is enabled ++ if ((regData & 0x10) == 0x10) ++ { ++ // dfe_agc_auto = 0 & dfe_agc_rf_bo_w = 14 ++ agcData &= 0xBF; ++ agcData |= 0x0E; ++ ++ // dfe_seq_tune_rf1_bo = 14 ++ dfeTuneData &= 0xC0; ++ dfeTuneData |= 0x0E; ++ ++ // dfe_seq_cdc_rf1_bo = 14 ++ dfeCdcData &= 0xC0; ++ dfeCdcData |= 0x0E; ++ } ++ else ++ { ++ // dfe_agc_auto = 1 & dfe_agc_rf_bo_w = 0 ++ agcData |= 0x40; ++ agcData &= 0xC0; ++ ++ // dfe_seq_tune_rf1_bo = 55 ++ dfeTuneData &= 0xC0; ++ dfeTuneData |= 0x37; ++ ++ // dfe_seq_cdc_rf1_bo = 55 ++ dfeCdcData &= 0xC0; ++ dfeCdcData |= 0x37; ++ } ++ ++ ret |= reg_write(dev->client, 0x60, dfeTuneData); ++ ret |= reg_write(dev->client, 0x5F, dfeCdcData); ++ ret |= reg_write(dev->client, PAGE_CHANGE_REG, 0x00); ++ ret |= reg_write(dev->client, 0xB6, agcData); ++ ++ // Bit <0> 1 : start , 0 : abort calibrations ++ ret |= reg_write(dev->client, START_TUNE_REG, 0x01); ++ ++ // Sleep 15 ms ++ msleep(15); ++ ++ // dfe_agc_auto = 1 ++ agcData = (agcData | 0x40); ++ ret |= reg_write(dev->client, 0xB6, agcData); ++ if(ret) ++ goto err; ++ ++ return ret; ++ ++err: ++ pr_err("failed = %d ",ret); ++ return ret; ++} ++ ++static int mxl603_get_status(struct dvb_frontend *fe,u32*status) ++{ ++ struct i2c_client *client =fe->tuner_priv; ++ struct mxl603_dev *dev = i2c_get_clientdata(client); ++ int ret; ++ u8 regData; ++ ++ ret = reg_read(dev->client, RF_REF_STATUS_REG, ®Data); ++ ++ if((regData & 0x03) == 0x03) ++ *status = 1; ++ else ++ *status = 0; ++ ++ return ret; ++ ++} ++ ++ ++static const struct dvb_tuner_ops mxl603_ops ={ ++ .info = { ++ .name = "MaxLinear tuner MXL603", ++ .frequency_min = 44000000, ++ .frequency_max = 1002000000, ++ }, ++ .init = mxl603_init, ++ .set_params = mxl603_set_params, ++ .get_status = mxl603_get_status, ++ ++}; ++static int mxl603_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct mxl603_config *cfg = client->dev.platform_data; ++ struct dvb_frontend *fe = cfg->fe; ++ struct mxl603_dev *dev; ++ ++ int ret; ++ u8 utemp; ++ ++ dev = kzalloc(sizeof(*dev),GFP_KERNEL); ++ if(!dev){ ++ ret = -ENOMEM; ++ dev_err(&client->dev,"kzalloc failed\n"); ++ goto err; ++ } ++ ++ dev->fe = cfg->fe; ++ dev->xtalFreqSel = cfg->xtalFreqSel; ++ dev->agcType = cfg->agcType; ++ dev->ifOutFreq = cfg->ifOutFreq; ++ dev->manualIFFreqSet = cfg->manualIFFreqSet; ++ dev->manualIFOutFreqInKHz = cfg->manualIFOutFreqInKHz; ++ dev->ifOutFreqinKHz = 5000; ++ dev->xtalCap = 31; ++ dev->gainLevel = 11; ++ dev->setagcPoint =66; ++ dev->client = client; ++ dev->active= false; ++ ++ /*check chip answers with correct chip iD*/ ++ ret = reg_read(dev->client,CHIP_ID_REQ_REG,&utemp); ++ if (ret) ++ goto err_kfree; ++ ++ pr_info("chip id = 0x%x \n",utemp); ++ ++ if(utemp!=0x1){ ++ ret = -ENODEV; ++ goto err_kfree; ++ } ++ ret = reg_write(dev->client,0x10,0x99); ++ ++ ret = reg_read(dev->client,0x10,&utemp) ; ++ ++ /**/ ++ memcpy(&fe->ops.tuner_ops,&mxl603_ops,sizeof(struct dvb_tuner_ops)); ++ fe->tuner_priv = client; ++ i2c_set_clientdata(client, dev); ++ ++ return 0; ++ ++ ++err_kfree: ++ kfree(dev); ++err: ++ pr_err("%s___failed=%d\n",__FUNCTION__, ret); ++ return ret; ++} ++static int mxl603_remove(struct i2c_client *client) ++{ ++ struct mxl603_dev *dev = i2c_get_clientdata(client); ++ ++ kfree(dev); ++ ++ return 0; ++} ++ ++ static const struct i2c_device_id mxl603_id_table[] = { ++ {"mxl603", 0}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, mxl603_id_table); ++ ++static struct i2c_driver mxl603_driver = { ++ .driver = { ++ .name = "mxl603", ++ }, ++ .probe = mxl603_probe, ++ .remove = mxl603_remove, ++ .id_table = mxl603_id_table, ++}; ++ ++module_i2c_driver(mxl603_driver); ++ ++MODULE_AUTHOR("Davin "); ++MODULE_DESCRIPTION("Panasonic MN88436 ATSC/QAMB demodulator driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/media/tuners/mxl603.h b/drivers/media/tuners/mxl603.h +new file mode 100644 +index 0000000..752c2ca +--- /dev/null ++++ b/drivers/media/tuners/mxl603.h +@@ -0,0 +1,49 @@ ++#ifndef MXL603_H ++#define MXL603_H ++ ++#include ++ ++typedef enum ++{ ++ MXL603_IF_3_65MHz = 0, ++ MXL603_IF_4MHz = 1, ++ MXL603_IF_4_1MHz = 2, ++ MXL603_IF_4_15MHz = 3, ++ MXL603_IF_4_5MHz = 4, ++ MXL603_IF_4_57MHz = 5, ++ MXL603_IF_5MHz = 6, ++ MXL603_IF_5_38MHz = 7, ++ MXL603_IF_6MHz = 8, ++ MXL603_IF_6_28MHz = 9, ++ MXL603_IF_7_2MHz = 10, ++ MXL603_IF_8_25MHz = 11, ++ MXL603_IF_35_25MHz = 12, ++ MXL603_IF_36MHz = 13, ++ MXL603_IF_36_15MHz = 14, ++ MXL603_IF_36_65MHz = 15, ++ MXL603_IF_44MHz = 16 ++} MXL603_IF_FREQ_E; ++ ++#define MXL603_XTAL_16MHz 0 ++#define MXL603_XTAL_24MHz 1 ++ ++struct mxl603_config{ ++ ++ u8 xtalFreqSel; ++ ++ u8 ifOutFreq; ++ ++#define MXL603_AGC_SELF 0 ++#define MXL603_AGC_EXTERNAL 1 ++ u8 agcType; ++ ++ bool manualIFFreqSet; /*enable and disable*/ ++ u32 manualIFOutFreqInKHz; ++ ++ struct dvb_frontend *fe; ++ ++}; ++ ++ ++ ++#endif +\ No newline at end of file +diff --git a/drivers/media/tuners/mxl603_priv.h b/drivers/media/tuners/mxl603_priv.h +new file mode 100644 +index 0000000..36f85bd +--- /dev/null ++++ b/drivers/media/tuners/mxl603_priv.h +@@ -0,0 +1,133 @@ ++#ifndef MXL603_PRIV_H ++#define MXL603_PRIV_H ++ ++#include "mxl603.h" ++#include "dvb_frontend.h" ++ ++ ++struct mxl603_dev{ ++ struct i2c_client *client; ++ ++ u8 xtalFreqSel; ++ u8 xtalCap; ++ u8 ifOutFreq; ++ u8 gainLevel; ++ u8 agcType; ++ u8 setagcPoint; ++ u32 ifOutFreqinKHz; ++ ++ bool manualIFFreqSet; /*enable and disable*/ ++ u32 manualIFOutFreqInKHz; ++ ++ struct dvb_frontend *fe; ++ bool active ; ++}; ++ ++typedef struct ++{ ++ u8 regAddr; ++ u8 mask; ++ u8 data; ++} MXL603_REG_CTRL_INFO_T, *PMXL603_REG_CTRL_INFO_T; ++ ++typedef enum ++{ ++ MXL603_DIG_DVB_C = 0, /* DVB-C mode */ ++ MXL603_DIG_ISDBT_ATSC, /* ATSC/ISDB-T mode */ ++ MXL603_DIG_DVB_T_DTMB, /* DVB-T/DVB-T2 and DTMB mode */ ++ MXL603_DIG_J83B /* J.83B mode */ ++} MXL603_SIGNAL_MODE_E; /* MxL603 Application mode */ ++ ++ ++#define AIC_RESET_REG 0xFF // For MxL603 Tuner ++ ++#define PAGE_CHANGE_REG 0x00 // Page change, can configured as page 0 or page 1 ++#define XTAL_CAP_CTRL_REG 0x01 // Xtal frequency and CAP register ++#define XTAL_ENABLE_DIV_REG 0x02 // Xtal enable and frequency div 4 register ++#define XTAL_CALI_SET_REG 0x03 // Xtal calibration enable register enable register ++#define IF_FREQ_SEL_REG 0x04 // IF frequency selection and manual set bypass register ++#define IF_PATH_GAIN_REG 0x05 // IF gain level and path selection register ++#define IF_FCW_LOW_REG 0x06 // Low register of IF FCW set when manual program IF frequency ++#define IF_FCW_HIGH_REG 0x07 // High register of IF FCW set when manual program IF frequency ++#define AGC_CONFIG_REG 0x08 // AGC configuration, include AGC select and AGC type ++#define AGC_SET_POINT_REG 0x09 ++#define AGC_FLIP_REG 0x5E ++#define AGC_SLOPE_REG 0xB5 ++#define AGC_OFFSET_REG 0xB4 ++#define GPO_SETTING_REG 0x0A // GPO set and inquiring register ++#define TUNER_ENABLE_REG 0x0B // Power up register, bit<0> ++#define TUNE_MODE_REG 0x0D ++#define MAIN_REG_AMP 0x0E ++#define CHAN_TUNE_BW_REG 0x0F // Band width register ++#define CHAN_TUNE_LOW_REG 0x10 // Tune frequency set low byte ++#define CHAN_TUNE_HI_REG 0x11 // Tune frequency set high byte ++#define START_TUNE_REG 0x12 // sequencer setting register ++#define FINE_TUNE_SET_REG 0x13 // Fine tune operation register ++#define FINE_TUNE_CTRL_REG_0 0x13 // Fine tune operation register ++#define FINE_TUNE_CTRL_REG_1 0x14 // Fine tune operation register ++ ++#define FINE_TUNE_OFFSET_LOW_REG 0x14 // Fine tune frequency offset low byte ++#define FINE_TUNE_OFFSET_HIGH_REG 0x15 // Fine tune frequency offset high byte ++#define CHIP_ID_REQ_REG 0x18 // Tuner Chip ID register ++#define CHIP_VERSION_REQ_REG 0x1A // Tuner Chip Revision register ++ ++#define RFPIN_RB_LOW_REG 0x1D // RF power low 8 bit register ++#define RFPIN_RB_HIGH_REG 0x1E // RF power high 8 bit register ++#define SIGNAL_TYPE_REG 0x1E // Signal type ++ ++#define DFE_CTRL_ACCUM_LOW_REG 0x24 // Bit<7:0> ++#define DFE_CTRL_ACCUM_MID_REG 0x25 // Bit<7:0> ++#define DFE_CTRL_ACCUM_HI_REG 0x26 // Bit<1:0> ++ ++#define DFE_CTRL_TRIG_REG 0xA0 // Bit<3> ++#define DFE_CTRL_RB_HI_REG 0x7B // Bit<7:0> ++#define DFE_CTRL_RB_LOW_REG 0x7A // Bit<1:0> ++ ++#define RF_REF_STATUS_REG 0x2B // RF/REF lock status register ++ ++#define AGC_SAGCLOCK_STATUS_REG 0x2C ++ ++#define DFE_DACIF_BYP_GAIN_REG 0x43 ++#define DIG_ANA_RFRSSI_REG 0x57 ++ ++#define RSSI_RESET_REG 0x78 ++#define DIG_ANA_GINJO_LT_REG 0x96 ++#define FINE_TUNE_INIT1_REG 0xA9 ++#define FINE_TUNE_INIT2_REG 0xAA ++ ++#define DFE_AGC_CEIL1_REG 0xB0 ++ ++#define DFE_RFLUT_BYP_REG 0xDB // Dec: 220, bit<7> ++#define DFE_RFLUT_DIV_MOD_REG 0xDB // Dec: 221 ++ ++#define DFE_RFLUT_SWP1_REG 0x49 ++ ++#define DFE_RFSX_FRAC_MOD1_REG 0xDF ++#define DFE_RFSX_FRAC_MOD2_REG 0xE0 ++#define DFE_RFSX_FRAC_MOD3_REG 0xE1 ++#define DFE_RFSX_FRAC_MOD4_REG 0xE2 ++ ++#define DFE_REFLUT_BYP_REG 0xEA // Dec: 240, bit<6> ++#define DFE_REFSX_INT_MOD_REG 0xEB // Dec: 241 ++ ++#define APP_MODE_FREQ_HZ_THRESHOLD_1 358000000 ++#define APP_MODE_FREQ_HZ_THRESHOLD_2 625000000 ++ ++#define IF_GAIN_SET_POINT1 10 ++#define IF_GAIN_SET_POINT2 11 ++#define IF_GAIN_SET_POINT3 12 ++ ++#define DIG_ANA_IF_CFG_0 0x5A ++#define DIG_ANA_IF_CFG_1 0x5B ++#define DIG_ANA_IF_PWR 0x5C ++ ++#define DFE_CSF_SS_SEL 0xEA ++#define DFE_DACIF_GAIN 0xDC ++ ++#define FINE_TUNE_FREQ_INCREASE 0x01 ++#define FINE_TUNE_FREQ_DECREASE 0x02 ++ ++#define RF_SX_FRAC_N_RANGE 0xDD ++ ++#define HIGH_IF_35250_KHZ 35250 ++#endif +diff --git a/drivers/media/tuners/r848.c b/drivers/media/tuners/r848.c +new file mode 100644 +index 0000000..4d09ffa +--- /dev/null ++++ b/drivers/media/tuners/r848.c +@@ -0,0 +1,3545 @@ ++/* ++ * Rafael Micro R848 silicon tuner driver ++ * ++ * Copyright (C) 2015 Luis Alves ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include "r848.h" ++#include "r848_priv.h" ++ ++/* read tuner registers (always starts at addr 0) */ ++static int r848_rd(struct r848_priv *priv, u8 *buf, int len) ++{ ++ int ret, i; ++ struct i2c_msg msg = { ++ .addr = priv->cfg->i2c_address, ++ .flags = I2C_M_RD, .buf = buf, .len = len }; ++ ++ ret = i2c_transfer(priv->i2c, &msg, 1); ++ if (ret == 1) { ++ for (i = 0; i < len; i++) ++ buf[i] = bitrev8(buf[i]); ++ ret = 0; ++ } else { ++ dev_warn(&priv->i2c->dev, "%s: i2c tuner rd failed=%d " \ ++ "len=%d\n", KBUILD_MODNAME, ret, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++ ++/* write registers starting at specified addr */ ++static int r848_wrm(struct r848_priv *priv, u8 addr, u8 *val, int len) ++{ ++ int ret; ++ u8 buf[len + 1]; ++ struct i2c_msg msg = { ++ .addr = priv->cfg->i2c_address, ++ .flags = 0, .buf = buf, .len = len + 1 }; ++ ++ memcpy(&buf[1], val, len); ++ buf[0] = addr; ++ ret = i2c_transfer(priv->i2c, &msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ dev_warn(&priv->i2c->dev, "%s: i2c tuner wr failed=%d " \ ++ "len=%d\n", KBUILD_MODNAME, ret, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++ ++/* write one register */ ++static int r848_wr(struct r848_priv *priv, u8 addr, u8 data) ++{ ++ return r848_wrm(priv, addr, &data, 1); ++} ++ ++ ++static int r848_get_lock_status(struct r848_priv *priv, u8 *lock) ++{ ++ int ret; ++ u8 buf[3]; ++ ++ ret = r848_rd(priv, buf, 3); ++ if (ret) ++ return ret; ++ ++ if ((buf[2] & 0x40) == 0x00) ++ *lock = 0; ++ else ++ *lock = 1; ++ ++ return ret; ++} ++ ++ ++static int r848_init_regs(struct r848_priv *priv, u8 standard) ++{ ++ u8 *ptr; ++ ++ if (standard != R848_DVB_S) ++ ptr = R848_iniArray_hybrid; ++ else ++ ptr = R848_iniArray_dvbs; ++ ++ memcpy(priv->regs, ptr, R848_REG_NUM); ++ ++ return r848_wrm(priv, 0x08, ptr, R848_REG_NUM); ++} ++ ++static int r848_get_imr(struct r848_priv *priv, u8 *imr) ++{ ++ u8 buf[2]; ++ int i, ret = 0; ++ u16 total = 0; ++ ++ for (i = 0; i < 4; i++) { ++ ret |= r848_rd(priv, buf, 2); ++ total += (buf[1] & 0x3f); ++ } ++ *imr = (u8) (total >> 2); ++ return ret; ++} ++ ++ ++ ++ ++ ++R848_Freq_Info_Type R848_Freq_Sel(u32 LO_freq, u32 RF_freq,R848_Standard_Type R848_Standard) ++{ ++ R848_Freq_Info_Type R848_Freq_Info; ++ ++ // LNA band R13[6:5] ++ if (RF_freq < R848_LNA_LOW_LOWEST[R848_TF_BEAD]) //<164 ++ R848_Freq_Info.LNA_BAND = 0x60; // ultra low ++ else if (RF_freq < R848_LNA_MID_LOW[R848_TF_BEAD]) //164~388 ++ R848_Freq_Info.LNA_BAND = 0x40; // low ++ else if (RF_freq < R848_LNA_HIGH_MID[R848_TF_BEAD]) //388~612 ++ R848_Freq_Info.LNA_BAND = 0x20; // mid ++ else // >612 ++ R848_Freq_Info.LNA_BAND = 0x00; // high ++ ++ // IMR point ++ if (LO_freq < 133000) ++ R848_Freq_Info.IMR_MEM = 0; ++ else if (LO_freq<221000) ++ R848_Freq_Info.IMR_MEM = 1; ++ else if (LO_freq<450000) ++ R848_Freq_Info.IMR_MEM = 2; ++ else if (LO_freq<775000) ++ R848_Freq_Info.IMR_MEM = 3; ++ else ++ R848_Freq_Info.IMR_MEM = 4; ++ ++ //RF polyfilter band R33[7:6] ++ if(LO_freq < 133000) ++ R848_Freq_Info.RF_POLY = 0x80; //low ++ else if (LO_freq < 221000) ++ R848_Freq_Info.RF_POLY = 0x40; // mid ++ else if (LO_freq < 775000) ++ R848_Freq_Info.RF_POLY = 0x00; // highest ++ else ++ R848_Freq_Info.RF_POLY = 0xC0; // ultra high ++ ++ // LPF Cap, Notch ++ switch(R848_Standard) { ++ case R848_DVB_C_8M: ++ case R848_DVB_C_6M: ++ case R848_J83B: ++ case R848_DVB_C_8M_IF_5M: ++ case R848_DVB_C_6M_IF_5M: ++ case R848_J83B_IF_5M: ++ if (LO_freq<77000) { ++ R848_Freq_Info.LPF_CAP = 16; ++ R848_Freq_Info.LPF_NOTCH = 10; ++ } else if (LO_freq<85000) { ++ R848_Freq_Info.LPF_CAP = 16; ++ R848_Freq_Info.LPF_NOTCH = 4; ++ } else if (LO_freq<115000) { ++ R848_Freq_Info.LPF_CAP = 13; ++ R848_Freq_Info.LPF_NOTCH = 3; ++ } else if (LO_freq<125000) { ++ R848_Freq_Info.LPF_CAP = 11; ++ R848_Freq_Info.LPF_NOTCH = 1; ++ } else if (LO_freq<141000) { ++ R848_Freq_Info.LPF_CAP = 9; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else if (LO_freq<157000) { ++ R848_Freq_Info.LPF_CAP = 8; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else if (LO_freq<181000) { ++ R848_Freq_Info.LPF_CAP = 6; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else if (LO_freq<205000) { ++ R848_Freq_Info.LPF_CAP = 3; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else { //LO>=201M ++ R848_Freq_Info.LPF_CAP = 0; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } ++ break; ++ default: ++ if(LO_freq<73000) { ++ R848_Freq_Info.LPF_CAP = 8; ++ R848_Freq_Info.LPF_NOTCH = 10; ++ } else if (LO_freq<81000) { ++ R848_Freq_Info.LPF_CAP = 8; ++ R848_Freq_Info.LPF_NOTCH = 4; ++ } else if (LO_freq<89000) { ++ R848_Freq_Info.LPF_CAP = 8; ++ R848_Freq_Info.LPF_NOTCH = 3; ++ } else if (LO_freq<121000) { ++ R848_Freq_Info.LPF_CAP = 6; ++ R848_Freq_Info.LPF_NOTCH = 1; ++ } else if (LO_freq<145000) { ++ R848_Freq_Info.LPF_CAP = 4; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else if (LO_freq<153000) { ++ R848_Freq_Info.LPF_CAP = 3; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else if (LO_freq<177000) { ++ R848_Freq_Info.LPF_CAP = 2; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else if (LO_freq<201000) { ++ R848_Freq_Info.LPF_CAP = 1; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } else { //LO>=201M ++ R848_Freq_Info.LPF_CAP = 0; ++ R848_Freq_Info.LPF_NOTCH = 0; ++ } ++ break; ++ } ++ return R848_Freq_Info; ++} ++ ++ ++ ++ ++ ++ ++R848_ErrCode R848_Cal_Prepare(struct r848_priv *priv, u8 u1CalFlag) ++{ ++ R848_Cal_Info_Type Cal_Info; ++ int ret; ++ ++ ++ // R848:R38[3] +6dB ++ Cal_Info.FILTER_6DB = 0x08; ++ // R848:R8[7] LNA power ++ Cal_Info.LNA_POWER = 0x80; ++ // R848:R12[6:5] (bit5 = RF_Buf ON(?), bit6=RF_Buf pwr) ++ Cal_Info.RFBUF_OUT = 0x20; ++ // R848:R9[2] RF_BUF_pwr ++ Cal_Info.RFBUF_POWER = 0x04; ++ // R848:R14[6:5] (bit5=TF cal ON/OFF, bit6=TF_-6dB ON/OFF) ++ Cal_Info.TF_CAL = 0x00; ++ // R848:R13[7:0] (manual: 0x9f (-97?) max, 0x80 (-128?) min) ++ Cal_Info.LNA_GAIN = 0x9F; ++ // R848:R15[4:0] (manual +8) (min(0)) ++ Cal_Info.MIXER_AMP_GAIN = 0x08; ++ // R848:R34[4:0] (manual min(0)) ++ Cal_Info.MIXER_BUFFER_GAIN = 0x10; ++ ++ switch(u1CalFlag) { ++ case R848_IMR_LNA_CAL: ++ Cal_Info.RFBUF_OUT = 0x00; ++ Cal_Info.RFBUF_POWER = 0x00; ++ Cal_Info.TF_CAL = 0x60; ++ Cal_Info.MIXER_AMP_GAIN = 0x00; ++ break; ++ case R848_TF_LNA_CAL: ++ Cal_Info.RFBUF_OUT = 0x00; ++ Cal_Info.RFBUF_POWER = 0x00; ++ Cal_Info.TF_CAL = 0x60; ++ Cal_Info.LNA_GAIN = 0x80; ++ Cal_Info.MIXER_AMP_GAIN = 0x00; ++ break; ++ case R848_LPF_LNA_CAL: ++ Cal_Info.RFBUF_OUT = 0x00; ++ Cal_Info.RFBUF_POWER = 0x00; ++ Cal_Info.TF_CAL = 0x20; ++ Cal_Info.LNA_GAIN = 0x80; ++ Cal_Info.MIXER_AMP_GAIN = 0x00; ++ break; ++ case R848_TF_CAL: ++ Cal_Info.MIXER_AMP_GAIN = 0x00; ++ break; ++ case R848_LPF_CAL: ++ case R848_IMR_CAL: ++ default: ++ break; ++ } ++ ++ // Ring From RF_Buf Output & RF_Buf Power ++ // R848:R12[5] ++ priv->regs[4] = (priv->regs[4] & 0xDF) | Cal_Info.RFBUF_OUT; ++ ret = r848_wr(priv, 0x0c, priv->regs[4]); ++ ++ // RF_Buf Power ++ priv->regs[1] = (priv->regs[1] & 0xFB) | Cal_Info.RFBUF_POWER; ++ ret |= r848_wr(priv, 0x09, priv->regs[1]); ++ ++ // (LNA power ON/OFF ) ++ // R848:R8[7] ++ priv->regs[0] = (priv->regs[0] & 0x7F) | Cal_Info.LNA_POWER; ++ ret |= r848_wr(priv, 0x08, priv->regs[0]); ++ ++ // TF cal (TF cal ON/OFF, TF_-6dB ON/OFF) ++ // R848:R14[6:5] ++ priv->regs[6] = (priv->regs[6] & 0x9F) | Cal_Info.TF_CAL; ++ ret |= r848_wr(priv, 0x0e, priv->regs[6]); ++ ++ // LNA gain ++ // R848:R13[7:0] ++ priv->regs[5] = (priv->regs[5] & 0x60) | Cal_Info.LNA_GAIN; ++ ret |= r848_wr(priv, 0x0d, priv->regs[5]); ++ ++ // Mixer Amp Gain ++ // R848:R15[4:0] 15-8=7 15(0x0F) is addr ; [7] is data ++ priv->regs[7] = (priv->regs[7] & 0xE0) | Cal_Info.MIXER_AMP_GAIN; ++ ret |= r848_wr(priv, 0x0f, priv->regs[7]); ++ ++ // Mixer Buffer Gain ++ // R848:R34[4:0] 34-8=26 34(0x22) is addr ; [26] is data ++ priv->regs[26] = (priv->regs[26] & 0xE0) | Cal_Info.MIXER_BUFFER_GAIN; ++ ret |= r848_wr(priv, 0x22, priv->regs[26]); ++ ++ // Set filter +0/6dB; NA det=OFF ++ // R848:R38[3] 38-8=30 38(0x26) is addr ; [30] is data ++ priv->regs[30] = (priv->regs[30] & 0xF7) | Cal_Info.FILTER_6DB | 0x80; ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); ++ ++ // Set NA det 710 = OFF ++ // R848:R40[3] 40-8=32 40(0x28) is addr ; [32] is data ++ priv->regs[32] = (priv->regs[32] | 0x08); ++ ret |= r848_wr(priv, 0x28, priv->regs[32]); ++ ++ //---- General calibration setting ----// ++ // IMR IQ cap=0 ++ // R848:R11[1:0] 11-8=3 11(0x0B) is addr ; [3] is data ++ priv->regs[3] = (priv->regs[3] & 0xFC); ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); ++ ++ // Set RF_Flag ON(%) ++ // R848:R22[0] 22-8=14 22(0x16) is addr ; [14] is data ++ priv->regs[14] = priv->regs[14] | 0x01; //force far-end mode ++ ret |= r848_wr(priv, 0x16, priv->regs[14]); ++ ++ // RingPLL power ON ++ // R848:R18[4] 18-8=10 18(0x12) is addr ; [10] is data ++ priv->regs[10] = (priv->regs[10] & 0xEF); ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ // LPF filter code = 15 ++ // R848:R18[3:0] 18-8=10 18(0x12) is addr ; [10] is data ++ priv->regs[10] = (priv->regs[10] & 0xF0) | 0x0F; ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ // HPF corner=narrowest; LPF coarse=6M; 1.7M disable ++ // R848:R19[7:0] 19-8=11 19(0x13) is addr ; [11] is data ++ priv->regs[11] = (priv->regs[11] & 0x00) | 0x60; ++ ret |= r848_wr(priv, 0x13, priv->regs[11]); ++ ++ // ADC/VGA PWR on; Vga code mode(b4=1), Gain = 26.5dB; Large Code mode Gain(b5=1) ++ // ADC PWR on (b7=0) R848:R15[7] 15-8=7 15(0x0F) is addr ; [7] is data ++ priv->regs[7] = (priv->regs[7] & 0x7F); ++ ret |= r848_wr(priv, 0x0f, priv->regs[7]); ++ ++/* // VGA PWR on (b0=0) ++ // R848:R9[0] 9-8=1 9(0x09) is addr ; [1] is data ++ priv->regs[1] = (priv->regs[1] & 0xFE); ++ ret |= r848_wr(priv, 0x09, priv->regs[1]);*/ ++ ++ // VGA PWR on (b0=0) MT2 ++ // R848:R18[7] ++ priv->regs[10] = (priv->regs[10] & 0x7F); ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ // Large Code mode Gain(b5=1) ++ // R848:R11[3] 11-8=3 11(0x0B) is addr ; [3] is data ++ priv->regs[3] = (priv->regs[3] & 0xF7) | 0x08; ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); ++ ++ // Vga code mode(b4=1) ++ // R848:R9[1] 9-8=1 9(0x09) is addr ; [1] is data ++ priv->regs[1] = (priv->regs[1] & 0xFD) | 0x02; ++ ret |= r848_wr(priv, 0x09, priv->regs[1]); ++ ++ // Gain = 26.5dB ++ // R848:R20[3:0] 20-8=12 20(0x14) is addr ; [12] is data ++ priv->regs[12] = (priv->regs[12] & 0xF0) | 0x0B; ++ ret |= r848_wr(priv, 0x14, priv->regs[12]); ++ ++ // LNA, RF, Nrb dector pw on; det2 cap=IF_det ++ // R848:R37[3:0] 37-8=29 37(0x25) is addr ; [29] is data ++ priv->regs[29] = (priv->regs[29] & 0xF0) | 0x02; ++ ret |= r848_wr(priv, 0x25, priv->regs[29]); ++ ++ return ret; ++} ++ ++R848_ErrCode R848_Xtal_Check( struct r848_priv *priv) ++{ ++ u8 i = 0; ++ u8 buf[3]; ++ int ret; ++ ++ // TF force sharp mode (for stable read) ++ priv->regs[14] = priv->regs[14] | 0x01; ++ ret = r848_wr(priv, 0x16, priv->regs[14]); ++ ++ // NA det off (for stable read) ++ priv->regs[30] = priv->regs[30] | 0x80; ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); ++ ++ // Set NA det 710 = OFF ++ priv->regs[32] = (priv->regs[32] | 0x08); ++ ret |= r848_wr(priv, 0x28, priv->regs[32]); ++ ++ // Xtal_pow=lowest(11) R848:R23[6:5] ++ priv->regs[15] = (priv->regs[15] & 0x9F) | 0x60; ++ ret |= r848_wr(priv, 0x17, priv->regs[15]); ++ ++ // Xtal_Gm=SMALL(0) R848:R27[0] ++ priv->regs[19] = (priv->regs[19] & 0xFE) | 0x00; ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ ++ // set pll autotune = 128kHz R848:R23[4:3] ++ priv->regs[15] = priv->regs[15] & 0xE7; ++ ret |= r848_wr(priv, 0x17, priv->regs[15]); ++ ++ // set manual initial reg = 1 000000; b5=0 => cap 30p; R848:R27[7:0] ++ priv->regs[19] = (priv->regs[19] & 0x80) | 0x40; ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ ++ // set auto ++ priv->regs[19] = (priv->regs[19] & 0xBF); ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ if (ret) ++ return ret; ++ ++ msleep(10); ++ ++ // Xtal_pow=lowest(11) R848:R23[6:5] ++ priv->regs[15] = (priv->regs[15] & 0x9F) | 0x60; ++ ret = r848_wr(priv, 0x17, priv->regs[15]); ++ ++ // Xtal_Gm=SMALL(0) R848:R27[0] ++ priv->regs[19] = (priv->regs[19] & 0xFE) | 0x00; ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ if (ret) ++ return ret; ++ ++ ++ for (i = 0; i < XTAL_CHECK_SIZE; i++) { ++ //set power ++ if (i <= XTAL_SMALL_HIGHEST) { ++ priv->regs[15] = (priv->regs[15] & 0x9F) | ((u8)(XTAL_SMALL_HIGHEST-i)<<5); ++ priv->regs[19] = (priv->regs[19] & 0xFE) | 0x00 ; //| 0x00; //SMALL Gm(0) ++ } else if (i == XTAL_LARGE_HIGHEST) { ++ //priv->regs[15] = (priv->regs[15] & 0x87) | 0x00 | 0x18; //3v Gm, highest ++ priv->regs[15] = (priv->regs[15] & 0x9F) | 0X00 ; ++ priv->regs[19] = (priv->regs[19] & 0xFE) | 0x01 ; //| 0x00; //LARGE Gm(1) ++ } else { ++ //priv->regs[15] = (priv->regs[15] & 0x87) | 0x00 | 0x18; //3v Gm, highest ++ priv->regs[15] = (priv->regs[15] & 0x9F) | 0X00 ; ++ priv->regs[19] = (priv->regs[19] & 0xFE) | 0x01 ; //| 0x00; //LARGE Gm(1) ++ } ++ ++ ret = r848_wr(priv, 0x17, priv->regs[15]); ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ if (ret) ++ return ret; ++ ++ msleep(50); ++ ++ ret = r848_rd(priv, buf, 3); ++ if (ret) ++ return ret; ++ ++ // depend on init Nint & Div value (N=59.6667, Div=16) ++ // lock to VCO band 8 if VCO=2768M for 16M Xtal ++ // lock to VCO band 46 if VCO=2768M for 24M Xtal ++ if ((buf[2] & 0x40) == 0x40) { ++ u8 v = buf[2] & 0x3F; ++ u8 ll, hl; ++ if (priv->cfg->xtal == 16000000) { ++ ll = 5; ++ hl = 11; ++ } else { ++ ll = 42; ++ hl = 48; ++ } ++ if ((v >= ll) && (v <= hl)) { ++ priv->cfg->R848_Xtal_Pwr_tmp = i; ++ break; ++ } ++ } ++ if (i == (XTAL_CHECK_SIZE-1)) { ++ priv->cfg->R848_Xtal_Pwr_tmp = i; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++static int r848_set_pll(struct r848_priv *priv, u32 LO_Freq, R848_Standard_Type R848_Standard) ++{ ++ int ret; ++ u8 buf[3]; ++ ++ u8 MixDiv = 2; ++ u8 DivBuf = 0; ++ u8 Ni = 0; ++ u8 Si = 0; ++ u8 DivNum = 0; ++ u16 Nint = 0; ++ u32 VCO_Min = 2410000; ++ u32 VCO_Max = VCO_Min*2; ++ u32 VCO_Freq = 0; ++ u32 PLL_Ref = R848_Xtal; ++ u32 VCO_Fra = 0; ++ u16 Nsdm = 2; ++ u16 SDM = 0; ++ u16 SDM16to9 = 0; ++ u16 SDM8to1 = 0; ++ u8 CP_CUR = 0x00; ++ u8 CP_OFFSET = 0x00; ++ u8 SDM_RES = 0x00; ++ u8 XTAL_POW1 = 0x00; ++ u8 XTAL_POW0 = 0x00; ++ u8 XTAL_GM = 0x00; ++ u16 u2XalDivJudge; ++ u8 u1XtalDivRemain; ++ u8 VCO_current_trial = 0; ++ ++ u8 u1RfFlag = 0; ++ u8 u1PulseFlag = 0; ++ u8 u1SPulseFlag=0; ++ ++ u8 R848_XtalDiv = XTAL_DIV2; ++ ++ ++ //TF, NA fix ++ u1RfFlag = (priv->regs[14] & 0x01); //R22[0] ++ u1PulseFlag = (priv->regs[30] & 0x80); //R38[7] ++ u1SPulseFlag= (priv->regs[32] & 0x08); //R40[3] ++ ++ ++ priv->regs[14] = priv->regs[14] | 0x01; // TF force sharp mode ++ ret = r848_wr(priv, 0x16, priv->regs[14]); ++ ++ priv->regs[30] = priv->regs[30] | 0x80; // NA det off ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); ++ ++ // Set NA det 710 = OFF ++ priv->regs[32] = (priv->regs[32] | 0x08); ++ ret |= r848_wr(priv, 0x28, priv->regs[32]); ++ ++ // DTV ++ CP_CUR = 0x00; //0.7m, R25[6:4]=000 ++ CP_OFFSET = 0x00; //0u, [2]=0 ++ ++ // CP current R25[6:4]=000 ++ priv->regs[17] = (priv->regs[17] & 0x8F) | CP_CUR ; ++ ret |= r848_wr(priv, 0x19, priv->regs[17]); ++ ++ // Div Cuurent R20[7:6]=2'b01(150uA) ++ priv->regs[12] = (priv->regs[12] & 0x3F) | 0x40; ++ ret |= r848_wr(priv, 0x14, priv->regs[12]); ++ ++ //CPI*2 R28[7]=1 ++ if ((R848_Standard!=R848_DVB_S) && (LO_Freq >= 865000)) ++ priv->regs[20] = (priv->regs[20] & 0x7F) | 0x80; ++ else ++ priv->regs[20] = (priv->regs[20] & 0x7F); ++ ret |= r848_wr(priv, 0x1c, priv->regs[20]); ++ ++ // R848:R26[7:5] VCO_current= 2 ++ priv->regs[18] = (priv->regs[18] & 0x1F) | 0x40; ++ ret |= r848_wr(priv, 0x1a, priv->regs[18]); ++ ++ //CP Offset R21[7] ++ priv->regs[13] = (priv->regs[13] & 0x7F) | CP_OFFSET; ++ ret |= r848_wr(priv, 0x15, priv->regs[13]); ++ if (ret) ++ return ret; ++ ++ //if(R848_Initial_done_flag==TRUE) ++ { ++ // set XTAL Power ++ if ((priv->cfg->R848_Xtal_Pwr < XTAL_SMALL_HIGH) && (LO_Freq > (64000+8500))) { ++ XTAL_POW1 = 0x00; //high, R16[4]=0 //R848:R23[7] ++ XTAL_POW0 = 0x20; //high, R15[6:5]=01 //R848:R23[6:5] ++ XTAL_GM = 0x00; //SMALL(0), R15[4:3]=00 ++ } else { ++ if(priv->cfg->R848_Xtal_Pwr <= XTAL_SMALL_HIGHEST) { ++ XTAL_POW1 = 0x00; //high, R16[4]=0 // R848:R23[7] ++ XTAL_POW0 = ((u8)(XTAL_SMALL_HIGHEST-priv->cfg->R848_Xtal_Pwr)<<5); //R848:R23[6:5] ++ XTAL_GM = 0x00; //SMALL(0), R27[0]=0 ++ } else if(priv->cfg->R848_Xtal_Pwr == XTAL_LARGE_HIGHEST) { ++ XTAL_POW1 = 0x00; //high, // R848:R23[7] ++ XTAL_POW0 = 0x00; //highest, // R848:R23[6:5] ++ XTAL_GM = 0x01; //LARGE(1), R27[0]=1 ++ } else { ++ XTAL_POW1 = 0x00; //high, // R848:R23[7] ++ XTAL_POW0 = 0x00; //highest, // R848:R23[6:5] ++ XTAL_GM = 0x01; //LARGE(1), R27[0]=1 ++ } ++ } ++ } ++// else ++// { ++// XTAL_POW1 = 0x00; //high, // R848:R23[7] ++// XTAL_POW0 = 0x00; //highest, // R848:R23[6:5] ++// XTAL_GM = 0x01; //LARGE(1), R27[0]=1 ++// } ++ ++ // Xtal_Gm=SMALL(0) R27[0] ++ priv->regs[19] = (priv->regs[19] & 0xFE) | XTAL_GM; ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ ++ priv->regs[15] = (priv->regs[15] & 0x9F) | XTAL_POW0; // R23[6:5] ++ ret |= r848_wr(priv, 0x17, priv->regs[15]); ++ ++ priv->regs[15] = (priv->regs[15] & 0x7F) | XTAL_POW1; // R23[7] ++ ret |= r848_wr(priv, 0x17, priv->regs[15]); ++ ++ // IQ gen ON ++ priv->regs[31] = (priv->regs[31] & 0xFD) | 0x00; // R39[1] [0]=0'b0 ++ ret |= r848_wr(priv, 0x27, priv->regs[31]); ++ ++ // current:Dmin, Bmin ++ priv->regs[27] = (priv->regs[27] & 0xCF) | 0x00; // R848:R35[5:4]=2'b00 ++ ret |= r848_wr(priv, 0x23, priv->regs[27]); ++ ++ //set pll autotune = 128kHz (fast) R23[4:3]=2'b00 ++ priv->regs[15] = priv->regs[15] & 0xE7; ++ ret |= r848_wr(priv, 0x17, priv->regs[15]); ++ ++ //Divider ++ while(MixDiv <= 64) { ++ if (((LO_Freq * MixDiv) >= VCO_Min) && ((LO_Freq * MixDiv) < VCO_Max)) { ++ DivBuf = MixDiv; ++ while(DivBuf > 2) { ++ DivBuf = DivBuf >> 1; ++ DivNum ++; ++ } ++ break; ++ } ++ MixDiv = MixDiv << 1; ++ } ++ ++ SDM_RES = 0x00; //short, R27[4:3]=00 ++ priv->regs[19] = (priv->regs[19] & 0xE7) | SDM_RES; ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ ++ // Xtal Div //R848:R24[2] ++ if(R848_Standard == R848_STD_SIZE) { //for cal ++ R848_XtalDiv = XTAL_DIV1; ++ priv->regs[16] = priv->regs[16] & 0xFB; //b2=0 // R848:R24[2] ++ PLL_Ref = R848_Xtal; ++ } else { // DTV_Standard ++ u2XalDivJudge = (u16) (LO_Freq/1000/8); ++ u1XtalDivRemain = (u8) (u2XalDivJudge % 2); ++ if(u1XtalDivRemain==1) { //odd ++ R848_XtalDiv = XTAL_DIV1; ++ priv->regs[16] = priv->regs[16] & 0xFB; //R24[2]=0 ++ PLL_Ref = R848_Xtal; ++ } else { // div2, note that agc clk also div2 ++ R848_XtalDiv = XTAL_DIV2; ++ priv->regs[16] |= 0x04; //R24[2]=1 ++ PLL_Ref = R848_Xtal / 2; ++ } ++ } ++ ret |= r848_wr(priv, 0x18, priv->regs[16]); ++ ++ //Divider num //R24[7:5] ++ priv->regs[16] &= 0x1F; ++ priv->regs[16] |= (DivNum << 5); ++ ret |= r848_wr(priv, 0x18, priv->regs[16]); ++ ++ VCO_Freq = LO_Freq * MixDiv; ++ Nint = (u16) (VCO_Freq / 2 / PLL_Ref); ++ VCO_Fra = (u16) (VCO_Freq - 2 * PLL_Ref * Nint); ++ ++ //Boundary spur prevention ++ if (VCO_Fra < PLL_Ref / 64) { //2*PLL_Ref/128 ++ VCO_Fra = 0; ++ } else if (VCO_Fra > PLL_Ref * 127/64) { //2*PLL_Ref*127/128 ++ VCO_Fra = 0; ++ Nint ++; ++ } else if((VCO_Fra > PLL_Ref * 127/128) && (VCO_Fra < PLL_Ref)) { //> 2*PLL_Ref*127/256, < 2*PLL_Ref*128/256 ++ VCO_Fra = PLL_Ref*127/128; // VCO_Fra = 2*PLL_Ref*127/256 ++ } else if((VCO_Fra > PLL_Ref) && (VCO_Fra < PLL_Ref * 129/128)) { //> 2*PLL_Ref*128/256, < 2*PLL_Ref*129/256 ++ VCO_Fra = PLL_Ref * 129/128; // VCO_Fra = 2*PLL_Ref*129/256 ++ } else { ++ VCO_Fra = VCO_Fra; ++ } ++ ++ //Ni:R848:R28[6:0] Si:R848:R20[5:4] ++ Ni = (Nint - 13) / 4; ++ Si = Nint - 4 *Ni - 13; ++ //Si ++ priv->regs[12] = (priv->regs[12] & 0xCF) | ((Si << 4)); ++ ret |= r848_wr(priv, 0x14, priv->regs[12]); ++ ++ //Ni ++ priv->regs[20] = (priv->regs[20] & 0x80) | (Ni); ++ ret |= r848_wr(priv, 0x1c, priv->regs[20]); ++ ++ //pw_sdm // R848:R27[7] ++ priv->regs[19] &= 0x7F; ++ if(VCO_Fra == 0) ++ priv->regs[19] |= 0x80; ++ ret |= r848_wr(priv, 0x1b, priv->regs[19]); ++ ++ //SDM calculator ++ while(VCO_Fra > 1) { ++ if (VCO_Fra > (2*PLL_Ref / Nsdm)) { ++ SDM = SDM + 32768 / (Nsdm/2); ++ VCO_Fra = VCO_Fra - 2*PLL_Ref / Nsdm; ++ if (Nsdm >= 0x8000) ++ break; ++ } ++ Nsdm = Nsdm << 1; ++ } ++ ++ SDM16to9 = SDM >> 8; ++ SDM8to1 = SDM - (SDM16to9 << 8); ++ ++ // R848:R30[7:0] ++ priv->regs[22] = (u8) SDM16to9; ++ ret |= r848_wr(priv, 0x1e, priv->regs[22]); ++ ++ // R848:R29[7:0] ++ priv->regs[21] = (u8) SDM8to1; ++ ret |= r848_wr(priv, 0x1d, priv->regs[21]); ++ if (ret) ++ return ret; ++ ++ //if(R848_Standard <= R848_SECAM_L1_INV) ++ if(R848_XtalDiv == XTAL_DIV2) ++ msleep(20); ++ else ++ msleep(10); ++ ++ for (VCO_current_trial = 0; VCO_current_trial < 3; VCO_current_trial++) { ++ // check PLL lock status ++ ret = r848_rd(priv, buf, 3); ++ if (ret) ++ return ret; ++ ++ // R848:R26[7:5] | Set VCO current = 011 (3) ++ if ((buf[2] & 0x40) == 0x00) { ++ //increase VCO current ++ priv->regs[18] = (priv->regs[18] & 0x1F) | ((2-VCO_current_trial) << 5); ++ ret = r848_wr(priv, 0x1a, priv->regs[18]); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ if (VCO_current_trial == 2) { ++ //check PLL lock status ++ ret = r848_rd(priv, buf, 3); ++ if (ret) ++ return ret; ++ ++ if( (buf[2] & 0x40) == 0x00) { ++ if(priv->cfg->R848_Xtal_Pwr <= XTAL_SMALL_HIGHEST) ++ XTAL_GM = 0x01; //LARGE(1), R15[4:3]=11 ++ ++ priv->regs[19] = (priv->regs[19] & 0xFE) | XTAL_GM; ++ ret = r848_wr(priv, 0x1b, priv->regs[19]); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ // set pll autotune = 8kHz (slow) ++ priv->regs[15] = (priv->regs[15] & 0xE7) | 0x10; ++ ret = r848_wr(priv, 0x17, priv->regs[15]); ++ ++ // restore TF, NA det setting ++ priv->regs[14] = (priv->regs[14] & 0xFE) | u1RfFlag; ++ ret |= r848_wr(priv, 0x16, priv->regs[14]); ++ ++ priv->regs[30] = (priv->regs[30] & 0x7F) | u1PulseFlag; ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); ++ ++ // Set NA det 710 = OFF ++ priv->regs[32] = (priv->regs[32] & 0xF7) | u1SPulseFlag; ++ ret |= r848_wr(priv, 0x28, priv->regs[32]); ++ ++ return ret; ++} ++ ++ ++ ++/* ++ ++--R9-- ++[7:3]=LNA Cap ++[2]=RF_BUF_pwr ++[1]=Vga code mode ++[0]=VGA PWR on ++ ++R10 ++[5]=?(0) ++[4:0]=LNA Notch ++ ++R11 ++[7]=force plain mode ++[6]=TF current ++[3]=vga6db ++[2]=3~6 shrink ++[1:0]=IMR_Iqcap ++ ++R13 ++[6:5]=LNA band ++[4]=AGC Type (negative=0, positive=1) ++ ++R16 ++[5:0]=IMR_Gain ++ ++R17 ++[7]=LNAPD_PLUSE_ENA ++[5:0]=IMR_Phase ++ ++R33 ++[7:6]=RF Polyfilter band ++[5]=vco_band ++[3:2]=Ring PLL power ++[1:0]=ring_div2 ++ ++*/ ++ ++static int r848_set_mux(struct r848_priv *priv, u32 LO_KHz, u32 RF_KHz, R848_Standard_Type R848_Standard) ++{ ++ int ret; ++ ++ R848_Freq_Info_Type Freq_Info1; ++ u8 Reg08_IMR_Gain = 0; ++ u8 Reg09_IMR_Phase = 0; ++ u8 Reg03_IMR_Iqcap = 0; ++ Freq_Info1 = R848_Freq_Sel(LO_KHz, RF_KHz, R848_Standard); ++ ++ ++ // LNA band (depend on RF_KHz) ++ // R13[6:5] ++ priv->regs[5] = (priv->regs[5] & 0x9F) | Freq_Info1.LNA_BAND; ++ ret = r848_wr(priv, 0x0d, priv->regs[5]); ++ ++ // RF Polyfilter ++ // R33[7:6] ++ priv->regs[25] = (priv->regs[25] & 0x3F) | Freq_Info1.RF_POLY; ++ ret |= r848_wr(priv, 0x21, priv->regs[25]); ++ ++ // LNA Cap ++ // R9[7:3] ++ priv->regs[1] = (priv->regs[1] & 0x07) | (Freq_Info1.LPF_CAP<<3); ++ ret |= r848_wr(priv, 0x09, priv->regs[1]); ++ ++ // LNA Notch ++ // R10[4:0] ++ priv->regs[2] = (priv->regs[2] & 0xE0) | (Freq_Info1.LPF_NOTCH); ++ ret |= r848_wr(priv, 0x0a, priv->regs[2]); ++ ++ //Set_IMR ++ Reg08_IMR_Gain = priv->imr_data[Freq_Info1.IMR_MEM].gain_x & 0x3F; ++ Reg09_IMR_Phase = priv->imr_data[Freq_Info1.IMR_MEM].phase_y & 0x3F; ++ Reg03_IMR_Iqcap = priv->imr_data[Freq_Info1.IMR_MEM].iqcap & 0x03; ++ ++ // R16[5:0] ++ priv->regs[8] = (priv->regs[8] & 0xC0) | Reg08_IMR_Gain; ++ ret |= r848_wr(priv, 0x10, priv->regs[8]); ++ ++ // R17[5:0] ++ priv->regs[9] = (priv->regs[9] & 0xC0) | Reg09_IMR_Phase; ++ ret |= r848_wr(priv, 0x11, priv->regs[9]); ++ ++ // R11[1:0] ++ priv->regs[3] = (priv->regs[3] & 0xFC) | Reg03_IMR_Iqcap; ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); ++ ++ return ret; ++} ++ ++ ++ ++ ++//-----------------------------------------------------------------------------------/ ++// Purpose: compare IMC result aray [0][1][2], find min value and store to CorArry[0] ++// input: CorArry: three IMR data array ++//-----------------------------------------------------------------------------------/ ++static void R848_CompreCor(struct r848_priv *priv, struct r848_sect_type *CorArry) ++{ ++ struct r848_sect_type CorTemp; ++ int i; ++ ++ for (i = 3; i > 0; i--) { ++ //compare IMC result [0][1][2], find min value ++ if (CorArry[0].value > CorArry[i - 1].value) { ++ CorTemp = CorArry[0]; ++ CorArry[0] = CorArry[i - 1]; ++ CorArry[i - 1] = CorTemp; ++ } ++ } ++} ++ ++ ++//-------------------------------------------------------------------------------------------- ++// Purpose: record IMC results by input gain/phase location ++// then adjust gain or phase positive 1 step and negtive 1 step, both record results ++// input: FixPot: phase or gain ++// FlucPot phase or gain ++// PotReg: 0x10 or 0x11 for R848 ++// CompareTree: 3 IMR trace and results ++// output: TRUE or FALSE ++//-------------------------------------------------------------------------------------------- ++static int R848_IQ_Tree( struct r848_priv *priv,u8 FixPot, u8 FlucPot, u8 PotReg, struct r848_sect_type* CompareTree) ++{ ++ int ret, i; ++ u8 PntReg; ++ ++ if(PotReg == 0x10) ++ PntReg = 0x11; //phase control ++ else ++ PntReg = 0x10; //gain control ++ ++ for (i = 0; i < 3; i++) { ++ ret = r848_wr(priv, PotReg, FixPot); ++ ret |= r848_wr(priv, PntReg, FlucPot); ++ ret |= r848_get_imr(priv,&CompareTree[i].value); ++ if (ret) ++ return ret; ++ ++ if (PotReg == 0x10) { ++ CompareTree[i].gain_x = FixPot; ++ CompareTree[i].phase_y = FlucPot; ++ } else { ++ CompareTree[i].phase_y = FixPot; ++ CompareTree[i].gain_x = FlucPot; ++ } ++ ++ if(i == 0) { //try right-side point ++ FlucPot ++; ++ } else if (i == 1) { //try left-side point ++ if((FlucPot & 0x1F) == 1) { //if absolute location is 1, change I/Q direction ++ if(FlucPot & 0x20) { //b[5]:I/Q selection. 0:Q-path, 1:I-path ++ FlucPot = (FlucPot & 0xC0) | 0x01; ++ } else { ++ FlucPot = (FlucPot & 0xC0) | 0x21; ++ } ++ } else { ++ FlucPot = FlucPot - 2; ++ } ++ } ++ } ++ return ret; ++} ++ ++ ++static int R848_Section(struct r848_priv *priv, struct r848_sect_type *IQ_Pont) ++{ ++ struct r848_sect_type Compare_IQ[3]; ++ struct r848_sect_type Compare_Bet[3]; ++ ++ //Try X-1 column and save min result to Compare_Bet[0] ++ if((IQ_Pont->gain_x & 0x1F) == 0x00) ++ { ++ Compare_IQ[0].gain_x = ((IQ_Pont->gain_x) & 0xDF) + 1; //Q-path, Gain=1 ++ } ++ else ++ { ++ Compare_IQ[0].gain_x = IQ_Pont->gain_x - 1; //left point ++ } ++ Compare_IQ[0].phase_y = IQ_Pont->phase_y; ++ ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) // y-direction ++ return RT_Fail; ++ ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ Compare_Bet[0].gain_x = Compare_IQ[0].gain_x; ++ Compare_Bet[0].phase_y = Compare_IQ[0].phase_y; ++ Compare_Bet[0].value = Compare_IQ[0].value; ++ ++ //Try X column and save min result to Compare_Bet[1] ++ Compare_IQ[0].gain_x = IQ_Pont->gain_x; ++ Compare_IQ[0].phase_y = IQ_Pont->phase_y; ++ ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) ++ return RT_Fail; ++ ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ Compare_Bet[1].gain_x = Compare_IQ[0].gain_x; ++ Compare_Bet[1].phase_y = Compare_IQ[0].phase_y; ++ Compare_Bet[1].value = Compare_IQ[0].value; ++ ++ //Try X+1 column and save min result to Compare_Bet[2] ++ if((IQ_Pont->gain_x & 0x1F) == 0x00) ++ Compare_IQ[0].gain_x = ((IQ_Pont->gain_x) | 0x20) + 1; //I-path, Gain=1 ++ else ++ Compare_IQ[0].gain_x = IQ_Pont->gain_x + 1; ++ Compare_IQ[0].phase_y = IQ_Pont->phase_y; ++ ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) ++ return RT_Fail; ++ ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ Compare_Bet[2].gain_x = Compare_IQ[0].gain_x; ++ Compare_Bet[2].phase_y = Compare_IQ[0].phase_y; ++ Compare_Bet[2].value = Compare_IQ[0].value; ++ ++ R848_CompreCor(priv,&Compare_Bet[0]); ++ return RT_Fail; ++ ++ *IQ_Pont = Compare_Bet[0]; ++ ++ return RT_Success; ++} ++ ++R848_ErrCode R848_IMR_Cross( struct r848_priv *priv,struct r848_sect_type* IQ_Pont, u8* X_Direct) ++{ ++ int ret; ++ ++ struct r848_sect_type Compare_Cross[9]; //(0,0)(0,Q-1)(0,I-1)(Q-1,0)(I-1,0)+(0,Q-2)(0,I-2)(Q-2,0)(I-2,0) ++ struct r848_sect_type Compare_Temp; ++ u8 CrossCount = 0; ++ u8 Reg16 = priv->regs[8] & 0xC0; ++ u8 Reg17 = priv->regs[9] & 0xC0; ++ ++ memset(&Compare_Temp, 0, sizeof(struct r848_sect_type)); ++ Compare_Temp.value = 255; ++ ++ for(CrossCount=0; CrossCount<9; CrossCount++) ++ { ++ ++ if(CrossCount==0) ++ { ++ Compare_Cross[CrossCount].gain_x = Reg16; ++ Compare_Cross[CrossCount].phase_y = Reg17; ++ } ++ else if(CrossCount==1) ++ { ++ Compare_Cross[CrossCount].gain_x = Reg16; //0 ++ Compare_Cross[CrossCount].phase_y = Reg17 + 1; //Q-1 ++ } ++ else if(CrossCount==2) ++ { ++ Compare_Cross[CrossCount].gain_x = Reg16; //0 ++ Compare_Cross[CrossCount].phase_y = (Reg17 | 0x20) + 1; //I-1 ++ } ++ else if(CrossCount==3) ++ { ++ Compare_Cross[CrossCount].gain_x = Reg16 + 1; //Q-1 ++ Compare_Cross[CrossCount].phase_y = Reg17; ++ } ++ else if(CrossCount==4) ++ { ++ Compare_Cross[CrossCount].gain_x = (Reg16 | 0x20) + 1; //I-1 ++ Compare_Cross[CrossCount].phase_y = Reg17; ++ } ++ else if(CrossCount==5) ++ { ++ Compare_Cross[CrossCount].gain_x = Reg16; //0 ++ Compare_Cross[CrossCount].phase_y = Reg17 + 2; //Q-2 ++ } ++ else if(CrossCount==6) ++ { ++ Compare_Cross[CrossCount].gain_x = Reg16; //0 ++ Compare_Cross[CrossCount].phase_y = (Reg17 | 0x20) + 2; //I-2 ++ } ++ else if(CrossCount==7) ++ { ++ Compare_Cross[CrossCount].gain_x = Reg16 + 2; //Q-2 ++ Compare_Cross[CrossCount].phase_y = Reg17; ++ } ++ else if(CrossCount==8) ++ { ++ Compare_Cross[CrossCount].gain_x = (Reg16 | 0x20) + 2; //I-2 ++ Compare_Cross[CrossCount].phase_y = Reg17; ++ } ++ ++ ret = r848_wr(priv, 0x10, Compare_Cross[CrossCount].gain_x); ++ if (ret) ++ return ret; ++ ++ ret = r848_wr(priv, 0x11, Compare_Cross[CrossCount].phase_y); ++ if (ret) ++ return ret; ++ ++ if(r848_get_imr(priv,&Compare_Cross[CrossCount].value) != RT_Success) ++ return RT_Fail; ++ ++ if( Compare_Cross[CrossCount].value < Compare_Temp.value) ++ { ++ Compare_Temp.value = Compare_Cross[CrossCount].value; ++ Compare_Temp.gain_x = Compare_Cross[CrossCount].gain_x; ++ Compare_Temp.phase_y = Compare_Cross[CrossCount].phase_y; ++ } ++ } //end for loop ++ ++ ++ if(((Compare_Temp.phase_y & 0x3F)==0x01) || (Compare_Temp.phase_y & 0x3F)==0x02) //phase Q1 or Q2 ++ { ++ *X_Direct = (u8) 0; ++ IQ_Pont[0].gain_x = Compare_Cross[0].gain_x; //0 ++ IQ_Pont[0].phase_y = Compare_Cross[0].phase_y; //0 ++ IQ_Pont[0].value = Compare_Cross[0].value; ++ ++ IQ_Pont[1].gain_x = Compare_Cross[1].gain_x; //0 ++ IQ_Pont[1].phase_y = Compare_Cross[1].phase_y; //Q1 ++ IQ_Pont[1].value = Compare_Cross[1].value; ++ ++ IQ_Pont[2].gain_x = Compare_Cross[5].gain_x; //0 ++ IQ_Pont[2].phase_y = Compare_Cross[5].phase_y;//Q2 ++ IQ_Pont[2].value = Compare_Cross[5].value; ++ } ++ else if(((Compare_Temp.phase_y & 0x3F)==0x21) || (Compare_Temp.phase_y & 0x3F)==0x22) //phase I1 or I2 ++ { ++ *X_Direct = (u8) 0; ++ IQ_Pont[0].gain_x = Compare_Cross[0].gain_x; //0 ++ IQ_Pont[0].phase_y = Compare_Cross[0].phase_y; //0 ++ IQ_Pont[0].value = Compare_Cross[0].value; ++ ++ IQ_Pont[1].gain_x = Compare_Cross[2].gain_x; //0 ++ IQ_Pont[1].phase_y = Compare_Cross[2].phase_y; //Q1 ++ IQ_Pont[1].value = Compare_Cross[2].value; ++ ++ IQ_Pont[2].gain_x = Compare_Cross[6].gain_x; //0 ++ IQ_Pont[2].phase_y = Compare_Cross[6].phase_y;//Q2 ++ IQ_Pont[2].value = Compare_Cross[6].value; ++ } ++ else if(((Compare_Temp.gain_x & 0x3F)==0x01) || (Compare_Temp.gain_x & 0x3F)==0x02) //gain Q1 or Q2 ++ { ++ *X_Direct = (u8) 1; ++ IQ_Pont[0].gain_x = Compare_Cross[0].gain_x; //0 ++ IQ_Pont[0].phase_y = Compare_Cross[0].phase_y; //0 ++ IQ_Pont[0].value = Compare_Cross[0].value; ++ ++ IQ_Pont[1].gain_x = Compare_Cross[3].gain_x; //Q1 ++ IQ_Pont[1].phase_y = Compare_Cross[3].phase_y; //0 ++ IQ_Pont[1].value = Compare_Cross[3].value; ++ ++ IQ_Pont[2].gain_x = Compare_Cross[7].gain_x; //Q2 ++ IQ_Pont[2].phase_y = Compare_Cross[7].phase_y;//0 ++ IQ_Pont[2].value = Compare_Cross[7].value; ++ } ++ else if(((Compare_Temp.gain_x & 0x3F)==0x21) || (Compare_Temp.gain_x & 0x3F)==0x22) //gain I1 or I2 ++ { ++ *X_Direct = (u8) 1; ++ IQ_Pont[0].gain_x = Compare_Cross[0].gain_x; //0 ++ IQ_Pont[0].phase_y = Compare_Cross[0].phase_y; //0 ++ IQ_Pont[0].value = Compare_Cross[0].value; ++ ++ IQ_Pont[1].gain_x = Compare_Cross[4].gain_x; //I1 ++ IQ_Pont[1].phase_y = Compare_Cross[4].phase_y; //0 ++ IQ_Pont[1].value = Compare_Cross[4].value; ++ ++ IQ_Pont[2].gain_x = Compare_Cross[8].gain_x; //I2 ++ IQ_Pont[2].phase_y = Compare_Cross[8].phase_y;//0 ++ IQ_Pont[2].value = Compare_Cross[8].value; ++ } ++ else //(0,0) ++ { ++ *X_Direct = (u8) 1; ++ IQ_Pont[0].gain_x = Compare_Cross[0].gain_x; ++ IQ_Pont[0].phase_y = Compare_Cross[0].phase_y; ++ IQ_Pont[0].value = Compare_Cross[0].value; ++ ++ IQ_Pont[1].gain_x = Compare_Cross[3].gain_x; //Q1 ++ IQ_Pont[1].phase_y = Compare_Cross[3].phase_y; //0 ++ IQ_Pont[1].value = Compare_Cross[3].value; ++ ++ IQ_Pont[2].gain_x = Compare_Cross[4].gain_x; //I1 ++ IQ_Pont[2].phase_y = Compare_Cross[4].phase_y; //0 ++ IQ_Pont[2].value = Compare_Cross[4].value; ++ } ++ return RT_Success; ++} ++ ++//-------------------------------------------------------------------------------------// ++// Purpose: if (Gain<9 or Phase<9), Gain+1 or Phase+1 and compare with min value ++// new < min => update to min and continue ++// new > min => Exit ++// input: StepArry: three IMR data array ++// Pace: gain or phase register ++//-------------------------------------------------------------------------------------// ++R848_ErrCode R848_CompreStep( struct r848_priv *priv,struct r848_sect_type* StepArry, u8 Pace) ++{ ++ int ret; ++ struct r848_sect_type StepTemp; ++ //min value already saved in StepArry[0] ++ StepTemp.phase_y = StepArry[0].phase_y; ++ StepTemp.gain_x = StepArry[0].gain_x; ++ //StepTemp.iqcap = StepArry[0].iqcap; ++ ++ while(((StepTemp.gain_x & 0x1F) < R848_IMR_TRIAL) && ((StepTemp.phase_y & 0x1F) < R848_IMR_TRIAL)) ++ { ++ if(Pace == 0x10) ++ StepTemp.gain_x ++; ++ else ++ StepTemp.phase_y ++; ++ ++ ret = r848_wr(priv, 0x10, StepTemp.gain_x); ++ if (ret) ++ return ret; ++ ++ ret = r848_wr(priv, 0x11, StepTemp.phase_y); ++ if (ret) ++ return ret; ++ ++ if(r848_get_imr(priv,&StepTemp.value) != RT_Success) ++ return RT_Fail; ++ ++ if(StepTemp.value <= StepArry[0].value) ++ { ++ StepArry[0].gain_x = StepTemp.gain_x; ++ StepArry[0].phase_y = StepTemp.phase_y; ++ //StepArry[0].iqcap = StepTemp.iqcap; ++ StepArry[0].value = StepTemp.value; ++ } ++ else if((StepTemp.value - 2) > StepArry[0].value) ++ { ++ break; ++ } ++ ++ } //end of while() ++ ++ return RT_Success; ++} ++ ++R848_ErrCode R848_IMR_Iqcap( struct r848_priv *priv,struct r848_sect_type* IQ_Point) ++{ ++ struct r848_sect_type Compare_Temp; ++ int i = 0, ret; ++ ++ //Set Gain/Phase to right setting ++// R848_I2C.RegAddr = 0x10; // R16[5:0] ++ ret = r848_wr(priv, 0x10, IQ_Point->gain_x); ++ if (ret) ++ return ret; ++ ++// R848_I2C.RegAddr = 0x11; // R17[5:0] ++ ret = r848_wr(priv, 0x11, IQ_Point->phase_y); ++ if (ret) ++ return ret; ++ ++ //try iqcap ++ for(i=0; i<3; i++) ++ { ++ Compare_Temp.iqcap = (u8) i; ++// R848_I2C.RegAddr = 0x0B; // R11[1:0] ++ priv->regs[3] = (priv->regs[3] & 0xFC) | Compare_Temp.iqcap; ++ ret = r848_wr(priv, 0x0b, priv->regs[3]); ++ if (ret) ++ return ret; ++ ++ if(r848_get_imr(priv,&(Compare_Temp.value)) != RT_Success) ++ return RT_Fail; ++ ++ if(Compare_Temp.value < IQ_Point->value) ++ { ++ IQ_Point->value = Compare_Temp.value; ++ IQ_Point->iqcap = Compare_Temp.iqcap; ++ } ++ } ++ ++ return RT_Success; ++} ++ ++ ++R848_ErrCode R848_IQ( struct r848_priv *priv,struct r848_sect_type* IQ_Pont) ++{ ++ int ret; ++ struct r848_sect_type Compare_IQ[3]; ++ u8 VGA_Count = 0; ++ u8 VGA_Read = 0; ++ u8 X_Direction; // 1:X, 0:Y ++ ++ ++ // increase VGA power to let image significant ++ for(VGA_Count=11; VGA_Count < 16; VGA_Count ++) ++ { ++// R848_I2C.RegAddr = 0x14; // R848:R20[3:0] ++ ret = r848_wr(priv, 0x14, (priv->regs[12] & 0xF0) + VGA_Count); ++ if (ret) ++ return ret; ++ ++ msleep(10); ++ ++ if(r848_get_imr(priv,&VGA_Read) != RT_Success) ++ return RT_Fail; ++ ++ if(VGA_Read > 40) ++ break; ++ } ++ ++ Compare_IQ[0].gain_x = priv->regs[8] & 0xC0; // R16[5:0] ++ Compare_IQ[0].phase_y = priv->regs[9] & 0xC0; // R17[5:0] ++ //Compare_IQ[0].iqcap = R848_iniArray[3] & 0xFC; ++ ++ // Determine X or Y ++ if(R848_IMR_Cross(priv,&Compare_IQ[0], &X_Direction) != RT_Success) ++ return RT_Fail; ++ ++ if(X_Direction==1) ++ { ++ //compare and find min of 3 points. determine I/Q direction ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ //increase step to find min value of this direction ++ if(R848_CompreStep(priv,&Compare_IQ[0], 0x10) != RT_Success) //X ++ return RT_Fail; ++ } ++ else ++ { ++ //compare and find min of 3 points. determine I/Q direction ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ //increase step to find min value of this direction ++ if(R848_CompreStep(priv,&Compare_IQ[0], 0x11) != RT_Success) //Y ++ return RT_Fail; ++ } ++ ++ //Another direction ++ if(X_Direction==1) ++ { ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) //Y ++ return RT_Fail; ++ ++ //compare and find min of 3 points. determine I/Q direction ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ //increase step to find min value of this direction ++ if(R848_CompreStep(priv,&Compare_IQ[0], 0x11) != RT_Success) //Y ++ return RT_Fail; ++ } ++ else ++ { ++ if(R848_IQ_Tree(priv,Compare_IQ[0].phase_y, Compare_IQ[0].gain_x, 0x11, &Compare_IQ[0]) != RT_Success) //X ++ return RT_Fail; ++ ++ //compare and find min of 3 points. determine I/Q direction ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ //increase step to find min value of this direction ++ if(R848_CompreStep(priv,&Compare_IQ[0], 0x10) != RT_Success) //X ++ return RT_Fail; ++ } ++ ++ ++ //--- Check 3 points again---// ++ if(X_Direction==1) ++ { ++ if(R848_IQ_Tree(priv,Compare_IQ[0].phase_y, Compare_IQ[0].gain_x, 0x11, &Compare_IQ[0]) != RT_Success) //X ++ return RT_Fail; ++ } ++ else ++ { ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) //Y ++ return RT_Fail; ++ } ++ ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ //Section-9 check ++ //if(R848_F_IMR(&Compare_IQ[0]) != RT_Success) ++ if(R848_Section(priv,&Compare_IQ[0]) != RT_Success) ++ return RT_Fail; ++ ++ //clear IQ_Cap = 0 // R11[1:0] ++ Compare_IQ[0].iqcap = priv->regs[3] & 0xFC; ++ ++ if(R848_IMR_Iqcap(priv,&Compare_IQ[0]) != RT_Success) ++ return RT_Fail; ++ ++ *IQ_Pont = Compare_IQ[0]; ++ ++ //reset gain/phase/iqcap control setting ++// R848_I2C.RegAddr = 0x10; // R16[5:0] ++ priv->regs[8] = priv->regs[8] & 0xC0; ++ ret = r848_wr(priv, 0x10, priv->regs[8]); ++ if (ret) ++ return ret; ++ ++// R848_I2C.RegAddr = 0x11; // R17[5:0] ++ priv->regs[9] = priv->regs[9] & 0xC0; ++ ret = r848_wr(priv, 0x11, priv->regs[9]); ++ if (ret) ++ return ret; ++ ++// R848_I2C.RegAddr = 0x0B; // R11[1:0] ++ priv->regs[3] = priv->regs[3] & 0xFC; ++ ret = r848_wr(priv, 0x0b, priv->regs[3]); ++ if (ret) ++ return ret; ++ ++ return RT_Success; ++} ++ ++//----------------------------------------------------------------------------------------// ++// purpose: search surrounding points from previous point ++// try (x-1), (x), (x+1) columns, and find min IMR result point ++// input: IQ_Pont: previous point data(IMR Gain, Phase, ADC Result, RefRreq) ++// will be updated to final best point ++// output: TRUE or FALSE ++//----------------------------------------------------------------------------------------// ++R848_ErrCode R848_F_IMR( struct r848_priv *priv,struct r848_sect_type* IQ_Pont) ++{ ++ int ret; ++ struct r848_sect_type Compare_IQ[3]; ++ struct r848_sect_type Compare_Bet[3]; ++ u8 VGA_Count = 0; ++ u8 VGA_Read = 0; ++ ++ //VGA ++ for(VGA_Count=11; VGA_Count < 16; VGA_Count ++) ++ { ++// R848_I2C.RegAddr = 0x14; // R20[3:0] ++ ret = r848_wr(priv, 0x14, (priv->regs[12] & 0xF0) + VGA_Count); ++ if (ret) ++ return ret; ++ ++ msleep(10); ++ ++ if(r848_get_imr(priv,&VGA_Read) != RT_Success) ++ return RT_Fail; ++ ++ if(VGA_Read > 40) ++ break; ++ } ++ ++ //Try X-1 column and save min result to Compare_Bet[0] ++ if((IQ_Pont->gain_x & 0x1F) == 0x00) ++ { ++ Compare_IQ[0].gain_x = ((IQ_Pont->gain_x) & 0xDF) + 1; //Q-path, Gain=1 ++ } ++ else ++ { ++ Compare_IQ[0].gain_x = IQ_Pont->gain_x - 1; //left point ++ } ++ Compare_IQ[0].phase_y = IQ_Pont->phase_y; ++ ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) // y-direction ++ return RT_Fail; ++ ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ Compare_Bet[0].gain_x = Compare_IQ[0].gain_x; ++ Compare_Bet[0].phase_y = Compare_IQ[0].phase_y; ++ Compare_Bet[0].value = Compare_IQ[0].value; ++ ++ //Try X column and save min result to Compare_Bet[1] ++ Compare_IQ[0].gain_x = IQ_Pont->gain_x; ++ Compare_IQ[0].phase_y = IQ_Pont->phase_y; ++ ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) ++ return RT_Fail; ++ ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ Compare_Bet[1].gain_x = Compare_IQ[0].gain_x; ++ Compare_Bet[1].phase_y = Compare_IQ[0].phase_y; ++ Compare_Bet[1].value = Compare_IQ[0].value; ++ ++ //Try X+1 column and save min result to Compare_Bet[2] ++ if((IQ_Pont->gain_x & 0x1F) == 0x00) ++ Compare_IQ[0].gain_x = ((IQ_Pont->gain_x) | 0x20) + 1; //I-path, Gain=1 ++ else ++ Compare_IQ[0].gain_x = IQ_Pont->gain_x + 1; ++ Compare_IQ[0].phase_y = IQ_Pont->phase_y; ++ ++ if(R848_IQ_Tree(priv,Compare_IQ[0].gain_x, Compare_IQ[0].phase_y, 0x10, &Compare_IQ[0]) != RT_Success) ++ return RT_Fail; ++ ++ R848_CompreCor(priv,&Compare_IQ[0]); ++ ++ Compare_Bet[2].gain_x = Compare_IQ[0].gain_x; ++ Compare_Bet[2].phase_y = Compare_IQ[0].phase_y; ++ Compare_Bet[2].value = Compare_IQ[0].value; ++ ++ R848_CompreCor(priv,&Compare_Bet[0]); ++ ++ //clear IQ_Cap = 0 ++ Compare_Bet[0].iqcap = priv->regs[3] & 0xFC; // R11[1:0] ++ ++ if(R848_IMR_Iqcap(priv,&Compare_Bet[0]) != RT_Success) ++ return RT_Fail; ++ ++ *IQ_Pont = Compare_Bet[0]; ++ ++ return RT_Success; ++} ++ ++ ++R848_ErrCode R848_SetTF( struct r848_priv *priv,u32 u4FreqKHz, u8 u1TfType) ++{ ++ int ret; ++ u8 u1FreqCount = 0; ++ u32 u4Freq1 = 0; ++ u32 u4Freq2 = 0; ++ u32 u4Ratio; ++ u8 u1TF_Set_Result1 = 0; ++ u8 u1TF_Set_Result2 = 0; ++ u8 u1TF_tmp1, u1TF_tmp2; ++ u8 u1TFCalNum = R848_TF_HIGH_NUM; ++ u8 R848_TF = 0; ++ ++ if(u4FreqKHz>2)*3 + (u1TF_Set_Result1 & 0x3F); //b6 is 3xb4 ++ u1TF_tmp2 = ((u1TF_Set_Result2 & 0x40)>>2)*3 + (u1TF_Set_Result2 & 0x3F); ++ u4Ratio = (u4Freq1- u4FreqKHz)*100/(u4Freq1 - u4Freq2); ++ R848_TF = u1TF_tmp1 + (u8)((u1TF_tmp2 - u1TF_tmp1)*u4Ratio/100); ++ if(R848_TF>=0x40) ++ R848_TF = (R848_TF + 0x10); ++ ++ } ++ } ++ else if((u4FreqKHz>=R848_LNA_LOW_LOWEST[R848_TF_BEAD]) && (u4FreqKHz>2) + (u1TF_Set_Result1 & 0x3F); //b6 is 1xb4 ++ u1TF_tmp2 = ((u1TF_Set_Result2 & 0x40)>>2) + (u1TF_Set_Result2 & 0x3F); ++ u4Ratio = (u4Freq1- u4FreqKHz)*100/(u4Freq1 - u4Freq2); ++ R848_TF = u1TF_tmp1 + (u8)((u1TF_tmp2 - u1TF_tmp1)*u4Ratio/100); ++ if(R848_TF>=0x40) ++ R848_TF = (R848_TF + 0x30); ++ } ++ } ++ else if((u4FreqKHz>=R848_LNA_MID_LOW[R848_TF_BEAD]) && (u4FreqKHzregs[0] = (priv->regs[0] & 0x80) | R848_TF; ++ ret = r848_wr(priv, 0x0b, priv->regs[0]); ++ if (ret) ++ return ret; ++ ++ return RT_Success; ++} ++ ++R848_ErrCode R848_IMR( struct r848_priv *priv,u8 IMR_MEM, bool IM_Flag) ++{ ++ int ret; ++ u32 RingVCO = 0; ++ u32 RingFreq = 0; ++ u8 u1MixerGain = 8; ++ ++ struct r848_sect_type IMR_POINT; ++ ++ RingVCO = 3200000; ++ priv->regs[31] &= 0x3F; //clear ring_div1, R24[7:6] //R848:R39[7:6] 39-8=31 39(0x27) is addr ; [31] is data ++ priv->regs[25] &= 0xFC; //clear ring_div2, R25[1:0] //R848:R33[1:0] 33-8=25 33(0x21) is addr ; [25] is data ++ priv->regs[25] &= 0xDF; //clear vco_band, R25[5] //R848:R33[5] 33-8=25 33(0x21) is addr ; [25] is data ++ priv->regs[31] &= 0xC3; //clear ring_div_num, R24[3:0]//R848:R39[5:2] 39-8=31 39(0x27) is addr ; [31] is data ++ ++ switch(IMR_MEM) ++ { ++ case 0: // RingFreq = 66.66M ++ RingFreq = RingVCO/48; ++ priv->regs[31] |= 0x80; // ring_div1 /6 (2) ++ priv->regs[25] |= 0x03; // ring_div2 /8 (3) ++ priv->regs[25] |= 0x00; // vco_band = 0 (high) ++ priv->regs[31] |= 0x24; // ring_div_num = 9 ++ u1MixerGain = 8; ++ break; ++ case 1: // RingFreq = 200M ++ RingFreq = RingVCO/16; ++ priv->regs[31] |= 0x00; // ring_div1 /4 (0) ++ priv->regs[25] |= 0x02; // ring_div2 /4 (2) ++ priv->regs[25] |= 0x00; // vco_band = 0 (high) ++ priv->regs[31] |= 0x24; // ring_div_num = 9 ++ u1MixerGain = 6; ++ break; ++ case 2: // RingFreq = 400M ++ RingFreq = RingVCO/8; ++ priv->regs[31] |= 0x00; // ring_div1 /4 (0) ++ priv->regs[25] |= 0x01; // ring_div2 /2 (1) ++ priv->regs[25] |= 0x00; // vco_band = 0 (high) ++ priv->regs[31] |= 0x24; // ring_div_num = 9 ++ u1MixerGain = 6; ++ break; ++ case 3: // RingFreq = 533.33M ++ RingFreq = RingVCO/6; ++ priv->regs[31] |= 0x80; // ring_div1 /6 (2) ++ priv->regs[25] |= 0x00; // ring_div2 /1 (0) ++ priv->regs[25] |= 0x00; // vco_band = 0 (high) ++ priv->regs[31] |= 0x24; // ring_div_num = 9 ++ u1MixerGain = 8; ++ break; ++ case 4: // RingFreq = 800M ++ RingFreq = RingVCO/4; ++ priv->regs[31] |= 0x00; // ring_div1 /4 (0) ++ priv->regs[25] |= 0x00; // ring_div2 /1 (0) ++ priv->regs[25] |= 0x00; // vco_band = 0 (high) ++ priv->regs[31] |= 0x24; // ring_div_num = 9 ++ u1MixerGain = 8; ++ break; ++ default: ++ RingFreq = RingVCO/4; ++ priv->regs[31] |= 0x00; // ring_div1 /4 (0) ++ priv->regs[25] |= 0x00; // ring_div2 /1 (0) ++ priv->regs[25] |= 0x00; // vco_band = 0 (high) ++ priv->regs[31] |= 0x24; // ring_div_num = 9 ++ u1MixerGain = 8; ++ break; ++ } ++ ++ //Mixer Amp Gain ++ //R848_I2C.RegAddr = 0x0F; //R848:R15[4:0] ++ priv->regs[7] = (priv->regs[7] & 0xE0) | u1MixerGain; ++ ret = r848_wr(priv, 0x0f, priv->regs[7]); ++ ++ //write I2C to set RingPLL ++ ret |= r848_wr(priv, 0x27, priv->regs[31]); ++ ret |= r848_wr(priv, 0x21, priv->regs[25]); ++ ++ //Ring PLL power ++ //if((RingFreq>=0) && (RingFreqR848_RING_POWER_FREQ_HIGH))) //R848:R33[3:2] ++ priv->regs[25] = (priv->regs[25] & 0xF3) | 0x08; //R25[3:2]=2'b10; min_lp ++ else ++ priv->regs[25] = (priv->regs[25] & 0xF3) | 0x00; //R25[3:2]=2'b00; min ++ ++ ret |= r848_wr(priv, 0x21, priv->regs[25]); ++ ++ //Must do MUX before PLL() ++ if(r848_set_mux(priv,RingFreq - R848_IMR_IF, RingFreq, R848_STD_SIZE) != RT_Success) //IMR MUX (LO, RF) ++ return RT_Fail; ++ ++ if(r848_set_pll(priv,(RingFreq - R848_IMR_IF), R848_STD_SIZE) != RT_Success) //IMR PLL ++ return RT_Fail; ++ ++ //Set TF, place after R848_MUX( ) ++ //TF is dependent to LNA/Mixer Gain setting ++ if(R848_SetTF(priv,RingFreq, (u8)R848_TF_BEAD) != RT_Success) ++ return RT_Fail; ++ ++ //clear IQ_cap ++ IMR_POINT.iqcap = priv->regs[3] & 0xFC; // R848:R11[1:0] ++ ++ if(IM_Flag == 0) ++ { ++ if(R848_IQ(priv,&IMR_POINT) != RT_Success) ++ return RT_Fail; ++ } ++ else ++ { ++ IMR_POINT.gain_x = priv->imr_data[3].gain_x; ++ IMR_POINT.phase_y = priv->imr_data[3].phase_y; ++ IMR_POINT.value = priv->imr_data[3].value; ++ //IMR_POINT.iqcap = priv->imr_data[3].iqcap; ++ if(R848_F_IMR(priv,&IMR_POINT) != RT_Success) ++ return RT_Fail; ++ } ++ ++ //Save IMR Value ++ switch(IMR_MEM) ++ { ++ case 0: ++ priv->imr_data[0].gain_x = IMR_POINT.gain_x; ++ priv->imr_data[0].phase_y = IMR_POINT.phase_y; ++ priv->imr_data[0].value = IMR_POINT.value; ++ priv->imr_data[0].iqcap = IMR_POINT.iqcap; ++ break; ++ case 1: ++ priv->imr_data[1].gain_x = IMR_POINT.gain_x; ++ priv->imr_data[1].phase_y = IMR_POINT.phase_y; ++ priv->imr_data[1].value = IMR_POINT.value; ++ priv->imr_data[1].iqcap = IMR_POINT.iqcap; ++ break; ++ case 2: ++ priv->imr_data[2].gain_x = IMR_POINT.gain_x; ++ priv->imr_data[2].phase_y = IMR_POINT.phase_y; ++ priv->imr_data[2].value = IMR_POINT.value; ++ priv->imr_data[2].iqcap = IMR_POINT.iqcap; ++ break; ++ case 3: ++ priv->imr_data[3].gain_x = IMR_POINT.gain_x; ++ priv->imr_data[3].phase_y = IMR_POINT.phase_y; ++ priv->imr_data[3].value = IMR_POINT.value; ++ priv->imr_data[3].iqcap = IMR_POINT.iqcap; ++ break; ++ case 4: ++ priv->imr_data[4].gain_x = IMR_POINT.gain_x; ++ priv->imr_data[4].phase_y = IMR_POINT.phase_y; ++ priv->imr_data[4].value = IMR_POINT.value; ++ priv->imr_data[4].iqcap = IMR_POINT.iqcap; ++ break; ++ default: ++ priv->imr_data[4].gain_x = IMR_POINT.gain_x; ++ priv->imr_data[4].phase_y = IMR_POINT.phase_y; ++ priv->imr_data[4].value = IMR_POINT.value; ++ priv->imr_data[4].iqcap = IMR_POINT.iqcap; ++ break; ++ } ++ return ret; ++} ++ ++ ++ ++#if 0 ++static int R848_GPO( struct r848_priv *priv,R848_GPO_Type R848_GPO_Conrl) ++{ ++ if(R848_GPO_Conrl == HI_SIG) // R23[0] ++ priv->regs[15] |= 0x01; //high ++ else ++ priv->regs[15] &= 0xFE; //low ++ return r848_wr(priv, 0x17, priv->regs[15]); ++} ++#endif ++ ++ ++u8 R848_Filt_Cal_ADC( struct r848_priv *priv,u32 IF_Freq, u8 R848_BW, u8 FilCal_Gap) ++{ ++ int ret; ++ u8 u1FilterCodeResult = 0; ++ u8 u1FilterCode = 0; ++ u32 u4RingFreq = 72000; ++ u8 u1FilterCalValue = 0; ++ u8 u1FilterCalValuePre = 0; ++ u8 initial_cnt = 0; ++ u8 i = 0; ++ u8 R848_Bandwidth = 0x00; ++ u8 VGA_Count = 0; ++ u8 VGA_Read = 0; ++ ++ R848_Standard_Type R848_Standard; ++ R848_Standard=R848_ATSC; //no set R848_DVB_S ++ ++ //Write initial reg before doing calibration ++ if(r848_init_regs(priv,R848_Standard) != RT_Success) ++ return RT_Fail; ++ ++ if(R848_Cal_Prepare(priv,R848_LPF_CAL) != RT_Success) ++ return RT_Fail; ++ ++ ++ ++ // R848:R39[5:2] ++ priv->regs[31] = (priv->regs[31] & 0xC3) | 0x2C; ++ ret = r848_wr(priv, 0x27, priv->regs[31]); ++ ++ // R848_I2C.RegAddr = 0x12; //R848:R18[4] ++ priv->regs[10] = (priv->regs[10] & 0xEF) | 0x00; ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ // R848_I2C.RegAddr = 0x25; // R848:R37[7] ++ priv->regs[29] = (priv->regs[29] & 0x7F) | 0x00; ++ ret |= r848_wr(priv, 0x25, priv->regs[29]); ++ ++ // R848_I2C.RegAddr = 0x27; // R848:R39[7:6] ++ priv->regs[31] = (priv->regs[31] & 0x3F) | 0x80; ++ ret |= r848_wr(priv, 0x27, priv->regs[31]); ++ ++ // R848_I2C.RegAddr = 0x21; // R848:R33[7:0] ++ priv->regs[25] = (priv->regs[25] & 0x00) | 0x8B; //out div=8, RF poly=low band, power=min_lp ++ ret |= r848_wr(priv, 0x21, priv->regs[25]); ++ ++ //Must do before PLL() ++ if(r848_set_mux(priv,u4RingFreq + IF_Freq, u4RingFreq, R848_STD_SIZE) != RT_Success) //FilCal MUX (LO_Freq, RF_Freq) ++ return RT_Fail; ++ ++ //Set PLL ++ if(r848_set_pll(priv,(u4RingFreq + IF_Freq), R848_STD_SIZE) != RT_Success) //FilCal PLL ++ return RT_Fail; ++ ++ //-----below must set after R848_MUX()-------// ++ //Set LNA TF for RF=72MHz. no use ++ ++ // R848_I2C.RegAddr = 0x08; // R848:R8[6:0] ++ priv->regs[0] = (priv->regs[0] & 0x80) | 0x00; ++ ret |= r848_wr(priv, 0x08, priv->regs[0]); ++ ++ //Adc=on set 0; ++ //R848_I2C.RegAddr = 0x0F; // R848:R15[7] ++ priv->regs[7] = (priv->regs[7] & 0x7F); ++ ret |= r848_wr(priv, 0x0f, priv->regs[7]); ++ ++ ++ ++ //pwd_vga vga power on set 0; ++ //R848_I2C.RegAddr = 0x12; // R848:R18[7] ++ priv->regs[10] = (priv->regs[10] & 0x7F); ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ ++ //vga6db normal set 0; ++ //R848_I2C.RegAddr = 0x0B; // R848:R11[3] ++ priv->regs[3] = (priv->regs[3] & 0xF7); ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); ++ ++ //Vga Gain = -12dB ++ //R848_I2C.RegAddr = 0x14; // R848:R20[3:0] ++ priv->regs[12] = (priv->regs[12] & 0xF0); ++ ret |= r848_wr(priv, 0x14, priv->regs[12]); ++ ++ // vcomp = 0 ++ //R848_I2C.RegAddr = 0x26; // R848:R38[6:5] ++ priv->regs[30] = (priv->regs[30] & 0x9F); ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); ++ ++ //Set BW=8M, HPF corner narrowest; 1.7M disable ++ //R848_I2C.RegAddr = 0x13; // R848:R19[7:0] ++ priv->regs[11] = (priv->regs[11] & 0x00); ++ ret |= r848_wr(priv, 0x13, priv->regs[11]); ++ ++ //------- increase VGA power to let ADC read value significant ---------// ++ ++ //R848_I2C.RegAddr = 0x12; // R848:R18[3:0] ++ priv->regs[10] = (priv->regs[10] & 0xF0) | 0; //filter code=0 ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ if (ret) ++ return ret; ++ ++ ++ for (VGA_Count = 0; VGA_Count < 16; VGA_Count++) { ++ //R848_I2C.RegAddr = 0x14; // R848:R20[3:0] ++ ret = r848_wr(priv, 0x14, (priv->regs[12] & 0xF0) + VGA_Count); ++ msleep(10); ++ ret |= r848_get_imr(priv,&VGA_Read); ++ if (ret) ++ return ret; ++ if (VGA_Read > 40) ++ break; ++ } ++ ++ //------- Try suitable BW --------// ++ ++ if(R848_BW==0x60) //6M ++ initial_cnt = 1; //try 7M first ++ else ++ initial_cnt = 0; //try 8M first ++ ++ for(i=initial_cnt; i<3; i++) ++ { ++ if(i==0) ++ R848_Bandwidth = 0x00; //8M ++ else if(i==1) ++ R848_Bandwidth = 0x40; //7M ++ else ++ R848_Bandwidth = 0x60; //6M ++ ++ //R848_I2C.RegAddr = 0x13; // R848:R19[7:0] ++ priv->regs[11] = (priv->regs[11] & 0x00) | R848_Bandwidth; ++ ret |= r848_wr(priv, 0x13, priv->regs[11]); ++ ++ // read code 0 ++ //R848_I2C.RegAddr = 0x12; // R848:R18[3:0] ++ priv->regs[10] = (priv->regs[10] & 0xF0) | 0; //code 0 ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ msleep(10); //delay ms ++ ++ if(r848_get_imr(priv,&u1FilterCalValuePre) != RT_Success) ++ return RT_Fail; ++ ++ //read code 13 ++ //R848_I2C.RegAddr = 0x12; // R848:R18[3:0] ++ priv->regs[10] = (priv->regs[10] & 0xF0) | 13; //code 13 ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ msleep(10); //delay ms ++ ++ if(r848_get_imr(priv,&u1FilterCalValue) != RT_Success) ++ return RT_Fail; ++ ++ if(u1FilterCalValuePre > (u1FilterCalValue+8)) //suitable BW found ++ break; ++ } ++ ++ //-------- Try LPF filter code ---------// ++ u1FilterCalValuePre = 0; ++ for(u1FilterCode=0; u1FilterCode<16; u1FilterCode++) ++ { ++ //R848_I2C.RegAddr = 0x12; // R848:R18[3:0] ++ priv->regs[10] = (priv->regs[10] & 0xF0) | u1FilterCode; ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ msleep(10); //delay ms ++ ++ if(r848_get_imr(priv,&u1FilterCalValue) != RT_Success) ++ return RT_Fail; ++ ++ if(u1FilterCode==0) ++ u1FilterCalValuePre = u1FilterCalValue; ++ ++ if((u1FilterCalValue+FilCal_Gap) < u1FilterCalValuePre) ++ { ++ u1FilterCodeResult = u1FilterCode; ++ break; ++ } ++ ++ } ++ ++ if(u1FilterCode==16) ++ u1FilterCodeResult = 15; ++ ++ return u1FilterCodeResult; ++ ++} ++ ++ ++R848_ErrCode R848_DVBS_Setting(struct r848_priv *priv) ++{ ++ int ret; ++ u32 LO_KHz; ++ u8 fine_tune,Coarse_tune; ++ u32 Coarse; ++ ++ //if (priv->standard != R848_DVB_S) ++ { ++ priv->standard = R848_DVB_S; ++ if(r848_init_regs(priv,priv->standard)) ++ return RT_Fail; ++ } ++ ++ LO_KHz = priv->freq; ++ ++ if (r848_set_pll(priv, LO_KHz, priv->standard)) ++ return RT_Fail; ++ ++ //VTH/VTL ++ if ((priv->freq >= 1200000) && (priv->freq <= 1750000)) { ++ priv->regs[23]=(priv->regs[23] & 0x00) | 0x93; //R848:R31[7:0 1.24/0.64 ++ } else { ++ priv->regs[23]=(priv->regs[23] & 0x00) | 0x83; //R848:R31[7:0] 1.14/0.64 ++ } ++ ret = r848_wr(priv, 0x1f, priv->regs[23]); ++ ++ ++ ++ if(priv->freq >= 2000000) ++ { ++ priv->regs[38]=(priv->regs[38] & 0xCF) | 0x20; //R848:R46[4:5] ++ ret |= r848_wr(priv, 0x2e, priv->regs[38]); ++ } ++ ++ ++ if((priv->freq >= 1600000) && (priv->freq <= 1950000)) { ++ priv->regs[35] |= 0x20; //LNA Mode with att //R710 R2[6] R848:R43[5] ++ //priv->regs[36] |= 0x04; //Mixer Buf -3dB //R710 R8[7] R848:R44[2] ++ } else { ++ priv->regs[35] &= 0xDF; //LNA Mode no att ++ //priv->regs[36] &= 0xFB; //Mixer Buf off ++ } ++ ret |= r848_wr(priv, 0x2b, priv->regs[35]); ++ //ret |= r848_wr(priv, 0x2c, priv->regs[36]); //TEST ++ ++ ++ //Output Signal Mode ( O is diff ; 1 is single ) ++ if(priv->output_mode != SINGLEOUT) { ++ priv->regs[35] &=0x7F; ++ } else { ++ priv->regs[35] |=0x80; // R848:R43[7] ++ } ++ ret |= r848_wr(priv, 0x2b, priv->regs[35]); ++ ++ ++ //AGC Type //R13[4] Negative=0 ; Positive=1; ++ if(priv->agc_mode != AGC_POSITIVE) { ++ priv->regs[37] &= 0xF7; ++ } else { ++ priv->regs[37] |= 0x08; // R848:R45[3] ++ } ++ ret |= r848_wr(priv, 0x2d, priv->regs[37]); ++ ++ ++ if (priv->bw > 67400) { ++ fine_tune=1; ++ Coarse = ((priv->bw - 67400) / 1600) + 31; ++ if (((priv->bw - 67400) % 1600) > 0) ++ Coarse += 1; ++ } else if ((priv->bw > 62360) && (priv->bw <= 67400)) { ++ Coarse=31; ++ fine_tune=1; ++ } else if ((priv->bw > 38000) && (priv->bw <= 62360)) { ++ fine_tune=1; ++ Coarse = ((priv->bw - 38000) / 1740) + 16; ++ if (((priv->bw - 38000) % 1740) > 0) ++ Coarse+=1; ++ } else if (priv->bw <= 5000) { ++ Coarse = 0; ++ fine_tune = 0; ++ } else if ((priv->bw > 5000) && (priv->bw <= 8000)) { ++ Coarse = 0; ++ fine_tune = 1; ++ } else if ((priv->bw > 8000) && (priv->bw <= 10000)) { ++ Coarse = 1; ++ fine_tune = 1; ++ } else if ((priv->bw > 10000) && (priv->bw <= 12000)) { ++ Coarse=2; ++ fine_tune=1; ++ } else if((priv->bw>12000) && (priv->bw<=14200)) { ++ Coarse=3; ++ fine_tune=1; ++ } else if((priv->bw>14200) && (priv->bw<=16000)) { ++ Coarse=4; ++ fine_tune=1; ++ } else if((priv->bw>16000) && (priv->bw<=17800)) { ++ Coarse=5; ++ fine_tune=0; ++ } else if((priv->bw>17800) && (priv->bw<=18600)) { ++ Coarse=5; ++ fine_tune=1; ++ } else if((priv->bw>18600) && (priv->bw<=20200)) { ++ Coarse=6; ++ fine_tune=1; ++ } else if((priv->bw>20200) && (priv->bw<=22400)) { ++ Coarse=7; ++ fine_tune=1; ++ } else if((priv->bw>22400) && (priv->bw<=24600)) { ++ Coarse=9; ++ fine_tune=1; ++ } else if((priv->bw>24600) && (priv->bw<=25400)) { ++ Coarse=10; ++ fine_tune=0; ++ } else if((priv->bw>25400) && (priv->bw<=26000)) { ++ Coarse=10; ++ fine_tune=1; ++ } else if((priv->bw>26000) && (priv->bw<=27200)) { ++ Coarse=11; ++ fine_tune=0; ++ } else if((priv->bw>27200) && (priv->bw<=27800)) { ++ Coarse=11; ++ fine_tune=1; ++ } else if((priv->bw>27800) && (priv->bw<=30200)) { ++ Coarse=12; ++ fine_tune=1; ++ } else if((priv->bw>30200) && (priv->bw<=32600)) { ++ Coarse=13; ++ fine_tune=1; ++ } else if((priv->bw>32600) && (priv->bw<=33800)) { ++ Coarse=14; ++ fine_tune=1; ++ } else if((priv->bw>33800) && (priv->bw<=36800)) { ++ Coarse=15; ++ fine_tune=1; ++ } else if((priv->bw>36800) && (priv->bw<=38000)) { ++ Coarse=16; ++ fine_tune=1; ++ } ++ ++ Coarse_tune = (unsigned char) Coarse; ++ ++ priv->regs[39] &= 0x00; //47-8=39 ++ priv->regs[39] = ((priv->regs[39] | ( fine_tune<< 6 ) ) | ( Coarse_tune)); ++ ret |= r848_wr(priv, 0x2f, priv->regs[39]); ++ ++ // Set GPO Low ++ // R848:R23[4:2] ++ priv->regs[15] = (priv->regs[15] & 0xFE); ++ ret |= r848_wr(priv, 0x17, priv->regs[15]); ++ ++ return ret; ++} ++ ++ ++ ++ ++R848_Sys_Info_Type R848_Sys_Sel( struct r848_priv *priv,R848_Standard_Type R848_Standard) ++{ ++ R848_Sys_Info_Type R848_Sys_Info; ++ ++ switch (R848_Standard) ++ { ++ case R848_DVB_T_6M: ++ case R848_DVB_T2_6M: ++ R848_Sys_Info.IF_KHz=4570; //IF ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7450; //CAL IF ++ R848_Sys_Info.HPF_COR=0x05; //R19[3:0]=5 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ ++ ++ ++ case R848_DVB_T_7M: ++ case R848_DVB_T2_7M: ++ R848_Sys_Info.IF_KHz=4570; //IF ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7750; //CAL IF ++ R848_Sys_Info.HPF_COR=0x08; //R19[3:0]=8 (1.45M) ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ ++ case R848_DVB_T_8M: ++ case R848_DVB_T2_8M: ++ R848_Sys_Info.IF_KHz=4570; //IF ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8130; //CAL IF ++ R848_Sys_Info.HPF_COR=0x09; //R19[3:0]=9 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ ++ case R848_DVB_T2_1_7M: ++ R848_Sys_Info.IF_KHz=1900; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7800; //CAL IF ++ R848_Sys_Info.HPF_COR=0x08; //R19[3:0]=8 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_DVB_T2_10M: ++ R848_Sys_Info.IF_KHz=5600; ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=10800; //CAL IF ++ R848_Sys_Info.HPF_COR=0x0C; //R19[3:0]=12 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_DVB_C_8M: ++ R848_Sys_Info.IF_KHz=5070; ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=9000; //CAL IF //9150 ++ R848_Sys_Info.HPF_COR=0x0A; //R19[3:0]=10 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x02; //R38[1:0]=10, lna=max-1 & Buf 4 ++ break; ++ ++ case R848_DVB_C_6M: ++ R848_Sys_Info.IF_KHz=5070; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8025; //CAL IF ++ R848_Sys_Info.HPF_COR=0x03; //R19[3:0]=3 //3 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_J83B: ++ R848_Sys_Info.IF_KHz=5070; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8025; //CAL IF ++ R848_Sys_Info.HPF_COR=0x03; //R19[3:0]=3 //3 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_ISDB_T: ++ R848_Sys_Info.IF_KHz=4063; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7000; //CAL IF //7200 ++ R848_Sys_Info.HPF_COR=0x08; //R19[3:0]=8 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ case R848_ISDB_T_4570: ++ R848_Sys_Info.IF_KHz=4570; //IF ++ R848_Sys_Info.BW=0x40; //BW=7M ++ R848_Sys_Info.FILT_CAL_IF=7250; //CAL IF ++ R848_Sys_Info.HPF_COR=0x05; //R19[3:0]=5 (2.0M) ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8, hpf+3 ++ break; ++ ++ case R848_DTMB_4570: ++ R848_Sys_Info.IF_KHz=4570; ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8330; //CAL IF //8130 ++ R848_Sys_Info.HPF_COR=0x0B; //R19[3:0]=11 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_DTMB_6000: ++ R848_Sys_Info.IF_KHz=6000; ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=9550; //CAL IF ++ R848_Sys_Info.HPF_COR=0x03; //R19[3:0]=3 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x02; //R38[1:0]=10, lna=max-1 & Buf 4 ++ break; ++ ++ case R848_DTMB_6M_BW_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x40; //BW=7M ++ R848_Sys_Info.FILT_CAL_IF=7700; //CAL IF ++ R848_Sys_Info.HPF_COR=0x04; //R19[3:0]=4 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 & Buf 4, hpf+1 ++ break; ++ ++ case R848_DTMB_6M_BW_IF_4500: ++ R848_Sys_Info.IF_KHz=4500; ++ R848_Sys_Info.BW=0x40; //BW=7M ++ R848_Sys_Info.FILT_CAL_IF=7000; //CAL IF ++ R848_Sys_Info.HPF_COR=0x05; //R19[3:0]=5 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x02; //R38[1:0]=10, lna=max-1 & Buf 4, hpf+3 ++ break; ++ ++ case R848_ATSC: ++ R848_Sys_Info.IF_KHz=5070; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7900; //CAL IF 20130621 Ryan Modify ++ R848_Sys_Info.HPF_COR=0x04; //R19[3:0]=4 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_DVB_T_6M_IF_5M: ++ case R848_DVB_T2_6M_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; //IF ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7800; //CAL IF ++ R848_Sys_Info.HPF_COR=0x04; //R19[3:0]=4 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ ++ case R848_DVB_T_7M_IF_5M: ++ case R848_DVB_T2_7M_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; //IF ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8300; //CAL IF ++ R848_Sys_Info.HPF_COR=0x07; //R19[3:0]=7 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ ++ case R848_DVB_T_8M_IF_5M: ++ case R848_DVB_T2_8M_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; //IF ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8500; //CAL IF ++ R848_Sys_Info.HPF_COR=0x08; //R19[3:0]=8 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ ++ case R848_DVB_T2_1_7M_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x60; //BW=6M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=5900; //CAL IF ++ R848_Sys_Info.HPF_COR=0x01; //R19[3:0]=1 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_DVB_C_8M_IF_5M: ++// case R848_DVB_C_CHINA_IF_5M: //RF>115MHz ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=9000; //CAL IF ++ R848_Sys_Info.HPF_COR=0x0A; //R19[3:0]=10 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x02; //R38[1:0]=10, lna=max-1 & Buf 4 ++ break; ++ ++ case R848_DVB_C_6M_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8100; //CAL IF ++ R848_Sys_Info.HPF_COR=0x04; //R19[3:0]=4 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_J83B_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8025; //CAL IF ++ R848_Sys_Info.HPF_COR=0x03; //R19[3:0]=3 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_ISDB_T_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7940; //CAL IF ++ R848_Sys_Info.HPF_COR=0x04; //R19[3:0]=4 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x03; //R38[1:0]=11, buf 8 ++ break; ++ ++ case R848_DTMB_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8650; //CAL IF ++ R848_Sys_Info.HPF_COR=0x09; //R19[3:0]=9 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x02; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_ATSC_IF_5M: ++ R848_Sys_Info.IF_KHz=5000; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7900; //CAL IF ++ R848_Sys_Info.HPF_COR=0x04; //R19[3:0]=4 ++ R848_Sys_Info.FILT_EXT_ENA=0x00; //R19[4]=0, ext disable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ case R848_FM: ++ R848_Sys_Info.IF_KHz=2400; ++ R848_Sys_Info.BW=0x40; //BW=7M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=7200; //CAL IF ++ R848_Sys_Info.HPF_COR=0x02; //R19[3:0]=2 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ default: //R848_DVB_T_8M ++ R848_Sys_Info.IF_KHz=4570; //IF ++ R848_Sys_Info.BW=0x00; //BW=8M R848:R19[6:5] ++ R848_Sys_Info.FILT_CAL_IF=8330; //CAL IF ++ R848_Sys_Info.HPF_COR=0x0B; //R19[3:0]=11 ++ R848_Sys_Info.FILT_EXT_ENA=0x10; //R19[4]=1, ext enable ++ R848_Sys_Info.FILT_EXT_WIDEST=0x00;//R38[2]=0, ext normal ++ R848_Sys_Info.FILT_EXT_POINT=0x00; //R38[1:0]=0, lna=max-1 ++ break; ++ ++ } ++ ++ //R848_Sys_Info.INDUC_BIAS = 0x01; //normal ++ //R848_Sys_Info.SWCAP_CLK = 0x01; //32k ++ R848_Sys_Info.SWCAP_CLK = 0x02; //8k //AGC 500Hz map to 8k R26[1:0] ++ R848_Sys_Info.NA_PWR_DET = 0x00; //on R38[7] ++ ++ R848_Sys_Info.TF_CUR = 0x40; //low R11[6]=1 ++ R848_Sys_Info.SWBUF_CUR = 0x04; //low R12[2]=1 ++ ++ ++ ++/* switch(R848_Standard) ++ { ++ case R848_DVB_T2_6M: ++ case R848_DVB_T2_7M: ++ case R848_DVB_T2_8M: ++ case R848_DVB_T2_1_7M: ++ case R848_DVB_T2_10M: ++ case R848_DVB_T2_6M_IF_5M: ++ case R848_DVB_T2_7M_IF_5M: ++ case R848_DVB_T2_8M_IF_5M: ++ case R848_DVB_T2_1_7M_IF_5M: ++ R848_Sys_Info.AGC_CLK = 0x1C; //250Hz R26[4:2] ++ break; ++ default: ++ R848_Sys_Info.AGC_CLK = 0x00; //1k R26[4:2] ++ break; ++ }*/ ++ ++ //Filter 3dB ++ switch(R848_Standard) ++ { ++ case R848_DVB_C_8M_IF_5M: ++ R848_Sys_Info.FILT_3DB = 0x08; // ON R38[3] ++ break; ++ default: ++ R848_Sys_Info.FILT_3DB = 0x00; // OFF R38[3] ++ break; ++ } ++ ++ R848_Sys_Info.FILT_COMP = 0x20; ++ R848_Sys_Info.FILT_CUR = 0x00; //highest R18[6:5] ++ ++ ++ //BW 1.7M ++ if((R848_Standard==R848_DVB_T2_1_7M) || (R848_Standard==R848_FM)) ++ R848_Sys_Info.V17M = 0x80; //enable, R19[7] ++ else ++ R848_Sys_Info.V17M = 0x00; //disable, (include DVBT2 1.7M IF=5MHz) R19[7] ++ ++ //TF Type select ++ switch(R848_Standard) ++ { ++ case R848_DTMB_4570: ++ case R848_DTMB_6000: ++ case R848_DTMB_6M_BW_IF_5M: ++ case R848_DTMB_6M_BW_IF_4500: ++ case R848_DTMB_IF_5M: ++ if(priv->cfg->R848_DetectTfType == R848_UL_USING_BEAD ) ++ { ++ priv->cfg->R848_SetTfType = R848_TF_82N_BEAD; ++ } ++ else ++ { ++ priv->cfg->R848_SetTfType = R848_TF_82N_270N; ++ } ++ break; ++ ++ default: ++ if(priv->cfg->R848_DetectTfType == R848_UL_USING_BEAD) ++ { ++ priv->cfg->R848_SetTfType = R848_TF_82N_BEAD; ++ } ++ else ++ { ++ priv->cfg->R848_SetTfType = R848_TF_82N_270N; ++ } ++ break; ++ } ++ ++ return R848_Sys_Info; ++} ++ ++ ++ ++R848_SysFreq_Info_Type R848_SysFreq_Sel(struct r848_priv *priv, R848_Standard_Type R848_Standard, u32 RF_freq) ++{ ++ R848_SysFreq_Info_Type R848_SysFreq_Info; ++ ++ switch (R848_Standard) { ++ case R848_DVB_T_6M: ++ case R848_DVB_T_7M: ++ case R848_DVB_T_8M: ++ case R848_DVB_T_6M_IF_5M: ++ case R848_DVB_T_7M_IF_5M: ++ case R848_DVB_T_8M_IF_5M: ++ case R848_DVB_T2_6M: ++ case R848_DVB_T2_7M: ++ case R848_DVB_T2_8M: ++ case R848_DVB_T2_1_7M: ++ case R848_DVB_T2_10M: ++ case R848_DVB_T2_6M_IF_5M: ++ case R848_DVB_T2_7M_IF_5M: ++ case R848_DVB_T2_8M_IF_5M: ++ case R848_DVB_T2_1_7M_IF_5M: ++ if((RF_freq>=300000)&&(RF_freq<=472000)) { ++ R848_SysFreq_Info.LNA_VTH_L=0xA4; // LNA VTH/L=1.34/0.74 (R31=0xA4) ++ R848_SysFreq_Info.MIXER_TOP=0x05; // MIXER TOP=10 (R36[3:0]=4'b0101) ++ R848_SysFreq_Info.MIXER_VTH_L=0x95; // MIXER VTH/L=1.24/0.84 (R32=0x95) ++ R848_SysFreq_Info.NRB_TOP=0xC0; // Nrb TOP=3 (R36[7:4]=4'b1100) ++ } else if((RF_freq>=184000) && (RF_freq<=299000)) { ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ R848_SysFreq_Info.MIXER_TOP=0x04; // MIXER TOP=11 (R36[3:0]=4'b0101) ++ R848_SysFreq_Info.MIXER_VTH_L=0xA6; // MIXER VTH/L=1.34/0.94 (R32=0xA6) ++ R848_SysFreq_Info.NRB_TOP=0x70; // Nrb TOP=8 (R36[7:4]=4'b1100) ++ } else { ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ R848_SysFreq_Info.MIXER_TOP=0x05; // MIXER TOP=10 (R36[3:0]=4'b0101) ++ R848_SysFreq_Info.MIXER_VTH_L=0x95; // MIXER VTH/L=1.24/0.84 (R32=0x95) ++ R848_SysFreq_Info.NRB_TOP=0xC0; // Nrb TOP=3 (R36[7:4]=4'b1100) ++ } ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.RF_TOP=0x40; // RF TOP=5 (R34[7:5]=3'b010) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ break; ++ ++ case R848_DVB_C_8M: ++ case R848_DVB_C_6M: ++ case R848_J83B: ++ case R848_DVB_C_8M_IF_5M: ++ case R848_DVB_C_6M_IF_5M: ++ case R848_J83B_IF_5M: ++ if(RF_freq<165000) { ++ R848_SysFreq_Info.LNA_TOP=0x02; // LNA TOP=5 (R35[2:0]=3'b010) ++ R848_SysFreq_Info.LNA_VTH_L=0x94; // LNA VTH/L=1.24/0.74 (R31=0x94) ++ R848_SysFreq_Info.RF_TOP=0x80; // RF TOP=3 (R34[7:5]=3'b100) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) //R848:R36[7:4] ++ } else if((RF_freq>=165000) && (RF_freq<=299000)) { ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.LNA_VTH_L=0x94; // LNA VTH/L=1.24/0.74 (R31=0x94) ++ R848_SysFreq_Info.RF_TOP=0x80; // RF TOP=3 (R34[7:5]=3'b100) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ } else if((RF_freq>299000) && (RF_freq<=345000)) { ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.LNA_VTH_L=0xA4; // LNA VTH/L=1.34/0.74 (R31=0xA4) ++ R848_SysFreq_Info.RF_TOP=0x80; // RF TOP=3 (R34[7:5]=3'b100) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ } else if((RF_freq>345000) && (RF_freq<=472000)) { ++ R848_SysFreq_Info.LNA_TOP=0x04; // LNA TOP=3 (R35[2:0]=3'b100) ++ R848_SysFreq_Info.LNA_VTH_L=0x93; // LNA VTH/L=1.24/0.64 (R31=0x93) ++ R848_SysFreq_Info.RF_TOP=0xA0; // RF TOP=2 (R34[7:5]=3'b101) ++ R848_SysFreq_Info.NRB_TOP=0x20; // Nrb TOP=13 (R36[7:4]=4'b0010) ++ } else { ++ R848_SysFreq_Info.LNA_TOP=0x04; // LNA TOP=3 (R35[2:0]=3'b100) ++ R848_SysFreq_Info.LNA_VTH_L=0x83; // LNA VTH/L=1.14/0.64 (R31=0x83) ++ R848_SysFreq_Info.RF_TOP=0xA0; // RF TOP=2 (R34[7:5]=3'b101) ++ R848_SysFreq_Info.NRB_TOP=0x20; // Nrb TOP=13 (R36[7:4]=4'b0010) ++ } ++ R848_SysFreq_Info.MIXER_TOP=0x05; // MIXER TOP=10 (R36[3:0]=4'b0100) ++ R848_SysFreq_Info.MIXER_VTH_L=0x95; // MIXER VTH/L=1.24/0.84 (R32=0x95) ++ break; ++ ++ case R848_ISDB_T: ++ case R848_ISDB_T_4570: ++ case R848_ISDB_T_IF_5M: ++ if((RF_freq>=300000)&&(RF_freq<=472000)) { ++ R848_SysFreq_Info.LNA_VTH_L=0xA4; // LNA VTH/L=1.34/0.74 (R31=0xA4) ++ } else { ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ } ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.MIXER_TOP=0x05; // MIXER TOP=10 (R36[3:0]=4'b0101) ++ R848_SysFreq_Info.MIXER_VTH_L=0x95; // MIXER VTH/L=1.24/0.84 (R32=0x95) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ //R848_SysFreq_Info.NRB_TOP=0x20; // Nrb TOP=13 (R36[7:4]=4'b0010) ++ R848_SysFreq_Info.NRB_TOP=0xB0; // Nrb TOP=4 (R36[7:4]=4'b1011) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ break; ++ case R848_DTMB_4570: ++ case R848_DTMB_6000: ++ case R848_DTMB_6M_BW_IF_5M: ++ case R848_DTMB_6M_BW_IF_4500: ++ case R848_DTMB_IF_5M: ++ if((RF_freq>=300000)&&(RF_freq<=472000)) { ++ R848_SysFreq_Info.LNA_VTH_L=0xA4; // LNA VTH/L=1.34/0.74 (R31=0xA4) ++ } else { ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ } ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.MIXER_TOP=0x05; // MIXER TOP=10 (R36[3:0]=4'b0100) ++ R848_SysFreq_Info.MIXER_VTH_L=0x95; // MIXER VTH/L=1.24/0.84 (R32=0x95) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0xA0; // Nrb TOP=5 (R36[7:4]=4'b1010) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ break; ++ ++ case R848_ATSC: ++ case R848_ATSC_IF_5M: ++ if(priv->cfg->R848_DetectTfType==R848_UL_USING_BEAD) { ++ if (RF_freq < 88000) { ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ R848_SysFreq_Info.RF_TOP=0xC0; // RF TOP=1 (R34[7:5]=3'b110) ++ R848_SysFreq_Info.NRB_TOP=0x30; // Nrb TOP=12 (R36[7:4]=4'b0011) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=88000) && (RF_freq<104000)) { ++ R848_SysFreq_Info.LNA_TOP=0x02; // LNA TOP=5 (R35[2:0]=3'b010) ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ R848_SysFreq_Info.RF_TOP=0xA0; // RF TOP=2 (R34[7:5]=3'b101) ++ R848_SysFreq_Info.NRB_TOP=0x30; // Nrb TOP=12 (R36[7:4]=4'b0011) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=104000) && (RF_freq<156000)) { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x30; // Nrb TOP=12 (R36[7:4]=4'b0011) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=156000) && (RF_freq<464000)) { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=464000) && (RF_freq<500000)) { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0xB6; // LNA VTH/L=1.44/0.94 (R31=0xB6) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0x94; // LNA VTH/L=1.24/0.74 (R31=0x94) ++ R848_SysFreq_Info.RF_TOP=0x40; // RF TOP=5 (R34[7:5]=3'b010) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } ++ } else { //270n ++ if(RF_freq<88000) { ++ R848_SysFreq_Info.LNA_TOP=0x02; // LNA TOP=5 (R35[2:0]=3'b010) ++ R848_SysFreq_Info.LNA_VTH_L=0x94; // LNA VTH/L=1.24/0.74 (R31=0x94) ++ R848_SysFreq_Info.RF_TOP=0x80; // RF TOP=3 (R34[7:5]=3'b100) ++ R848_SysFreq_Info.NRB_TOP=0xC0; // Nrb TOP=3 (R36[7:4]=4'b1100) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=88000) && (RF_freq<104000)) { ++ R848_SysFreq_Info.LNA_TOP=0x02; // LNA TOP=5 (R35[2:0]=3'b010) ++ R848_SysFreq_Info.LNA_VTH_L=0x94; // LNA VTH/L=1.24/0.74 (R31=0x94) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=104000) && (RF_freq<248000)) { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0x94; // LNA VTH/L=1.24/0.74 (R31=0x94) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=248000) && (RF_freq<464000)) { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else if((RF_freq>=464000) && (RF_freq<500000)) { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0xB6; // LNA VTH/L=1.44/0.94 (R31=0xB6) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } else { ++ R848_SysFreq_Info.LNA_TOP=0x01; // LNA TOP=6 (R35[2:0]=3'b001) ++ R848_SysFreq_Info.LNA_VTH_L=0x94; // LNA VTH/L=1.24/0.74 (R31=0x94) ++ R848_SysFreq_Info.RF_TOP=0x40; // RF TOP=5 (R34[7:5]=3'b010) ++ R848_SysFreq_Info.NRB_TOP=0x90; // Nrb TOP=6 (R36[7:4]=4'b1001) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ } ++ } ++ R848_SysFreq_Info.MIXER_TOP=0x04; // MIXER TOP=11 (R36[3:0]=4'b0100) ++ R848_SysFreq_Info.MIXER_VTH_L=0xB7; // MIXER VTH/L=1.44/1.04 (R32=0xB7) ++ //R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ break; ++ case R848_FM: ++ if ((RF_freq>=300000) && (RF_freq<=472000)) { ++ R848_SysFreq_Info.LNA_VTH_L=0xA4; // LNA VTH/L=1.34/0.74 (R31=0xA4) ++ } else { ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ } ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.MIXER_TOP=0x05; // MIXER TOP=10 (R36[3:0]=4'b0100) ++ R848_SysFreq_Info.MIXER_VTH_L=0x95; // MIXER VTH/L=1.24/0.84 (R32=0x95) ++ R848_SysFreq_Info.RF_TOP=0x60; // RF TOP=4 (R34[7:5]=3'b011) ++ R848_SysFreq_Info.NRB_TOP=0x20; // Nrb TOP=13 (R36[7:4]=4'b0010) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ break; ++ default: //DVB-T 8M ++ if ((RF_freq >= 300000) && (RF_freq <= 472000)) { ++ R848_SysFreq_Info.LNA_VTH_L=0xA4; // LNA VTH/L=1.34/0.74 (R31=0xA4) ++ } else { ++ R848_SysFreq_Info.LNA_VTH_L=0xA5; // LNA VTH/L=1.34/0.84 (R31=0xA5) ++ } ++ R848_SysFreq_Info.LNA_TOP=0x03; // LNA TOP=4 (R35[2:0]=3'b011) ++ R848_SysFreq_Info.MIXER_TOP=0x05; // MIXER TOP=10 (R36[3:0]=4'b0100) ++ R848_SysFreq_Info.MIXER_VTH_L=0x95; // MIXER VTH/L=1.24/0.84 (R32=0x95) ++ R848_SysFreq_Info.RF_TOP=0x40; // RF TOP=5 (R34[7:5]=3'b010) ++ R848_SysFreq_Info.NRB_TOP=0x20; // Nrb TOP=13 (R36[7:4]=4'b0010) ++ R848_SysFreq_Info.NRB_BW=0xC0; // Nrb BW=lowest (R35[7:6]=2'b11) ++ break; ++ } ++ ++ R848_SysFreq_Info.RF_FAST_DISCHARGE = 0x00; //0 R848:R46[3:1]=3'b000 ++ R848_SysFreq_Info.RF_SLOW_DISCHARGE = 0x80; //4 R848:R22[7:5]=2'b100 ++ R848_SysFreq_Info.RFPD_PLUSE_ENA = 0x10; //1 R848:R38[4]=1 ++ ++ R848_SysFreq_Info.LNA_FAST_DISCHARGE = 0x0A; //10 R848:R43[4:0]=5'b01010 ++ R848_SysFreq_Info.LNA_SLOW_DISCHARGE = 0x00; //0 R848:R22[4:2]=3'b000 ++ R848_SysFreq_Info.LNAPD_PLUSE_ENA = 0x00 ; //0 R848:R17[7]=0 ++ ++ //AGC Clk Rate ++ R848_SysFreq_Info.AGC_CLK = 0x00; //1k R26[4:2] //default ++ ++ //TF LPF setting ++ switch (R848_Standard) { ++ case R848_DTMB_4570: ++ case R848_DTMB_6000: ++ case R848_DTMB_6M_BW_IF_5M: ++ case R848_DTMB_6M_BW_IF_4500: ++ case R848_DTMB_IF_5M: ++ R848_SysFreq_Info.BYP_LPF = 0x00; //bypass R12[6] ++ break; ++ case R848_DVB_T_6M: ++ case R848_DVB_T_7M: ++ case R848_DVB_T_8M: ++ case R848_DVB_T_6M_IF_5M: ++ case R848_DVB_T_7M_IF_5M: ++ case R848_DVB_T_8M_IF_5M: ++ case R848_DVB_T2_6M: ++ case R848_DVB_T2_7M: ++ case R848_DVB_T2_8M: ++ case R848_DVB_T2_1_7M: ++ case R848_DVB_T2_10M: ++ case R848_DVB_T2_6M_IF_5M: ++ case R848_DVB_T2_7M_IF_5M: ++ case R848_DVB_T2_8M_IF_5M: ++ case R848_DVB_T2_1_7M_IF_5M: ++ if (RF_freq >= 662000 && RF_freq <= 670000) { ++ R848_SysFreq_Info.RF_SLOW_DISCHARGE = 0x20; //1 R848:R22[7:5]=2'b001 ++ R848_SysFreq_Info.AGC_CLK = 0x18; //60Hz R26[4:2] ++ } else { ++ R848_SysFreq_Info.RF_SLOW_DISCHARGE = 0x80; //4 R848:R22[7:5]=2'b100 ++ R848_SysFreq_Info.AGC_CLK = 0x00; //1KHz R26[4:2] ++ switch(R848_Standard) { ++ case R848_DVB_T2_6M: ++ case R848_DVB_T2_7M: ++ case R848_DVB_T2_8M: ++ case R848_DVB_T2_1_7M: ++ case R848_DVB_T2_10M: ++ case R848_DVB_T2_6M_IF_5M: ++ case R848_DVB_T2_7M_IF_5M: ++ case R848_DVB_T2_8M_IF_5M: ++ case R848_DVB_T2_1_7M_IF_5M: ++ R848_SysFreq_Info.AGC_CLK = 0x1C; //250Hz R26[4:2] ++ break; ++ } ++ } ++ break; ++ default: //other standard ++ if(RF_freq<=236000) ++ R848_SysFreq_Info.BYP_LPF = 0x40; //low pass R12[6] ++ else ++ R848_SysFreq_Info.BYP_LPF = 0x00; //bypass R12[6] ++ break; ++ } ++ return R848_SysFreq_Info; ++} ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++#if 0 ++R848_ErrCode R848_RfGainMode( struct r848_priv *priv,R848_RF_Gain_TYPE R848_RfGainType) ++{ ++ int ret; ++ u8 buf[5]; ++ ++ u8 MixerGain = 0; ++ u8 RfGain = 0; ++ u8 LnaGain = 0; ++ ++ if(R848_RfGainType==RF_MANUAL) { ++ //LNA auto off ++ priv->regs[5] = priv->regs[5] | 0x80; // 848:13[7:0] ++ ret = r848_wr(priv, 0x0d, priv->regs[5]); ++ ++ //Mixer buffer off ++ priv->regs[26] = priv->regs[26] | 0x10; // 848:34[7:0] ++ ret |= r848_wr(priv, 0x22, priv->regs[26]); ++ ++ //Mixer auto off ++ priv->regs[7] = priv->regs[7] & 0xEF; //848:15[6:0] ++ ret |= r848_wr(priv, 0x0f, priv->regs[7]); ++ ++ ret = r848_rd(priv, buf, 5); ++ if (ret) ++ return ret; ++ ++ //MixerGain = (((buf[1] & 0x40) >> 6)<<3)+((buf[3] & 0xE0)>>5); //? ++ MixerGain = (buf[3] & 0x0F); //mixer // 848:3[4:0] ++ RfGain = ((buf[3] & 0xF0) >> 4); //rf // 848:3[4:0] ++ LnaGain = buf[4] & 0x1F; //lna // 848:4[4:0] ++ ++ //set LNA gain ++ priv->regs[5] = (priv->regs[5] & 0xE0) | LnaGain; // 848:13[7:0] ++ ret |= r848_wr(priv, 0x0d, priv->regs[5]); ++ ++ //set Mixer Buffer gain ++ priv->regs[26] = (priv->regs[26] & 0xF0) | RfGain; //848:34[7:0] ++ ret |= r848_wr(priv, 0x22, priv->regs[26]); ++ ++ //set Mixer gain ++ priv->regs[7] = (priv->regs[7] & 0xF0) | MixerGain; // 848:15[6:0] ++ ret |= r848_wr(priv, 0x0f, priv->regs[7]); ++ } else { ++ //LNA auto on ++ priv->regs[5] = priv->regs[5] & 0x7F; // 848:13[7:0] ++ ret = r848_wr(priv, 0x0d, priv->regs[5]); ++ ++ //Mixer buffer on ++ priv->regs[26] = priv->regs[26] & 0xEF; // 848:34[7:0] ++ ret |= r848_wr(priv, 0x22, priv->regs[26]); ++ ++ //Mixer auto on ++ priv->regs[7] = priv->regs[7] | 0x10; // 848:15[6:0] ++ ret |= r848_wr(priv, 0x0f, priv->regs[7]); ++ } ++ ++ return ret; ++} ++#endif ++ ++ ++static int R848_TF_Check(struct r848_priv *priv) ++{ ++ u32 RingVCO, RingFreq; ++ u8 divnum_ring; ++ u8 VGA_Count; ++ u8 VGA_Read; ++ int ret; ++ ++ if (R848_Xtal == 16000) { ++ divnum_ring = 11; ++ } else { //24M ++ divnum_ring = 2; ++ } ++ ++ RingVCO = (16 + divnum_ring) * 8 * R848_Xtal; ++ RingFreq = RingVCO / 48; ++ ++ if (R848_Cal_Prepare(priv, R848_TF_LNA_CAL)) ++ return RT_Fail; ++ ++ priv->regs[31] = (priv->regs[31] & 0x03) | 0x80 | (divnum_ring<<2); //pre div=6 & div_num ++ ret = r848_wr(priv, 0x27, priv->regs[31]); ++ ++ // Ring PLL PW on ++ priv->regs[18] = (priv->regs[18] & 0xEF); ++ ret |= r848_wr(priv, 0x12, priv->regs[18]); ++ ++ // NAT Det Sour : Mixer buf out ++ priv->regs[37] = (priv->regs[37] & 0x7F); ++ ret |= r848_wr(priv, 0x25, priv->regs[37]); ++ ++ // R848 R33[7:0] ++ priv->regs[25] = (priv->regs[25] & 0x00) | 0x8B; //out div=8, RF poly=low band, power=min_lp ++ if(RingVCO>=3200000) ++ priv->regs[25] = (priv->regs[25] & 0xDF); //vco_band=high, R25[5]=0 ++ else ++ priv->regs[25] = (priv->regs[25] | 0x20); //vco_band=low, R25[5]=1 ++ ret |= r848_wr(priv, 0x21, priv->regs[25]); ++ if (ret) ++ return ret; ++ ++ // Must do before PLL() ++ if (r848_set_mux(priv, RingFreq + 5000, RingFreq, R848_STD_SIZE)) //FilCal MUX (LO_Freq, RF_Freq) ++ return RT_Fail; ++ ++ // Set PLL ++ if (r848_set_pll(priv, (RingFreq + 5000), R848_STD_SIZE)) //FilCal PLL ++ return RT_Fail; ++ ++ // Set LNA TF=(1,15),for VGA training // R848 R8[6:0] ++ priv->regs[0] = (priv->regs[0] & 0x80) | 0x1F; ++ ret = r848_wr(priv, 0x08, priv->regs[0]); ++ ++ // Qctrl=off // R848 R14[5] ++ priv->regs[6] = (priv->regs[6] & 0xDF); ++ ret |= r848_wr(priv, 0x0e, priv->regs[6]); ++ ++ // FilterComp OFF // R848 R14[2] ++ priv->regs[6] = (priv->regs[6] & 0xFB); ++ ret |= r848_wr(priv, 0x0e, priv->regs[6]); ++ ++ // Byp-LPF: Bypass R848 R12[6] 12-8=4 12(0x0C) is addr ; [4] is data ++ priv->regs[4] = priv->regs[4] & 0xBF; ++ ret |= r848_wr(priv, 0x0c, priv->regs[4]); ++ ++ //Adc=on; Vga code mode, Gain = -12dB ++ //R848 R20[3:0] set 0 ++ //R848 R9[1] set 1 ++ //R848 R11[3] set 0 ++ //R848 R18[7] set 0 ++ //R848 R15[7] set 0 ++ ++ // VGA Gain = -12dB ++ priv->regs[12] = (priv->regs[12] & 0xF0); ++ ret |= r848_wr(priv, 0x14, priv->regs[12]); ++ ++ // Vga code mode ++ priv->regs[1] = (priv->regs[1] | 0x02); ++ ret |= r848_wr(priv, 0x09, priv->regs[1]); ++ ++ // VGA 6dB ++ priv->regs[3] = (priv->regs[3] & 0xF7); ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); ++ ++ // VGA PW ON ++ priv->regs[10] = (priv->regs[10] & 0x7F); ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ // Adc on ++ priv->regs[7] = (priv->regs[7] & 0x7F); ++ ret |= r848_wr(priv, 0x0f, priv->regs[7]); ++ if (ret) ++ return ret; ++ ++ ++ // increase VGA power to let ADC read value significant ++ for (VGA_Count = 0; VGA_Count < 16; VGA_Count++) { ++ ret = r848_wr(priv, 0x14, (priv->regs[12] & 0xf0) + VGA_Count); ++ if (ret) ++ return ret; ++ msleep(10); ++ ++ if (r848_get_imr(priv,&VGA_Read)) ++ return RT_Fail; ++ ++ if (VGA_Read > 40) ++ break; ++ } ++ ++ // Set LNA TF=(0,0) ++ priv->regs[0] = (priv->regs[0] & 0x80); ++ ret = r848_wr(priv, 0x08, priv->regs[0]); ++ if (ret) ++ return ret; ++ ++ msleep(10); ++ ++ if (r848_get_imr(priv, &VGA_Read)) ++ return RT_Fail; ++ ++ if (VGA_Read > 36) ++ priv->cfg->R848_DetectTfType = R848_UL_USING_BEAD; ++ else ++ priv->cfg->R848_DetectTfType = R848_UL_USING_270NH; ++ ++ return 0; ++} ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++static int r848_set_standard(struct r848_priv *priv, u8 standard) ++{ ++ struct filter_cal *fc = &priv->fc[standard]; ++ int ret; ++ // Filter Calibration ++ u8 u1FilCalGap = 8; ++ ++ ++ if (standard != priv->standard) { ++ ret = r848_init_regs(priv, standard); ++ if (ret) ++ return ret; ++ } ++ priv->Sys_Info1 = R848_Sys_Sel(priv, standard); ++ ++ // Filter Calibration ++ if (!fc->flag) { ++ fc->code = R848_Filt_Cal_ADC(priv, priv->Sys_Info1.FILT_CAL_IF, priv->Sys_Info1.BW, u1FilCalGap); ++ fc->bw = 0;// R848_Bandwidth; ++ fc->flag = 1; ++ //Reset register and Array ++ ret = r848_init_regs(priv, standard); ++ if (ret) ++ return ret; ++ } ++ ++ // Set Filter Auto Ext ++ // R19[4] ++ priv->regs[11] = (priv->regs[11] & 0xEF) | priv->Sys_Info1.FILT_EXT_ENA; ++ ret = r848_wr(priv, 0x13, priv->regs[11]); ++ ++ if (priv->Sys_Info1.FILT_EXT_ENA == 0x10) { //(%) ++ if (fc->code< 2) ++ fc->code = 2; ++ ++ if ((priv->Sys_Info1.FILT_EXT_POINT & 0x02) == 0x02) { //HPF+3 ++ if(priv->Sys_Info1.HPF_COR > 12) ++ priv->Sys_Info1.HPF_COR = 12; ++ } else { //HPF+1 ++ if(priv->Sys_Info1.HPF_COR > 14) ++ priv->Sys_Info1.HPF_COR = 15; ++ } ++ } ++ ++ // Set LPF fine code ++ // R848:R18[3:0] ++ priv->regs[10] = (priv->regs[10] & 0xF0) | fc->code; ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ // Set LPF coarse BW ++ // R848:R19[6:5] ++ priv->regs[11] = (priv->regs[11] & 0x9F) | fc->bw; ++ //ret |= r848_wr(priv, 0x13, priv->regs[11]); ++ ++ // Set HPF corner & 1.7M mode ++ // R848:R19[7 & 3:0] ++ priv->regs[11] = (priv->regs[11] & 0x70) | priv->Sys_Info1.HPF_COR | priv->Sys_Info1.V17M; ++ ret |= r848_wr(priv, 0x13, priv->regs[11]); ++ ++ // Set TF current ++ // R848:R11[6] ++ priv->regs[3] = (priv->regs[3] & 0xBF) | priv->Sys_Info1.TF_CUR; ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); ++ ++ // Set Filter current ++ // R848:R18[6:5] ++ priv->regs[10] = (priv->regs[10] & 0x9F) | priv->Sys_Info1.FILT_CUR; ++ //R848_Array[10] = (R848_Array[10] & 0x9F) | 0x60; //lowest ++ ret |= r848_wr(priv, 0x12, priv->regs[10]); ++ ++ // Set Switch Buffer current ++ // R848:R12[2] ++ priv->regs[4] = (priv->regs[4] & 0xFB) | priv->Sys_Info1.SWBUF_CUR; ++ ret |= r848_wr(priv, 0x0c, priv->regs[4]); ++ ++ // Set Filter Comp ++ // R848:R38[6:5] ++ priv->regs[30] = (priv->regs[30] & 0x9F) | priv->Sys_Info1.FILT_COMP; ++ //ret |= r848_wr(priv, 0x26, priv->regs[30]); ++ // Set Filter 3dB ++ // R848:R38[7] ++ priv->regs[30] = (priv->regs[30] & 0xF7) | priv->Sys_Info1.FILT_3DB; ++ // Set Filter Ext Condition (%) ++ // R848:R38[2:0] ++ priv->regs[30] = (priv->regs[30] & 0xF8) | 0x04 | priv->Sys_Info1.FILT_EXT_POINT; //ext both HPF/LPF ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); ++/* ++ // Set Inductor Bias ++ R848_I2C.RegAddr = 0x04; ++ R848_Array[4] = (R848_Array[4] & 0xFE) | Sys_Info1.INDUC_BIAS; ++ R848_I2C.Data = R848_Array[4]; ++ if(I2C_Write(&R848_I2C) != RT_Success) ++ return RT_Fail; ++*/ ++ // Set sw cap clk ++ // R848:R26[1:0] ++ priv->regs[18] = (priv->regs[18] & 0xFC) | priv->Sys_Info1.SWCAP_CLK; ++ ret |= r848_wr(priv, 0x1a, priv->regs[18]); ++ ++ // Set NA det power ++ // 848:R38[7] ++ priv->regs[30] = (priv->regs[30] & 0x7F) | priv->Sys_Info1.NA_PWR_DET; ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); ++ ++/* ++ // Set AGC clk ++ R848_I2C.RegAddr = 0x1A; // R848:R26[4:2] ++ R848_Array[18] = (R848_Array[18] & 0xE3) | Sys_Info1.AGC_CLK; ++ R848_I2C.Data = R848_Array[18]; ++ if(I2C_Write(&R848_I2C) != RT_Success) ++ return RT_Fail; ++*/ ++ ++ // Set GPO High ++ // R848:R23[4:2] ++ priv->regs[15] = (priv->regs[15] & 0xFE) | 0x01; ++ ret |= r848_wr(priv, 0x17, priv->regs[15]); ++ ++ priv->standard = standard; ++ ++ return ret; ++} ++ ++ ++ ++/* freq in kHz */ ++static int r848_set_frequency(struct r848_priv *priv) ++{ ++ u32 LO_KHz; ++ R848_SysFreq_Info_Type SysFreq_Info1; ++ int ret; ++ ++ // Check Input Frequency Range ++ if (priv->freq < 40000) ++ return -EINVAL; ++ ++ if (priv->standard != R848_DVB_S) { ++ if (priv->freq > 1002000) ++ return -EINVAL; ++ } else { ++ if (priv->freq > 2400000) ++ return -EINVAL; ++ } ++ ++ LO_KHz = priv->freq + priv->Sys_Info1.IF_KHz; ++ ++ // Set MUX dependent var. Must do before PLL( ) ++ if (r848_set_mux(priv, LO_KHz, priv->freq, priv->standard)) //normal MUX ++ return RT_Fail; ++ ++ // Set PLL ++ if (r848_set_pll(priv, LO_KHz, priv->standard)) ++ return RT_Fail; ++ ++ //Set TF ++ if (R848_SetTF(priv, priv->freq, priv->cfg->R848_SetTfType)) ++ return RT_Fail; ++ ++ //R848_IMR_point_num = Freq_Info1.IMR_MEM; ++ ++ //Q1.5K Q_ctrl R848:R14[4] ++ //if(R848_INFO.RF_KHzfreq <= 472000) //<472MHz ++ priv->regs[6] = priv->regs[6] | 0x10; ++ else ++ priv->regs[6] = priv->regs[6] & 0xEF; ++ ++ // medQctrl 1.5K ++ if ((priv->freq >= 300000) && (priv->freq <= 472000)) //<473MHz and >299MHz ++ priv->regs[6] = priv->regs[6] | 0x01; ++ else ++ priv->regs[6] = priv->regs[6] & 0xFE; ++ ret = r848_wr(priv, 0x0e, priv->regs[6]); // R848:R14[1] ++ ++ // 3~6 shrink ++ if ((priv->freq >= 300000) && (priv->freq <= 550000)) //<551MHz and >299MHz ++ priv->regs[3] = priv->regs[3] & 0xFB; ++ else ++ priv->regs[3] = priv->regs[3] | 0x04; ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); // R848:R11[2] ++ ++ // set Xtal AAC on=1; off=0 ++ priv->regs[16] = priv->regs[16] & 0xFD; ++ ret |= r848_wr(priv, 0x18, priv->regs[16]); // R848:R24[1] ++ ++ // Get Sys-Freq parameter ++ SysFreq_Info1 = R848_SysFreq_Sel(priv, priv->standard, priv->freq); ++ ++ // Set LNA_TOP ++ priv->regs[27] = (priv->regs[27] & 0xF8) | (SysFreq_Info1.LNA_TOP); ++ ret |= r848_wr(priv, 0x23, priv->regs[27]); // R848:R35[2:0] ++ ++ // Set LNA VTHL ++ priv->regs[23] = (priv->regs[23] & 0x00) | SysFreq_Info1.LNA_VTH_L; ++ ret |= r848_wr(priv, 0x1f, priv->regs[23]); // R848:R31[7:0] ++ ++ // Set MIXER TOP ++ priv->regs[28] = (priv->regs[28] & 0xF0) | (SysFreq_Info1.MIXER_TOP); ++ ret |= r848_wr(priv, 0x24, priv->regs[28]); // R848:R36[7:0] ++ ++ // Set MIXER VTHL ++ priv->regs[24] = (priv->regs[24] & 0x00) | SysFreq_Info1.MIXER_VTH_L; ++ ret |= r848_wr(priv, 0x20, priv->regs[24]); // R848:R32[7:0] ++ ++ // Set RF TOP ++ priv->regs[26] = (priv->regs[26] & 0x1F) | SysFreq_Info1.RF_TOP; ++ ret |= r848_wr(priv, 0x22, priv->regs[26]); // R848:R34[7:0] ++ ++ // Set Nrb TOP ++ priv->regs[28] = (priv->regs[28] & 0x0F) | SysFreq_Info1.NRB_TOP; ++ ret |= r848_wr(priv, 0x24, priv->regs[28]); // R848:R36[7:0] ++ ++ // Set Nrb BW ++ priv->regs[27] = (priv->regs[27] & 0x3F) | SysFreq_Info1.NRB_BW; ++ ret |= r848_wr(priv, 0x23, priv->regs[27]); // R848:R35[7:6] ++ ++ // Set TF LPF ++ priv->regs[4] = (priv->regs[4] & 0xBF) | SysFreq_Info1.BYP_LPF; ++ ret |= r848_wr(priv, 0x0c, priv->regs[4]); // R848:R12[6] ++ ++ priv->regs[38] = (priv->regs[38] & 0xF1) | SysFreq_Info1.RF_FAST_DISCHARGE; ++ ret |= r848_wr(priv, 0x2e, priv->regs[38]); // R848:R46[3:1] = 0b000 ++ ++ priv->regs[14] = (priv->regs[14] & 0x1F) | SysFreq_Info1.RF_SLOW_DISCHARGE; ++ ret |= r848_wr(priv, 0x16, priv->regs[14]); // R848:R22[7:5] = 0b010 ++ ++ priv->regs[30] = (priv->regs[30] & 0xEF) | SysFreq_Info1.RFPD_PLUSE_ENA; ++ ret |= r848_wr(priv, 0x26, priv->regs[30]); // R848:R38[4] = 1 ++ ++ priv->regs[35] = (priv->regs[35] & 0xE0) | SysFreq_Info1.LNA_FAST_DISCHARGE; ++ ret |= r848_wr(priv, 0x2b, priv->regs[35]); // R848:R43[4:0] = 0b01010 ++ ++ priv->regs[14] = (priv->regs[14] & 0xE3) | SysFreq_Info1.LNA_SLOW_DISCHARGE; ++ ret |= r848_wr(priv, 0x16, priv->regs[14]); // R848:R22[4:2] = 0b000 ++ ++ priv->regs[9] = (priv->regs[9] & 0x7F) | SysFreq_Info1.LNAPD_PLUSE_ENA; ++ ret |= r848_wr(priv, 0x11, priv->regs[9]); // R848:R17[7] = 0 ++ ++ // Set AGC clk ++ priv->regs[18] = (priv->regs[18] & 0xE3) | SysFreq_Info1.AGC_CLK; ++ ret |= r848_wr(priv, 0x1a, priv->regs[18]); // R848:R26[4:2] ++ ++ // no clk out ++ priv->regs[17] = (priv->regs[17] | 0x80); // R848:R25[7] ++ ret |= r848_wr(priv, 0x19, priv->regs[17]); ++ ++ // for DVB-T2 ++ switch (priv->standard) { ++ case R848_DVB_T2_6M: ++ case R848_DVB_T2_7M: ++ case R848_DVB_T2_8M: ++ case R848_DVB_T2_1_7M: ++ case R848_DVB_T2_10M: ++ case R848_DVB_T2_6M_IF_5M: ++ case R848_DVB_T2_7M_IF_5M: ++ case R848_DVB_T2_8M_IF_5M: ++ case R848_DVB_T2_1_7M_IF_5M: ++ msleep(100); ++/* ++ // AGC clk 250Hz ++ priv->regs[18] = (priv->regs[18] & 0xE3) | 0x1C; //[4:2]=111 ++ ret |= r848_wr(priv, 0x1a, priv->regs[18]); // R848:R26[4:2] ++*/ ++ // force plain mode ++ priv->regs[3] = (priv->regs[3] | 0x80); //[7]=1 ++ ret |= r848_wr(priv, 0x0b, priv->regs[3]); // R848:R11[7] ++ ++ priv->regs[2] = (priv->regs[2] & 0xDF); //[5]=0 ++ ret |= r848_wr(priv, 0x0a, priv->regs[2]); // R848:R10[5] ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++ ++ ++ ++ ++ ++ ++static int r848_release(struct dvb_frontend *fe) ++{ ++ struct r848_priv *priv = fe->tuner_priv; ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ return 0; ++} ++ ++static int r848_init(struct dvb_frontend *fe) ++{ ++ struct r848_priv *priv = fe->tuner_priv; ++ int ret; ++ u8 i; ++ ++ printk("init tuner\n"); ++ ++ if (priv->inited == 1) ++ return 0; ++ ++ ++ printk("init tuner first time\n"); ++ ++ ++ for (i = 0; i < R848_STD_SIZE; i++) { ++ priv->fc[i].flag = 0; ++ priv->fc[i].code = 0; ++ priv->fc[i].bw = 0x00; ++ } ++ ++ ++ if (r848_init_regs(priv,R848_STD_SIZE) != RT_Success) ++ return RT_Fail; ++ ++ if(R848_TF_Check(priv) != RT_Success) ++ return RT_Fail; ++ ++ //start IMR calibration ++ if(r848_init_regs(priv,R848_STD_SIZE) != RT_Success) //write initial reg before doing IMR Cal ++ return RT_Fail; ++ ++ if(R848_Cal_Prepare(priv,R848_IMR_CAL) != RT_Success) ++ return RT_Fail; ++ ++ if(R848_IMR(priv,3, 0) != RT_Success) //Full K node 3 ++ return RT_Fail; ++ ++ if(R848_IMR(priv,0, 1) != RT_Success) ++ return RT_Fail; ++ ++ if(R848_IMR(priv,1, 1) != RT_Success) ++ return RT_Fail; ++ ++ if(R848_IMR(priv,2, 1) != RT_Success) ++ return RT_Fail; ++ ++ if(R848_IMR(priv,4, 0) != RT_Success) //Full K node 4 ++ return RT_Fail; ++ ++ //do Xtal check ++ if(r848_init_regs(priv,R848_STD_SIZE) != RT_Success) ++ return RT_Fail; ++ ++ priv->cfg->R848_Xtal_Pwr = XTAL_SMALL_LOWEST; ++ priv->cfg->R848_Xtal_Pwr_tmp = XTAL_SMALL_LOWEST; ++ ++ for (i=0; i<3; i++) { ++ if(R848_Xtal_Check(priv) != RT_Success) ++ return RT_Fail; ++ ++ if(priv->cfg->R848_Xtal_Pwr_tmp > priv->cfg->R848_Xtal_Pwr) ++ priv->cfg->R848_Xtal_Pwr = priv->cfg->R848_Xtal_Pwr_tmp; ++ } ++ ++ //write initial reg ++ if(r848_init_regs(priv,R848_STD_SIZE) != RT_Success) ++ return RT_Fail; ++ ++ priv->standard = R848_STD_SIZE; ++ ++ ret = 0; ++ ++ if (ret) ++ dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__); ++ ++ priv->inited = 1; ++ ++ printk("init tuner done\n"); ++ return ret; ++} ++ ++static int r848_sleep(struct dvb_frontend *fe) ++{ ++ struct r848_priv *priv = fe->tuner_priv; ++ int ret = 0; ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ ++ //if (ret) ++ // dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__); ++ return ret; ++} ++ ++static int r848_set_params(struct dvb_frontend *fe) ++{ ++ struct r848_priv *priv = fe->tuner_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i; ++ u8 tuner_lock; ++ u8 standard; ++ ++ dev_info(&priv->i2c->dev, "%s() delivery_system=%d frequency=%d " \ ++ "symbol_rate=%d bandwidth_hz=%d\n", __func__, ++ c->delivery_system, c->frequency, c->symbol_rate, ++ c->bandwidth_hz); ++ ++ ++ /* failsafe */ ++ standard = R848_DVB_T2_8M_IF_5M; ++ ++ switch (c->delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ priv->freq = c->frequency / 1000; ++ if(c->bandwidth_hz <= 6000000) { ++ standard = R848_DVB_C_6M_IF_5M; ++ } else if (c->bandwidth_hz <= 8000000) { ++ standard = R848_DVB_C_8M_IF_5M; ++ } ++ ++ /* set pll data */ ++ if(r848_set_standard(priv, standard) != RT_Success) { ++ return RT_Fail; ++ } ++ if(r848_set_frequency(priv)) ++ return RT_Fail; ++ break; ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ priv->freq = c->frequency; ++ priv->standard = R848_DVB_S; ++ priv->bw = (c->symbol_rate/200*135+2000000)/1000*2;//unit KHz ++ priv->output_mode = DIFFERENTIALOUT; ++ priv->agc_mode = AGC_NEGATIVE; ++ ++ /* set pll data */ ++ if(R848_DVBS_Setting(priv) != RT_Success) ++ return RT_Fail; ++ break; ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ default: ++ priv->freq = c->frequency / 1000; ++ if(c->bandwidth_hz <= 1700000) { ++ standard = R848_DVB_T2_1_7M_IF_5M; ++ } else if (c->bandwidth_hz <= 6000000) { ++ standard = R848_DVB_T2_6M_IF_5M; ++ } else if (c->bandwidth_hz <= 7000000) { ++ standard = R848_DVB_T2_7M_IF_5M; ++ } else { ++ standard = R848_DVB_T2_8M_IF_5M; ++ } ++ ++ if (r848_set_standard(priv, standard)) ++ return RT_Fail; ++ if (r848_set_frequency(priv)) ++ return RT_Fail; ++ break; ++ } ++ ++ for (i = 0; i < 5; i++) { ++ ret = r848_get_lock_status(priv, &tuner_lock); ++ if(tuner_lock) { ++ printk("Tuner Locked.\n"); ++ break; ++ } else { ++ printk("Tuner not Locked!\n"); ++ } ++ msleep(20); ++ } ++ ++ return ret; ++} ++ ++static const struct dvb_tuner_ops r848_tuner_ops = { ++ .info = { ++ .name = "Rafael R848", ++ ++// .frequency_min = 850000, ++// .frequency_max = 2300000, ++// .frequency_step = 206, ++ }, ++ ++ .release = r848_release, ++ ++ .init = r848_init, ++ .sleep = r848_sleep, ++ .set_params = r848_set_params, ++}; ++ ++struct dvb_frontend *r848_attach(struct dvb_frontend *fe, ++ struct r848_config *cfg, struct i2c_adapter *i2c) ++{ ++ struct r848_priv *priv = NULL; ++ ++ priv = kzalloc(sizeof(struct r848_priv), GFP_KERNEL); ++ if (priv == NULL) { ++ dev_dbg(&i2c->dev, "%s() attach failed\n", __func__); ++ return NULL; ++ } ++ ++ priv->cfg = cfg; ++ priv->i2c = i2c; ++ priv->inited = 0; ++ ++ dev_info(&priv->i2c->dev, ++ "%s: Rafael R848 successfully attached\n", ++ KBUILD_MODNAME); ++ ++ memcpy(&fe->ops.tuner_ops, &r848_tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ ++ fe->tuner_priv = priv; ++ return fe; ++} ++EXPORT_SYMBOL(r848_attach); ++ ++MODULE_DESCRIPTION("Rafael R848 silicon tuner driver"); ++MODULE_AUTHOR("Luis Alves "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/tuners/r848.h b/drivers/media/tuners/r848.h +new file mode 100644 +index 0000000..b730e12 +--- /dev/null ++++ b/drivers/media/tuners/r848.h +@@ -0,0 +1,63 @@ ++/* ++ * Rafael R848 silicon tuner driver ++ * ++ * Copyright (C) 2015 Luis Alves ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef R848_H ++#define R848_H ++ ++#include ++#include "dvb_frontend.h" ++ ++ ++ ++ ++ ++ ++ ++ ++struct r848_config { ++ /* tuner i2c address */ ++ u8 i2c_address; ++ ++ u32 xtal; ++ ++ // tuner ++ u8 R848_DetectTfType ; ++ ++ u8 R848_Xtal_Pwr ; ++ u8 R848_Xtal_Pwr_tmp ; ++ ++ /* dvbc/t */ ++ u8 R848_SetTfType; ++ ++}; ++ ++#if IS_ENABLED(CONFIG_MEDIA_TUNER_R848) ++extern struct dvb_frontend *r848_attach(struct dvb_frontend *fe, ++ struct r848_config *cfg, struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *r848_attach(struct dvb_frontend *fe, ++ struct r848_config *cfg, struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif ++ ++#endif /* R848_H */ +diff --git a/drivers/media/tuners/r848_priv.h b/drivers/media/tuners/r848_priv.h +new file mode 100644 +index 0000000..3a3d398 +--- /dev/null ++++ b/drivers/media/tuners/r848_priv.h +@@ -0,0 +1,487 @@ ++/* ++ * Rafael R848 silicon tuner driver ++ * ++ * Copyright (C) 2015 Luis Alves ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef R848_PRIV_H ++#define R848_PRIV_H ++ ++#define NUM_REGS 40 ++#define NUM_IMR 5 ++ ++ ++typedef enum _R848_Standard_Type //Don't remove standand list!! ++{ ++ R848_DVB_T_6M = 0, ++ R848_DVB_T_7M, ++ R848_DVB_T_8M, ++ R848_DVB_T2_6M, //IF=4.57M ++ R848_DVB_T2_7M, //IF=4.57M ++ R848_DVB_T2_8M, //IF=4.57M ++ R848_DVB_T2_1_7M, ++ R848_DVB_T2_10M, ++ R848_DVB_C_8M, ++ R848_DVB_C_6M, ++ R848_J83B, ++ R848_ISDB_T, //IF=4.063M ++ R848_ISDB_T_4570, //IF=4.57M ++ R848_DTMB_4570, //IF=4.57M ++ R848_DTMB_6000, //IF=6.00M ++ R848_DTMB_6M_BW_IF_5M, //IF=5.0M, BW=6M ++ R848_DTMB_6M_BW_IF_4500, //IF=4.5M, BW=6M ++ R848_ATSC, ++ R848_DVB_S, ++ R848_DVB_T_6M_IF_5M, ++ R848_DVB_T_7M_IF_5M, ++ R848_DVB_T_8M_IF_5M, ++ R848_DVB_T2_6M_IF_5M, ++ R848_DVB_T2_7M_IF_5M, ++ R848_DVB_T2_8M_IF_5M, ++ R848_DVB_T2_1_7M_IF_5M, ++ R848_DVB_C_8M_IF_5M, ++ R848_DVB_C_6M_IF_5M, ++ R848_J83B_IF_5M, ++ R848_ISDB_T_IF_5M, ++ R848_DTMB_IF_5M, ++ R848_ATSC_IF_5M, ++ R848_FM, ++ R848_STD_SIZE, ++}R848_Standard_Type; ++ ++ ++typedef struct _R848_Sys_Info_Type ++{ ++ u16 IF_KHz; ++ u16 FILT_CAL_IF; ++ u8 BW; ++ u8 V17M; ++ u8 HPF_COR; ++ u8 FILT_EXT_ENA; ++ u8 FILT_EXT_WIDEST; ++ u8 FILT_EXT_POINT; ++// u8 AGC_CLK; ++ u8 FILT_COMP; ++ u8 FILT_CUR; ++ u8 FILT_3DB; ++ u8 SWBUF_CUR; ++ u8 TF_CUR; ++ u8 INDUC_BIAS; ++ u8 SWCAP_CLK; ++ u8 NA_PWR_DET; ++}R848_Sys_Info_Type; ++ ++ ++ ++ ++ ++ ++ ++ ++struct filter_cal { ++ u8 flag; ++ u8 bw; ++ u8 code; ++}; ++ ++struct r848_sect_type { ++ u8 phase_y; ++ u8 gain_x; ++ u8 iqcap; ++ u8 value; ++}; ++ ++struct r848_priv { ++ struct r848_config *cfg; ++ struct i2c_adapter *i2c; ++ u8 inited; ++ ++ ++ u8 regs[NUM_REGS]; ++ struct r848_sect_type imr_data[NUM_IMR]; ++ ++ u8 delsys; ++ ++ /* tune settings */ ++ u32 bw; ++ u32 freq; /* kHz */ ++ u8 standard; ++ u8 output_mode; ++ u8 agc_mode; ++ ++ struct filter_cal fc[R848_STD_SIZE]; ++ ++ ++ ++ R848_Sys_Info_Type Sys_Info1; ++}; ++ ++ ++ ++ ++ ++ ++typedef struct _R848_Set_Info ++{ ++ u32 RF_KHz; ++ u32 DVBS_BW; ++ u8 R848_Standard; ++ int R848_DVBS_OutputSignal_Mode; ++ int R848_DVBS_AGC_Mode; ++} R848_Set_Info; ++ ++ ++ ++/* R848 */ ++ ++//----------------------------------------------------------// ++// Define // ++//----------------------------------------------------------// ++ ++#define VERSION "R848_GUI_2.3A" ++ ++#define R848_REG_NUM 40 ++#define R848_TF_HIGH_NUM 8 ++#define R848_TF_MID_NUM 8 ++#define R848_TF_LOW_NUM 8 ++#define R848_TF_LOWEST_NUM 8 ++#define R848_RING_POWER_FREQ_LOW 115000 ++#define R848_RING_POWER_FREQ_HIGH 450000 ++#define R848_IMR_IF 5300 ++#define R848_IMR_TRIAL 9 ++#define R848_Xtal 16000 ++//----------------------------------------------------------// ++// Internal Structure // ++//----------------------------------------------------------// ++ ++ ++typedef struct _R848_Freq_Info_Type ++{ ++ u8 RF_POLY; ++ u8 LNA_BAND; ++ u8 LPF_CAP; ++ u8 LPF_NOTCH; ++ u8 XTAL_POW0; ++ u8 CP_CUR; ++ u8 IMR_MEM; ++ u8 Q_CTRL; ++}R848_Freq_Info_Type; ++ ++typedef struct _R848_SysFreq_Info_Type ++{ ++ u8 LNA_TOP; ++ u8 LNA_VTH_L; ++ u8 MIXER_TOP; ++ u8 MIXER_VTH_L; ++ u8 RF_TOP; ++ u8 NRB_TOP; ++ u8 NRB_BW; ++ u8 BYP_LPF; ++ u8 RF_FAST_DISCHARGE; ++ u8 RF_SLOW_DISCHARGE; ++ u8 RFPD_PLUSE_ENA; ++ u8 LNA_FAST_DISCHARGE; ++ u8 LNA_SLOW_DISCHARGE; ++ u8 LNAPD_PLUSE_ENA; ++ u8 AGC_CLK; ++ ++}R848_SysFreq_Info_Type; ++ ++typedef struct _R848_Cal_Info_Type ++{ ++ u8 FILTER_6DB; ++ u8 MIXER_AMP_GAIN; ++ u8 MIXER_BUFFER_GAIN; ++ u8 LNA_GAIN; ++ u8 LNA_POWER; ++ u8 RFBUF_OUT; ++ u8 RFBUF_POWER; ++ u8 TF_CAL; ++}R848_Cal_Info_Type; ++ ++ ++ ++typedef struct _R848_TF_Result ++{ ++ u8 TF_Set; ++ u8 TF_Value; ++}R848_TF_Result; ++ ++typedef enum _R848_TF_Band_Type ++{ ++ TF_HIGH = 0, ++ TF_MID, ++ TF_LOW ++}R848_TF_Band_Type; ++ ++typedef enum _R848_TF_Type ++{ ++ R848_TF_NARROW = 0, //270n/68n (ISDB-T, DVB-T/T2) ++ R848_TF_BEAD, //Bead/68n (DTMB) ++ R848_TF_NARROW_LIN, //270n/68n (N/A) ++ R848_TF_NARROW_ATV_LIN, //270n/68n (ATV) ++ R848_TF_BEAD_LIN, //Bead/68n (PAL_DK for China Hybrid TV) ++ R848_TF_NARROW_ATSC, //270n/68n (ATSC, DVB-C, J83B) ++ R848_TF_BEAD_LIN_ATSC, //Bead/68n (ATSC, DVB-C, J83B) ++ R848_TF_82N_BEAD, //Bead/82n (DTMB) ++ R848_TF_82N_270N, //270n/82n (OTHER Standard) ++ R848_TF_SIZE ++} R848_TF_Type; ++ ++ ++ ++u32 R848_LNA_HIGH_MID[R848_TF_SIZE] = { 644000, 644000, 644000, 644000, 644000, 500000, 500000, 500000, 500000}; ++u32 R848_LNA_MID_LOW[R848_TF_SIZE] = { 388000, 388000, 348000, 348000, 348000, 300000, 300000, 300000, 300000}; ++u32 R848_LNA_LOW_LOWEST[R848_TF_SIZE] = {164000, 164000, 148000, 124000, 124000, 156000, 156000, 108000, 108000}; ++ ++ ++u32 R848_TF_Freq_High[R848_TF_SIZE][R848_TF_HIGH_NUM] = ++{ { 784000, 784000, 776000, 744000, 712000, 680000, 648000, 647000}, ++ { 784000, 784000, 776000, 744000, 712000, 680000, 648000, 647000}, ++ { 784000, 784000, 776000, 744000, 712000, 680000, 648000, 647000}, ++ { 784000, 784000, 776000, 744000, 712000, 680000, 648000, 647000}, ++ { 784000, 784000, 776000, 744000, 712000, 680000, 648000, 647000}, ++ { 784000, 784000, 776000, 680000, 608000, 584000, 536000, 504000}, ++ { 784000, 784000, 776000, 680000, 608000, 584000, 536000, 504000}, ++ { 784000, 776000, 712000, 616000, 584000, 560000, 520000, 504000}, ++ { 784000, 776000, 712000, 616000, 584000, 560000, 520000, 504000} ++}; ++ ++ ++u32 R848_TF_Freq_Mid[R848_TF_SIZE][R848_TF_MID_NUM] = ++{ {608000, 584000, 560000, 536000, 488000, 440000, 416000, 392000}, ++ {608000, 584000, 560000, 536000, 488000, 440000, 416000, 392000}, ++ {608000, 560000, 536000, 488000, 440000, 392000, 376000, 352000}, ++ {608000, 560000, 536000, 488000, 440000, 392000, 376000, 352000}, ++ {608000, 560000, 536000, 488000, 440000, 392000, 376000, 352000}, ++ {488000, 464000, 440000, 416000, 392000, 352000, 320000, 304000}, ++ {488000, 464000, 440000, 416000, 392000, 352000, 320000, 304000}, ++ {480000, 464000, 440000, 416000, 392000, 352000, 320000, 304000}, ++ {480000, 464000, 440000, 416000, 392000, 352000, 320000, 304000}, ++}; ++u32 R848_TF_Freq_Low[R848_TF_SIZE][R848_TF_LOW_NUM] = ++{ {320000, 304000, 272000, 240000, 232000, 216000, 192000, 168000}, //164~388 ++ {320000, 304000, 272000, 240000, 232000, 216000, 192000, 168000}, //164~388 ++ {256000, 240000, 232000, 224000, 216000, 192000, 168000, 160000}, //148~348 ++ {256000, 240000, 232000, 192000, 160000, 152000, 144000, 128000}, //124~348 ++ {264000, 240000, 192000, 184000, 176000, 152000, 144000, 128000}, //124~348 ++ {280000, 248000, 232000, 216000, 192000, 176000, 168000, 160000}, //156~300 ++ {280000, 248000, 232000, 216000, 192000, 176000, 168000, 160000}, //156~300 ++ {296000, 280000, 256000, 216000, 184000, 168000, 136000, 112000}, // ++ {296000, 280000, 256000, 216000, 184000, 168000, 136000, 112000} // ++}; ++u32 R848_TF_Freq_Lowest[R848_TF_SIZE][R848_TF_LOWEST_NUM] = ++{ {160000, 120000, 104000, 88000, 80000, 72000, 56000, 48000}, ++ {160000, 120000, 104000, 88000, 80000, 72000, 56000, 48000}, ++ {144000, 120000, 104000, 88000, 80000, 72000, 56000, 48000}, ++ {120000, 96000, 88000, 80000, 72000, 64000, 56000, 48000}, ++ {104000, 96000, 88000, 80000, 72000, 64000, 56000, 48000}, ++ {136000, 120000, 104000, 88000, 72000, 64000, 56000, 48000}, ++ {128000, 120000, 104000, 96000, 80000, 72000, 64000, 56000}, ++ {104000, 96000, 88000, 80000, 72000, 64000, 56000, 48000}, ++ {104000, 96000, 88000, 80000, 72000, 64000, 56000, 48000} ++}; ++ ++u8 R848_TF_Result_High[R848_TF_SIZE][R848_TF_HIGH_NUM] = ++{ {0x00, 0x00, 0x01, 0x03, 0x04, 0x05, 0x07, 0x07}, ++ {0x00, 0x00, 0x01, 0x03, 0x04, 0x05, 0x07, 0x07}, ++ {0x00, 0x00, 0x01, 0x03, 0x04, 0x05, 0x07, 0x07}, ++ {0x00, 0x00, 0x01, 0x03, 0x04, 0x05, 0x07, 0x07}, ++ {0x00, 0x00, 0x01, 0x03, 0x04, 0x05, 0x07, 0x07}, ++ {0x00, 0x00, 0x01, 0x05, 0x0A, 0x0C, 0x13, 0x19}, ++ {0x00, 0x00, 0x01, 0x05, 0x0A, 0x0C, 0x13, 0x19}, ++ {0x00, 0x03, 0x07, 0x0C, 0x0E, 0x0F, 0x1A, 0x1A}, ++ {0x00, 0x03, 0x07, 0x0C, 0x0E, 0x0F, 0x1A, 0x1A} ++}; ++ ++u8 R848_TF_Result_Mid[R848_TF_SIZE][R848_TF_MID_NUM] = ++{ {0x00, 0x01, 0x03, 0x03, 0x06, 0x0B, 0x0E, 0x11}, ++ {0x00, 0x01, 0x03, 0x03, 0x06, 0x0B, 0x0E, 0x11}, ++ {0x00, 0x03, 0x03, 0x06, 0x0B, 0x11, 0x12, 0x19}, ++ {0x00, 0x03, 0x03, 0x06, 0x0B, 0x11, 0x12, 0x19}, ++ {0x00, 0x03, 0x03, 0x06, 0x0B, 0x11, 0x12, 0x19}, ++ {0x06, 0x08, 0x0B, 0x0E, 0x13, 0x17, 0x1E, 0x1F}, ++ {0x06, 0x08, 0x0B, 0x0E, 0x13, 0x17, 0x1E, 0x1F}, ++ {0x09, 0x0D, 0x10, 0x12, 0x16, 0x1B, 0x1E, 0x1F}, ++ {0x09, 0x0D, 0x10, 0x12, 0x16, 0x1B, 0x1E, 0x1F} ++}; ++u8 R848_TF_Result_Low[R848_TF_SIZE][R848_TF_LOW_NUM] = ++{ {0x00, 0x02, 0x04, 0x07, 0x0A, 0x0B, 0x0F, 0x16}, ++ {0x00, 0x02, 0x04, 0x07, 0x0A, 0x0B, 0x0F, 0x16}, ++ {0x05, 0x07, 0x0A, 0x0B, 0x0B, 0x0F, 0x16, 0x1A}, ++ {0x05, 0x07, 0x0A, 0x0F, 0x1A, 0x1A, 0x23, 0x2A}, ++ {0x05, 0x08, 0x10, 0x13, 0x1A, 0x1A, 0x23, 0x2A}, ++ {0x05, 0x08, 0x0C, 0x0E, 0x10, 0x14, 0x18, 0x1A}, ++ {0x05, 0x08, 0x0C, 0x0E, 0x10, 0x14, 0x18, 0x1A}, ++ {0x00, 0x01, 0x03, 0x07, 0x0D, 0x11, 0x1E, 0x2F}, ++ {0x00, 0x01, 0x03, 0x07, 0x0D, 0x11, 0x1E, 0x2F} ++}; ++u8 R848_TF_Result_Lowest[R848_TF_SIZE][R848_TF_LOWEST_NUM] = ++{ {0x00, 0x06, 0x0C, 0x15, 0x1C, 0x1F, 0x3C, 0x3F}, ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08}, ++ {0x02, 0x06, 0x0C, 0x15, 0x1C, 0x1F, 0x3C, 0x3F}, ++ {0x06, 0x11, 0x15, 0x1C, 0x1F, 0x2F, 0x3C, 0x3F}, ++ {0x04, 0x08, 0x08, 0x08, 0x10, 0x12, 0x13, 0x13}, ++ {0x06, 0x09, 0x0E, 0x18, 0x25, 0x2F, 0x3C, 0x3F}, ++ {0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x12, 0x13}, ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08}, ++ {0x0E, 0x14, 0x18, 0x1E, 0x25, 0x2F, 0x3C, 0x3F} ++}; ++ ++ ++u8 R848_iniArray_hybrid[R848_REG_NUM] = { ++ 0x00, 0x00, 0x40, 0x44, 0x17, 0x00, 0x06, 0xF0, 0x00, 0x41, ++ // 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 0x11 ++ 0x7B, 0x0B, 0x70, 0x06, 0x6E, 0x20, 0x70, 0x87, 0x96, 0x00, ++ // 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B ++ 0x10, 0x00, 0x80, 0xA5, 0xB7, 0x00, 0x40, 0xCB, 0x95, 0xF0, ++ // 0x1C 0x1D 0x1E 0x1F 0x20 0x21 0x22 0x23 0x24 0x25 ++ 0x24, 0x00, 0xFD, 0x8B, 0x17, 0x13, 0x01, 0x07, 0x01, 0x3F}; ++ // 0x26 0x27 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F ++ ++ ++ ++u8 R848_iniArray_dvbs[R848_REG_NUM] = { ++ 0x80, 0x05, 0x40, 0x40, 0x1F, 0x1F, 0x07, 0xFF, 0x00, 0x40, ++ // 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 0x11 ++ 0xF0, 0x0F, 0x4D, 0x06, 0x6F, 0x20, 0x28, 0x83, 0x96, 0x00, //0x16[1] pulse_flag HPF : Bypass ; 0x19[1:0] Deglich SW Cur : highest ++ // 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B ++ 0x1C, 0x99, 0xC1, 0x83, 0xB7, 0x00, 0x4F, 0xCB, 0x95, 0xFD, ++ // 0x1C 0x1D 0x1E 0x1F 0x20 0x21 0x22 0x23 0x24 0x25 ++ 0xA4, 0x01, 0x24, 0x0B, 0x4F, 0x05, 0x01, 0x47, 0x3F, 0x3F}; ++ // 0x26 0x27 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F ++ ++ ++ ++ ++ ++ ++ ++ ++typedef enum _R848_UL_TF_Type ++{ ++ R848_UL_USING_BEAD = 0, ++ R848_UL_USING_270NH, ++}R848_UL_TF_Type; ++ ++ ++ ++typedef enum _R848_Cal_Type ++{ ++ R848_IMR_CAL = 0, ++ R848_IMR_LNA_CAL, ++ R848_TF_CAL, ++ R848_TF_LNA_CAL, ++ R848_LPF_CAL, ++ R848_LPF_LNA_CAL ++}R848_Cal_Type; ++ ++typedef enum _R848_BW_Type ++{ ++ BW_6M = 0, ++ BW_7M, ++ BW_8M, ++ BW_1_7M, ++ BW_10M, ++ BW_200K ++}R848_BW_Type; ++ ++ ++enum R848_XTAL_PWR_VALUE { ++ XTAL_SMALL_LOWEST = 0, ++ XTAL_SMALL_LOW, ++ XTAL_SMALL_HIGH, ++ XTAL_SMALL_HIGHEST, ++ XTAL_LARGE_HIGHEST, ++ XTAL_CHECK_SIZE ++}; ++ ++ ++typedef enum _R848_Xtal_Div_TYPE ++{ ++ XTAL_DIV1 = 0, ++ XTAL_DIV2 ++}R848_Xtal_Div_TYPE; ++ ++ ++//----------------------------------------------------------// ++// R848 Public Parameter // ++//----------------------------------------------------------// ++typedef enum _R848_ErrCode ++{ ++ RT_Success = 0, ++ RT_Fail = 1 ++}R848_ErrCode; ++ ++ ++ ++typedef enum _R848_GPO_Type ++{ ++ HI_SIG = 0, ++ LO_SIG = 1 ++}R848_GPO_Type; ++ ++typedef enum _R848_RF_Gain_TYPE ++{ ++ RF_AUTO = 0, ++ RF_MANUAL ++}R848_RF_Gain_TYPE; ++ ++typedef enum _R848_DVBS_OutputSignal_Type ++{ ++ DIFFERENTIALOUT = 0, ++ SINGLEOUT = 1 ++}R848_DVBS_OutputSignal_Type; ++ ++typedef enum _R848_DVBS_AGC_Type ++{ ++ AGC_NEGATIVE = 0, ++ AGC_POSITIVE = 1 ++}R848_DVBS_AGC_Type; ++ ++ ++ ++ ++ ++typedef struct _R848_RF_Gain_Info ++{ ++ u16 RF_gain_comb; ++ u8 RF_gain1; ++ u8 RF_gain2; ++ u8 RF_gain3; ++}R848_RF_Gain_Info; ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++#endif /* R848_PRIV_H */ +diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c +index 57b2508..68b0dfb 100644 +--- a/drivers/media/tuners/si2157.c ++++ b/drivers/media/tuners/si2157.c +@@ -40,7 +40,7 @@ static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd) + + if (cmd->rlen) { + /* wait cmd execution terminate */ +- #define TIMEOUT 80 ++ #define TIMEOUT 500 + timeout = jiffies + msecs_to_jiffies(TIMEOUT); + while (!time_after(jiffies, timeout)) { + ret = i2c_master_recv(client, cmd->args, cmd->rlen); +@@ -288,23 +288,25 @@ static int si2157_set_params(struct dvb_frontend *fe) + + switch (c->delivery_system) { + case SYS_ATSC: +- delivery_system = 0x00; +- if_frequency = 3250000; +- break; +- case SYS_DVBC_ANNEX_B: +- delivery_system = 0x10; +- if_frequency = 4000000; +- break; ++ delivery_system = 0x00; ++ if_frequency = 3250000; ++ break; + case SYS_DVBT: + case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */ +- delivery_system = 0x20; +- break; ++ delivery_system = 0x20; ++ break; + case SYS_DVBC_ANNEX_A: +- delivery_system = 0x30; ++ delivery_system = 0x30; ++ break; ++ case SYS_DVBC_ANNEX_B: ++ delivery_system = 0x10; ++ break; ++ case SYS_ISDBT: ++ delivery_system = 0x40; + break; + default: +- ret = -EINVAL; +- goto err; ++ ret = -EINVAL; ++ goto err; + } + + memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6); +@@ -436,8 +438,15 @@ static int si2157_probe(struct i2c_client *client, + INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work); + + /* check if the tuner is there */ +- cmd.wlen = 0; +- cmd.rlen = 1; ++ /* wake tuner */ ++ if (dev->chiptype == SI2157_CHIPTYPE_SI2146) { ++ memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9); ++ cmd.wlen = 9; ++ } else { ++ memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15); ++ cmd.wlen = 15; ++ } ++ cmd.rlen = 1; + ret = si2157_cmd_execute(client, &cmd); + if (ret) + goto err_kfree; +diff --git a/drivers/media/tuners/stv6120.c b/drivers/media/tuners/stv6120.c +new file mode 100644 +index 0000000..9d5cc65 +--- /dev/null ++++ b/drivers/media/tuners/stv6120.c +@@ -0,0 +1,712 @@ ++/* ++ * Driver for the ST STV6120 tuner ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++ ++#include "stv6120.h" ++ ++#define REG_N0 0 ++#define REG_N1_F0 1 ++#define REG_F1 2 ++#define REG_F2_ICP 3 ++#define REG_CF_PDIV 4 ++#define REG_CFHF 5 ++#define REG_CAL 6 ++ ++struct SLookup { ++ s16 Value; ++ u16 RegValue; ++}; ++ ++static struct SLookup Gain_RFAGC_LookUp[] = { ++ /*Gain *100dB*/ /*reg*/ ++ { 7429 , 0 }, /* 74.61 dB */ ++ { 7368 , 18711 }, /* 74.43 dB */ ++ { 7214 , 23432 }, /* 73.36 dB */ ++ { 7090 , 25123 }, /* 72.4 dB */ ++ { 6988 , 26305 }, /* 71.47 dB */ ++ { 6897 , 27100 }, /* 70.47 dB */ ++ { 6809 , 27741 }, /* 69.5 dB */ ++ { 6728 , 28271 }, /* 68.52 dB */ ++ { 6645 , 28737 }, /* 67.52 dB */ ++ { 6571 , 29120 }, /* 66.53 dB */ ++ { 6494 , 29504 }, /* 65.54 dB */ ++ { 6416 , 29857 }, /* 64.55 dB */ ++ { 6341 , 30180 }, /* 63.55 dB */ ++ { 6263 , 30490 }, /* 62.56 dB */ ++ { 6179 , 30815 }, /* 61.57 dB */ ++ { 6101 , 31088 }, /* 60.58 dB */ ++ { 6028 , 31345 }, /* 59.57 dB */ ++ { 5956 , 31600 }, /* 58.59 dB */ ++ { 5883 , 31840 }, /* 57.6 dB */ ++ { 5801 , 32096 }, /* 56.6 dB */ ++ { 5730 , 32320 }, /* 55.59 dB */ ++ { 5659 , 32544 }, /* 54.59 dB */ ++ { 5582 , 32752 }, /* 53.61 dB */ ++ { 5498 , 32960 }, /* 52.61 dB */ ++ { 5414 , 33184 }, /* 51.61 dB */ ++ { 5340 , 33392 }, /* 50.62 dB */ ++ { 5271 , 33584 }, /* 49.61 dB */ ++ { 5198 , 33775 }, /* 48.61 dB */ ++ { 5125 , 33967 }, /* 47.62 dB */ ++ { 5048 , 34160 }, /* 46.62 dB */ ++ { 4963 , 34352 }, /* 45.62 dB */ ++ { 4884 , 34543 }, /* 44.62 dB */ ++ { 4820 , 34719 }, /* 43.62 dB */ ++ { 4740 , 34910 }, /* 42.62 dB */ ++ { 4666 , 35103 }, /* 41.62 dB */ ++ { 4582 , 35295 }, /* 40.62 dB */ ++ { 4500 , 35488 }, /* 39.62 dB */ ++ { 4426 , 35680 }, /* 38.62 dB */ ++ { 4365 , 35870 }, /* 37.62 dB */ ++ { 4279 , 36095 }, /* 36.62 dB */ ++ { 4113 , 36289 }, /* 35.62 dB */ ++ { 4020 , 36500 }, /* 34.62 dB */ ++ { 3930 , 36704 }, /* 33.62 dB */ ++ { 3838 , 36912 }, /* 32.62 dB */ ++ { 3738 , 37152 }, /* 31.62 dB */ ++ { 3648 , 37375 }, /* 30.62 dB */ ++ { 3544 , 37600 }, /* 29.62 dB */ ++ { 3458 , 37823 }, /* 28.62 dB */ ++ { 3358 , 38048 }, /* 27.62 dB */ ++ { 3281 , 38240 }, /* 26.62 dB */ ++ { 3191 , 38479 }, /* 25.62 dB */ ++ { 3091 , 38720 }, /* 24.62 dB */ ++ { 2993 , 38976 }, /* 23.63 dB */ ++ { 2900 , 39226 }, /* 22.63 dB */ ++ { 2792 , 39520 }, /* 21.62 dB */ ++ { 2692 , 39792 }, /* 20.62 dB */ ++ { 2592 , 40064 }, /* 19.62 dB */ ++ { 2497 , 40351 }, /* 18.62 dB */ ++ { 2392 , 40640 }, /* 17.62 dB */ ++ { 2290 , 40976 }, /* 16.62 dB */ ++ { 2189 , 41295 }, /* 15.62 dB */ ++ { 2088 , 41631 }, /* 14.62 dB */ ++ { 1999 , 41934 }, /* 13.62 dB */ ++ { 1875 , 42354 }, /* 12.62 dB */ ++ { 1764 , 42815 }, /* 11.62 dB */ ++ { 1637 , 43263 }, /* 10.62 dB */ ++ { 1537 , 43743 }, /* 9.62 dB */ ++ { 1412 , 44288 }, /* 8.62 dB */ ++ { 1291 , 44913 }, /* 7.62 dB */ ++ { 1188 , 45712 }, /* 6.62 dB */ ++ { 1080 , 46720 }, /* 5.63 dB */ ++ { 976 , 48164 }, /* 4.63 dB */ ++ { 930 , 50816 }, /* 3.63 dB */ ++ { 898 , 65534 }, /* 2.94 dB */ ++ { 880 , 65535 } /* 2.95 dB */ ++}; ++ ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++#endif ++ ++ ++static const u8 tuner_init[25] = { ++ 0x77, ++ 0x33, 0xce, 0x54, 0x55, 0x0d, 0x32, 0x44, 0x0e, ++ 0xf9, 0x1b, ++ 0x33, 0xce, 0x54, 0x55, 0x0d, 0x32, 0x44, 0x0e, ++ 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4c, ++}; ++ ++LIST_HEAD(stvlist); ++ ++static inline u32 MulDiv32(u32 a, u32 b, u32 c) ++{ ++ u64 tmp64; ++ ++ tmp64 = (u64)a * (u64)b; ++ do_div(tmp64, c); ++ ++ return (u32) tmp64; ++} ++ ++ ++struct stv_base { ++ struct list_head stvlist; ++ ++ u8 adr; ++ struct i2c_adapter *i2c; ++ struct mutex i2c_lock; ++ struct mutex reg_lock; ++ int count; ++}; ++ ++ ++struct stv { ++ struct stv_base *base; ++ struct dvb_frontend *fe; ++ int nr; ++ ++ struct stv6120_cfg *cfg; ++ ++ u8 reg[7]; ++}; ++ ++static int i2c_read(struct i2c_adapter *adap, ++ u8 adr, u8 *msg, int len, u8 *answ, int alen) ++{ ++ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, ++ .buf = msg, .len = len}, ++ { .addr = adr, .flags = I2C_M_RD, ++ .buf = answ, .len = alen } }; ++ if (i2c_transfer(adap, msgs, 2) != 2) { ++ pr_err("stv6120: i2c_read error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ pr_err("stv6120: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++#if 0 ++static int write_regs(struct stv *state, int reg, int len) ++{ ++ u8 d[8]; ++ ++ u8 base = 0x02 + 0xa * state->nr; ++ ++ memcpy(&d[1], &state->base->reg[reg], len); ++ d[0] = reg; ++ return i2c_write(state->base->i2c, state->base->adr, d, len + 1); ++} ++#endif ++static int write_tuner_regs(struct stv *state) ++{ ++ u8 d[8]; ++ memcpy(&d[1], state->reg, 7); ++ d[0] = 0x02 + 0xa * state->nr; ++ return i2c_write(state->base->i2c, state->base->adr, d, 8); ++} ++ ++static int read_reg(struct stv *state, u8 reg, u8 *val) ++{ ++ return i2c_read(state->base->i2c, state->base->adr, ®, 1, val, 1); ++} ++ ++static int read_regs(struct stv *state, u8 reg, u8 *val, int len) ++{ ++ return i2c_read(state->base->i2c, state->base->adr, ®, 1, val, len); ++} ++ ++#if 0 ++static void dump_regs(struct stv *state) ++{ ++ u8 d[25], *c = &state->reg[0]; ++ ++ read_regs(state, state->nr * 0xa + 2, d, 7); ++ pr_info("stv6120_regs = %02x %02x %02x %02x %02x %02x %02x\n", ++ d[0], d[1], d[2], d[3], d[4], d[5], d[6]); ++ pr_info("reg[] = %02x %02x %02x %02x %02x %02x %02x\n", ++ c[0], c[1], c[2], c[3], c[4], c[5], c[6]); ++ ++ ++ read_regs(state, 0, d, 14); ++ pr_info("global: 0=%02x a=%02x 1=%02x b=%02x\n", d[0], d[0xa], d[1], d[0xb]); ++} ++#endif ++ ++static int wait_for_call_done(struct stv *state, u8 mask) ++{ ++ int status = 0; ++ u32 LockRetryCount = 10; ++ ++ while (LockRetryCount > 0) { ++ u8 Status; ++ ++ status = read_reg(state, state->nr * 0xa + 8, &Status); ++ if (status < 0) ++ return status; ++ ++ if ((Status & mask) == 0) ++ break; ++ usleep_range(4000, 6000); ++ LockRetryCount -= 1; ++ ++ status = -1; ++ } ++ return status; ++} ++ ++static void init_regs(struct stv *state) ++{ ++ u32 clkdiv = 0; ++ u32 agcmode = 0; ++ u32 agcref = 2; ++ u32 agcset = 0xffffffff; ++ u32 bbmode = 0xffffffff; ++ ++/* ++ 0f40 00770133 02ce0354 0455050d 06320744 .w.3...T.U...2.D ++ 0f50 080e09f9 0a030b33 0cce0d54 0e550f0d .......3...T.U.. ++ ++ 0f60 10321144 120e1300 1400154c 16001700 .2.D.......L.... ++ 0f70 184c0000 00000000 00000000 00000000 .L.............. ++*/ ++ ++//i = 0 ++// rd(i) != (i+1) ? ++// wr(i, i+1) ++// repeat until 32 ++// ++// wr(0xa, 0x1b) ++ ++ //memcpy(state->base->reg, tuner_init, 25); ++/* ++ state->ref_freq = 16000; ++ ++ ++ if (clkdiv <= 3) ++ state->reg[0x00] |= (clkdiv & 0x03); ++ if (agcmode <= 3) { ++ state->reg[0x03] |= (agcmode << 5); ++ if (agcmode == 0x01) ++ state->reg[0x01] |= 0x30; ++ } ++ if (bbmode <= 3) ++ state->reg[0x01] = (state->reg[0x01] & ~0x30) | (bbmode << 4); ++ if (agcref <= 7) ++ state->reg[0x03] |= agcref; ++ if (agcset <= 31) ++ state->reg[0x02] = (state->reg[0x02] & ~0x1F) | agcset | 0x40; ++*/ ++} ++ ++static int probe(struct stv *state) ++{ ++ struct dvb_frontend *fe = state->fe; ++ int ret = 0; ++ ++ u8 d[26]; ++ ++ init_regs(state); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ ++ memcpy(&d[1], tuner_init, 25); ++ d[0] = 0; ++ ret = i2c_write(state->base->i2c, state->base->adr, d, 25 + 1); ++ ++ if (ret < 0) ++ goto err; ++#if 0 ++ pr_info("attach_init OK\n"); ++ dump_regs(state); ++#endif ++ ++err: ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ return ret; ++} ++ ++static int sleep(struct dvb_frontend *fe) ++{ ++ /* struct tda_state *state = fe->tuner_priv; */ ++ ++ //pr_info("tuner sleep\n"); ++ return 0; ++} ++ ++static int init(struct dvb_frontend *fe) ++{ ++ /* struct tda_state *state = fe->tuner_priv; */ ++ //pr_info("init\n"); ++ return 0; ++} ++ ++static int release(struct dvb_frontend *fe) ++{ ++ struct stv *state = fe->tuner_priv; ++ ++ state->base->count--; ++ if (state->base->count == 0) { ++ //pr_info("remove STV tuner base\n"); ++ list_del(&state->base->stvlist); ++ kfree(state->base); ++ } ++ kfree(state); ++ fe->tuner_priv = NULL; ++ return 0; ++} ++#if 0 ++static int set_bandwidth(struct dvb_frontend *fe, u32 CutOffFrequency) ++{ ++ struct stv *state = fe->tuner_priv; ++ u32 index = (CutOffFrequency + 999999) / 1000000; ++ ++ if (index < 6) ++ index = 6; ++ if (index > 50) ++ index = 50; ++ if ((state->base->reg[0x08] & ~0xFC) == ((index-6) << 2)) ++ return 0; ++ ++ state->base->reg[0x08] = (state->base->reg[0x08] & ~0xFC) | ((index-6) << 2); ++ state->base->reg[0x09] = (state->base->reg[0x09] & ~0x0C) | 0x08; ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ write_regs(state, 0x08, 2); ++ wait_for_call_done(state, 0x08); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ return 0; ++} ++ ++#endif ++ ++ ++ ++static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency) ++{ ++ int cf_index = (CutOffFrequency / 1000000) - 5; ++ u32 Frequency = (LocalFrequency + 500) / 1000; // Hz -> kHz ++ u32 p = 1, psel = 0, fvco, div, frac; ++ u8 Icp, tmp; ++ ++ u32 freq = Frequency; ++ u8 PDIV, P; ++ ++ //pr_info("F = %u, CutOff = %u\n", Frequency, CutOffFrequency); ++ ++ ++ /* set PDIV and CF */ ++ if (cf_index < 0) ++ cf_index = 0; ++ if (cf_index > 31) ++ cf_index = 31; ++ ++ if (Frequency >= 1191000) { ++ PDIV = 0; ++ P = 2; ++ } else if (Frequency >= 596000) { ++ PDIV = 1; ++ P = 4; ++ } else if (Frequency >= 299000) { ++ PDIV = 2; ++ P = 8; ++ } else { ++ PDIV = 3; ++ P = 16; ++ } ++ ++ ++ fvco = Frequency * P; ++ div = (fvco * state->cfg->Rdiv) / state->cfg->xtal; ++ ++ /* charge pump current */ ++ Icp = 0; ++ if (fvco < 2472000) ++ Icp = 0; ++ else if (fvco < 2700000) ++ Icp = 1; ++ else if (fvco < 3021000) ++ Icp = 2; ++ else if (fvco < 3387000) ++ Icp = 3; ++ else if (fvco < 3845000) ++ Icp = 5; ++ else if (fvco < 4394000) ++ Icp = 6; ++ else ++ Icp = 7; ++ ++ ++ ++ ++ ++ frac = (fvco * state->cfg->Rdiv) % state->cfg->xtal; ++ frac = MulDiv32(frac, 0x40000, state->cfg->xtal); ++ ++ ++ state->reg[REG_N0] = div & 0xff; ++ state->reg[REG_N1_F0] = (((div >> 8) & 0x01) | ((frac & 0x7f) << 1)) & 0xff; ++ state->reg[REG_F1] = (frac >> 7) & 0xff; ++ state->reg[REG_F2_ICP] &= 0x88; ++ state->reg[REG_F2_ICP] |= (Icp << 4) | ((frac >> 15) & 0x07); ++ state->reg[REG_CF_PDIV] &= 0x9f; ++ state->reg[REG_CF_PDIV] |= ((PDIV << 5) | cf_index); ++ ++ /* Start cal vco,CF */ ++ state->reg[REG_CAL] &= 0xf8; ++ state->reg[REG_CAL] |= 0x06; ++ ++ write_tuner_regs(state); ++ ++ wait_for_call_done(state, 0x06); ++ ++ usleep_range(10000, 12000); ++ ++#if 0 ++ read_reg(state, 0x03, &tmp); ++ if (tmp & 0x10) { ++ state->base->reg[0x02] &= ~0x80; /* LNA NF Mode */ ++ write_regs(state, 2, 1); ++ } ++ read_reg(state, 0x08, &tmp); ++#endif ++ ++// dump_regs(state); ++ return 0; ++} ++ ++static int set_params(struct dvb_frontend *fe) ++{ ++ struct stv *state = fe->tuner_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ int status; ++ u32 freq, symb, cutoff; ++ u32 rolloff; ++ ++ if (p->delivery_system != SYS_DVBS && p->delivery_system != SYS_DVBS2) ++ return -EINVAL; ++ ++ switch (p->rolloff) { ++ case ROLLOFF_20: ++ rolloff = 120; ++ break; ++ case ROLLOFF_25: ++ rolloff = 125; ++ break; ++ default: ++ rolloff = 135; ++ break; ++ } ++ ++ freq = p->frequency * 1000; ++ symb = p->symbol_rate; ++ cutoff = 5000000 + MulDiv32(p->symbol_rate, rolloff, 200); ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ set_lof(state, freq, cutoff); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ return status; ++} ++ ++static int get_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; ++ return 0; ++} ++ ++static u32 AGC_Gain[] = { ++ 000, /* 0.0 */ ++ 000, /* 0.1 */ ++ 1000, /* 0.2 */ ++ 2000, /* 0.3 */ ++ 3000, /* 0.4 */ ++ 4000, /* 0.5 */ ++ 5000, /* 0.6 */ ++ 6000, /* 0.7 */ ++ 7000, /* 0.8 */ ++ 14000, /* 0.9 */ ++ 20000, /* 1.0 */ ++ 27000, /* 1.1 */ ++ 32000, /* 1.2 */ ++ 37000, /* 1.3 */ ++ 42000, /* 1.4 */ ++ 47000, /* 1.5 */ ++ 50000, /* 1.6 */ ++ 53000, /* 1.7 */ ++ 56000, /* 1.8 */ ++ 58000, /* 1.9 */ ++ 60000, /* 2.0 */ ++ 62000, /* 2.1 */ ++ 63000, /* 2.2 */ ++ 64000, /* 2.3 */ ++ 64500, /* 2.4 */ ++ 65000, /* 2.5 */ ++ 65500, /* 2.6 */ ++ 66000, /* 2.7 */ ++ 66500, /* 2.8 */ ++ 67000, /* 2.9 */ ++}; ++ ++static s32 TableLookup(struct SLookup *Table, int TableSize, u16 RegValue) ++{ ++ s32 Gain; ++ s32 RegDiff; ++ int imin = 0; ++ int imax = TableSize - 1; ++ int i; ++ ++ // Assumes Table[0].RegValue < Table[imax].RegValue ++ if( RegValue <= Table[0].RegValue ) ++ Gain = Table[0].Value; ++ else if( RegValue >= Table[imax].RegValue ) ++ Gain = Table[imax].Value; ++ else { ++ while(imax-imin > 1) { ++ i = (imax + imin) / 2; ++ if ((Table[imin].RegValue <= RegValue) && ++ (RegValue <= Table[i].RegValue) ) ++ imax = i; ++ else ++ imin = i; ++ } ++ RegDiff = Table[imax].RegValue - Table[imin].RegValue; ++ Gain = Table[imin].Value; ++ if (RegDiff != 0) ++ Gain += ((s32) (RegValue - Table[imin].RegValue) * ++ (s32)(Table[imax].Value - Table[imin].Value))/(RegDiff); ++ } ++ return Gain; ++} ++ ++static int get_rf_strength(struct dvb_frontend *fe, u16 *st) ++{ ++ struct stv *state = fe->tuner_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ s32 gain = 1, ref_bbgain = 12, tilt = 6; ++ u32 freq; ++ ++ gain = TableLookup(Gain_RFAGC_LookUp, ARRAY_SIZE(Gain_RFAGC_LookUp), *st); ++ ++ gain += 100 * (6 - ref_bbgain); ++ ++ freq = p->frequency / 10000; ++ ++ if (freq<159) ++ gain -= 200; /* HMR filter 2dB gain compensation below freq=1590MHz */ ++ ++ gain-=(((freq-155)*tilt)/12)*10; ++ //pr_warn("%s: str = %u\n", __func__, *st); ++ ++ return 0; ++} ++ ++static int get_if(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; ++ return 0; ++} ++ ++static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ return 0; ++} ++ ++static struct dvb_tuner_ops tuner_ops = { ++ .info = { ++ .name = "STV6120", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_step = 0 ++ }, ++ .init = init, ++ .sleep = sleep, ++ .set_params = set_params, ++ .release = release, ++// .get_frequency = get_frequency, ++// .get_if_frequency = get_if, ++// .get_bandwidth = get_bandwidth, ++ .get_rf_strength = get_rf_strength, ++// .set_bandwidth = set_bandwidth, ++}; ++ ++static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr) ++{ ++ struct stv_base *p; ++ ++ list_for_each_entry(p, &stvlist, stvlist) ++ if (p->i2c == i2c && p->adr == adr) ++ return p; ++ return NULL; ++} ++ ++ ++struct dvb_frontend *stv6120_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct stv6120_cfg *cfg, int nr) ++{ ++ struct stv *state; ++ struct stv_base *base; ++ int stat = 0; ++ ++ state = kzalloc(sizeof(struct stv), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); ++ state->fe = fe; ++ memcpy(state->reg, &tuner_init[2], 7); ++ ++ base = match_base(i2c, cfg->adr); ++ if (base) { ++ base->count++; ++ state->base = base; ++ } else { ++ base = kzalloc(sizeof(struct stv_base), GFP_KERNEL); ++ if (!base) ++ goto fail; ++ base->i2c = i2c; ++ base->adr = cfg->adr; ++ base->count = 1; ++ mutex_init(&base->i2c_lock); ++ mutex_init(&base->reg_lock); ++ state->base = base; ++ if (probe(state) < 0) { ++ kfree(base); ++ goto fail; ++ } ++ list_add(&base->stvlist, &stvlist); ++ } ++ ++ ++ if (cfg->xtal == 0) { ++ printk("xtal=0!!!\n"); ++ goto fail; ++ } ++ ++ state->cfg = cfg; ++ state->nr = nr; ++ ++ fe->tuner_priv = state; ++ return fe; ++fail: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(stv6120_attach); ++ ++MODULE_DESCRIPTION("STV6120 driver"); ++MODULE_AUTHOR("Luis Alves"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/media/tuners/stv6120.h b/drivers/media/tuners/stv6120.h +new file mode 100644 +index 0000000..e907e41 +--- /dev/null ++++ b/drivers/media/tuners/stv6120.h +@@ -0,0 +1,17 @@ ++#ifndef _STV6120_H_ ++#define _STV6120_H_ ++ ++ ++struct stv6120_cfg { ++ u8 adr; ++ ++ u32 xtal; ++ u8 Rdiv; ++}; ++ ++ ++ ++ ++struct dvb_frontend *stv6120_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct stv6120_cfg *cfg, int nr); ++#endif +diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c +index 7b80683..fd827b4 100644 +--- a/drivers/media/tuners/tda18212.c ++++ b/drivers/media/tuners/tda18212.c +@@ -95,6 +95,7 @@ static int tda18212_set_params(struct dvb_frontend *fe) + ret = -EINVAL; + goto error; + } ++ buf[0] = 0x30; + break; + case SYS_DVBT2: + switch (c->bandwidth_hz) { +@@ -114,11 +115,13 @@ static int tda18212_set_params(struct dvb_frontend *fe) + ret = -EINVAL; + goto error; + } ++ buf[0] = 0x30; + break; + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: + if_khz = dev->cfg.if_dvbc; + i = DVBC_8; ++ buf[0] = 0x00; + break; + default: + ret = -EINVAL; +@@ -129,17 +132,28 @@ static int tda18212_set_params(struct dvb_frontend *fe) + if (ret) + goto error; + ++ ret = regmap_write(dev->regmap, 0x5f, 0x00); ++ if (ret) ++ goto error; ++ + ret = regmap_write(dev->regmap, 0x06, 0x00); + if (ret) + goto error; + ++ if (dev->cfg.loop_through) ++ buf[0] |= 0x80; ++ ++ ret = regmap_write(dev->regmap, 0x0c, buf[0]); ++ if (ret) ++ goto error; ++ + ret = regmap_write(dev->regmap, 0x0f, bw_params[i][0]); + if (ret) + goto error; + + buf[0] = 0x02; + buf[1] = bw_params[i][1]; +- buf[2] = 0x03; /* default value */ ++ buf[2] = dev->cfg.xtout ? 0x43 : 0x40; /* 0x03; default value */ + buf[3] = DIV_ROUND_CLOSEST(if_khz, 50); + buf[4] = ((c->frequency / 1000) >> 16) & 0xff; + buf[5] = ((c->frequency / 1000) >> 8) & 0xff; +diff --git a/drivers/media/tuners/tda18212.h b/drivers/media/tuners/tda18212.h +index 6391daf..7b1ff03 100644 +--- a/drivers/media/tuners/tda18212.h ++++ b/drivers/media/tuners/tda18212.h +@@ -34,6 +34,8 @@ struct tda18212_config { + u16 if_dvbc; + u16 if_atsc_vsb; + u16 if_atsc_qam; ++ u8 loop_through:1; ++ u8 xtout:1; + + /* + * pointer to DVB frontend +diff --git a/drivers/media/tuners/tda18273.c b/drivers/media/tuners/tda18273.c +new file mode 100644 +index 0000000..ac2cbae +--- /dev/null ++++ b/drivers/media/tuners/tda18273.c +@@ -0,0 +1,2184 @@ ++/* ++ tda18273.c - driver for the NXP TDA18273 silicon tuner ++ Copyright (C) 2014 CrazyCat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++ ++#include "tda18273_priv.h" ++ ++static unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "Set Verbosity level"); ++ ++#define FE_ERROR 0 ++#define FE_NOTICE 1 ++#define FE_INFO 2 ++#define FE_DEBUG 3 ++#define FE_DEBUGREG 4 ++ ++#define dprintk(__y, __z, format, arg...) do { \ ++ if (__z) { \ ++ if ((verbose > FE_ERROR) && (verbose > __y)) \ ++ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ ++ else if ((verbose > FE_NOTICE) && (verbose > __y)) \ ++ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ ++ else if ((verbose > FE_INFO) && (verbose > __y)) \ ++ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ ++ else if ((verbose > FE_DEBUG) && (verbose > __y)) \ ++ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ ++ } else { \ ++ if (verbose > __y) \ ++ printk(format, ##arg); \ ++ } \ ++} while (0) ++ ++#define TDA18273_REG_ADD_SZ (0x01) ++#define TDA18273_REG_DATA_MAX_SZ (0x01) ++#define TDA18273_REG_MAP_NB_BYTES (0x6D) ++ ++#define TDA18273_REG_DATA_LEN(_FIRST_REG, _LAST_REG) ( (_LAST_REG.Address - _FIRST_REG.Address) + 1) ++ ++struct tda18273_state { ++ struct dvb_frontend *fe; ++ struct i2c_adapter *i2c; ++ u8 i2c_addr; ++ ++ unsigned int if_freq; ++ unsigned int freq_hz; ++ unsigned int bandwidth; ++ unsigned char freq_band; ++ unsigned char agc_mode; ++ unsigned char pll_step; ++ unsigned char pll_step_val; ++ unsigned char pll_charge_pump; ++ ++ unsigned int power_state; ++ unsigned char regmap[TDA18273_REG_MAP_NB_BYTES]; ++ ++ pTDA18273Object_t pObj; ++}; ++ ++TDA18273Object_t gTDA18273Instance = ++{ ++ 0, ++ 0, ++ 0, ++ TDA18273_StandardMode_Unknown, ++ NULL, ++ TDA18273_INSTANCE_CUSTOM_STD_DEF ++}; ++ ++ ++/* TDA18273 Register ID_byte_1 0x00 */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_1 = { 0x00, 0x00, 0x08, 0x00 }; ++/* MS bit(s): Indicate if Device is a Master or a Slave */ ++/* 1 => Master device */ ++/* 0 => Slave device */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_1__MS = { 0x00, 0x07, 0x01, 0x00 }; ++/* Ident_1 bit(s): MSB of device identifier */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_1__Ident_1 = { 0x00, 0x00, 0x07, 0x00 }; ++ ++ ++/* TDA18273 Register ID_byte_2 0x01 */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_2 = { 0x01, 0x00, 0x08, 0x00 }; ++/* Ident_2 bit(s): LSB of device identifier */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_2__Ident_2 = { 0x01, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register ID_byte_3 0x02 */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_3 = { 0x02, 0x00, 0x08, 0x00 }; ++/* Major_rev bit(s): Major revision of device */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_3__Major_rev = { 0x02, 0x04, 0x04, 0x00 }; ++/* Major_rev bit(s): Minor revision of device */ ++const TDA18273_BitField_t gTDA18273_Reg_ID_byte_3__Minor_rev = { 0x02, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register Thermo_byte_1 0x03 */ ++const TDA18273_BitField_t gTDA18273_Reg_Thermo_byte_1 = { 0x03, 0x00, 0x08, 0x00 }; ++/* TM_D bit(s): Device temperature */ ++const TDA18273_BitField_t gTDA18273_Reg_Thermo_byte_1__TM_D = { 0x03, 0x00, 0x07, 0x00 }; ++ ++ ++/* TDA18273 Register Thermo_byte_2 0x04 */ ++const TDA18273_BitField_t gTDA18273_Reg_Thermo_byte_2 = { 0x04, 0x00, 0x08, 0x00 }; ++/* TM_ON bit(s): Set device temperature measurement to ON or OFF */ ++/* 1 => Temperature measurement ON */ ++/* 0 => Temperature measurement OFF */ ++const TDA18273_BitField_t gTDA18273_Reg_Thermo_byte_2__TM_ON = { 0x04, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register Power_state_byte_1 0x05 */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_1 = { 0x05, 0x00, 0x08, 0x00 }; ++/* POR bit(s): Indicates that device just powered ON */ ++/* 1 => POR: No access done to device */ ++/* 0 => At least one access has been done to device */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_1__POR = { 0x05, 0x07, 0x01, 0x00 }; ++/* AGCs_Lock bit(s): Indicates that AGCs are locked */ ++/* 1 => AGCs locked */ ++/* 0 => AGCs not locked */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_1__AGCs_Lock = { 0x05, 0x02, 0x01, 0x00 }; ++/* Vsync_Lock bit(s): Indicates that VSync is locked */ ++/* 1 => VSync locked */ ++/* 0 => VSync not locked */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_1__Vsync_Lock = { 0x05, 0x01, 0x01, 0x00 }; ++/* LO_Lock bit(s): Indicates that LO is locked */ ++/* 1 => LO locked */ ++/* 0 => LO not locked */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_1__LO_Lock = { 0x05, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register Power_state_byte_2 0x06 */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_2 = { 0x06, 0x00, 0x08, 0x00 }; ++/* SM bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_2__SM = { 0x06, 0x01, 0x01, 0x00 }; ++/* SM_XT bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_state_byte_2__SM_XT = { 0x06, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register Input_Power_Level_byte 0x07 */ ++const TDA18273_BitField_t gTDA18273_Reg_Input_Power_Level_byte = { 0x07, 0x00, 0x08, 0x00 }; ++/* Power_Level bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Input_Power_Level_byte__Power_Level = { 0x07, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register IRQ_status 0x08 */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status = { 0x08, 0x00, 0x08, 0x00 }; ++/* IRQ_status bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status__IRQ_status = { 0x08, 0x07, 0x01, 0x00 }; ++/* MSM_XtalCal_End bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status__MSM_XtalCal_End = { 0x08, 0x05, 0x01, 0x00 }; ++/* MSM_RSSI_End bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status__MSM_RSSI_End = { 0x08, 0x04, 0x01, 0x00 }; ++/* MSM_LOCalc_End bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status__MSM_LOCalc_End = { 0x08, 0x03, 0x01, 0x00 }; ++/* MSM_RFCal_End bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status__MSM_RFCal_End = { 0x08, 0x02, 0x01, 0x00 }; ++/* MSM_IRCAL_End bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status__MSM_IRCAL_End = { 0x08, 0x01, 0x01, 0x00 }; ++/* MSM_RCCal_End bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_status__MSM_RCCal_End = { 0x08, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register IRQ_enable 0x09 */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable = { 0x09, 0x00, 0x08, 0x00 }; ++/* IRQ_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable__IRQ_Enable = { 0x09, 0x07, 0x01, 0x00 }; ++/* MSM_XtalCal_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable__MSM_XtalCal_Enable = { 0x09, 0x05, 0x01, 0x00 }; ++/* MSM_RSSI_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable__MSM_RSSI_Enable = { 0x09, 0x04, 0x01, 0x00 }; ++/* MSM_LOCalc_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable__MSM_LOCalc_Enable = { 0x09, 0x03, 0x01, 0x00 }; ++/* MSM_RFCal_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable__MSM_RFCal_Enable = { 0x09, 0x02, 0x01, 0x00 }; ++/* MSM_IRCAL_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable__MSM_IRCAL_Enable = { 0x09, 0x01, 0x01, 0x00 }; ++/* MSM_RCCal_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_enable__MSM_RCCal_Enable = { 0x09, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register IRQ_clear 0x0A */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear = { 0x0A, 0x00, 0x08, 0x00 }; ++/* IRQ_Clear bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear__IRQ_Clear = { 0x0A, 0x07, 0x01, 0x00 }; ++/* MSM_XtalCal_Clear bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear__MSM_XtalCal_Clear = { 0x0A, 0x05, 0x01, 0x00 }; ++/* MSM_RSSI_Clear bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear__MSM_RSSI_Clear = { 0x0A, 0x04, 0x01, 0x00 }; ++/* MSM_LOCalc_Clear bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear__MSM_LOCalc_Clear = { 0x0A, 0x03, 0x01, 0x00 }; ++/* MSM_RFCal_Clear bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear__MSM_RFCal_Clear = { 0x0A, 0x02, 0x01, 0x00 }; ++/* MSM_IRCAL_Clear bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear__MSM_IRCAL_Clear = { 0x0A, 0x01, 0x01, 0x00 }; ++/* MSM_RCCal_Clear bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_clear__MSM_RCCal_Clear = { 0x0A, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register IRQ_set 0x0B */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set = { 0x0B, 0x00, 0x08, 0x00 }; ++/* IRQ_Set bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set__IRQ_Set = { 0x0B, 0x07, 0x01, 0x00 }; ++/* MSM_XtalCal_Set bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set__MSM_XtalCal_Set = { 0x0B, 0x05, 0x01, 0x00 }; ++/* MSM_RSSI_Set bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set__MSM_RSSI_Set = { 0x0B, 0x04, 0x01, 0x00 }; ++/* MSM_LOCalc_Set bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set__MSM_LOCalc_Set = { 0x0B, 0x03, 0x01, 0x00 }; ++/* MSM_RFCal_Set bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set__MSM_RFCal_Set = { 0x0B, 0x02, 0x01, 0x00 }; ++/* MSM_IRCAL_Set bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set__MSM_IRCAL_Set = { 0x0B, 0x01, 0x01, 0x00 }; ++/* MSM_RCCal_Set bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IRQ_set__MSM_RCCal_Set = { 0x0B, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register AGC1_byte_1 0x0C */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_1 = { 0x0C, 0x00, 0x08, 0x00 }; ++/* AGC1_TOP bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_1__AGC1_TOP = { 0x0C, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register AGC1_byte_2 0x0D */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_2 = { 0x0D, 0x00, 0x08, 0x00 }; ++/* AGC1_Top_Mode_Val bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_2__AGC1_Top_Mode_Val = { 0x0D, 0x03, 0x02, 0x00 }; ++/* AGC1_Top_Mode bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_2__AGC1_Top_Mode = { 0x0D, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register AGC2_byte_1 0x0E */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC2_byte_1 = { 0x0E, 0x00, 0x08, 0x00 }; ++/* AGC2_TOP bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC2_byte_1__AGC2_TOP = { 0x0E, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register AGCK_byte_1 0x0F */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCK_byte_1 = { 0x0F, 0x00, 0x08, 0x00 }; ++/* AGCs_Up_Step_assym bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCK_byte_1__AGCs_Up_Step_assym = { 0x0F, 0x06, 0x02, 0x00 }; ++/* Pulse_Shaper_Disable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCK_byte_1__Pulse_Shaper_Disable = { 0x0F, 0x04, 0x01, 0x00 }; ++/* AGCK_Step bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCK_byte_1__AGCK_Step = { 0x0F, 0x02, 0x02, 0x00 }; ++/* AGCK_Mode bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCK_byte_1__AGCK_Mode = { 0x0F, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register RF_AGC_byte 0x10 */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_AGC_byte = { 0x10, 0x00, 0x08, 0x00 }; ++/* PD_AGC_Adapt3x bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_AGC_byte__PD_AGC_Adapt3x = { 0x10, 0x06, 0x02, 0x00 }; ++/* RFAGC_Adapt_TOP bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_AGC_byte__RFAGC_Adapt_TOP = { 0x10, 0x04, 0x02, 0x00 }; ++/* RFAGC_Low_BW bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_AGC_byte__RFAGC_Low_BW = { 0x10, 0x03, 0x01, 0x00 }; ++/* RFAGC_Top bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_AGC_byte__RFAGC_Top = { 0x10, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register W_Filter_byte 0x11 */ ++const TDA18273_BitField_t gTDA18273_Reg_W_Filter_byte = { 0x11, 0x00, 0x08, 0x00 }; ++/* VHF_III_mode bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_W_Filter_byte__VHF_III_mode = { 0x11, 0x07, 0x01, 0x00 }; ++/* RF_Atten_3dB bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_W_Filter_byte__RF_Atten_3dB = { 0x11, 0x06, 0x01, 0x00 }; ++/* W_Filter_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_W_Filter_byte__W_Filter_Enable = { 0x11, 0x05, 0x01, 0x00 }; ++/* W_Filter_Bypass bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_W_Filter_byte__W_Filter_Bypass = { 0x11, 0x04, 0x01, 0x00 }; ++/* W_Filter bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_W_Filter_byte__W_Filter = { 0x11, 0x02, 0x02, 0x00 }; ++/* W_Filter_Offset bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_W_Filter_byte__W_Filter_Offset = { 0x11, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register IR_Mixer_byte_1 0x12 */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_1 = { 0x12, 0x00, 0x08, 0x00 }; ++/* S2D_Gain bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_1__S2D_Gain = { 0x12, 0x04, 0x02, 0x00 }; ++/* IR_Mixer_Top bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_1__IR_Mixer_Top = { 0x12, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register AGC5_byte_1 0x13 */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_1 = { 0x13, 0x00, 0x08, 0x00 }; ++/* AGCs_Do_Step_assym bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_1__AGCs_Do_Step_assym = { 0x13, 0x05, 0x02, 0x00 }; ++/* AGC5_Ana bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_1__AGC5_Ana = { 0x13, 0x04, 0x01, 0x00 }; ++/* AGC5_TOP bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_1__AGC5_TOP = { 0x13, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register IF_AGC_byte 0x14 */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_AGC_byte = { 0x14, 0x00, 0x08, 0x00 }; ++/* IFnotchToRSSI bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_AGC_byte__IFnotchToRSSI = { 0x14, 0x07, 0x01, 0x00 }; ++/* LPF_DCOffset_Corr bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_AGC_byte__LPF_DCOffset_Corr = { 0x14, 0x06, 0x01, 0x00 }; ++/* IF_level bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_AGC_byte__IF_level = { 0x14, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register IF_Byte_1 0x15 */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_Byte_1 = { 0x15, 0x00, 0x08, 0x00 }; ++/* IF_HP_Fc bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_Byte_1__IF_HP_Fc = { 0x15, 0x06, 0x02, 0x00 }; ++/* IF_ATSC_Notch bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_Byte_1__IF_ATSC_Notch = { 0x15, 0x05, 0x01, 0x00 }; ++/* LP_FC_Offset bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_Byte_1__LP_FC_Offset = { 0x15, 0x03, 0x02, 0x00 }; ++/* LP_Fc bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_Byte_1__LP_Fc = { 0x15, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register Reference_Byte 0x16 */ ++const TDA18273_BitField_t gTDA18273_Reg_Reference_Byte = { 0x16, 0x00, 0x08, 0x00 }; ++/* Digital_Clock_Mode bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode = { 0x16, 0x06, 0x02, 0x00 }; ++/* XTout bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Reference_Byte__XTout = { 0x16, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register IF_Frequency_byte 0x17 */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_Frequency_byte = { 0x17, 0x00, 0x08, 0x00 }; ++/* IF_Freq bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IF_Frequency_byte__IF_Freq = { 0x17, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Frequency_byte_1 0x18 */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Frequency_byte_1 = { 0x18, 0x00, 0x08, 0x00 }; ++/* RF_Freq_1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Frequency_byte_1__RF_Freq_1 = { 0x18, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Frequency_byte_2 0x19 */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Frequency_byte_2 = { 0x19, 0x00, 0x08, 0x00 }; ++/* RF_Freq_2 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Frequency_byte_2__RF_Freq_2 = { 0x19, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Frequency_byte_3 0x1A */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Frequency_byte_3 = { 0x1A, 0x00, 0x08, 0x00 }; ++/* RF_Freq_3 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Frequency_byte_3__RF_Freq_3 = { 0x1A, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register MSM_byte_1 0x1B */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1 = { 0x1B, 0x00, 0x08, 0x00 }; ++/* RSSI_Meas bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__RSSI_Meas = { 0x1B, 0x07, 0x01, 0x00 }; ++/* RF_CAL_AV bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__RF_CAL_AV = { 0x1B, 0x06, 0x01, 0x00 }; ++/* RF_CAL bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__RF_CAL = { 0x1B, 0x05, 0x01, 0x00 }; ++/* IR_CAL_Loop bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__IR_CAL_Loop = { 0x1B, 0x04, 0x01, 0x00 }; ++/* IR_Cal_Image bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__IR_Cal_Image = { 0x1B, 0x03, 0x01, 0x00 }; ++/* IR_CAL_Wanted bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__IR_CAL_Wanted = { 0x1B, 0x02, 0x01, 0x00 }; ++/* RC_Cal bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__RC_Cal = { 0x1B, 0x01, 0x01, 0x00 }; ++/* Calc_PLL bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_1__Calc_PLL = { 0x1B, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register MSM_byte_2 0x1C */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_2 = { 0x1C, 0x00, 0x08, 0x00 }; ++/* XtalCal_Launch bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_2__XtalCal_Launch = { 0x1C, 0x01, 0x01, 0x00 }; ++/* MSM_Launch bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_MSM_byte_2__MSM_Launch = { 0x1C, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register PowerSavingMode 0x1D */ ++const TDA18273_BitField_t gTDA18273_Reg_PowerSavingMode = { 0x1D, 0x00, 0x08, 0x00 }; ++/* PSM_AGC1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_PowerSavingMode__PSM_AGC1 = { 0x1D, 0x07, 0x01, 0x00 }; ++/* PSM_Bandsplit_Filter bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_PowerSavingMode__PSM_Bandsplit_Filter = { 0x1D, 0x05, 0x02, 0x00 }; ++/* PSM_RFpoly bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_PowerSavingMode__PSM_RFpoly = { 0x1D, 0x04, 0x01, 0x00 }; ++/* PSM_Mixer bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_PowerSavingMode__PSM_Mixer = { 0x1D, 0x03, 0x01, 0x00 }; ++/* PSM_Ifpoly bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_PowerSavingMode__PSM_Ifpoly = { 0x1D, 0x02, 0x01, 0x00 }; ++/* PSM_Lodriver bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_PowerSavingMode__PSM_Lodriver = { 0x1D, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register Power_Level_byte_2 0x1E */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Level_byte_2 = { 0x1E, 0x00, 0x08, 0x00 }; ++/* PD_PLD_read bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Level_byte_2__PD_PLD_read = { 0x1E, 0x07, 0x01, 0x00 }; ++/* IR_Target bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Level_byte_2__PLD_Temp_Slope = { 0x1E, 0x05, 0x02, 0x00 }; ++/* IR_GStep bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Level_byte_2__PLD_Gain_Corr = { 0x1E, 0x00, 0x05, 0x00 }; ++ ++ ++/* TDA18273 Register Adapt_Top_byte 0x1F */ ++const TDA18273_BitField_t gTDA18273_Reg_Adapt_Top_byte = { 0x1F, 0x00, 0x08, 0x00 }; ++/* Fast_Mode_AGC bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Adapt_Top_byte__Fast_Mode_AGC = { 0x1F, 0x06, 0x01, 0x00 }; ++/* Range_LNA_Adapt bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Adapt_Top_byte__Range_LNA_Adapt = { 0x1F, 0x05, 0x01, 0x00 }; ++/* Index_K_LNA_Adapt bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Adapt_Top_byte__Index_K_LNA_Adapt = { 0x1F, 0x03, 0x02, 0x00 }; ++/* Index_K_Top_Adapt bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Adapt_Top_byte__Index_K_Top_Adapt = { 0x1F, 0x01, 0x02, 0x00 }; ++/* Ovld_Udld_FastUp bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Adapt_Top_byte__Ovld_Udld_FastUp = { 0x1F, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register Vsync_byte 0x20 */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_byte = { 0x20, 0x00, 0x08, 0x00 }; ++/* Neg_modulation bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_byte__Neg_modulation = { 0x20, 0x07, 0x01, 0x00 }; ++/* Tracer_Step bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_byte__Tracer_Step = { 0x20, 0x05, 0x02, 0x00 }; ++/* Vsync_int bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_byte__Vsync_int = { 0x20, 0x04, 0x01, 0x00 }; ++/* Vsync_Thresh bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_byte__Vsync_Thresh = { 0x20, 0x02, 0x02, 0x00 }; ++/* Vsync_Len bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_byte__Vsync_Len = { 0x20, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register Vsync_Mgt_byte 0x21 */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_Mgt_byte = { 0x21, 0x00, 0x08, 0x00 }; ++/* PD_Vsync_Mgt bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_Mgt_byte__PD_Vsync_Mgt = { 0x21, 0x07, 0x01, 0x00 }; ++/* PD_Ovld bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_Mgt_byte__PD_Ovld = { 0x21, 0x06, 0x01, 0x00 }; ++/* PD_Ovld_RF bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_Mgt_byte__PD_Ovld_RF = { 0x21, 0x05, 0x01, 0x00 }; ++/* AGC_Ovld_TOP bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_Mgt_byte__AGC_Ovld_TOP = { 0x21, 0x02, 0x03, 0x00 }; ++/* Up_Step_Ovld bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_Mgt_byte__Up_Step_Ovld = { 0x21, 0x01, 0x01, 0x00 }; ++/* AGC_Ovld_Timer bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Vsync_Mgt_byte__AGC_Ovld_Timer = { 0x21, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register IR_Mixer_byte_2 0x22 */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_2 = { 0x22, 0x00, 0x08, 0x00 }; ++/* IR_Mixer_loop_off bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_2__IR_Mixer_loop_off = { 0x22, 0x07, 0x01, 0x00 }; ++/* IR_Mixer_Do_step bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_2__IR_Mixer_Do_step = { 0x22, 0x05, 0x02, 0x00 }; ++/* Hi_Pass bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_2__Hi_Pass = { 0x22, 0x01, 0x01, 0x00 }; ++/* IF_Notch bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Mixer_byte_2__IF_Notch = { 0x22, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register AGC1_byte_3 0x23 */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_3 = { 0x23, 0x00, 0x08, 0x00 }; ++/* AGC1_loop_off bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_3__AGC1_loop_off = { 0x23, 0x07, 0x01, 0x00 }; ++/* AGC1_Do_step bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_3__AGC1_Do_step = { 0x23, 0x05, 0x02, 0x00 }; ++/* Force_AGC1_gain bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_3__Force_AGC1_gain = { 0x23, 0x04, 0x01, 0x00 }; ++/* AGC1_Gain bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC1_byte_3__AGC1_Gain = { 0x23, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register RFAGCs_Gain_byte_1 0x24 */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1 = { 0x24, 0x00, 0x08, 0x00 }; ++/* PLD_DAC_Scale bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1__PLD_DAC_Scale = { 0x24, 0x07, 0x01, 0x00 }; ++/* PLD_CC_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1__PLD_CC_Enable = { 0x24, 0x06, 0x01, 0x00 }; ++/* PLD_Temp_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1__PLD_Temp_Enable = { 0x24, 0x05, 0x01, 0x00 }; ++/* TH_AGC_Adapt34 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1__TH_AGC_Adapt34 = { 0x24, 0x04, 0x01, 0x00 }; ++/* RFAGC_Sense_Enable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1__RFAGC_Sense_Enable = { 0x24, 0x02, 0x01, 0x00 }; ++/* RFAGC_K_Bypass bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1__RFAGC_K_Bypass = { 0x24, 0x01, 0x01, 0x00 }; ++/* RFAGC_K_8 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_1__RFAGC_K_8 = { 0x24, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register RFAGCs_Gain_byte_2 0x25 */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_2 = { 0x25, 0x00, 0x08, 0x00 }; ++/* RFAGC_K bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_2__RFAGC_K = { 0x25, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register AGC5_byte_2 0x26 */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_2 = { 0x26, 0x00, 0x08, 0x00 }; ++/* AGC5_loop_off bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_2__AGC5_loop_off = { 0x26, 0x07, 0x01, 0x00 }; ++/* AGC5_Do_step bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_2__AGC5_Do_step = { 0x26, 0x05, 0x02, 0x00 }; ++/* Force_AGC5_gain bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_2__Force_AGC5_gain = { 0x26, 0x03, 0x01, 0x00 }; ++/* AGC5_Gain bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGC5_byte_2__AGC5_Gain = { 0x26, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Cal_byte_1 0x27 */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_1 = { 0x27, 0x00, 0x08, 0x00 }; ++/* RFCAL_Offset_Cprog0 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog0 = { 0x27, 0x06, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog1 = { 0x27, 0x04, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog2 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog2 = { 0x27, 0x02, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog3 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog3 = { 0x27, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Cal_byte_2 0x28 */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_2 = { 0x28, 0x00, 0x08, 0x00 }; ++/* RFCAL_Offset_Cprog4 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog4 = { 0x28, 0x06, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog5 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog5 = { 0x28, 0x04, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog6 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog6 = { 0x28, 0x02, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog7 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog7 = { 0x28, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Cal_byte_3 0x29 */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_3 = { 0x29, 0x00, 0x08, 0x00 }; ++/* RFCAL_Offset_Cprog8 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_3__RFCAL_Offset_Cprog8 = { 0x29, 0x06, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog9 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_3__RFCAL_Offset_Cprog9 = { 0x29, 0x04, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog10 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_3__RFCAL_Offset_Cprog10 = { 0x29, 0x02, 0x02, 0x00 }; ++/* RFCAL_Offset_Cprog11 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Cal_byte_3__RFCAL_Offset_Cprog11 = { 0x29, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register Bandsplit_Filter_byte 0x2A */ ++const TDA18273_BitField_t gTDA18273_Reg_Bandsplit_Filter_byte = { 0x2A, 0x00, 0x08, 0x00 }; ++/* Bandsplit_Filter_SubBand bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Bandsplit_Filter_byte__Bandsplit_Filter_SubBand = { 0x2A, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Filters_byte_1 0x2B */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_1 = { 0x2B, 0x00, 0x08, 0x00 }; ++/* RF_Filter_Bypass bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_1__RF_Filter_Bypass = { 0x2B, 0x07, 0x01, 0x00 }; ++/* AGC2_loop_off bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_1__AGC2_loop_off = { 0x2B, 0x05, 0x01, 0x00 }; ++/* Force_AGC2_gain bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_1__Force_AGC2_gain = { 0x2B, 0x04, 0x01, 0x00 }; ++/* RF_Filter_Gv bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_1__RF_Filter_Gv = { 0x2B, 0x02, 0x02, 0x00 }; ++/* RF_Filter_Band bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_1__RF_Filter_Band = { 0x2B, 0x00, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Filters_byte_2 0x2C */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_2 = { 0x2C, 0x00, 0x08, 0x00 }; ++/* RF_Filter_Cap bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_2__RF_Filter_Cap = { 0x2C, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Filters_byte_3 0x2D */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_3 = { 0x2D, 0x00, 0x08, 0x00 }; ++/* AGC2_Do_step bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_3__AGC2_Do_step = { 0x2D, 0x06, 0x02, 0x00 }; ++/* Gain_Taper bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Filters_byte_3__Gain_Taper = { 0x2D, 0x00, 0x06, 0x00 }; ++ ++ ++/* TDA18273 Register RF_Band_Pass_Filter_byte 0x2E */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Band_Pass_Filter_byte = { 0x2E, 0x00, 0x08, 0x00 }; ++/* RF_BPF_Bypass bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Band_Pass_Filter_byte__RF_BPF_Bypass = { 0x2E, 0x07, 0x01, 0x00 }; ++/* RF_BPF bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RF_Band_Pass_Filter_byte__RF_BPF = { 0x2E, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register CP_Current_byte 0x2F */ ++const TDA18273_BitField_t gTDA18273_Reg_CP_Current_byte = { 0x2F, 0x00, 0x08, 0x00 }; ++/* LO_CP_Current bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_CP_Current_byte__LO_CP_Current = { 0x2F, 0x07, 0x01, 0x00 }; ++/* N_CP_Current bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_CP_Current_byte__N_CP_Current = { 0x2F, 0x00, 0x07, 0x00 }; ++ ++ ++/* TDA18273 Register AGCs_DetOut_byte 0x30 */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte = { 0x30, 0x00, 0x08, 0x00 }; ++/* Up_AGC5 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Up_AGC5 = { 0x30, 0x07, 0x01, 0x00 }; ++/* Do_AGC5 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Do_AGC5 = { 0x30, 0x06, 0x01, 0x00 }; ++/* Up_AGC4 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Up_AGC4 = { 0x30, 0x05, 0x01, 0x00 }; ++/* Do_AGC4 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Do_AGC4 = { 0x30, 0x04, 0x01, 0x00 }; ++/* Up_AGC2 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Up_AGC2 = { 0x30, 0x03, 0x01, 0x00 }; ++/* Do_AGC2 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Do_AGC2 = { 0x30, 0x02, 0x01, 0x00 }; ++/* Up_AGC1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Up_AGC1 = { 0x30, 0x01, 0x01, 0x00 }; ++/* Do_AGC1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_AGCs_DetOut_byte__Do_AGC1 = { 0x30, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register RFAGCs_Gain_byte_3 0x31 */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_3 = { 0x31, 0x00, 0x08, 0x00 }; ++/* AGC2_Gain_Read bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_3__AGC2_Gain_Read = { 0x31, 0x04, 0x02, 0x00 }; ++/* AGC1_Gain_Read bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_3__AGC1_Gain_Read = { 0x31, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register RFAGCs_Gain_byte_4 0x32 */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_4 = { 0x32, 0x00, 0x08, 0x00 }; ++/* Cprog_Read bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_4__Cprog_Read = { 0x32, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register RFAGCs_Gain_byte_5 0x33 */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_5 = { 0x33, 0x00, 0x08, 0x00 }; ++/* RFAGC_Read_K_8 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_5__RFAGC_Read_K_8 = { 0x33, 0x07, 0x01, 0x00 }; ++/* Do_AGC1bis bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_5__Do_AGC1bis = { 0x33, 0x06, 0x01, 0x00 }; ++/* AGC1_Top_Adapt_Low bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_5__AGC1_Top_Adapt_Low = { 0x33, 0x05, 0x01, 0x00 }; ++/* Up_LNA_Adapt bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_5__Up_LNA_Adapt = { 0x33, 0x04, 0x01, 0x00 }; ++/* Do_LNA_Adapt bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_5__Do_LNA_Adapt = { 0x33, 0x03, 0x01, 0x00 }; ++/* TOP_AGC3_Read bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_5__TOP_AGC3_Read = { 0x33, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register RFAGCs_Gain_byte_6 0x34 */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_6 = { 0x34, 0x00, 0x08, 0x00 }; ++/* RFAGC_Read_K bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RFAGCs_Gain_byte_6__RFAGC_Read_K = { 0x34, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register IFAGCs_Gain_byte 0x35 */ ++const TDA18273_BitField_t gTDA18273_Reg_IFAGCs_Gain_byte = { 0x35, 0x00, 0x08, 0x00 }; ++/* AGC5_Gain_Read bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IFAGCs_Gain_byte__AGC5_Gain_Read = { 0x35, 0x03, 0x03, 0x00 }; ++/* AGC4_Gain_Read bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IFAGCs_Gain_byte__AGC4_Gain_Read = { 0x35, 0x00, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register RSSI_byte_1 0x36 */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_1 = { 0x36, 0x00, 0x08, 0x00 }; ++/* RSSI bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_1__RSSI = { 0x36, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register RSSI_byte_2 0x37 */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_2 = { 0x37, 0x00, 0x08, 0x00 }; ++/* RSSI_AV bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_2__RSSI_AV = { 0x37, 0x05, 0x01, 0x00 }; ++/* RSSI_Cap_Reset_En bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_2__RSSI_Cap_Reset_En = { 0x37, 0x03, 0x01, 0x00 }; ++/* RSSI_Cap_Val bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_2__RSSI_Cap_Val = { 0x37, 0x02, 0x01, 0x00 }; ++/* RSSI_Ck_Speed bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_2__RSSI_Ck_Speed = { 0x37, 0x01, 0x01, 0x00 }; ++/* RSSI_Dicho_not bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_RSSI_byte_2__RSSI_Dicho_not = { 0x37, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register Misc_byte 0x38 */ ++const TDA18273_BitField_t gTDA18273_Reg_Misc_byte = { 0x38, 0x00, 0x08, 0x00 }; ++/* RFCALPOR_I2C bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Misc_byte__RFCALPOR_I2C = { 0x38, 0x06, 0x01, 0x00 }; ++/* PD_Underload bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Misc_byte__PD_Underload = { 0x38, 0x05, 0x01, 0x00 }; ++/* DDS_Polarity bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Misc_byte__DDS_Polarity = { 0x38, 0x04, 0x01, 0x00 }; ++/* IRQ_Mode bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Misc_byte__IRQ_Mode = { 0x38, 0x01, 0x01, 0x00 }; ++/* IRQ_Polarity bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Misc_byte__IRQ_Polarity = { 0x38, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_0 0x39 */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_0 = { 0x39, 0x00, 0x08, 0x00 }; ++/* rfcal_log_0 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_0__rfcal_log_0 = { 0x39, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_1 0x3A */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_1 = { 0x3A, 0x00, 0x08, 0x00 }; ++/* rfcal_log_1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_1__rfcal_log_1 = { 0x3A, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_2 0x3B */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_2 = { 0x3B, 0x00, 0x08, 0x00 }; ++/* rfcal_log_2 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_2__rfcal_log_2 = { 0x3B, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_3 0x3C */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_3 = { 0x3C, 0x00, 0x08, 0x00 }; ++/* rfcal_log_3 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_3__rfcal_log_3 = { 0x3C, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_4 0x3D */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_4 = { 0x3D, 0x00, 0x08, 0x00 }; ++/* rfcal_log_4 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_4__rfcal_log_4 = { 0x3D, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_5 0x3E */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_5 = { 0x3E, 0x00, 0x08, 0x00 }; ++/* rfcal_log_5 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_5__rfcal_log_5 = { 0x3E, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_6 0x3F */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_6 = { 0x3F, 0x00, 0x08, 0x00 }; ++/* rfcal_log_6 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_6__rfcal_log_6 = { 0x3F, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_7 0x40 */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_7 = { 0x40, 0x00, 0x08, 0x00 }; ++/* rfcal_log_7 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_7__rfcal_log_7 = { 0x40, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_8 0x41 */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_8 = { 0x41, 0x00, 0x08, 0x00 }; ++/* rfcal_log_8 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_8__rfcal_log_8 = { 0x41, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_9 0x42 */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_9 = { 0x42, 0x00, 0x08, 0x00 }; ++/* rfcal_log_9 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_9__rfcal_log_9 = { 0x42, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_10 0x43 */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_10 = { 0x43, 0x00, 0x08, 0x00 }; ++/* rfcal_log_10 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_10__rfcal_log_10 = { 0x43, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register rfcal_log_11 0x44 */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_11 = { 0x44, 0x00, 0x08, 0x00 }; ++/* rfcal_log_11 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_rfcal_log_11__rfcal_log_11 = { 0x44, 0x00, 0x08, 0x00 }; ++ ++ ++ ++/* TDA18273 Register Main_Post_Divider_byte 0x51 */ ++const TDA18273_BitField_t gTDA18273_Reg_Main_Post_Divider_byte = { 0x51, 0x00, 0x08, 0x00 }; ++/* LOPostDiv bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Main_Post_Divider_byte__LOPostDiv = { 0x51, 0x04, 0x03, 0x00 }; ++/* LOPresc bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Main_Post_Divider_byte__LOPresc = { 0x51, 0x00, 0x04, 0x00 }; ++ ++ ++/* TDA18273 Register Sigma_delta_byte_1 0x52 */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_1 = { 0x52, 0x00, 0x08, 0x00 }; ++/* LO_Int bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_1__LO_Int = { 0x52, 0x00, 0x07, 0x00 }; ++ ++ ++/* TDA18273 Register Sigma_delta_byte_2 0x53 */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_2 = { 0x53, 0x00, 0x08, 0x00 }; ++/* LO_Frac_2 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_2__LO_Frac_2 = { 0x53, 0x00, 0x07, 0x00 }; ++ ++ ++/* TDA18273 Register Sigma_delta_byte_3 0x54 */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_3 = { 0x54, 0x00, 0x08, 0x00 }; ++/* LO_Frac_1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_3__LO_Frac_1 = { 0x54, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register Sigma_delta_byte_4 0x55 */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_4 = { 0x55, 0x00, 0x08, 0x00 }; ++/* LO_Frac_0 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_4__LO_Frac_0 = { 0x55, 0x00, 0x08, 0x00 }; ++ ++ ++/* TDA18273 Register Sigma_delta_byte_5 0x56 */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_5 = { 0x56, 0x00, 0x08, 0x00 }; ++/* N_K_correct_manual bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_5__N_K_correct_manual = { 0x56, 0x01, 0x01, 0x00 }; ++/* LO_Calc_Disable bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Sigma_delta_byte_5__LO_Calc_Disable = { 0x56, 0x00, 0x01, 0x00 }; ++ ++ ++/* TDA18273 Register Regulators_byte 0x58 */ ++const TDA18273_BitField_t gTDA18273_Reg_Regulators_byte = { 0x58, 0x00, 0x08, 0x00 }; ++/* RF_Reg bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Regulators_byte__RF_Reg = { 0x58, 0x02, 0x02, 0x00 }; ++ ++ ++/* TDA18273 Register IR_Cal_byte_5 0x5B */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Cal_byte_5 = { 0x5B, 0x00, 0x08, 0x00 }; ++/* Mixer_Gain_Bypass bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Cal_byte_5__Mixer_Gain_Bypass = { 0x5B, 0x07, 0x01, 0x00 }; ++/* IR_Mixer_Gain bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_IR_Cal_byte_5__IR_Mixer_Gain = { 0x5B, 0x04, 0x03, 0x00 }; ++ ++ ++/* TDA18273 Register Power_Down_byte_2 0x5F */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_2 = { 0x5F, 0x00, 0x08, 0x00 }; ++/* PD_LNA bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_2__PD_LNA = { 0x5F, 0x07, 0x01, 0x00 }; ++/* PD_Det4 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_2__PD_Det4 = { 0x5F, 0x03, 0x01, 0x00 }; ++/* PD_Det3 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_2__PD_Det3 = { 0x5F, 0x02, 0x01, 0x00 }; ++/* PD_Det1 bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_2__PD_Det1 = { 0x5F, 0x00, 0x01, 0x00 }; ++ ++/* TDA18273 Register Power_Down_byte_3 0x60 */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_3 = { 0x60, 0x00, 0x08, 0x00 }; ++/* Force_Soft_Reset bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_3__Force_Soft_Reset = { 0x60, 0x01, 0x01, 0x00 }; ++/* Soft_Reset bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Power_Down_byte_3__Soft_Reset = { 0x60, 0x00, 0x01, 0x00 }; ++ ++/* TDA18273 Register Charge_pump_byte 0x64 */ ++const TDA18273_BitField_t gTDA18273_Reg_Charge_pump_byte = { 0x64, 0x00, 0x08, 0x00 }; ++/* ICP_Bypass bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Charge_pump_byte__ICP_Bypass = { 0x64, 0x07, 0x01, 0x00 }; ++/* ICP bit(s): */ ++const TDA18273_BitField_t gTDA18273_Reg_Charge_pump_byte__ICP = { 0x64, 0x00, 0x02, 0x00 }; ++ ++ ++static int tda18273_readreg(struct tda18273_state *priv, unsigned char reg, unsigned char *val) ++{ ++ int ret = TDA_RESULT_SUCCESS; ++ struct dvb_frontend *fe = priv->fe; ++ ++ struct i2c_msg msg[2] = { ++ { .addr = priv->i2c_addr, ++ .flags = 0, .buf = ®, .len = 1}, ++ { .addr = priv->i2c_addr, ++ .flags = I2C_M_RD, .buf = val, .len = 1}, ++ }; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ ++ ret = i2c_transfer(priv->i2c, msg, 2); ++ ++ if (ret != 2) { ++ dprintk(FE_ERROR, 1, "I2C read failed"); ++ ret = TDA_RESULT_I2C_READ_FAILURE; ++ } ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return ret; ++} ++ ++static int tda18273_readregs(struct tda18273_state *priv, const TDA18273_BitField_t* pBitField, unsigned char *val, tmbslFrontEndBusAccess_t eBusAccess) ++{ ++ unsigned char RegAddr = 0; ++ unsigned char RegMask = 0; ++ unsigned char RegData = 0; ++ unsigned char* pRegData = NULL; ++ ++ RegAddr = pBitField->Address; ++ ++ if(RegAddr < TDA18273_REG_MAP_NB_BYTES) { ++ pRegData = (unsigned char *)(&(priv->regmap)) + RegAddr; ++ } else { ++ pRegData = &RegData; ++ } ++ ++ if((eBusAccess & Bus_NoRead) == 0x00) { ++ if(tda18273_readreg(priv, RegAddr, pRegData) == TDA_RESULT_I2C_READ_FAILURE) { ++ return TDA_RESULT_I2C_READ_FAILURE; ++ } ++ } ++ ++ *val = *pRegData; ++ ++ RegMask = ((1 << pBitField->WidthInBits) - 1) << pBitField->PositionInBits; ++ ++ *val &= RegMask; ++ *val = (*val) >> pBitField->PositionInBits; ++ ++ return TDA_RESULT_SUCCESS; ++} ++ ++static int tda18273_readregmap(struct tda18273_state *priv, unsigned char reg, unsigned int len) ++{ ++ int ret, i; ++ unsigned char* pRegData = NULL; ++ ++ if((reg < TDA18273_REG_MAP_NB_BYTES) && ((reg + len) <= TDA18273_REG_MAP_NB_BYTES)) { ++ pRegData = (unsigned char *)(&(priv->regmap)) + reg; ++ ++ for(i=0; ife; ++ unsigned char tmp[2] = {reg, val}; ++ ++ struct i2c_msg msg = { ++ .addr = priv->i2c_addr, ++ .flags = 0, .buf = tmp, .len = 2}; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ ++ ret = i2c_transfer(priv->i2c, &msg, 1); ++ ++ if (ret != 1) { ++ dprintk(FE_ERROR, 1, "I2C write failed"); ++ ret = TDA_RESULT_I2C_READ_FAILURE; ++ } ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return ret; ++} ++ ++static int tda18273_writeregs(struct tda18273_state *priv, const TDA18273_BitField_t* pBitField, unsigned char val, tmbslFrontEndBusAccess_t eBusAccess) ++{ ++ unsigned char RegAddr = 0; ++ unsigned char RegData = 0; ++ unsigned char RegMask = 0; ++ unsigned char* pRegData = NULL; ++ ++ RegAddr = pBitField->Address; ++ ++ if(RegAddr < TDA18273_REG_MAP_NB_BYTES) { ++ pRegData = (unsigned char *)(&(priv->regmap)) + RegAddr; ++ } else { ++ pRegData = &RegData; ++ } ++ ++ if((eBusAccess & Bus_NoRead) == 0x00) { ++ if(tda18273_readreg(priv, RegAddr, pRegData) == TDA_RESULT_I2C_READ_FAILURE) { ++ return TDA_RESULT_I2C_READ_FAILURE; ++ } ++ } ++ ++ RegMask = (1 << pBitField->WidthInBits) - 1; ++ val &= RegMask; ++ ++ RegMask = RegMask << pBitField->PositionInBits; ++ *pRegData &= (UInt8)(~RegMask); ++ *pRegData |= val << pBitField->PositionInBits; ++ ++ if((eBusAccess & Bus_NoWrite) == 0x00) { ++ if(tda18273_writereg(priv, RegAddr, *pRegData) == TDA_RESULT_I2C_READ_FAILURE) { ++ return TDA_RESULT_I2C_READ_FAILURE; ++ } ++ } ++ ++ return TDA_RESULT_SUCCESS; ++} ++ ++static int tda18273_writeregmap(struct tda18273_state *priv, unsigned char reg, unsigned int len) ++{ ++ int ret, i; ++ unsigned char* pRegData = NULL; ++ ++ if((reg < TDA18273_REG_MAP_NB_BYTES) && ((reg + len) <= TDA18273_REG_MAP_NB_BYTES)) { ++ pRegData = (unsigned char *)(&(priv->regmap)) + reg; ++ ++ for(i=0; i data : 0x%02x", i, val); ++ } ++} ++ ++static int tda18273_get_lock_status(struct tda18273_state *priv, unsigned short *lock_status) ++{ ++ int ret; ++ unsigned char val=0; ++ unsigned char val_lo=0; ++ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Power_state_byte_1__LO_Lock, &val_lo, Bus_RW); ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_IRQ_status__IRQ_status, &val, Bus_RW); ++ *lock_status = val & val_lo; ++ ++ dprintk(FE_INFO, 1, "lock=0x%02X/0x%02x, lock_status=0x%x", val, val_lo, *lock_status); ++ ++ return 0; ++} ++ ++static int tda18273_pwr_state(struct dvb_frontend *fe, int pwr_state) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ int ret=0; ++ ++ if(priv->power_state != pwr_state) { ++ if(pwr_state == tmPowerOn) { ++ /* Set TDA18273 power state to Normal Mode */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_2__PD_LNA, 0x1, Bus_RW); /* PD LNA */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_2__PD_Det1, 0x1, Bus_NoRead); /* PD Detector AGC1 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_3__AGC1_loop_off, 0x1, Bus_RW); /* AGC1 Detector loop off */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_state_byte_2, TDA18273_SM_NONE, Bus_RW); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode, 0x03, Bus_RW); /* Set digital clock mode to sub-LO if normal mode is entered */ ++ } else if(pwr_state == tmPowerStandby) { ++ /* Set TDA18273 power state to standby with Xtal ON */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode, 0x00, Bus_RW); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_state_byte_2, 0x02, Bus_RW); ++ } ++ ++ priv->power_state = pwr_state; ++ } ++ ++ return 0; ++} ++ ++static int tda18273_firstpass_lnapwr(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ int ret; ++ ++ /* PD LNA */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_2__PD_LNA, 0x1, Bus_RW); ++ /* PD Detector AGC1 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_2__PD_Det1, 0x1, Bus_NoRead); ++ /* AGC1 Detector loop off */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_3__AGC1_loop_off, 0x1, Bus_RW); ++ ++ return 0; ++} ++ ++static int tda18273_lastpass_lnapwr(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ unsigned char val = 0; ++ int ret; ++ ++ /* Check if LNA is PD */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Power_Down_byte_2__PD_LNA, &val, Bus_NoWrite); ++ ++ if(val == 1) { ++ /* LNA is Powered Down, so power it up */ ++ /* Force gain to -10dB */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_3__AGC1_Gain, 0x0, Bus_RW); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_3__Force_AGC1_gain, 0x1, Bus_NoRead); ++ /* PD LNA */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_2__PD_LNA, 0x0, Bus_NoRead); ++ /* Release LNA gain control */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_3__Force_AGC1_gain, 0x0, Bus_NoRead); ++ /* PD Detector AGC1 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_2__PD_Det1, 0x0, Bus_NoRead); ++ /* AGC1 Detector loop off */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_3__AGC1_loop_off, 0x0, Bus_NoRead); ++ } ++ ++ return 0; ++} ++ ++static int tda18273_llpwr_state(struct dvb_frontend *fe, int llpwr_state) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ unsigned char val = 0; ++ int ret; ++ ++ if(llpwr_state == TDA18273_PowerNormalMode) { ++ /* If we come from any standby mode, then power on the IC with LNA off */ ++ /* Then powering on LNA with the minimal gain on AGC1 to avoid glitches at RF input will */ ++ /* be done during SetRF */ ++ ++ /* Workaround to limit the spurs occurence on RF input, do it before entering normal mode */ ++ /* PD LNA */ ++ ret = tda18273_firstpass_lnapwr(fe); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_state_byte_2, TDA18273_SM_NONE, Bus_RW); ++ /* Set digital clock mode to sub-LO if normal mode is entered */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode, 0x03, Bus_RW); ++ ++ /* Reset val to use it as a flag for below test */ ++ val = 0; ++ } else if(llpwr_state == TDA18273_PowerStandbyWithXtalOn) { ++ val = TDA18273_SM; ++ } else if(llpwr_state == TDA18273_PowerStandby) { ++ /* power state not supported */ ++ val = TDA18273_SM|TDA18273_SM_XT; ++ } ++ ++ if(val) { ++ /* Set digital clock mode to 16 Mhz before entering standby */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode, 0x00, Bus_RW); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_state_byte_2, val, Bus_RW); ++ } ++ ++ return 0; ++} ++ ++static int tda18273_check_calcpll(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ int ret; ++ unsigned char val; ++ ++ /* Check if Calc_PLL algorithm is in automatic mode */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Sigma_delta_byte_5__LO_Calc_Disable, &val, Bus_None); ++ ++ if(val != 0x00) { ++ /* Enable Calc_PLL algorithm by putting PLL in automatic mode */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_5__N_K_correct_manual, 0x00, Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_5__LO_Calc_Disable, 0x00, Bus_NoRead); ++ } ++ ++ return 0; ++} ++ ++static int tda18273_set_msm(struct dvb_frontend *fe, unsigned char val, int launch) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ int ret; ++ ++ /* Set state machine and Launch it */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_MSM_byte_1, val, Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_MSM_byte_2__MSM_Launch, 0x01, Bus_None); ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_MSM_byte_1.Address, (launch ? 0x02 : 0x01)); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_MSM_byte_2__MSM_Launch, 0x00, Bus_None); ++ ++ return 0; ++} ++ ++static int tda18273_override_bandsplit(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ int ret; ++ unsigned char Bandsplit = 0; ++ unsigned char uPrevPSM_Bandsplit_Filter = 0; ++ unsigned char PSM_Bandsplit_Filter = 0; ++ ++ /* Setting PSM bandsplit at -3.9 mA for some RF frequencies */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Bandsplit_Filter_byte__Bandsplit_Filter_SubBand, &Bandsplit, Bus_None); ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_PowerSavingMode__PSM_Bandsplit_Filter, &uPrevPSM_Bandsplit_Filter, Bus_None); ++ ++ switch(Bandsplit) ++ { ++ default: ++ case 0: /* LPF0 133MHz - LPF1 206MHz - HPF0 422MHz */ ++ if(priv->pObj->uProgRF < 133000000) { ++ /* Set PSM bandsplit at -3.9 mA */ ++ PSM_Bandsplit_Filter = 0x03; ++ } else { ++ /* Set PSM bandsplit at nominal */ ++ PSM_Bandsplit_Filter = 0x02; ++ } ++ break; ++ case 1: /* LPF0 139MHz - LPF1 218MHz - HPF0 446MHz */ ++ if(priv->pObj->uProgRF < 139000000) { ++ /* Set PSM bandsplit at -3.9 mA */ ++ PSM_Bandsplit_Filter = 0x03; ++ } else { ++ /* Set PSM bandsplit at nominal */ ++ PSM_Bandsplit_Filter = 0x02; ++ } ++ break; ++ case 2: /* LPF0 145MHz - LPF1 230MHz - HPF0 470MHz */ ++ if(priv->pObj->uProgRF < 145000000) { ++ /* Set PSM bandsplit at -3.9 mA */ ++ PSM_Bandsplit_Filter = 0x03; ++ } else { ++ /* Set PSM bandsplit at nominal */ ++ PSM_Bandsplit_Filter = 0x02; ++ } ++ break; ++ case 3: /* LPF0 151MHz - LPF1 242MHz - HPF0 494MHz */ ++ if(priv->pObj->uProgRF < 151000000) { ++ /* Set PSM bandsplit at -3.9 mA */ ++ PSM_Bandsplit_Filter = 0x03; ++ } else { ++ /* Set PSM bandsplit at nominal */ ++ PSM_Bandsplit_Filter = 0x02; ++ } ++ break; ++ } ++ ++ if(uPrevPSM_Bandsplit_Filter != PSM_Bandsplit_Filter) { ++ /* Write PSM bandsplit */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_PowerSavingMode__PSM_Bandsplit_Filter, PSM_Bandsplit_Filter, Bus_NoRead); ++ } ++ ++ return 0; ++} ++ ++static int tda18273_set_standardmode(struct dvb_frontend *fe, TDA18273StandardMode_t StandardMode) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ int ret; ++ ++ unsigned char wantedValue=0; ++ unsigned char checked=0; ++ ++ priv->pObj->StandardMode = StandardMode; ++ ++ if((priv->pObj->StandardMode > TDA18273_StandardMode_Unknown) && (priv->pObj->StandardMode < TDA18273_StandardMode_Max)) { ++ /* Update standard map pointer */ ++ priv->pObj->pStandard = &priv->pObj->Std_Array[priv->pObj->StandardMode - 1]; ++ ++ /****************************************************************/ ++ /* IF SELECTIVITY Settings */ ++ /****************************************************************/ ++ /* Set LPF */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IF_Byte_1__LP_Fc, priv->pObj->pStandard->LPF, Bus_None); ++ /* Set LPF Offset */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IF_Byte_1__LP_FC_Offset, priv->pObj->pStandard->LPF_Offset, Bus_None); ++ /* Set DC_Notch_IF_PPF */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IR_Mixer_byte_2__IF_Notch, priv->pObj->pStandard->DC_Notch_IF_PPF, Bus_None); ++ /* Enable/disable HPF */ ++ if(priv->pObj->pStandard->IF_HPF == TDA18273_IF_HPF_Disabled) { ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IR_Mixer_byte_2__Hi_Pass, 0x00, Bus_None); ++ } else { ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IR_Mixer_byte_2__Hi_Pass, 0x01, Bus_None); ++ /* Set IF HPF */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IF_Byte_1__IF_HP_Fc, (UInt8)(priv->pObj->pStandard->IF_HPF - 1), Bus_None); ++ } ++ /* Set IF Notch */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IF_Byte_1__IF_ATSC_Notch, priv->pObj->pStandard->IF_Notch, Bus_None); ++ /* Set IF notch to RSSI */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IF_AGC_byte__IFnotchToRSSI, priv->pObj->pStandard->IFnotchToRSSI, Bus_None); ++ ++ /****************************************************************/ ++ /* AGC TOP Settings */ ++ /****************************************************************/ ++ /* Set AGC1 TOP I2C DN/UP */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_1__AGC1_TOP, priv->pObj->pStandard->AGC1_TOP_I2C_DN_UP, Bus_None); ++ /* Set AGC1 Adapt TOP DN/UP */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_2__AGC1_Top_Mode_Val, priv->pObj->pStandard->AGC1_Adapt_TOP_DN_UP, Bus_None); ++ /* Set AGC1 DN Time Constant */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_3__AGC1_Do_step, priv->pObj->pStandard->AGC1_DN_Time_Constant, Bus_None); ++ /* Set AGC1 mode */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC1_byte_2__AGC1_Top_Mode, priv->pObj->pStandard->AGC1_Mode, Bus_None); ++ /* Set Range_LNA_Adapt */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Adapt_Top_byte__Range_LNA_Adapt, priv->pObj->pStandard->Range_LNA_Adapt, Bus_None); ++ /* Set LNA_Adapt_RFAGC_Gv_Threshold */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Adapt_Top_byte__Index_K_LNA_Adapt, priv->pObj->pStandard->LNA_Adapt_RFAGC_Gv_Threshold, Bus_None); ++ /* Set AGC1_Top_Adapt_RFAGC_Gv_Threshold */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Adapt_Top_byte__Index_K_Top_Adapt, priv->pObj->pStandard->AGC1_Top_Adapt_RFAGC_Gv_Threshold, Bus_None); ++ /* Set AGC2 TOP DN/UP */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC2_byte_1__AGC2_TOP, priv->pObj->pStandard->AGC2_TOP_DN_UP, Bus_None); ++ /* Set AGC2 DN Time Constant */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Filters_byte_3__AGC2_Do_step, priv->pObj->pStandard->AGC2_DN_Time_Constant, Bus_None); ++ /* Set AGC4 TOP DN/UP */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IR_Mixer_byte_1__IR_Mixer_Top, priv->pObj->pStandard->AGC4_TOP_DN_UP, Bus_None); ++ /* Set AGC5 TOP DN/UP */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC5_byte_1__AGC5_TOP, priv->pObj->pStandard->AGC5_TOP_DN_UP, Bus_None); ++ /* Set AGC3_Top_Adapt_Algorithm */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_AGC_byte__PD_AGC_Adapt3x, priv->pObj->pStandard->AGC3_Top_Adapt_Algorithm, Bus_None); ++ /* Set AGC Overload TOP */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Vsync_Mgt_byte__AGC_Ovld_TOP, priv->pObj->pStandard->AGC_Overload_TOP, Bus_None); ++ /* Set Adapt TOP 34 Gain Threshold */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RFAGCs_Gain_byte_1__TH_AGC_Adapt34, priv->pObj->pStandard->TH_AGC_Adapt34, Bus_None); ++ /* Set RF atten 3dB */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_W_Filter_byte__RF_Atten_3dB, priv->pObj->pStandard->RF_Atten_3dB, Bus_None); ++ /* Set IF Output Level */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IF_AGC_byte__IF_level, priv->pObj->pStandard->IF_Output_Level, Bus_None); ++ /* Set S2D gain */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IR_Mixer_byte_1__S2D_Gain, priv->pObj->pStandard->S2D_Gain, Bus_None); ++ /* Set Negative modulation, write into register directly because vsync_int bit is checked afterwards */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Vsync_byte__Neg_modulation, priv->pObj->pStandard->Negative_Modulation, Bus_RW); ++ ++ /****************************************************************/ ++ /* GSK Settings */ ++ /****************************************************************/ ++ /* Set AGCK Step */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGCK_byte_1__AGCK_Step, priv->pObj->pStandard->AGCK_Steps, Bus_None); ++ /* Set AGCK Time Constant */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGCK_byte_1__AGCK_Mode, priv->pObj->pStandard->AGCK_Time_Constant, Bus_None); ++ /* Set AGC5 HPF */ ++ wantedValue = priv->pObj->pStandard->AGC5_HPF; ++ if(priv->pObj->pStandard->AGC5_HPF == TDA18273_AGC5_HPF_Enabled) { ++ /* Check if Internal Vsync is selected */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Vsync_byte__Vsync_int, &checked, Bus_RW); ++ ++ if(checked == 0) { ++ /* Internal Vsync is OFF, so override setting to OFF */ ++ wantedValue = TDA18273_AGC5_HPF_Disabled; ++ } ++ } ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGC5_byte_1__AGC5_Ana, wantedValue, Bus_None); ++ /* Set Pulse Shaper Disable */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_AGCK_byte_1__Pulse_Shaper_Disable, priv->pObj->pStandard->Pulse_Shaper_Disable, Bus_None); ++ ++ /****************************************************************/ ++ /* H3H5 Settings */ ++ /****************************************************************/ ++ /* Set VHF_III_Mode */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_W_Filter_byte__VHF_III_mode, priv->pObj->pStandard->VHF_III_Mode, Bus_None); ++ ++ /****************************************************************/ ++ /* PLL Settings */ ++ /****************************************************************/ ++ /* Set LO_CP_Current */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_CP_Current_byte__LO_CP_Current, priv->pObj->pStandard->LO_CP_Current, Bus_None); ++ ++ /****************************************************************/ ++ /* IF Settings */ ++ /****************************************************************/ ++ /* Set IF */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IF_Frequency_byte__IF_Freq, (UInt8)((priv->pObj->pStandard->IF - priv->pObj->pStandard->CF_Offset)/50000), Bus_None); ++ ++ /****************************************************************/ ++ /* MISC Settings */ ++ /****************************************************************/ ++ /* Set PD Underload */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Misc_byte__PD_Underload, priv->pObj->pStandard->PD_Underload, Bus_None); ++ ++ /****************************************************************/ ++ /* Update Registers */ ++ /****************************************************************/ ++ /* Write AGC1_byte_1 (0x0C) to IF_Byte_1 (0x15) Registers */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_AGC1_byte_1.Address, TDA18273_REG_DATA_LEN(gTDA18273_Reg_AGC1_byte_1, gTDA18273_Reg_IF_Byte_1)); ++ /* Write IF_Frequency_byte (0x17) Register */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_IF_Frequency_byte.Address, 1); ++ /* Write Adapt_Top_byte (0x1F) Register */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_Adapt_Top_byte.Address, 1); ++ /* Write Vsync_byte (0x20) to RFAGCs_Gain_byte_1 (0x24) Registers */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_Vsync_byte.Address, TDA18273_REG_DATA_LEN(gTDA18273_Reg_Vsync_byte, gTDA18273_Reg_RFAGCs_Gain_byte_1)); ++ /* Write RF_Filters_byte_3 (0x2D) Register */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_RF_Filters_byte_3.Address, 1); ++ /* Write CP_Current_byte (0x2F) Register */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_CP_Current_byte.Address, 1); ++ /* Write Misc_byte (0x38) Register */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_Misc_byte.Address, 1); ++ } ++ ++ return 0; ++} ++ ++typedef struct _TDA18273_PostDivPrescalerTableDef_ ++{ ++ unsigned int LO_max; ++ unsigned int LO_min; ++ unsigned char Prescaler; ++ unsigned char PostDiv; ++} TDA18273_PostDivPrescalerTableDef; ++ ++/* Table that maps LO vs Prescaler & PostDiv values */ ++static TDA18273_PostDivPrescalerTableDef PostDivPrescalerTable[35] = ++{ ++ /* PostDiv 1 */ ++ {974000, 852250, 7, 1}, ++ {852250, 745719, 8, 1}, ++ {757556, 662861, 9, 1}, ++ {681800, 596575, 10, 1}, ++ {619818, 542341, 11, 1}, ++ {568167, 497146, 12, 1}, ++ {524462, 458904, 13, 1}, ++ /* PostDiv 2 */ ++ {487000, 426125, 7, 2}, ++ {426125, 372859, 8, 2}, ++ {378778, 331431, 9, 2}, ++ {340900, 298288, 10, 2}, ++ {309909, 271170, 11, 2}, ++ {284083, 248573, 12, 2}, ++ {262231, 229452, 13, 2}, ++ /* PostDiv 4 */ ++ {243500, 213063, 7, 4}, ++ {213063, 186430, 8, 4}, ++ {189389, 165715, 9, 4}, ++ {170450, 149144, 10, 4}, ++ {154955, 135585, 11, 4}, ++ {142042, 124286, 12, 4}, ++ {131115, 114726, 13, 4}, ++ /* PostDiv 8 */ ++ {121750, 106531, 7, 8}, ++ {106531, 93215, 8, 8}, ++ {94694, 82858, 9, 8}, ++ {85225, 74572, 10, 8}, ++ {77477, 67793, 11, 8}, ++ {71021, 62143, 12, 8}, ++ {65558, 57363, 13, 8}, ++ /* PostDiv 16 */ ++ {60875, 53266, 7, 16}, ++ {53266, 46607, 8, 16}, ++ {47347, 41429, 9, 16}, ++ {42613, 37286, 10, 16}, ++ {38739, 33896, 11, 16}, ++ {35510, 31072, 12, 16}, ++ {32779, 28681, 13, 16} ++}; ++ ++static int tda18273_calculate_postdivandprescaler(unsigned int LO, int growingOrder, unsigned char* PostDiv, unsigned char* Prescaler) ++{ ++ int ret = 0; ++ ++ unsigned char index; ++ unsigned char sizeTable = sizeof(PostDivPrescalerTable) / sizeof(TDA18273_PostDivPrescalerTableDef); ++ ++ if(growingOrder == 1) { ++ /* Start from LO = 28.681 kHz */ ++ for(index=(sizeTable-1); index>=0; index--) { ++ if((LO > PostDivPrescalerTable[index].LO_min) && (LO < PostDivPrescalerTable[index].LO_max)) { ++ /* We are at correct index in the table */ ++ break; ++ } ++ } ++ } else { ++ /* Start from LO = 974000 kHz */ ++ for(index=0; index PostDivPrescalerTable[index].LO_min) && (LO < PostDivPrescalerTable[index].LO_max)) { ++ /* We are at correct index in the table */ ++ break; ++ } ++ } ++ } ++ ++ if((index == -1) || (index == sizeTable)) { ++ ret = -1; ++ } else { ++ /* Write Prescaler */ ++ *Prescaler = PostDivPrescalerTable[index].Prescaler; ++ ++ /* Decode PostDiv */ ++ *PostDiv = PostDivPrescalerTable[index].PostDiv; ++ } ++ ++ return ret; ++} ++ ++/* Middle of VCO frequency excursion : VCOmin + (VCOmax - VCOmin)/2 in KHz */ ++#define TDA18273_MIDDLE_FVCO_RANGE ((6818000 - 5965750) / 2 + 5965750) ++ ++static int tda18273_find_postdivandprescalerwithbettermargin(unsigned int LO, unsigned char* PostDiv, unsigned char* Prescaler) ++{ ++ int ret; ++ ++ unsigned char PostDivGrowing; ++ unsigned char PrescalerGrowing; ++ unsigned char PostDivDecreasing = 0; ++ unsigned char PrescalerDecreasing = 0; ++ unsigned int FCVOGrowing = 0; ++ unsigned int DistanceFCVOGrowing = 0; ++ unsigned int FVCODecreasing = 0; ++ unsigned int DistanceFVCODecreasing = 0; ++ ++ /* Get the 2 possible values for PostDiv & Prescaler to find the one ++ which provides the better margin on LO */ ++ ret = tda18273_calculate_postdivandprescaler(LO, 1, &PostDivGrowing, &PrescalerGrowing); ++ if(ret != -1) { ++ /* Calculate corresponding FVCO value in kHz */ ++ FCVOGrowing = LO * PrescalerGrowing * PostDivGrowing; ++ } ++ ++ ret = tda18273_calculate_postdivandprescaler(LO, 0, &PostDivDecreasing, &PrescalerDecreasing); ++ if(ret != -1) { ++ /* Calculate corresponding FVCO value in kHz */ ++ FVCODecreasing = LO * PrescalerDecreasing * PostDivDecreasing; ++ } ++ ++ /* Now take the values that are providing the better margin, the goal is +-2 MHz on LO */ ++ /* So take the point that is the nearest of (FVCOmax - FVCOmin)/2 = 6391,875 MHz */ ++ if(FCVOGrowing != 0) { ++ if(FCVOGrowing >= TDA18273_MIDDLE_FVCO_RANGE) { ++ DistanceFCVOGrowing = FCVOGrowing - TDA18273_MIDDLE_FVCO_RANGE; ++ } else { ++ DistanceFCVOGrowing = TDA18273_MIDDLE_FVCO_RANGE - FCVOGrowing; ++ } ++ } ++ ++ if(FVCODecreasing != 0) { ++ if(FVCODecreasing >= TDA18273_MIDDLE_FVCO_RANGE) { ++ DistanceFVCODecreasing = FVCODecreasing - TDA18273_MIDDLE_FVCO_RANGE; ++ } else { ++ DistanceFVCODecreasing = TDA18273_MIDDLE_FVCO_RANGE - FVCODecreasing; ++ } ++ } ++ ++ if(FCVOGrowing == 0) { ++ if(FVCODecreasing == 0) { ++ /* No value at all are found */ ++ ret = -1; ++ } else { ++ /* No value in growing mode, so take the decreasing ones */ ++ *PostDiv = PostDivDecreasing; ++ *Prescaler = PrescalerDecreasing; ++ } ++ } else { ++ if(FVCODecreasing == 0) { ++ /* No value in decreasing mode, so take the growing ones */ ++ *PostDiv = PostDivGrowing; ++ *Prescaler = PrescalerGrowing; ++ } else { ++ /* Find the value which are the nearest of the middle of VCO range */ ++ if(DistanceFCVOGrowing <= DistanceFVCODecreasing) { ++ *PostDiv = PostDivGrowing; ++ *Prescaler = PrescalerGrowing; ++ } else { ++ *PostDiv = PostDivDecreasing; ++ *Prescaler = PrescalerDecreasing; ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++static int tda18273_calculate_nintkint(unsigned int LO, unsigned char PostDiv, unsigned char Prescaler, unsigned int* NInt, unsigned int* KInt) ++{ ++ /* Algorithm that calculates N_K */ ++ unsigned int FVCO = 0; ++ unsigned int N_K_prog = 0; ++ ++ /* Algorithm that calculates N, K corrected */ ++ unsigned int Nprime = 0; ++ unsigned int KforceK0_1 = 0; ++ unsigned int K2msb = 0; ++ unsigned int N0 = 0; ++ unsigned int Nm1 = 0; ++ ++ /* Calculate N_K_Prog */ ++ FVCO = LO * Prescaler * PostDiv; ++ N_K_prog = (FVCO * 128) / 125; ++ ++ /* Calculate N & K corrected values */ ++ Nprime = N_K_prog & 0xFF0000; ++ ++ /* Force LSB to 1 */ ++ KforceK0_1 = 2*(((N_K_prog - Nprime) << 7) / 2) + 1; ++ ++ /* Check MSB bit around 2 */ ++ K2msb = KforceK0_1 >> 21; ++ if(K2msb < 1) { ++ N0 = 1; ++ } else { ++ if (K2msb >= 3) { ++ N0 = 1; ++ } else { ++ N0 = 0; ++ } ++ } ++ ++ if(K2msb < 1) { ++ Nm1 = 1; ++ } else { ++ Nm1 = 0; ++ } ++ ++ /* Calculate N */ ++ *NInt = (2 * ((Nprime >> 16) - Nm1) + N0) - 128; ++ ++ /* Calculate K */ ++ if(K2msb < 1) { ++ *KInt = KforceK0_1 + (2 << 21); ++ } else { ++ if (K2msb >= 3) { ++ *KInt = KforceK0_1 - (2 << 21); ++ } else { ++ *KInt = KforceK0_1; ++ } ++ } ++ ++ /* Force last 7 bits of K_int to 0x5D, as the IC is doing for spurs optimization */ ++ *KInt &= 0xFFFFFF80; ++ *KInt |= 0x5D; ++ ++ return 0; ++} ++ ++ ++static int tda18273_set_pll(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ int ret; ++ ++ /* LO wanted = RF wanted + IF in KHz */ ++ unsigned int LO = 0; ++ ++ /* Algorithm that calculates PostDiv */ ++ unsigned char PostDiv = 0; /* absolute value */ ++ unsigned char LOPostDiv = 0; /* register value */ ++ ++ /* Algorithm that calculates Prescaler */ ++ unsigned char Prescaler = 0; ++ ++ /* Algorithm that calculates N, K */ ++ unsigned int N_int = 0; ++ unsigned int K_int = 0; ++ ++ /* Calculate wanted LO = RF + IF in Hz */ ++ LO = (priv->pObj->uRF + priv->pObj->uIF) / 1000; ++ ++ /* Calculate the best PostDiv and Prescaler : the ones that provide the best margin */ ++ /* in case of fine tuning +-2 MHz */ ++ ret = tda18273_find_postdivandprescalerwithbettermargin(LO, &PostDiv, &Prescaler); ++ ++ if(ret != -1) { ++ /* Program the PLL only if valid values are found, in that case err == TM_OK */ ++ /* Decode PostDiv */ ++ switch(PostDiv) { ++ case 1: LOPostDiv = 1; break; ++ case 2: LOPostDiv = 2; break; ++ case 4: LOPostDiv = 3; break; ++ case 8: LOPostDiv = 4; break; ++ case 16: LOPostDiv = 5; break; ++ default: dprintk(FE_INFO, 1, "%s *PostDiv value is wrong.", __func__); break; ++ } ++ ++ /* Affect register map without writing into IC */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Main_Post_Divider_byte__LOPostDiv, LOPostDiv, Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Main_Post_Divider_byte__LOPresc, Prescaler, Bus_None); ++ /* Calculate N & K values of the PLL */ ++ ret = tda18273_calculate_nintkint(LO, PostDiv, Prescaler, &N_int, &K_int); ++ /* Affect registers map without writing to IC */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_4__LO_Frac_0, (UInt8)(K_int & 0xFF), Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_3__LO_Frac_1, (UInt8)((K_int >> 8) & 0xFF), Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_2__LO_Frac_2, (UInt8)((K_int >> 16) & 0xFF), Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_1__LO_Int, (UInt8)(N_int & 0xFF), Bus_None); ++ /* Force manual selection mode : 0x3 at @0x56 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_5__N_K_correct_manual, 0x01, Bus_None); ++ /* Force manual selection mode : 0x3 at @0x56 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Sigma_delta_byte_5__LO_Calc_Disable, 0x01, Bus_None); ++ /* Write bytes Main_Post_Divider_byte (0x51) to Sigma_delta_byte_5 (0x56) */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_Main_Post_Divider_byte.Address, TDA18273_REG_DATA_LEN(gTDA18273_Reg_Main_Post_Divider_byte, gTDA18273_Reg_Sigma_delta_byte_5)); ++ } ++ ++ return 0; ++} ++ ++static int tda18273_override_icp(struct dvb_frontend *fe, unsigned int uRF) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ int ret; ++ unsigned int uIF = 0; ++ unsigned char ProgIF = 0; ++ unsigned char LOPostdiv = 0; ++ unsigned char LOPrescaler = 0; ++ unsigned int FVCO = 0; ++ unsigned char uICPBypass = 0; ++ unsigned char ICP = 0; ++ unsigned char uPrevICP = 0; ++ ++ /* Read PostDiv et Prescaler */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Main_Post_Divider_byte, &LOPostdiv, Bus_RW); ++ /* PostDiv */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Main_Post_Divider_byte__LOPostDiv, &LOPostdiv, Bus_NoRead); ++ /* Prescaler */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Main_Post_Divider_byte__LOPresc, &LOPrescaler, Bus_NoRead); ++ /* IF */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_IF_Frequency_byte__IF_Freq, &ProgIF, Bus_NoRead); ++ /* Decode IF */ ++ uIF = ProgIF*50000; ++ /* Decode PostDiv */ ++ switch(LOPostdiv) { ++ case 1: LOPostdiv = 1; break; ++ case 2: LOPostdiv = 2; break; ++ case 3: LOPostdiv = 4; break; ++ case 4: LOPostdiv = 8; break; ++ case 5: LOPostdiv = 16; break; ++ default: ret = -1; break; ++ } ++ ++ if(ret != -1) { ++ /* Calculate FVCO in MHz*/ ++ FVCO = LOPostdiv * LOPrescaler * ((uRF + uIF) / 1000000); ++ /* Set correct ICP */ ++ if(FVCO < 6352) { ++ /* Set ICP to 01 (= 150)*/ ++ ICP = 0x01; ++ } else if(FVCO < 6592) { ++ /* Set ICP to 10 (= 300)*/ ++ ICP = 0x02; ++ } else { ++ /* Set ICP to 00 (= 500)*/ ++ ICP = 0x00; ++ } ++ /* Get ICP_bypass bit */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Charge_pump_byte__ICP_Bypass, &uICPBypass, Bus_RW); ++ /* Get ICP */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Charge_pump_byte__ICP, &uPrevICP, Bus_NoRead); ++ ++ if(uICPBypass == 0x0 || uPrevICP != ICP) { ++ /* Set ICP_bypass bit */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Charge_pump_byte__ICP_Bypass, 0x01, Bus_None); ++ /* Set ICP */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Charge_pump_byte__ICP, ICP, Bus_None); ++ /* Write Charge_pump_byte register */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_Charge_pump_byte.Address, 1); ++ } ++ } ++ ++ return ret; ++} ++ ++static int tda18273_override_digitalclock(struct dvb_frontend *fe, unsigned int uRF) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ int ret; ++ unsigned char uDigClock = 0; ++ unsigned char uPrevDigClock = 0; ++ unsigned char uProgIF = 0; ++ ++ /* LO < 55 MHz then Digital Clock set to 16 MHz else subLO */ ++ /* Read Current IF */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_IF_Frequency_byte__IF_Freq, &uProgIF, Bus_NoWrite); ++ /* Read Current Digital Clock */ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode, &uPrevDigClock, Bus_NoWrite); ++ /* LO = RF + IF */ ++ if((uRF + (uProgIF*50000)) < 55000000) { ++ uDigClock = 0; /* '00' = 16 MHz */ ++ } else { ++ uDigClock = 3; /* '11' = subLO */ ++ } ++ ++ if(uPrevDigClock != uDigClock) { ++ /* Set Digital Clock bits */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode, uDigClock, Bus_NoRead); ++ } ++ ++ return 0; ++} ++ ++static int tda18273_set_rffreq(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ int ret; ++ unsigned int uRF=priv->pObj->uProgRF; ++ unsigned int uRFLocal=0; ++ ++ /* Set the proper settings depending on the standard & RF frequency */ ++ /****************************************************************/ ++ /* AGC TOP Settings */ ++ /****************************************************************/ ++ /* Set AGC3 RF AGC Top */ ++ if(uRF < priv->pObj->pStandard->Freq_Start_LTE) { ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_AGC_byte__RFAGC_Top, priv->pObj->pStandard->AGC3_TOP_I2C_Low_Band, Bus_RW); ++ } else { ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_AGC_byte__RFAGC_Top, priv->pObj->pStandard->AGC3_TOP_I2C_High_Band, Bus_RW); ++ } ++ /* Set AGC3 Adapt TOP */ ++ if(uRF < priv->pObj->pStandard->Freq_Start_LTE) { ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_AGC_byte__RFAGC_Adapt_TOP, priv->pObj->pStandard->AGC3_Adapt_TOP_Low_Band, Bus_NoRead); ++ } else { ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_AGC_byte__RFAGC_Adapt_TOP, priv->pObj->pStandard->AGC3_Adapt_TOP_High_Band, Bus_NoRead); ++ } ++ /* Set IRQ_clear */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IRQ_clear, TDA18273_IRQ_Global|TDA18273_IRQ_SetRF, Bus_NoRead); ++ /* Set RF */ ++ uRFLocal = (uRF + 500) / 1000; ++ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Frequency_byte_1__RF_Freq_1, (unsigned char)((uRFLocal & 0x00FF0000) >> 16), Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Frequency_byte_2__RF_Freq_2, (unsigned char)((uRFLocal & 0x0000FF00) >> 8), Bus_None); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Frequency_byte_3__RF_Freq_3, (unsigned char)(uRFLocal & 0x000000FF), Bus_None); ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_RF_Frequency_byte_1.Address, TDA18273_REG_DATA_LEN(gTDA18273_Reg_RF_Frequency_byte_1, gTDA18273_Reg_RF_Frequency_byte_3)); ++ /* Set state machine and Launch it */ ++ ret = tda18273_set_msm(fe, TDA18273_MSM_SetRF, 0x1); ++ /* Wait for IRQ to trigger */ ++ //ret = iTDA18273_WaitIRQ(pObj, 50, 5, TDA18273_IRQ_SetRF); ++ mdelay(50); ++ ++ /* Override the calculated PLL to get the best margin in case fine tuning is used */ ++ /* which means set the PLL in manual mode that provides the best occurence of LO tuning (+-2 MHz) */ ++ /* without touching PostDiv and Prescaler */ ++ ret = tda18273_set_pll(fe); ++ /* Override ICP */ ++ ret = tda18273_override_icp(fe, priv->pObj->uProgRF); ++ /* Override Digital Clock */ ++ if(ret != -1) { ++ ret = tda18273_override_digitalclock(fe, priv->pObj->uProgRF); ++ } ++ ++ return 0; ++} ++ ++static int tda18273_set_rf(struct dvb_frontend *fe, unsigned int uRF) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ priv->pObj->uRF = uRF; ++ priv->pObj->uProgRF = priv->pObj->uRF + priv->pObj->pStandard->CF_Offset; ++ ++ tda18273_llpwr_state(fe, TDA18273_PowerNormalMode); ++ tda18273_lastpass_lnapwr(fe); ++ tda18273_check_calcpll(fe); ++ tda18273_override_bandsplit(fe); ++ tda18273_set_rffreq(fe); ++ ++ return 0; ++} ++ ++static int tda18273_hw_reset(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ int ret; ++ ++ tda18273_pwr_state(fe, tmPowerStandby); ++ tda18273_llpwr_state(fe, TDA18273_PowerNormalMode); ++ ++ /* Set digital clock mode to 16 Mhz before resetting the IC to avoid unclocking the digital part */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Reference_Byte__Digital_Clock_Mode, 0x00, Bus_RW); ++ /* Perform a SW reset to reset the digital calibrations & the IC machine state */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_3, 0x03, Bus_RW); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Power_Down_byte_3, 0x00, Bus_NoRead); ++ /* Set power state on */ ++ //ret = tda18273_llpwr_state(fe, TDA18273_PowerNormalMode); ++ ++#if 0 ++ /* Only if tuner has a XTAL */ ++ if(1) { //if (priv->bBufferMode == False) ++ /* Reset XTALCAL_End bit */ ++ /* Set IRQ_clear */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IRQ_clear, TDA18273_IRQ_Global|TDA18273_IRQ_XtalCal|TDA18273_IRQ_HwInit|TDA18273_IRQ_IrCal, Bus_NoRead); ++ /* Launch XTALCAL */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_MSM_byte_2__XtalCal_Launch, 0x01, Bus_NoRead); ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_MSM_byte_2__XtalCal_Launch, 0x00, Bus_None); ++ /* Wait XTALCAL_End bit */ ++ //ret = iTDA18273_WaitXtalCal_End(priv, 100, 10); ++ } ++#endif ++ ++ /* Read all bytes */ ++ ret = tda18273_readregmap(priv, 0x00, TDA18273_REG_MAP_NB_BYTES); ++ /* Check if Calc_PLL algorithm is in automatic mode */ ++ ret = tda18273_check_calcpll(fe); ++ /* Up_Step_Ovld: POR = 1 -> 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Vsync_Mgt_byte__Up_Step_Ovld, 0x00, Bus_NoRead); ++ /* PLD_CC_Enable: POR = 1 -> 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RFAGCs_Gain_byte_1__PLD_CC_Enable, 0x00, Bus_NoRead); ++ /* RFCAL_Offset0 : 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog0, 0x00, Bus_None); ++ /* RFCAL_Offset1 : 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog1, 0x00, Bus_None); ++ /* RFCAL_Offset2 : 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog2, 0x00, Bus_None); ++ /* RFCAL_Offset3 : 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_1__RFCAL_Offset_Cprog3, 0x00, Bus_None); ++ /* RFCAL_Offset4 : 3 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog4, 0x03, Bus_None); ++ /* RFCAL_Offset5 : 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog5, 0x00, Bus_None); ++ /* RFCAL_Offset6 : 3 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog6, 0x03, Bus_None); ++ /* RFCAL_Offset7 : 3 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_2__RFCAL_Offset_Cprog7, 0x03, Bus_None); ++ /* RFCAL_Offset8 : 1 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RF_Cal_byte_3__RFCAL_Offset_Cprog8, 0x01, Bus_None); ++ /* Write RF_Cal_byte_1 (0x27) to RF_Cal_byte_3 (0x29) Registers */ ++ ret = tda18273_writeregmap(priv, gTDA18273_Reg_RF_Cal_byte_1.Address, TDA18273_REG_DATA_LEN(gTDA18273_Reg_RF_Cal_byte_1, gTDA18273_Reg_RF_Cal_byte_3)); ++ /* PLD_Temp_Enable: POR = 1 -> 0 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_RFAGCs_Gain_byte_1__PLD_Temp_Enable, 0x00, Bus_NoRead); ++ /* Power Down Vsync Management: POR = 0 -> 1 */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_Vsync_Mgt_byte__PD_Vsync_Mgt, 0x01, Bus_NoRead); ++ /* Set IRQ_clear */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IRQ_clear, TDA18273_IRQ_Global|TDA18273_IRQ_HwInit|TDA18273_IRQ_IrCal, Bus_NoRead); ++ /* Set state machine (all CALs except IRCAL) and Launch it */ ++ ret = tda18273_set_msm(fe, TDA18273_MSM_HwInit, 0x1); ++ /* Inform that init phase has started */ ++ /* State reached after 500 ms max */ ++ //ret = iTDA18273_WaitIRQ(priv, 500, 10, TDA18273_IRQ_HwInit); ++ mdelay(500); ++ /* Set IRQ_clear */ ++ ret = tda18273_writeregs(priv, &gTDA18273_Reg_IRQ_clear, TDA18273_IRQ_Global|TDA18273_IRQ_HwInit|TDA18273_IRQ_IrCal, Bus_NoRead); ++ /* Launch IRCALs after all other CALs are finished */ ++ ret = tda18273_set_msm(fe, TDA18273_MSM_IrCal, 0x1); ++ /* State reached after 500 ms max, 10 ms step due to CAL ~ 30ms */ ++ //ret = iTDA18273_WaitIRQ(priv, 500, 10, TDA18273_IRQ_IrCal); ++ mdelay(500); ++ ++ tda18273_llpwr_state(fe, TDA18273_PowerStandbyWithXtalOn); ++ ++ return 0; ++} ++ ++static int tda18273_hw_init(struct dvb_frontend *fe) ++{ ++ tda18273_pwr_state(fe, tmPowerOn); ++ ++ tda18273_hw_reset(fe); ++ ++ return 0; ++} ++ ++static int tda18273_init(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ int ret; ++ unsigned char val=0; ++ unsigned short id=0; ++ unsigned char major; ++ unsigned char minor; ++ ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_ID_byte_1__Ident_1, &val, Bus_RW); ++ id = val << 8; ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_ID_byte_2__Ident_2, &val, Bus_RW); ++ id |= val; ++ ++ if(ret == TDA_RESULT_SUCCESS) { ++ if(id == TDA_DEVICE_TYPE) { ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_ID_byte_3__Major_rev, &major, Bus_RW); ++ ret = tda18273_readregs(priv, &gTDA18273_Reg_ID_byte_3__Minor_rev, &minor, Bus_RW); ++ dprintk(FE_INFO, 1, "id:%d / ver:%d.%d", id, major, minor); ++ } else { ++ return -1; ++ } ++ } else { ++ return -1; ++ } ++ ++ priv->pObj = &gTDA18273Instance; ++ ++ tda18273_hw_init(fe); ++ ++ return 0; ++} ++ ++static int tda18273_get_status(struct dvb_frontend *fe, u32 *status) ++{ ++ struct tda18273_state *priv = (struct tda18273_state*)fe->tuner_priv; ++ unsigned short lock_status = 0; ++ int ret = 0; ++ ++ ret = tda18273_get_lock_status(priv, &lock_status); ++ if (ret) ++ goto err; ++err: ++ dprintk(FE_DEBUG, 1, "ret=%d", ret); ++ return ret; ++} ++#if 0 ++static int tda18273_get_state(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ int ret; ++ ++ switch (param) { ++ case DVBFE_TUNER_FREQUENCY: ++ state->frequency = priv->freq_hz; ++ ret = 0; ++ break; ++ case DVBFE_TUNER_TUNERSTEP: ++ state->tunerstep = fe->ops.tuner_ops.info.frequency_step; ++ ret = 0; ++ break; ++ case DVBFE_TUNER_IFFREQ: ++ state->ifreq = priv->if_freq; ++ ret = 0; ++ break; ++ case DVBFE_TUNER_BANDWIDTH: ++ if (fe->ops.info.type == FE_OFDM) ++ state->bandwidth = priv->bandwidth; ++ ret = 0; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++#endif ++static int tda18273_set_params(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct tda18273_state *priv = fe->tuner_priv; ++ u32 delsys = c->delivery_system; ++ u32 bw = c->bandwidth_hz; ++ u32 freq = c->frequency; ++ unsigned short lock = 0; ++ int ret; ++ ++ BUG_ON(!priv); ++ ++ dprintk(FE_DEBUG, 1, "freq=%d, bw=%d", freq, bw); ++ ++ switch (delsys) { ++ case SYS_ATSC: ++ tda18273_set_standardmode(fe, TDA18273_ATSC_6MHz); ++ break; ++ case SYS_DVBT: ++ case SYS_DVBT2: ++ switch (bw) { ++ case 1700000: ++ tda18273_set_standardmode(fe, TDA18273_DVBT_1_7MHz); ++ break; ++ case 6000000: ++ tda18273_set_standardmode(fe, TDA18273_DVBT_6MHz); ++ break; ++ case 7000000: ++ tda18273_set_standardmode(fe, TDA18273_DVBT_7MHz); ++ break; ++ case 8000000: ++ tda18273_set_standardmode(fe, TDA18273_DVBT_8MHz); ++ break; ++ case 10000000: ++ tda18273_set_standardmode(fe, TDA18273_DVBT_10MHz); ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ break; ++ case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_C: ++ tda18273_set_standardmode(fe, TDA18273_QAM_8MHz); ++ break; ++ case SYS_DVBC_ANNEX_B: ++ tda18273_set_standardmode(fe, TDA18273_QAM_6MHz); ++ break; ++ } ++ ++ ret = tda18273_pwr_state(fe, tmPowerOn); ++ if (ret) ++ goto err; ++ ++ dprintk(FE_DEBUG, 1, "if_freq=%d", priv->pObj->pStandard->IF); ++ ++ ret = tda18273_set_rf(fe, freq + priv->pObj->pStandard->IF); ++ if (ret) ++ goto err; ++ ++ msleep(100); ++ tda18273_get_lock_status(priv, &lock); ++ ++ tda18273_regall_debug(priv); ++ ++ dprintk(FE_INFO, 1, "Lock status = %d", lock); ++ if (lock) { ++ priv->freq_hz = freq; ++ priv->if_freq = priv->pObj->pStandard->IF; ++ priv->bandwidth = bw; ++ } ++err: ++ dprintk(FE_DEBUG, 1, "ret=%d", ret); ++ return ret; ++} ++ ++static int tda18273_get_freq(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ *frequency = priv->freq_hz; ++ return 0; ++} ++ ++static int tda18273_get_if_freq(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ *frequency = priv->if_freq; ++ return 0; ++} ++ ++static int tda18273_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ *bandwidth = priv->bandwidth; ++ return 0; ++} ++ ++static int tda18273_release(struct dvb_frontend *fe) ++{ ++ struct tda18273_state *priv = fe->tuner_priv; ++ ++ BUG_ON(!priv); ++ ++ if(priv->power_state != tmPowerOff) { ++ tda18273_pwr_state(fe, tmPowerStandby); ++ } ++ ++ fe->tuner_priv = NULL; ++ kfree(priv); ++ return 0; ++} ++ ++static struct dvb_tuner_ops tda18273_ops = { ++ .info = { ++ .name = "TDA18273 Silicon Tuner", ++ .frequency_min = 42000000, ++ .frequency_max = 870000000, ++ .frequency_step = 50000, ++ }, ++ .init = tda18273_init, ++// .sleep = tda18273_sleep, ++ .get_status = tda18273_get_status, ++ .set_params = tda18273_set_params, ++ .get_frequency = tda18273_get_freq, ++ .get_bandwidth = tda18273_get_bandwidth, ++ .get_if_frequency = tda18273_get_if_freq, ++ .release = tda18273_release ++}; ++ ++struct dvb_frontend *tda18273_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const u8 i2c_addr) ++{ ++ struct tda18273_state *tda18273; ++ int ret; ++ ++ BUG_ON(!i2c); ++ ++ tda18273 = kzalloc(sizeof (struct tda18273_state), GFP_KERNEL); ++ if (!tda18273) ++ goto err; ++ ++ tda18273->i2c = i2c; ++ tda18273->fe = fe; ++ tda18273->i2c_addr = i2c_addr; ++ tda18273->power_state = tmPowerOff; ++ ++ fe->tuner_priv = tda18273; ++ fe->ops.tuner_ops = tda18273_ops; ++ ++ ret = tda18273_init(fe); ++ if (ret) { ++ dprintk(FE_ERROR, 1, "Error Initializing!"); ++ goto err; ++ } ++ ++ dprintk(FE_DEBUG, 1, "Done"); ++ return tda18273->fe; ++err: ++ kfree(tda18273); ++ return NULL; ++} ++EXPORT_SYMBOL(tda18273_attach); ++ ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_DESCRIPTION("TDA18273 Silicon tuner"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/tuners/tda18273.h b/drivers/media/tuners/tda18273.h +new file mode 100644 +index 0000000..534b85f +--- /dev/null ++++ b/drivers/media/tuners/tda18273.h +@@ -0,0 +1,38 @@ ++/* ++ tda18273.h - header for the NXP TDA18273 silicon tuner ++ Copyright (C) 2014 CrazyCat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef __TDA18273_H ++#define __TDA18273_H ++ ++#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA18273) ++extern struct dvb_frontend *tda18273_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const u8 i2c_addr); ++ ++#else ++static inline struct dvb_frontend *tda18273_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const u8 i2c_addr) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif ++ ++#endif /* __TDA18273_H */ +diff --git a/drivers/media/tuners/tda18273_priv.h b/drivers/media/tuners/tda18273_priv.h +new file mode 100644 +index 0000000..a282b14 +--- /dev/null ++++ b/drivers/media/tuners/tda18273_priv.h +@@ -0,0 +1,1427 @@ ++/* ++ tda18273-priv.h - private header for the NXP TDA18273 silicon tuner ++ Copyright (C) 2014 CrazyCat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef __TDA18273_PRIV ++#define __TDA18273_PRIV ++ ++#define TDA18273_TUNER_RESET 0 ++ ++#define TDA_FREQ_LOW_BAND 1 ++#define TDA_FREQ_MID_BAND 2 ++#define TDA_FREQ_HIGH_BAND 4 ++ ++#define TDA_AGC_115dBuV 1 ++#define TDA_AGC_112dBuV 2 ++#define TDA_AGC_109dBuV 3 ++#define TDA_AGC_106dBuV 4 ++#define TDA_AGC_103dBuV 5 ++#define TDA_AGC_EXTERNAL 6 ++#define TDA_AGC_DISABLE 7 ++ ++#define TDA_PLL_CP_50uA 6 ++#define TDA_PLL_CP_125uA 7 ++#define TDA_PLL_CP_250uA 0x0e ++#define TDA_PLL_CP_650uA 0x0f ++ ++#define TDA_PLLref_DIVIDER_64 3 ++#define TDA_PLLref_DIVIDER_24 2 ++ ++//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++typedef unsigned char UInt8; ++typedef unsigned int UInt32; ++typedef int Int32; ++ ++ ++/* Result codes */ ++#define TDA_RESULT_SUCCESS 0 ++#define TDA_RESULT_RESET_FAILURE 1 ++#define TDA_RESULT_I2C_WRITE_FAILURE 2 ++#define TDA_RESULT_I2C_READ_FAILURE 3 ++#define TDA_RESULT_OUT_OF_RANGE 5 ++ ++ ++/* Product id */ ++#define TDA_DEVICE_TYPE 18273 ++ ++/* Register Bit-Field Definition */ ++typedef struct _TDA18273_BitField_t { ++ UInt8 Address; ++ UInt8 PositionInBits; ++ UInt8 WidthInBits; ++ UInt8 Attributes; ++} TDA18273_BitField_t, *pTDA18273_BitField_t; ++ ++/* Bus Access */ ++typedef enum _tmbslFrontEndBusAccess_t { ++ Bus_RW = 0x00, /* RW Bus access */ ++ Bus_NoRead = 0x01, /* No Read Bus access */ ++ Bus_NoWrite = 0x02, /* No Write Bus access */ ++ Bus_None = Bus_NoRead|Bus_NoWrite, /* No Bus access. Update RegMap only */ ++ Bus_Max ++} tmbslFrontEndBusAccess_t; ++ ++typedef enum tmPowerState ++{ ++ tmPowerOn = 0, /* Device powered on (D0 state) */ ++ tmPowerStandby, /* Device power standby (D1 state) */ ++ tmPowerSuspend, /* Device power suspended (D2 state) */ ++ tmPowerOff, /* Device powered off (D3 state) */ ++ tmPowerMax /* Device power max */ ++} tmPowerState_t, *ptmPowerState_t; ++ ++typedef enum _TDA18273PowerState_t { ++ TDA18273_PowerNormalMode = 0, /* Device normal mode */ ++ TDA18273_PowerStandbyWithXtalOn, /* Device standby mode with Xtal Output */ ++ TDA18273_PowerStandby, /* Device standby mode */ ++ TDA18273_PowerMax ++} TDA18273PowerState_t, *pTDA18273PowerState_t; ++ ++typedef enum _TDA18273StandardMode_t { ++ TDA18273_StandardMode_Unknown = 0, /* Unknown standard */ ++ TDA18273_QAM_6MHz, /* Digital TV QAM 6MHz */ ++ TDA18273_QAM_8MHz, /* Digital TV QAM 8MHz */ ++ TDA18273_ATSC_6MHz, /* Digital TV ATSC 6MHz */ ++ TDA18273_ISDBT_6MHz, /* Digital TV ISDBT 6MHz */ ++ TDA18273_DVBT_1_7MHz, /* Digital TV DVB-T/T2 6MHz */ ++ TDA18273_DVBT_6MHz, /* Digital TV DVB-T/T2 6MHz */ ++ TDA18273_DVBT_7MHz, /* Digital TV DVB-T/T2 7MHz */ ++ TDA18273_DVBT_8MHz, /* Digital TV DVB-T/T2 8MHz */ ++ TDA18273_DVBT_10MHz, /* Digital TV DVB-T/T2 10MHz */ ++ TDA18273_DMBT_8MHz, /* Digital TV DMB-T 8MHz */ ++ TDA18273_FM_Radio, /* Analog FM Radio */ ++ TDA18273_ANLG_MN, /* Analog TV M/N */ ++ TDA18273_ANLG_B, /* Analog TV B */ ++ TDA18273_ANLG_GH, /* Analog TV G/H */ ++ TDA18273_ANLG_I, /* Analog TV I */ ++ TDA18273_ANLG_DK, /* Analog TV D/K */ ++ TDA18273_ANLG_L, /* Analog TV L */ ++ TDA18273_ANLG_LL, /* Analog TV L' */ ++ TDA18273_Scanning, /* Analog Preset Blind Scanning */ ++ TDA18273_ScanXpress, /* ScanXpress */ ++ TDA18273_StandardMode_Max ++} TDA18273StandardMode_t, *pTDA18273StandardMode_t; ++ ++/* TDA18273 Driver State Machine */ ++typedef enum _TDA18273HwState_t { ++ TDA18273_HwState_Unknown = 0, /* Hw State Unknown */ ++ TDA18273_HwState_InitNotDone, /* Hw Init Not Done */ ++ TDA18273_HwState_InitPending, /* Hw Init Pending */ ++ TDA18273_HwState_InitDone, /* Hw Init Done */ ++ TDA18273_HwState_SetStdDone, /* Set Standard Done */ ++ TDA18273_HwState_SetRFDone, /* Set RF Done */ ++ TDA18273_HwState_SetFineRFDone, /* Set Fine RF Done */ ++ TDA18273_HwState_Max ++} TDA18273HwState_t, *pTDA18273HwState_t; ++ ++typedef enum _TDA18273HwStateCaller_t { ++ TDA18273_HwStateCaller_Unknown = 0, /* Caller Unknown */ ++ TDA18273_HwStateCaller_SetPower, /* Caller SetPowerState */ ++ TDA18273_HwStateCaller_HwInit, /* Caller HwInit */ ++ TDA18273_HwStateCaller_SetStd, /* Caller SetStandardMode */ ++ TDA18273_HwStateCaller_SetRF, /* Caller SetRF */ ++ TDA18273_HwStateCaller_SetFineRF, /* Caller SetFineRF */ ++ TDA18273_HwStateCaller_GetRSSI, /* Caller GetRSSI */ ++ TDA18273_HwStateCaller_SetRawRF, /* Caller SetRawRF */ ++ TDA18273_HwStateCaller_Max ++} TDA18273HwStateCaller_t, *pTDA18273HwStateCaller_t; ++ ++/* TDA18273 specific powerstate bits: */ ++typedef enum _TDA18273SM_Reg_t { ++ TDA18273_SM_NONE = 0x00, /* No SM bit to set */ ++ TDA18273_SM_XT = 0x01, /* SM_XT bit to set */ ++ TDA18273_SM = 0x02 /* SM bit to set */ ++} TDA18273SM_Reg_t, *pTDA18273SM_Reg_t; ++ ++/* TDA18273 specific MSM: */ ++typedef enum _TDA18273MSM_t { ++ TDA18273_MSM_Calc_PLL = 0x01, /* Calc_PLL bit */ ++ TDA18273_MSM_RC_Cal = 0x02, /* RC_Cal bit */ ++ TDA18273_MSM_IR_CAL_Wanted = 0x04, /* IR_CAL_Wanted bit */ ++ TDA18273_MSM_IR_Cal_Image = 0x08, /* IR_Cal_Image bit */ ++ TDA18273_MSM_IR_CAL_Loop = 0x10, /* IR_CAL_Loop bit */ ++ TDA18273_MSM_RF_CAL = 0x20, /* RF_CAL bit */ ++ TDA18273_MSM_RF_CAL_AV = 0x40, /* RF_CAL_AV bit */ ++ TDA18273_MSM_RSSI_Meas = 0x80, /* RSSI_Meas bit */ ++ /* Performs all CALs except IR_CAL */ ++ TDA18273_MSM_HwInit = TDA18273_MSM_Calc_PLL\ ++ |TDA18273_MSM_RC_Cal\ ++ |TDA18273_MSM_RF_CAL, ++ /* Performs all IR_CAL */ ++ TDA18273_MSM_IrCal = TDA18273_MSM_IR_Cal_Image\ ++ |TDA18273_MSM_IR_CAL_Loop, ++ TDA18273_MSM_SetRF = TDA18273_MSM_Calc_PLL\ ++ |TDA18273_MSM_RF_CAL_AV, ++ TDA18273_MSM_GetPowerLevel = TDA18273_MSM_RSSI_Meas ++} TDA18273MSM_t, *pTDA18273MSM_t; ++ ++/* TDA18273 specific IRQ clear: */ ++typedef enum _TDA18273IRQ_t { ++ TDA18273_IRQ_MSM_RCCal = 0x01, /* MSM_RCCal bit */ ++ TDA18273_IRQ_MSM_IRCAL = 0x02, /* MSM_IRCAL bit */ ++ TDA18273_IRQ_MSM_RFCal = 0x04, /* MSM_RFCal bit */ ++ TDA18273_IRQ_MSM_LOCalc = 0x08, /* MSM_LOCalc bit */ ++ TDA18273_IRQ_MSM_RSSI = 0x10, /* MSM_RSSI bit */ ++ TDA18273_IRQ_XtalCal = 0x20, /* XtalCal bit */ ++ TDA18273_IRQ_Global = 0x80, /* IRQ_status bit */ ++ TDA18273_IRQ_HwInit = TDA18273_IRQ_MSM_RCCal\ ++ |TDA18273_IRQ_MSM_RFCal\ ++ |TDA18273_IRQ_MSM_LOCalc\ ++ |TDA18273_IRQ_MSM_RSSI, ++ TDA18273_IRQ_IrCal = TDA18273_IRQ_MSM_IRCAL\ ++ |TDA18273_IRQ_MSM_LOCalc\ ++ |TDA18273_IRQ_MSM_RSSI, ++ TDA18273_IRQ_SetRF = TDA18273_IRQ_MSM_RFCal\ ++ |TDA18273_IRQ_MSM_LOCalc, ++ TDA18273_IRQ_GetPowerLevel = TDA18273_IRQ_MSM_RSSI ++} TDA18273IRQ_t, *pTDA18273IRQ_t; ++ ++/* TDA18273 Standard settings: */ ++typedef enum _TDA18273LPF_t { ++ TDA18273_LPF_6MHz = 0, /* 6MHz LPFc */ ++ TDA18273_LPF_7MHz, /* 7MHz LPFc */ ++ TDA18273_LPF_8MHz, /* 8MHz LPFc */ ++ TDA18273_LPF_9MHz, /* 9MHz LPFc */ ++ TDA18273_LPF_1_5MHz, /* 1.5MHz LPFc */ ++ TDA18273_LPF_Max ++} TDA18273LPF_t, *pTDA18273LPF_t; ++ ++typedef enum _TDA18273LPFOffset_t { ++ TDA18273_LPFOffset_0pc = 0, /* LPFc 0% */ ++ TDA18273_LPFOffset_min_4pc, /* LPFc -4% */ ++ TDA18273_LPFOffset_min_8pc, /* LPFc -8% */ ++ TDA18273_LPFOffset_min_12pc, /* LPFc -12% */ ++ TDA18273_LPFOffset_Max ++} TDA18273LPFOffset_t, *pTDA18273LPFOffset_t; ++ ++typedef enum TDA18273DC_Notch_IF_PPF_t { ++ TDA18273_DC_Notch_IF_PPF_Disabled = 0, /* IF Notch Disabled */ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* IF Notch Enabled */ ++ TDA18273_DC_Notch_IF_PPF_Max ++} TDA18273DC_Notch_IF_PPF_t, *pTDA18273DC_Notch_IF_PPF_t; ++ ++typedef enum _TDA18273IF_HPF_t { ++ TDA18273_IF_HPF_Disabled = 0, /* IF HPF disabled */ ++ TDA18273_IF_HPF_0_4MHz, /* IF HPF 0.4MHz */ ++ TDA18273_IF_HPF_0_85MHz, /* IF HPF 0.85MHz */ ++ TDA18273_IF_HPF_1MHz, /* IF HPF 1MHz */ ++ TDA18273_IF_HPF_1_5MHz, /* IF HPF 1.5MHz */ ++ TDA18273_IF_HPF_Max ++} TDA18273IF_HPF_t, *pTDA18273IF_HPF_t; ++ ++typedef enum _TDA18273IF_Notch_t { ++ TDA18273_IF_Notch_Disabled = 0, /* IF Notch Disabled */ ++ TDA18273_IF_Notch_Enabled, /* IF Notch Enabled */ ++ TDA18273_IF_Notch_Max ++} TDA18273IF_Notch_t, *pTDA18273IF_Notch_t; ++ ++typedef enum _TDA18273IFnotchToRSSI_t { ++ TDA18273_IFnotchToRSSI_Disabled = 0, /* IFnotchToRSSI Disabled */ ++ TDA18273_IFnotchToRSSI_Enabled, /* IFnotchToRSSI Enabled */ ++ TDA18273_IFnotchToRSSI_Max ++} TDA18273IFnotchToRSSI_t, *pTDA18273IFnotchToRSSI_t; ++ ++typedef enum _TDA18273AGC1_TOP_I2C_DN_UP_t { ++ TDA18273_AGC1_TOP_I2C_DN_UP_d88_u82dBuV = 0, /* AGC1 TOP I2C DN/UP down 88 up 82 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d90_u84dBuV, /* AGC1 TOP I2C DN/UP down 90 up 84 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89wdBuV, /* AGC1 TOP I2C DN/UP down 95 up 89 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d93_u87dBuV, /* AGC1 TOP I2C DN/UP down 93 up 87 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP down 95 up 89 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d99_u84dBuV, /* AGC1 TOP I2C DN/UP down 99 up 84 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d100_u82dBuV, /* AGC1 TOP I2C DN/UP down 100 up 82 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d100_u94bisdBuV, /* AGC1 TOP I2C DN/UP down 100 up 94 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d102_u82dBuV, /* AGC1 TOP I2C DN/UP down 102 up 82 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d102_u84dBuV, /* AGC1 TOP I2C DN/UP down 102 up 84 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d100_u94dBuV, /* AGC1 TOP I2C DN/UP down 100 up 94 dBuV */ ++ TDA18273_AGC1_TOP_I2C_DN_UP_Max ++} TDA18273AGC1_TOP_I2C_DN_UP_t, *pTDA18273AGC1_TOP_I2C_DN_UP_t; ++ ++typedef enum _TDA18273AGC1_Adapt_TOP_DN_UP_t { ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step = 0, /* AGC1 Adapt TOP DN/UP 0 Step */ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP 1 Step */ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_2_Step, /* AGC1 Adapt TOP DN/UP 2 Step */ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_3_Step, /* AGC1 Adapt TOP DN/UP 3 Step */ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_Max ++} TDA18273AGC1_Adapt_TOP_DN_UP_t, *pTDA18273AGC1_Adapt_TOP_DN_UP_t; ++ ++typedef enum _TDA18273AGC1_Mode_t { ++ TDA18273_AGC1_Mode_No_Mode = 0, /* AGC1 Mode */ ++ TDA18273_AGC1_Mode_TOP_ADAPT, /* AGC1 Mode: TOP ADAPT */ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 Mode: LNA ADAPT */ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 Mode: LNA ADAPT & TOP ADAPT */ ++ TDA18273_AGC1_Mode_FREEZE, /* AGC1 Mode: FREEZE */ ++ TDA18273_AGC1_Mode_WIDE, /* AGC1 Mode: WIDE */ ++ TDA18273_AGC1_Mode_LNA_ADAPT_FREEZE, /* AGC1 Mode: LNA ADAPT & FREEZE */ ++ TDA18273_AGC1_Mode_LNA_ADAPT_WIDE, /* AGC1 Mode: LNA ADAPT & WIDE */ ++ TDA18273_AGC1_Mode_Max ++} TDA18273AGC1_Mode_t, *pTDA18273AGC1_Mode_t; ++ ++typedef enum _TDA18273Range_LNA_Adapt_t { ++ TDA18273_Range_LNA_Adapt_20dB_8dB = 0, /* Range LNA Adapt 20dB-8dB */ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt 20dB-11dB */ ++ TDA18273_Range_LNA_Adapt_Max ++} TDA18273Range_LNA_Adapt_t, *pTDA18273Range_LNA_Adapt_t; ++ ++typedef enum _TDA18273LNA_Adapt_RFAGC_Gv_Threshold { ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB = 0, /* 18.25dB */ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_16_75dB, /* 16.75dB */ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_15_25dB, /* 15.25dB */ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_13_75dB, /* 13.75dB */ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_Max ++} TDA18273LNA_Adapt_RFAGC_Gv_Threshold, *pTDA18273LNA_Adapt_RFAGC_Gv_Threshold; ++ ++typedef enum _TDA18273AGC1_Top_Adapt_RFAGC_Gv_Threshold { ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB = 0, /* 16.75dB */ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* 15.25dB */ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_13_75dB, /* 13.75dB */ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_12_25dB, /* 12.25dB */ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_Max ++} TDA18273AGC1_Top_Adapt_RFAGC_Gv_Threshold, *pTDA18273AGC1_Top_Adapt_RFAGC_Gv_Threshold; ++ ++typedef enum _TDA18273AGC1_DN_Time_Constant_t { ++ TDA18273_AGC1_DN_Time_Constant_32_752ms = 0, /* 32.752 ms */ ++ TDA18273_AGC1_DN_Time_Constant_16_376ms, /* 16.376 ms */ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* 8.188 ms */ ++ TDA18273_AGC1_DN_Time_Constant_4_094ms /* 4.094 ms */ ++} TDA18273AGC1_DN_Time_Constant_t, *pTDA18273AGC1_DN_Time_Constant_t; ++ ++typedef enum _TDA18273AGC2_TOP_DN_UP_t { ++ TDA18273_AGC2_TOP_DN_UP_d88_u81dBuV = 0, /* AGC2 TOP DN/UP down 88 up 81 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_d90_u83dBuV, /* AGC2 TOP DN/UP down 90 up 83 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_d93_u86dBuV, /* AGC2 TOP DN/UP down 93 up 86 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_d95_u88dBuV, /* AGC2 TOP DN/UP down 95 up 88 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_d88_u82dBuV, /* AGC2 TOP DN/UP down 88 up 82 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP down 90 up 84 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_d93_u87dBuV, /* AGC2 TOP DN/UP down 93 up 87 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_d95_u89dBuV, /* AGC2 TOP DN/UP down 95 up 89 dBuV */ ++ TDA18273_AGC2_TOP_DN_UP_Max ++} TDA18273AGC2_TOP_DN_UP_t, *pTDA18273AGC2_TOP_DN_UP_t; ++ ++typedef enum _TDA18273AGC2_DN_Time_Constant_t { ++ TDA18273_AGC2_DN_Time_Constant_16_376ms = 0, /* 16.376 ms */ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* 8.188 ms */ ++ TDA18273_AGC2_DN_Time_Constant_4_094ms, /* 4.094 ms */ ++ TDA18273_AGC2_DN_Time_Constant_2_047ms, /* 2.047 ms */ ++} TDA18273AGC2_DN_Time_Constant_t, *pTDA18273AGC2_DN_Time_Constant_t; ++ ++typedef enum _TDA18273AGC3_TOP_I2C_t { ++ TDA18273_AGC3_TOP_I2C_94dBuV = 0, /* AGC3 TOP I2C 94 dBuV */ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C 96 dBuV */ ++ TDA18273_AGC3_TOP_I2C_98dBuV, /* AGC3 TOP I2C 98 dBuV */ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C 100 dBuV */ ++ TDA18273_AGC3_TOP_I2C_102dBuV, /* AGC3 TOP I2C 102 dBuV */ ++ TDA18273_AGC3_TOP_I2C_104dBuV, /* AGC3 TOP I2C 104 dBuV */ ++ TDA18273_AGC3_TOP_I2C_106dBuV, /* AGC3 TOP I2C 106 dBuV */ ++ TDA18273_AGC3_TOP_I2C_107dBuV, /* AGC3 TOP I2C 107 dBuV */ ++ TDA18273_AGC3_TOP_I2C_Max ++} TDA18273AGC3_TOP_I2C_t, *pTDA18273AGC3_TOP_I2C_t; ++ ++typedef enum _TDA18273AGC4_TOP_DN_UP_t { ++ TDA18273_AGC4_TOP_DN_UP_d105_u99dBuV = 0, /* AGC4 TOP DN/UP down 105 up 99 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP down 105 up 100 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d105_u101dBuV, /* AGC4 TOP DN/UP down 105 up 101 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d107_u101dBuV, /* AGC4 TOP DN/UP down 107 up 101 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d107_u102dBuV, /* AGC4 TOP DN/UP down 107 up 102 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d107_u103dBuV, /* AGC4 TOP DN/UP down 107 up 103 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d108_u102dBuV, /* AGC4 TOP DN/UP down 108 up 102 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d109_u103dBuV, /* AGC4 TOP DN/UP down 109 up 103 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d109_u104dBuV, /* AGC4 TOP DN/UP down 109 up 104 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d109_u105dBuV, /* AGC4 TOP DN/UP down 109 up 105 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d110_u104dBuV, /* AGC4 TOP DN/UP down 110 up 104 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP down 110 up 105 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d110_u106dBuV, /* AGC4 TOP DN/UP down 110 up 106 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d112_u106dBuV, /* AGC4 TOP DN/UP down 112 up 106 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d112_u107dBuV, /* AGC4 TOP DN/UP down 112 up 107 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_d112_u108dBuV, /* AGC4 TOP DN/UP down 112 up 108 dBuV */ ++ TDA18273_AGC4_TOP_DN_UP_Max ++} TDA18273AGC4_TOP_DN_UP_t, *pTDA18273AGC4_TOP_DN_UP_t; ++ ++typedef enum _TDA18273AGC5_TOP_DN_UP_t { ++ TDA18273_AGC5_TOP_DN_UP_d105_u99dBuV = 0, /* AGC5 TOP DN/UP down 105 up 99 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP down 105 up 100 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d105_u101dBuV, /* AGC5 TOP DN/UP down 105 up 101 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d107_u101dBuV, /* AGC5 TOP DN/UP down 107 up 101 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d107_u102dBuV, /* AGC5 TOP DN/UP down 107 up 102 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d107_u103dBuV, /* AGC5 TOP DN/UP down 107 up 103 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d108_u102dBuV, /* AGC5 TOP DN/UP down 108 up 102 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d109_u103dBuV, /* AGC5 TOP DN/UP down 109 up 103 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d109_u104dBuV, /* AGC5 TOP DN/UP down 109 up 104 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d109_u105dBuV, /* AGC5 TOP DN/UP down 109 up 105 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d110_u104dBuV, /* AGC5 TOP DN/UP down 108 up 104 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP down 108 up 105 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d110_u106dBuV, /* AGC5 TOP DN/UP down 108 up 106 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d112_u106dBuV, /* AGC5 TOP DN/UP down 108 up 106 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d112_u107dBuV, /* AGC5 TOP DN/UP down 108 up 107 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_d112_u108dBuV, /* AGC5 TOP DN/UP down 108 up 108 dBuV */ ++ TDA18273_AGC5_TOP_DN_UP_Max ++} TDA18273AGC5_TOP_DN_UP_t, *pTDA18273AGC5_TOP_DN_UP_t; ++ ++typedef enum _TDA18273AGC3_Top_Adapt_Algorithm { ++ TDA18273_Top_Adapt_NO_TOP_ADAPT = 0, /* NO TOP ADAPT */ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* TOP ADAPT35 */ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* TOP ADAPT34 */ ++ TDA18273_Top_Adapt_Max ++} TDA18273AGC3_Top_Adapt_Algorithm, *pTDA18273AGC3_Top_Adapt_Algorithm; ++ ++typedef enum _TDA18273AGC3_Adapt_TOP_t { ++ TDA18273_AGC3_Adapt_TOP_0_Step = 0, /* same level as AGC3 TOP */ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* 1 level below AGC3 TOP */ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* 2 level below AGC3 TOP */ ++ TDA18273_AGC3_Adapt_TOP_3_Step /* 3 level below AGC3 TOP */ ++} TDA18273AGC3_Adapt_TOP_t, *pTDA18273AGC3_Adapt_TOP_t; ++ ++typedef enum _TDA18273AGC_Overload_TOP_t { ++ TDA18273_AGC_Overload_TOP_plus_9_plus_3_5_min_3_5 = 0, /* +9/+3.5/-3.5 */ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_4_5, /* +9/+4.5/-4.5 */ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* +9/+4.5/-3.5 */ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_6_min_4_5, /* +9/+6/-4.5 */ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_6_min_6, /* +9/+6/-6 */ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_6_min_9, /* +9/+6/-9 */ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_7_5_min_9, /* +9/+7.5/-9 */ ++ TDA18273_AGC_Overload_TOP_plus_12_plus_7_5_min_9 /* +12/+7.5/-9 */ ++} TDA18273AGC_Overload_TOP_t, *pTDA18273AGC_Overload_TOP_t; ++ ++typedef enum _TDA18273TH_AGC_Adapt34_t { ++ TDA18273_TH_AGC_Adapt34_2dB = 0, /* Adapt TOP 34 Gain Threshold 2dB */ ++ TDA18273_TH_AGC_Adapt34_5dB /* Adapt TOP 34 Gain Threshold 5dB */ ++} TDA18273TH_AGC_Adapt34_t, *pTDA18273TH_AGC_Adapt34_t; ++ ++typedef enum _TDA18273RF_Atten_3dB_t { ++ TDA18273_RF_Atten_3dB_Disabled = 0, /* RF_Atten_3dB Disabled */ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF_Atten_3dB Enabled */ ++ TDA18273_RF_Atten_3dB_Max ++} TDA18273RF_Atten_3dB_t, *pTDA18273RF_Atten_3dB_t; ++ ++typedef enum _TDA18273IF_Output_Level_t { ++ TDA18273_IF_Output_Level_2Vpp_0_30dB = 0, /* 2Vpp 0 - 30dB */ ++ TDA18273_IF_Output_Level_1_25Vpp_min_4_26dB, /* 1.25Vpp -4 - 26dB */ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* 1Vpp -6 - 24dB */ ++ TDA18273_IF_Output_Level_0_8Vpp_min_8_22dB, /* 0.8Vpp -8 - 22dB */ ++ TDA18273_IF_Output_Level_0_85Vpp_min_7_5_22_5dB, /* 0.85Vpp -7.5 - 22.5dB */ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* 0.7Vpp -9 - 21dB */ ++ TDA18273_IF_Output_Level_0_6Vpp_min_10_3_19_7dB, /* 0.6Vpp -10.3 - 19.7dB */ ++ TDA18273_IF_Output_Level_0_5Vpp_min_12_18dB, /* 0.5Vpp -12 - 18dB */ ++ TDA18273_IF_Output_Level_Max ++} TDA18273IF_Output_Level_t, *pTDA18273IF_Output_Level_t; ++ ++typedef enum _TDA18273S2D_Gain_t { ++ TDA18273_S2D_Gain_3dB = 0, /* 3dB */ ++ TDA18273_S2D_Gain_6dB, /* 6dB */ ++ TDA18273_S2D_Gain_9dB, /* 9dB */ ++ TDA18273_S2D_Gain_Max ++} TDA18273S2D_Gain_t, *pTDA18273S2D_Gain_t; ++ ++typedef enum _TDA18273Negative_Modulation_t { ++ TDA18273_Negative_Modulation_Disabled = 0, ++ TDA18273_Negative_Modulation_Enabled, ++ TDA18273_Negative_Modulation_Max ++} TDA18273Negative_Modulation_t, *pTDA18273Negative_Modulation_t; ++ ++typedef enum _TDA18273AGCK_Steps_t { ++ TDA18273_AGCK_Steps_0_2dB = 0, /* 0.2dB */ ++ TDA18273_AGCK_Steps_0_4dB, /* 0.4dB */ ++ TDA18273_AGCK_Steps_0_6dB, /* 0.6dB */ ++ TDA18273_AGCK_Steps_0_8dB, /* 0.8dB */ ++ TDA18273_AGCK_Steps_Max ++} TDA18273AGCK_Steps_t, *pTDA18273AGCK_Steps_t; ++ ++typedef enum _TDA18273AGCK_Time_Constant_t { ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE = 0, /* 1 Step Each VSYNC Rising Edge */ ++ TDA18273_AGCK_Time_Constant_0_512ms, /* 0.512ms */ ++ TDA18273_AGCK_Time_Constant_8_192ms, /* 8.192ms */ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* 32.768ms */ ++ TDA18273_AGCK_Time_Constant_Max ++} TDA18273AGCK_Time_Constant_t, *pTDA18273AGCK_Time_Constant_t; ++ ++typedef enum _TDA18273AGC5_HPF_t { ++ TDA18273_AGC5_HPF_Disabled = 0, /* AGC5 HPF Disabled */ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF Enabled */ ++ TDA18273_AGC5_HPF_Max ++} TDA18273AGC5_HPF_t, *pTDA18273AGC5_HPF_t; ++ ++typedef enum _TDA18273Pulse_Shaper_Disable_t { ++ TDA18273_Pulse_Shaper_Disable_Disabled = 0, ++ TDA18273_Pulse_Shaper_Disable_Enabled, ++ TDA18273_Pulse_Shaper_Disable_Max ++} TDA18273Pulse_Shaper_Disable_t, *pTDA18273Pulse_Shaper_Disable_t; ++ ++typedef enum _TDA18273VHF_III_Mode_t { ++ TDA18273_VHF_III_Mode_Disabled = 0, /* VHF_III_Mode Disabled */ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF_III_Mode Enabled */ ++ TDA18273_VHF_III_Mode_Max ++} TDA18273VHF_III_Mode_t, *pTDA18273VHF_III_Mode_t; ++ ++typedef enum _TDA18273LO_CP_Current_t { ++ TDA18273_LO_CP_Current_Disabled = 0, /* LO CP Current Disabled */ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current Enabled */ ++ TDA18273_LO_CP_Current_Max ++} TDA18273LO_CP_Current_t, *pTDA18273LO_CP_Current_t; ++ ++typedef enum _TDA18273PD_Underload_t { ++ TDA18273_PD_Underload_Disabled = 0, /* PD Underload Disabled */ ++ TDA18273_PD_Underload_Enabled, /* PD Underload Enabled */ ++ TDA18273_PD_Underload_Max ++} TDA18273PD_Underload_t, *pTDA18273PD_Underload_t; ++ ++typedef struct _TDA18273StdCoefficients ++{ ++ /****************************************************************/ ++ /* IF Settings */ ++ /****************************************************************/ ++ UInt32 IF; /* IF Frequency */ ++ Int32 CF_Offset; ++ ++ /****************************************************************/ ++ /* IF SELECTIVITY Settings */ ++ /****************************************************************/ ++ TDA18273LPF_t LPF; /* LPF Cut off */ ++ TDA18273LPFOffset_t LPF_Offset; /* LPF offset */ ++ TDA18273DC_Notch_IF_PPF_t DC_Notch_IF_PPF; /* DC notch IF PPF */ ++ TDA18273IF_HPF_t IF_HPF; /* Hi Pass */ ++ TDA18273IF_Notch_t IF_Notch; /* IF notch */ ++ TDA18273IFnotchToRSSI_t IFnotchToRSSI; /* IFnotchToRSSI */ ++ ++ /****************************************************************/ ++ /* AGC TOP Settings */ ++ /****************************************************************/ ++ TDA18273AGC1_TOP_I2C_DN_UP_t AGC1_TOP_I2C_DN_UP; /* AGC1 TOP I2C DN/UP */ ++ TDA18273AGC1_Adapt_TOP_DN_UP_t AGC1_Adapt_TOP_DN_UP; /* AGC1 Adapt TOP DN/UP */ ++ TDA18273AGC1_DN_Time_Constant_t AGC1_DN_Time_Constant; /* AGC1 DN Time Constant */ ++ TDA18273AGC1_Mode_t AGC1_Mode; /* AGC1 mode */ ++ TDA18273Range_LNA_Adapt_t Range_LNA_Adapt; /* Range_LNA_Adapt */ ++ TDA18273LNA_Adapt_RFAGC_Gv_Threshold LNA_Adapt_RFAGC_Gv_Threshold; /* LNA_Adapt_RFAGC_Gv_Threshold */ ++ TDA18273AGC1_Top_Adapt_RFAGC_Gv_Threshold AGC1_Top_Adapt_RFAGC_Gv_Threshold; /* AGC1_Top_Adapt_RFAGC_Gv_Threshold */ ++ TDA18273AGC2_TOP_DN_UP_t AGC2_TOP_DN_UP; /* AGC2 TOP DN/UP */ ++ TDA18273AGC2_DN_Time_Constant_t AGC2_DN_Time_Constant; /* AGC2 DN Time Constant */ ++ TDA18273AGC3_TOP_I2C_t AGC3_TOP_I2C_Low_Band; /* AGC3 TOP I2C Low Band */ ++ TDA18273AGC3_TOP_I2C_t AGC3_TOP_I2C_High_Band; /* AGC3 TOP I2C High Band */ ++ TDA18273AGC4_TOP_DN_UP_t AGC4_TOP_DN_UP; /* AGC4 TOP DN/UP */ ++ TDA18273AGC5_TOP_DN_UP_t AGC5_TOP_DN_UP; /* AGC5 TOP DN/UP */ ++ TDA18273AGC3_Top_Adapt_Algorithm AGC3_Top_Adapt_Algorithm; /* AGC3_Top_Adapt_Algorithm */ ++ TDA18273AGC3_Adapt_TOP_t AGC3_Adapt_TOP_Low_Band; /* AGC3 Adapt TOP Low Band */ ++ TDA18273AGC3_Adapt_TOP_t AGC3_Adapt_TOP_High_Band; /* AGC3 Adapt TOP High Band */ ++ TDA18273AGC_Overload_TOP_t AGC_Overload_TOP; /* AGC Overload TOP */ ++ TDA18273TH_AGC_Adapt34_t TH_AGC_Adapt34; /* Adapt TOP 34 Gain Threshold */ ++ TDA18273RF_Atten_3dB_t RF_Atten_3dB; /* RF atten 3dB */ ++ TDA18273IF_Output_Level_t IF_Output_Level; /* IF Output Level */ ++ TDA18273S2D_Gain_t S2D_Gain; /* S2D gain */ ++ TDA18273Negative_Modulation_t Negative_Modulation; /* Negative modulation */ ++ ++ /****************************************************************/ ++ /* GSK Settings */ ++ /****************************************************************/ ++ TDA18273AGCK_Steps_t AGCK_Steps; /* Step */ ++ TDA18273AGCK_Time_Constant_t AGCK_Time_Constant; /* AGCK Time Constant */ ++ TDA18273AGC5_HPF_t AGC5_HPF; /* AGC5 HPF */ ++ TDA18273Pulse_Shaper_Disable_t Pulse_Shaper_Disable; /* Pulse Shaper Disable */ ++ ++ /****************************************************************/ ++ /* H3H5 Settings */ ++ /****************************************************************/ ++ TDA18273VHF_III_Mode_t VHF_III_Mode; /* VHF_III_Mode */ ++ ++ /****************************************************************/ ++ /* PLL Settings */ ++ /****************************************************************/ ++ TDA18273LO_CP_Current_t LO_CP_Current; /* LO_CP_Current */ ++ ++ /****************************************************************/ ++ /* MISC Settings */ ++ /****************************************************************/ ++ TDA18273PD_Underload_t PD_Underload; /* PD Underload */ ++ UInt32 Freq_Start_LTE; /* Frequency start of high band for LTE */ ++} TDA18273StdCoefficients, *pTDA18273StdCoefficients; ++ ++typedef struct _TDA18273Object_t ++{ ++ UInt32 uRF; ++ UInt32 uProgRF; ++ UInt32 uIF; ++ TDA18273StandardMode_t StandardMode; ++ pTDA18273StdCoefficients pStandard; ++ TDA18273StdCoefficients Std_Array[TDA18273_StandardMode_Max-1]; ++} TDA18273Object_t, *pTDA18273Object_t, **ppTDA18273Object_t; ++ ++/* Standard Preset Definitions: */ ++#define TDA18273_INSTANCE_CUSTOM_STD_QAM_6MHZ \ ++ { /* QAM 6MHz */ \ ++ 3600000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_6MHz, /* LPF */ \ ++ TDA18273_LPFOffset_min_4pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_1MHz, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89wdBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_WIDE, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_NO_TOP_ADAPT, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_QAM_8MHZ \ ++ { /* QAM 8MHz */ \ ++ 5000000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_9MHz, /* LPF */ \ ++ TDA18273_LPFOffset_min_8pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_0_85MHz, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89wdBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_WIDE, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_NO_TOP_ADAPT, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ATSC_6MHZ \ ++ { /* ATSC */ \ ++ 3250000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_6MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_0_4MHz, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d100_u94dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_104dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_104dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d112_u107dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d112_u107dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_3_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_3_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_6Vpp_min_10_3_19_7dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_3dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 662000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ISDBT_6MHZ \ ++ { /* ISDBT */ \ ++ 3250000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_6MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_0_4MHz, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_6Vpp_min_10_3_19_7dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_DVBT_1_7MHZ \ ++ { /* DVB-T/T2 1.7MHz */ \ ++ 850000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_1_5MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_4_094ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_2_047ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_94dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Enabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_DVBT_6MHZ \ ++ { /* DVB-T/T2 6MHz */ \ ++ 3250000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_6MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_0_4MHz, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_4_094ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_2_047ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_94dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Enabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_DVBT_7MHZ \ ++ { /* DVB-T/T2 7MHz */ \ ++ 3500000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_7MHz, /* LPF */ \ ++ TDA18273_LPFOffset_min_8pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_4_094ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_2_047ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_94dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Enabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_DVBT_8MHZ \ ++ { /* DVB-T/T2 8MHz */ \ ++ 4000000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_4_094ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_2_047ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_94dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Enabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_DVBT_10MHZ \ ++ { /* DVB-T/T2 10MHz */ \ ++ 5000000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_9MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_DMBT_8MHZ \ ++ { /* DMB-T */ \ ++ 4000000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT35, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_2_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Enabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Enabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_FM_RADIO \ ++ { /* FM */ \ ++ 1250000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_1_5MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_0_85MHz, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_8Vpp_min_8_22dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_MN \ ++ { /* NTSC M/N */ \ ++ 5400000, /* IF */ \ ++ 1750000, /* CF_Offset */ \ ++ TDA18273_LPF_6MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Enabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_B \ ++ { /* PAL B */ \ ++ 6400000, /* IF */ \ ++ 2250000, /* CF_Offset */ \ ++ TDA18273_LPF_7MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Enabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_GH \ ++ { /* PAL G/H */ \ ++ 6750000, /* IF */ \ ++ 2750000, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Enabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_I \ ++ { /* PAL I */ \ ++ 7250000, /* IF */ \ ++ 2750000, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Enabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_DK \ ++ { /* SECAM D/K */ \ ++ 6850000, /* IF */ \ ++ 2750000, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Enabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_L \ ++ { /* SECAM L */ \ ++ 6750000, /* IF */ \ ++ 2750000, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Enabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Disabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_6_min_9, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_LL \ ++ { /* SECAM L' */ \ ++ 1250000, /* IF */ \ ++ -2750000, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_6_min_9, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_ANALOG_BLIND_SCANNING \ ++ { /* Blind Scanning copy of PAL-I */ \ ++ 7250000, /* IF */ \ ++ 2750000, /* CF_Offset */ \ ++ TDA18273_LPF_8MHz, /* LPF */ \ ++ TDA18273_LPFOffset_0pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Disabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_Disabled, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89dBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_1_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_TOP_ADAPT, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_15_25dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_96dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d105_u100dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d105_u100dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_TOP_ADAPT34, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_1_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_0_7Vpp_min_9_21dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_1_STEP_EACH_VSYNC_RISING_EDGE, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Enabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++#define TDA18273_INSTANCE_CUSTOM_STD_SCANXPRESS \ ++ { /* ScanXpress */ \ ++ 5000000, /* IF */ \ ++ 0, /* CF_Offset */ \ ++ TDA18273_LPF_9MHz, /* LPF */ \ ++ TDA18273_LPFOffset_min_8pc, /* LPF_Offset */ \ ++ TDA18273_DC_Notch_IF_PPF_Enabled, /* DC notch IF PPF */ \ ++ TDA18273_IF_HPF_0_85MHz, /* Hi Pass */ \ ++ TDA18273_IF_Notch_Disabled, /* IF notch */ \ ++ TDA18273_IFnotchToRSSI_Enabled, /* IF notch To RSSI */ \ ++ TDA18273_AGC1_TOP_I2C_DN_UP_d95_u89wdBuV, /* AGC1 TOP I2C DN/UP */ \ ++ TDA18273_AGC1_Adapt_TOP_DN_UP_0_Step, /* AGC1 Adapt TOP DN/UP */ \ ++ TDA18273_AGC1_DN_Time_Constant_8_188ms, /* AGC1 DN Time Constant */ \ ++ TDA18273_AGC1_Mode_LNA_ADAPT_WIDE, /* AGC1 mode */ \ ++ TDA18273_Range_LNA_Adapt_20dB_11dB, /* Range LNA Adapt */ \ ++ TDA18273_LNA_Adapt_RFAGC_Gv_Threshold_18_25dB, /* LNA Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC1_Top_Adapt_RFAGC_Gv_Threshold_16_75dB, /* AGC1 TOP Adapt RFAGC Gv Threshold */ \ ++ TDA18273_AGC2_TOP_DN_UP_d90_u84dBuV, /* AGC2 TOP DN/UP */ \ ++ TDA18273_AGC2_DN_Time_Constant_8_188ms, /* AGC2 DN Time Constant */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C Low Band */ \ ++ TDA18273_AGC3_TOP_I2C_100dBuV, /* AGC3 TOP I2C High Band */ \ ++ TDA18273_AGC4_TOP_DN_UP_d110_u105dBuV, /* AGC4 TOP DN/UP */ \ ++ TDA18273_AGC5_TOP_DN_UP_d110_u105dBuV, /* AGC5 TOP DN/UP */ \ ++ TDA18273_Top_Adapt_NO_TOP_ADAPT, /* AGC3 TOP Adapt Algorithm */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt Low Band */ \ ++ TDA18273_AGC3_Adapt_TOP_0_Step, /* AGC3 Adapt High Band */ \ ++ TDA18273_AGC_Overload_TOP_plus_9_plus_4_5_min_3_5, /* AGC Overload TOP */ \ ++ TDA18273_TH_AGC_Adapt34_5dB, /* Adapt TOP 34 Gain Threshold */ \ ++ TDA18273_RF_Atten_3dB_Disabled, /* RF Atten 3dB */ \ ++ TDA18273_IF_Output_Level_1Vpp_min_6_24dB, /* IF Output Level */ \ ++ TDA18273_S2D_Gain_6dB, /* S2D Gain */ \ ++ TDA18273_Negative_Modulation_Disabled, /* Negative Modulation */ \ ++ TDA18273_AGCK_Steps_0_2dB, /* Step */ \ ++ TDA18273_AGCK_Time_Constant_32_768ms, /* AGCK Time Constant */ \ ++ TDA18273_AGC5_HPF_Disabled, /* AGC5 HPF */ \ ++ TDA18273_Pulse_Shaper_Disable_Enabled, /* Pulse Shaper Disable */ \ ++ TDA18273_VHF_III_Mode_Disabled, /* VHF III Mode */ \ ++ TDA18273_LO_CP_Current_Enabled, /* LO CP Current */ \ ++ TDA18273_PD_Underload_Disabled, /* PD Underload */ \ ++ 754000000 /* Frequency Start LTE */ \ ++ } ++ ++/* Standard Presets Aggregation: */ ++#define TDA18273_INSTANCE_CUSTOM_STD_DEF \ ++ { \ ++ TDA18273_INSTANCE_CUSTOM_STD_QAM_6MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_QAM_8MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ATSC_6MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ISDBT_6MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_DVBT_1_7MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_DVBT_6MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_DVBT_7MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_DVBT_8MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_DVBT_10MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_DMBT_8MHZ, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_FM_RADIO, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_MN, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_B, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_GH, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_I, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_DK, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_L, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_LL, \ ++ TDA18273_INSTANCE_CUSTOM_STD_ANALOG_BLIND_SCANNING, \ ++ TDA18273_INSTANCE_CUSTOM_STD_SCANXPRESS \ ++ } ++ ++#endif /* __TDA18273_PRIV */ +diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig +index 0cced3e..c7d9e6a 100644 +--- a/drivers/media/usb/cx231xx/Kconfig ++++ b/drivers/media/usb/cx231xx/Kconfig +@@ -51,6 +51,11 @@ config VIDEO_CX231XX_DVB + select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT + select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CXD2820R if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_TAS2101 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_AV201X if MEDIA_SUBDRV_AUTOSELECT + + ---help--- + This adds support for DVB cards based on the +diff --git a/drivers/media/usb/cx231xx/Makefile b/drivers/media/usb/cx231xx/Makefile +index 52cf769..21e041d 100644 +--- a/drivers/media/usb/cx231xx/Makefile ++++ b/drivers/media/usb/cx231xx/Makefile +@@ -6,7 +6,8 @@ cx231xx-alsa-objs := cx231xx-audio.o + + obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o + obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o +-obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o ++obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb-ci.o ++cx231xx-dvb-ci-objs += cx231xx-dvb.o tbscxci.o + + ccflags-y += -Idrivers/media/i2c + ccflags-y += -Idrivers/media/tuners +diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c +index 2f52d66..af189af 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c ++++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c +@@ -360,6 +360,9 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev, + case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: + case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: + case CX231XX_BOARD_OTG102: ++ case CX231XX_BOARD_TBS_5280: ++ case CX231XX_BOARD_TBS_5281: ++ case CX231XX_BOARD_TBS_5990: + if (avmode == POLARIS_AVMODE_ANALOGT_TV) { + while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL)) { +@@ -2667,7 +2670,7 @@ EXPORT_SYMBOL_GPL(cx231xx_capture_start); + /***************************************************************************** + * G P I O B I T control functions * + ******************************************************************************/ +-static int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 gpio_val) ++ int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 gpio_val) + { + int status = 0; + +@@ -2677,7 +2680,10 @@ static int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 gpio_val) + return status; + } + +-static int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 *gpio_val) ++ ++EXPORT_SYMBOL_GPL(cx231xx_set_gpio_bit); ++ ++ int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 *gpio_val) + { + __le32 tmp; + int status = 0; +@@ -2688,6 +2694,8 @@ static int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 *gpio_val + return status; + } + ++EXPORT_SYMBOL_GPL(cx231xx_get_gpio_bit); ++ + /* + * cx231xx_set_gpio_direction + * Sets the direction of the GPIO pin to input or output +@@ -2723,6 +2731,8 @@ int cx231xx_set_gpio_direction(struct cx231xx *dev, + return status; + } + ++EXPORT_SYMBOL_GPL(cx231xx_set_gpio_direction); ++ + /* + * cx231xx_set_gpio_value + * Sets the value of the GPIO pin to Logic high or low. The Pin under +@@ -2767,6 +2777,10 @@ int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value) + return status; + } + ++EXPORT_SYMBOL_GPL(cx231xx_set_gpio_value); ++ ++ ++ + /***************************************************************************** + * G P I O I2C related functions * + ******************************************************************************/ +diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c +index 36bc254..19851a1 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-cards.c ++++ b/drivers/media/usb/cx231xx/cx231xx-cards.c +@@ -106,6 +106,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x02, + .norm = V4L2_STD_PAL, + +@@ -146,6 +147,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x32, + .norm = V4L2_STD_NTSC, + +@@ -186,6 +188,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x02, + .norm = V4L2_STD_PAL, + +@@ -227,6 +230,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x02, + .norm = V4L2_STD_PAL, + +@@ -298,6 +302,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x02, + .norm = V4L2_STD_PAL, + +@@ -326,6 +331,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x32, + .norm = V4L2_STD_NTSC, + +@@ -354,6 +360,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_1, + .demod_i2c_master = I2C_1_MUX_1, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x0e, + .norm = V4L2_STD_NTSC, + +@@ -419,6 +426,7 @@ struct cx231xx_board cx231xx_boards[] = { + .demod_i2c_master = I2C_1_MUX_3, + .ir_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x10, + .norm = V4L2_STD_PAL_M, + .input = {{ +@@ -457,6 +465,7 @@ struct cx231xx_board cx231xx_boards[] = { + .demod_i2c_master = I2C_1_MUX_3, + .ir_i2c_master = I2C_2, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x10, + .norm = V4L2_STD_NTSC_M, + .input = {{ +@@ -496,6 +505,7 @@ struct cx231xx_board cx231xx_boards[] = { + .ir_i2c_master = I2C_2, + .rc_map_name = RC_MAP_PIXELVIEW_002T, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x10, + .norm = V4L2_STD_PAL_M, + .input = {{ +@@ -793,6 +803,7 @@ struct cx231xx_board cx231xx_boards[] = { + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_1_MUX_3, + .has_dvb = 1, ++ .adap_cnt = 1, + .demod_addr = 0x0e, + .norm = V4L2_STD_NTSC, + +@@ -841,6 +852,121 @@ struct cx231xx_board cx231xx_boards[] = { + .gpio = NULL, + } }, + }, ++ [CX231XX_BOARD_TBS_5280] = { ++ .name = "TurboSight TBS 5280", ++ .tuner_type = TUNER_ABSENT, ++ .decoder = CX231XX_AVDECODER, ++ .output_mode = OUT_MODE_VIP11, ++ .demod_xfer_mode = 0, ++ .ctl_pin_status_mask = 0xFFFFFFC4, ++ .agc_analog_digital_select_gpio = 0x00, ++ .tuner_sif_gpio = -1, ++ .tuner_scl_gpio = -1, ++ .tuner_sda_gpio = -1, ++ .gpio_pin_status_mask = 0x4001000, ++ .tuner_i2c_master = 2, ++ .demod_i2c_master = 1, ++ .has_dvb = 1, ++ .adap_cnt = 2, ++ .demod_addr = 0x6c, ++ .norm = V4L2_STD_PAL_M, ++ ++ .input = {{ ++ .type = CX231XX_VMUX_TELEVISION, ++ .vmux = CX231XX_VIN_3_1, ++ .amux = CX231XX_AMUX_VIDEO, ++ .gpio = NULL, ++ }, { ++ .type = CX231XX_VMUX_COMPOSITE1, ++ .vmux = CX231XX_VIN_2_1, ++ .amux = CX231XX_AMUX_LINE_IN, ++ .gpio = NULL, ++ }, { ++ .type = CX231XX_VMUX_SVIDEO, ++ .vmux = CX231XX_VIN_1_1 | ++ (CX231XX_VIN_1_2 << 8) | ++ CX25840_SVIDEO_ON, ++ .amux = CX231XX_AMUX_LINE_IN, ++ .gpio = NULL, ++ } }, ++ }, ++ [CX231XX_BOARD_TBS_5281] = { ++ .name = "TurboSight TBS 5281", ++ .tuner_type = TUNER_ABSENT, ++ .decoder = CX231XX_AVDECODER, ++ .output_mode = OUT_MODE_VIP11, ++ .demod_xfer_mode = 0, ++ .ctl_pin_status_mask = 0xFFFFFFC4, ++ .agc_analog_digital_select_gpio = 0x00, ++ .tuner_sif_gpio = -1, ++ .tuner_scl_gpio = -1, ++ .tuner_sda_gpio = -1, ++ .gpio_pin_status_mask = 0x4001000, ++ .tuner_i2c_master = I2C_2, ++ .demod_i2c_master = I2C_1, ++ .has_dvb = 1, ++ .adap_cnt = 2, ++ .demod_addr = 0x6c, ++ .norm = V4L2_STD_PAL_M, ++ ++ .input = {{ ++ .type = CX231XX_VMUX_TELEVISION, ++ .vmux = CX231XX_VIN_3_1, ++ .amux = CX231XX_AMUX_VIDEO, ++ .gpio = NULL, ++ }, { ++ .type = CX231XX_VMUX_COMPOSITE1, ++ .vmux = CX231XX_VIN_2_1, ++ .amux = CX231XX_AMUX_LINE_IN, ++ .gpio = NULL, ++ }, { ++ .type = CX231XX_VMUX_SVIDEO, ++ .vmux = CX231XX_VIN_1_1 | ++ (CX231XX_VIN_1_2 << 8) | ++ CX25840_SVIDEO_ON, ++ .amux = CX231XX_AMUX_LINE_IN, ++ .gpio = NULL, ++ } }, ++ }, ++ [CX231XX_BOARD_TBS_5990] = { ++ .name = "TurboSight TBS 5990", ++ .tuner_type = TUNER_ABSENT, ++ .decoder = CX231XX_AVDECODER, ++ .output_mode = OUT_MODE_VIP11, ++ .demod_xfer_mode = 0, ++ .ctl_pin_status_mask = 0xFFFFFFC4, ++ .agc_analog_digital_select_gpio = 0x00, ++ .tuner_sif_gpio = -1, ++ .tuner_scl_gpio = -1, ++ .tuner_sda_gpio = -1, ++ .gpio_pin_status_mask = 0x4001000, ++ .tuner_i2c_master = I2C_2, ++ .demod_i2c_master = I2C_1, ++ .has_dvb = 1, ++ .adap_cnt = 2, ++ .demod_addr = 0x60, ++ .norm = V4L2_STD_PAL_M, ++ ++ .input = {{ ++ .type = CX231XX_VMUX_TELEVISION, ++ .vmux = CX231XX_VIN_3_1, ++ .amux = CX231XX_AMUX_VIDEO, ++ .gpio = NULL, ++ }, { ++ .type = CX231XX_VMUX_COMPOSITE1, ++ .vmux = CX231XX_VIN_2_1, ++ .amux = CX231XX_AMUX_LINE_IN, ++ .gpio = NULL, ++ }, { ++ .type = CX231XX_VMUX_SVIDEO, ++ .vmux = CX231XX_VIN_1_1 | ++ (CX231XX_VIN_1_2 << 8) | ++ CX25840_SVIDEO_ON, ++ .amux = CX231XX_AMUX_LINE_IN, ++ .gpio = NULL, ++ } }, ++ }, ++ + }; + const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); + +@@ -908,6 +1034,13 @@ struct usb_device_id cx231xx_id_table[] = { + .driver_info = CX231XX_BOARD_OTG102}, + {USB_DEVICE(USB_VID_TERRATEC, 0x00a6), + .driver_info = CX231XX_BOARD_TERRATEC_GRABBY}, ++ {USB_DEVICE(0x734c, 0x5280), ++ .driver_info = CX231XX_BOARD_TBS_5280}, ++ {USB_DEVICE(0x734c, 0x5281), ++ .driver_info = CX231XX_BOARD_TBS_5281}, ++ {USB_DEVICE(0x734c, 0x5990), ++ .driver_info = CX231XX_BOARD_TBS_5990}, ++ + {}, + }; + +@@ -1358,7 +1491,7 @@ static void request_module_async(struct work_struct *work) + request_module("cx231xx-alsa"); + + if (dev->board.has_dvb) +- request_module("cx231xx-dvb"); ++ request_module("cx231xx-dvb-ci"); + + } + +@@ -1674,6 +1807,44 @@ static int cx231xx_usb_probe(struct usb_interface *interface, + } + } + ++ if (dev->current_pcb_config.ts2_source != 0xff) { ++ /* compute alternate max packet sizes for TS2 */ ++ idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts2_index + 1; ++ if (idx >= dev->max_iad_interface_count) { ++ dev_err(d, "TS2 PCB interface #%d doesn't exist\n", ++ idx); ++ retval = -ENODEV; ++ goto err_video_alt; ++ } ++ uif = udev->actconfig->interface[idx]; ++ ++ dev->ts2_mode.end_point_addr = ++ uif->altsetting[0].endpoint[isoc_pipe]. ++ desc.bEndpointAddress; ++ ++ dev->ts2_mode.num_alt = uif->num_altsetting; ++ dev_info(d, ++ "TS EndPoint Addr 0x%x, Alternate settings: %i\n", ++ dev->ts2_mode.end_point_addr, ++ dev->ts2_mode.num_alt); ++ ++ dev->ts2_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts2_mode.num_alt, GFP_KERNEL); ++ if (dev->ts2_mode.alt_max_pkt_size == NULL) { ++ retval = -ENOMEM; ++ goto err_video_alt; ++ } ++ ++ for (i = 0; i < dev->ts2_mode.num_alt; i++) { ++ u16 tmp = le16_to_cpu(uif->altsetting[i]. ++ endpoint[isoc_pipe].desc. ++ wMaxPacketSize); ++ dev->ts2_mode.alt_max_pkt_size[i] = ++ (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); ++ dev_dbg(d, "Alternate setting %i, max size= %i\n", ++ i, dev->ts2_mode.alt_max_pkt_size[i]); ++ } ++ } ++ + if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) { + cx231xx_enable_OSC(dev); + cx231xx_reset_out(dev); +diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c +index 550ec93..ceb0344 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-core.c ++++ b/drivers/media/usb/cx231xx/cx231xx-core.c +@@ -542,6 +542,10 @@ int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + ts2_index + 1; ++ dev->ts2_mode.alt = alt; ++ if (dev->ts2_mode.alt_max_pkt_size != NULL) ++ max_pkt_size = dev->ts2_mode.max_pkt_size = ++ dev->ts2_mode.alt_max_pkt_size[dev->ts2_mode.alt]; + break; + case INDEX_AUDIO: + usb_interface_index = +@@ -728,7 +732,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_SHELBY: + case CX231XX_BOARD_CNXT_RDU_250: +- errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); ++ errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); + break; + case CX231XX_BOARD_CNXT_RDE_253S: + case CX231XX_BOARD_CNXT_RDU_253S: +@@ -737,6 +741,9 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: + case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: + case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: ++ case CX231XX_BOARD_TBS_5280: ++ case CX231XX_BOARD_TBS_5281: ++ case CX231XX_BOARD_TBS_5990: + errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); + break; + default: +@@ -826,6 +833,47 @@ static void cx231xx_isoc_irq_callback(struct urb *urb) + urb->status); + } + } ++ ++static void cx231xx_isoc_irq_callback_ts2(struct urb *urb) ++{ ++ struct cx231xx_dmaqueue *dma_q = urb->context; ++ struct cx231xx_video_mode *vmode = ++ container_of(dma_q, struct cx231xx_video_mode, vidq); ++ struct cx231xx *dev = container_of(vmode, struct cx231xx, ts2_mode); ++ int i; ++ ++ switch (urb->status) { ++ case 0: /* success */ ++ case -ETIMEDOUT: /* NAK */ ++ break; ++ case -ECONNRESET: /* kill */ ++ case -ENOENT: ++ case -ESHUTDOWN: ++ return; ++ default: /* error */ ++ cx231xx_isocdbg("urb completition error %d.\n", urb->status); ++ break; ++ } ++ ++ /* Copy data from URB */ ++ spin_lock(&dev->ts2_mode.slock); ++ dev->ts2_mode.isoc_ctl.isoc_copy(dev, urb); ++ spin_unlock(&dev->ts2_mode.slock); ++ ++ /* Reset urb buffers */ ++ for (i = 0; i < urb->number_of_packets; i++) { ++ urb->iso_frame_desc[i].status = 0; ++ urb->iso_frame_desc[i].actual_length = 0; ++ } ++ urb->status = 0; ++ ++ urb->status = usb_submit_urb(urb, GFP_ATOMIC); ++ if (urb->status) { ++ cx231xx_isocdbg("urb resubmit failed (error=%i)\n", ++ urb->status); ++ } ++} ++ + /***************************************************************** + * URB Streaming functions * + ******************************************************************/ +@@ -927,6 +975,54 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) + } + EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); + ++void cx231xx_uninit_isoc_ts2(struct cx231xx *dev) ++{ ++ struct cx231xx_dmaqueue *dma_q_ts2 = &dev->ts2_mode.vidq; ++ struct urb *urb; ++ int i; ++ ++ cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc_ts2\n"); ++ ++ dev->ts2_mode.isoc_ctl.nfields = -1; ++ for (i = 0; i < dev->ts2_mode.isoc_ctl.num_bufs; i++) { ++ urb = dev->ts2_mode.isoc_ctl.urb[i]; ++ if (urb) { ++ if (!irqs_disabled()) ++ usb_kill_urb(urb); ++ else ++ usb_unlink_urb(urb); ++ ++ if (dev->ts2_mode.isoc_ctl.transfer_buffer[i]) { ++ usb_free_coherent(dev->udev, ++ urb->transfer_buffer_length, ++ dev->ts2_mode.isoc_ctl. ++ transfer_buffer[i], ++ urb->transfer_dma); ++ } ++ usb_free_urb(urb); ++ dev->ts2_mode.isoc_ctl.urb[i] = NULL; ++ } ++ dev->ts2_mode.isoc_ctl.transfer_buffer[i] = NULL; ++ } ++ ++ kfree(dev->ts2_mode.isoc_ctl.urb); ++ kfree(dev->ts2_mode.isoc_ctl.transfer_buffer); ++ kfree(dma_q_ts2->p_left_data); ++ ++ dev->ts2_mode.isoc_ctl.urb = NULL; ++ dev->ts2_mode.isoc_ctl.transfer_buffer = NULL; ++ dev->ts2_mode.isoc_ctl.num_bufs = 0; ++ dma_q_ts2->p_left_data = NULL; ++ ++ if (dev->mode_tv == 0) ++ cx231xx_capture_start(dev, 0, Raw_Video); ++ else ++ cx231xx_capture_start(dev, 0, TS2); ++ ++ ++} ++EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc_ts2); ++ + /* + * Stop and Deallocate URBs + */ +@@ -1121,6 +1217,141 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, + } + EXPORT_SYMBOL_GPL(cx231xx_init_isoc); + ++int cx231xx_init_isoc_ts2(struct cx231xx *dev, int max_packets, ++ int num_bufs, int max_pkt_size, ++ int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) ++{ ++ struct cx231xx_dmaqueue *dma_q_ts2 = &dev->ts2_mode.vidq; ++ int i; ++ int sb_size, pipe; ++ struct urb *urb; ++ int j, k; ++ int rc; ++ ++ /* De-allocates all pending stuff */ ++ cx231xx_uninit_isoc_ts2(dev); ++ ++ dma_q_ts2->p_left_data = kzalloc(4096, GFP_KERNEL); ++ if (dma_q_ts2->p_left_data == NULL) ++ return -ENOMEM; ++ ++ dev->ts2_mode.isoc_ctl.isoc_copy = isoc_copy; ++ dev->ts2_mode.isoc_ctl.num_bufs = num_bufs; ++ dma_q_ts2->pos = 0; ++ dma_q_ts2->is_partial_line = 0; ++ dma_q_ts2->last_sav = 0; ++ dma_q_ts2->current_field = -1; ++ dma_q_ts2->field1_done = 0; ++ dma_q_ts2->lines_per_field = dev->height / 2; ++ dma_q_ts2->bytes_left_in_line = dev->width << 1; ++ dma_q_ts2->lines_completed = 0; ++ dma_q_ts2->mpeg_buffer_done = 0; ++ dma_q_ts2->left_data_count = 0; ++ dma_q_ts2->mpeg_buffer_completed = 0; ++ dma_q_ts2->add_ps_package_head = CX231XX_NEED_ADD_PS_PACKAGE_HEAD; ++ dma_q_ts2->ps_head[0] = 0x00; ++ dma_q_ts2->ps_head[1] = 0x00; ++ dma_q_ts2->ps_head[2] = 0x01; ++ dma_q_ts2->ps_head[3] = 0xBA; ++ for (i = 0; i < 8; i++) ++ dma_q_ts2->partial_buf[i] = 0; ++ ++ dev->ts2_mode.isoc_ctl.urb = ++ kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); ++ if (!dev->ts2_mode.isoc_ctl.urb) { ++ dev_err(dev->dev, ++ "cannot alloc memory for usb buffers\n"); ++ return -ENOMEM; ++ } ++ ++ dev->ts2_mode.isoc_ctl.transfer_buffer = ++ kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); ++ if (!dev->ts2_mode.isoc_ctl.transfer_buffer) { ++ dev_err(dev->dev, ++ "cannot allocate memory for usbtransfer\n"); ++ kfree(dev->ts2_mode.isoc_ctl.urb); ++ return -ENOMEM; ++ } ++ ++ dev->ts2_mode.isoc_ctl.max_pkt_size = max_pkt_size; ++ dev->ts2_mode.isoc_ctl.buf = NULL; ++ ++ sb_size = max_packets * dev->ts2_mode.isoc_ctl.max_pkt_size; ++ ++ if (dev->mode_tv == 1) ++ dev->ts2_mode.end_point_addr = 0x82; ++ else ++ dev->ts2_mode.end_point_addr = 0x84; ++ ++ ++ /* allocate urbs and transfer buffers */ ++ for (i = 0; i < dev->ts2_mode.isoc_ctl.num_bufs; i++) { ++ urb = usb_alloc_urb(max_packets, GFP_KERNEL); ++ if (!urb) { ++ dev_err(dev->dev, ++ "cannot alloc isoc_ctl.urb %i\n", i); ++ cx231xx_uninit_isoc_ts2(dev); ++ return -ENOMEM; ++ } ++ dev->ts2_mode.isoc_ctl.urb[i] = urb; ++ ++ dev->ts2_mode.isoc_ctl.transfer_buffer[i] = ++ usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, ++ &urb->transfer_dma); ++ if (!dev->ts2_mode.isoc_ctl.transfer_buffer[i]) { ++ dev_err(dev->dev, ++ "unable to allocate %i bytes for transfer" ++ " buffer %i%s\n", ++ sb_size, i, ++ in_interrupt() ? " while in int" : ""); ++ cx231xx_uninit_isoc_ts2(dev); ++ return -ENOMEM; ++ } ++ memset(dev->ts2_mode.isoc_ctl.transfer_buffer[i], 0, sb_size); ++ ++ pipe = ++ usb_rcvisocpipe(dev->udev, dev->ts2_mode.end_point_addr); ++ ++ usb_fill_int_urb(urb, dev->udev, pipe, ++ dev->ts2_mode.isoc_ctl.transfer_buffer[i], ++ sb_size, cx231xx_isoc_irq_callback_ts2, dma_q_ts2, 1); ++ ++ urb->number_of_packets = max_packets; ++ urb->transfer_flags = URB_ISO_ASAP; ++ ++ k = 0; ++ for (j = 0; j < max_packets; j++) { ++ urb->iso_frame_desc[j].offset = k; ++ urb->iso_frame_desc[j].length = ++ dev->ts2_mode.isoc_ctl.max_pkt_size; ++ k += dev->ts2_mode.isoc_ctl.max_pkt_size; ++ } ++ } ++ ++ init_waitqueue_head(&dma_q_ts2->wq); ++ ++ /* submit urbs and enables IRQ */ ++ for (i = 0; i < dev->ts2_mode.isoc_ctl.num_bufs; i++) { ++ rc = usb_submit_urb(dev->ts2_mode.isoc_ctl.urb[i], ++ GFP_ATOMIC); ++ if (rc) { ++ dev_err(dev->dev, ++ "submit of urb %i failed (error=%i)\n", i, ++ rc); ++ cx231xx_uninit_isoc_ts2(dev); ++ return rc; ++ } ++ } ++ ++ if (dev->mode_tv == 0) ++ cx231xx_capture_start(dev, 1, Raw_Video); ++ else ++ cx231xx_capture_start(dev, 1, TS2); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(cx231xx_init_isoc_ts2); ++ + /* + * Allocate URBs and start IRQ + */ +@@ -1348,8 +1579,9 @@ int cx231xx_dev_init(struct cx231xx *dev) + + /* scan the real bus segments in the order of physical port numbers */ + cx231xx_do_i2c_scan(dev, I2C_0); +- cx231xx_do_i2c_scan(dev, I2C_1_MUX_1); ++ cx231xx_do_i2c_scan(dev, I2C_1); + cx231xx_do_i2c_scan(dev, I2C_2); ++ cx231xx_do_i2c_scan(dev, I2C_1_MUX_1); + cx231xx_do_i2c_scan(dev, I2C_1_MUX_3); + + /* init hardware */ +@@ -1388,6 +1620,7 @@ int cx231xx_dev_init(struct cx231xx *dev) + __func__, errCode); + return errCode; + } ++ + errCode = cx231xx_afe_init_channels(dev); + if (errCode < 0) { + dev_err(dev->dev, +@@ -1395,7 +1628,6 @@ int cx231xx_dev_init(struct cx231xx *dev) + __func__, errCode); + return errCode; + } +- + /* Set DIF in By pass mode */ + errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (errCode < 0) { +@@ -1404,7 +1636,6 @@ int cx231xx_dev_init(struct cx231xx *dev) + __func__, errCode); + return errCode; + } +- + /* I2S block related functions */ + errCode = cx231xx_i2s_blk_initialize(dev); + if (errCode < 0) { +@@ -1413,7 +1644,6 @@ int cx231xx_dev_init(struct cx231xx *dev) + __func__, errCode); + return errCode; + } +- + /* init control pins */ + errCode = cx231xx_init_ctrl_pin_status(dev); + if (errCode < 0) { +@@ -1422,7 +1652,6 @@ int cx231xx_dev_init(struct cx231xx *dev) + __func__, errCode); + return errCode; + } +- + /* set AGC mode to Analog */ + switch (dev->model) { + case CX231XX_BOARD_CNXT_CARRAERA: +@@ -1438,6 +1667,9 @@ int cx231xx_dev_init(struct cx231xx *dev) + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: + case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: + case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: ++ case CX231XX_BOARD_TBS_5280: ++ case CX231XX_BOARD_TBS_5281: ++ case CX231XX_BOARD_TBS_5990: + errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); + break; + default: +@@ -1449,15 +1681,19 @@ int cx231xx_dev_init(struct cx231xx *dev) + __func__, errCode); + return errCode; + } +- + /* set all alternate settings to zero initially */ + cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + cx231xx_set_alt_setting(dev, INDEX_HANC, 0); +- if (dev->board.has_dvb) ++ if (dev->board.has_dvb) { + cx231xx_set_alt_setting(dev, INDEX_TS1, 0); ++ if (dev->board.adap_cnt == 2) ++ cx231xx_set_alt_setting(dev, INDEX_TS2, 0); ++ } ++ ++ ++ errCode = cx231xx_enable_i2c_port_3( dev,true); + +- errCode = 0; + return errCode; + } + EXPORT_SYMBOL_GPL(cx231xx_dev_init); +diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c +index 2868546..5fafc20 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c ++++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c +@@ -35,7 +35,13 @@ + #include "si2165.h" + #include "mb86a20s.h" + #include "si2157.h" ++#include "si2168.h" + #include "lgdt3306a.h" ++#include "tda18212.h" ++#include "cxd2820r.h" ++#include "tas2101.h" ++#include "av201x.h" ++#include "tbscxci.h" + + MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); + MODULE_AUTHOR("Srinivasa Deevi "); +@@ -51,24 +57,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define CX231XX_DVB_MAX_PACKETSIZE 564 + #define CX231XX_DVB_MAX_PACKETS 64 + +-struct cx231xx_dvb { +- struct dvb_frontend *frontend; +- +- /* feed count management */ +- struct mutex lock; +- int nfeeds; +- +- /* general boilerplate stuff */ +- struct dvb_adapter adapter; +- struct dvb_demux demux; +- struct dmxdev dmxdev; +- struct dmx_frontend fe_hw; +- struct dmx_frontend fe_mem; +- struct dvb_net net; +- struct i2c_client *i2c_client_demod; +- struct i2c_client *i2c_client_tuner; +-}; +- + static struct s5h1432_config dvico_s5h1432_config = { + .output_mode = S5H1432_SERIAL_OUTPUT, + .gpio = S5H1432_GPIO_ON, +@@ -163,6 +151,28 @@ static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { + .xtalMHz = 25, + }; + ++static struct cxd2820r_config cxd2820r_config0 = { ++ .i2c_address = 0x6c, /* (0xd8 >> 1) */ ++ .ts_mode = 0x08, ++}; ++ ++static struct cxd2820r_config cxd2820r_config1 = { ++ .i2c_address = 0x6d, /* (0xda >> 1) */ ++ .ts_mode = 0x08, ++}; ++ ++static struct tda18212_config tda18212_config = { ++ .if_dvbt_6 = 3550, ++ .if_dvbt_7 = 3700, ++ .if_dvbt_8 = 4150, ++ .if_dvbt2_6 = 3250, ++ .if_dvbt2_7 = 4000, ++ .if_dvbt2_8 = 4000, ++ .if_dvbc = 5000, ++ .loop_through = 1, ++ .xtout = 1 ++}; ++ + static inline void print_err_status(struct cx231xx *dev, int packet, int status) + { + char *errmsg = "Unknown"; +@@ -228,7 +238,41 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb) + continue; + } + +- dvb_dmx_swfilter(&dev->dvb->demux, ++ dvb_dmx_swfilter(&dev->dvb[0]->demux, ++ urb->transfer_buffer + ++ urb->iso_frame_desc[i].offset, ++ urb->iso_frame_desc[i].actual_length); ++ } ++ ++ return 0; ++} ++ ++static inline int dvb_isoc_copy_ts2(struct cx231xx *dev, struct urb *urb) ++{ ++ int i; ++ ++ if (!dev) ++ return 0; ++ ++ if (dev->state & DEV_DISCONNECTED) ++ return 0; ++ ++ if (urb->status < 0) { ++ print_err_status(dev, -1, urb->status); ++ if (urb->status == -ENOENT) ++ return 0; ++ } ++ ++ for (i = 0; i < urb->number_of_packets; i++) { ++ int status = urb->iso_frame_desc[i].status; ++ ++ if (status < 0) { ++ print_err_status(dev, i, status); ++ if (urb->iso_frame_desc[i].status != -EPROTO) ++ continue; ++ } ++ ++ dvb_dmx_swfilter(&dev->dvb[1]->demux, + urb->transfer_buffer + + urb->iso_frame_desc[i].offset, + urb->iso_frame_desc[i].actual_length); +@@ -252,7 +296,7 @@ static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb) + } + + /* Feed the transport payload into the kernel demux */ +- dvb_dmx_swfilter(&dev->dvb->demux, ++ dvb_dmx_swfilter(&dev->dvb[0]->demux, + urb->transfer_buffer, urb->actual_length); + + return 0; +@@ -265,26 +309,43 @@ static int start_streaming(struct cx231xx_dvb *dvb) + + if (dev->USE_ISO) { + dev_dbg(dev->dev, "DVB transfer mode is ISO.\n"); +- cx231xx_set_alt_setting(dev, INDEX_TS1, 4); ++ mutex_lock(&dev->i2c_lock); ++ cx231xx_enable_i2c_port_3(dev, false); ++ if (dvb->count == 0) ++ cx231xx_set_alt_setting(dev, INDEX_TS1, 4); ++ if (dvb->count == 1) ++ cx231xx_set_alt_setting(dev, INDEX_TS2, 4); ++ cx231xx_enable_i2c_port_3(dev, true); ++ mutex_unlock(&dev->i2c_lock); + rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); + if (rc < 0) + return rc; + dev->mode_tv = 1; ++ if (dvb->count == 1) ++ return cx231xx_init_isoc_ts2(dev, CX231XX_DVB_MAX_PACKETS, ++ CX231XX_DVB_NUM_BUFS, ++ dev->ts2_mode.max_pkt_size, ++ dvb_isoc_copy_ts2); ++ else + return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS, +- CX231XX_DVB_NUM_BUFS, +- dev->ts1_mode.max_pkt_size, +- dvb_isoc_copy); ++ CX231XX_DVB_NUM_BUFS, ++ dev->ts1_mode.max_pkt_size, ++ dvb_isoc_copy); + } else { + dev_dbg(dev->dev, "DVB transfer mode is BULK.\n"); +- cx231xx_set_alt_setting(dev, INDEX_TS1, 0); ++ if (dvb->count == 0) ++ cx231xx_set_alt_setting(dev, INDEX_TS1, 0); ++ if (dvb->count == 1) ++ cx231xx_set_alt_setting(dev, INDEX_TS2, 0); + rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); + if (rc < 0) + return rc; + dev->mode_tv = 1; + return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS, +- CX231XX_DVB_NUM_BUFS, +- dev->ts1_mode.max_pkt_size, +- dvb_bulk_copy); ++ CX231XX_DVB_NUM_BUFS, ++ dvb->count ? dev->ts2_mode.max_pkt_size ++ : dev->ts1_mode.max_pkt_size, ++ dvb_bulk_copy); + } + + } +@@ -294,7 +355,10 @@ static int stop_streaming(struct cx231xx_dvb *dvb) + struct cx231xx *dev = dvb->adapter.priv; + + if (dev->USE_ISO) +- cx231xx_uninit_isoc(dev); ++ if (dvb->count == 0) ++ cx231xx_uninit_isoc(dev); ++ if (dvb->count == 1) ++ cx231xx_uninit_isoc_ts2(dev); + else + cx231xx_uninit_bulk(dev); + +@@ -363,7 +427,52 @@ static struct xc5000_config cnxt_rdu250_tunerconfig = { + .i2c_address = 0x61, + .if_khz = 3250, + }; ++static void tbs5990_lnb_power(struct dvb_frontend *fe, ++ int enpwr_pin, int onoff) ++{ ++ struct cx231xx *dev = fe->dvb->priv; ++ ++ /* lnb power, active low */ ++ cx231xx_set_gpio_direction(dev, enpwr_pin, 1); ++ if (onoff) ++ cx231xx_set_gpio_value(dev, enpwr_pin, 0); ++ else ++ cx231xx_set_gpio_value(dev, enpwr_pin, 1); ++} ++ ++static void tbs5990_lnb0_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs5990_lnb_power(fe, 26, onoff); ++} ++ ++static void tbs5990_lnb1_power(struct dvb_frontend *fe, int onoff) ++{ ++ tbs5990_lnb_power(fe, 22, onoff); ++} + ++static struct tas2101_config tbs5990_config0 ={ ++ .i2c_address = 0x60, ++ .id = ID_TAS2101, ++ .reset_demod = NULL, ++ .lnb_power = tbs5990_lnb0_power, ++ .init = {0x80, 0xAB, 0x47, 0x61, 0x25, 0x93, 0x31}, ++ .init2 = 0, ++ ++}; ++static struct tas2101_config tbs5990_config1 ={ ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = NULL, ++ .lnb_power = tbs5990_lnb1_power, ++ .init = {0xB0, 0xA8, 0x21, 0x53, 0x74, 0x96, 0x31}, ++ .init2 = 0, ++ ++}; ++static struct av201x_config tbs5990_tuner_config = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, ++}; + /* ------------------------------------------------------------------ */ + #if 0 + static int attach_xc5000(u8 addr, struct cx231xx *dev) +@@ -398,9 +507,9 @@ static int attach_xc5000(u8 addr, struct cx231xx *dev) + + int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq) + { +- if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { ++ if ((dev->dvb[0] != NULL) && (dev->dvb[0]->frontend != NULL)) { + +- struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; ++ struct dvb_tuner_ops *dops = &dev->dvb[0]->frontend->ops.tuner_ops; + + if (dops->set_analog_params != NULL) { + struct analog_parameters params; +@@ -411,7 +520,7 @@ int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq) + /*params.audmode = ; */ + + /* Set the analog parameters to set the frequency */ +- dops->set_analog_params(dev->dvb->frontend, ¶ms); ++ dops->set_analog_params(dev->dvb[0]->frontend, ¶ms); + } + + } +@@ -423,15 +532,15 @@ int cx231xx_reset_analog_tuner(struct cx231xx *dev) + { + int status = 0; + +- if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { ++ if ((dev->dvb[0] != NULL) && (dev->dvb[0]->frontend != NULL)) { + +- struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; ++ struct dvb_tuner_ops *dops = &dev->dvb[0]->frontend->ops.tuner_ops; + + if (dops->init != NULL && !dev->xc_fw_load_done) { + + dev_dbg(dev->dev, + "Reloading firmware for XC5000\n"); +- status = dops->init(dev->dvb->frontend); ++ status = dops->init(dev->dvb[0]->frontend); + if (status == 0) { + dev->xc_fw_load_done = 1; + dev_dbg(dev->dev, +@@ -457,8 +566,6 @@ static int register_dvb(struct cx231xx_dvb *dvb, + int result; + + mutex_init(&dvb->lock); +- +- + /* register adapter */ + result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, + adapter_nr); +@@ -468,13 +575,13 @@ static int register_dvb(struct cx231xx_dvb *dvb, + dev->name, result); + goto fail_adapter; + } +- dvb_register_media_controller(&dvb->adapter, dev->media_dev); ++// dvb_register_media_controller(&dvb->adapter, dev->media_dev); + + /* Ensure all frontends negotiate bus access */ +- dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; ++// dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; + + dvb->adapter.priv = dev; +- ++#if 0 + /* register frontend */ + result = dvb_register_frontend(&dvb->adapter, dvb->frontend); + if (result < 0) { +@@ -483,7 +590,7 @@ static int register_dvb(struct cx231xx_dvb *dvb, + dev->name, result); + goto fail_frontend; + } +- ++#endif + /* register demux stuff */ + dvb->demux.dmx.capabilities = + DMX_TS_FILTERING | DMX_SECTION_FILTERING | +@@ -545,7 +652,7 @@ static int register_dvb(struct cx231xx_dvb *dvb, + dev->tuner_type == TUNER_ABSENT); + if (result < 0) + goto fail_create_graph; +- ++ + return 0; + + fail_create_graph: +@@ -592,18 +699,51 @@ static void unregister_dvb(struct cx231xx_dvb *dvb) + dvb_unregister_adapter(&dvb->adapter); + } + ++static int tbs_cx_mac(struct i2c_adapter *i2c_adap, u8 count, u8 *mac) ++{ ++ u8 b[64], e[256]; ++ int ret, i; ++ ++ struct i2c_msg msg[] = { ++ { .addr = 0x50, .flags = 0, ++ .buf = b, .len = 1 }, ++ { .addr = 0x50, .flags = I2C_M_RD, ++ .buf = b, .len = 64 } ++ }; ++ ++ for (i = 0; i < 4; i++) { ++ b[0] = 0x40 * i; ++ ++ ret = i2c_transfer(i2c_adap, msg, 2); ++ ++ if (ret != 2) { ++ printk("TBS CX read MAC failed\n"); ++ return -1; ++ } ++ ++ memcpy(&e[0x40 * i], b , 64); ++ } ++ ++ memcpy(mac, &e[0x58 + 6 + 0x10*count], 6); ++ ++ return 0; ++} ++ + static int dvb_init(struct cx231xx *dev) + { +- int result = 0; ++ int i, result = 0; + struct cx231xx_dvb *dvb; + struct i2c_adapter *tuner_i2c; + struct i2c_adapter *demod_i2c; +- ++ u8 mac[6] = {0,0,0,0,0,0}; + if (!dev->board.has_dvb) { + /* This device does not support the extension */ + return 0; + } ++ ++ mutex_lock(&dev->lock); + ++ for (i = 0; i < dev->board.adap_cnt; i++) { + dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL); + + if (dvb == NULL) { +@@ -611,13 +751,19 @@ static int dvb_init(struct cx231xx *dev) + "cx231xx_dvb: memory allocation failed\n"); + return -ENOMEM; + } +- dev->dvb = dvb; ++ ++ dvb->count = i; ++ ++ dev->dvb[i] = dvb; + dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq; + dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; + + tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master); + demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master); +- mutex_lock(&dev->lock); ++ ++ result = register_dvb(dev->dvb[i],THIS_MODULE,dev,&dev->udev->dev); ++ ++ + cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); + cx231xx_demod_reset(dev); + /* init frontend */ +@@ -625,11 +771,11 @@ static int dvb_init(struct cx231xx *dev) + case CX231XX_BOARD_CNXT_CARRAERA: + case CX231XX_BOARD_CNXT_RDE_250: + +- dev->dvb->frontend = dvb_attach(s5h1432_attach, ++ dev->dvb[i]->frontend = dvb_attach(s5h1432_attach, + &dvico_s5h1432_config, + demod_i2c); + +- if (dev->dvb->frontend == NULL) { ++ if (dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach s5h1432 front end\n"); + result = -EINVAL; +@@ -639,7 +785,7 @@ static int dvb_init(struct cx231xx *dev) + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + +- if (!dvb_attach(xc5000_attach, dev->dvb->frontend, ++ if (!dvb_attach(xc5000_attach, dev->dvb[i]->frontend, + tuner_i2c, + &cnxt_rde250_tunerconfig)) { + result = -EINVAL; +@@ -650,11 +796,11 @@ static int dvb_init(struct cx231xx *dev) + case CX231XX_BOARD_CNXT_SHELBY: + case CX231XX_BOARD_CNXT_RDU_250: + +- dev->dvb->frontend = dvb_attach(s5h1411_attach, ++ dev->dvb[i]->frontend = dvb_attach(s5h1411_attach, + &xc5000_s5h1411_config, + demod_i2c); + +- if (dev->dvb->frontend == NULL) { ++ if (dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach s5h1411 front end\n"); + result = -EINVAL; +@@ -664,7 +810,7 @@ static int dvb_init(struct cx231xx *dev) + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + +- if (!dvb_attach(xc5000_attach, dev->dvb->frontend, ++ if (!dvb_attach(xc5000_attach, dev->dvb[i]->frontend, + tuner_i2c, + &cnxt_rdu250_tunerconfig)) { + result = -EINVAL; +@@ -673,11 +819,11 @@ static int dvb_init(struct cx231xx *dev) + break; + case CX231XX_BOARD_CNXT_RDE_253S: + +- dev->dvb->frontend = dvb_attach(s5h1432_attach, ++ dev->dvb[i]->frontend = dvb_attach(s5h1432_attach, + &dvico_s5h1432_config, + demod_i2c); + +- if (dev->dvb->frontend == NULL) { ++ if (dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach s5h1432 front end\n"); + result = -EINVAL; +@@ -687,7 +833,7 @@ static int dvb_init(struct cx231xx *dev) + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + +- if (!dvb_attach(tda18271_attach, dev->dvb->frontend, ++ if (!dvb_attach(tda18271_attach, dev->dvb[i]->frontend, + 0x60, tuner_i2c, + &cnxt_rde253s_tunerconfig)) { + result = -EINVAL; +@@ -697,11 +843,11 @@ static int dvb_init(struct cx231xx *dev) + case CX231XX_BOARD_CNXT_RDU_253S: + case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID: + +- dev->dvb->frontend = dvb_attach(s5h1411_attach, ++ dev->dvb[i]->frontend = dvb_attach(s5h1411_attach, + &tda18271_s5h1411_config, + demod_i2c); + +- if (dev->dvb->frontend == NULL) { ++ if (dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach s5h1411 front end\n"); + result = -EINVAL; +@@ -711,7 +857,7 @@ static int dvb_init(struct cx231xx *dev) + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + +- if (!dvb_attach(tda18271_attach, dev->dvb->frontend, ++ if (!dvb_attach(tda18271_attach, dev->dvb[i]->frontend, + 0x60, tuner_i2c, + &cnxt_rde253s_tunerconfig)) { + result = -EINVAL; +@@ -724,11 +870,11 @@ static int dvb_init(struct cx231xx *dev) + "%s: looking for tuner / demod on i2c bus: %d\n", + __func__, i2c_adapter_id(tuner_i2c)); + +- dev->dvb->frontend = dvb_attach(lgdt3305_attach, ++ dev->dvb[i]->frontend = dvb_attach(lgdt3305_attach, + &hcw_lgdt3305_config, + demod_i2c); + +- if (dev->dvb->frontend == NULL) { ++ if (dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach LG3305 front end\n"); + result = -EINVAL; +@@ -738,7 +884,7 @@ static int dvb_init(struct cx231xx *dev) + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + +- dvb_attach(tda18271_attach, dev->dvb->frontend, ++ dvb_attach(tda18271_attach, dev->dvb[i]->frontend, + 0x60, tuner_i2c, + &hcw_tda18271_config); + break; +@@ -751,7 +897,7 @@ static int dvb_init(struct cx231xx *dev) + + /* attach demod */ + memset(&si2165_pdata, 0, sizeof(si2165_pdata)); +- si2165_pdata.fe = &dev->dvb->frontend; ++ si2165_pdata.fe = &dev->dvb[i]->frontend; + si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL, + si2165_pdata.ref_freq_Hz = 16000000, + +@@ -761,7 +907,7 @@ static int dvb_init(struct cx231xx *dev) + info.platform_data = &si2165_pdata; + request_module(info.type); + client = i2c_new_device(demod_i2c, &info); +- if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) { ++ if (client == NULL || client->dev.driver == NULL || dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach SI2165 front end\n"); + result = -EINVAL; +@@ -776,12 +922,12 @@ static int dvb_init(struct cx231xx *dev) + + dvb->i2c_client_demod = client; + +- dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; ++ dev->dvb[i]->frontend->ops.i2c_gate_ctrl = NULL; + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + +- dvb_attach(tda18271_attach, dev->dvb->frontend, ++ dvb_attach(tda18271_attach, dev->dvb[i]->frontend, + 0x60, + tuner_i2c, + &hcw_tda18271_config); +@@ -798,7 +944,7 @@ static int dvb_init(struct cx231xx *dev) + + /* attach demod */ + memset(&si2165_pdata, 0, sizeof(si2165_pdata)); +- si2165_pdata.fe = &dev->dvb->frontend; ++ si2165_pdata.fe = &dev->dvb[i]->frontend; + si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT, + si2165_pdata.ref_freq_Hz = 24000000, + +@@ -808,7 +954,7 @@ static int dvb_init(struct cx231xx *dev) + info.platform_data = &si2165_pdata; + request_module(info.type); + client = i2c_new_device(demod_i2c, &info); +- if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) { ++ if (client == NULL || client->dev.driver == NULL || dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach SI2165 front end\n"); + result = -EINVAL; +@@ -825,14 +971,14 @@ static int dvb_init(struct cx231xx *dev) + + memset(&info, 0, sizeof(struct i2c_board_info)); + +- dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; ++ dev->dvb[i]->frontend->ops.i2c_gate_ctrl = NULL; + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); +- si2157_config.fe = dev->dvb->frontend; ++ si2157_config.fe = dev->dvb[i]->frontend; + #ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; + #endif +@@ -847,21 +993,21 @@ static int dvb_init(struct cx231xx *dev) + tuner_i2c, + &info); + if (client == NULL || client->dev.driver == NULL) { +- dvb_frontend_detach(dev->dvb->frontend); ++ dvb_frontend_detach(dev->dvb[i]->frontend); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); +- dvb_frontend_detach(dev->dvb->frontend); ++ dvb_frontend_detach(dev->dvb[i]->frontend); + result = -ENODEV; + goto out_free; + } + + dev->cx231xx_reset_analog_tuner = NULL; + +- dev->dvb->i2c_client_tuner = client; ++ dev->dvb[i]->i2c_client_tuner = client; + break; + } + case CX231XX_BOARD_HAUPPAUGE_955Q: +@@ -872,26 +1018,26 @@ static int dvb_init(struct cx231xx *dev) + + memset(&info, 0, sizeof(struct i2c_board_info)); + +- dev->dvb->frontend = dvb_attach(lgdt3306a_attach, ++ dev->dvb[i]->frontend = dvb_attach(lgdt3306a_attach, + &hauppauge_955q_lgdt3306a_config, + demod_i2c + ); + +- if (dev->dvb->frontend == NULL) { ++ if (dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach LGDT3306A frontend.\n"); + result = -EINVAL; + goto out_free; + } + +- dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; ++ dev->dvb[i]->frontend->ops.i2c_gate_ctrl = NULL; + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); +- si2157_config.fe = dev->dvb->frontend; ++ si2157_config.fe = dev->dvb[i]->frontend; + #ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; + #endif +@@ -906,21 +1052,21 @@ static int dvb_init(struct cx231xx *dev) + tuner_i2c, + &info); + if (client == NULL || client->dev.driver == NULL) { +- dvb_frontend_detach(dev->dvb->frontend); ++ dvb_frontend_detach(dev->dvb[i]->frontend); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); +- dvb_frontend_detach(dev->dvb->frontend); ++ dvb_frontend_detach(dev->dvb[i]->frontend); + result = -ENODEV; + goto out_free; + } + + dev->cx231xx_reset_analog_tuner = NULL; + +- dev->dvb->i2c_client_tuner = client; ++ dev->dvb[i]->i2c_client_tuner = client; + break; + } + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: +@@ -930,11 +1076,11 @@ static int dvb_init(struct cx231xx *dev) + "%s: looking for demod on i2c bus: %d\n", + __func__, i2c_adapter_id(tuner_i2c)); + +- dev->dvb->frontend = dvb_attach(mb86a20s_attach, ++ dev->dvb[i]->frontend = dvb_attach(mb86a20s_attach, + &pv_mb86a20s_config, + demod_i2c); + +- if (dev->dvb->frontend == NULL) { ++ if (dev->dvb[i]->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach mb86a20s demod\n"); + result = -EINVAL; +@@ -944,17 +1090,162 @@ static int dvb_init(struct cx231xx *dev) + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + +- dvb_attach(tda18271_attach, dev->dvb->frontend, ++ dvb_attach(tda18271_attach, dev->dvb[i]->frontend, + 0x60, tuner_i2c, + &pv_tda18271_config); + break; + ++ case CX231XX_BOARD_TBS_5280: ++ { ++ struct i2c_client *client; ++ struct i2c_board_info board_info = { ++ .type = "tda18212", ++ .platform_data = &tda18212_config, ++ }; ++ ++ ++ board_info.addr = (i == 0) ? 0x60 : 0x63; ++ ++ dev->dvb[i]->frontend = dvb_attach(cxd2820r_attach, ++ i ? &cxd2820r_config1 : &cxd2820r_config0, ++ demod_i2c, NULL); ++ ++ if (dev->dvb[i]->frontend == NULL) { ++ dev_err(dev->dev, ++ "Failed to attach demod cxd2820r %d\n", i); ++ result = -EINVAL; ++ goto out_free; ++ } ++ ++ /* define general-purpose callback pointer */ ++ dvb->frontend->callback = cx231xx_tuner_callback; ++ ++ /* attach tuner */ ++ tda18212_config.fe = dev->dvb[i]->frontend; ++ request_module("tda18212"); ++ client = i2c_new_device(tuner_i2c, &board_info); /* could it be demod_i2c ?? */ ++ if (client == NULL || client->dev.driver == NULL) { ++ dvb_frontend_detach(dev->dvb[i]->frontend); ++ result = -ENODEV; ++ goto out_free; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ dvb_frontend_detach(dev->dvb[i]->frontend); ++ result = -ENODEV; ++ goto out_free; ++ } ++ dev->dvb[i]->i2c_client_tuner = client; ++ ++ break; ++ } ++ case CX231XX_BOARD_TBS_5281: ++ { ++ struct i2c_adapter *adapter; ++ struct i2c_client *client_demod; ++ struct i2c_client *client_tuner; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ ++ demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master+i); ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &dev->dvb[i]->frontend; ++ si2168_config.ts_mode = SI2168_TS_SERIAL; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(demod_i2c, &info); ++ if (client_demod == NULL || client_demod->dev.driver == NULL) { ++ result = -ENODEV; ++ goto out_free; ++ } ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ result = -ENODEV; ++ goto out_free; ++ } ++ ++ /* define general-purpose callback pointer */ ++ dvb->frontend->callback = cx231xx_tuner_callback; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = dev->dvb[i]->frontend; ++ si2157_config.if_port = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(adapter, &info); ++ if (client_tuner == NULL || client_tuner->dev.driver == NULL) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ result = -ENODEV; ++ goto out_free; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ result = -ENODEV; ++ goto out_free; ++ } ++ ++ dev->dvb[i]->i2c_client_demod = client_demod; ++ dev->dvb[i]->i2c_client_tuner = client_tuner; ++ ++ break; ++ } ++ case CX231XX_BOARD_TBS_5990: ++ { ++ dev->dvb[i]->frontend = dvb_attach(tas2101_attach,i ? &tbs5990_config1 : &tbs5990_config0, ++ &dev->i2c_bus[1+i].i2c_adap); ++ if (dev->dvb[i]->frontend == NULL) { ++ dev_err(dev->dev, ++ "Failed to attach demod TAS2101 %d\n", i); ++ result = -EINVAL; ++ goto out_free; ++ } ++ ++ /*attach tuner*/ ++ if(dvb_attach(av201x_attach,dev->dvb[i]->frontend, ++ &tbs5990_tuner_config,tas2101_get_i2c_adapter(dev->dvb[i]->frontend, 2))==NULL) ++ { ++ dvb_frontend_detach(dev->dvb[i]->frontend); ++ result = -ENODEV; ++ goto out_free; ++ } ++ ++ if (i == 0) { ++ tbs_cx_mac(&dev->i2c_bus[1].i2c_adap, 0, mac); ++ } ++ ++ if (i == 1) { ++ memcpy(dev->dvb[0]->adapter.proposed_mac, mac, 6); ++ printk(KERN_INFO "TurboSight TBS5990 MAC Addresse bas: %pM\n", mac); ++ mac[5] +=1; ++ memcpy(dev->dvb[1]->adapter.proposed_mac, mac, 6); ++ } ++ ++ /* define general-purpose callback pointer */ ++ dvb->frontend->callback = cx231xx_tuner_callback; ++ ++ break; ++ } + default: + dev_err(dev->dev, + "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", + dev->name); + break; + } ++ + if (NULL == dvb->frontend) { + dev_err(dev->dev, + "%s/2: frontend initialization failed\n", dev->name); +@@ -962,13 +1253,19 @@ static int dvb_init(struct cx231xx *dev) + goto out_free; + } + +- /* register everything */ +- result = register_dvb(dvb, THIS_MODULE, dev, dev->dev); ++ strlcpy(dev->dvb[i]->frontend->ops.info.name,dev->board.name,52); + ++ result = dvb_register_frontend(&dev->dvb[i]->adapter,dev->dvb[i]->frontend); + if (result < 0) + goto out_free; ++ switch(dev->model){ ++ case CX231XX_BOARD_TBS_5990: ++ tbscxci_init(dev->dvb[i], i); ++ } + + ++ } ++ + dev_info(dev->dev, "Successfully loaded cx231xx-dvb\n"); + + ret: +@@ -978,20 +1275,29 @@ static int dvb_init(struct cx231xx *dev) + + out_free: + kfree(dvb); +- dev->dvb = NULL; ++ dev->dvb[i] = NULL; + goto ret; + } + + static int dvb_fini(struct cx231xx *dev) + { ++ int i; ++ + if (!dev->board.has_dvb) { + /* This device does not support the extension */ + return 0; + } + +- if (dev->dvb) { +- unregister_dvb(dev->dvb); +- dev->dvb = NULL; ++ for (i = 0; i < dev->board.adap_cnt; i++) { ++ if (dev->dvb[i]) { ++ switch (dev->model) { ++ case CX231XX_BOARD_TBS_5990: ++ tbscxci_release(dev->dvb[i]); ++ break; ++ } ++ unregister_dvb(dev->dvb[i]); ++ dev->dvb[i] = NULL; ++ } + } + + return 0; +diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c +index 35e9acf..95d9a017 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c ++++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c +@@ -94,7 +94,7 @@ static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, + u8 *buf_ptr = NULL; + u16 saddr = 0; + u8 need_gpio = 0; +- ++ + if (is_tuner(dev, bus, msg, TUNER_XC5000)) { + size = msg->len; + +@@ -173,6 +173,37 @@ static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, + + } else { /* regular case */ + ++ if (bus->nr == 2) { ++ size = msg->len; ++ buf_ptr = (u8 *) msg->buf; ++ do { ++ /* prepare xfer_data struct */ ++ req_data.dev_addr = msg->addr; ++ req_data.direction = msg->flags; ++ req_data.saddr_len = 0; ++ req_data.saddr_dat = 0; ++ req_data.buf_size = size > 4 ? 4 : size; ++ req_data.p_buffer = (u8 *) (buf_ptr + loop * 4); ++ ++ bus->i2c_nostop = (size > 4) ? 1 : 0; ++ bus->i2c_reserve = (loop == 0) ? 0 : 1; ++ ++ /* usb send command */ ++ status = dev->cx231xx_send_usb_command(bus, &req_data); ++ loop++; ++ ++ if (size >= 4) ++ size -= 4; ++ else ++ size = 0; ++ ++ } while (size > 0); ++ ++ bus->i2c_nostop = 0; ++ bus->i2c_reserve = 0; ++ ++ }else{ ++ + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; +@@ -183,6 +214,7 @@ static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); ++ } + } + + return status < 0 ? status : 0; +@@ -353,11 +385,11 @@ static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; +- req_data.direction = I2C_M_RD; ++ req_data.direction = msg->flags; + req_data.saddr_len = 0; + req_data.saddr_dat = 0; +- req_data.buf_size = 1; +- req_data.p_buffer = buf; ++ req_data.buf_size = 0; ++ req_data.p_buffer = NULL; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); +@@ -376,6 +408,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, + struct cx231xx *dev = bus->dev; + int addr, rc, i, byte; + ++ + if (num <= 0) + return 0; + mutex_lock(&dev->i2c_lock); +@@ -472,7 +505,6 @@ static struct i2c_adapter cx231xx_adap_template = { + * incomplete list of known devices + */ + static const char *i2c_devs[128] = { +- [0x20 >> 1] = "demod", + [0x60 >> 1] = "colibri", + [0x88 >> 1] = "hammerhead", + [0x8e >> 1] = "CIR", +@@ -492,6 +524,7 @@ void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port) + unsigned char buf; + int i, rc; + struct i2c_client client; ++ i2c_scan=1; + + if (!i2c_scan) + return; +diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h +index 90c8676..5c4821e 100644 +--- a/drivers/media/usb/cx231xx/cx231xx.h ++++ b/drivers/media/usb/cx231xx/cx231xx.h +@@ -78,6 +78,9 @@ + #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20 + #define CX231XX_BOARD_HAUPPAUGE_955Q 21 + #define CX231XX_BOARD_TERRATEC_GRABBY 22 ++#define CX231XX_BOARD_TBS_5280 23 ++#define CX231XX_BOARD_TBS_5281 24 ++#define CX231XX_BOARD_TBS_5990 25 + + /* Limits minimum and default number of buffers */ + #define CX231XX_MIN_BUF 4 +@@ -342,6 +345,8 @@ struct cx231xx_board { + int demod_addr; + u8 demod_xfer_mode; /* 0 - Serial; 1 - parallel */ + ++ int adap_cnt; ++ + /* GPIO Pins */ + struct cx231xx_reg_seq *dvb_gpio; + struct cx231xx_reg_seq *suspend_gpio; +@@ -584,6 +589,31 @@ struct cx231xx_tsport { + void *port_priv; + }; + ++ ++ ++struct cx231xx_dvb { ++ struct dvb_frontend *frontend; ++ ++ /* feed count management */ ++ struct mutex lock; ++ int nfeeds; ++ u8 count; ++ ++ /* general boilerplate stuff */ ++ struct dvb_adapter adapter; ++ struct dvb_demux demux; ++ struct dmxdev dmxdev; ++ struct dmx_frontend fe_hw; ++ struct dmx_frontend fe_mem; ++ struct dvb_net net; ++ struct i2c_client *i2c_client_demod; ++ struct i2c_client *i2c_client_tuner; ++ ++ void *adap_priv; ++}; ++ ++ ++ + /* main device struct */ + struct cx231xx { + /* generic device properties */ +@@ -673,6 +703,7 @@ struct cx231xx { + struct cx231xx_video_mode vbi_mode; + struct cx231xx_video_mode sliced_cc_mode; + struct cx231xx_video_mode ts1_mode; ++ struct cx231xx_video_mode ts2_mode; + + atomic_t devlist_count; + +@@ -686,6 +717,7 @@ struct cx231xx { + char *buf, int len); + int (*cx231xx_send_usb_command) (struct cx231xx_i2c *i2c_bus, + struct cx231xx_i2c_xfer_data *req_data); ++ + int (*cx231xx_gpio_i2c_read) (struct cx231xx *dev, u8 dev_addr, + u8 *buf, u8 len); + int (*cx231xx_gpio_i2c_write) (struct cx231xx *dev, u8 dev_addr, +@@ -696,7 +728,7 @@ struct cx231xx { + + enum cx231xx_mode mode; + +- struct cx231xx_dvb *dvb; ++ struct cx231xx_dvb *dvb[2]; + + /* Cx231xx supported PCB config's */ + struct pcb_config current_pcb_config; +@@ -873,6 +905,8 @@ int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev); + + int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len); + int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len); ++int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 gpio_val); ++int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 *gpio_val); + + /* audio related functions */ + int cx231xx_set_audio_decoder_input(struct cx231xx *dev, +@@ -887,6 +921,10 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx *dev, + struct urb *urb)); ++int cx231xx_init_isoc_ts2(struct cx231xx *dev, int max_packets, ++ int num_bufs, int max_pkt_size, ++ int (*isoc_copy) (struct cx231xx *dev, ++ struct urb *urb)); + int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*bulk_copy) (struct cx231xx *dev, +@@ -894,6 +932,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, + void cx231xx_stop_TS1(struct cx231xx *dev); + void cx231xx_start_TS1(struct cx231xx *dev); + void cx231xx_uninit_isoc(struct cx231xx *dev); ++void cx231xx_uninit_isoc_ts2(struct cx231xx *dev); + void cx231xx_uninit_bulk(struct cx231xx *dev); + int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); + int cx231xx_unmute_audio(struct cx231xx *dev); +diff --git a/drivers/media/usb/cx231xx/tbscxci.c b/drivers/media/usb/cx231xx/tbscxci.c +new file mode 100644 +index 0000000..5558cd1 +--- /dev/null ++++ b/drivers/media/usb/cx231xx/tbscxci.c +@@ -0,0 +1,353 @@ ++/* ++ TurboSight TBS CI driver for CX23102 ++ Copyright (C) 2014 Konstantin Dimitrov ++ ++ Copyright (C) 2014 TurboSight.com ++*/ ++ ++#include "tbscxci.h" ++ ++#define TBSCXCI_I2C_ADDR 0x1b ++ ++ ++struct tbscxci_state { ++ struct dvb_ca_en50221 ca; ++ struct mutex ca_mutex; ++ struct i2c_adapter *i2c_adap; ++ int nr; ++ void *priv; /* struct cx231xx_dvb *priv; */ ++}; ++ ++int tbscxci_i2c_read(struct tbscxci_state *state) ++{ ++ int ret; ++ u8 buf = 0; ++ ++ struct i2c_msg msg = { .addr = TBSCXCI_I2C_ADDR, .flags = I2C_M_RD, ++ .buf = &buf, .len = 1 }; ++ ++ if (state->nr == 1) ++ msg.addr -= 1; ++ ++ ret = i2c_transfer(state->i2c_adap, &msg, 1); ++ ++ if (ret != 1) { ++ printk("tbscxci: read error=%d\n", ret); ++ return -EREMOTEIO; ++ } ++ ++ return buf; ++}; ++ ++int tbscxci_i2c_write(struct tbscxci_state *state, ++ u8 addr, u8 data[], int len) ++{ ++ int ret; ++ unsigned char buf[len + 1]; ++ ++ struct i2c_msg msg = { .addr = TBSCXCI_I2C_ADDR, .flags = 0, ++ .buf = &buf[0], .len = len + 1 }; ++ ++ if (state->nr == 1) ++ msg.addr -= 1; ++ ++ memcpy(&buf[1], data, len); ++ buf[0] = addr; ++ ++ ret = i2c_transfer(state->i2c_adap, &msg, 1); ++ ++ if (ret != 1) { ++ /* printk("tbscxci: error=%d\n", ret); */ ++ return -EREMOTEIO; ++ } ++ ++ return 0; ++}; ++ ++int tbscxci_read_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, u8 address) ++{ ++ struct tbscxci_state *state = ca->data; ++ int ret; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data = (address & 3); ++ ret = tbscxci_i2c_write(state, 0x80, &data, 1); ++ data = tbscxci_i2c_read(state); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return data; ++} ++ ++int tbscxci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct tbscxci_state *state = ca->data; ++ int ret; ++ unsigned char data[2]; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data[0] = (address & 3); ++ data[1] = value; ++ ret = tbscxci_i2c_write(state, 0x80, data, 2); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++int tbscxci_read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct tbscxci_state *state = ca->data; ++ int ret; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data = (address & 0xff); ++ ret = tbscxci_i2c_write(state, ++ ((address >> 8) & 0x7f), &data, 1); ++ data = tbscxci_i2c_read(state); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return data; ++} ++ ++int tbscxci_write_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address, u8 value) ++{ ++ struct tbscxci_state *state = ca->data; ++ int ret; ++ unsigned char data[2]; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data[0] = (address & 0xff); ++ data[1] = value; ++ ret = tbscxci_i2c_write(state, ++ ((address >> 8) & 0x7f), data, 2); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbscxci_set_video_port(struct dvb_ca_en50221 *ca, ++ int slot, int enable) ++{ ++ struct tbscxci_state *state = ca->data; ++ struct cx231xx_dvb *adap = state->priv; ++ unsigned char data; ++ int ret; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ data = enable & 1; ++ ret = tbscxci_i2c_write(state, 0xc0, &data, 1); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ printk("tbscxci: Adapter %d CI slot %sabled\n", ++// adap->fe->dvb->num, ++ adap->adapter.num, ++ enable ? "en" : "dis"); ++ ++ return 0; ++} ++ ++int tbscxci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbscxci_set_video_port(ca, slot, /* enable */ 0); ++} ++ ++int tbscxci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbscxci_set_video_port(ca, slot, /* enable */ 1); ++} ++ ++int tbscxci_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct tbscxci_state *state = ca->data; ++ int ret; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock (&state->ca_mutex); ++ ++ data = 1; ++ ret = tbscxci_i2c_write(state, 0xc1, &data, 1); ++ msleep (5); ++ ++ data = 0; ++ ret = tbscxci_i2c_write(state, 0xc1, &data, 1); ++ msleep (1400); ++ ++ mutex_unlock (&state->ca_mutex); ++ ++ if (ret != 0) ++ return ret; ++ ++ return 0; ++} ++ ++int tbscxci_poll_slot_status(struct dvb_ca_en50221 *ca, ++ int slot, int open) ++{ ++ struct tbscxci_state *state = ca->data; ++ struct cx231xx_dvb *adap = state->priv; ++ struct cx231xx *dev = adap->adapter.priv; ++ unsigned char data; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ cx231xx_get_gpio_bit(dev, dev->gpio_dir, &dev->gpio_val); ++ data = dev->gpio_val >> (state->nr ? 25 : 27); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (data & 1) { ++ return (DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY); ++ } else { ++ return 0; ++ } ++} ++ ++int tbscxci_init(struct cx231xx_dvb *adap, int nr) ++{ ++ struct cx231xx *dev = adap->adapter.priv; ++ struct tbscxci_state *state; ++ int ret; ++ unsigned char data; ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct tbscxci_state), GFP_KERNEL); ++ if (state == NULL) { ++ ret = -ENOMEM; ++ goto error1; ++ } ++ ++ adap->adap_priv = state; ++ ++ state->nr = nr; ++ ++ mutex_init(&state->ca_mutex); ++ ++ switch (state->nr) { ++ case 0: ++ state->i2c_adap = &dev->i2c_bus[1].i2c_adap; ++ dev->gpio_dir &= ~(1 << 27); ++ cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val); ++ break; ++ case 1: ++ state->i2c_adap = &dev->i2c_bus[2].i2c_adap; ++ dev->gpio_dir &= ~(1 << 25); ++ cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val); ++ break; ++ } ++ ++ state->ca.owner = THIS_MODULE; ++ state->ca.read_attribute_mem = tbscxci_read_attribute_mem; ++ state->ca.write_attribute_mem = tbscxci_write_attribute_mem; ++ state->ca.read_cam_control = tbscxci_read_cam_control; ++ state->ca.write_cam_control = tbscxci_write_cam_control; ++ state->ca.slot_reset = tbscxci_slot_reset; ++ state->ca.slot_shutdown = tbscxci_slot_shutdown; ++ state->ca.slot_ts_enable = tbscxci_slot_ts_enable; ++ state->ca.poll_slot_status = tbscxci_poll_slot_status; ++ state->ca.data = state; ++ state->priv = adap; ++ ++ data = 1; ++ tbscxci_i2c_write(state, 0xc2, &data, 1); ++ data = tbscxci_i2c_read(state); ++ ++ switch (data) { ++ case 0x62: ++ case 0x60: ++ printk("tbscxci: Initializing TBS CX CI#%d slot\n", nr); ++ break; ++ default: ++ ret = -EREMOTEIO; ++ goto error2; ++ } ++ ++ ret = dvb_ca_en50221_init(&adap->adapter, &state->ca, ++ /* flags */ 0, /* n_slots */ 1); ++ if (ret != 0) goto error2; ++ ++ printk("tbscxci: Adapter %d CI slot initialized\n", ++ adap->adapter.num); ++ ++ ret = tbscxci_poll_slot_status(&state->ca, 0, 0); ++ if (0 == ret) ++ tbscxci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); ++ ++ return 0; ++ ++error2: ++ //memset (&state->ca, 0, sizeof (state->ca)); ++ kfree(state); ++error1: ++ printk("tbscxci: Adapter %d CI slot initialization failed\n", ++ adap->adapter.num); ++ return ret; ++} ++ ++void tbscxci_release(struct cx231xx_dvb *adap) ++{ ++ struct tbscxci_state *state; ++ ++ if (NULL == adap) return; ++ ++ state = (struct tbscxci_state *)adap->adap_priv; ++ ++ if (NULL == state) return; ++ ++ if (NULL == state->ca.data) return; ++ ++ dvb_ca_en50221_release(&state->ca); ++ //memset(&state->ca, 0, sizeof(state->ca)); ++ kfree(state); ++} +diff --git a/drivers/media/usb/cx231xx/tbscxci.h b/drivers/media/usb/cx231xx/tbscxci.h +new file mode 100644 +index 0000000..f2d52e5 +--- /dev/null ++++ b/drivers/media/usb/cx231xx/tbscxci.h +@@ -0,0 +1,34 @@ ++/* ++ TurboSight TBS CI driver for CX23102 ++ Copyright (C) 2014 Konstantin Dimitrov ++ ++ Copyright (C) 2014 TurboSight.com ++*/ ++ ++#ifndef TBSCXCI_H ++#define TBSCXCI_H ++ ++#include "cx231xx.h" ++ ++#include "dvb_ca_en50221.h" ++ ++extern int tbscxci_read_attribute_mem(struct dvb_ca_en50221 *en50221, ++ int slot, int addr); ++extern int tbscxci_write_attribute_mem(struct dvb_ca_en50221 *en50221, ++ int slot, int addr, u8 data); ++extern int tbscxci_read_cam_control(struct dvb_ca_en50221 *en50221, ++ int slot, u8 addr); ++extern int tbscxci_write_cam_control(struct dvb_ca_en50221 *en50221, ++ int slot, u8 addr, u8 data); ++extern int tbscxci_slot_reset(struct dvb_ca_en50221 *en50221, ++ int slot); ++extern int tbscxci_slot_shutdown(struct dvb_ca_en50221 *en50221, ++ int slot); ++extern int tbscxci_slot_ts_enable(struct dvb_ca_en50221 *en50221, ++ int slot); ++extern int tbscxci_poll_slot_status(struct dvb_ca_en50221 *en50221, ++ int slot, int open); ++extern int tbscxci_init(struct cx231xx_dvb *adap, int nr); ++extern void tbscxci_release(struct cx231xx_dvb *adap); ++ ++#endif +diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig +index 959fa09..803e5b8 100644 +--- a/drivers/media/usb/dvb-usb/Kconfig ++++ b/drivers/media/usb/dvb-usb/Kconfig +@@ -331,3 +331,111 @@ config DVB_USB_TECHNISAT_USB2 + select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Technisat USB2 DVB-S/S2 device ++ ++config DVB_USB_TBSQBOX ++ tristate "TurboSight QBOX DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight QBOX DVB-S USB2.0 receivers ++ ++config DVB_USB_TBSQBOX2 ++ tristate "TurboSight QBOX2 DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight QBOX2 DVB-S USB2.0 receivers ++ ++config DVB_USB_TBSQBOX22 ++ tristate "TurboSight QBOX22 DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_TAS2101 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_AV201X if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight QBOX22 DVB-S USB2.0 receivers ++ ++ ++config DVB_USB_TBS5922SE ++ tristate "TurboSight 5922SE DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_TAS2101 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_AV201X if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight 5922SE DVB-S USB2.0 receivers ++ ++config DVB_USB_TBSQBOXS2 ++ tristate "TurboSight QBOX2 DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight QBOX2 DVB-S USB2.0 receivers ++ ++config DVB_USB_TBSQBOX2CI ++ tristate "TurboSight QBOX2 CI DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight QBOX2 CI DVB-S USB2.0 receivers ++ ++config DVB_USB_TBS5925 ++ tristate "TurboSight TBS5925 DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight TBS5925 DVB-S USB2.0 receivers ++ ++config DVB_USB_TBS5880 ++ tristate "TurboSight TBS5880 DVB-T/T2/C USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CXD2820R if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight TBS5880 DVB-T/T2/C USB2.0 receivers ++ ++config DVB_USB_TBS5220 ++ tristate "TurboSight TBS5220 DVB-T/T2/C USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight TBS5220 DVB-T/T2/C USB2.0 receivers ++ ++config DVB_USB_TBS5881 ++ tristate "TurboSight TBS5881 DVB-T/T2/C USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight TBS5881 DVB-T/T2/C USB2.0 receivers ++ ++config DVB_USB_TBS5520 ++ tristate "Turbosight TBS5520 support" ++ depends on DVB_USB ++ select DVB_AVL6882 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_R848 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the Turbosight TBS5520 USB2 DVB-T/T2/C/S/S2 device ++ ++config DVB_USB_TBS5927 ++ tristate "TurboSight TBS5927 DVB-S2 USB2.0 support" ++ depends on DVB_USB ++ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV0910 if MEDIA_SUBDRV_AUTOSELECT ++ select MEDIA_TUNER_STV6120 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the TurboSight TBS5927 DVB-S USB2.0 receivers +diff --git a/drivers/media/usb/dvb-usb/Makefile b/drivers/media/usb/dvb-usb/Makefile +index 3b3f32b..6b48da0 100644 +--- a/drivers/media/usb/dvb-usb/Makefile ++++ b/drivers/media/usb/dvb-usb/Makefile +@@ -79,6 +79,42 @@ obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o + dvb-usb-technisat-usb2-objs := technisat-usb2.o + obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o + ++dvb-usb-tbsqbox-objs = tbs-qbox.o ++obj-$(CONFIG_DVB_USB_TBSQBOX) += dvb-usb-tbsqbox.o ++ ++dvb-usb-tbsqbox2-objs = tbs-qbox2.o ++obj-$(CONFIG_DVB_USB_TBSQBOX2) += dvb-usb-tbsqbox2.o ++ ++dvb-usb-tbsqbox22-objs = tbs-qbox22.o ++obj-$(CONFIG_DVB_USB_TBSQBOX22) += dvb-usb-tbsqbox22.o ++ ++dvb-usb-tbs5922se-objs = tbs5922se.o ++obj-$(CONFIG_DVB_USB_TBS5922SE) += dvb-usb-tbs5922se.o ++ ++dvb-usb-tbsqboxs2-objs = tbs-qboxs2.o ++obj-$(CONFIG_DVB_USB_TBSQBOXS2) += dvb-usb-tbsqboxs2.o ++ ++dvb-usb-tbsqbox2ci-objs = tbs-qbox2ci.o ++obj-$(CONFIG_DVB_USB_TBSQBOX2CI) += dvb-usb-tbsqbox2ci.o ++ ++dvb-usb-tbs5925-objs = tbs5925.o ++obj-$(CONFIG_DVB_USB_TBS5925) += dvb-usb-tbs5925.o ++ ++dvb-usb-tbs5880-objs = tbs5880.o ++obj-$(CONFIG_DVB_USB_TBS5880) += dvb-usb-tbs5880.o ++ ++dvb-usb-tbs5220-objs = tbs5220.o ++obj-$(CONFIG_DVB_USB_TBS5220) += dvb-usb-tbs5220.o ++ ++dvb-usb-tbs5881-objs = tbs5881.o ++obj-$(CONFIG_DVB_USB_TBS5881) += dvb-usb-tbs5881.o ++ ++dvb-usb-tbs5520-objs := tbs5520.o ++obj-$(CONFIG_DVB_USB_TBS5520) += dvb-usb-tbs5520.o ++ ++dvb-usb-tbs5927-objs = tbs5927.o ++obj-$(CONFIG_DVB_USB_TBS5927) += dvb-usb-tbs5927.o ++ + ccflags-y += -I$(srctree)/drivers/media/dvb-core + ccflags-y += -I$(srctree)/drivers/media/dvb-frontends/ + # due to tuner-xc3028 +diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c +index 9b8771e..7c59c47 100644 +--- a/drivers/media/usb/dvb-usb/cxusb.c ++++ b/drivers/media/usb/dvb-usb/cxusb.c +@@ -1366,8 +1366,6 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) + return -ENODEV; + } + +- st->i2c_client_demod = client_demod; +- + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = adap->fe_adap[0].fe; +@@ -1390,6 +1388,7 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) + return -ENODEV; + } + ++ st->i2c_client_demod = client_demod; + st->i2c_client_tuner = client_tuner; + + /* hook fe: need to resync the slave fifo when signal locks. */ +diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c +index e1be7a3..8ebc26f 100644 +--- a/drivers/media/usb/dvb-usb/dw2102.c ++++ b/drivers/media/usb/dvb-usb/dw2102.c +@@ -2,7 +2,7 @@ + * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, + * TeVii S421, S480, S482, S600, S630, S632, S650, S660, S662, + * Prof 1100, 7500, +- * Geniatech SU3000, T220, ++ * Geniatech SU3000, T220, T220A, + * TechnoTrend S2-4600, + * Terratec Cinergy S2 cards + * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by) +@@ -33,8 +33,10 @@ + #include "stb6100_proc.h" + #include "m88rs2000.h" + #include "tda18271.h" ++#include "tda18273.h" + #include "cxd2820r.h" + #include "m88ds3103.h" ++#include "ts2020.h" + + /* Max transfer size done by I2C transfer functions */ + #define MAX_XFER_SIZE 64 +@@ -1410,6 +1412,56 @@ static int t220_frontend_attach(struct dvb_usb_adapter *d) + return -EIO; + } + ++static int t220a_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ u8 obuf[3] = { 0xe, 0x87, 0 }; ++ u8 ibuf[] = { 0 }; ++ ++ if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) ++ err("command 0x0e transfer failed."); ++ ++ obuf[0] = 0xe; ++ obuf[1] = 0x86; ++ obuf[2] = 1; ++ ++ if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) ++ err("command 0x0e transfer failed."); ++ ++ obuf[0] = 0xe; ++ obuf[1] = 0x80; ++ obuf[2] = 0; ++ ++ if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) ++ err("command 0x0e transfer failed."); ++ ++ msleep(50); ++ ++ obuf[0] = 0xe; ++ obuf[1] = 0x80; ++ obuf[2] = 1; ++ ++ if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) ++ err("command 0x0e transfer failed."); ++ ++ obuf[0] = 0x51; ++ ++ if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0) ++ err("command 0x51 transfer failed."); ++ ++ d->fe_adap[0].fe = dvb_attach(cxd2820r_attach, &cxd2820r_config, ++ &d->dev->i2c_adap, NULL); ++ if (d->fe_adap[0].fe != NULL) { ++ if (dvb_attach(tda18273_attach, d->fe_adap[0].fe, ++ &d->dev->i2c_adap, 0x60)) { ++ info("Attached TDA18273/CXD2820R!\n"); ++ return 0; ++ } ++ } ++ ++ info("Failed to attach TDA18273/CXD2820R!\n"); ++ return -EIO; ++} ++ + static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d) + { + u8 obuf[] = { 0x51 }; +@@ -1644,6 +1696,7 @@ enum dw2102_table_entry { + TERRATEC_CINERGY_S2_R4, + GOTVIEW_SAT_HD, + GENIATECH_T220, ++ GENIATECH_T220A, + TECHNOTREND_S2_4600, + TEVII_S482_1, + TEVII_S482_2, +@@ -1674,6 +1727,7 @@ static struct usb_device_id dw2102_table[] = { + [TERRATEC_CINERGY_S2_R4] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4)}, + [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, + [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, ++ [GENIATECH_T220A] = {USB_DEVICE(0x0572, 0xC686)}, + [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, + USB_PID_TECHNOTREND_CONNECT_S2_4600)}, + [TEVII_S482_1] = {USB_DEVICE(0x9022, 0xd483)}, +@@ -2164,6 +2218,55 @@ static struct dvb_usb_device_properties t220_properties = { + } + }; + ++static struct dvb_usb_device_properties t220a_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .size_of_priv = sizeof(struct dw2102_state), ++ .power_ctrl = su3000_power_ctrl, ++ .num_adapters = 1, ++ .identify_state = su3000_identify_state, ++ .i2c_algo = &su3000_i2c_algo, ++ ++ .rc.core = { ++ .rc_interval = 150, ++ .rc_codes = RC_MAP_SU3000, ++ .module_name = "dw2102", ++ .allowed_protos = RC_BIT_RC5, ++ .rc_query = su3000_rc_query, ++ }, ++ ++ .read_mac_address = su3000_read_mac_address, ++ ++ .generic_bulk_ctrl_endpoint = 0x01, ++ ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { { ++ .streaming_ctrl = su3000_streaming_ctrl, ++ .frontend_attach = t220a_frontend_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ } ++ } }, ++ } ++ }, ++ .num_device_descs = 1, ++ .devices = { ++ { "Geniatech T220A DVB-T/T2 USB2.0", ++ { &dw2102_table[GENIATECH_T220A], NULL }, ++ { NULL }, ++ }, ++ } ++}; ++ + static struct dvb_usb_device_properties tt_s2_4600_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, +@@ -2304,6 +2407,8 @@ static int dw2102_probe(struct usb_interface *intf, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &t220_properties, + THIS_MODULE, NULL, adapter_nr) || ++ 0 == dvb_usb_device_init(intf, &t220a_properties, ++ THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties, + THIS_MODULE, NULL, adapter_nr)) + return 0; +@@ -2346,9 +2451,10 @@ module_usb_driver(dw2102_driver); + MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); + MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," + " DVB-C 3101 USB2.0," +- " TeVii S421, S480, S482, S600, S630, S632, S650," ++ " TeVii S421, S480, S482, S600, S630, S632, S650, S660" + " TeVii S660, S662, Prof 1100, 7500 USB2.0," +- " Geniatech SU3000, T220," ++ " Prof 1100, 7500 USB2.0," ++ " Geniatech SU3000, T220, T220A," + " TechnoTrend S2-4600, Terratec Cinergy S2 devices"); + MODULE_VERSION("0.1"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox.c b/drivers/media/usb/dvb-usb/tbs-qbox.c +new file mode 100644 +index 0000000..89d665b +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox.c +@@ -0,0 +1,514 @@ ++/* DVB USB framework compliant Linux driver for the ++* TBS QBOX ++* ++* Copyright (C) 2008 Bob Liu (Bob@Turbosight.com) ++* Igor M. Liplianin (liplianin@me.by) ++* ++* Konstantin Dimitrov ++* June 2009 ++* Some fixes and improvements. ++* ++* 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, version 2. ++* ++* see Documentation/dvb/README.dvb-usb for more information ++*/ ++#include ++#include "tbs-qbox.h" ++#include "stv0299.h" ++#include "stv0288.h" ++#include "stb6000.h" ++ ++#define TBSQBOX_READ_MSG 0 ++#define TBSQBOX_WRITE_MSG 1 ++ ++/* on my own*/ ++#define TBSQBOX_VOLTAGE_CTRL (0x1800) ++#define TBSQBOX_RC_QUERY (0x1a00) ++#define TBSQBOX_LED_CTRL (0x1b00) ++ ++struct tbsqboxs1_state { ++ u32 last_key_pressed; ++}; ++struct tbsqboxs1_rc_keys { ++ u32 keycode; ++ u32 event; ++}; ++ ++/* debug */ ++static int dvb_usb_tbsqboxs1_debug; ++module_param_named(debug, dvb_usb_tbsqboxs1_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbsqboxs1_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBSQBOX_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBSQBOX_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; ++ ++ if (flags == TBSQBOX_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, ++ value, index , u8buf, len, 2000); ++ ++ if (flags == TBSQBOX_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbsqboxs1_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0; ++ u8 buf6[20]; ++ u8 inbuf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ buf6[2]=msg[0].buf[0];//register ++ ++ tbsqboxs1_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBSQBOX_WRITE_MSG); ++ msleep(5); ++ tbsqboxs1_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, msg[1].len, TBSQBOX_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x68: ++ /* write to stv0299 register */ ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//demod addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBSQBOX_WRITE_MSG); ++ msleep(3); ++ break; ++ case 0x61: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ /* write to tuner pll */ ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//tuner addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBSQBOX_WRITE_MSG); ++ } ++ msleep(3); ++ break; ++ case (TBSQBOX_RC_QUERY): ++ tbsqboxs1_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBSQBOX_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ msleep(3); ++ //info("TBSQBOX_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ case (TBSQBOX_VOLTAGE_CTRL): ++ buf6[0] = 3; ++ buf6[1] = msg[0].buf[0]; ++ tbsqboxs1_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ case (TBSQBOX_LED_CTRL): ++ buf6[0] = 5; ++ buf6[1] = msg[0].buf[0]; ++ tbsqboxs1_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbsqboxs1_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static void tbsqboxs1_led_ctrl(struct dvb_frontend *fe, int offon) ++{ ++ static u8 led_off[] = { 0 }; ++ static u8 led_on[] = { 1 }; ++ struct i2c_msg msg = { ++ .addr = TBSQBOX_LED_CTRL, ++ .flags = 0, ++ .buf = led_off, ++ .len = 1 ++ }; ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ ++ if (offon) ++ msg.buf = led_on; ++ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); ++} ++ ++ ++static struct stv0288_config earda_config = { ++ .demod_address = 0x68, ++ .set_lock_led = tbsqboxs1_led_ctrl, ++}; ++ ++static struct i2c_algorithm tbsqboxs1_i2c_algo = { ++ .master_xfer = tbsqboxs1_i2c_transfer, ++ .functionality = tbsqboxs1_i2c_func, ++}; ++ ++static int tbsqboxs1_earda_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ if (!dvb_attach(stb6000_attach, adap->fe_adap->fe, 0x61, ++ &adap->dev->i2c_adap)) ++ return -EIO; ++ ++ return 0; ++} ++static int tbsqboxs1_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbsqboxs1_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBSQBOX_WRITE_MSG); ++ ret = tbsqboxs1_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBSQBOX_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static int tbsqboxs1_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ static u8 command_13v[1] = {0x00}; ++ static u8 command_18v[1] = {0x01}; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_VOLTAGE_CTRL, .flags = 0, ++ .buf = command_13v, .len = 1}, ++ }; ++ ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ if (voltage == SEC_VOLTAGE_18) ++ msg[0].buf = command_18v; ++ //info("tbsqboxs1_set_voltage %d",voltage); ++ i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); ++ return 0; ++} ++ ++static struct dvb_usb_device_properties tbsqboxs1_properties; ++ ++static int tbsqboxs1_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ u8 buf[20]; ++ ++ if (tbsqboxs1_properties.adapter->fe->tuner_attach == &tbsqboxs1_earda_tuner_attach) { ++ d->fe_adap->fe = dvb_attach(stv0288_attach, &earda_config, ++ &u->i2c_adap); ++ if (d->fe_adap->fe != NULL) { ++ d->fe_adap->fe->ops.set_voltage = tbsqboxs1_set_voltage; ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbsqboxs1_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ return 0; ++ } ++ } ++ ++ return -EIO; ++} ++ ++ ++ ++static struct rc_map_table tbsqboxs1_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++ ++ ++static int tbsqboxs1_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbsqboxs1_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbsqboxs1_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbsqboxs1_table[] = { ++ {USB_DEVICE(0x734c, 0x2601)}, ++ {USB_DEVICE(0x734c, 0x5910)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbsqboxs1_table); ++ ++static int tbsqboxs1_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ const char *filename = "dvb-usb-tbsqbox-id2601.fw"; ++ switch (dev->descriptor.idProduct) { ++ case 0x2601: ++ ret = request_firmware(&fw, filename, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", filename); ++ return ret; ++ } ++ break; ++ case 0x5910: ++ ret = request_firmware(&fw, tbsqboxs1_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbsqboxs1_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBSQBOX firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbsqboxs1_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ tbsqboxs1_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbsqboxs1_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBSQBOX_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbsqboxs1_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbsqboxs1_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbsqboxs1_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5910.fw", ++ .size_of_priv = sizeof(struct tbsqboxs1_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbsqboxs1_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbsqboxs1_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbsqboxs1_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbsqboxs1_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbsqboxs1_load_firmware, ++ .read_mac_address = tbsqboxs1_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbsqboxs1_frontend_attach, ++ .streaming_ctrl = NULL, ++ .tuner_attach = tbsqboxs1_earda_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } }, ++ ++ .num_device_descs = 2, ++ .devices = { ++ {"TurboSight TBS QBOX DVB-S", ++ {&tbsqboxs1_table[0], NULL}, ++ {NULL}, ++ }, ++ {"TurboSight TBS QBOX DVB-S", ++ {&tbsqboxs1_table[1], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbsqboxs1_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbsqboxs1_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbsqboxs1_driver = { ++ .name = "tbsqboxs1", ++ .probe = tbsqboxs1_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbsqboxs1_table, ++}; ++ ++static int __init tbsqboxs1_module_init(void) ++{ ++ int ret = usb_register(&tbsqboxs1_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbsqboxs1_module_exit(void) ++{ ++ usb_deregister(&tbsqboxs1_driver); ++} ++ ++module_init(tbsqboxs1_module_init); ++module_exit(tbsqboxs1_module_exit); ++ ++MODULE_AUTHOR("Bob Liu "); ++MODULE_DESCRIPTION("Driver for TBS QBOX"); ++MODULE_VERSION("0.1"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox.h b/drivers/media/usb/dvb-usb/tbs-qbox.h +new file mode 100644 +index 0000000..4c8cdcc +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox.h +@@ -0,0 +1,8 @@ ++#ifndef _TBSQBOX_H_ ++#define _TBSQBOX_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbsqboxs1" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbsqboxs1_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox2.c b/drivers/media/usb/dvb-usb/tbs-qbox2.c +new file mode 100644 +index 0000000..fe46f02 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox2.c +@@ -0,0 +1,519 @@ ++/* DVB USB framework compliant Linux driver for the ++* TBS QBOX ++* ++* Copyright (C) 2008 Bob Liu (Bob@Turbosight.com) ++* Igor M. Liplianin (liplianin@me.by) ++* ++* Konstantin Dimitrov ++* August 2009 ++* Add QBOX II STV0903 support ++* ++* 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, version 2. ++* ++* see Documentation/dvb/README.dvb-usb for more information ++*/ ++#include ++#include "tbs-qbox2.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "stb6100.h" ++#include "stb6100_cfg.h" ++ ++#define TBSQBOX_READ_MSG 0 ++#define TBSQBOX_WRITE_MSG 1 ++ ++/* on my own*/ ++#define TBSQBOX_VOLTAGE_CTRL (0x1800) ++#define TBSQBOX_RC_QUERY (0x1a00) ++#define TBSQBOX_LED_CTRL (0x1b00) ++ ++struct tbsqbox2_state { ++ u32 last_key_pressed; ++}; ++struct tbsqbox2_rc_keys { ++ u32 keycode; ++ u32 event; ++}; ++ ++/* debug */ ++static int dvb_usb_tbsqbox2_debug; ++module_param_named(debug, dvb_usb_tbsqbox2_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbsqbox2_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBSQBOX_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBSQBOX_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; ++ ++ if (flags == TBSQBOX_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, ++ value, index , u8buf, len, 2000); ++ ++ if (flags == TBSQBOX_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbsqbox2_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0; ++ u8 buf6[20]; ++ u8 inbuf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ //register ++ buf6[2] = msg[0].buf[0]; ++ buf6[3] = msg[0].buf[1]; ++ ++ tbsqbox2_op_rw(d->udev, 0x92, 0, 0, ++ buf6, 4, TBSQBOX_WRITE_MSG); ++ //msleep(5); ++ tbsqbox2_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, msg[1].len, TBSQBOX_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x6a: ++ case 0x61: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBSQBOX_WRITE_MSG); ++ } else { ++ buf6[0] = msg[0].len;//length ++ buf6[1] = msg[0].addr<<1;//addr ++ buf6[2] = 0x00; ++ tbsqbox2_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBSQBOX_WRITE_MSG); ++ //msleep(5); ++ tbsqbox2_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBSQBOX_READ_MSG); ++ memcpy(msg[0].buf, inbuf, msg[0].len); ++ } ++ //msleep(3); ++ break; ++ case (TBSQBOX_RC_QUERY): ++ tbsqbox2_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBSQBOX_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ msleep(3); ++ //info("TBSQBOX_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ case (TBSQBOX_VOLTAGE_CTRL): ++ buf6[0] = 3; ++ buf6[1] = msg[0].buf[0]; ++ tbsqbox2_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ case (TBSQBOX_LED_CTRL): ++ buf6[0] = 5; ++ buf6[1] = msg[0].buf[0]; ++ tbsqbox2_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbsqbox2_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static void tbsqbox2_led_ctrl(struct dvb_frontend *fe, int offon) ++{ ++ static u8 led_off[] = { 0 }; ++ static u8 led_on[] = { 1 }; ++ struct i2c_msg msg = { ++ .addr = TBSQBOX_LED_CTRL, ++ .flags = 0, ++ .buf = led_off, ++ .len = 1 ++ }; ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ ++ if (offon) ++ msg.buf = led_on; ++ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); ++} ++ ++static struct stv090x_config earda_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 27000000, ++ .address = 0x6a, ++ ++ .ts1_mode = STV090x_TSMODE_DVBCI, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_get_frequency = stb6100_get_frequency, ++ .tuner_set_frequency = stb6100_set_frequency, ++ .tuner_set_bandwidth = stb6100_set_bandwidth, ++ .tuner_get_bandwidth = stb6100_get_bandwidth, ++ ++ .set_lock_led = tbsqbox2_led_ctrl, ++}; ++ ++static struct stb6100_config qbox2_stb6100_config = { ++ .tuner_address = 0x60, ++ .refclock = 27000000, ++}; ++ ++static struct i2c_algorithm tbsqbox2_i2c_algo = { ++ .master_xfer = tbsqbox2_i2c_transfer, ++ .functionality = tbsqbox2_i2c_func, ++}; ++ ++static int tbsqbox2_earda_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ if (!dvb_attach(stb6100_attach, adap->fe_adap->fe, &qbox2_stb6100_config, ++ &adap->dev->i2c_adap)) ++ return -EIO; ++ ++ return 0; ++} ++static int tbsqbox2_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbsqbox2_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBSQBOX_WRITE_MSG); ++ ret = tbsqbox2_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBSQBOX_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static int tbsqbox2_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ static u8 command_13v[1] = {0x00}; ++ static u8 command_18v[1] = {0x01}; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_VOLTAGE_CTRL, .flags = 0, ++ .buf = command_13v, .len = 1}, ++ }; ++ ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ if (voltage == SEC_VOLTAGE_18) ++ msg[0].buf = command_18v; ++ //info("tbsqbox2_set_voltage %d",voltage); ++ i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); ++ return 0; ++} ++ ++static struct dvb_usb_device_properties tbsqbox2_properties; ++ ++static int tbsqbox2_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ u8 buf[20]; ++ ++ if (tbsqbox2_properties.adapter->fe->tuner_attach == &tbsqbox2_earda_tuner_attach) { ++ d->fe_adap->fe = dvb_attach(stv090x_attach, &earda_config, ++ &u->i2c_adap, STV090x_DEMODULATOR_0); ++ if (d->fe_adap->fe != NULL) { ++ d->fe_adap->fe->ops.set_voltage = tbsqbox2_set_voltage; ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbsqbox2_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ return 0; ++ } ++ } ++ ++ return -EIO; ++} ++ ++ ++ ++static struct rc_map_table tbsqbox2_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++ ++ ++static int tbsqbox2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbsqbox2_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbsqbox2_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbsqbox2_table[] = { ++ {USB_DEVICE(0x734c, 0x2601)}, ++ {USB_DEVICE(0x734c, 0x5920)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbsqbox2_table); ++ ++static int tbsqbox2_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5920: ++ ret = request_firmware(&fw, tbsqbox2_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbsqbox2_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBSQBOX2 firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbsqbox2_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ tbsqbox2_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbsqbox2_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBSQBOX_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbsqbox2_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbsqbox2_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbsqbox2_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5920.fw", ++ .size_of_priv = sizeof(struct tbsqbox2_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbsqbox2_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbsqbox2_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbsqbox2_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbsqbox2_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbsqbox2_load_firmware, ++ .read_mac_address = tbsqbox2_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbsqbox2_frontend_attach, ++ .streaming_ctrl = NULL, ++ .tuner_attach = tbsqbox2_earda_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } }, ++ ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS QBOX2 DVB-S/S2", ++ {&tbsqbox2_table[1], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbsqbox2_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbsqbox2_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbsqbox2_driver = { ++ .name = "tbsqbox2", ++ .probe = tbsqbox2_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbsqbox2_table, ++}; ++ ++static int __init tbsqbox2_module_init(void) ++{ ++ int ret = usb_register(&tbsqbox2_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbsqbox2_module_exit(void) ++{ ++ usb_deregister(&tbsqbox2_driver); ++} ++ ++module_init(tbsqbox2_module_init); ++module_exit(tbsqbox2_module_exit); ++ ++MODULE_AUTHOR("Bob Liu "); ++MODULE_DESCRIPTION("Driver for TBS QBOX2 STV0903"); ++MODULE_VERSION("0.3"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox2.h b/drivers/media/usb/dvb-usb/tbs-qbox2.h +new file mode 100644 +index 0000000..adac50e +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox2.h +@@ -0,0 +1,8 @@ ++#ifndef _TBSQBOX2_H_ ++#define _TBSQBOX2_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbsqbox2" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbsqbox2_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox22.c b/drivers/media/usb/dvb-usb/tbs-qbox22.c +new file mode 100644 +index 0000000..9fa1786 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox22.c +@@ -0,0 +1,463 @@ ++/* DVB USB framework compliant Linux driver for the ++* TBS QBOX ++* ++* Copyright (C) 2008 Bob Liu (Bob@Turbosight.com) ++* Igor M. Liplianin (liplianin@me.by) ++* ++* 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, version 2. ++* ++* see Documentation/dvb/README.dvb-usb for more information ++*/ ++ ++/* ++* History: ++* ++* December 2011 Konstantin Dimitrov ++* remove QBOXS3 support ++* add QBOX22 support ++*/ ++ ++#include ++#include "tbs-qbox22.h" ++#include "tas2101.h" ++#include "av201x.h" ++ ++#ifndef USB_PID_TBSQBOX_1 ++#define USB_PID_TBSQBOX_1 0x5922 ++#endif ++ ++#define TBSQBOX_READ_MSG 0 ++#define TBSQBOX_WRITE_MSG 1 ++ ++/* on my own*/ ++#define TBSQBOX_VOLTAGE_CTRL (0x1800) ++#define TBSQBOX_RC_QUERY (0x1a00) ++ ++struct tbsqbox22_state { ++ u32 last_key_pressed; ++}; ++struct tbsqbox22_rc_keys { ++ u32 keycode; ++ u32 event; ++}; ++ ++/* debug */ ++static int dvb_usb_tbsqbox22_debug; ++module_param_named(debug, dvb_usb_tbsqbox22_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbsqbox22_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBSQBOX_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBSQBOX_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; ++ ++ if (flags == TBSQBOX_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, ++ value, index, u8buf, len, 2000); ++ ++ if (flags == TBSQBOX_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbsqbox22_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0; ++ u8 buf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ /* read */ ++ buf[0] = msg[1].len; ++ buf[1] = msg[0].addr << 1; ++ buf[2] = msg[0].buf[0]; ++ ++ tbsqbox22_op_rw(d->udev, 0x90, 0, 0, ++ buf, 3, TBSQBOX_WRITE_MSG); ++ msleep(5); ++ tbsqbox22_op_rw(d->udev, 0x91, 0, 0, ++ buf, msg[1].len, TBSQBOX_READ_MSG); ++ memcpy(msg[1].buf, buf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x68: ++ case 0x63: ++ /* write to register */ ++ buf[0] = msg[0].len + 1; //lenth ++ buf[1] = msg[0].addr << 1; //demod addr ++ for(i=0; i < msg[0].len; i++) ++ buf[2+i] = msg[0].buf[i]; //register ++ tbsqbox22_op_rw(d->udev, 0x80, 0, 0, ++ buf, msg[0].len+2, TBSQBOX_WRITE_MSG); ++ //msleep(3); ++ break; ++ case (TBSQBOX_RC_QUERY): ++ tbsqbox22_op_rw(d->udev, 0xb8, 0, 0, ++ buf, 4, TBSQBOX_READ_MSG); ++ msg[0].buf[0] = buf[2]; ++ msg[0].buf[1] = buf[3]; ++ msleep(3); ++ //info("TBSQBOX_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ case (TBSQBOX_VOLTAGE_CTRL): ++ break; ++ default: ++ break; ++ } ++ ++ break; ++ default: ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbsqbox22_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++ ++static struct i2c_algorithm tbsqbox22_i2c_algo = { ++ .master_xfer = tbsqbox22_i2c_transfer, ++ .functionality = tbsqbox22_i2c_func, ++}; ++ ++ ++static int tbsqbox22_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 buf[3]; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ buf[0] = 1; //lenth ++ buf[1] = 0xa0; //eeprom addr ++ buf[2] = i; //register ++ ret = tbsqbox22_op_rw(d->udev, 0x90, 0, 0, ++ buf, 3, TBSQBOX_WRITE_MSG); ++ ret = tbsqbox22_op_rw(d->udev, 0x91, 0, 0, ++ buf, 1, TBSQBOX_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed"); ++ return -1; ++ } else { ++ eepromline[i % 16] = buf[0]; ++ eeprom[i] = buf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static struct dvb_usb_device_properties tbsqbox22_properties; ++ ++ ++static struct tas2101_config tbs5922_cfg = { ++ .i2c_address = 0x68, ++ .id = ID_TAS2100, ++ .reset_demod = NULL, ++ .lnb_power = NULL, ++ .init = {0xb8, 0x67, 0x45, 0x23, 0x01, 0x9a, 0x33}, ++ .init2 = 0, ++}; ++ ++static struct av201x_config tbs5922_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int tbsqbox22_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ u8 buf[20]; ++ ++ d->fe_adap->fe = dvb_attach(tas2101_attach, &tbs5922_cfg, ++ &u->i2c_adap); ++ if (d->fe_adap->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, d->fe_adap->fe, &tbs5922_av201x_cfg, ++ tas2101_get_i2c_adapter(d->fe_adap->fe, 2)) == NULL) { ++ dvb_frontend_detach(d->fe_adap->fe); ++ d->fe_adap->fe = NULL; ++ goto err; ++ } ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbsqbox22_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBSQBOX_WRITE_MSG); ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ tbsqbox22_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBSQBOX_WRITE_MSG); ++ ++ buf[0] = 6; ++ buf[1] = 1; ++ tbsqbox22_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBSQBOX_WRITE_MSG); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ ++ return 0; ++err: ++ return -ENODEV; ++} ++ ++ ++ ++static struct rc_map_table tbsqbox22_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++ ++ ++static int tbsqbox22_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbsqbox22_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbsqbox22_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbsqbox22_table[] = { ++ {USB_DEVICE(0x734c, 0x5922)}, ++ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_TBSQBOX_1)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbsqbox22_table); ++ ++static int tbsqbox22_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ const char *filename = "dvb-usb-tbsqbox-id5922.fw"; ++ switch (dev->descriptor.idProduct) { ++ case 0x5922: ++ ret = request_firmware(&fw, filename, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", filename); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBSQBOX firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbsqbox22_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ tbsqbox22_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbsqbox22_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBSQBOX_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbsqbox22_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbsqbox22_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbsqbox22_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5922.fw", ++ .size_of_priv = sizeof(struct tbsqbox22_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbsqbox22_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbsqbox22_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbsqbox22_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbsqbox22_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbsqbox22_load_firmware, ++ .read_mac_address = tbsqbox22_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbsqbox22_frontend_attach, ++ .streaming_ctrl = NULL, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ }}, ++ }}, ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight QBOX3 DVB-S/S2", ++ {&tbsqbox22_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbsqbox22_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbsqbox22_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbsqbox22_driver = { ++ .name = "tbsqbox22", ++ .probe = tbsqbox22_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbsqbox22_table, ++}; ++ ++static int __init tbsqbox22_module_init(void) ++{ ++ int ret = usb_register(&tbsqbox22_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbsqbox22_module_exit(void) ++{ ++ usb_deregister(&tbsqbox22_driver); ++} ++ ++module_init(tbsqbox22_module_init); ++module_exit(tbsqbox22_module_exit); ++ ++MODULE_AUTHOR("Bob Liu "); ++MODULE_DESCRIPTION("Driver for TBS QBOX22"); ++MODULE_VERSION("0.2"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox22.h b/drivers/media/usb/dvb-usb/tbs-qbox22.h +new file mode 100644 +index 0000000..f05ea3c +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox22.h +@@ -0,0 +1,8 @@ ++#ifndef _TBSQBOX22_H_ ++#define _TBSQBOX22_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbsqbox22" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbsqbox22_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox2ci.c b/drivers/media/usb/dvb-usb/tbs-qbox2ci.c +new file mode 100644 +index 0000000..5b008b9 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox2ci.c +@@ -0,0 +1,849 @@ ++/* ++ * TurboSight (TBS) Qbox DVB-S2 CI driver ++ * ++ * Copyright (c) 2010 Konstantin Dimitrov ++ * ++ * 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, version 2. ++ * ++ */ ++ ++#include ++#include "tbs-qbox2ci.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "stb6100.h" ++#include "stb6100_cfg.h" ++ ++#include "dvb_ca_en50221.h" ++ ++#define TBSQBOX_READ_MSG 0 ++#define TBSQBOX_WRITE_MSG 1 ++#define TBSQBOX_LED_CTRL (0x1b00) ++ ++/* on my own*/ ++#define TBSQBOX_VOLTAGE_CTRL (0x1800) ++#define TBSQBOX_RC_QUERY (0x1a00) ++ ++struct tbsqbox2ci_state { ++ struct dvb_ca_en50221 ca; ++ struct mutex ca_mutex; ++ ++ u32 last_key_pressed; ++}; ++ ++/*struct tbsqbox2ci_rc_keys { ++ u32 keycode; ++ u32 event; ++};*/ ++ ++/* debug */ ++static int dvb_usb_tbsqbox2ci_debug; ++module_param_named(debug, dvb_usb_tbsqbox2ci_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbsqbox2ci_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBSQBOX_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBSQBOX_READ_MSG) ? USB_DIR_IN : ++ USB_DIR_OUT; ++ ++ if (flags == TBSQBOX_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | ++ USB_TYPE_VENDOR, value, index , u8buf, len, 2000); ++ ++ if (flags == TBSQBOX_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++static int tbsqbox2ci_read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ u8 buf[4], rbuf[3]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ ++ //msleep(10); ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa4, 0, 0, ++ buf, 4, TBSQBOX_WRITE_MSG); ++ ++ //msleep(1); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa5, 0, 0, ++ rbuf, 1, TBSQBOX_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return rbuf[0]; ++} ++ ++static int tbsqbox2ci_write_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address, u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ u8 buf[5];//, rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ buf[4] = value; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa2, 0, 0, ++ buf, 5, TBSQBOX_WRITE_MSG); ++ ++ //msleep(1); ++ ++ //ret = tbsqbox2ci_op_rw(d->udev, 0xa5, 0, 0, ++ // rbuf, 1, TBSQBOX_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbsqbox2ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ u8 buf[4], rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa4, 0, 0, ++ buf, 4, TBSQBOX_WRITE_MSG); ++ ++ //msleep(10); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa5, 0, 0, ++ rbuf, 1, TBSQBOX_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return rbuf[0]; ++} ++ ++static int tbsqbox2ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ u8 buf[5];//, rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ buf[4] = value; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa2, 0, 0, ++ buf, 5, TBSQBOX_WRITE_MSG); ++ ++ //msleep(1); ++ ++ //ret = tbsqbox2ci_op_rw(d->udev, 0xa5, 0, 0, ++ // rbuf, 1, TBSQBOX_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbsqbox2ci_set_video_port(struct dvb_ca_en50221 *ca, ++ int slot, int enable) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ u8 buf[2]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 2; ++ buf[1] = enable; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ if (enable != buf[1]) { ++ err("CI not %sabled.", enable ? "en" : "dis"); ++ return -EIO; ++ } ++ ++ info("CI %sabled.", enable ? "en" : "dis"); ++ return 0; ++} ++ ++static int tbsqbox2ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbsqbox2ci_set_video_port(ca, slot, /* enable */ 0); ++} ++ ++static int tbsqbox2ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbsqbox2ci_set_video_port(ca, slot, /* enable */ 1); ++} ++ ++static int tbsqbox2ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ u8 buf[2]; ++ int ret; ++ ++ if (0 != slot) { ++ return -EINVAL; ++ } ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ ++ mutex_lock (&state->ca_mutex); ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ msleep (5); ++ ++ buf[1] = 1; ++ ++ ret = tbsqbox2ci_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ msleep (1400); ++ ++ mutex_unlock (&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbsqbox2ci_poll_slot_status(struct dvb_ca_en50221 *ca, ++ int slot, int open) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ u8 buf[3]; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ tbsqbox2ci_op_rw(d->udev, 0xa8, 0, 0, ++ buf, 3, TBSQBOX_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if ((1 == buf[2]) && (1 == buf[1]) && (0xa9 == buf[0])) { ++ return (DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY); ++ } else { ++ return 0; ++ } ++} ++ ++static void tbsqbox2ci_uninit(struct dvb_usb_device *d) ++{ ++ struct tbsqbox2ci_state *state; ++ ++ if (NULL == d) ++ return; ++ ++ state = (struct tbsqbox2ci_state *)d->priv; ++ if (NULL == state) ++ return; ++ ++ if (NULL == state->ca.data) ++ return; ++ ++ /* Error ignored. */ ++ tbsqbox2ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); ++ ++ dvb_ca_en50221_release(&state->ca); ++ ++ memset(&state->ca, 0, sizeof(state->ca)); ++} ++ ++static int tbsqbox2ci_init(struct dvb_usb_adapter *a) ++{ ++ ++ struct dvb_usb_device *d = a->dev; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ int ret; ++ ++ state->ca.owner = THIS_MODULE; ++ state->ca.read_attribute_mem = tbsqbox2ci_read_attribute_mem; ++ state->ca.write_attribute_mem = tbsqbox2ci_write_attribute_mem; ++ state->ca.read_cam_control = tbsqbox2ci_read_cam_control; ++ state->ca.write_cam_control = tbsqbox2ci_write_cam_control; ++ state->ca.slot_reset = tbsqbox2ci_slot_reset; ++ state->ca.slot_shutdown = tbsqbox2ci_slot_shutdown; ++ state->ca.slot_ts_enable = tbsqbox2ci_slot_ts_enable; ++ state->ca.poll_slot_status = tbsqbox2ci_poll_slot_status; ++ state->ca.data = d; ++ ++ ret = dvb_ca_en50221_init (&a->dvb_adap, &state->ca, ++ /* flags */ 0, /* n_slots */ 1); ++ ++ if (0 != ret) { ++ err ("Cannot initialize CI: Error %d.", ret); ++ memset (&state->ca, 0, sizeof (state->ca)); ++ return ret; ++ } ++ ++ info ("CI initialized."); ++ ++ ret = tbsqbox2ci_poll_slot_status(&state->ca, 0, 0); ++ if (0 == ret) ++ tbsqbox2ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); ++ ++ return 0; ++} ++ ++/* I2C */ ++static int tbsqbox2ci_i2c_transfer(struct i2c_adapter *adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)d->priv; ++ int i = 0; ++ u8 buf6[20]; ++ u8 inbuf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ //register ++ buf6[2] = msg[0].buf[0]; ++ buf6[3] = msg[0].buf[1]; ++ ++ tbsqbox2ci_op_rw(d->udev, 0x92, 0, 0, ++ buf6, 4, TBSQBOX_WRITE_MSG); ++ //msleep(5); ++ tbsqbox2ci_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, msg[1].len, TBSQBOX_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x6a: ++ case 0x61: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBSQBOX_WRITE_MSG); ++ } else { ++ buf6[0] = msg[0].len;//length ++ buf6[1] = msg[0].addr<<1;//addr ++ buf6[2] = 0x00; ++ tbsqbox2ci_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBSQBOX_WRITE_MSG); ++ //msleep(5); ++ tbsqbox2ci_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBSQBOX_READ_MSG); ++ memcpy(msg[0].buf, inbuf, msg[0].len); ++ } ++ //msleep(3); ++ break; ++ case (TBSQBOX_RC_QUERY): ++ tbsqbox2ci_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBSQBOX_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ //msleep(3); ++ //info("TBSQBOX_RC_QUERY %x %x %x %x\n", ++ // buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ case (TBSQBOX_VOLTAGE_CTRL): ++ buf6[0] = 3; ++ buf6[1] = msg[0].buf[0]; ++ tbsqbox2ci_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ case (TBSQBOX_LED_CTRL): ++ buf6[0] = 5; ++ buf6[1] = msg[0].buf[0]; ++ tbsqbox2ci_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ mutex_unlock(&state->ca_mutex); ++ return num; ++} ++ ++static u32 tbsqbox2ci_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static void tbsqbox2ci_led_ctrl(struct dvb_frontend *fe, int offon) ++{ ++ static u8 led_off[] = { 0 }; ++ static u8 led_on[] = { 1 }; ++ struct i2c_msg msg = { ++ .addr = TBSQBOX_LED_CTRL, ++ .flags = 0, ++ .buf = led_off, ++ .len = 1 ++ }; ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ ++ if (offon) ++ msg.buf = led_on; ++ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); ++} ++ ++static struct stv090x_config earda_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 27000000, ++ .address = 0x6a, ++ ++ .ts1_mode = STV090x_TSMODE_DVBCI, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_get_frequency = stb6100_get_frequency, ++ .tuner_set_frequency = stb6100_set_frequency, ++ .tuner_set_bandwidth = stb6100_set_bandwidth, ++ .tuner_get_bandwidth = stb6100_get_bandwidth, ++ ++ .set_lock_led = tbsqbox2ci_led_ctrl, ++}; ++ ++static struct stb6100_config qbox2_stb6100_config = { ++ .tuner_address = 0x60, ++ .refclock = 27000000, ++}; ++ ++static struct i2c_algorithm tbsqbox2ci_i2c_algo = { ++ .master_xfer = tbsqbox2ci_i2c_transfer, ++ .functionality = tbsqbox2ci_i2c_func, ++}; ++ ++static int tbsqbox2ci_earda_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ if (!dvb_attach(stb6100_attach, adap->fe_adap->fe, &qbox2_stb6100_config, ++ &adap->dev->i2c_adap)) ++ return -EIO; ++ ++ return 0; ++} ++static int tbsqbox2ci_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbsqbox2ci_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBSQBOX_WRITE_MSG); ++ ret = tbsqbox2ci_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBSQBOX_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static int tbsqbox2ci_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ static u8 command_13v[1] = {0x00}; ++ static u8 command_18v[1] = {0x01}; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_VOLTAGE_CTRL, .flags = 0, ++ .buf = command_13v, .len = 1}, ++ }; ++ ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ if (voltage == SEC_VOLTAGE_18) ++ msg[0].buf = command_18v; ++ //info("tbsqbox2ci_set_voltage %d",voltage); ++ i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); ++ return 0; ++} ++ ++static struct dvb_usb_device_properties tbsqbox2ci_properties; ++ ++static int tbsqbox2ci_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ struct tbsqbox2ci_state *state = (struct tbsqbox2ci_state *)u->priv; ++ u8 buf[20]; ++ ++ mutex_init(&state->ca_mutex); ++ ++ if (tbsqbox2ci_properties.adapter->fe->tuner_attach == &tbsqbox2ci_earda_tuner_attach) { ++ d->fe_adap->fe = dvb_attach(stv090x_attach, &earda_config, ++ &u->i2c_adap, STV090x_DEMODULATOR_0); ++ if (d->fe_adap->fe != NULL) { ++ d->fe_adap->fe->ops.set_voltage = tbsqbox2ci_set_voltage; ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbsqbox2ci_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ tbsqbox2ci_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ buf[0] = 6; ++ buf[1] = 1; ++ tbsqbox2ci_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ tbsqbox2ci_init(d); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ return 0; ++ } ++ } ++ ++ return -EIO; ++} ++ ++static void tbsqbox2ci2_usb_disconnect (struct usb_interface * intf) ++{ ++ struct dvb_usb_device *d = usb_get_intfdata (intf); ++ ++ tbsqbox2ci_uninit (d); ++ dvb_usb_device_exit (intf); ++} ++ ++static struct rc_map_table tbsqbox2ci_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++static int tbsqbox2ci_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbsqbox2ci_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbsqbox2ci_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbsqbox2ci_table[] = { ++ {USB_DEVICE(0x734c, 0x5980)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbsqbox2ci_table); ++ ++static int tbsqbox2ci_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5980: ++ ret = request_firmware(&fw, tbsqbox2ci_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbsqbox2ci_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBSQBOX2CI firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbsqbox2ci_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ tbsqbox2ci_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbsqbox2ci_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBSQBOX_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbsqbox2ci_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbsqbox2ci_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbsqbox2ci_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5980.fw", ++ .size_of_priv = sizeof(struct tbsqbox2ci_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbsqbox2ci_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbsqbox2ci_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbsqbox2ci_rc_keys), ++ .rc_interval = 450, ++ .rc_query = tbsqbox2ci_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbsqbox2ci_load_firmware, ++ .read_mac_address = tbsqbox2ci_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbsqbox2ci_frontend_attach, ++ .streaming_ctrl = NULL, ++ .tuner_attach = tbsqbox2ci_earda_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } }, ++ ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS QBOX2-CI DVB-S/S2", ++ {&tbsqbox2ci_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbsqbox2ci_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbsqbox2ci_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbsqbox2ci_driver = { ++ .name = "tbsqbox2ci", ++ .probe = tbsqbox2ci_probe, ++ .disconnect = tbsqbox2ci2_usb_disconnect, ++ .id_table = tbsqbox2ci_table, ++}; ++ ++static int __init tbsqbox2ci_module_init(void) ++{ ++ int ret = usb_register(&tbsqbox2ci_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbsqbox2ci_module_exit(void) ++{ ++ usb_deregister(&tbsqbox2ci_driver); ++} ++ ++module_init(tbsqbox2ci_module_init); ++module_exit(tbsqbox2ci_module_exit); ++ ++MODULE_AUTHOR("Konstantin Dimitrov "); ++MODULE_DESCRIPTION("TurboSight (TBS) Qbox DVB-S2 CI driver"); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs-qbox2ci.h b/drivers/media/usb/dvb-usb/tbs-qbox2ci.h +new file mode 100644 +index 0000000..152849f +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qbox2ci.h +@@ -0,0 +1,8 @@ ++#ifndef _TBSQBOX2CI_H_ ++#define _TBSQBOX2CI_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbsqbox2ci" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbsqbox2ci_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs-qboxs2.c b/drivers/media/usb/dvb-usb/tbs-qboxs2.c +new file mode 100644 +index 0000000..d3b03a2 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qboxs2.c +@@ -0,0 +1,508 @@ ++/* DVB USB framework compliant Linux driver for the ++* TBS QBOX ++* ++* Copyright (C) 2008 Bob Liu (Bob@Turbosight.com) ++* Igor M. Liplianin (liplianin@me.by) ++* ++* 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, version 2. ++* ++* see Documentation/dvb/README.dvb-usb for more information ++*/ ++ ++/* ++* History: ++* ++* July 2009 Konstantin Dimitrov ++* remove QBOX2-DS3000 support ++* add QBOXS2-CX24116 support ++*/ ++ ++#include ++#include "tbs-qboxs2.h" ++#include "cx24116.h" ++ ++#define TBSQBOX_READ_MSG 0 ++#define TBSQBOX_WRITE_MSG 1 ++ ++/* on my own*/ ++#define TBSQBOX_VOLTAGE_CTRL (0x1800) ++#define TBSQBOX_RC_QUERY (0x1a00) ++#define TBSQBOX_LED_CTRL (0x1b00) ++ ++struct tbsqboxs2_state { ++ u32 last_key_pressed; ++}; ++struct tbsqboxs2_rc_keys { ++ u32 keycode; ++ u32 event; ++}; ++ ++/* debug */ ++static int dvb_usb_tbsqboxs2_debug; ++module_param_named(debug, dvb_usb_tbsqboxs2_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbsqboxs2_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBSQBOX_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBSQBOX_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; ++ ++ if (flags == TBSQBOX_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, ++ value, index, u8buf, len, 2000); ++ ++ if (flags == TBSQBOX_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbsqboxs2_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0, len; ++ u8 ibuf[1], obuf[3]; ++ u8 buf6[20]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: { ++ /* read */ ++ obuf[0] = msg[0].len; ++ obuf[1] = msg[0].addr<<1; ++ obuf[2] = msg[0].buf[0]; ++ ++ tbsqboxs2_op_rw(d->udev, 0x90, 0, 0, ++ obuf, 3, TBSQBOX_WRITE_MSG); ++ msleep(5); ++ tbsqboxs2_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, msg[1].len, TBSQBOX_READ_MSG); ++ memcpy(msg[1].buf, ibuf, msg[1].len); ++ break; ++ } ++ case 1: ++ switch (msg[0].addr) { ++ case 0x55: { ++ if (msg[0].buf[0] == 0xf7) { ++ /* firmware */ ++ /* Write in small blocks */ ++ u8 iobuf[19]; ++ iobuf[0] = 0x12; ++ iobuf[1] = 0xaa; ++ iobuf[2] = 0xf7; ++ len = msg[0].len - 1; ++ i = 1; ++ do { ++ memcpy(iobuf + 3, msg[0].buf + i, (len > 16 ? 16 : len)); ++ tbsqboxs2_op_rw(d->udev, 0x80, 0, 0, ++ iobuf, (len > 16 ? 16 : len) + 3, TBSQBOX_WRITE_MSG); ++ i += 16; ++ len -= 16; ++ } while (len > 0); ++ } else { ++ /* write to register */ ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//demod addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBSQBOX_WRITE_MSG); ++ //msleep(3); ++ } ++ break; ++ } ++ case 0x60: { ++ /* write to register */ ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//demod addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBSQBOX_WRITE_MSG); ++ msleep(3); ++ ++ break; ++ } ++ case (TBSQBOX_RC_QUERY): { ++ tbsqboxs2_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBSQBOX_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ msleep(3); ++ //info("TBSQBOX_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ } ++ case (TBSQBOX_VOLTAGE_CTRL): { ++ buf6[0] = 3; ++ buf6[1] = msg[0].buf[0]; ++ tbsqboxs2_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ } ++ case (TBSQBOX_LED_CTRL): { ++ buf6[0] = 5; ++ buf6[1] = msg[0].buf[0]; ++ tbsqboxs2_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBSQBOX_WRITE_MSG); ++ break; ++ } ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbsqboxs2_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm tbsqboxs2_i2c_algo = { ++ .master_xfer = tbsqboxs2_i2c_transfer, ++ .functionality = tbsqboxs2_i2c_func, ++}; ++ ++static void tbsqboxs2_led_ctrl(struct dvb_frontend *fe, int offon) ++{ ++ static u8 led_off[] = { 0 }; ++ static u8 led_on[] = { 1 }; ++ struct i2c_msg msg = { ++ .addr = TBSQBOX_LED_CTRL, ++ .flags = 0, ++ .buf = led_off, ++ .len = 1 ++ }; ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ ++ if (offon) ++ msg.buf = led_on; ++ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); ++} ++ ++static const struct cx24116_config qbox2_cx24116_config = { ++ .demod_address = 0x55, ++ .mpg_clk_pos_pol = 0x01, ++ .set_lock_led = tbsqboxs2_led_ctrl, ++}; ++ ++static int tbsqboxs2_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbsqboxs2_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBSQBOX_WRITE_MSG); ++ ret = tbsqboxs2_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBSQBOX_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed"); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static int tbsqboxs2_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) ++{ ++ static u8 command_13v[1] = {0x00}; ++ static u8 command_18v[1] = {0x01}; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_VOLTAGE_CTRL, .flags = 0, ++ .buf = command_13v, .len = 1}, ++ }; ++ ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ if (voltage == SEC_VOLTAGE_18) ++ msg[0].buf = command_18v; ++ info("tbsqboxs2_set_voltage %d",voltage); ++ i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); ++ return 0; ++} ++ ++static struct dvb_usb_device_properties tbsqboxs2_properties; ++ ++static int tbsqboxs2_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ u8 buf[20]; ++ ++ if ((d->fe_adap->fe = dvb_attach(cx24116_attach, &qbox2_cx24116_config, ++ &u->i2c_adap)) != NULL) { ++ d->fe_adap->fe->ops.set_voltage = tbsqboxs2_set_voltage; ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbsqboxs2_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBSQBOX_WRITE_MSG); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ return 0; ++ } ++ ++ return -EIO; ++} ++ ++static struct rc_map_table tbsqboxs2_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++ ++ ++static int tbsqboxs2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbsqboxs2_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBSQBOX_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbsqboxs2_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbsqboxs2_table[] = { ++ {USB_DEVICE(0x734c, 0x5928)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbsqboxs2_table); ++ ++static int tbsqboxs2_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5928: ++ ret = request_firmware(&fw, tbsqboxs2_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbsqboxs2_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBSQBOX firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbsqboxs2_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ tbsqboxs2_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBSQBOX_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbsqboxs2_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBSQBOX_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbsqboxs2_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbsqboxs2_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBSQBOX_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbsqboxs2_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5928.fw", ++ .size_of_priv = sizeof(struct tbsqboxs2_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbsqboxs2_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbsqboxs2_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbsqboxs2_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbsqboxs2_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbsqboxs2_load_firmware, ++ .read_mac_address = tbsqboxs2_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbsqboxs2_frontend_attach, ++ .streaming_ctrl = NULL, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } }, ++ ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS QBOX-S2 DVB-S/S2", ++ {&tbsqboxs2_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbsqboxs2_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbsqboxs2_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbsqboxs2_driver = { ++ .name = "tbsqboxs2", ++ .probe = tbsqboxs2_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbsqboxs2_table, ++}; ++ ++static int __init tbsqboxs2_module_init(void) ++{ ++ int ret = usb_register(&tbsqboxs2_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbsqboxs2_module_exit(void) ++{ ++ usb_deregister(&tbsqboxs2_driver); ++} ++ ++module_init(tbsqboxs2_module_init); ++module_exit(tbsqboxs2_module_exit); ++ ++MODULE_AUTHOR("Bob Liu "); ++MODULE_DESCRIPTION("Driver for TBS QBOXS2-CX24116"); ++MODULE_VERSION("0.2"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs-qboxs2.h b/drivers/media/usb/dvb-usb/tbs-qboxs2.h +new file mode 100644 +index 0000000..fb7fd04 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs-qboxs2.h +@@ -0,0 +1,8 @@ ++#ifndef _TBSQBOXS2_H_ ++#define _TBSQBOXS2_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbsqboxs2" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbsqboxs2_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs5220.c b/drivers/media/usb/dvb-usb/tbs5220.c +new file mode 100644 +index 0000000..7bf7dea +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5220.c +@@ -0,0 +1,500 @@ ++/* ++ * TurboSight TBS 5220 driver ++ * ++ * Copyright (c) 2013 Konstantin Dimitrov ++ * ++ * 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, version 2. ++ * ++ */ ++ ++#include ++#include "tbs5220.h" ++#include "si2168.h" ++#include "si2157.h" ++ ++#define TBS5220_READ_MSG 0 ++#define TBS5220_WRITE_MSG 1 ++ ++#define TBS5220_RC_QUERY (0x1a00) ++ ++struct tbs5220_state { ++ struct i2c_client *i2c_client_demod; ++ struct i2c_client *i2c_client_tuner; ++ u32 last_key_pressed; ++}; ++ ++/* debug */ ++static int dvb_usb_tbs5220_debug; ++module_param_named(debug, dvb_usb_tbs5220_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbs5220_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBS5220_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBS5220_READ_MSG) ? USB_DIR_IN : ++ USB_DIR_OUT; ++ ++ if (flags == TBS5220_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | ++ USB_TYPE_VENDOR, value, index , u8buf, len, 2000); ++ ++ if (flags == TBS5220_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbs5220_i2c_transfer(struct i2c_adapter *adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0; ++ u8 buf6[20]; ++ u8 inbuf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ //register ++ buf6[2] = msg[0].buf[0]; ++ ++ tbs5220_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBS5220_WRITE_MSG); ++ //msleep(5); ++ tbs5220_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBS5220_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x64: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBS5220_WRITE_MSG); ++ } else { ++ buf6[0] = msg[0].len;//length ++ buf6[1] = (msg[0].addr<<1) | 0x01;//addr ++ tbs5220_op_rw(d->udev, 0x93, 0, 0, ++ buf6, 2, TBS5220_WRITE_MSG); ++ //msleep(5); ++ tbs5220_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBS5220_READ_MSG); ++ memcpy(msg[0].buf, inbuf, msg[0].len); ++ } ++ //msleep(3); ++ break; ++ case (TBS5220_RC_QUERY): ++ tbs5220_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBS5220_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ //msleep(3); ++ //info("TBS5220_RC_QUERY %x %x %x %x\n", ++ // buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbs5220_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm tbs5220_i2c_algo = { ++ .master_xfer = tbs5220_i2c_transfer, ++ .functionality = tbs5220_i2c_func, ++}; ++ ++static int tbs5220_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbs5220_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBS5220_WRITE_MSG); ++ ret = tbs5220_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBS5220_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static struct dvb_usb_device_properties tbs5220_properties; ++ ++static int tbs5220_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ struct dvb_usb_device *d = adap->dev; ++ struct tbs5220_state *st = d->priv; ++ struct i2c_adapter *adapter; ++ struct i2c_client *client_demod; ++ struct i2c_client *client_tuner; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ u8 buf[20]; ++ ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &adap->fe_adap[0].fe; ++ si2168_config.ts_mode = SI2168_TS_PARALLEL; ++ si2168_config.ts_clock_gapped = true; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(&d->i2c_adap, &info); ++ if (client_demod == NULL || client_demod->dev.driver == NULL) ++ return -ENODEV; ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adap->fe_adap[0].fe; ++ si2157_config.if_port = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(adapter, &info); ++ if (client_tuner == NULL || client_tuner->dev.driver == NULL) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ ++ st->i2c_client_demod = client_demod; ++ st->i2c_client_tuner = client_tuner; ++ ++ buf[0] = 0; ++ buf[1] = 0; ++ tbs5220_op_rw(d->udev, 0xb7, 0, 0, ++ buf, 2, TBS5220_WRITE_MSG); ++ buf[0] = 8; ++ buf[1] = 1; ++ tbs5220_op_rw(d->udev, 0x8a, 0, 0, ++ buf, 2, TBS5220_WRITE_MSG); ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbs5220_op_rw(d->udev, 0x8a, 0, 0, ++ buf, 2, TBS5220_WRITE_MSG); ++ ++ buf[0] = 6; ++ buf[1] = 1; ++ tbs5220_op_rw(d->udev, 0x8a, 0, 0, ++ buf, 2, TBS5220_WRITE_MSG); ++ ++ strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52); ++ ++ return 0; ++} ++ ++static struct rc_map_table tbs5220_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++static int tbs5220_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbs5220_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBS5220_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbs5220_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbs5220_table[] = { ++ {USB_DEVICE(0x734c, 0x5220)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbs5220_table); ++ ++static int tbs5220_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5220: ++ ret = request_firmware(&fw, tbs5220_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbs5220_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBS5220 firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbs5220_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5220_WRITE_MSG); ++ tbs5220_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5220_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbs5220_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBS5220_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbs5220_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBS5220_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbs5220_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBS5220_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbs5220_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5220.fw", ++ .size_of_priv = sizeof(struct tbs5220_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbs5220_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbs5220_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbs5220_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbs5220_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbs5220_load_firmware, ++ .read_mac_address = tbs5220_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbs5220_frontend_attach, ++ .streaming_ctrl = NULL, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ }}, ++ }}, ++ ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS 5220 DVB-T/T2/C", ++ {&tbs5220_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbs5220_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbs5220_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static void tbs5220_disconnect(struct usb_interface *intf) ++{ ++#if 0 ++ struct dvb_usb_device *d = usb_get_intfdata(intf); ++ struct tbs5220_state *st = d->priv; ++ struct i2c_client *client; ++ ++ /* remove I2C client for tuner */ ++ client = st->i2c_client_tuner; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ ++ /* remove I2C client for demodulator */ ++ client = st->i2c_client_demod; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++#endif ++ dvb_usb_device_exit(intf); ++} ++ ++static struct usb_driver tbs5220_driver = { ++ .name = "tbs5220", ++ .probe = tbs5220_probe, ++ .disconnect = tbs5220_disconnect, ++ .id_table = tbs5220_table, ++}; ++ ++static int __init tbs5220_module_init(void) ++{ ++ int ret = usb_register(&tbs5220_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbs5220_module_exit(void) ++{ ++ usb_deregister(&tbs5220_driver); ++} ++ ++module_init(tbs5220_module_init); ++module_exit(tbs5220_module_exit); ++ ++MODULE_AUTHOR("Konstantin Dimitrov "); ++MODULE_DESCRIPTION("TurboSight TBS 5220 driver"); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs5220.h b/drivers/media/usb/dvb-usb/tbs5220.h +new file mode 100644 +index 0000000..52595cf +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5220.h +@@ -0,0 +1,8 @@ ++#ifndef _TBS5220_H_ ++#define _TBS5220_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbs5220" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbs5220_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs5520.c b/drivers/media/usb/dvb-usb/tbs5520.c +new file mode 100644 +index 0000000..37849bd +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5520.c +@@ -0,0 +1,518 @@ ++/* ++ * TurboSight TBS 5520 driver ++ * ++ * Copyright (c) 2013 Konstantin Dimitrov ++ * ++ * 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, version 2. ++ * ++ */ ++ ++#include ++#include "tbs5520.h" ++ ++#include "avl6882.h" ++#include "r848.h" ++ ++#ifndef USB_PID_tbs5520 ++#define USB_PID_tbs5520 0x5520 ++#endif ++ ++#define tbs5520_READ_MSG 0 ++#define tbs5520_WRITE_MSG 1 ++ ++#define tbs5520_RC_QUERY (0x1a00) ++ ++struct tbs5520_state { ++ u32 last_key_pressed; ++}; ++ ++/* debug */ ++static int dvb_usb_tbs5520_debug; ++module_param_named(debug, dvb_usb_tbs5520_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbs5520_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 *data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == tbs5520_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == tbs5520_READ_MSG) ? USB_DIR_IN : ++ USB_DIR_OUT; ++ ++ if (flags == tbs5520_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | ++ USB_TYPE_VENDOR, value, index , u8buf, len, 2000); ++ ++ if (flags == tbs5520_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++ ++#define MAX_I2C_LEN 62 ++ ++static int tbs5520_i2c_transfer(struct i2c_adapter *adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i; ++ u8 txbuf[64]; ++ ++ if (msg[0].addr == tbs5520_RC_QUERY) ++ return -ENODEV; ++ ++ if (!d) ++ return -ENODEV; ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ for (i = 0; i < num; i++) { ++ if (msg[i].len > MAX_I2C_LEN) ++ break; ++ if (msg[i].buf == NULL) ++ break; ++ ++ if (msg[i].flags & I2C_M_RD) { ++ //printk("RD: saddr=%02x len=%d:", msg[i].addr, msg[i].len); ++ /* read */ ++ txbuf[0] = msg[i].len; ++ txbuf[1] = (msg[i].addr << 1) | 1; ++ tbs5520_op_rw(d->udev, 0x93, 0, 0, txbuf, 2, tbs5520_WRITE_MSG); ++ tbs5520_op_rw(d->udev, 0x91, 0, 0, msg[i].buf, msg[i].len, tbs5520_READ_MSG); ++ //for (j = 0; j < msg[i].len; j++) ++ // printk(" %02x", msg[i].buf[j]); ++ //printk("\n"); ++ } else { ++ //printk("WR: saddr=%02x len=%d:", msg[i].addr, msg[i].len); ++ //for (j = 0; j < msg[i].len; j++) ++ // printk(" %02x", msg[i].buf[j]); ++ //printk("\n"); ++ txbuf[0] = msg[i].len + 1; ++ txbuf[1] = msg[i].addr << 1; ++ memcpy(&txbuf[2], msg[i].buf, msg[i].len); ++ tbs5520_op_rw(d->udev, 0x80, 0, 0, txbuf, msg[i].len + 2, tbs5520_WRITE_MSG); ++ } ++ } ++ ++ //printk("msg=%d\n", i); ++#if 0 ++ ++ switch (num) { ++ case 2: ++ printk("wr-rd: adr=%02x rd_len=%02x", msg[0].addr, msg[1].len); ++ buf6[0] = msg[1].len; // lenth ++ buf6[1] = (msg[0].addr<<1)+1; // slave addr ++ ++ ++ //register ++ //buf6[2] = 0; ++ ++ /* wr,rd | 0x90 -> 0x91 ++ wr | 0x80 ++ rd | 0x90 -> 0x91 ++ */ ++ ++ /* request 0x80 = i2c write (data=[wr_len+1, slave_addr, buf...] len=wr_len+2) */ ++ /* request 0x82 = i2c write (data=buf, len=64) -- no i2c stop? -- */ ++ ++ /* request 0x90 = i2c read n bytes (data=[rd_len, slave_addr, x?]; len=2+x?) */ ++ /* request 0x91 = i2c grab received data (data=buf, len=rd_len) */ ++ ++ /* request 0x92 = i2c read n bytes 16bit reg? (data=[rd_len, slave_addr, r1, r2]; len=4) */ ++ /* request 0x93 = i2c read n bytes (data=[rd_len, slave_addr | 1]; len=2) */ ++ ++ /* tbs5520_op_rw(struct usb_device *dev, u8 request, u16 value, u16 index, u8 * data, u16 len, int flags) */ ++ ++ tbs5520_op_rw(d->udev, 0x93, 0, 0, buf6, 2, tbs5520_WRITE_MSG); ++ //msleep(5); ++ tbs5520_op_rw(d->udev, 0x91, 0, 0, inbuf, buf6[0], tbs5520_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ ++ for (i = 0; i < msg[1].len; i++) ++ printk(" %02x", inbuf[i]); ++ ++ printk("\n"); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x14: ++ case 0x7a: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, buf6, msg[0].len+2, tbs5520_WRITE_MSG); ++ } else { ++ printk("wr_1:"); ++ for (i = 0; i < msg[0].len; i++) ++ printk(" %02x", msg[0].buf[i]); ++ tbs5520_op_rw(d->udev, 0x82, 0, 0, msg[0].buf, 64, tbs5520_WRITE_MSG); ++ } ++ printk("\n"); ++ ++ //msleep(3); ++ break; ++ ++ case (tbs5520_RC_QUERY): ++ tbs5520_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, tbs5520_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ //msleep(3); ++ //info("tbs5520_RC_QUERY %x %x %x %x\n", ++ // buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ } ++ ++ break; ++ } ++ ++#endif ++ mutex_unlock(&d->i2c_mutex); ++ return i; ++} ++ ++static u32 tbs5520_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static struct r848_config r848_config = { ++ .i2c_address = 0x7a, ++ .xtal = 16000000, ++ ++ .R848_DetectTfType = 0, //R848_UL_USING_BEAD, ++ .R848_Xtal_Pwr = 3, //XTAL_SMALL_HIGHEST, ++ .R848_Xtal_Pwr_tmp = 4, //XTAL_LARGE_HIGHEST, ++ ++ /* dvb t/c */ ++ .R848_SetTfType = 1, //R848_TF_BEAD, ++}; ++ ++ ++static struct avl6882_config avl6882_config = { ++ .demod_address = 0x14, ++}; ++ ++static struct i2c_algorithm tbs5520_i2c_algo = { ++ .master_xfer = tbs5520_i2c_transfer, ++ .functionality = tbs5520_i2c_func, ++}; ++ ++static int tbs5520_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ ++ int i,ret; ++ ++ ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++return 0; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbs5520_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, tbs5520_WRITE_MSG); ++ ret = tbs5520_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, tbs5520_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static struct dvb_usb_device_properties tbs5520_properties; ++ ++static int tbs5520_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ u8 buf[2]; ++ ++ d->fe_adap->fe = dvb_attach(avl6882_attach, &avl6882_config, ++ &d->dev->i2c_adap); ++ if (d->fe_adap->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(r848_attach, d->fe_adap->fe, &r848_config, ++ &d->dev->i2c_adap) == NULL) { ++ dvb_frontend_detach(d->fe_adap->fe); ++ d->fe_adap->fe = NULL; ++ printk("TBS5520: tuner attach failed\n"); ++ goto err; ++ } ++ ++ info("TBS5520: frontend attached\n"); ++ buf[0] = 7; ++ buf[1] = 1; ++ tbs5520_op_rw(d->dev->udev, 0x8a, 0, 0, ++ buf, 2, tbs5520_WRITE_MSG); ++ ++ buf[0] = 6; ++ buf[1] = 1; ++ tbs5520_op_rw(d->dev->udev, 0x8a, 0, 0, ++ buf, 2, tbs5520_WRITE_MSG); ++ ++ return 0; ++err: ++ printk("TBS5520: frontend attach failed\n"); ++ return -ENODEV; ++} ++ ++static struct rc_map_table tbs5520_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++static int tbs5520_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbs5520_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = tbs5520_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbs5520_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbs5520_table[] = { ++ {USB_DEVICE(0x734c, 0x5520)}, ++ {USB_DEVICE(0x734c, 0x5922)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbs5520_table); ++ ++static int tbs5520_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ const char *filename = "dvb-usb-tbs5520-01.fw"; ++ switch (dev->descriptor.idProduct) { ++ case 0xdc02: ++ ret = request_firmware(&fw, filename, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", filename); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading tbs5520 firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbs5520_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, tbs5520_WRITE_MSG); ++ tbs5520_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, tbs5520_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbs5520_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ tbs5520_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret |= tbs5520_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ tbs5520_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret |= tbs5520_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ tbs5520_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ info("end downloading tbs5520 firmware"); ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbs5520_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbs5520-01.fw", ++ .download_firmware = tbs5520_load_firmware, ++ .size_of_priv = sizeof(struct tbs5520_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbs5520_i2c_algo, ++ ++ .rc.legacy = { ++ .rc_map_table = tbs5520_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbs5520_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbs5520_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ ++ .read_mac_address = tbs5520_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbs5520_frontend_attach, ++ .streaming_ctrl = NULL, ++ .tuner_attach = NULL, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ }}, ++ }}, ++ .num_device_descs = 1, ++ .devices = { ++ {"TBS 5520 USB2.0", {&tbs5520_table[0], NULL}, {NULL}, }, ++ } ++}; ++ ++ ++static int tbs5520_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbs5520_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbs5520_driver = { ++ .name = "tbs5520", ++ .probe = tbs5520_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbs5520_table, ++}; ++ ++static int __init tbs5520_module_init(void) ++{ ++ int ret = usb_register(&tbs5520_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbs5520_module_exit(void) ++{ ++ usb_deregister(&tbs5520_driver); ++} ++ ++module_init(tbs5520_module_init); ++module_exit(tbs5520_module_exit); ++ ++MODULE_AUTHOR("Konstantin Dimitrov "); ++MODULE_DESCRIPTION("TurboSight TBS 5520 driver"); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs5520.h b/drivers/media/usb/dvb-usb/tbs5520.h +new file mode 100644 +index 0000000..20796a7 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5520.h +@@ -0,0 +1,8 @@ ++#ifndef _TBS5520_H_ ++#define _TBS5520_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbs5520" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbs5520_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs5880.c b/drivers/media/usb/dvb-usb/tbs5880.c +new file mode 100644 +index 0000000..880f53a +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5880.c +@@ -0,0 +1,835 @@ ++/* ++ * TurboSight TBS 5880 CI driver ++ * ++ * Copyright (c) 2011 Konstantin Dimitrov ++ * ++ * 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, version 2. ++ * ++ */ ++ ++#include ++#include "tbs5880.h" ++#include "tda18212.h" ++#include "cxd2820r.h" ++ ++#include "dvb_ca_en50221.h" ++ ++#define TBS5880_READ_MSG 0 ++#define TBS5880_WRITE_MSG 1 ++ ++#define TBS5880_RC_QUERY (0x1a00) ++#define TBS5880_LED_CTRL (0x1b00) ++ ++struct tbs5880_state { ++ struct dvb_ca_en50221 ca; ++ struct mutex ca_mutex; ++ ++ u32 last_key_pressed; ++ ++ struct i2c_client *i2c_client_tuner; ++}; ++ ++/*struct tbs5880_rc_keys { ++ u32 keycode; ++ u32 event; ++};*/ ++ ++/* debug */ ++static int dvb_usb_tbs5880_debug; ++module_param_named(debug, dvb_usb_tbs5880_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbs5880_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBS5880_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBS5880_READ_MSG) ? USB_DIR_IN : ++ USB_DIR_OUT; ++ ++ if (flags == TBS5880_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | ++ USB_TYPE_VENDOR, value, index , u8buf, len, 2000); ++ ++ if (flags == TBS5880_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++static int tbs5880_read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ u8 buf[4], rbuf[3]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ ++ //msleep(10); ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa4, 0, 0, ++ buf, 4, TBS5880_WRITE_MSG); ++ ++ //msleep(1); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa5, 0, 0, ++ rbuf, 1, TBS5880_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return rbuf[0]; ++} ++ ++static int tbs5880_write_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address, u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ u8 buf[5];//, rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ buf[4] = value; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa2, 0, 0, ++ buf, 5, TBS5880_WRITE_MSG); ++ ++ //msleep(1); ++ ++ //ret = tbs5880_op_rw(d->udev, 0xa5, 0, 0, ++ // rbuf, 1, TBS5880_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbs5880_read_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ u8 buf[4], rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa4, 0, 0, ++ buf, 4, TBS5880_WRITE_MSG); ++ ++ //msleep(10); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa5, 0, 0, ++ rbuf, 1, TBS5880_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return rbuf[0]; ++} ++ ++static int tbs5880_write_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ u8 buf[5];//, rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ buf[4] = value; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa2, 0, 0, ++ buf, 5, TBS5880_WRITE_MSG); ++ ++ //msleep(1); ++ ++ //ret = tbs5880_op_rw(d->udev, 0xa5, 0, 0, ++ // rbuf, 1, TBS5880_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbs5880_set_video_port(struct dvb_ca_en50221 *ca, ++ int slot, int enable) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ u8 buf[2]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 2; ++ buf[1] = enable; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBS5880_WRITE_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ if (enable != buf[1]) { ++ err("CI not %sabled.", enable ? "en" : "dis"); ++ return -EIO; ++ } ++ ++ info("CI %sabled.", enable ? "en" : "dis"); ++ return 0; ++} ++ ++static int tbs5880_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbs5880_set_video_port(ca, slot, /* enable */ 0); ++} ++ ++static int tbs5880_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbs5880_set_video_port(ca, slot, /* enable */ 1); ++} ++ ++static int tbs5880_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ u8 buf[2]; ++ int ret; ++ ++ if (0 != slot) { ++ return -EINVAL; ++ } ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ ++ mutex_lock (&state->ca_mutex); ++ ++ ret = tbs5880_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBS5880_WRITE_MSG); ++ ++ msleep (5); ++ ++ buf[1] = 1; ++ ++ ret = tbs5880_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBS5880_WRITE_MSG); ++ ++ msleep (1400); ++ ++ mutex_unlock (&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbs5880_poll_slot_status(struct dvb_ca_en50221 *ca, ++ int slot, int open) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ u8 buf[3]; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ tbs5880_op_rw(d->udev, 0xa8, 0, 0, ++ buf, 3, TBS5880_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if ((1 == buf[2]) && (1 == buf[1]) && (0xa9 == buf[0])) { ++ return (DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY); ++ } else { ++ return 0; ++ } ++} ++ ++static void tbs5880_uninit(struct dvb_usb_device *d) ++{ ++ struct tbs5880_state *state; ++ struct i2c_client *client; ++ ++ if (NULL == d) ++ return; ++ ++ state = (struct tbs5880_state *)d->priv; ++ if (NULL == state) ++ return; ++ ++ if (NULL == state->ca.data) ++ return; ++ ++ /* remove I2C tuner */ ++ client = state->i2c_client_tuner; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ ++ /* Error ignored. */ ++ tbs5880_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); ++ ++ dvb_ca_en50221_release(&state->ca); ++ ++ memset(&state->ca, 0, sizeof(state->ca)); ++} ++ ++static int tbs5880_init(struct dvb_usb_adapter *a) ++{ ++ ++ struct dvb_usb_device *d = a->dev; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ int ret; ++ ++ state->ca.owner = THIS_MODULE; ++ state->ca.read_attribute_mem = tbs5880_read_attribute_mem; ++ state->ca.write_attribute_mem = tbs5880_write_attribute_mem; ++ state->ca.read_cam_control = tbs5880_read_cam_control; ++ state->ca.write_cam_control = tbs5880_write_cam_control; ++ state->ca.slot_reset = tbs5880_slot_reset; ++ state->ca.slot_shutdown = tbs5880_slot_shutdown; ++ state->ca.slot_ts_enable = tbs5880_slot_ts_enable; ++ state->ca.poll_slot_status = tbs5880_poll_slot_status; ++ state->ca.data = d; ++ ++ ret = dvb_ca_en50221_init (&a->dvb_adap, &state->ca, ++ /* flags */ 0, /* n_slots */ 1); ++ ++ if (0 != ret) { ++ err ("Cannot initialize CI: Error %d.", ret); ++ memset (&state->ca, 0, sizeof (state->ca)); ++ return ret; ++ } ++ ++ info ("CI initialized."); ++ ++ ret = tbs5880_poll_slot_status(&state->ca, 0, 0); ++ if (0 == ret) ++ tbs5880_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); ++ ++ return 0; ++} ++ ++/* I2C */ ++static int tbs5880_i2c_transfer(struct i2c_adapter *adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ int i = 0; ++ u8 buf6[20]; ++ u8 inbuf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ //register ++ buf6[2] = msg[0].buf[0]; ++ ++ tbs5880_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBS5880_WRITE_MSG); ++ //msleep(5); ++ tbs5880_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, msg[1].len, TBS5880_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x6c: ++ case 0x6e: ++ case 0x61: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBS5880_WRITE_MSG); ++ } else { ++ buf6[0] = msg[0].len;//length ++ buf6[1] = msg[0].addr<<1;//addr ++ buf6[2] = 0x00; ++ tbs5880_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBS5880_WRITE_MSG); ++ //msleep(5); ++ tbs5880_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBS5880_READ_MSG); ++ memcpy(msg[0].buf, inbuf, msg[0].len); ++ } ++ //msleep(3); ++ break; ++ case (TBS5880_RC_QUERY): ++ tbs5880_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBS5880_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ //msleep(3); ++ //info("TBS5880_RC_QUERY %x %x %x %x\n", ++ // buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ case (TBS5880_LED_CTRL): ++ buf6[0] = 5; ++ buf6[1] = msg[0].buf[0]; ++ tbs5880_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBS5880_WRITE_MSG); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ mutex_unlock(&state->ca_mutex); ++ return num; ++} ++ ++static u32 tbs5880_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm tbs5880_i2c_algo = { ++ .master_xfer = tbs5880_i2c_transfer, ++ .functionality = tbs5880_i2c_func, ++}; ++ ++static int tbs5880_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbs5880_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBS5880_WRITE_MSG); ++ ret = tbs5880_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBS5880_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static void tbs5880_led_ctrl(struct dvb_frontend *fe, int offon) ++{ ++ static u8 led_off[] = { 0 }; ++ static u8 led_on[] = { 1 }; ++ struct i2c_msg msg = { ++ .addr = TBS5880_LED_CTRL, ++ .flags = 0, ++ .buf = led_off, ++ .len = 1 ++ }; ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ ++ if (offon) ++ msg.buf = led_on; ++ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); ++} ++ ++static struct dvb_usb_device_properties tbs5880_properties; ++ ++static struct cxd2820r_config cxd2820r_config = { ++ .i2c_address = 0x6c, /* (0xd8 >> 1) */ ++ .ts_mode = CXD2820R_TS_SERIAL, ++ .set_lock_led = tbs5880_led_ctrl, ++}; ++ ++static struct tda18212_config tda18212_config = { ++ //.i2c_address = 0x60 /* (0xc0 >> 1) */, ++ .if_dvbt_6 = 3550, ++ .if_dvbt_7 = 3700, ++ .if_dvbt_8 = 4150, ++ .if_dvbt2_6 = 3250, ++ .if_dvbt2_7 = 4000, ++ .if_dvbt2_8 = 4000, ++ .if_dvbc = 5000, ++}; ++ ++static int tbs5880_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ struct dvb_usb_device *d = adap->dev; ++ struct tbs5880_state *state = (struct tbs5880_state *)d->priv; ++ ++ struct i2c_adapter *adapter = &d->i2c_adap; ++ struct i2c_client *client; ++ struct i2c_board_info board_info = { ++ .type = "tda18212", ++ .addr = 0x60, ++ .platform_data = &tda18212_config, ++ }; ++ ++ /* attach tuner */ ++ tda18212_config.fe = adap->fe_adap->fe; ++ request_module("tda18212"); ++ client = i2c_new_device(adapter, &board_info); ++ if (client == NULL || client->dev.driver == NULL) { ++ dvb_frontend_detach(adap->fe_adap->fe); ++ goto err; ++ } ++ if (!try_module_get(client->dev.driver->owner)) { ++ i2c_unregister_device(client); ++ dvb_frontend_detach(adap->fe_adap->fe); ++ goto err; ++ } ++ state->i2c_client_tuner = client; ++ ++ return 0; ++ ++err: ++ return -ENODEV; ++} ++ ++static int tbs5880_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ struct tbs5880_state *state = (struct tbs5880_state *)u->priv; ++ u8 buf[20]; ++ ++ mutex_init(&state->ca_mutex); ++ ++ if (tbs5880_properties.adapter->fe->tuner_attach == &tbs5880_tuner_attach) { ++ d->fe_adap->fe = dvb_attach(cxd2820r_attach, &cxd2820r_config, ++ &d->dev->i2c_adap,NULL); ++ ++ if (d->fe_adap->fe != NULL) { ++ buf[0] = 7; ++ buf[1] = 1; ++ tbs5880_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBS5880_WRITE_MSG); ++ ++ tbs5880_init(d); ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ return 0; ++ } ++ } ++ ++ return -EIO; ++} ++ ++static void tbs58802_usb_disconnect (struct usb_interface * intf) ++{ ++ struct dvb_usb_device *d = usb_get_intfdata (intf); ++ ++ tbs5880_uninit (d); ++ dvb_usb_device_exit (intf); ++} ++ ++static struct rc_map_table tbs5880_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++static int tbs5880_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbs5880_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBS5880_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbs5880_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbs5880_table[] = { ++ {USB_DEVICE(0x734c, 0x5880)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbs5880_table); ++ ++static int tbs5880_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5880: ++ ret = request_firmware(&fw, tbs5880_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbs5880_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBS5880 CI firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbs5880_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5880_WRITE_MSG); ++ tbs5880_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5880_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbs5880_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBS5880_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbs5880_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBS5880_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbs5880_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBS5880_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbs5880_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5880.fw", ++ .size_of_priv = sizeof(struct tbs5880_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbs5880_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbs5880_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbs5880_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbs5880_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbs5880_load_firmware, ++ .read_mac_address = tbs5880_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbs5880_frontend_attach, ++ .streaming_ctrl = NULL, ++ .tuner_attach = tbs5880_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } }, ++ ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS 5880 DVB-T/T2/C + CI", ++ {&tbs5880_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbs5880_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbs5880_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbs5880_driver = { ++ .name = "tbs5880", ++ .probe = tbs5880_probe, ++ .disconnect = tbs58802_usb_disconnect, ++ .id_table = tbs5880_table, ++}; ++ ++static int __init tbs5880_module_init(void) ++{ ++ int ret = usb_register(&tbs5880_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbs5880_module_exit(void) ++{ ++ usb_deregister(&tbs5880_driver); ++} ++ ++module_init(tbs5880_module_init); ++module_exit(tbs5880_module_exit); ++ ++MODULE_AUTHOR("Konstantin Dimitrov "); ++MODULE_DESCRIPTION("TurboSight TBS 5880 CI driver"); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs5880.h b/drivers/media/usb/dvb-usb/tbs5880.h +new file mode 100644 +index 0000000..b0f9d9a +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5880.h +@@ -0,0 +1,8 @@ ++#ifndef _TBS5880_H_ ++#define _TBS5880_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbs5880" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbs5880_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs5881.c b/drivers/media/usb/dvb-usb/tbs5881.c +new file mode 100644 +index 0000000..c6d0f47 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5881.c +@@ -0,0 +1,818 @@ ++/* ++ * TurboSight TBS 5881 CI driver ++ * ++ * Copyright (c) 2013 Konstantin Dimitrov ++ * ++ * 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, version 2. ++ * ++ */ ++ ++#include ++#include "tbs5881.h" ++#include "si2168.h" ++#include "si2157.h" ++ ++#include "dvb_ca_en50221.h" ++ ++#define TBS5881_READ_MSG 0 ++#define TBS5881_WRITE_MSG 1 ++ ++#define TBS5881_RC_QUERY (0x1a00) ++ ++struct tbs5881_state { ++ struct i2c_client *i2c_client_demod; ++ struct i2c_client *i2c_client_tuner; ++ struct dvb_ca_en50221 ca; ++ struct mutex ca_mutex; ++ u32 last_key_pressed; ++}; ++ ++/*struct tbs5881_rc_keys { ++ u32 keycode; ++ u32 event; ++};*/ ++ ++/* debug */ ++static int dvb_usb_tbs5881_debug; ++module_param_named(debug, dvb_usb_tbs5881_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbs5881_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBS5881_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBS5881_READ_MSG) ? USB_DIR_IN : ++ USB_DIR_OUT; ++ ++ if (flags == TBS5881_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | ++ USB_TYPE_VENDOR, value, index , u8buf, len, 2000); ++ ++ if (flags == TBS5881_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++static int tbs5881_read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ u8 buf[4], rbuf[3]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ ++ //msleep(10); ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa4, 0, 0, ++ buf, 4, TBS5881_WRITE_MSG); ++ ++ //msleep(1); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa5, 0, 0, ++ rbuf, 1, TBS5881_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return rbuf[0]; ++} ++ ++static int tbs5881_write_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address, u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ u8 buf[5];//, rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ buf[4] = value; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa2, 0, 0, ++ buf, 5, TBS5881_WRITE_MSG); ++ ++ //msleep(1); ++ ++ //ret = tbs5881_op_rw(d->udev, 0xa5, 0, 0, ++ // rbuf, 1, TBS5881_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbs5881_read_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ u8 buf[4], rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa4, 0, 0, ++ buf, 4, TBS5881_WRITE_MSG); ++ ++ //msleep(10); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa5, 0, 0, ++ rbuf, 1, TBS5881_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return rbuf[0]; ++} ++ ++static int tbs5881_write_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ u8 buf[5];//, rbuf[1]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ buf[2] = (address >> 8) & 0x0f; ++ buf[3] = address; ++ buf[4] = value; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa2, 0, 0, ++ buf, 5, TBS5881_WRITE_MSG); ++ ++ //msleep(1); ++ ++ //ret = tbs5881_op_rw(d->udev, 0xa5, 0, 0, ++ // rbuf, 1, TBS5881_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbs5881_set_video_port(struct dvb_ca_en50221 *ca, ++ int slot, int enable) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ u8 buf[2]; ++ int ret; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ buf[0] = 2; ++ buf[1] = enable; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBS5881_WRITE_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ if (enable != buf[1]) { ++ err("CI not %sabled.", enable ? "en" : "dis"); ++ return -EIO; ++ } ++ ++ info("CI %sabled.", enable ? "en" : "dis"); ++ return 0; ++} ++ ++static int tbs5881_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbs5881_set_video_port(ca, slot, /* enable */ 0); ++} ++ ++static int tbs5881_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return tbs5881_set_video_port(ca, slot, /* enable */ 1); ++} ++ ++static int tbs5881_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ u8 buf[2]; ++ int ret; ++ ++ if (0 != slot) { ++ return -EINVAL; ++ } ++ ++ buf[0] = 1; ++ buf[1] = 0; ++ ++ mutex_lock (&state->ca_mutex); ++ ++ ret = tbs5881_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBS5881_WRITE_MSG); ++ ++ msleep (5); ++ ++ buf[1] = 1; ++ ++ ret = tbs5881_op_rw(d->udev, 0xa6, 0, 0, ++ buf, 2, TBS5881_WRITE_MSG); ++ ++ msleep (1400); ++ ++ mutex_unlock (&state->ca_mutex); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int tbs5881_poll_slot_status(struct dvb_ca_en50221 *ca, ++ int slot, int open) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ u8 buf[3]; ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ tbs5881_op_rw(d->udev, 0xa8, 0, 0, ++ buf, 3, TBS5881_READ_MSG); ++ ++ mutex_unlock(&state->ca_mutex); ++ ++ if ((1 == buf[2]) && (1 == buf[1]) && (0xa9 == buf[0])) { ++ return (DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY); ++ } else { ++ return 0; ++ } ++} ++ ++static void tbs5881_uninit(struct dvb_usb_device *d) ++{ ++ struct tbs5881_state *state; ++ ++ if (NULL == d) ++ return; ++ ++ state = (struct tbs5881_state *)d->priv; ++ if (NULL == state) ++ return; ++ ++ if (NULL == state->ca.data) ++ return; ++ ++ /* Error ignored. */ ++ tbs5881_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); ++ ++ dvb_ca_en50221_release(&state->ca); ++ ++ memset(&state->ca, 0, sizeof(state->ca)); ++} ++ ++static int tbs5881_init(struct dvb_usb_adapter *a) ++{ ++ ++ struct dvb_usb_device *d = a->dev; ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ int ret; ++ ++ state->ca.owner = THIS_MODULE; ++ state->ca.read_attribute_mem = tbs5881_read_attribute_mem; ++ state->ca.write_attribute_mem = tbs5881_write_attribute_mem; ++ state->ca.read_cam_control = tbs5881_read_cam_control; ++ state->ca.write_cam_control = tbs5881_write_cam_control; ++ state->ca.slot_reset = tbs5881_slot_reset; ++ state->ca.slot_shutdown = tbs5881_slot_shutdown; ++ state->ca.slot_ts_enable = tbs5881_slot_ts_enable; ++ state->ca.poll_slot_status = tbs5881_poll_slot_status; ++ state->ca.data = d; ++ ++ ret = dvb_ca_en50221_init (&a->dvb_adap, &state->ca, ++ /* flags */ 0, /* n_slots */ 1); ++ ++ if (0 != ret) { ++ err ("Cannot initialize CI: Error %d.", ret); ++ memset (&state->ca, 0, sizeof (state->ca)); ++ return ret; ++ } ++ ++ info ("CI initialized."); ++ ++ ret = tbs5881_poll_slot_status(&state->ca, 0, 0); ++ if (0 == ret) ++ tbs5881_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); ++ ++ return 0; ++} ++ ++/* I2C */ ++static int tbs5881_i2c_transfer(struct i2c_adapter *adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ struct tbs5881_state *state = (struct tbs5881_state *)d->priv; ++ int i = 0; ++ u8 buf6[20]; ++ u8 inbuf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ //register ++ buf6[2] = msg[0].buf[0]; ++ ++ tbs5881_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBS5881_WRITE_MSG); ++ //msleep(5); ++ tbs5881_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, 1, TBS5881_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x64: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBS5881_WRITE_MSG); ++ } else { ++ buf6[0] = msg[0].len;//length ++ buf6[1] = (msg[0].addr<<1) | 0x01;//addr ++ tbs5881_op_rw(d->udev, 0x93, 0, 0, ++ buf6, 2, TBS5881_WRITE_MSG); ++ //msleep(5); ++ tbs5881_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBS5881_READ_MSG); ++ memcpy(msg[0].buf, inbuf, msg[0].len); ++ } ++ //msleep(3); ++ break; ++ case (TBS5881_RC_QUERY): ++ tbs5881_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBS5881_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ //msleep(3); ++ //info("TBS5881_RC_QUERY %x %x %x %x\n", ++ // buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ mutex_unlock(&state->ca_mutex); ++ return num; ++} ++ ++static u32 tbs5881_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm tbs5881_i2c_algo = { ++ .master_xfer = tbs5881_i2c_transfer, ++ .functionality = tbs5881_i2c_func, ++}; ++ ++static int tbs5881_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbs5881_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBS5881_WRITE_MSG); ++ ret = tbs5881_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBS5881_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static struct dvb_usb_device_properties tbs5881_properties; ++ ++static int tbs5881_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ struct dvb_usb_device *d = adap->dev; ++ struct tbs5881_state *st = (struct tbs5881_state *)d->priv; ++ struct i2c_adapter *adapter; ++ struct i2c_client *client_demod; ++ struct i2c_client *client_tuner; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ u8 buf[20]; ++ ++ mutex_init(&st->ca_mutex); ++ ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &adap->fe_adap[0].fe; ++ si2168_config.ts_mode = SI2168_TS_SERIAL; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(&d->i2c_adap, &info); ++ if (client_demod == NULL || client_demod->dev.driver == NULL) ++ return -ENODEV; ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adap->fe_adap[0].fe; ++ si2157_config.if_port = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(adapter, &info); ++ if (client_tuner == NULL || client_tuner->dev.driver == NULL) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ ++ st->i2c_client_demod = client_demod; ++ st->i2c_client_tuner = client_tuner; ++ ++ buf[0] = 0; ++ buf[1] = 0; ++ tbs5881_op_rw(d->udev, 0xb7, 0, 0, ++ buf, 2, TBS5881_WRITE_MSG); ++ ++ buf[0] = 8; ++ buf[1] = 1; ++ tbs5881_op_rw(d->udev, 0x8a, 0, 0, ++ buf, 2, TBS5881_WRITE_MSG); ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbs5881_op_rw(d->udev, 0x8a, 0, 0, ++ buf, 2, TBS5881_WRITE_MSG); ++ ++ buf[0] = 6; ++ buf[1] = 1; ++ tbs5881_op_rw(d->udev, 0x8a, 0, 0, ++ buf, 2, TBS5881_WRITE_MSG); ++ ++ tbs5881_init(adap); ++ strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52); ++ return 0; ++} ++ ++static void tbs5881_usb_disconnect (struct usb_interface * intf) ++{ ++ struct dvb_usb_device *d = usb_get_intfdata (intf); ++#if 0 ++ struct tbs5881_state *st = d->priv; ++ struct i2c_client *client; ++ ++ /* remove I2C client for tuner */ ++ client = st->i2c_client_tuner; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ ++ /* remove I2C client for demodulator */ ++ client = st->i2c_client_demod; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++#endif ++ tbs5881_uninit (d); ++ dvb_usb_device_exit (intf); ++} ++ ++static struct rc_map_table tbs5881_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++static int tbs5881_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbs5881_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBS5881_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbs5881_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbs5881_table[] = { ++ {USB_DEVICE(0x734c, 0x5881)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbs5881_table); ++ ++static int tbs5881_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5881: ++ ret = request_firmware(&fw, tbs5881_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbs5881_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBS5881 CI firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbs5881_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5881_WRITE_MSG); ++ tbs5881_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5881_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbs5881_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBS5881_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbs5881_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBS5881_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbs5881_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBS5881_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbs5881_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5881.fw", ++ .size_of_priv = sizeof(struct tbs5881_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbs5881_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbs5881_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbs5881_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbs5881_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbs5881_load_firmware, ++ .read_mac_address = tbs5881_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbs5881_frontend_attach, ++ .streaming_ctrl = NULL, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ }}, ++ }}, ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS 5881 DVB-T/T2/C + CI", ++ {&tbs5881_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbs5881_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbs5881_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbs5881_driver = { ++ .name = "tbs5881", ++ .probe = tbs5881_probe, ++ .disconnect = tbs5881_usb_disconnect, ++ .id_table = tbs5881_table, ++}; ++ ++static int __init tbs5881_module_init(void) ++{ ++ int ret = usb_register(&tbs5881_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbs5881_module_exit(void) ++{ ++ usb_deregister(&tbs5881_driver); ++} ++ ++module_init(tbs5881_module_init); ++module_exit(tbs5881_module_exit); ++ ++MODULE_AUTHOR("Konstantin Dimitrov "); ++MODULE_DESCRIPTION("TurboSight TBS 5881 CI driver"); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs5881.h b/drivers/media/usb/dvb-usb/tbs5881.h +new file mode 100644 +index 0000000..827073b +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5881.h +@@ -0,0 +1,8 @@ ++#ifndef _TBS5881_H_ ++#define _TBS5881_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbs5881" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbs5881_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs5922se.c b/drivers/media/usb/dvb-usb/tbs5922se.c +new file mode 100644 +index 0000000..5ce8398 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5922se.c +@@ -0,0 +1,463 @@ ++/* DVB USB framework compliant Linux driver for the ++* TBS 5922SE ++* ++* Copyright (C) 2008 Bob Liu (Bob@Turbosight.com) ++* Igor M. Liplianin (liplianin@me.by) ++* ++* 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, version 2. ++* ++* see Documentation/dvb/README.dvb-usb for more information ++*/ ++ ++/* ++* History: ++* ++* December 2011 Konstantin Dimitrov ++* remove QBOXS3 support ++* add QBOX22 support ++*/ ++ ++#include ++#include "tbs5922se.h" ++#include "tas2101.h" ++#include "av201x.h" ++ ++#ifndef USB_PID_TBS5922SE_1 ++#define USB_PID_TBS5922SE_1 0x5923 ++#endif ++ ++#define TBS5922SE_READ_MSG 0 ++#define TBS5922SE_WRITE_MSG 1 ++ ++/* on my own*/ ++#define TBS5922SE_VOLTAGE_CTRL (0x1800) ++#define TBS5922SE_RC_QUERY (0x1a00) ++ ++struct tbs5922se_state { ++ u32 last_key_pressed; ++}; ++struct tbs5922se_rc_keys { ++ u32 keycode; ++ u32 event; ++}; ++ ++/* debug */ ++static int dvb_usb_tbs5922se_debug; ++module_param_named(debug, dvb_usb_tbs5922se_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbs5922se_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBS5922SE_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBS5922SE_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; ++ ++ if (flags == TBS5922SE_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, ++ value, index, u8buf, len, 2000); ++ ++ if (flags == TBS5922SE_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbs5922se_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0; ++ u8 buf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ /* read */ ++ buf[0] = msg[1].len; ++ buf[1] = msg[0].addr << 1; ++ buf[2] = msg[0].buf[0]; ++ ++ tbs5922se_op_rw(d->udev, 0x90, 0, 0, ++ buf, 3, TBS5922SE_WRITE_MSG); ++ msleep(5); ++ tbs5922se_op_rw(d->udev, 0x91, 0, 0, ++ buf, msg[1].len, TBS5922SE_READ_MSG); ++ memcpy(msg[1].buf, buf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x68: ++ case 0x63: ++ /* write to register */ ++ buf[0] = msg[0].len + 1; //lenth ++ buf[1] = msg[0].addr << 1; //demod addr ++ for(i=0; i < msg[0].len; i++) ++ buf[2+i] = msg[0].buf[i]; //register ++ tbs5922se_op_rw(d->udev, 0x80, 0, 0, ++ buf, msg[0].len+2, TBS5922SE_WRITE_MSG); ++ //msleep(3); ++ break; ++ case (TBS5922SE_RC_QUERY): ++ tbs5922se_op_rw(d->udev, 0xb8, 0, 0, ++ buf, 4, TBS5922SE_READ_MSG); ++ msg[0].buf[0] = buf[2]; ++ msg[0].buf[1] = buf[3]; ++ msleep(3); ++ //info("TBS5922SE_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ case (TBS5922SE_VOLTAGE_CTRL): ++ break; ++ default: ++ break; ++ } ++ ++ break; ++ default: ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbs5922se_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++ ++static struct i2c_algorithm tbs5922se_i2c_algo = { ++ .master_xfer = tbs5922se_i2c_transfer, ++ .functionality = tbs5922se_i2c_func, ++}; ++ ++ ++static int tbs5922se_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 buf[3]; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ buf[0] = 1; //lenth ++ buf[1] = 0xa0; //eeprom addr ++ buf[2] = i; //register ++ ret = tbs5922se_op_rw(d->udev, 0x90, 0, 0, ++ buf, 3, TBS5922SE_WRITE_MSG); ++ ret = tbs5922se_op_rw(d->udev, 0x91, 0, 0, ++ buf, 1, TBS5922SE_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed"); ++ return -1; ++ } else { ++ eepromline[i % 16] = buf[0]; ++ eeprom[i] = buf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static struct dvb_usb_device_properties tbs5922se_properties; ++ ++ ++static struct tas2101_config tbs5922_cfg = { ++ .i2c_address = 0x68, ++ .id = ID_TAS2101, ++ .reset_demod = NULL, ++ .lnb_power = NULL, ++ .init = {0x67, 0x45, 0xba, 0x23, 0x01, 0x98, 0x33}, ++ .init2 = 1, ++}; ++ ++static struct av201x_config tbs5922_av201x_cfg = { ++ .i2c_address = 0x63, ++ .id = ID_AV2012, ++ .xtal_freq = 27000, /* kHz */ ++}; ++ ++static int tbs5922se_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ u8 buf[20]; ++ ++ d->fe_adap->fe = dvb_attach(tas2101_attach, &tbs5922_cfg, ++ &u->i2c_adap); ++ if (d->fe_adap->fe == NULL) ++ goto err; ++ ++ if (dvb_attach(av201x_attach, d->fe_adap->fe, &tbs5922_av201x_cfg, ++ tas2101_get_i2c_adapter(d->fe_adap->fe, 2)) == NULL) { ++ dvb_frontend_detach(d->fe_adap->fe); ++ d->fe_adap->fe = NULL; ++ goto err; ++ } ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbs5922se_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBS5922SE_WRITE_MSG); ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ tbs5922se_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBS5922SE_WRITE_MSG); ++ ++ buf[0] = 6; ++ buf[1] = 1; ++ tbs5922se_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBS5922SE_WRITE_MSG); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ ++ return 0; ++err: ++ return -ENODEV; ++} ++ ++ ++ ++static struct rc_map_table tbs5922se_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++ ++ ++static int tbs5922se_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbs5922se_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBS5922SE_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbs5922se_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbs5922se_table[] = { ++ {USB_DEVICE(0x734c, 0x5923)}, ++ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_TBS5922SE_1)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbs5922se_table); ++ ++static int tbs5922se_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ const char *filename = "dvb-usb-tbsqbox-id5923.fw"; ++ switch (dev->descriptor.idProduct) { ++ case 0x5923: ++ ret = request_firmware(&fw, filename, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", filename); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBS5922SE firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbs5922se_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5922SE_WRITE_MSG); ++ tbs5922se_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5922SE_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbs5922se_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBS5922SE_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbs5922se_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBS5922SE_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbs5922se_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBS5922SE_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbs5922se_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5923.fw", ++ .size_of_priv = sizeof(struct tbs5922se_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbs5922se_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbs5922se_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbs5922se_rc_keys), ++ .rc_interval = 150, ++ .rc_query = tbs5922se_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbs5922se_load_firmware, ++ .read_mac_address = tbs5922se_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbs5922se_frontend_attach, ++ .streaming_ctrl = NULL, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ }}, ++ }}, ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS 5922SE DVB-S/S2", ++ {&tbs5922se_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbs5922se_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbs5922se_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbs5922se_driver = { ++ .name = "tbs5922se", ++ .probe = tbs5922se_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbs5922se_table, ++}; ++ ++static int __init tbs5922se_module_init(void) ++{ ++ int ret = usb_register(&tbs5922se_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbs5922se_module_exit(void) ++{ ++ usb_deregister(&tbs5922se_driver); ++} ++ ++module_init(tbs5922se_module_init); ++module_exit(tbs5922se_module_exit); ++ ++MODULE_AUTHOR("Bob Liu "); ++MODULE_DESCRIPTION("Driver for TBS 5922SE"); ++MODULE_VERSION("0.1"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs5922se.h b/drivers/media/usb/dvb-usb/tbs5922se.h +new file mode 100644 +index 0000000..36f02b7 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5922se.h +@@ -0,0 +1,8 @@ ++#ifndef _TBS5922SE_H_ ++#define _TBS5922SE_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbs5922se" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbs5922se_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs5925.c b/drivers/media/usb/dvb-usb/tbs5925.c +new file mode 100644 +index 0000000..47e8bf2 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5925.c +@@ -0,0 +1,523 @@ ++/* ++ * TurboSight TBS 5925 DVB-S2 driver ++ * ++ * Copyright (c) 2012 Konstantin Dimitrov ++ * ++ * 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, version 2. ++ * ++ */ ++ ++#include ++#include "tbs5925.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "stb6100.h" ++#include "stb6100_cfg.h" ++ ++#define TBS5925_READ_MSG 0 ++#define TBS5925_WRITE_MSG 1 ++#define TBS5925_LED_CTRL (0x1b00) ++ ++/* on my own*/ ++#define TBS5925_RC_QUERY (0x1a00) ++#define TBS5925_VOLTAGE_CTRL (0x1800) ++ ++struct tbs5925_state { ++ u32 last_key_pressed; ++}; ++ ++/* struct tbs5925_rc_keys { ++ u32 keycode; ++ u32 event; ++}; */ ++ ++/* debug */ ++static int dvb_usb_tbs5925_debug; ++module_param_named(debug, dvb_usb_tbs5925_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbs5925_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBS5925_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBS5925_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; ++ ++ if (flags == TBS5925_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, ++ value, index , u8buf, len, 2000); ++ ++ if (flags == TBS5925_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbs5925_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0; ++ u8 buf6[20]; ++ u8 inbuf[20]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ //register ++ buf6[2] = msg[0].buf[0]; ++ buf6[3] = msg[0].buf[1]; ++ ++ tbs5925_op_rw(d->udev, 0x92, 0, 0, ++ buf6, 4, TBS5925_WRITE_MSG); ++ //msleep(5); ++ tbs5925_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, msg[1].len, TBS5925_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x68: ++ case 0x61: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBS5925_WRITE_MSG); ++ } else { ++ buf6[0] = msg[0].len;//length ++ buf6[1] = msg[0].addr<<1;//addr ++ buf6[2] = 0x00; ++ tbs5925_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBS5925_WRITE_MSG); ++ //msleep(5); ++ tbs5925_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBS5925_READ_MSG); ++ memcpy(msg[0].buf, inbuf, msg[0].len); ++ } ++ //msleep(3); ++ break; ++ case (TBS5925_RC_QUERY): ++ tbs5925_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBS5925_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ msleep(3); ++ //info("TBS5925_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]); ++ break; ++ case (TBS5925_VOLTAGE_CTRL): ++ buf6[0] = 3; ++ buf6[1] = msg[0].buf[0]; ++ tbs5925_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBS5925_WRITE_MSG); ++ break; ++ case (TBS5925_LED_CTRL): ++ buf6[0] = 5; ++ buf6[1] = msg[0].buf[0]; ++ tbs5925_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBS5925_WRITE_MSG); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbs5925_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static void tbs5925_led_ctrl(struct dvb_frontend *fe, int offon) ++{ ++ static u8 led_off[] = { 0 }; ++ static u8 led_on[] = { 1 }; ++ struct i2c_msg msg = { ++ .addr = TBS5925_LED_CTRL, ++ .flags = 0, ++ .buf = led_off, ++ .len = 1 ++ }; ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ ++ if (offon) ++ msg.buf = led_on; ++ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); ++} ++ ++static struct stv090x_config stv0900_config = { ++ .device = STV0900, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 27000000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_DVBCI, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_get_frequency = stb6100_get_frequency, ++ .tuner_set_frequency = stb6100_set_frequency, ++ .tuner_set_bandwidth = stb6100_set_bandwidth, ++ .tuner_get_bandwidth = stb6100_get_bandwidth, ++ ++ .set_lock_led = tbs5925_led_ctrl, ++}; ++ ++static struct stb6100_config stb6100_config = { ++ .tuner_address = 0x60, ++ .refclock = 27000000, ++}; ++ ++static struct i2c_algorithm tbs5925_i2c_algo = { ++ .master_xfer = tbs5925_i2c_transfer, ++ .functionality = tbs5925_i2c_func, ++}; ++ ++static int tbs5925_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ if (!dvb_attach(stb6100_attach, adap->fe_adap->fe, &stb6100_config, ++ &adap->dev->i2c_adap)) ++ return -EIO; ++ ++ return 0; ++} ++static int tbs5925_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbs5925_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBS5925_WRITE_MSG); ++ ret = tbs5925_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBS5925_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static int tbs5925_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ static u8 command_13v[1] = {0x00}; ++ static u8 command_18v[1] = {0x01}; ++ struct i2c_msg msg[] = { ++ {.addr = TBS5925_VOLTAGE_CTRL, .flags = 0, ++ .buf = command_13v, .len = 1}, ++ }; ++ ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ if (voltage == SEC_VOLTAGE_18) ++ msg[0].buf = command_18v; ++ //info("tbs5925_set_voltage %d",voltage); ++ i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); ++ return 0; ++} ++ ++static struct dvb_usb_device_properties tbs5925_properties; ++ ++static int tbs5925_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ u8 buf[20]; ++ ++ if (tbs5925_properties.adapter->fe->tuner_attach == &tbs5925_tuner_attach) { ++ d->fe_adap->fe = dvb_attach(stv090x_attach, &stv0900_config, ++ &u->i2c_adap, STV090x_DEMODULATOR_0); ++ if (d->fe_adap->fe != NULL) { ++ d->fe_adap->fe->ops.set_voltage = tbs5925_set_voltage; ++ ++ buf[0] = 6; ++ buf[1] = 1; ++ tbs5925_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBS5925_WRITE_MSG); ++ ++ buf[0] = 1; ++ buf[1] = 1; ++ tbs5925_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBS5925_WRITE_MSG); ++ ++ buf[0] = 7; ++ buf[1] = 1; ++ tbs5925_op_rw(u->udev, 0x8a, 0, 0, ++ buf, 2, TBS5925_WRITE_MSG); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ ++ return 0; ++ } ++ } ++ ++ return -EIO; ++} ++ ++static struct rc_map_table tbs5925_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++static int tbs5925_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbs5925_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBS5925_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbs5925_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbs5925_table[] = { ++ {USB_DEVICE(0x734c, 0x5925)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbs5925_table); ++ ++static int tbs5925_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5925: ++ ret = request_firmware(&fw, tbs5925_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbs5925_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBS5925 firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbs5925_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5925_WRITE_MSG); ++ tbs5925_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5925_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbs5925_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBS5925_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbs5925_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBS5925_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbs5925_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBS5925_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbs5925_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5925.fw", ++ .size_of_priv = sizeof(struct tbs5925_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbs5925_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbs5925_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbs5925_rc_keys), ++ .rc_interval = 250, ++ .rc_query = tbs5925_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbs5925_load_firmware, ++ .read_mac_address = tbs5925_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbs5925_frontend_attach, ++ .streaming_ctrl = NULL, ++ .tuner_attach = tbs5925_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } }, ++ ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS 5925 DVB-S/S2", ++ {&tbs5925_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbs5925_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbs5925_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbs5925_driver = { ++ .name = "tbs5925", ++ .probe = tbs5925_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbs5925_table, ++}; ++ ++static int __init tbs5925_module_init(void) ++{ ++ int ret = usb_register(&tbs5925_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbs5925_module_exit(void) ++{ ++ usb_deregister(&tbs5925_driver); ++} ++ ++module_init(tbs5925_module_init); ++module_exit(tbs5925_module_exit); ++ ++MODULE_AUTHOR("Konstantin Dimitrov "); ++MODULE_DESCRIPTION("TurboSight TBS 5925 DVB-S2 driver"); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs5925.h b/drivers/media/usb/dvb-usb/tbs5925.h +new file mode 100644 +index 0000000..83278f5 +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5925.h +@@ -0,0 +1,8 @@ ++#ifndef _TBS5925_H_ ++#define _TBS5925_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbs5925" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbs5925_debug, 0x02, args) ++#endif +diff --git a/drivers/media/usb/dvb-usb/tbs5927.c b/drivers/media/usb/dvb-usb/tbs5927.c +new file mode 100644 +index 0000000..672234d +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5927.c +@@ -0,0 +1,529 @@ ++/* ++ * TurboSight TBS 5927 DVB-S2 driver ++ * ++ * Copyright (c) 2016 TBSDTV ++ * ++ * 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, version 2. ++ * ++ */ ++ ++#include ++#include "tbs5927.h" ++#include "stv6120.h" ++#include "stv0910.h" ++ ++#define TBS5927_READ_MSG 0 ++#define TBS5927_WRITE_MSG 1 ++#define TBS5927_LED_CTRL (0x1b00) ++ ++/* on my own*/ ++#define TBS5927_RC_QUERY (0x1a00) ++#define TBS5927_VOLTAGE_CTRL (0x1800) ++ ++struct tbs5927_state { ++ u32 last_key_pressed; ++}; ++ ++/* struct tbs5927_rc_keys { ++ u32 keycode; ++ u32 event; ++}; */ ++ ++/* debug */ ++static int dvb_usb_tbs5927_debug; ++module_param_named(debug, dvb_usb_tbs5927_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int tbs5927_op_rw(struct usb_device *dev, u8 request, u16 value, ++ u16 index, u8 * data, u16 len, int flags) ++{ ++ int ret; ++ u8 u8buf[len]; ++ ++ unsigned int pipe = (flags == TBS5927_READ_MSG) ? ++ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); ++ u8 request_type = (flags == TBS5927_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; ++ ++ if (flags == TBS5927_WRITE_MSG) ++ memcpy(u8buf, data, len); ++ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, ++ value, index , u8buf, len, 2000); ++ ++ if (flags == TBS5927_READ_MSG) ++ memcpy(data, u8buf, len); ++ return ret; ++} ++ ++/* I2C */ ++static int tbs5927_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int i = 0; ++ u8 buf6[32]; ++ u8 inbuf[32]; ++ ++ if (!d) ++ return -ENODEV; ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ switch (num) { ++ case 2: ++ buf6[0]=msg[1].len;//lenth ++ buf6[1]=msg[0].addr<<1;//demod addr ++ //register ++ memcpy(buf6+2,msg[0].buf,msg[0].len); ++ ++ tbs5927_op_rw(d->udev, msg[0].addr < 0x68 ? 0x90 : 0x92, 0, 0, ++ buf6, msg[0].len+2, TBS5927_WRITE_MSG); ++ //msleep(5); ++ tbs5927_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, msg[1].len, TBS5927_READ_MSG); ++ memcpy(msg[1].buf, inbuf, msg[1].len); ++ break; ++ case 1: ++ switch (msg[0].addr) { ++ case 0x68: ++ case 0x61: ++ case 0x60: ++ if (msg[0].flags == 0) { ++ buf6[0] = msg[0].len+1;//lenth ++ buf6[1] = msg[0].addr<<1;//addr ++ for(i=0;iudev, 0x80, 0, 0, ++ buf6, msg[0].len+2, TBS5927_WRITE_MSG); ++ } else { ++ buf6[0] = msg[0].len;//length ++ buf6[1] = msg[0].addr<<1;//addr ++ buf6[2] = 0x00; ++ tbs5927_op_rw(d->udev, 0x90, 0, 0, ++ buf6, 3, TBS5927_WRITE_MSG); ++ //msleep(5); ++ tbs5927_op_rw(d->udev, 0x91, 0, 0, ++ inbuf, buf6[0], TBS5927_READ_MSG); ++ memcpy(msg[0].buf, inbuf, msg[0].len); ++ } ++ //msleep(3); ++ break; ++ case (TBS5927_RC_QUERY): ++ tbs5927_op_rw(d->udev, 0xb8, 0, 0, ++ buf6, 4, TBS5927_READ_MSG); ++ msg[0].buf[0] = buf6[2]; ++ msg[0].buf[1] = buf6[3]; ++ msleep(3); ++ /* info("TBS5927_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]); */ ++ break; ++ case (TBS5927_VOLTAGE_CTRL): ++ buf6[0] = 1; ++ buf6[1] = msg[0].buf[0] < 2; ++ tbs5927_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBS5927_WRITE_MSG); ++ msleep(5); ++ if (msg[0].buf[0] < 2) { ++ buf6[0] = 3; ++ buf6[1] = msg[0].buf[0]; ++ tbs5927_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBS5927_WRITE_MSG); ++ } ++ break; ++ case (TBS5927_LED_CTRL): ++ buf6[0] = 5; ++ buf6[1] = msg[0].buf[0]; ++ tbs5927_op_rw(d->udev, 0x8a, 0, 0, ++ buf6, 2, TBS5927_WRITE_MSG); ++ break; ++ } ++ ++ break; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ return num; ++} ++ ++static u32 tbs5927_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static void tbs5927_led_ctrl(struct dvb_frontend *fe, int offon) ++{ ++ static u8 led_off[] = { 0 }; ++ static u8 led_on[] = { 1 }; ++ struct i2c_msg msg = { ++ .addr = TBS5927_LED_CTRL, ++ .flags = 0, ++ .buf = led_off, ++ .len = 1 ++ }; ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ ++ if (offon) ++ msg.buf = led_on; ++ ++ /* info("tbs5927_led_ctrl %d", msg.buf[0]); */ ++ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); ++} ++ ++static struct stv0910_cfg tbs5927_stv0910_cfg = { ++ .adr = 0x68, ++ .parallel = 1, ++ .rptlvl = 3, ++ .clk = 30000000, ++ .dual_tuner = 1, ++ .set_lock_led = tbs5927_led_ctrl, ++}; ++ ++static struct stv6120_cfg tbs5927_stv6120_cfg = { ++ .adr = 0x60, ++ .xtal = 30000, ++ .Rdiv = 2, ++}; ++ ++static struct i2c_algorithm tbs5927_i2c_algo = { ++ .master_xfer = tbs5927_i2c_transfer, ++ .functionality = tbs5927_i2c_func, ++}; ++ ++static int tbs5927_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int i,ret; ++ u8 ibuf[3] = {0, 0,0}; ++ u8 eeprom[256], eepromline[16]; ++ ++ for (i = 0; i < 256; i++) { ++ ibuf[0]=1;//lenth ++ ibuf[1]=0xa0;//eeprom addr ++ ibuf[2]=i;//register ++ ret = tbs5927_op_rw(d->udev, 0x90, 0, 0, ++ ibuf, 3, TBS5927_WRITE_MSG); ++ ret = tbs5927_op_rw(d->udev, 0x91, 0, 0, ++ ibuf, 1, TBS5927_READ_MSG); ++ if (ret < 0) { ++ err("read eeprom failed."); ++ return -1; ++ } else { ++ eepromline[i%16] = ibuf[0]; ++ eeprom[i] = ibuf[0]; ++ } ++ ++ if ((i % 16) == 15) { ++ deb_xfer("%02x: ", i - 15); ++ debug_dump(eepromline, 16, deb_xfer); ++ } ++ } ++ memcpy(mac, eeprom + 16, 6); ++ return 0; ++}; ++ ++static int tbs5927_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ static u8 cmd[1] = {0x00}; ++ ++ struct i2c_msg msg[] = { ++ {.addr = TBS5927_VOLTAGE_CTRL, .flags = 0, ++ .buf = cmd, .len = 1}, ++ }; ++ ++ struct dvb_usb_adapter *udev_adap = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cmd[0] = 0; ++ break; ++ case SEC_VOLTAGE_18: ++ cmd[0] = 1; ++ break; ++ case SEC_VOLTAGE_OFF: ++ cmd[0] = 2; ++ break; ++ } ++ ++ /*info("tbs5927_set_voltage %d", voltage);*/ ++ i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); ++ return 0; ++} ++ ++static int tbs5927_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ if (!dvb_attach(stv6120_attach, adap->fe_adap->fe, ++ &adap->dev->i2c_adap, &tbs5927_stv6120_cfg, 0)) ++ return -EIO; ++ ++ return 0; ++} ++ ++static struct dvb_usb_device_properties tbs5927_properties; ++ ++static int tbs5927_frontend_attach(struct dvb_usb_adapter *d) ++{ ++ struct dvb_usb_device *u = d->dev; ++ u8 buf[20]; ++ ++ buf[0] = 6; /* I2C speed */ ++ buf[1] = 0; /* 100KHz */ ++ tbs5927_op_rw(d->dev->udev, 0x8a, 0, 0, ++ buf, 2, TBS5927_WRITE_MSG); ++ ++ if (tbs5927_properties.adapter->fe->tuner_attach == &tbs5927_tuner_attach) { ++ d->fe_adap->fe = dvb_attach(stv0910_attach, &d->dev->i2c_adap, ++ &tbs5927_stv0910_cfg, 1 ); ++ if (d->fe_adap->fe != NULL) { ++ d->fe_adap->fe->ops.set_voltage = tbs5927_set_voltage; ++ ++ buf[0] = 1; /* LNB power disable */ ++ buf[1] = 0; ++ tbs5927_op_rw(d->dev->udev, 0x8a, 0, 0, ++ buf, 2, TBS5927_WRITE_MSG); ++ ++ buf[0] = 7; /* IR RC enable */ ++ buf[1] = 1; ++ tbs5927_op_rw(d->dev->udev, 0x8a, 0, 0, ++ buf, 2, TBS5927_WRITE_MSG); ++ ++ strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52); ++ ++ return 0; ++ } ++ } ++ ++ return -EIO; ++} ++ ++static struct rc_map_table tbs5927_rc_keys[] = { ++ { 0xff84, KEY_POWER2}, /* power */ ++ { 0xff94, KEY_MUTE}, /* mute */ ++ { 0xff87, KEY_1}, ++ { 0xff86, KEY_2}, ++ { 0xff85, KEY_3}, ++ { 0xff8b, KEY_4}, ++ { 0xff8a, KEY_5}, ++ { 0xff89, KEY_6}, ++ { 0xff8f, KEY_7}, ++ { 0xff8e, KEY_8}, ++ { 0xff8d, KEY_9}, ++ { 0xff92, KEY_0}, ++ { 0xff96, KEY_CHANNELUP}, /* ch+ */ ++ { 0xff91, KEY_CHANNELDOWN}, /* ch- */ ++ { 0xff93, KEY_VOLUMEUP}, /* vol+ */ ++ { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */ ++ { 0xff83, KEY_RECORD}, /* rec */ ++ { 0xff98, KEY_PAUSE}, /* pause, yellow */ ++ { 0xff99, KEY_OK}, /* ok */ ++ { 0xff9a, KEY_CAMERA}, /* snapshot */ ++ { 0xff81, KEY_UP}, ++ { 0xff90, KEY_LEFT}, ++ { 0xff82, KEY_RIGHT}, ++ { 0xff88, KEY_DOWN}, ++ { 0xff95, KEY_FAVORITES}, /* blue */ ++ { 0xff97, KEY_SUBTITLE}, /* green */ ++ { 0xff9d, KEY_ZOOM}, ++ { 0xff9f, KEY_EXIT}, ++ { 0xff9e, KEY_MENU}, ++ { 0xff9c, KEY_EPG}, ++ { 0xff80, KEY_PREVIOUS}, /* red */ ++ { 0xff9b, KEY_MODE}, ++ { 0xffdd, KEY_TV }, ++ { 0xffde, KEY_PLAY }, ++ { 0xffdc, KEY_STOP }, ++ { 0xffdb, KEY_REWIND }, ++ { 0xffda, KEY_FASTFORWARD }, ++ { 0xffd9, KEY_PREVIOUS }, /* replay */ ++ { 0xffd8, KEY_NEXT }, /* skip */ ++ { 0xffd1, KEY_NUMERIC_STAR }, ++ { 0xffd2, KEY_NUMERIC_POUND }, ++ { 0xffd4, KEY_DELETE }, /* clear */ ++}; ++ ++static int tbs5927_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ++{ ++ struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; ++ int keymap_size = d->props.rc.legacy.rc_map_size; ++ ++ struct tbs5927_state *st = d->priv; ++ u8 key[2]; ++ struct i2c_msg msg[] = { ++ {.addr = TBS5927_RC_QUERY, .flags = I2C_M_RD, .buf = key, ++ .len = 2}, ++ }; ++ int i; ++ ++ *state = REMOTE_NO_KEY_PRESSED; ++ if (tbs5927_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { ++ //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]); ++ for (i = 0; i < keymap_size; i++) { ++ if (rc5_data(&keymap[i]) == msg[0].buf[1]) { ++ *state = REMOTE_KEY_PRESSED; ++ *event = keymap[i].keycode; ++ st->last_key_pressed = ++ keymap[i].keycode; ++ break; ++ } ++ st->last_key_pressed = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_id tbs5927_table[] = { ++ {USB_DEVICE(0x734c, 0x5927)}, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(usb, tbs5927_table); ++ ++static int tbs5927_load_firmware(struct usb_device *dev, ++ const struct firmware *frmwr) ++{ ++ u8 *b, *p; ++ int ret = 0, i; ++ u8 reset; ++ const struct firmware *fw; ++ switch (dev->descriptor.idProduct) { ++ case 0x5927: ++ ret = request_firmware(&fw, tbs5927_properties.firmware, &dev->dev); ++ if (ret != 0) { ++ err("did not find the firmware file. (%s) " ++ "Please see linux/Documentation/dvb/ for more details " ++ "on firmware-problems.", tbs5927_properties.firmware); ++ return ret; ++ } ++ break; ++ default: ++ fw = frmwr; ++ break; ++ } ++ info("start downloading TBS5927 firmware"); ++ p = kmalloc(fw->size, GFP_KERNEL); ++ reset = 1; ++ /*stop the CPU*/ ++ tbs5927_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5927_WRITE_MSG); ++ tbs5927_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5927_WRITE_MSG); ++ ++ if (p != NULL) { ++ memcpy(p, fw->data, fw->size); ++ for (i = 0; i < fw->size; i += 0x40) { ++ b = (u8 *) p + i; ++ if (tbs5927_op_rw(dev, 0xa0, i, 0, b , 0x40, ++ TBS5927_WRITE_MSG) != 0x40) { ++ err("error while transferring firmware"); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ /* restart the CPU */ ++ reset = 0; ++ if (ret || tbs5927_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, ++ TBS5927_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ if (ret || tbs5927_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, ++ TBS5927_WRITE_MSG) != 1) { ++ err("could not restart the USB controller CPU."); ++ ret = -EINVAL; ++ } ++ ++ msleep(100); ++ kfree(p); ++ } ++ return ret; ++} ++ ++static struct dvb_usb_device_properties tbs5927_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .firmware = "dvb-usb-tbsqbox-id5927.fw", ++ .size_of_priv = sizeof(struct tbs5927_state), ++ .no_reconnect = 1, ++ ++ .i2c_algo = &tbs5927_i2c_algo, ++ .rc.legacy = { ++ .rc_map_table = tbs5927_rc_keys, ++ .rc_map_size = ARRAY_SIZE(tbs5927_rc_keys), ++ .rc_interval = 250, ++ .rc_query = tbs5927_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ /* parameter for the MPEG2-data transfer */ ++ .num_adapters = 1, ++ .download_firmware = tbs5927_load_firmware, ++ .read_mac_address = tbs5927_read_mac_address, ++ .adapter = {{ ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = tbs5927_frontend_attach, ++ .streaming_ctrl = NULL, ++ .tuner_attach = tbs5927_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } }, ++ ++ .num_device_descs = 1, ++ .devices = { ++ {"TurboSight TBS 5927 DVB-S/S2", ++ {&tbs5927_table[0], NULL}, ++ {NULL}, ++ } ++ } ++}; ++ ++static int tbs5927_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ if (0 == dvb_usb_device_init(intf, &tbs5927_properties, ++ THIS_MODULE, NULL, adapter_nr)) { ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static struct usb_driver tbs5927_driver = { ++ .name = "tbs5927", ++ .probe = tbs5927_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = tbs5927_table, ++}; ++ ++static int __init tbs5927_module_init(void) ++{ ++ int ret = usb_register(&tbs5927_driver); ++ if (ret) ++ err("usb_register failed. Error number %d", ret); ++ ++ return ret; ++} ++ ++static void __exit tbs5927_module_exit(void) ++{ ++ usb_deregister(&tbs5927_driver); ++} ++ ++module_init(tbs5927_module_init); ++module_exit(tbs5927_module_exit); ++ ++MODULE_AUTHOR("TBSDTV"); ++MODULE_DESCRIPTION("TurboSight TBS 5927 DVB-S2 driver"); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb/tbs5927.h b/drivers/media/usb/dvb-usb/tbs5927.h +new file mode 100644 +index 0000000..9b5948c +--- /dev/null ++++ b/drivers/media/usb/dvb-usb/tbs5927.h +@@ -0,0 +1,8 @@ ++#ifndef _TBS5927_H_ ++#define _TBS5927_H_ ++ ++#define DVB_USB_LOG_PREFIX "tbs5927" ++#include "dvb-usb.h" ++ ++#define deb_xfer(args...) dprintk(dvb_usb_tbs5927_debug, 0x02, args) ++#endif +diff --git a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h +index 00a20cd..3157d38 100644 +--- a/include/uapi/linux/dvb/frontend.h ++++ b/include/uapi/linux/dvb/frontend.h +@@ -156,6 +156,8 @@ enum fe_code_rate { + FEC_3_5, + FEC_9_10, + FEC_2_5, ++ FEC_1_4, ++ FEC_1_3, + }; + + enum fe_modulation { +@@ -342,6 +344,7 @@ enum fe_delivery_system { + SYS_DVBT2, + SYS_TURBO, + SYS_DVBC_ANNEX_C, ++ SYS_DVBC2, + }; + + /* backward compatibility */ diff --git a/packages/linux/patches/default/linux-220.02-T230C-support.patch b/packages/linux/patches/default/linux-220.02-T230C-support.patch new file mode 100644 index 0000000000..c837c8d4df --- /dev/null +++ b/packages/linux/patches/default/linux-220.02-T230C-support.patch @@ -0,0 +1,294 @@ +From: https://github.com/crazycat69/linux_media/ +From: CrazyCat +Date: Wed, 28 Sep 2016 01:29:23 +0300 +Subject: [PATCH] cxusb: Geniatech T230C support. + +index 0f6ace4..72a8e91 100644 +--- a/drivers/media/usb/dvb-usb/cxusb.c ++++ b/drivers/media/usb/dvb-usb/cxusb.c +@@ -369,6 +369,26 @@ static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + return 0; + } + ++static int cxusb_read_status(struct dvb_frontend *fe, ++ enum fe_status *status) ++{ ++ struct dvb_usb_adapter *adap = (struct dvb_usb_adapter *)fe->dvb->priv; ++ struct cxusb_state *state = (struct cxusb_state *)adap->dev->priv; ++ int ret; ++ ++ ret = state->fe_read_status(fe, status); ++ ++ /* it need resync slave fifo when signal change from unlock to lock.*/ ++ if ((*status & FE_HAS_LOCK) && (!state->last_lock)) { ++ mutex_lock(&state->stream_mutex); ++ cxusb_streaming_ctrl(adap, 1); ++ mutex_unlock(&state->stream_mutex); ++ } ++ ++ state->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; ++ return ret; ++} ++ + static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d) + { + int ep = d->props.generic_bulk_ctrl_endpoint; +@@ -633,6 +653,44 @@ static struct rc_map_table rc_map_d680_dmb_table[] = { + { 0x0025, KEY_POWER }, + }; + ++static struct rc_map_table rc_map_t230_table[] = { ++ { 0x0000, KEY_0 }, ++ { 0x0001, KEY_1 }, ++ { 0x0002, KEY_2 }, ++ { 0x0003, KEY_3 }, ++ { 0x0004, KEY_4 }, ++ { 0x0005, KEY_5 }, ++ { 0x0006, KEY_6 }, ++ { 0x0007, KEY_7 }, ++ { 0x0008, KEY_8 }, ++ { 0x0009, KEY_9 }, ++ { 0x000a, KEY_MUTE }, ++ { 0x000b, KEY_STOP }, /* Stop */ ++ { 0x000c, KEY_POWER2 }, /* Turn on/off application */ ++ { 0x000d, KEY_OK }, /* OK */ ++ { 0x000e, KEY_CAMERA }, /* Snapshot */ ++ { 0x000f, KEY_ZOOM }, /* Full Screen/Restore */ ++ { 0x0010, KEY_RIGHT }, /* Right arrow */ ++ { 0x0011, KEY_LEFT }, /* Left arrow */ ++ { 0x0012, KEY_CHANNELUP }, ++ { 0x0013, KEY_CHANNELDOWN }, ++ { 0x0014, KEY_SHUFFLE }, ++ { 0x0016, KEY_PAUSE }, ++ { 0x0017, KEY_PLAY }, /* Play */ ++ { 0x001e, KEY_TIME }, /* Time Shift */ ++ { 0x001f, KEY_RECORD }, ++ { 0x0020, KEY_UP }, ++ { 0x0021, KEY_DOWN }, ++ { 0x0025, KEY_POWER }, /* Turn off computer */ ++ { 0x0026, KEY_REWIND }, /* FR << */ ++ { 0x0027, KEY_FASTFORWARD }, /* FF >> */ ++ { 0x0029, KEY_ESC }, ++ { 0x002b, KEY_VOLUMEUP }, ++ { 0x002c, KEY_VOLUMEDOWN }, ++ { 0x002d, KEY_CHANNEL }, /* CH Surfing */ ++ { 0x0038, KEY_VIDEO }, /* TV/AV/S-Video/YPbPr */ ++}; ++ + static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) + { + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; +@@ -1371,6 +1429,88 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) + st->i2c_client_demod = client_demod; + st->i2c_client_tuner = client_tuner; + ++ /* hook fe: need to resync the slave fifo when signal locks. */ ++ mutex_init(&st->stream_mutex); ++ st->last_lock = 0; ++ st->fe_read_status = adap->fe_adap[0].fe->ops.read_status; ++ adap->fe_adap[0].fe->ops.read_status = cxusb_read_status; ++ ++ return 0; ++} ++ ++static int cxusb_mygica_t230c_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ struct dvb_usb_device *d = adap->dev; ++ struct cxusb_state *st = d->priv; ++ struct i2c_adapter *adapter; ++ struct i2c_client *client_demod; ++ struct i2c_client *client_tuner; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ ++ /* Select required USB configuration */ ++ if (usb_set_interface(d->udev, 0, 0) < 0) ++ err("set interface failed"); ++ ++ /* Unblock all USB pipes */ ++ usb_clear_halt(d->udev, ++ usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); ++ usb_clear_halt(d->udev, ++ usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); ++ usb_clear_halt(d->udev, ++ usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint)); ++ ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &adap->fe_adap[0].fe; ++ si2168_config.ts_mode = SI2168_TS_PARALLEL; ++ si2168_config.ts_clock_inv = 1; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(&d->i2c_adap, &info); ++ if (client_demod == NULL || client_demod->dev.driver == NULL) ++ return -ENODEV; ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adap->fe_adap[0].fe; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2141", I2C_NAME_SIZE); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ request_module("si2157"); ++ client_tuner = i2c_new_device(adapter, &info); ++ if (client_tuner == NULL || client_tuner->dev.driver == NULL) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ return -ENODEV; ++ } ++ ++ st->i2c_client_demod = client_demod; ++ st->i2c_client_tuner = client_tuner; ++ ++ /* hook fe: need to resync the slave fifo when signal locks. */ ++ mutex_init(&st->stream_mutex); ++ st->last_lock = 0; ++ st->fe_read_status = adap->fe_adap[0].fe->ops.read_status; ++ adap->fe_adap[0].fe->ops.read_status = cxusb_read_status; ++ + return 0; + } + +@@ -1456,6 +1596,7 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties; + static struct dvb_usb_device_properties cxusb_d680_dmb_properties; + static struct dvb_usb_device_properties cxusb_mygica_d689_properties; + static struct dvb_usb_device_properties cxusb_mygica_t230_properties; ++static struct dvb_usb_device_properties cxusb_mygica_t230c_properties; + + static int cxusb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +@@ -1488,6 +1629,8 @@ static int cxusb_probe(struct usb_interface *intf, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, + THIS_MODULE, NULL, adapter_nr) || ++ 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230c_properties, ++ THIS_MODULE, NULL, adapter_nr) || + 0) + return 0; + +@@ -1539,6 +1682,7 @@ enum cxusb_table_index { + CONEXANT_D680_DMB, + MYGICA_D689, + MYGICA_T230, ++ MYGICA_T230C, + NR__cxusb_table_index + }; + +@@ -1606,6 +1750,9 @@ static struct usb_device_id cxusb_table[NR__cxusb_table_index + 1] = { + [MYGICA_T230] = { + USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) + }, ++ [MYGICA_T230C] = { ++ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230+1) ++ }, + {} /* Terminating entry */ + }; + MODULE_DEVICE_TABLE (usb, cxusb_table); +@@ -2290,8 +2437,8 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties = { + + .rc.legacy = { + .rc_interval = 100, +- .rc_map_table = rc_map_d680_dmb_table, +- .rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table), ++ .rc_map_table = rc_map_t230_table, ++ .rc_map_size = ARRAY_SIZE(rc_map_t230_table), + .rc_query = cxusb_d680_dmb_rc_query, + }, + +@@ -2305,6 +2452,59 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties = { + } + }; + ++static struct dvb_usb_device_properties cxusb_mygica_t230c_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = CYPRESS_FX2, ++ ++ .size_of_priv = sizeof(struct cxusb_state), ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = {{ ++ .streaming_ctrl = cxusb_streaming_ctrl, ++ .frontend_attach = cxusb_mygica_t230c_frontend_attach, ++ ++ /* parameter for the MPEG2-data transfer */ ++ .stream = { ++ .type = USB_BULK, ++ .count = 5, ++ .endpoint = 0x02, ++ .u = { ++ .bulk = { ++ .buffersize = 8192, ++ } ++ } ++ }, ++ } }, ++ }, ++ }, ++ ++ .power_ctrl = cxusb_d680_dmb_power_ctrl, ++ ++ .i2c_algo = &cxusb_i2c_algo, ++ ++ .generic_bulk_ctrl_endpoint = 0x01, ++ ++ .rc.legacy = { ++ .rc_interval = 100, ++ .rc_map_table = rc_map_t230_table, ++ .rc_map_size = ARRAY_SIZE(rc_map_t230_table), ++ .rc_query = cxusb_d680_dmb_rc_query, ++ }, ++ ++ .num_device_descs = 1, ++ .devices = { ++ { ++ "Mygica T230C DVB-T/T2/C", ++ { NULL }, ++ { &cxusb_table[MYGICA_T230C], NULL }, ++ }, ++ } ++}; ++ + static struct usb_driver cxusb_driver = { + .name = "dvb_usb_cxusb", + .probe = cxusb_probe, +diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h +index 18acda1..66429d7 100644 +--- a/drivers/media/usb/dvb-usb/cxusb.h ++++ b/drivers/media/usb/dvb-usb/cxusb.h +@@ -37,6 +37,11 @@ struct cxusb_state { + struct i2c_client *i2c_client_tuner; + + unsigned char data[MAX_XFER_SIZE]; ++ ++ struct mutex stream_mutex; ++ u8 last_lock; ++ int (*fe_read_status)(struct dvb_frontend *fe, ++ enum fe_status *status); + }; + + #endif +-- +2.7.4 + diff --git a/packages/linux/patches/default/linux-220.03-fixes-in-si2168-conf.patch b/packages/linux/patches/default/linux-220.03-fixes-in-si2168-conf.patch new file mode 100644 index 0000000000..013e4fd827 --- /dev/null +++ b/packages/linux/patches/default/linux-220.03-fixes-in-si2168-conf.patch @@ -0,0 +1,35 @@ +From: https://github.com/crazycat69/linux_media/commit/b9a64b0bf203030b3203916789ca4dfe55825edc +From: CrazyCat +Date: Mon, 18 Jul 2016 16:33:31 +0300 +Subject: [PATCH] Fixes in si2168 configuration. + +--- a/drivers/media/usb/dvb-usb/cxusb.c ++++ b/drivers/media/usb/dvb-usb/cxusb.c +@@ -1386,6 +1386,7 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) + usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint)); + + /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &adap->fe_adap[0].fe; + si2168_config.ts_mode = SI2168_TS_PARALLEL; +@@ -1641,6 +1642,7 @@ static void cxusb_disconnect(struct usb_interface *intf) + { + struct dvb_usb_device *d = usb_get_intfdata(intf); + struct cxusb_state *st = d->priv; ++#if 0 + struct i2c_client *client; + + /* remove I2C client for tuner */ +@@ -1656,7 +1658,7 @@ static void cxusb_disconnect(struct usb_interface *intf) + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } +- ++#endif + dvb_usb_device_exit(intf); + } + +-- +2.7.4 + diff --git a/packages/linux/patches/default/linux-221-ddbridge-features.patch b/packages/linux/patches/default/linux-221-ddbridge-features.patch deleted file mode 100644 index 87eafb9f25..0000000000 --- a/packages/linux/patches/default/linux-221-ddbridge-features.patch +++ /dev/null @@ -1,28495 +0,0 @@ -diff --git a/drivers/media/dvb-core/Makefile b/drivers/media/dvb-core/Makefile -index 8f22bcd..5ff851a 100644 ---- a/drivers/media/dvb-core/Makefile -+++ b/drivers/media/dvb-core/Makefile -@@ -6,6 +6,6 @@ dvb-net-$(CONFIG_DVB_NET) := dvb_net.o - - dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_frontend.o \ -- $(dvb-net-y) dvb_ringbuffer.o dvb_math.o -+ $(dvb-net-y) dvb_ringbuffer.o dvb_math.o dvb_netstream.o - - obj-$(CONFIG_DVB_CORE) += dvb-core.o -diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c -index b5b5b19..2cb8415 100644 ---- a/drivers/media/dvb-core/dvb_ca_en50221.c -+++ b/drivers/media/dvb-core/dvb_ca_en50221.c -@@ -344,7 +344,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) - /* read the buffer size from the CAM */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) - return ret; -- if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0) -+ if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ)) != 0) - return ret; - if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) - return -EIO; -@@ -641,65 +641,78 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb - } - } - -- /* check if there is data available */ -- if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -- goto exit; -- if (!(status & STATUSREG_DA)) { -- /* no data */ -- status = 0; -- goto exit; -- } -- -- /* read the amount of data */ -- if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) -- goto exit; -- bytes_read = status << 8; -- if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) -- goto exit; -- bytes_read |= status; -+ if (ca->pub->read_data && (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_LINKINIT)) { -+ if (ebuf == NULL) -+ status = ca->pub->read_data(ca->pub, slot, buf, sizeof(buf)); -+ else -+ status = ca->pub->read_data(ca->pub, slot, buf, ecount); -+ if (status < 0) -+ return status; -+ bytes_read = status; -+ if (status == 0) -+ goto exit; -+ } else { - -- /* check it will fit */ -- if (ebuf == NULL) { -- if (bytes_read > ca->slot_info[slot].link_buf_size) { -- printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", -- ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size); -- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -- status = -EIO; -+ /* check if there is data available */ -+ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) - goto exit; -- } -- if (bytes_read < 2) { -- printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", -- ca->dvbdev->adapter->num); -- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -- status = -EIO; -+ if (!(status & STATUSREG_DA)) { -+ /* no data */ -+ status = 0; - goto exit; - } -- } else { -- if (bytes_read > ecount) { -- printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", -- ca->dvbdev->adapter->num); -- status = -EIO; -+ -+ /* read the amount of data */ -+ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) -+ goto exit; -+ bytes_read = status << 8; -+ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) - goto exit; -+ bytes_read |= status; -+ -+ /* check it will fit */ -+ if (ebuf == NULL) { -+ if (bytes_read > ca->slot_info[slot].link_buf_size) { -+ printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", -+ ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size); -+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -+ status = -EIO; -+ goto exit; -+ } -+ if (bytes_read < 2) { -+ printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", -+ ca->dvbdev->adapter->num); -+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -+ status = -EIO; -+ goto exit; -+ } -+ } else { -+ if (bytes_read > ecount) { -+ printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", -+ ca->dvbdev->adapter->num); -+ status = -EIO; -+ goto exit; -+ } - } -- } - -- /* fill the buffer */ -- for (i = 0; i < bytes_read; i++) { -- /* read byte and check */ -- if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) -- goto exit; -+ /* fill the buffer */ -+ for (i = 0; i < bytes_read; i++) { -+ /* read byte and check */ -+ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) -+ goto exit; - -- /* OK, store it in the buffer */ -- buf[i] = status; -- } -+ /* OK, store it in the buffer */ -+ buf[i] = status; -+ } - -- /* check for read error (RE should now be 0) */ -- if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -- goto exit; -- if (status & STATUSREG_RE) { -- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -- status = -EIO; -- goto exit; -+ /* check for read error (RE should now be 0) */ -+ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -+ goto exit; -+ if (status & STATUSREG_RE) { -+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -+ status = -EIO; -+ goto exit; -+ } - } - - /* OK, add it to the receive buffer, or copy into external buffer if supplied */ -@@ -751,6 +764,9 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b - if (bytes_write > ca->slot_info[slot].link_buf_size) - return -EINVAL; - -+ if (ca->pub->write_data && (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_LINKINIT)) -+ return ca->pub->write_data(ca->pub, slot, buf, bytes_write); -+ - /* it is possible we are dealing with a single buffer implementation, - thus if there is data available for read or if there is even a read - already in progress, we do nothing but awake the kernel thread to -@@ -1086,7 +1102,8 @@ static int dvb_ca_en50221_thread(void *data) - - printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", - ca->dvbdev->adapter->num); -- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -+ printk("dvb_ca adapter %d: Trying to read attribute memory again (some CAMs are slow)\n", -+ ca->dvbdev->adapter->num); - dvb_ca_en50221_thread_update_delay(ca); - break; - } -@@ -1116,7 +1133,10 @@ static int dvb_ca_en50221_thread(void *data) - if (time_after(jiffies, ca->slot_info[slot].timeout)) { - printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", - ca->dvbdev->adapter->num); -- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -+ printk("dvb_ca adapter %d: Ignoring missing FR (some CAMs are broken)\n", -+ ca->dvbdev->adapter->num); -+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -+ ca->wakeup = 1; - dvb_ca_en50221_thread_update_delay(ca); - break; - } -@@ -1142,7 +1162,7 @@ static int dvb_ca_en50221_thread(void *data) - } - - printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); -- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED; - dvb_ca_en50221_thread_update_delay(ca); - break; - } -diff --git a/drivers/media/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb-core/dvb_ca_en50221.h -index 1e4bbbd..056d10c 100644 ---- a/drivers/media/dvb-core/dvb_ca_en50221.h -+++ b/drivers/media/dvb-core/dvb_ca_en50221.h -@@ -41,6 +41,8 @@ - * @write_attribute_mem: function for writing attribute memory on the CAM - * @read_cam_control: function for reading the control interface on the CAM - * @write_cam_control: function for reading the control interface on the CAM -+ * @read_data: function for reading data -+ * @write_data: function for writing data - * @slot_reset: function to reset the CAM slot - * @slot_shutdown: function to shutdown a CAM slot - * @slot_ts_enable: function to enable the Transport Stream on a CAM slot -@@ -66,6 +68,11 @@ struct dvb_ca_en50221 { - int (*write_cam_control)(struct dvb_ca_en50221 *ca, - int slot, u8 address, u8 value); - -+ int (*read_data)(struct dvb_ca_en50221* ca, -+ int slot, u8 *ebuf, int ecount); -+ int (*write_data)(struct dvb_ca_en50221* ca, -+ int slot, u8 *ebuf, int ecount); -+ - int (*slot_reset)(struct dvb_ca_en50221 *ca, int slot); - int (*slot_shutdown)(struct dvb_ca_en50221 *ca, int slot); - int (*slot_ts_enable)(struct dvb_ca_en50221 *ca, int slot); -diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c -index be99c8d..254f89d 100644 ---- a/drivers/media/dvb-core/dvb_frontend.c -+++ b/drivers/media/dvb-core/dvb_frontend.c -@@ -1037,6 +1037,7 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { - _DTV_CMD(DTV_STREAM_ID, 1, 0), - _DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0), - _DTV_CMD(DTV_LNA, 1, 0), -+ _DTV_CMD(DTV_INPUT, 1, 0), - - /* Get */ - _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), -@@ -1467,6 +1468,14 @@ static int dtv_property_process_get(struct dvb_frontend *fe, - tvp->u.data = c->lna; - break; - -+ case DTV_INPUT: -+ tvp->u.buffer.data[0] = c->input; -+ tvp->u.buffer.data[1] = fe->ops.xbar[0]; -+ tvp->u.buffer.data[2] = fe->ops.xbar[1]; -+ tvp->u.buffer.data[3] = fe->ops.xbar[2]; -+ tvp->u.buffer.len = 4; -+ break; -+ - /* Fill quality measures */ - case DTV_STAT_SIGNAL_STRENGTH: - tvp->u.st = c->strength; -@@ -1902,6 +1911,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe, - c->lna = LNA_AUTO; - break; - -+ case DTV_INPUT: -+ c->input = tvp->u.data; -+ if (fe->ops.set_input) -+ r = fe->ops.set_input(fe, c->input); -+ break; -+ - default: - return -EINVAL; - } -diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h -index fb6e848..3efb21b 100644 ---- a/drivers/media/dvb-core/dvb_frontend.h -+++ b/drivers/media/dvb-core/dvb_frontend.h -@@ -452,6 +452,7 @@ struct dvb_frontend_ops { - int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); - int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); - int (*set_lna)(struct dvb_frontend *); -+ int (*set_input)(struct dvb_frontend *, int); - - /* - * These callbacks are for devices that implement their own -@@ -464,6 +465,8 @@ struct dvb_frontend_ops { - - int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); - int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); -+ -+ u8 xbar[3]; - }; - - #ifdef __DVB_CORE__ -@@ -613,6 +616,7 @@ struct dtv_frontend_properties { - u8 atscmh_sccc_code_mode_d; - - u32 lna; -+ s32 input; - - /* statistics data */ - struct dtv_fe_stats strength; -diff --git a/drivers/media/dvb-core/dvb_netstream.c b/drivers/media/dvb-core/dvb_netstream.c -new file mode 100644 -index 0000000..0d80780 ---- /dev/null -+++ b/drivers/media/dvb-core/dvb_netstream.c -@@ -0,0 +1,259 @@ -+/* -+ * dvb_netstream.c: support for DVB to network streaming hardware -+ * -+ * Copyright (C) 2012-2013 Marcus and Ralph Metzler -+ * for Digital Devices GmbH -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include "dvb_netstream.h" -+ -+static ssize_t ns_write(struct file *file, const char *buf, -+ size_t count, loff_t *ppos) -+{ -+ pr_info("%s\n", __func__); -+ return 0; -+} -+ -+static ssize_t ns_read(struct file *file, char *buf, -+ size_t count, loff_t *ppos) -+{ -+ pr_info("%s\n", __func__); -+ return 0; -+} -+ -+static unsigned int ns_poll(struct file *file, poll_table *wait) -+{ -+ pr_info("%s\n", __func__); -+ return 0; -+} -+ -+static int ns_stop(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ -+ mutex_lock(&ns->mutex); -+ if (nss->running && ns->stop) { -+ ns->stop(nss); -+ nss->running = 0; -+ } -+ mutex_unlock(&ns->mutex); -+ return 0; -+} -+ -+static int ns_release(struct inode *inode, struct file *file) -+{ -+ struct dvbnss *nss = file->private_data; -+ struct dvb_netstream *ns = nss->ns; -+ -+ ns_stop(nss); -+ if (ns->free) -+ ns->free(nss); -+ mutex_lock(&ns->mutex); -+ list_del(&nss->nssl); -+ mutex_unlock(&ns->mutex); -+ vfree(nss); -+ return 0; -+} -+ -+static int ns_open(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct dvb_netstream *ns = dvbdev->priv; -+ struct dvbnss *nss; -+ -+ nss = vmalloc(sizeof(*nss)); -+ if (!nss) -+ return -ENOMEM; -+ nss->ns = ns; -+ if (ns->alloc && ns->alloc(nss) < 0) { -+ vfree(nss); -+ return -EBUSY; -+ } -+ file->private_data = nss; -+ nss->running = 0; -+ mutex_lock(&ns->mutex); -+ list_add(&nss->nssl, &ns->nssl); -+ mutex_unlock(&ns->mutex); -+ return 0; -+} -+ -+static int set_net(struct dvbnss *nss, struct dvb_ns_params *p) -+{ -+ return 0; -+} -+ -+static int do_ioctl(struct file *file, unsigned int cmd, void *parg) -+{ -+ struct dvbnss *nss = file->private_data; -+ struct dvb_netstream *ns = nss->ns; -+ /*unsigned long arg = (unsigned long) parg;*/ -+ int ret = 0; -+ -+ switch (cmd) { -+ case NS_SET_RTCP_MSG: -+ { -+ struct dvb_ns_rtcp *rtcpm = parg; -+ -+ if (ns->set_rtcp_msg) -+ ret = ns->set_rtcp_msg(nss, rtcpm->msg, rtcpm->len); -+ break; -+ } -+ -+ case NS_SET_NET: -+ memcpy(&nss->params, parg, sizeof(nss->params)); -+ if (ns->set_net) -+ ret = ns->set_net(nss); -+ else -+ ret = set_net(nss, (struct dvb_ns_params *) parg); -+ break; -+ -+ case NS_START: -+ mutex_lock(&ns->mutex); -+ if (nss->running) { -+ ret = -EBUSY; -+ } else if (ns->start) { -+ ret = ns->start(nss); -+ nss->running = 1; -+ } -+ mutex_unlock(&ns->mutex); -+ break; -+ -+ case NS_STOP: -+ ns_stop(nss); -+ break; -+ -+ case NS_SET_PACKETS: -+ { -+ struct dvb_ns_packet *packet = parg; -+ -+ if (ns->set_ts_packets) -+ ret = ns->set_ts_packets(nss, packet->buf, -+ packet->count * 188); -+ break; -+ } -+ -+ case NS_INSERT_PACKETS: -+ { -+ u8 count = *(u8 *) parg; -+ -+ if (ns->insert_ts_packets) -+ ret = ns->insert_ts_packets(nss, count); -+ break; -+ } -+ -+ case NS_SET_PID: -+ { -+ u16 pid = *(u16 *) parg; -+ u16 byte = (pid & 0x1fff) >> 3; -+ u8 bit = 1 << (pid & 7); -+ -+ if (pid & 0x2000) { -+ if (pid & 0x8000) -+ memset(nss->pids, 0xff, 0x400); -+ else -+ memset(nss->pids, 0x00, 0x400); -+ } else { -+ if (pid & 0x8000) -+ nss->pids[byte] |= bit; -+ else -+ nss->pids[byte] &= ~bit; -+ } -+ if (ns->set_pid) -+ ret = ns->set_pid(nss, pid); -+ break; -+ } -+ -+ case NS_SET_PIDS: -+ ret = copy_from_user(nss->pids, *(u8 **) parg, 0x400); -+ if (ret < 0) -+ return ret; -+ if (ns->set_pids) -+ ret = ns->set_pids(nss); -+ break; -+ -+ case NS_SET_CI: -+ { -+ u8 ci = *(u8 *) parg; -+ -+ if (nss->running) -+ ret = -EBUSY; -+ else if (ns->set_ci) -+ ret = ns->set_ci(nss, ci); -+ break; -+ } -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+static long ns_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy(file, cmd, arg, do_ioctl); -+} -+ -+static const struct file_operations ns_fops = { -+ .owner = THIS_MODULE, -+ .read = ns_read, -+ .write = ns_write, -+ .open = ns_open, -+ .release = ns_release, -+ .poll = ns_poll, -+ .mmap = 0, -+ .unlocked_ioctl = ns_ioctl, -+}; -+ -+static struct dvb_device ns_dev = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 1, -+ .fops = &ns_fops, -+}; -+ -+ -+int dvb_netstream_init(struct dvb_adapter *dvb_adapter, -+ struct dvb_netstream *ns) -+{ -+ mutex_init(&ns->mutex); -+ spin_lock_init(&ns->lock); -+ ns->exit = 0; -+ dvb_register_device(dvb_adapter, &ns->dvbdev, &ns_dev, ns, -+ DVB_DEVICE_NS, 0); -+ INIT_LIST_HEAD(&ns->nssl); -+ return 0; -+} -+EXPORT_SYMBOL(dvb_netstream_init); -+ -+void dvb_netstream_release(struct dvb_netstream *ns) -+{ -+ ns->exit = 1; -+ if (ns->dvbdev->users > 1) { -+ wait_event(ns->dvbdev->wait_queue, -+ ns->dvbdev->users == 1); -+ } -+ dvb_unregister_device(ns->dvbdev); -+} -+EXPORT_SYMBOL(dvb_netstream_release); -diff --git a/drivers/media/dvb-core/dvb_netstream.h b/drivers/media/dvb-core/dvb_netstream.h -new file mode 100644 -index 0000000..a40f1f1 ---- /dev/null -+++ b/drivers/media/dvb-core/dvb_netstream.h -@@ -0,0 +1,93 @@ -+/* -+ * dvb_netstream.c: support for DVB to network streaming hardware -+ * -+ * Copyright (C) 2012-2013 Marcus and Ralph Metzler -+ * for Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#ifndef _DVB_NETSTREAM_H_ -+#define _DVB_NETSTREAM_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvbdev.h" -+ -+#define DVBNS_MAXPIDS 32 -+ -+struct dvbnss { -+ struct dvb_netstream *ns; -+ void *priv; -+ -+ u8 pids[1024]; -+ u8 packet[1328]; -+ u32 pp; -+ -+ struct socket *sock; -+ struct sockaddr_in sadr; -+ u32 sn; -+ -+ struct dvb_ns_params params; -+ -+ struct list_head nssl; -+ int running; -+}; -+ -+#define MAX_DVBNSS 32 -+ -+struct dvb_netstream { -+ void *priv; -+ -+ struct mutex mutex; -+ spinlock_t lock; -+ struct dvb_device *dvbdev; -+ int exit; -+ -+ struct list_head nssl; -+ -+ int (*set_net)(struct dvbnss *); -+ int (*set_pid)(struct dvbnss *, u16); -+ int (*set_pids)(struct dvbnss *); -+ int (*set_ci)(struct dvbnss *, u8); -+ int (*set_rtcp_msg)(struct dvbnss *, u8 *, u32); -+ int (*set_ts_packets)(struct dvbnss *, u8 *, u32); -+ int (*insert_ts_packets)(struct dvbnss *, u8); -+ int (*start)(struct dvbnss *); -+ int (*stop)(struct dvbnss *); -+ int (*alloc)(struct dvbnss *); -+ void (*free)(struct dvbnss *); -+}; -+ -+ -+void dvb_netstream_release(struct dvb_netstream *); -+int dvb_netstream_init(struct dvb_adapter *, struct dvb_netstream *); -+ -+ -+#endif -diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c -index 75a3f4b..3f309b4 100644 ---- a/drivers/media/dvb-core/dvbdev.c -+++ b/drivers/media/dvb-core/dvbdev.c -@@ -50,7 +50,7 @@ static DEFINE_MUTEX(dvbdev_register_lock); - - static const char * const dnames[] = { - "video", "audio", "sec", "frontend", "demux", "dvr", "ca", -- "net", "osd" -+ "net", "osd", "ci", "mod", "ns", "nsd" - }; - - #ifdef CONFIG_DVB_DYNAMIC_MINORS -@@ -900,6 +900,7 @@ int dvb_usercopy(struct file *file, - kfree(mbuf); - return err; - } -+EXPORT_SYMBOL(dvb_usercopy); - - static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) - { -diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h -index 4aff7bd..ae4f4d1 100644 ---- a/drivers/media/dvb-core/dvbdev.h -+++ b/drivers/media/dvb-core/dvbdev.h -@@ -48,6 +48,10 @@ - #define DVB_DEVICE_CA 6 - #define DVB_DEVICE_NET 7 - #define DVB_DEVICE_OSD 8 -+#define DVB_DEVICE_CI 9 -+#define DVB_DEVICE_MOD 10 -+#define DVB_DEVICE_NS 11 -+#define DVB_DEVICE_NSD 12 - - #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ - static short adapter_nr[] = \ -diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig -index c645aa8..f5ff222 100644 ---- a/drivers/media/dvb-frontends/Kconfig -+++ b/drivers/media/dvb-frontends/Kconfig -@@ -28,6 +28,14 @@ config DVB_STV090x - DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators. - Say Y when you want to support these frontends. - -+config DVB_STV0910 -+ tristate "STV0910 based" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ ST STV0910 DVB-S/S2 demodulator. -+ Say Y when you want to support these frontends. -+ - config DVB_STV6110x - tristate "STV6110/(A) based tuners" - depends on DVB_CORE && I2C -@@ -35,6 +43,21 @@ config DVB_STV6110x - help - A Silicon tuner that supports DVB-S and DVB-S2 modes - -+config DVB_STV6111 -+ tristate "STV6111 based tuners" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ A Silicon tuner that supports DVB-S and DVB-S2 modes -+ -+config DVB_MXL5XX -+ tristate "Maxlinear MX58x based" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ Maxlinear MX58x family of tuners/demods. -+ Say Y when you want to support these frontends. -+ - config DVB_M88DS3103 - tristate "Montage Technology M88DS3103" - depends on DVB_CORE && I2C && I2C_MUX -@@ -89,6 +112,24 @@ config DVB_MN88473 - help - Say Y when you want to support this frontend. - -+config DVB_STV0367DD -+ tristate "STV 0367 (DD)" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ STV 0367 DVB-C/T demodulator (Digital Devices driver). -+ -+ Say Y when you want to support this frontend. -+ -+config DVB_CXD2843 -+ tristate "Sony CXD2843 DVB-C/T demodulator family" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ Sony CXD2843 demodulator (Digital Devices driver). -+ -+ Say Y when you want to support this frontend. -+ - comment "DVB-S (satellite) frontends" - depends on DVB_CORE - -diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile -index e90165a..d3fed98 100644 ---- a/drivers/media/dvb-frontends/Makefile -+++ b/drivers/media/dvb-frontends/Makefile -@@ -111,6 +111,11 @@ obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o - obj-$(CONFIG_DVB_CXD2841ER) += cxd2841er.o - obj-$(CONFIG_DVB_DRXK) += drxk.o - obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o -+obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o -+obj-$(CONFIG_DVB_CXD2843) += cxd2843.o -+obj-$(CONFIG_DVB_STV0910) += stv0910.o -+obj-$(CONFIG_DVB_STV6111) += stv6111.o -+obj-$(CONFIG_DVB_MXL5XX) += mxl5xx.o - obj-$(CONFIG_DVB_SI2165) += si2165.o - obj-$(CONFIG_DVB_A8293) += a8293.o - obj-$(CONFIG_DVB_SP2) += sp2.o -diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c -new file mode 100644 -index 0000000..959e4ab ---- /dev/null -+++ b/drivers/media/dvb-frontends/cxd2843.c -@@ -0,0 +1,2063 @@ -+/* -+ * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator. -+ * Also supports the CXD2837ER DVB-T/T2/C and the -+ * CXD2838ER ISDB-T demodulator. -+ * -+ * Copyright (C) 2013-2015 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#undef pr_fmt -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "dvb_math.h" -+#include "cxd2843.h" -+ -+#define FE_STATUS_FULL_LOCK (FE_HAS_SIGNAL \ -+ | FE_HAS_CARRIER \ -+ | FE_HAS_VITERBI \ -+ | FE_HAS_SYNC \ -+ | FE_HAS_LOCK) -+ -+#define INTLOG10X100(x) ((u32) (((u64) intlog10(x) * 100) >> 24)) -+ -+#define USE_ALGO 1 -+ -+enum demod_type { CXD2843, CXD2837, CXD2838 }; -+enum demod_state { Unknown, Shutdown, Sleep, ActiveT, -+ ActiveT2, ActiveC, ActiveC2, ActiveIT }; -+enum t2_profile { T2P_Base, T2P_Lite }; -+ -+struct cxd_state { -+ struct dvb_frontend frontend; -+ struct i2c_adapter *i2c; -+ struct mutex mutex; -+ -+ u8 adrt; -+ u8 curbankt; -+ -+ u8 adrx; -+ u8 curbankx; -+ -+ enum demod_type type; -+ enum demod_state state; -+ enum t2_profile T2Profile; -+ enum fe_delivery_system delsys; -+ -+ u8 IF_FS; -+ int ContinuousClock; -+ int SerialMode; -+ u8 SerialClockFrequency; -+ -+ u32 LockTimeout; -+ u32 TSLockTimeout; -+ u32 L1PostTimeout; -+ u32 DataSliceID; -+ int FirstTimeLock; -+ u32 plp; -+ u32 last_status; -+ -+ u32 bandwidth; -+ u32 bw; -+ -+ unsigned long tune_time; -+ -+ u32 LastBERNominator; -+ u32 LastBERDenominator; -+ u8 BERScaleMax; -+}; -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = { -+ .addr = adr, .flags = 0, .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_err("i2c_write error\n"); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int writeregs(struct cxd_state *state, u8 adr, u8 reg, -+ u8 *regd, u16 len) -+{ -+ u8 data[len + 1]; -+ -+ data[0] = reg; -+ memcpy(data + 1, regd, len); -+ return i2c_write(state->i2c, adr, data, len + 1); -+} -+ -+static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) -+{ -+ u8 mm[2] = {reg, dat}; -+ -+ return i2c_write(state->i2c, adr, mm, 2); -+} -+ -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ pr_err("i2c_read error\n"); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int readregs(struct cxd_state *state, u8 adr, u8 reg, -+ u8 *val, int count) -+{ -+ return i2c_read(state->i2c, adr, ®, 1, val, count); -+} -+ -+static int readregst_unlocked(struct cxd_state *cxd, u8 bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (bank != 0xFF && cxd->curbankt != bank) { -+ status = writereg(cxd, cxd->adrt, 0, bank); -+ if (status < 0) { -+ cxd->curbankt = 0xFF; -+ return status; -+ } -+ cxd->curbankt = bank; -+ } -+ status = readregs(cxd, cxd->adrt, Address, pValue, count); -+ return status; -+} -+ -+static int readregst(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregst_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (Bank != 0xFF && cxd->curbankx != Bank) { -+ status = writereg(cxd, cxd->adrx, 0, Bank); -+ if (status < 0) { -+ cxd->curbankx = 0xFF; -+ return status; -+ } -+ cxd->curbankx = Bank; -+ } -+ status = readregs(cxd, cxd->adrx, Address, pValue, count); -+ return status; -+} -+ -+static int readregsx(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregsx_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (Bank != 0xFF && cxd->curbankx != Bank) { -+ status = writereg(cxd, cxd->adrx, 0, Bank); -+ if (status < 0) { -+ cxd->curbankx = 0xFF; -+ return status; -+ } -+ cxd->curbankx = Bank; -+ } -+ status = writeregs(cxd, cxd->adrx, Address, pValue, count); -+ return status; -+} -+ -+static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = writeregsx_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) -+{ -+ return writeregsx(cxd, Bank, Address, &val, 1); -+} -+ -+static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (Bank != 0xFF && cxd->curbankt != Bank) { -+ status = writereg(cxd, cxd->adrt, 0, Bank); -+ if (status < 0) { -+ cxd->curbankt = 0xFF; -+ return status; -+ } -+ cxd->curbankt = Bank; -+ } -+ status = writeregs(cxd, cxd->adrt, Address, pValue, count); -+ return status; -+} -+ -+static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = writeregst_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) -+{ -+ return writeregst(cxd, Bank, Address, &val, 1); -+} -+ -+static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 Value, u8 Mask) -+{ -+ int status = 0; -+ u8 tmp; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1); -+ if (status < 0) -+ return status; -+ tmp = (tmp & ~Mask) | Value; -+ status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 Value, u8 Mask) -+{ -+ int status = 0; -+ u8 Tmp = 0x00; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1); -+ if (status < 0) -+ return status; -+ Tmp = (Tmp & ~Mask) | Value; -+ status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int freeze_regst(struct cxd_state *cxd) -+{ -+ mutex_lock(&cxd->mutex); -+ return writereg(cxd, cxd->adrt, 1, 1); -+} -+ -+static int unfreeze_regst(struct cxd_state *cxd) -+{ -+ int status = 0; -+ -+ status = writereg(cxd, cxd->adrt, 1, 0); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+/* TPSData[0] [7:6] CNST[1:0] */ -+/* TPSData[0] [5:3] HIER[2:0] */ -+/* TPSData[0] [2:0] HRATE[2:0] */ -+/* TPSData[1] [7:5] LRATE[2:0] */ -+/* TPSData[1] [4:3] GI[1:0] */ -+/* TPSData[1] [2:1] MODE[1:0] */ -+/* TPSData[2] [7:6] FNUM[1:0] */ -+/* TPSData[2] [5:0] LENGTH_INDICATOR[5:0] */ -+/* TPSData[3] [7:0] CELLID[15:8] */ -+/* TPSData[4] [7:0] CELLID[7:0] */ -+/* TPSData[5] [5:0] RESERVE_EVEN[5:0] */ -+/* TPSData[6] [5:0] RESERVE_ODD[5:0] */ -+ -+static int read_tps(struct cxd_state *state, u8 *tps) -+{ -+ if (state->last_status != FE_STATUS_FULL_LOCK) -+ return 0; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x10, 0x2f, tps, 7); -+ unfreeze_regst(state); -+ return 0; -+} -+ -+static void Active_to_Sleep(struct cxd_state *state) -+{ -+ if (state->state <= Sleep) -+ return; -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ -+ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ -+ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ -+ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ -+ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ -+ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ -+ state->state = Sleep; -+} -+ -+static void ActiveT2_to_Sleep(struct cxd_state *state) -+{ -+ if (state->state <= Sleep) -+ return; -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ -+ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ -+ -+ writeregt(state, 0x13, 0x83, 0x40); -+ writeregt(state, 0x13, 0x86, 0x21); -+ writebitst(state, 0x13, 0x9E, 0x09, 0x0F); -+ writeregt(state, 0x13, 0x9F, 0xFB); -+ -+ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ -+ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ -+ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ -+ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ -+ state->state = Sleep; -+} -+ -+static void ActiveC2_to_Sleep(struct cxd_state *state) -+{ -+ if (state->state <= Sleep) -+ return; -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ -+ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ -+ -+ writeregt(state, 0x20, 0xC2, 0x11); -+ writebitst(state, 0x25, 0x6A, 0x02, 0x03); -+ { -+ static u8 data[3] = { 0x07, 0x61, 0x36 }; -+ -+ writeregst(state, 0x25, 0x89, data, sizeof(data)); -+ } -+ writebitst(state, 0x25, 0xCB, 0x05, 0x07); -+ { -+ static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 }; -+ -+ writeregst(state, 0x25, 0xDC, data, sizeof(data)); -+ } -+ writeregt(state, 0x25, 0xE2, 0x2F); -+ writeregt(state, 0x25, 0xE5, 0x2F); -+ writebitst(state, 0x27, 0x20, 0x00, 0x01); -+ writebitst(state, 0x27, 0x35, 0x00, 0x01); -+ writebitst(state, 0x27, 0xD9, 0x19, 0x3F); -+ writebitst(state, 0x2A, 0x78, 0x01, 0x07); -+ writeregt(state, 0x2A, 0x86, 0x08); -+ writeregt(state, 0x2A, 0x88, 0x14); -+ writebitst(state, 0x2B, 0x2B, 0x00, 0x1F); -+ { -+ u8 data[2] = { 0x75, 0x75 }; -+ -+ writeregst(state, 0x2D, 0x24, data, sizeof(data)); -+ } -+ -+ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ -+ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ -+ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ -+ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ -+ state->state = Sleep; -+} -+ -+static int ConfigureTS(struct cxd_state *state, -+ enum demod_state newDemodState) -+{ -+ int status = 0; -+ u8 OSERCKMODE = state->SerialMode ? 1 : 0; -+ u8 OSERDUTYMODE = state->SerialMode ? 1 : 0; -+ u8 OTSCKPERIOD = 8; -+ u8 OREG_CKSEL_TSIF = state->SerialMode ? -+ state->SerialClockFrequency : 0; -+ -+ if (state->SerialMode && state->SerialClockFrequency >= 3) { -+ OSERCKMODE = 2; -+ OSERDUTYMODE = 2; -+ OTSCKPERIOD = 16; -+ OREG_CKSEL_TSIF = state->SerialClockFrequency - 3; -+ } -+ writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */ -+ writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */ -+ writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */ -+ writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */ -+ /* OREG_CKSEL_TSIF */ -+ writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03); -+ writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */ -+ -+ if (newDemodState == ActiveT) -+ writebitst(state, 0x10, 0x66, 0x01, 0x01); -+ if (newDemodState == ActiveC) -+ writebitst(state, 0x40, 0x66, 0x01, 0x01); -+ -+ return status; -+} -+ -+static void BandSettingT(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = { (iffreq >> 16) & 0xff, -+ (iffreq >> 8) & 0xff, iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x01, 0xE0 }; -+ u8 NF_data[] = { 0x01, 0x02 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x00, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ case 7: -+ { -+ u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x12, 0xF8 }; -+ u8 NF_data[] = { 0x00, 0x03 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x02, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ case 6: -+ { -+ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; -+ u8 CL_data[] = { 0x1F, 0xDC }; -+ u8 NF_data[] = { 0x00, 0x03 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x04, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ case 5: -+ { -+ static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; -+ static u8 CL_data[] = { 0x26, 0x3C }; -+ static u8 NF_data[] = { 0x00, 0x03 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x06, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ } -+} -+ -+static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveT); -+ writeregx(state, 0x00, 0x17, 0x01); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */ -+ writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ -+ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */ -+ writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */ -+ writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ BandSettingT(state, iffreq); -+ -+ writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */ -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+static void BandSettingT2(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, -+ iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; -+ -+ /* Timing recovery */ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ /* Add EQ Optimisation for tuner here */ -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ /* System Bandwidth */ -+ writebitst(state, 0x10, 0xD7, 0x00, 0x07); -+ } -+ break; -+ case 7: -+ { -+ u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x02, 0x07); -+ } -+ break; -+ case 6: -+ { -+ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x04, 0x07); -+ } -+ break; -+ case 5: -+ { -+ u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x06, 0x07); -+ } -+ break; -+ case 2: /* 1.7 MHz */ -+ { -+ u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x03, 0x07); -+ } -+ break; -+ } -+} -+ -+ -+static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveT2); -+ -+ writeregx(state, 0x00, 0x17, 0x02); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ -+ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */ -+ writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */ -+ writeregt(state, 0x13, 0x86, 0x34); -+ writebitst(state, 0x13, 0x9E, 0x09, 0x0F); -+ writeregt(state, 0x13, 0x9F, 0xD8); -+ -+ BandSettingT2(state, iffreq); -+ -+ writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */ -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+ -+static void BandSettingC(struct cxd_state *state, u32 iffreq) -+{ -+ u8 data[3]; -+ -+ data[0] = (iffreq >> 16) & 0xFF; -+ data[1] = (iffreq >> 8) & 0xFF; -+ data[2] = (iffreq) & 0xFF; -+ writeregst(state, 0x10, 0xB6, data, 3); -+} -+ -+static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveC); -+ -+ writeregx(state, 0x00, 0x17, 0x04); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */ -+ writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ BandSettingC(state, iffreq); -+ -+ writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */ -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+static void BandSettingC2(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = { (iffreq >> 16) & 0xff, -+ (iffreq >> 8) & 0xff, iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; -+ u8 data[2] = { 0x11, 0x9E }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x00, 0x07); -+ writeregst(state, 0x50, 0xEC, data, sizeof(data)); -+ writeregt(state, 0x50, 0xEF, 0x11); -+ writeregt(state, 0x50, 0xF1, 0x9E); -+ } -+ break; -+ case 6: -+ { -+ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; -+ u8 data[2] = { 0x17, 0x70 }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x04, 0x07); -+ writeregst(state, 0x50, 0xEC, data, sizeof(data)); -+ writeregt(state, 0x50, 0xEF, 0x17); -+ writeregt(state, 0x50, 0xF1, 0x70); -+ } -+ break; -+ } -+} -+ -+static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveC2); -+ -+ writeregx(state, 0x00, 0x17, 0x05); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ -+ writeregst(state, 0x00, 0x43, data, sizeof(data)); -+ /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ -+ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ writeregt(state, 0x20, 0xC2, 0x00); -+ writebitst(state, 0x25, 0x6A, 0x00, 0x03); -+ { -+ u8 data[3] = { 0x0C, 0xD1, 0x40 }; -+ -+ writeregst(state, 0x25, 0x89, data, sizeof(data)); -+ } -+ writebitst(state, 0x25, 0xCB, 0x01, 0x07); -+ { -+ u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 }; -+ -+ writeregst(state, 0x25, 0xDC, data, sizeof(data)); -+ } -+ writeregt(state, 0x25, 0xE2, 0x30); -+ writeregt(state, 0x25, 0xE5, 0x30); -+ writebitst(state, 0x27, 0x20, 0x01, 0x01); -+ writebitst(state, 0x27, 0x35, 0x01, 0x01); -+ writebitst(state, 0x27, 0xD9, 0x18, 0x3F); -+ writebitst(state, 0x2A, 0x78, 0x00, 0x07); -+ writeregt(state, 0x2A, 0x86, 0x20); -+ writeregt(state, 0x2A, 0x88, 0x32); -+ writebitst(state, 0x2B, 0x2B, 0x10, 0x1F); -+ { -+ u8 data[2] = { 0x01, 0x01 }; -+ -+ writeregst(state, 0x2D, 0x24, data, sizeof(data)); -+ } -+ -+ BandSettingC2(state, iffreq); -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+ -+static void BandSettingIT(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = { (iffreq >> 16) & 0xff, -+ (iffreq >> 8) & 0xff, iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */ -+ u8 CL_data[] = { 0x15, 0xA8 }; -+ -+ /*u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 }; */ /* 24 */ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ /* Add EQ Optimisation for tuner here */ -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ -+ writeregt(state, 0x10, 0xD7, 0x00); /* System Bandwidth */ -+ /*u8 CL_data[] = { 0x13, 0xFC }; */ -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ } -+ break; -+ case 7: -+ { -+ u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x1B, 0x5D }; -+ -+ /*u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; */ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ -+ writeregt(state, 0x10, 0xD7, 0x02); -+ /*static u8 CL_data[] = { 0x1A, 0xFA };*/ -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ } -+ break; -+ case 6: -+ { -+ u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x1F, 0xEC }; -+ /*u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 }; */ -+ /*u8 CL_data[] = { 0x1F, 0x79 }; */ -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writeregt(state, 0x10, 0xD7, 0x04); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ } -+ break; -+ } -+} -+ -+static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq) -+{ -+ u8 data2[3] = { 0xB9, 0xBA, 0x63 }; /* 20.5/41 MHz */ -+ /*u8 data2[3] = { 0xB7,0x1B,0x00 }; */ /* 24 MHz */ -+ u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */ -+ /*u8 TSIF_data[2] = { 0x60,0x00 } ; */ /* 24 MHz */ -+ -+ -+ ConfigureTS(state, ActiveIT); -+ -+ /* writeregx(state, 0x00,0x17,0x01); */ /* 2838 has only one Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz, 24 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writeregst(state, 0x60, 0xA8, data2, sizeof(data2)); -+ -+ writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data)); -+ -+ writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ BandSettingIT(state, iffreq); -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+static void T2_SetParameters(struct cxd_state *state) -+{ -+ u8 Profile = 0x01; /* Profile Base */ -+ u8 notT2time = 12; /* early unlock detection time */ -+ -+ if (state->T2Profile == T2P_Lite) { -+ Profile = 0x05; -+ notT2time = 40; -+ } -+ -+ if (state->plp != 0xffffffff) { -+ state->T2Profile = ((state->plp & 0x100) != 0) ? -+ T2P_Lite : T2P_Base; -+ writeregt(state, 0x23, 0xAF, state->plp); -+ writeregt(state, 0x23, 0xAD, 0x01); -+ } else { -+ state->T2Profile = T2P_Base; -+ writeregt(state, 0x23, 0xAD, 0x00); -+ } -+ -+ writebitst(state, 0x2E, 0x10, Profile, 0x07); -+ writeregt(state, 0x2B, 0x19, notT2time); -+} -+ -+static void C2_ReleasePreset(struct cxd_state *state) -+{ -+ { -+ static u8 data[2] = { 0x02, 0x80}; -+ -+ writeregst(state, 0x27, 0xF4, data, sizeof(data)); -+ } -+ writebitst(state, 0x27, 0x51, 0x40, 0xF0); -+ writebitst(state, 0x27, 0x73, 0x07, 0x0F); -+ writebitst(state, 0x27, 0x74, 0x19, 0x3F); -+ writebitst(state, 0x27, 0x75, 0x19, 0x3F); -+ writebitst(state, 0x27, 0x76, 0x19, 0x3F); -+ if (state->bw == 6) { -+ static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA}; -+ -+ writeregst(state, 0x20, 0x9F, data, sizeof(data)); -+ } else { -+ static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00}; -+ -+ writeregst(state, 0x20, 0x9F, data, sizeof(data)); -+ } -+ writebitst(state, 0x27, 0xC9, 0x07, 0x07); -+ writebitst(state, 0x20, 0xC2, 0x11, 0x33); -+ { -+ static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8, -+ 0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 }; -+ -+ writeregst(state, 0x2A, 0x20, data, sizeof(data)); -+ } -+ { -+ static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 }; -+ -+ writeregst(state, 0x50, 0x6B, data, sizeof(data)); -+ } -+ writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */ -+} -+ -+static void C2_DemodSetting2(struct cxd_state *state) -+{ -+ u8 data[6]; -+ u32 TunePosition = -+ state->frontend.dtv_property_cache.frequency / 1000; -+ -+ if (state->bw == 6) -+ TunePosition = ((TunePosition * 1792) / 3) / 1000; -+ else -+ TunePosition = (TunePosition * 448) / 1000; -+ -+ TunePosition = ((TunePosition + 6) / 12) * 12; -+ -+ pr_info("TunePosition = %u\n", TunePosition); -+ -+ data[0] = ((TunePosition >> 16) & 0xFF); -+ data[1] = ((TunePosition >> 8) & 0xFF); -+ data[2] = (TunePosition & 0xFF); -+ data[3] = 0x02; -+ data[4] = (state->DataSliceID & 0xFF); -+ data[5] = (state->plp & 0xFF); -+ writeregst(state, 0x50, 0x7A, data, sizeof(data)); -+ writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */ -+} -+ -+static void Stop(struct cxd_state *state) -+{ -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+} -+ -+static void ShutDown(struct cxd_state *state) -+{ -+ switch (state->state) { -+ case ActiveT2: -+ ActiveT2_to_Sleep(state); -+ break; -+ case ActiveC2: -+ ActiveC2_to_Sleep(state); -+ break; -+ default: -+ Active_to_Sleep(state); -+ break; -+ } -+} -+ -+static int gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ -+ return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01); -+} -+ -+static void release(struct dvb_frontend *fe) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ -+ Stop(state); -+ ShutDown(state); -+ kfree(state); -+} -+ -+static int sleep(struct dvb_frontend *fe) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ -+ Stop(state); -+ ShutDown(state); -+ return 0; -+} -+ -+static int Start(struct cxd_state *state, u32 IntermediateFrequency) -+{ -+ enum demod_state newDemodState = Unknown; -+ u32 iffreq; -+ -+ if (state->state < Sleep) -+ return -EINVAL; -+ -+ iffreq = MulDiv32(IntermediateFrequency, 16777216, 41000000); -+ -+ switch (state->delsys) { -+ case SYS_DVBT: -+ if (state->type == CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveT; -+ break; -+ case SYS_DVBT2: -+ if (state->type == CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveT2; -+ break; -+ case SYS_DVBC_ANNEX_A: -+ if (state->type == CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveC; -+ break; -+ case SYS_ISDBT: -+ if (state->type != CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveIT; -+ break; -+ case SYS_DVBC2: -+ if (state->type != CXD2843) -+ return -EINVAL; -+ newDemodState = ActiveC2; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ state->LockTimeout = 0; -+ state->TSLockTimeout = 0; -+ state->L1PostTimeout = 0; -+ state->last_status = 0; -+ state->FirstTimeLock = 1; -+ state->LastBERNominator = 0; -+ state->LastBERDenominator = 1; -+ state->BERScaleMax = 19; -+ -+ if (state->state == newDemodState) { -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS Output */ -+ switch (newDemodState) { -+ case ActiveT: -+ /* Stick with HP ( 0x01 = LP ) */ -+ writeregt(state, 0x10, 0x67, 0x00); -+ BandSettingT(state, iffreq); -+ state->BERScaleMax = 18; -+ break; -+ case ActiveT2: -+ T2_SetParameters(state); -+ BandSettingT2(state, iffreq); -+ state->BERScaleMax = 12; -+ break; -+ case ActiveC: -+ BandSettingC(state, iffreq); -+ state->BERScaleMax = 19; -+ break; -+ case ActiveC2: -+ BandSettingC2(state, iffreq); -+ C2_ReleasePreset(state); -+ C2_DemodSetting2(state); -+ break; -+ case ActiveIT: -+ BandSettingIT(state, iffreq); -+ break; -+ default: -+ break; -+ } -+ } else { -+ if (state->state > Sleep) { -+ switch (state->state) { -+ case ActiveT2: -+ ActiveT2_to_Sleep(state); -+ break; -+ case ActiveC2: -+ ActiveC2_to_Sleep(state); -+ break; -+ default: -+ Active_to_Sleep(state); -+ break; -+ } -+ } -+ switch (newDemodState) { -+ case ActiveT: -+ /* Stick with HP ( 0x01 = LP ) */ -+ writeregt(state, 0x10, 0x67, 0x00); -+ Sleep_to_ActiveT(state, iffreq); -+ state->BERScaleMax = 18; -+ break; -+ case ActiveT2: -+ T2_SetParameters(state); -+ Sleep_to_ActiveT2(state, iffreq); -+ state->BERScaleMax = 12; -+ break; -+ case ActiveC: -+ Sleep_to_ActiveC(state, iffreq); -+ state->BERScaleMax = 19; -+ break; -+ case ActiveC2: -+ Sleep_to_ActiveC2(state, iffreq); -+ C2_ReleasePreset(state); -+ C2_DemodSetting2(state); -+ break; -+ case ActiveIT: -+ Sleep_to_ActiveIT(state, iffreq); -+ break; -+ default: -+ break; -+ } -+ } -+ state->state = newDemodState; -+ writeregt(state, 0x00, 0xFE, 0x01); /* SW Reset */ -+ writeregt(state, 0x00, 0xC3, 0x00); /* Enable TS Output */ -+ -+ return 0; -+} -+ -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ int stat; -+ struct cxd_state *state = fe->demodulator_priv; -+ u32 IF; -+ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ case SYS_DVBC2: -+ case SYS_DVBT: -+ case SYS_DVBT2: -+ case SYS_ISDBT: -+ state->delsys = fe->dtv_property_cache.delivery_system; -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; -+ state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000; -+ if (fe->dtv_property_cache.stream_id == 0xffffffff) { -+ state->DataSliceID = 0xffffffff; -+ state->plp = 0xffffffff; -+ } else { -+ state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8) -+ & 0xff; -+ state->plp = fe->dtv_property_cache.stream_id & 0xff; -+ } -+ /* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */ -+ if (fe->ops.tuner_ops.get_if_frequency) -+ fe->ops.tuner_ops.get_if_frequency(fe, &IF); -+ stat = Start(state, IF); -+ return stat; -+} -+ -+ -+static void init(struct cxd_state *state) -+{ -+ u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */ -+ -+ state->delsys = SYS_UNDEFINED; -+ state->state = Unknown; -+ -+ writeregx(state, 0xFF, 0x02, 0x00); -+ usleep_range(4000, 5000); -+ writeregx(state, 0x00, 0x15, 0x01); -+ if (state->type != CXD2838) -+ writeregx(state, 0x00, 0x17, 0x01); -+ usleep_range(4000, 5000); -+ -+ writeregx(state, 0x00, 0x10, 0x01); -+ -+ writeregsx(state, 0x00, 0x13, data, 2); -+ writeregx(state, 0x00, 0x15, 0x00); -+ usleep_range(3000, 4000); -+ writeregx(state, 0x00, 0x10, 0x00); -+ usleep_range(2000, 3000); -+ -+ state->curbankx = 0xFF; -+ state->curbankt = 0xFF; -+ -+ writeregt(state, 0x00, 0x43, 0x0A); -+ writeregt(state, 0x00, 0x41, 0x0A); -+ if (state->type == CXD2838) -+ writeregt(state, 0x60, 0x5A, 0x00); -+ -+ writebitst(state, 0x10, 0xCB, 0x00, 0x40); -+ writeregt(state, 0x10, 0xCD, state->IF_FS); -+ -+ writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98); -+ writebitst(state, 0x00, 0xC5, 0x01, 0x07); -+ writebitst(state, 0x00, 0xCB, 0x00, 0x01); -+ writebitst(state, 0x00, 0xC6, 0x00, 0x1D); -+ writebitst(state, 0x00, 0xC8, 0x01, 0x1D); -+ writebitst(state, 0x00, 0xC9, 0x00, 0x1D); -+ writebitst(state, 0x00, 0x83, 0x00, 0x07); -+ writeregt(state, 0x00, 0x84, 0x00); -+ writebitst(state, 0x00, 0xD3, -+ (state->type == CXD2838) ? 0x01 : 0x00, 0x01); -+ writebitst(state, 0x00, 0xDE, 0x00, 0x01); -+ -+ state->state = Sleep; -+} -+ -+ -+static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg) -+{ -+ state->adrt = cfg->adr; -+ state->adrx = cfg->adr + 0x02; -+ state->curbankt = 0xff; -+ state->curbankx = 0xff; -+ mutex_init(&state->mutex); -+ -+ state->SerialMode = cfg->parallel ? 0 : 1; -+ state->ContinuousClock = 1; -+ state->SerialClockFrequency = -+ (cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ? -+ cfg->ts_clock : 1; /* 1 = fastest (82 MBit/s), 5 = slowest */ -+ /* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ -+ state->IF_FS = 0x50; -+} -+ -+static int read_status(struct dvb_frontend *fe, enum fe_status *status) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ u8 rdata; -+ -+ *status = 0; -+ switch (state->state) { -+ case ActiveC: -+ readregst(state, 0x40, 0x88, &rdata, 1); -+ if (rdata & 0x02) -+ break; -+ if (rdata & 0x01) { -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI); -+ readregst(state, 0x40, 0x10, &rdata, 1); -+ if (rdata & 0x20) -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI -+ | FE_HAS_SYNC -+ | FE_HAS_LOCK); -+ } -+ break; -+ case ActiveT: -+ readregst(state, 0x10, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if ((rdata & 0x07) == 0x06) { -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI); -+ if (rdata & 0x20) -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI -+ | FE_HAS_SYNC -+ | FE_HAS_LOCK); -+ } -+ break; -+ case ActiveT2: -+ readregst(state, 0x20, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if ((rdata & 0x07) == 0x06) { -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI); -+ if (rdata & 0x20) -+ *status |= FE_HAS_SYNC; -+ } -+ if (*status & 0x08) { -+ readregst(state, 0x22, 0x12, &rdata, 1); -+ if (rdata & 0x01) -+ *status |= FE_HAS_LOCK; -+ } -+ break; -+ case ActiveC2: -+ readregst(state, 0x20, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if ((rdata & 0x07) == 0x06) { -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI); -+ if (rdata & 0x20) -+ *status |= (FE_HAS_SYNC | FE_HAS_LOCK); -+ } -+ if ((*status & FE_HAS_LOCK) && state->FirstTimeLock) { -+ u8 data; -+ -+ /* Change1stTrial */ -+ readregst(state, 0x28, 0xE6, &rdata, 1); -+ data = rdata & 1; -+ readregst(state, 0x50, 0x15, &rdata, 1); -+ data |= ((rdata & 0x18) >> 2); -+ /*writebitst(state, 0x50,0x6F,rdata,0x07);*/ -+ state->FirstTimeLock = 0; -+ } -+ break; -+ case ActiveIT: -+ readregst(state, 0x60, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if (rdata & 0x02) { -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI); -+ if (rdata & 0x01) -+ *status |= (FE_HAS_SYNC | FE_HAS_LOCK); -+ } -+ break; -+ default: -+ break; -+ } -+ state->last_status = *status; -+ return 0; -+} -+ -+static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ u8 BERRegs[3]; -+ u8 Scale; -+ -+ *n = 0; -+ *d = 1; -+ -+ readregst(state, 0x10, 0x62, BERRegs, 3); -+ readregst(state, 0x10, 0x60, &Scale, 1); -+ Scale &= 0x1F; -+ -+ if (BERRegs[0] & 0x80) { -+ state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | -+ (((u32) BERRegs[1]) << 8) | BERRegs[2]; -+ state->LastBERDenominator = 1632 << Scale; -+ if (state->LastBERNominator < 256 && -+ Scale < state->BERScaleMax) { -+ writebitst(state, 0x10, 0x60, Scale + 1, 0x1F); -+ } else if (state->LastBERNominator > 512 && Scale > 11) -+ writebitst(state, 0x10, 0x60, Scale - 1, 0x1F); -+ } -+ *n = state->LastBERNominator; -+ *d = state->LastBERDenominator; -+ -+ return 0; -+} -+ -+static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ *n = 0; -+ *d = 1; -+ return 0; -+} -+ -+static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ u8 BERRegs[3]; -+ u8 Scale; -+ -+ *n = 0; -+ *d = 1; -+ -+ readregst(state, 0x40, 0x62, BERRegs, 3); -+ readregst(state, 0x40, 0x60, &Scale, 1); -+ Scale &= 0x1F; -+ -+ if (BERRegs[0] & 0x80) { -+ state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | -+ (((u32) BERRegs[1]) << 8) | BERRegs[2]; -+ state->LastBERDenominator = 1632 << Scale; -+ if (state->LastBERNominator < 256 && -+ Scale < state->BERScaleMax) { -+ writebitst(state, 0x40, 0x60, Scale + 1, 0x1F); -+ } else if (state->LastBERNominator > 512 && Scale > 11) -+ writebitst(state, 0x40, 0x60, Scale - 1, 0x1F); -+ } -+ *n = state->LastBERNominator; -+ *d = state->LastBERDenominator; -+ -+ return 0; -+} -+ -+static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ *n = 0; -+ *d = 1; -+ return 0; -+} -+ -+static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ *n = 0; -+ *d = 1; -+ return 0; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber, u32 *n, u32 *d) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ int s = 0; -+ -+ *ber = 0; -+ *n = 0; -+ *d = 1; -+ -+ switch (state->state) { -+ case ActiveT: -+ s = get_ber_t(state, n, d); -+ break; -+ case ActiveT2: -+ s = get_ber_t2(state, n, d); -+ break; -+ case ActiveC: -+ s = get_ber_c(state, n, d); -+ break; -+ case ActiveC2: -+ s = get_ber_c2(state, n, d); -+ break; -+ case ActiveIT: -+ s = get_ber_it(state, n, d); -+ break; -+ default: -+ break; -+ } -+ -+ if (s) -+ return s; -+ -+ if (d) -+ *ber = (*n * 1000) / *d; -+ -+ return 0; -+} -+ -+static u32 snrreg_to_db_t_c2_it(u32 reg, u32 max, u32 offset) -+{ -+ s32 snr; -+ -+ if (reg == 0) -+ return 0; -+ -+ snr = 100 * ((INTLOG10X100(reg) - INTLOG10X100(max - reg)) + offset); -+ -+ if (snr < 0) -+ return 0; -+ -+ return snr; -+} -+ -+static u32 snrreg_to_db_c(u32 reg, u32 max, u32 mult) -+{ -+ return (reg != 0 ? ((max - INTLOG10X100(reg)) * mult + 500) / 10 : 0); -+} -+ -+static int GetSignalToNoiseIT(struct cxd_state *state, u32 *snr) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ -+ switch (state->bw) { -+ case 8: -+ if (reg > 1143) -+ reg = 1143; -+ *snr = snrreg_to_db_t_c2_it(reg, 1200, 220); -+ break; -+ default: -+ if (reg > 51441) -+ reg = 51441; -+ -+ *snr = (reg > 0 ? (INTLOG10X100(reg) - 90) : 0); -+ break; -+ } -+ -+ return 0; -+} -+ -+static int GetSignalToNoiseC2(struct cxd_state *state, u32 *snr) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ if (reg > 51441) -+ reg = 51441; -+ -+ *snr = snrreg_to_db_t_c2_it(reg, 55000, 384); -+ -+ return 0; -+} -+ -+ -+static int GetSignalToNoiseT2(struct cxd_state *state, u32 *snr) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ if (reg > 10876) -+ reg = 10876; -+ -+ *snr = snrreg_to_db_t_c2_it(reg, 12600, 320); -+ -+ return 0; -+} -+ -+static int GetSignalToNoiseT(struct cxd_state *state, u32 *snr) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ if (reg > 4996) -+ reg = 4996; -+ -+ *snr = snrreg_to_db_t_c2_it(reg, 5350, 285); -+ -+ return 0; -+} -+ -+static int GetSignalToNoiseC(struct cxd_state *state, u32 *snr) -+{ -+ u8 Data[2]; -+ u8 Constellation = 0; -+ u32 reg; -+ -+ *snr = 0; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x40, 0x19, &Constellation, 1); -+ readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]); -+ if (reg == 0) -+ return 0; -+ -+ switch (Constellation & 0x07) { -+ case 0: /* QAM 16 */ -+ case 2: /* QAM 64 */ -+ case 4: /* QAM 256 */ -+ if (reg < 126) -+ reg = 126; -+ *snr = snrreg_to_db_c(reg, 439, 2134); -+ break; -+ case 1: /* QAM 32 */ -+ case 3: /* QAM 128 */ -+ if (reg < 69) -+ reg = 69; -+ *snr = snrreg_to_db_c(reg, 432, 2015); -+ break; -+ } -+ -+ return 0; -+} -+ -+static u32 read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ u32 ret = 0; -+ struct cxd_state *state = fe->demodulator_priv; -+ -+ if (state->last_status != FE_STATUS_FULL_LOCK) -+ return 0; -+ -+ switch (state->state) { -+ case ActiveC: -+ GetSignalToNoiseC(state, &ret); -+ break; -+ case ActiveC2: -+ GetSignalToNoiseC2(state, &ret); -+ break; -+ case ActiveT: -+ GetSignalToNoiseT(state, &ret); -+ break; -+ case ActiveT2: -+ GetSignalToNoiseT2(state, &ret); -+ break; -+ case ActiveIT: -+ GetSignalToNoiseIT(state, &ret); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ *snr = ret & 0xffff; -+ return 0; -+} -+ -+static int read_agc_gain_c_t_t2(struct dvb_frontend *fe, u16 *strength) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ u8 data[2]; -+ u8 regbank; -+ -+ switch (state->state) { -+ case ActiveC: -+ case ActiveT: -+ regbank = 0x10; -+ break; -+ case ActiveT2: -+ regbank = 0x20; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ freeze_regst(state); -+ readregst_unlocked(state, regbank, 0x26, data, sizeof(data)); -+ unfreeze_regst(state); -+ -+ *strength = 65535 - -+ (((((u16)data[0] & 0x0F) << 8) -+ | (u16)(data[1] & 0xFF)) -+ << 4); -+ -+ return 0; -+} -+ -+static int tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, -+ unsigned int *delay, enum fe_status *status) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ int r; -+ -+ if (re_tune) { -+ r = set_parameters(fe); -+ if (r) -+ return r; -+ state->tune_time = jiffies; -+ -+ } -+ if (*status & FE_HAS_LOCK) -+ return 0; -+ /* *delay = 50; */ -+ r = read_status(fe, status); -+ if (r) -+ return r; -+ return 0; -+} -+ -+static enum dvbfe_search search(struct dvb_frontend *fe) -+{ -+ int r; -+ u32 loops = 20, i; -+ enum fe_status status; -+ -+ r = set_parameters(fe); -+ -+ for (i = 0; i < loops; i++) { -+ msleep(50); -+ r = read_status(fe, &status); -+ if (r) -+ return DVBFE_ALGO_SEARCH_ERROR; -+ if (status & FE_HAS_LOCK) -+ break; -+ } -+ -+ if (status & FE_HAS_LOCK) -+ return DVBFE_ALGO_SEARCH_SUCCESS; -+ else -+ return DVBFE_ALGO_SEARCH_AGAIN; -+} -+ -+static int get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+ -+static int get_fe_t(struct cxd_state *state) -+{ -+ struct dvb_frontend *fe = &state->frontend; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ u8 tps[7]; -+ -+ read_tps(state, tps); -+ -+/* TPSData[0] [7:6] CNST[1:0] -+ * TPSData[0] [5:3] HIER[2:0] -+ * TPSData[0] [2:0] HRATE[2:0] -+ */ -+ switch ((tps[0] >> 6) & 0x03) { -+ case 0: -+ p->modulation = QPSK; -+ break; -+ case 1: -+ p->modulation = QAM_16; -+ break; -+ case 2: -+ p->modulation = QAM_64; -+ break; -+ } -+ switch ((tps[0] >> 3) & 0x07) { -+ case 0: -+ p->hierarchy = HIERARCHY_NONE; -+ break; -+ case 1: -+ p->hierarchy = HIERARCHY_1; -+ break; -+ case 2: -+ p->hierarchy = HIERARCHY_2; -+ break; -+ case 3: -+ p->hierarchy = HIERARCHY_4; -+ break; -+ } -+ switch ((tps[0] >> 0) & 0x07) { -+ case 0: -+ p->code_rate_HP = FEC_1_2; -+ break; -+ case 1: -+ p->code_rate_HP = FEC_2_3; -+ break; -+ case 2: -+ p->code_rate_HP = FEC_3_4; -+ break; -+ case 3: -+ p->code_rate_HP = FEC_5_6; -+ break; -+ case 4: -+ p->code_rate_HP = FEC_7_8; -+ break; -+ } -+ -+/* TPSData[1] [7:5] LRATE[2:0] -+ * TPSData[1] [4:3] GI[1:0] -+ * TPSData[1] [2:1] MODE[1:0] -+ */ -+ switch ((tps[1] >> 5) & 0x07) { -+ case 0: -+ p->code_rate_LP = FEC_1_2; -+ break; -+ case 1: -+ p->code_rate_LP = FEC_2_3; -+ break; -+ case 2: -+ p->code_rate_LP = FEC_3_4; -+ break; -+ case 3: -+ p->code_rate_LP = FEC_5_6; -+ break; -+ case 4: -+ p->code_rate_LP = FEC_7_8; -+ break; -+ } -+ switch ((tps[1] >> 3) & 0x03) { -+ case 0: -+ p->guard_interval = GUARD_INTERVAL_1_32; -+ break; -+ case 1: -+ p->guard_interval = GUARD_INTERVAL_1_16; -+ break; -+ case 2: -+ p->guard_interval = GUARD_INTERVAL_1_8; -+ break; -+ case 3: -+ p->guard_interval = GUARD_INTERVAL_1_4; -+ break; -+ } -+ switch ((tps[1] >> 1) & 0x03) { -+ case 0: -+ p->transmission_mode = TRANSMISSION_MODE_2K; -+ break; -+ case 1: -+ p->transmission_mode = TRANSMISSION_MODE_8K; -+ break; -+ } -+ -+ return 0; -+} -+ -+static int get_fe_c(struct cxd_state *state) -+{ -+ struct dvb_frontend *fe = &state->frontend; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ u8 qam; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x40, 0x19, &qam, 1); -+ unfreeze_regst(state); -+ p->modulation = 1 + (qam & 0x07); -+ return 0; -+} -+ -+static int get_frontend(struct dvb_frontend *fe, -+ struct dtv_frontend_properties *p) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ enum fe_status status = 0; -+ int tmp; -+ u16 snr = 0, strength = 0; -+ u32 ber = 0, bernom = 0, berdenom = 1; -+ -+ tmp = read_status(fe, &status); -+ -+ p->strength.len = 1; -+ p->cnr.len = 1; -+ p->pre_bit_error.len = 1; -+ p->pre_bit_count.len = 1; -+ p->post_bit_error.len = 1; -+ -+ if (state->last_status != FE_STATUS_FULL_LOCK) { -+ p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ p->cnr.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; -+ -+ return 0; -+ } -+ -+ if (state->state == ActiveT) -+ get_fe_t(state); -+ else if (state->state == ActiveC) -+ get_fe_c(state); -+ -+ if (read_agc_gain_c_t_t2(fe, &strength)) -+ p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->strength.stat[0].scale = FE_SCALE_RELATIVE; -+ p->strength.stat[0].uvalue = strength; -+ } -+ -+ if (read_snr(fe, &snr)) -+ p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->cnr.stat[0].scale = FE_SCALE_DECIBEL; -+ p->cnr.stat[0].svalue = snr; -+ } -+ -+ if (read_ber(fe, &ber, &bernom, &berdenom)) { -+ 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; -+ } else { -+ p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->pre_bit_error.stat[0].uvalue = bernom; -+ p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; -+ p->pre_bit_count.stat[0].uvalue = berdenom; -+ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->post_bit_error.stat[0].uvalue = ber; -+ } -+ -+ return 0; -+} -+ -+static struct dvb_frontend_ops common_ops_2843 = { -+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 }, -+ .info = { -+ .name = "CXD2843 DVB-C/C2 DVB-T/T2", -+ .frequency_stepsize = 166667, /* DVB-T only */ -+ .frequency_min = 47000000, /* DVB-T: 47125000 */ -+ .frequency_max = 865000000, /* DVB-C: 862000000 */ -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | -+ FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | -+ FE_CAN_QAM_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_4_5 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION -+ }, -+ .release = release, -+ .sleep = sleep, -+ .i2c_gate_ctrl = gate_ctrl, -+ .set_frontend = set_parameters, -+ -+ .read_status = read_status, -+ .get_frontend = get_frontend, -+#ifdef USE_ALGO -+ .get_frontend_algo = get_algo, -+ .search = search, -+ .tune = tune, -+#endif -+}; -+ -+static struct dvb_frontend_ops common_ops_2837 = { -+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, -+ .info = { -+ .name = "CXD2837 DVB-C DVB-T/T2", -+ .frequency_stepsize = 166667, /* DVB-T only */ -+ .frequency_min = 47000000, /* DVB-T: 47125000 */ -+ .frequency_max = 865000000, /* DVB-C: 862000000 */ -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | -+ FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | -+ FE_CAN_QAM_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_4_5 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION -+ }, -+ .release = release, -+ .sleep = sleep, -+ .i2c_gate_ctrl = gate_ctrl, -+ .set_frontend = set_parameters, -+ -+ .read_status = read_status, -+ .get_frontend = get_frontend, -+#ifdef USE_ALGO -+ .get_frontend_algo = get_algo, -+ .search = search, -+ .tune = tune, -+#endif -+}; -+ -+static struct dvb_frontend_ops common_ops_2838 = { -+ .delsys = { SYS_ISDBT }, -+ .info = { -+ .name = "CXD2838 ISDB-T", -+ .frequency_stepsize = 166667, -+ .frequency_min = 47000000, -+ .frequency_max = 865000000, -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | -+ FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION -+ }, -+ .release = release, -+ .sleep = sleep, -+ .i2c_gate_ctrl = gate_ctrl, -+ .set_frontend = set_parameters, -+ -+ .read_status = read_status, -+#ifdef USE_ALGO -+ .get_frontend_algo = get_algo, -+ .search = search, -+ .tune = tune, -+#endif -+}; -+ -+static int probe(struct cxd_state *state) -+{ -+ u8 ChipID = 0x00; -+ int status; -+ -+ status = readregst(state, 0x00, 0xFD, &ChipID, 1); -+ -+ if (status) -+ status = readregsx(state, 0x00, 0xFD, &ChipID, 1); -+ if (status) -+ return status; -+ -+ /*printk("ChipID = %02X\n", ChipID);*/ -+ switch (ChipID) { -+ case 0xa4: -+ state->type = CXD2843; -+ memcpy(&state->frontend.ops, &common_ops_2843, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ case 0xb1: -+ state->type = CXD2837; -+ memcpy(&state->frontend.ops, &common_ops_2837, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ case 0xb0: -+ state->type = CXD2838; -+ memcpy(&state->frontend.ops, &common_ops_2838, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ default: -+ return -ENODEV; -+ } -+ -+ pr_info("%s with ChipID %02X found at adr %02X on %s\n", -+ state->frontend.ops.info.name, ChipID, state->adrt, -+ dev_name(&state->i2c->dev)); -+ -+ state->frontend.demodulator_priv = state; -+ return 0; -+} -+ -+struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, -+ struct cxd2843_cfg *cfg) -+{ -+ struct cxd_state *state = NULL; -+ -+ state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->i2c = i2c; -+ init_state(state, cfg); -+ if (probe(state) == 0) { -+ init(state); -+ return &state->frontend; -+ } -+ pr_err("No supported demodulator found at adr %02X on %s\n", -+ cfg->adr, dev_name(&i2c->dev)); -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL(cxd2843_attach); -+ -+MODULE_DESCRIPTION("CXD2843/37/38 driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h -new file mode 100644 -index 0000000..2467a6b ---- /dev/null -+++ b/drivers/media/dvb-frontends/cxd2843.h -@@ -0,0 +1,30 @@ -+#ifndef _CXD2843_H_ -+#define _CXD2843_H_ -+ -+#include -+#include -+ -+struct cxd2843_cfg { -+ u8 adr; -+ u32 ts_clock; -+ u8 parallel; -+}; -+ -+#if IS_REACHABLE(CONFIG_DVB_CXD2843) -+ -+extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, -+ struct cxd2843_cfg *cfg); -+ -+ -+#else -+ -+static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, -+ struct cxd2843_cfg *cfg) -+{ -+ pr_warn("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif /* CONFIG_DVB_CXD2843 */ -+ -+#endif /* _CXD2843_H_ */ -diff --git a/drivers/media/dvb-frontends/mxl5xx.c b/drivers/media/dvb-frontends/mxl5xx.c -new file mode 100644 -index 0000000..4413fd2 ---- /dev/null -+++ b/drivers/media/dvb-frontends/mxl5xx.c -@@ -0,0 +1,1749 @@ -+/* -+ * Driver for the Maxlinear MX58x family of tuners/demods -+ * -+ * Copyright (C) 2014-2015 Ralph Metzler -+ * Marcus Metzler -+ * developed for Digital Devices GmbH -+ * -+ * based on code: -+ * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved -+ * which was released under GPL V2 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#undef pr_fmt -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "mxl5xx.h" -+#include "mxl5xx_regs.h" -+#include "mxl5xx_defs.h" -+ -+#define BYTE0(v) ((v >> 0) & 0xff) -+#define BYTE1(v) ((v >> 8) & 0xff) -+#define BYTE2(v) ((v >> 16) & 0xff) -+#define BYTE3(v) ((v >> 24) & 0xff) -+ -+ -+LIST_HEAD(mxllist); -+ -+struct mxl_base { -+ struct list_head mxllist; -+ struct list_head mxls; -+ -+ u8 adr; -+ struct i2c_adapter *i2c; -+ -+ u32 count; -+ u32 type; -+ u32 sku_type; -+ u32 chipversion; -+ u32 clock; -+ u32 fwversion; -+ -+ u8 *ts_map; -+ u8 can_clkout; -+ u8 chan_bond; -+ u8 demod_num; -+ u8 tuner_num; -+ -+ unsigned long next_tune; -+ -+ struct mutex i2c_lock; -+ struct mutex status_lock; -+ struct mutex tune_lock; -+ -+ u8 buf[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; -+ -+ u32 cmd_size; -+ u8 cmd_data[MAX_CMD_DATA]; -+}; -+ -+struct mxl { -+ struct list_head mxl; -+ -+ struct mxl_base *base; -+ struct dvb_frontend fe; -+ u32 demod; -+ u32 tuner; -+ u32 tuner_in_use; -+ -+ unsigned long tune_time; -+}; -+ -+static void convert_endian(u8 flag, u32 size, u8 *d) -+{ -+ u32 i; -+ -+ if (!flag) -+ return; -+ for (i = 0; i < (size & ~3); i += 4) { -+ d[i + 0] ^= d[i + 3]; -+ d[i + 3] ^= d[i + 0]; -+ d[i + 0] ^= d[i + 3]; -+ -+ d[i + 1] ^= d[i + 2]; -+ d[i + 2] ^= d[i + 1]; -+ d[i + 1] ^= d[i + 2]; -+ } -+ -+ switch (size & 3) { -+ case 0: -+ case 1: -+ /* do nothing */ -+ break; -+ case 2: -+ d[i + 0] ^= d[i + 1]; -+ d[i + 1] ^= d[i + 0]; -+ d[i + 0] ^= d[i + 1]; -+ break; -+ -+ case 3: -+ d[i + 0] ^= d[i + 2]; -+ d[i + 2] ^= d[i + 0]; -+ d[i + 0] ^= d[i + 2]; -+ break; -+ } -+ -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, -+ u8 *data, u32 len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_read(struct i2c_adapter *adap, u8 adr, -+ u8 *data, u32 len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = I2C_M_RD, -+ .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ -+static int i2cread(struct mxl *state, u8 *data, int len) -+{ -+ return i2c_read(state->base->i2c, state->base->adr, data, len); -+} -+ -+static int i2cwrite(struct mxl *state, u8 *data, int len) -+{ -+ return i2c_write(state->base->i2c, state->base->adr, data, len); -+} -+ -+static int read_register_unlocked(struct mxl *state, u32 reg, u32 *val) -+{ -+ int stat; -+ u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = { -+ MXL_HYDRA_PLID_REG_READ, 0x04, -+ GET_BYTE(reg, 0), GET_BYTE(reg, 1), -+ GET_BYTE(reg, 2), GET_BYTE(reg, 3), -+ }; -+ -+ stat = i2cwrite(state, data, -+ MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE); -+ if (stat) -+ pr_err("i2c read error 1\n"); -+ if (!stat) -+ stat = i2cread(state, (u8 *) val, MXL_HYDRA_REG_SIZE_IN_BYTES); -+ le32_to_cpus(val); -+ if (stat) -+ pr_err("i2c read error 2\n"); -+ return stat; -+} -+ -+ -+#define DMA_I2C_INTERRUPT_ADDR 0x8000011C -+#define DMA_INTR_PROT_WR_CMP 0x08 -+ -+static int send_command(struct mxl *state, u32 size, u8 *buf) -+{ -+ int stat; -+ u32 val, count = 10; -+ -+ mutex_lock(&state->base->i2c_lock); -+ if (state->base->fwversion > 0x02010109) { -+ read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, &val); -+ if (DMA_INTR_PROT_WR_CMP & val) -+ pr_info("send_command busy\n"); -+ while ((DMA_INTR_PROT_WR_CMP & val) && --count) { -+ mutex_unlock(&state->base->i2c_lock); -+ usleep_range(1000, 2000); -+ mutex_lock(&state->base->i2c_lock); -+ read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, &val); -+ } -+ if (!count) { -+ pr_info("send_command busy\n"); -+ mutex_unlock(&state->base->i2c_lock); -+ return -EBUSY; -+ } -+ } -+ stat = i2cwrite(state, buf, size); -+ mutex_unlock(&state->base->i2c_lock); -+ return stat; -+} -+ -+static int write_register(struct mxl *state, u32 reg, u32 val) -+{ -+ int stat; -+ u8 data[MXL_HYDRA_REG_WRITE_LEN] = { -+ MXL_HYDRA_PLID_REG_WRITE, 0x08, -+ BYTE0(reg), BYTE1(reg), BYTE2(reg), BYTE3(reg), -+ BYTE0(val), BYTE1(val), BYTE2(val), BYTE3(val), -+ }; -+ mutex_lock(&state->base->i2c_lock); -+ stat = i2cwrite(state, data, sizeof(data)); -+ mutex_unlock(&state->base->i2c_lock); -+ if (stat) -+ pr_err("i2c write error\n"); -+ return stat; -+} -+ -+static int write_firmware_block(struct mxl *state, -+ u32 reg, u32 size, u8 *regDataPtr) -+{ -+ int stat; -+ u8 *buf = state->base->buf; -+ -+ mutex_lock(&state->base->i2c_lock); -+ buf[0] = MXL_HYDRA_PLID_REG_WRITE; -+ buf[1] = size + 4; -+ buf[2] = GET_BYTE(reg, 0); -+ buf[3] = GET_BYTE(reg, 1); -+ buf[4] = GET_BYTE(reg, 2); -+ buf[5] = GET_BYTE(reg, 3); -+ memcpy(&buf[6], regDataPtr, size); -+ stat = i2cwrite(state, buf, -+ MXL_HYDRA_I2C_HDR_SIZE + -+ MXL_HYDRA_REG_SIZE_IN_BYTES + size); -+ mutex_unlock(&state->base->i2c_lock); -+ if (stat) -+ pr_err("fw block write failed\n"); -+ return stat; -+} -+ -+static int read_register(struct mxl *state, u32 reg, u32 *val) -+{ -+ int stat; -+ u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = { -+ MXL_HYDRA_PLID_REG_READ, 0x04, -+ GET_BYTE(reg, 0), GET_BYTE(reg, 1), -+ GET_BYTE(reg, 2), GET_BYTE(reg, 3), -+ }; -+ -+ mutex_lock(&state->base->i2c_lock); -+ stat = i2cwrite(state, data, -+ MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE); -+ if (stat) -+ pr_err("i2c read error 1\n"); -+ if (!stat) -+ stat = i2cread(state, (u8 *) val, MXL_HYDRA_REG_SIZE_IN_BYTES); -+ mutex_unlock(&state->base->i2c_lock); -+ le32_to_cpus(val); -+ if (stat) -+ pr_err("i2c read error 2\n"); -+ return stat; -+} -+ -+static int read_register_block(struct mxl *state, u32 reg, u32 size, u8 *data) -+{ -+ int stat; -+ u8 *buf = state->base->buf; -+ -+ mutex_lock(&state->base->i2c_lock); -+ -+ buf[0] = MXL_HYDRA_PLID_REG_READ; -+ buf[1] = size + 4; -+ buf[2] = GET_BYTE(reg, 0); -+ buf[3] = GET_BYTE(reg, 1); -+ buf[4] = GET_BYTE(reg, 2); -+ buf[5] = GET_BYTE(reg, 3); -+ stat = i2cwrite(state, buf, -+ MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES); -+ if (!stat) { -+ stat = i2cread(state, data, size); -+ convert_endian(MXL_ENABLE_BIG_ENDIAN, size, data); -+ } -+ mutex_unlock(&state->base->i2c_lock); -+ return stat; -+} -+ -+static int read_by_mnemonic(struct mxl *state, -+ u32 reg, u8 lsbloc, u8 numofbits, u32 *val) -+{ -+ u32 data = 0, mask = 0; -+ int stat; -+ -+ stat = read_register(state, reg, &data); -+ if (stat) -+ return stat; -+ mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); -+ data &= mask; -+ data >>= lsbloc; -+ *val = data; -+ return 0; -+} -+ -+ -+static int update_by_mnemonic(struct mxl *state, -+ u32 reg, u8 lsbloc, u8 numofbits, u32 val) -+{ -+ u32 data, mask; -+ int stat; -+ -+ stat = read_register(state, reg, &data); -+ if (stat) -+ return stat; -+ mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); -+ data = (data & ~mask) | ((val << lsbloc) & mask); -+ stat = write_register(state, reg, data); -+ return stat; -+} -+ -+static int firmware_is_alive(struct mxl *state) -+{ -+ u32 hb0, hb1; -+ -+ if (read_register(state, HYDRA_HEAR_BEAT, &hb0)) -+ return 0; -+ msleep(20); -+ if (read_register(state, HYDRA_HEAR_BEAT, &hb1)) -+ return 0; -+ if (hb1 == hb0) -+ return 0; -+ return 1; -+} -+ -+static int init(struct dvb_frontend *fe) -+{ -+ return 0; -+} -+ -+static void release(struct dvb_frontend *fe) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ -+ list_del(&state->mxl); -+ /* Release one frontend, two more shall take its place! */ -+ state->base->count--; -+ if (state->base->count == 0) { -+ list_del(&state->base->mxllist); -+ kfree(state->base); -+ } -+ kfree(state); -+} -+ -+static int get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+ -+static int CfgDemodAbortTune(struct mxl *state) -+{ -+ MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd; -+ u8 cmdSize = sizeof(abortTuneCmd); -+ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; -+ -+ abortTuneCmd.demodId = state->demod; -+ BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, cmdSize, &abortTuneCmd, cmdBuff); -+ return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); -+} -+ -+static int send_master_cmd(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *cmd) -+{ -+ /*struct mxl *state = fe->demodulator_priv;*/ -+ -+ return 0; /*CfgDemodAbortTune(state);*/ -+} -+ -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ MXL_HYDRA_DEMOD_PARAM_T demodChanCfg; -+ u8 cmdSize = sizeof(demodChanCfg); -+ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; -+ u32 srange = 10; -+ int stat; -+ -+ if (p->frequency < 950000 || p->frequency > 2150000) -+ return -EINVAL; -+ if (p->symbol_rate < 1000000 || p->symbol_rate > 45000000) -+ return -EINVAL; -+ -+ /* CfgDemodAbortTune(state); */ -+ -+ switch (p->delivery_system) { -+ case SYS_DSS: -+ demodChanCfg.standard = MXL_HYDRA_DSS; -+ demodChanCfg.rollOff = MXL_HYDRA_ROLLOFF_AUTO; -+ break; -+ case SYS_DVBS: -+ srange = p->symbol_rate / 1000000; -+ if (srange > 10) -+ srange = 10; -+ demodChanCfg.standard = MXL_HYDRA_DVBS; -+ demodChanCfg.rollOff = MXL_HYDRA_ROLLOFF_0_35; -+ demodChanCfg.modulationScheme = MXL_HYDRA_MOD_QPSK; -+ demodChanCfg.pilots = MXL_HYDRA_PILOTS_OFF; -+ break; -+ case SYS_DVBS2: -+ demodChanCfg.standard = MXL_HYDRA_DVBS2; -+ demodChanCfg.rollOff = MXL_HYDRA_ROLLOFF_AUTO; -+ demodChanCfg.modulationScheme = MXL_HYDRA_MOD_AUTO; -+ demodChanCfg.pilots = MXL_HYDRA_PILOTS_AUTO; -+ /* cfg_scrambler(state); */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ demodChanCfg.tunerIndex = state->tuner; -+ demodChanCfg.demodIndex = state->demod; -+ demodChanCfg.frequencyInHz = p->frequency * 1000; -+ demodChanCfg.symbolRateInHz = p->symbol_rate; -+ demodChanCfg.maxCarrierOffsetInMHz = srange; -+ demodChanCfg.spectrumInversion = MXL_HYDRA_SPECTRUM_AUTO; -+ demodChanCfg.fecCodeRate = MXL_HYDRA_FEC_AUTO; -+ -+ mutex_lock(&state->base->tune_lock); -+ if (time_after(jiffies + msecs_to_jiffies(200), state->base->next_tune)) -+ while (time_before(jiffies, state->base->next_tune)) -+ usleep_range(10000, 11000); -+ state->base->next_tune = jiffies + msecs_to_jiffies(100); -+ state->tuner_in_use = state->tuner; -+ BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE, -+ cmdSize, &demodChanCfg, cmdBuff); -+ stat = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); -+ mutex_unlock(&state->base->tune_lock); -+ return stat; -+} -+ -+static int enable_tuner(struct mxl *state, u32 tuner, u32 enable); -+ -+static int sleep(struct dvb_frontend *fe) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ struct mxl *p; -+ -+ CfgDemodAbortTune(state); -+ if (state->tuner_in_use != 0xffffffff) { -+ mutex_lock(&state->base->tune_lock); -+ state->tuner_in_use = 0xffffffff; -+ list_for_each_entry(p, &state->base->mxls, mxl) { -+ if (p->tuner_in_use == state->tuner) -+ break; -+ } -+ if (&p->mxl == &state->base->mxls) -+ enable_tuner(state, state->tuner, 0); -+ mutex_unlock(&state->base->tune_lock); -+ } -+ return 0; -+} -+ -+static int read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ int stat; -+ u32 regData = 0; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ -+ mutex_lock(&state->base->status_lock); -+ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); -+ stat = read_register(state, (HYDRA_DMD_SNR_ADDR_OFFSET + -+ HYDRA_DMD_STATUS_OFFSET(state->demod)), -+ ®Data); -+ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); -+ mutex_unlock(&state->base->status_lock); -+ -+ p->cnr.len = 1; -+ p->cnr.stat[0].scale = FE_SCALE_DECIBEL; -+ p->cnr.stat[0].svalue = (s16)regData * 10; -+ -+ if (regData > 2000) regData = 2000; -+ *snr = (s16)(regData/10) * 328; /* 20dB = 100% */ -+ -+ return stat; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ u32 reg[8]; -+ int stat; -+ -+ mutex_lock(&state->base->status_lock); -+ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); -+ stat = read_register_block(state, -+ (HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET + -+ HYDRA_DMD_STATUS_OFFSET(state->demod)), -+ (4 * sizeof(u32)), -+ (u8 *) ®[0]); -+ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); -+ -+ switch (p->delivery_system) { -+ case SYS_DSS: -+ case SYS_DVBS: -+ p->pre_bit_error.len = 1; -+ p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->pre_bit_error.stat[0].uvalue = reg[2]; -+ p->pre_bit_count.len = 1; -+ p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; -+ p->pre_bit_count.stat[0].uvalue = reg[3]; -+ break; -+ default: -+ break; -+ } -+ -+ stat = read_register_block(state, -+ (HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET + -+ HYDRA_DMD_STATUS_OFFSET(state->demod)), -+ (7 * sizeof(u32)), -+ (u8 *) ®[0]); -+ -+ switch (p->delivery_system) { -+ case SYS_DSS: -+ case SYS_DVBS: -+ p->post_bit_error.len = 1; -+ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->post_bit_error.stat[0].uvalue = reg[5]; -+ p->post_bit_count.len = 1; -+ p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; -+ p->post_bit_count.stat[0].uvalue = reg[6]; -+ break; -+ case SYS_DVBS2: -+ p->post_bit_error.len = 1; -+ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->post_bit_error.stat[0].uvalue = reg[1]; -+ p->post_bit_count.len = 1; -+ p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; -+ p->post_bit_count.stat[0].uvalue = reg[2]; -+ break; -+ default: -+ break; -+ } -+ -+ *ber = p->post_bit_error.stat[0].uvalue; -+ -+ mutex_unlock(&state->base->status_lock); -+ -+ return 0; -+} -+ -+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ int stat; -+ u32 regData = 0; -+ -+ mutex_lock(&state->base->status_lock); -+ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); -+ stat = read_register(state, (HYDRA_DMD_STATUS_INPUT_POWER_ADDR + -+ HYDRA_DMD_STATUS_OFFSET(state->demod)), -+ ®Data); -+ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); -+ mutex_unlock(&state->base->status_lock); -+ -+ p->strength.len = 1; -+ p->strength.stat[0].scale = FE_SCALE_DECIBEL; -+ p->strength.stat[0].svalue = (s16)regData *10; -+ -+ *strength = (100 + (s16)regData/100) * 656; -+ return stat; -+} -+ -+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ return 0; -+} -+ -+static int read_status(struct dvb_frontend *fe, enum fe_status *status) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ -+ int stat; -+ u32 regData = 0; -+ u16 val; -+ -+ mutex_lock(&state->base->status_lock); -+ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); -+ stat = read_register(state, (HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET + -+ HYDRA_DMD_STATUS_OFFSET(state->demod)), -+ ®Data); -+ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); -+ mutex_unlock(&state->base->status_lock); -+ -+ *status = (regData == 1) ? 0x1f : 0; -+ read_signal_strength(fe, &val); -+ if (*status) { -+ read_snr(fe, &val); -+ read_ber(fe, ®Data); -+ } -+ -+ return 0; -+} -+ -+static int tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, -+ unsigned int *delay, enum fe_status *status) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ int r = 0; -+ -+ *delay = HZ / 2; -+ if (re_tune) { -+ r = set_parameters(fe); -+ if (r) -+ return r; -+ state->tune_time = jiffies; -+ return 0; -+ } -+ if (*status & FE_HAS_LOCK) -+ return 0; -+ -+ r = read_status(fe, status); -+ if (r) -+ return r; -+ -+ return 0; -+} -+ -+static enum fe_code_rate conv_fec(MXL_HYDRA_FEC_E fec) -+{ -+ enum fe_code_rate fec2fec[11] = { -+ FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3, -+ FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, -+ FEC_7_8, FEC_8_9, FEC_9_10 -+ }; -+ -+ if (fec > MXL_HYDRA_FEC_9_10) -+ return FEC_NONE; -+ return fec2fec[fec]; -+} -+ -+static int get_frontend(struct dvb_frontend *fe, -+ struct dtv_frontend_properties *p) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ u32 regData[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE]; -+ u32 freq; -+ int stat; -+ -+ mutex_lock(&state->base->status_lock); -+ HYDRA_DEMOD_STATUS_LOCK(state, state->demod); -+ stat = read_register_block(state, -+ (HYDRA_DMD_STANDARD_ADDR_OFFSET + -+ HYDRA_DMD_STATUS_OFFSET(state->demod)), -+ (MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), /* 25 * 4 bytes */ -+ (u8 *) ®Data[0]); -+ /* read demod channel parameters */ -+ stat = read_register_block(state, -+ (HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR + -+ HYDRA_DMD_STATUS_OFFSET(state->demod)), -+ (4), /* 4 bytes */ -+ (u8 *) &freq); -+ HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); -+ mutex_unlock(&state->base->status_lock); -+ -+ pr_debug("freq=%u delsys=%u srate=%u\n", -+ freq * 1000, regData[DMD_STANDARD_ADDR], -+ regData[DMD_SYMBOL_RATE_ADDR]); -+ p->symbol_rate = regData[DMD_SYMBOL_RATE_ADDR]; -+ p->frequency = freq; -+ /* -+ * p->delivery_system = (MXL_HYDRA_BCAST_STD_E )regData[DMD_STANDARD_ADDR]; -+ * p->inversion = (MXL_HYDRA_SPECTRUM_E )regData[DMD_SPECTRUM_INVERSION_ADDR]; -+ * freqSearchRangeKHz = (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]); -+ */ -+ -+ p->fec_inner = conv_fec(regData[DMD_FEC_CODE_RATE_ADDR]); -+ switch (p->delivery_system) { -+ case SYS_DSS: -+ break; -+ case SYS_DVBS2: -+ switch ((MXL_HYDRA_PILOTS_E) regData[DMD_DVBS2_PILOT_ON_OFF_ADDR]) { -+ case MXL_HYDRA_PILOTS_OFF: -+ p->pilot = PILOT_OFF; -+ break; -+ case MXL_HYDRA_PILOTS_ON: -+ p->pilot = PILOT_ON; -+ break; -+ default: -+ break; -+ } -+ case SYS_DVBS: -+ switch ((MXL_HYDRA_MODULATION_E) regData[DMD_MODULATION_SCHEME_ADDR]) { -+ case MXL_HYDRA_MOD_QPSK: -+ p->modulation = QPSK; -+ break; -+ case MXL_HYDRA_MOD_8PSK: -+ p->modulation = PSK_8; -+ break; -+ default: -+ break; -+ } -+ switch ((MXL_HYDRA_ROLLOFF_E) regData[DMD_SPECTRUM_ROLL_OFF_ADDR]) { -+ case MXL_HYDRA_ROLLOFF_0_20: -+ p->rolloff = ROLLOFF_20; -+ break; -+ case MXL_HYDRA_ROLLOFF_0_35: -+ p->rolloff = ROLLOFF_35; -+ break; -+ case MXL_HYDRA_ROLLOFF_0_25: -+ p->rolloff = ROLLOFF_25; -+ break; -+ default: -+ break; -+ } -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static int set_input(struct dvb_frontend *fe, int input) -+{ -+ struct mxl *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ -+ state->tuner = p->input = input; -+ return 0; -+} -+ -+static struct dvb_frontend_ops mxl_ops = { -+ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, -+ .xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */ -+ .info = { -+ .name = "MXL5XX", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_stepsize = 0, -+ .frequency_tolerance = 0, -+ .symbol_rate_min = 1000000, -+ .symbol_rate_max = 45000000, -+ .caps = FE_CAN_INVERSION_AUTO | -+ FE_CAN_FEC_AUTO | -+ FE_CAN_QPSK | -+ FE_CAN_2G_MODULATION -+ }, -+ .init = init, -+ .release = release, -+ .get_frontend_algo = get_algo, -+ .tune = tune, -+ .read_status = read_status, -+ .sleep = sleep, -+ .read_snr = read_snr, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_ucblocks = read_ucblocks, -+ .get_frontend = get_frontend, -+ .set_input = set_input, -+ .diseqc_send_master_cmd = send_master_cmd, -+}; -+ -+static struct mxl_base *match_base(struct i2c_adapter *i2c, u8 adr) -+{ -+ struct mxl_base *p; -+ -+ list_for_each_entry(p, &mxllist, mxllist) -+ if (p->i2c == i2c && p->adr == adr) -+ return p; -+ return NULL; -+} -+ -+static void cfg_dev_xtal(struct mxl *state, u32 freq, u32 cap, u32 enable) -+{ -+ if (state->base->can_clkout || !enable) -+ SET_REG_FIELD_DATA(AFE_REG_D2A_XTAL_EN_CLKOUT_1P8, enable); -+ -+ if (freq == 24000000) -+ write_register(state, HYDRA_CRYSTAL_SETTING, 0); -+ else -+ write_register(state, HYDRA_CRYSTAL_SETTING, 1); -+ -+ write_register(state, HYDRA_CRYSTAL_CAP, cap); -+} -+ -+static u32 get_big_endian(u8 numOfBits, const u8 buf[]) -+{ -+ u32 retValue = 0; -+ -+ switch (numOfBits) { -+ case 24: -+ retValue = (((u32) buf[0]) << 16) | -+ (((u32) buf[1]) << 8) | buf[2]; -+ break; -+ case 32: -+ retValue = (((u32) buf[0]) << 24) | -+ (((u32) buf[1]) << 16) | -+ (((u32) buf[2]) << 8) | buf[3]; -+ break; -+ default: -+ break; -+ } -+ -+ return retValue; -+} -+ -+static int write_fw_segment(struct mxl *state, -+ u32 MemAddr, u32 totalSize, u8 *dataPtr) -+{ -+ int status; -+ u32 dataCount = 0; -+ u32 size = 0; -+ u32 origSize = 0; -+ u8 *wBufPtr = NULL; -+ u32 blockSize = ((MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - -+ (MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4; -+ u8 wMsgBuffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - -+ (MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)]; -+ -+ do { -+ size = origSize = (((u32)(dataCount + blockSize)) > totalSize) ? -+ (totalSize - dataCount) : blockSize; -+ -+ if (origSize & 3) -+ size = (origSize + 4) & ~3; -+ wBufPtr = &wMsgBuffer[0]; -+ memset((void *) wBufPtr, 0, size); -+ memcpy((void *) wBufPtr, (void *) dataPtr, origSize); -+ convert_endian(1, size, wBufPtr); -+ status = write_firmware_block(state, MemAddr, size, wBufPtr); -+ if (status) -+ return status; -+ dataCount += size; -+ MemAddr += size; -+ dataPtr += size; -+ } while (dataCount < totalSize); -+ -+ return status; -+} -+ -+static int do_firmware_download(struct mxl *state, u8 *mbinBufferPtr, u32 mbinBufferSize) -+ -+{ -+ int status; -+ u32 index = 0; -+ u32 segLength = 0; -+ u32 segAddress = 0; -+ MBIN_FILE_T *mbinPtr = (MBIN_FILE_T *)mbinBufferPtr; -+ MBIN_SEGMENT_T *segmentPtr; -+ MXL_BOOL_E xcpuFwFlag = MXL_FALSE; -+ -+ if (mbinPtr->header.id != MBIN_FILE_HEADER_ID) { -+ pr_err("%s: Invalid file header ID (%c)\n", -+ __func__, mbinPtr->header.id); -+ return -EINVAL; -+ } -+ status = write_register(state, FW_DL_SIGN_ADDR, 0); -+ if (status) -+ return status; -+ segmentPtr = (MBIN_SEGMENT_T *) (&mbinPtr->data[0]); -+ for (index = 0; index < mbinPtr->header.numSegments; index++) { -+ if (segmentPtr->header.id != MBIN_SEGMENT_HEADER_ID) { -+ pr_err("%s: Invalid segment header ID (%c)\n", -+ __func__, segmentPtr->header.id); -+ return -EINVAL; -+ } -+ segLength = get_big_endian(24, &(segmentPtr->header.len24[0])); -+ segAddress = get_big_endian(32, &(segmentPtr->header.address[0])); -+ -+ if (state->base->type == MXL_HYDRA_DEVICE_568) { -+ if ((((segAddress & 0x90760000) == 0x90760000) || -+ ((segAddress & 0x90740000) == 0x90740000)) && -+ (xcpuFwFlag == MXL_FALSE)) { -+ SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N, 1); -+ msleep(200); -+ write_register(state, 0x90720000, 0); -+ usleep_range(10000, 11000); -+ xcpuFwFlag = MXL_TRUE; -+ } -+ status = write_fw_segment(state, segAddress, -+ segLength, (u8 *) segmentPtr->data); -+ } else { -+ if (((segAddress & 0x90760000) != 0x90760000) && -+ ((segAddress & 0x90740000) != 0x90740000)) -+ status = write_fw_segment(state, segAddress, -+ segLength, (u8 *) segmentPtr->data); -+ } -+ if (status) -+ return status; -+ segmentPtr = (MBIN_SEGMENT_T *) -+ &(segmentPtr->data[((segLength + 3) / 4) * 4]); -+ } -+ return status; -+} -+ -+static int check_fw(u8 *mbin, u32 mbin_len) -+{ -+ MBIN_FILE_HEADER_T *fh = (MBIN_FILE_HEADER_T *) mbin; -+ u32 flen = (fh->imageSize24[0] << 16) | -+ (fh->imageSize24[1] << 8) | fh->imageSize24[2]; -+ u8 *fw, cs = 0; -+ u32 i; -+ -+ if (fh->id != 'M' || fh->fmtVersion != '1' || flen > 0x3FFF0) { -+ pr_info("Invalid FW Header\n"); -+ return -1; -+ } -+ fw = mbin + sizeof(MBIN_FILE_HEADER_T); -+ for (i = 0; i < flen; i += 1) -+ cs += fw[i]; -+ if (cs != fh->imageChecksum) { -+ pr_info("Invalid FW Checksum\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len) -+{ -+ int status; -+ u32 regData = 0; -+ MXL_HYDRA_SKU_COMMAND_T devSkuCfg; -+ u8 cmdSize = sizeof(MXL_HYDRA_SKU_COMMAND_T); -+ u8 cmdBuff[sizeof(MXL_HYDRA_SKU_COMMAND_T) + 6]; -+ -+ if (check_fw(mbin, mbin_len)) -+ return -1; -+ -+ /* put CPU into reset */ -+ status = SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N, 0); -+ if (status) -+ return status; -+ usleep_range(1000, 2000); -+ -+ /* Reset TX FIFO's, BBAND, XBAR */ -+ status = write_register(state, HYDRA_RESET_TRANSPORT_FIFO_REG, -+ HYDRA_RESET_TRANSPORT_FIFO_DATA); -+ if (status) -+ return status; -+ status = write_register(state, HYDRA_RESET_BBAND_REG, -+ HYDRA_RESET_BBAND_DATA); -+ if (status) -+ return status; -+ status = write_register(state, HYDRA_RESET_XBAR_REG, -+ HYDRA_RESET_XBAR_DATA); -+ if (status) -+ return status; -+ -+ /* Disable clock to Baseband, Wideband, SerDes, Alias ext & Transport modules */ -+ status = write_register(state, HYDRA_MODULES_CLK_2_REG, HYDRA_DISABLE_CLK_2); -+ if (status) -+ return status; -+ /* Clear Software & Host interrupt status - (Clear on read) */ -+ status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, ®Data); -+ if (status) -+ return status; -+ status = do_firmware_download(state, mbin, mbin_len); -+ if (status) -+ return status; -+ -+ if (state->base->type == MXL_HYDRA_DEVICE_568) { -+ usleep_range(10000, 11000); -+ -+ /* bring XCPU out of reset */ -+ status = write_register(state, 0x90720000, 1); -+ if (status) -+ return status; -+ msleep(500); -+ -+ /* Enable XCPU UART message processing in MCPU */ -+ status = write_register(state, 0x9076B510, 1); -+ if (status) -+ return status; -+ } else { -+ /* Bring CPU out of reset */ -+ status = SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N, 1); -+ if (status) -+ return status; -+ /* Wait until FW boots */ -+ msleep(150); -+ } -+ -+ /* Initilize XPT XBAR */ -+ status = write_register(state, XPT_DMD0_BASEADDR, 0x76543210); -+ if (status) -+ return status; -+ -+ if (!firmware_is_alive(state)) -+ return -1; -+ -+ pr_info("Hydra FW alive. Hail!\n"); -+ -+ /* sometimes register values are wrong shortly after first heart beats */ -+ msleep(50); -+ -+ devSkuCfg.skuType = state->base->sku_type; -+ BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE, -+ cmdSize, &devSkuCfg, cmdBuff); -+ status = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); -+ -+ return status; -+} -+ -+static int cfg_ts_pad_mux(struct mxl *state, MXL_BOOL_E enableSerialTS) -+{ -+ int status = 0; -+ u32 padMuxValue = 0; -+ -+ if (enableSerialTS == MXL_TRUE) { -+ padMuxValue = 0; -+ if ((state->base->type == MXL_HYDRA_DEVICE_541) || -+ (state->base->type == MXL_HYDRA_DEVICE_541S)) -+ padMuxValue = 2; -+ } else { -+ if ((state->base->type == MXL_HYDRA_DEVICE_581) || -+ (state->base->type == MXL_HYDRA_DEVICE_581S)) -+ padMuxValue = 2; -+ else -+ padMuxValue = 3; -+ } -+ -+ switch (state->base->type) { -+ case MXL_HYDRA_DEVICE_561: -+ case MXL_HYDRA_DEVICE_581: -+ case MXL_HYDRA_DEVICE_541: -+ case MXL_HYDRA_DEVICE_541S: -+ case MXL_HYDRA_DEVICE_561S: -+ case MXL_HYDRA_DEVICE_581S: -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL, padMuxValue); -+ break; -+ -+ case MXL_HYDRA_DEVICE_544: -+ case MXL_HYDRA_DEVICE_542: -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_01_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_02_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_03_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_04_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_08_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_27_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_28_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_29_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_30_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_32_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_33_PINMUX_SEL, 1); -+ if (enableSerialTS == MXL_ENABLE) { -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_09_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_10_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_11_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_12_PINMUX_SEL, 0); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_13_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL, 2); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL, 2); -+ } else { -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_09_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_10_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_11_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_12_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_13_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL, 3); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL, 1); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL, 1); -+ } -+ break; -+ -+ case MXL_HYDRA_DEVICE_568: -+ if (enableSerialTS == MXL_FALSE) { -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_02_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_03_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_04_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_05_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_06_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_07_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_08_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_09_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_10_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_11_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_12_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_13_PINMUX_SEL, 5); -+ -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL, padMuxValue); -+ -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_27_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_28_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_29_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_30_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_31_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_32_PINMUX_SEL, 5); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_33_PINMUX_SEL, 5); -+ } else { -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_09_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_10_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_11_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_12_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_13_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue); -+ } -+ break; -+ -+ -+ case MXL_HYDRA_DEVICE_584: -+ default: -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_09_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_10_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_11_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_12_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_13_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue); -+ status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue); -+ break; -+ } -+ return status; -+} -+ -+ -+static int set_drive_strength(struct mxl *state, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_E tsDriveStrength) -+{ -+ int stat = 0; -+ u32 val; -+ -+ read_register(state, 0x90000194, &val); -+ pr_info("DIGIO = %08x\n", val); -+ pr_info("set drive_strength = %u\n", tsDriveStrength); -+ -+ -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_00, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_05, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_06, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_11, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_12, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_13, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_14, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_16, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_17, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_18, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_22, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_23, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_24, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_25, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_29, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_30, tsDriveStrength); -+ stat |= SET_REG_FIELD_DATA(PAD_MUX_PAD_DRV_DIGIO_31, tsDriveStrength); -+ -+ return stat; -+} -+ -+ -+static int enable_tuner(struct mxl *state, u32 tuner, u32 enable) -+{ -+ int stat = 0; -+ MxL_HYDRA_TUNER_CMD ctrlTunerCmd; -+ u8 cmdSize = sizeof(ctrlTunerCmd); -+ u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; -+ u32 val, count = 10; -+ -+ ctrlTunerCmd.tunerId = tuner; -+ ctrlTunerCmd.enable = enable; -+ BUILD_HYDRA_CMD(MXL_HYDRA_TUNER_ACTIVATE_CMD, MXL_CMD_WRITE, -+ cmdSize, &ctrlTunerCmd, cmdBuff); -+ stat = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); -+ if (stat) -+ return stat; -+ read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); -+ while (--count && ((val >> tuner) & 1) != enable) { -+ msleep(20); -+ read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); -+ } -+ if (!count) -+ return -1; -+ read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); -+ pr_info("tuner %u ready = %u\n", tuner, (val >> tuner) & 1); -+ -+ return 0; -+} -+ -+ -+static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId, -+ MXL_HYDRA_MPEGOUT_PARAM_T *mpegOutParamPtr) -+{ -+ int status = 0; -+ u32 ncoCountMin = 0; -+ u32 clkType = 0; -+ -+ MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_SYNC_POLARITY0}, {XPT_SYNC_POLARITY1}, -+ {XPT_SYNC_POLARITY2}, {XPT_SYNC_POLARITY3}, -+ {XPT_SYNC_POLARITY4}, {XPT_SYNC_POLARITY5}, -+ {XPT_SYNC_POLARITY6}, {XPT_SYNC_POLARITY7} }; -+ MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_CLOCK_POLARITY0}, {XPT_CLOCK_POLARITY1}, -+ {XPT_CLOCK_POLARITY2}, {XPT_CLOCK_POLARITY3}, -+ {XPT_CLOCK_POLARITY4}, {XPT_CLOCK_POLARITY5}, -+ {XPT_CLOCK_POLARITY6}, {XPT_CLOCK_POLARITY7} }; -+ MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_VALID_POLARITY0}, {XPT_VALID_POLARITY1}, -+ {XPT_VALID_POLARITY2}, {XPT_VALID_POLARITY3}, -+ {XPT_VALID_POLARITY4}, {XPT_VALID_POLARITY5}, -+ {XPT_VALID_POLARITY6}, {XPT_VALID_POLARITY7} }; -+ MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_TS_CLK_PHASE0}, {XPT_TS_CLK_PHASE1}, -+ {XPT_TS_CLK_PHASE2}, {XPT_TS_CLK_PHASE3}, -+ {XPT_TS_CLK_PHASE4}, {XPT_TS_CLK_PHASE5}, -+ {XPT_TS_CLK_PHASE6}, {XPT_TS_CLK_PHASE7} }; -+ MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_LSB_FIRST0}, {XPT_LSB_FIRST1}, {XPT_LSB_FIRST2}, {XPT_LSB_FIRST3}, -+ {XPT_LSB_FIRST4}, {XPT_LSB_FIRST5}, {XPT_LSB_FIRST6}, {XPT_LSB_FIRST7} }; -+ MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_SYNC_FULL_BYTE0}, {XPT_SYNC_FULL_BYTE1}, -+ {XPT_SYNC_FULL_BYTE2}, {XPT_SYNC_FULL_BYTE3}, -+ {XPT_SYNC_FULL_BYTE4}, {XPT_SYNC_FULL_BYTE5}, -+ {XPT_SYNC_FULL_BYTE6}, {XPT_SYNC_FULL_BYTE7} }; -+ MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_ENABLE_OUTPUT0}, {XPT_ENABLE_OUTPUT1}, -+ {XPT_ENABLE_OUTPUT2}, {XPT_ENABLE_OUTPUT3}, -+ {XPT_ENABLE_OUTPUT4}, {XPT_ENABLE_OUTPUT5}, -+ {XPT_ENABLE_OUTPUT6}, {XPT_ENABLE_OUTPUT7} }; -+ MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_ERROR_REPLACE_SYNC0}, {XPT_ERROR_REPLACE_SYNC1}, -+ {XPT_ERROR_REPLACE_SYNC2}, {XPT_ERROR_REPLACE_SYNC3}, -+ {XPT_ERROR_REPLACE_SYNC4}, {XPT_ERROR_REPLACE_SYNC5}, -+ {XPT_ERROR_REPLACE_SYNC6}, {XPT_ERROR_REPLACE_SYNC7} }; -+ MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_ERROR_REPLACE_VALID0}, {XPT_ERROR_REPLACE_VALID1}, -+ {XPT_ERROR_REPLACE_VALID2}, {XPT_ERROR_REPLACE_VALID3}, -+ {XPT_ERROR_REPLACE_VALID4}, {XPT_ERROR_REPLACE_VALID5}, -+ {XPT_ERROR_REPLACE_VALID6}, {XPT_ERROR_REPLACE_VALID7} }; -+ MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_TS_CLK_OUT_EN0}, {XPT_TS_CLK_OUT_EN1}, -+ {XPT_TS_CLK_OUT_EN2}, {XPT_TS_CLK_OUT_EN3}, -+ {XPT_TS_CLK_OUT_EN4}, {XPT_TS_CLK_OUT_EN5}, -+ {XPT_TS_CLK_OUT_EN6}, {XPT_TS_CLK_OUT_EN7} }; -+ MXL_REG_FIELD_T xpt_nco_clock_rate[MXL_HYDRA_DEMOD_MAX] = { -+ {XPT_NCO_COUNT_MIN0}, {XPT_NCO_COUNT_MIN1}, -+ {XPT_NCO_COUNT_MIN2}, {XPT_NCO_COUNT_MIN3}, -+ {XPT_NCO_COUNT_MIN4}, {XPT_NCO_COUNT_MIN5}, -+ {XPT_NCO_COUNT_MIN6}, {XPT_NCO_COUNT_MIN7} }; -+ -+ demodId = state->base->ts_map[demodId]; -+ -+ if (mpegOutParamPtr->enable == MXL_ENABLE) { -+ if (mpegOutParamPtr->mpegMode == MXL_HYDRA_MPEG_MODE_PARALLEL) { -+ } else { -+ cfg_ts_pad_mux(state, MXL_TRUE); -+ SET_REG_FIELD_DATA(XPT_ENABLE_PARALLEL_OUTPUT, MXL_FALSE); -+ } -+ } -+ -+ ncoCountMin = (u32)(MXL_HYDRA_NCO_CLK/mpegOutParamPtr->maxMpegClkRate); -+ -+ if (state->base->chipversion >= 2) { -+ status |= update_by_mnemonic(state, -+ xpt_nco_clock_rate[demodId].regAddr, /* Reg Addr */ -+ xpt_nco_clock_rate[demodId].lsbPos, /* LSB pos */ -+ xpt_nco_clock_rate[demodId].numOfBits, /* Num of bits */ -+ ncoCountMin); /* Data */ -+ } else -+ SET_REG_FIELD_DATA(XPT_NCO_COUNT_MIN, ncoCountMin); -+ -+ if (mpegOutParamPtr->mpegClkType == MXL_HYDRA_MPEG_CLK_CONTINUOUS) -+ clkType = 1; -+ -+ if (mpegOutParamPtr->mpegMode < MXL_HYDRA_MPEG_MODE_PARALLEL) { -+ status |= update_by_mnemonic(state, -+ xpt_continuous_clock[demodId].regAddr, -+ xpt_continuous_clock[demodId].lsbPos, -+ xpt_continuous_clock[demodId].numOfBits, -+ clkType); -+ } else -+ SET_REG_FIELD_DATA(XPT_TS_CLK_OUT_EN_PARALLEL, clkType); -+ -+ status |= update_by_mnemonic(state, -+ xpt_sync_polarity[demodId].regAddr, -+ xpt_sync_polarity[demodId].lsbPos, -+ xpt_sync_polarity[demodId].numOfBits, -+ mpegOutParamPtr->mpegSyncPol); -+ -+ status |= update_by_mnemonic(state, -+ xpt_valid_polarity[demodId].regAddr, -+ xpt_valid_polarity[demodId].lsbPos, -+ xpt_valid_polarity[demodId].numOfBits, -+ mpegOutParamPtr->mpegValidPol); -+ -+ status |= update_by_mnemonic(state, -+ xpt_clock_polarity[demodId].regAddr, -+ xpt_clock_polarity[demodId].lsbPos, -+ xpt_clock_polarity[demodId].numOfBits, -+ mpegOutParamPtr->mpegClkPol); -+ -+ status |= update_by_mnemonic(state, -+ xpt_sync_byte[demodId].regAddr, -+ xpt_sync_byte[demodId].lsbPos, -+ xpt_sync_byte[demodId].numOfBits, -+ mpegOutParamPtr->mpegSyncPulseWidth); -+ -+ status |= update_by_mnemonic(state, -+ xpt_ts_clock_phase[demodId].regAddr, -+ xpt_ts_clock_phase[demodId].lsbPos, -+ xpt_ts_clock_phase[demodId].numOfBits, -+ mpegOutParamPtr->mpegClkPhase); -+ -+ status |= update_by_mnemonic(state, -+ xpt_lsb_first[demodId].regAddr, -+ xpt_lsb_first[demodId].lsbPos, -+ xpt_lsb_first[demodId].numOfBits, -+ mpegOutParamPtr->lsbOrMsbFirst); -+ -+ switch (mpegOutParamPtr->mpegErrorIndication) { -+ case MXL_HYDRA_MPEG_ERR_REPLACE_SYNC: -+ status |= update_by_mnemonic(state, -+ xpt_err_replace_sync[demodId].regAddr, -+ xpt_err_replace_sync[demodId].lsbPos, -+ xpt_err_replace_sync[demodId].numOfBits, -+ MXL_TRUE); -+ status |= update_by_mnemonic(state, -+ xpt_err_replace_valid[demodId].regAddr, -+ xpt_err_replace_valid[demodId].lsbPos, -+ xpt_err_replace_valid[demodId].numOfBits, -+ MXL_FALSE); -+ break; -+ -+ case MXL_HYDRA_MPEG_ERR_REPLACE_VALID: -+ status |= update_by_mnemonic(state, -+ xpt_err_replace_sync[demodId].regAddr, -+ xpt_err_replace_sync[demodId].lsbPos, -+ xpt_err_replace_sync[demodId].numOfBits, -+ MXL_FALSE); -+ -+ status |= update_by_mnemonic(state, -+ xpt_err_replace_valid[demodId].regAddr, -+ xpt_err_replace_valid[demodId].lsbPos, -+ xpt_err_replace_valid[demodId].numOfBits, -+ MXL_TRUE); -+ break; -+ -+ case MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED: -+ default: -+ status |= update_by_mnemonic(state, -+ xpt_err_replace_sync[demodId].regAddr, -+ xpt_err_replace_sync[demodId].lsbPos, -+ xpt_err_replace_sync[demodId].numOfBits, -+ MXL_FALSE); -+ -+ status |= update_by_mnemonic(state, -+ xpt_err_replace_valid[demodId].regAddr, -+ xpt_err_replace_valid[demodId].lsbPos, -+ xpt_err_replace_valid[demodId].numOfBits, -+ MXL_FALSE); -+ -+ break; -+ -+ } -+ -+ if (mpegOutParamPtr->mpegMode != MXL_HYDRA_MPEG_MODE_PARALLEL) { -+ status |= update_by_mnemonic(state, -+ xpt_enable_output[demodId].regAddr, -+ xpt_enable_output[demodId].lsbPos, -+ xpt_enable_output[demodId].numOfBits, -+ mpegOutParamPtr->enable); -+ } -+ return status; -+} -+ -+static int config_mux(struct mxl *state) -+{ -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT0, 0); -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT1, 0); -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT2, 0); -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT3, 0); -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT4, 0); -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT5, 0); -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT6, 0); -+ SET_REG_FIELD_DATA(XPT_ENABLE_OUTPUT7, 0); -+ SET_REG_FIELD_DATA(XPT_STREAM_MUXMODE0, 1); -+ SET_REG_FIELD_DATA(XPT_STREAM_MUXMODE1, 1); -+ return 0; -+} -+ -+static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg) -+{ -+ int stat = 0; -+ u8 *buf; -+ -+ if (cfg->fw) -+ return firmware_download(state, cfg->fw, cfg->fw_len); -+ -+ if (!cfg->fw_read) -+ return -1; -+ -+ buf = vmalloc(0x40000); -+ if (!buf) -+ return -ENOMEM; -+ -+ cfg->fw_read(cfg->fw_priv, buf, 0x40000); -+ stat = firmware_download(state, buf, 0x40000); -+ vfree(buf); -+ -+ return stat; -+} -+ -+static int validate_sku(struct mxl *state) -+{ -+ u32 padMuxBond, prcmChipId, prcmSoCId; -+ int status; -+ u32 type = state->base->type; -+ -+ status = GET_REG_FIELD_DATA(PAD_MUX_BOND_OPTION, &padMuxBond); -+ status |= GET_REG_FIELD_DATA(PRCM_PRCM_CHIP_ID, &prcmChipId); -+ status |= GET_REG_FIELD_DATA(PRCM_AFE_SOC_ID, &prcmSoCId); -+ if (status) -+ return -1; -+ -+ pr_info("padMuxBond=%08x, prcmChipId=%08x, prcmSoCId=%08x\n", -+ padMuxBond, prcmChipId, prcmSoCId); -+ -+ if (prcmChipId != 0x560) { -+ switch (padMuxBond) { -+ case MXL_HYDRA_SKU_ID_581: -+ if (type == MXL_HYDRA_DEVICE_581) -+ return 0; -+ if (type == MXL_HYDRA_DEVICE_581S) { -+ state->base->type = MXL_HYDRA_DEVICE_581; -+ return 0; -+ } -+ break; -+ case MXL_HYDRA_SKU_ID_584: -+ if (type == MXL_HYDRA_DEVICE_584) -+ return 0; -+ break; -+ case MXL_HYDRA_SKU_ID_544: -+ if (type == MXL_HYDRA_DEVICE_544) -+ return 0; -+ if (type == MXL_HYDRA_DEVICE_542) -+ return 0; -+ break; -+ case MXL_HYDRA_SKU_ID_582: -+ if (type == MXL_HYDRA_DEVICE_582) -+ return 0; -+ break; -+ default: -+ return -1; -+ } -+ } else { -+ -+ } -+ return -1; -+} -+ -+static int get_fwinfo(struct mxl *state) -+{ -+ int status; -+ u32 val = 0; -+ -+ status = GET_REG_FIELD_DATA(PAD_MUX_BOND_OPTION, &val); -+ if (status) -+ return status; -+ pr_info("chipID=%08x\n", val); -+ -+ status = GET_REG_FIELD_DATA(PRCM_AFE_CHIP_MMSK_VER, &val); -+ if (status) -+ return status; -+ pr_info("chipVer=%08x\n", val); -+ -+ status = read_register(state, HYDRA_FIRMWARE_VERSION, &val); -+ if (status) -+ return status; -+ pr_info("FWVer=%08x\n", val); -+ -+ state->base->fwversion = val; -+ return status; -+} -+ -+ -+static u8 tsMap1_to_1[MXL_HYDRA_DEMOD_MAX] = { -+ MXL_HYDRA_DEMOD_ID_0, -+ MXL_HYDRA_DEMOD_ID_1, -+ MXL_HYDRA_DEMOD_ID_2, -+ MXL_HYDRA_DEMOD_ID_3, -+ MXL_HYDRA_DEMOD_ID_4, -+ MXL_HYDRA_DEMOD_ID_5, -+ MXL_HYDRA_DEMOD_ID_6, -+ MXL_HYDRA_DEMOD_ID_7, -+}; -+ -+static u8 tsMap54x[MXL_HYDRA_DEMOD_MAX] = { -+ MXL_HYDRA_DEMOD_ID_2, -+ MXL_HYDRA_DEMOD_ID_3, -+ MXL_HYDRA_DEMOD_ID_4, -+ MXL_HYDRA_DEMOD_ID_5, -+ MXL_HYDRA_DEMOD_MAX, -+ MXL_HYDRA_DEMOD_MAX, -+ MXL_HYDRA_DEMOD_MAX, -+ MXL_HYDRA_DEMOD_MAX, -+}; -+ -+static int probe(struct mxl *state, struct mxl5xx_cfg *cfg) -+{ -+ u32 chipver; -+ int fw, status, j; -+ MXL_HYDRA_MPEGOUT_PARAM_T mpegInterfaceCfg; -+ -+ state->base->ts_map = tsMap1_to_1; -+ -+ switch (state->base->type) { -+ case MXL_HYDRA_DEVICE_581: -+ case MXL_HYDRA_DEVICE_581S: -+ state->base->can_clkout = 1; -+ state->base->demod_num = 8; -+ state->base->tuner_num = 1; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_581; -+ break; -+ case MXL_HYDRA_DEVICE_582: -+ state->base->can_clkout = 1; -+ state->base->demod_num = 8; -+ state->base->tuner_num = 3; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_582; -+ break; -+ case MXL_HYDRA_DEVICE_585: -+ state->base->can_clkout = 0; -+ state->base->demod_num = 8; -+ state->base->tuner_num = 4; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_585; -+ break; -+ case MXL_HYDRA_DEVICE_544: -+ state->base->can_clkout = 0; -+ state->base->demod_num = 4; -+ state->base->tuner_num = 4; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_544; -+ state->base->ts_map = tsMap54x; -+ break; -+ case MXL_HYDRA_DEVICE_541: -+ case MXL_HYDRA_DEVICE_541S: -+ state->base->can_clkout = 0; -+ state->base->demod_num = 4; -+ state->base->tuner_num = 1; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_541; -+ state->base->ts_map = tsMap54x; -+ break; -+ case MXL_HYDRA_DEVICE_561: -+ case MXL_HYDRA_DEVICE_561S: -+ state->base->can_clkout = 0; -+ state->base->demod_num = 6; -+ state->base->tuner_num = 1; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_561; -+ break; -+ case MXL_HYDRA_DEVICE_568: -+ state->base->can_clkout = 0; -+ state->base->demod_num = 8; -+ state->base->tuner_num = 1; -+ state->base->chan_bond = 1; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_568; -+ break; -+ case MXL_HYDRA_DEVICE_542: -+ state->base->can_clkout = 1; -+ state->base->demod_num = 4; -+ state->base->tuner_num = 3; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_542; -+ state->base->ts_map = tsMap54x; -+ break; -+ case MXL_HYDRA_DEVICE_TEST: -+ case MXL_HYDRA_DEVICE_584: -+ default: -+ state->base->can_clkout = 0; -+ state->base->demod_num = 8; -+ state->base->tuner_num = 4; -+ state->base->sku_type = MXL_HYDRA_SKU_TYPE_584; -+ break; -+ } -+ -+ status = validate_sku(state); -+ if (status) -+ return status; -+ -+ SET_REG_FIELD_DATA(PRCM_AFE_REG_CLOCK_ENABLE, 1); -+ SET_REG_FIELD_DATA(PRCM_PRCM_AFE_REG_SOFT_RST_N, 1); -+ status = GET_REG_FIELD_DATA(PRCM_CHIP_VERSION, &chipver); -+ if (status) -+ state->base->chipversion = 0; -+ else -+ state->base->chipversion = (chipver == 2) ? 2 : 1; -+ pr_info("Hydra chip version %u\n", state->base->chipversion); -+ -+ cfg_dev_xtal(state, cfg->clk, cfg->cap, 0); -+ -+ fw = firmware_is_alive(state); -+ if (!fw) { -+ status = load_fw(state, cfg); -+ if (status) -+ return status; -+ } -+ get_fwinfo(state); -+ -+ config_mux(state); -+ mpegInterfaceCfg.enable = MXL_ENABLE; -+ mpegInterfaceCfg.lsbOrMsbFirst = MXL_HYDRA_MPEG_SERIAL_MSB_1ST; -+ /* supports only (0-104&139)MHz */ -+ if (cfg->ts_clk) -+ mpegInterfaceCfg.maxMpegClkRate = cfg->ts_clk; -+ else -+ mpegInterfaceCfg.maxMpegClkRate = 69; /* 139; */ -+ mpegInterfaceCfg.mpegClkPhase = MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG; -+ mpegInterfaceCfg.mpegClkPol = MXL_HYDRA_MPEG_CLK_IN_PHASE; -+ /* MXL_HYDRA_MPEG_CLK_GAPPED; */ -+ mpegInterfaceCfg.mpegClkType = MXL_HYDRA_MPEG_CLK_CONTINUOUS; -+ mpegInterfaceCfg.mpegErrorIndication = -+ MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED; -+ mpegInterfaceCfg.mpegMode = MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE; -+ mpegInterfaceCfg.mpegSyncPol = MXL_HYDRA_MPEG_ACTIVE_HIGH; -+ mpegInterfaceCfg.mpegSyncPulseWidth = MXL_HYDRA_MPEG_SYNC_WIDTH_BIT; -+ mpegInterfaceCfg.mpegValidPol = MXL_HYDRA_MPEG_ACTIVE_HIGH; -+ -+ -+ for (j = 0; j < state->base->demod_num; j++) { -+ status = config_ts(state, (MXL_HYDRA_DEMOD_ID_E) j, -+ &mpegInterfaceCfg); -+ if (status) -+ return status; -+ } -+ set_drive_strength(state, 1); -+ return 0; -+} -+ -+struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, -+ struct mxl5xx_cfg *cfg, -+ u32 demod, u32 tuner) -+{ -+ struct mxl *state; -+ struct mxl_base *base; -+ -+ state = kzalloc(sizeof(struct mxl), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->demod = demod; -+ state->tuner = tuner; -+ state->tuner_in_use = 0xffffffff; -+ -+ base = match_base(i2c, cfg->adr); -+ if (base) { -+ base->count++; -+ if (base->count > base->demod_num) -+ goto fail; -+ state->base = base; -+ } else { -+ base = kzalloc(sizeof(struct mxl_base), GFP_KERNEL); -+ if (!base) -+ goto fail; -+ base->i2c = i2c; -+ base->adr = cfg->adr; -+ base->type = cfg->type; -+ base->count = 1; -+ mutex_init(&base->i2c_lock); -+ mutex_init(&base->status_lock); -+ mutex_init(&base->tune_lock); -+ INIT_LIST_HEAD(&base->mxls); -+ -+ state->base = base; -+ if (probe(state, cfg) < 0) { -+ kfree(base); -+ goto fail; -+ } -+ list_add(&base->mxllist, &mxllist); -+ } -+ state->fe.ops = mxl_ops; -+ state->fe.ops.xbar[1] = demod; -+ state->fe.demodulator_priv = state; -+ state->fe.dtv_property_cache.input = tuner; -+ list_add(&state->mxl, &base->mxls); -+ return &state->fe; -+ -+fail: -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(mxl5xx_attach); -+ -+ -+MODULE_DESCRIPTION("MXL5XX driver"); -+MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/mxl5xx.h b/drivers/media/dvb-frontends/mxl5xx.h -new file mode 100644 -index 0000000..e02ba1d ---- /dev/null -+++ b/drivers/media/dvb-frontends/mxl5xx.h -@@ -0,0 +1,39 @@ -+#ifndef _MXL5XX_H_ -+#define _MXL5XX_H_ -+ -+#include -+#include -+ -+struct mxl5xx_cfg { -+ u8 adr; -+ u8 type; -+ u32 cap; -+ u32 clk; -+ u32 ts_clk; -+ -+ u8 *fw; -+ u32 fw_len; -+ -+ int (*fw_read)(void *priv, u8 *buf, u32 len); -+ void *fw_priv; -+}; -+ -+#if IS_REACHABLE(CONFIG_DVB_MXL5XX) -+ -+extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, -+ struct mxl5xx_cfg *cfg, -+ u32 demod, u32 tuner); -+ -+#else -+ -+static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, -+ struct mxl5xx_cfg *cfg, -+ u32 demod, u32 tuner) -+{ -+ pr_warn("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif /* CONFIG_DVB_MXL5XX */ -+ -+#endif /* _MXL5XX_H_ */ -diff --git a/drivers/media/dvb-frontends/mxl5xx_defs.h b/drivers/media/dvb-frontends/mxl5xx_defs.h -new file mode 100644 -index 0000000..35b5c0b ---- /dev/null -+++ b/drivers/media/dvb-frontends/mxl5xx_defs.h -@@ -0,0 +1,818 @@ -+/* -+ * Defines for the Maxlinear MX58x family of tuners/demods -+ * -+ * Copyright (C) 2014 Digital Devices GmbH -+ * -+ * based on code: -+ * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved -+ * which was released under GPL V2 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2, as published by the Free Software Foundation. -+ */ -+ -+typedef enum -+{ -+ MXL_DISABLE = 0, -+ MXL_ENABLE = 1, -+ -+ MXL_FALSE = 0, -+ MXL_TRUE = 1, -+ -+ MXL_INVALID = 0, -+ MXL_VALID = 1, -+ -+ MXL_NO = 0, -+ MXL_YES = 1, -+ -+ MXL_OFF = 0, -+ MXL_ON = 1 -+} MXL_BOOL_E; -+ -+// Firmware-Host Command IDs -+typedef enum -+{ -+ //--Device command IDs-- -+ MXL_HYDRA_DEV_NO_OP_CMD = 0, //No OP -+ -+ MXL_HYDRA_DEV_SET_POWER_MODE_CMD = 1, -+ MXL_HYDRA_DEV_SET_OVERWRITE_DEF_CMD = 2, -+ -+ // Host-used CMD, not used by firmware -+ MXL_HYDRA_DEV_FIRMWARE_DOWNLOAD_CMD = 3, -+ -+ // Additional CONTROL types from DTV -+ MXL_HYDRA_DEV_SET_BROADCAST_PID_STB_ID_CMD = 4, -+ MXL_HYDRA_DEV_GET_PMM_SLEEP_CMD = 5, -+ -+ //--Tuner command IDs-- -+ MXL_HYDRA_TUNER_TUNE_CMD = 6, -+ MXL_HYDRA_TUNER_GET_STATUS_CMD = 7, -+ -+ //--Demod command IDs-- -+ MXL_HYDRA_DEMOD_SET_PARAM_CMD = 8, -+ MXL_HYDRA_DEMOD_GET_STATUS_CMD = 9, -+ -+ MXL_HYDRA_DEMOD_RESET_FEC_COUNTER_CMD = 10, -+ -+ MXL_HYDRA_DEMOD_SET_PKT_NUM_CMD = 11, -+ -+ MXL_HYDRA_DEMOD_SET_IQ_SOURCE_CMD = 12, -+ MXL_HYDRA_DEMOD_GET_IQ_DATA_CMD = 13, -+ -+ MXL_HYDRA_DEMOD_GET_M68HC05_VER_CMD = 14, -+ -+ MXL_HYDRA_DEMOD_SET_ERROR_COUNTER_MODE_CMD = 15, -+ -+ //--- ABORT channel tune -+ MXL_HYDRA_ABORT_TUNE_CMD = 16, // Abort current tune command. -+ -+ //--SWM/FSK command IDs-- -+ MXL_HYDRA_FSK_RESET_CMD = 17, -+ MXL_HYDRA_FSK_MSG_CMD = 18, -+ MXL_HYDRA_FSK_SET_OP_MODE_CMD = 19, -+ -+ //--DiSeqC command IDs-- -+ MXL_HYDRA_DISEQC_MSG_CMD = 20, -+ MXL_HYDRA_DISEQC_COPY_MSG_TO_MAILBOX = 21, -+ MXL_HYDRA_DISEQC_CFG_MSG_CMD = 22, -+ -+ //--- FFT Debug Command IDs-- -+ MXL_HYDRA_REQ_FFT_SPECTRUM_CMD = 23, -+ -+ // -- Demod scramblle code -+ MXL_HYDRA_DEMOD_SCRAMBLE_CODE_CMD = 24, -+ -+ //---For host to know how many commands in total--- -+ MXL_HYDRA_LAST_HOST_CMD = 25, -+ -+ MXL_HYDRA_DEMOD_INTR_TYPE_CMD = 47, -+ MXL_HYDRA_DEV_INTR_CLEAR_CMD = 48, -+ MXL_HYDRA_TUNER_SPECTRUM_REQ_CMD = 53, -+ MXL_HYDRA_TUNER_ACTIVATE_CMD = 55, -+ MXL_HYDRA_DEV_CFG_POWER_MODE_CMD = 56, -+ MXL_HYDRA_DEV_XTAL_CAP_CMD = 57, -+ MXL_HYDRA_DEV_CFG_SKU_CMD = 58, -+ MXL_HYDRA_TUNER_SPECTRUM_MIN_GAIN_CMD = 59, -+ MXL_HYDRA_DISEQC_CONT_TONE_CFG = 60, -+ MXL_HYDRA_DEV_RF_WAKE_UP_CMD = 61, -+ MXL_HYDRA_DEMOD_CFG_EQ_CTRL_PARAM_CMD = 62, -+ MXL_HYDRA_DEMOD_FREQ_OFFSET_SEARCH_RANGE_CMD = 63, -+ MXL_HYDRA_DEV_REQ_PWR_FROM_ADCRSSI_CMD = 64, -+ -+ MXL_XCPU_PID_FLT_CFG_CMD = 65, -+ MXL_XCPU_SHMEM_TEST_CMD = 66, -+ MXL_XCPU_ABORT_TUNE_CMD = 67, -+ MXL_XCPU_CHAN_TUNE_CMD = 68, -+ MXL_XCPU_FLT_BOND_HDRS_CMD = 69, -+ -+ MXL_HYDRA_DEV_BROADCAST_WAKE_UP_CMD = 70, -+ MXL_HYDRA_FSK_CFG_FSK_FREQ_CMD = 71, -+ MXL_HYDRA_FSK_POWER_DOWN_CMD = 72, -+ MXL_XCPU_CLEAR_CB_STATS_CMD = 73, -+ MXL_XCPU_CHAN_BOND_RESTART_CMD = 74 -+} MXL_HYDRA_HOST_CMD_ID_E; -+ -+#define MXL_ENABLE_BIG_ENDIAN (0) -+ -+#define MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH 248 -+ -+#define MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN (248) -+ -+#define MXL_HYDRA_CAP_MIN 10 -+#define MXL_HYDRA_CAP_MAX 33 -+ -+#define MXL_HYDRA_PLID_REG_READ 0xFB // Read register PLID -+#define MXL_HYDRA_PLID_REG_WRITE 0xFC // Write register PLID -+ -+#define MXL_HYDRA_PLID_CMD_READ 0xFD // Command Read PLID -+#define MXL_HYDRA_PLID_CMD_WRITE 0xFE // Command Write PLID -+ -+#define MXL_HYDRA_REG_SIZE_IN_BYTES 4 // Hydra register size in bytes -+#define MXL_HYDRA_I2C_HDR_SIZE (2 * sizeof(u8)) // PLID + LEN(0xFF) -+#define MXL_HYDRA_CMD_HEADER_SIZE (MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE) -+ -+#define MXL_HYDRA_SKU_ID_581 0 -+#define MXL_HYDRA_SKU_ID_584 1 -+#define MXL_HYDRA_SKU_ID_585 2 -+#define MXL_HYDRA_SKU_ID_544 3 -+#define MXL_HYDRA_SKU_ID_561 4 -+#define MXL_HYDRA_SKU_ID_582 5 -+#define MXL_HYDRA_SKU_ID_568 6 -+ -+// macro for register write data buffer size (PLID + LEN (0xFF) + RegAddr + RegData) -+#define MXL_HYDRA_REG_WRITE_LEN (MXL_HYDRA_I2C_HDR_SIZE + (2 * MXL_HYDRA_REG_SIZE_IN_BYTES)) -+ -+// maro to extract a single byte from 4-byte(32-bit) data -+#define GET_BYTE(x,n) (((x) >> (8*(n))) & 0xFF) -+ -+#define MAX_CMD_DATA 512 -+ -+#define MXL_GET_REG_MASK_32(lsbLoc,numOfBits) ((0xFFFFFFFF >> (32 - (numOfBits))) << (lsbLoc)) -+ -+#define GET_REG_FIELD_DATA(fieldName, dataPtr) read_by_mnemonic(state, fieldName, dataPtr); -+#define SET_REG_FIELD_DATA(fieldName, data) update_by_mnemonic(state, fieldName, data); -+ -+#define FW_DL_SIGN (0xDEADBEEF) -+ -+#define MBIN_FORMAT_VERSION '1' -+#define MBIN_FILE_HEADER_ID 'M' -+#define MBIN_SEGMENT_HEADER_ID 'S' -+#define MBIN_MAX_FILE_LENGTH (1<<23) -+ -+typedef struct -+{ -+ u8 id; -+ u8 fmtVersion; -+ u8 headerLen; -+ u8 numSegments; -+ u8 entryAddress[4]; -+ u8 imageSize24[3]; -+ u8 imageChecksum; -+ u8 reserved[4]; -+} MBIN_FILE_HEADER_T; -+ -+typedef struct -+{ -+ MBIN_FILE_HEADER_T header; -+ u8 data[1]; -+} MBIN_FILE_T; -+ -+typedef struct -+{ -+ u8 id; -+ u8 len24[3]; -+ u8 address[4]; -+} MBIN_SEGMENT_HEADER_T; -+ -+ -+typedef struct -+{ -+ MBIN_SEGMENT_HEADER_T header; -+ u8 data[1]; -+} MBIN_SEGMENT_T; -+ -+ -+typedef enum { MXL_CMD_WRITE = 0, MXL_CMD_READ} MXL_CMD_TYPE_E; -+ -+#define BUILD_HYDRA_CMD(cmdID, reqType, size, dataPtr, cmdBuff) \ -+ do { \ -+ cmdBuff[0] = ((reqType == MXL_CMD_WRITE) ? MXL_HYDRA_PLID_CMD_WRITE : MXL_HYDRA_PLID_CMD_READ); \ -+ cmdBuff[1] = (size > 251) ? 0xff : (u8) (size + 4); \ -+ cmdBuff[2] = size; \ -+ cmdBuff[3] = cmdID; \ -+ cmdBuff[4] = 0x00; \ -+ cmdBuff[5] = 0x00; \ -+ convert_endian(MXL_ENABLE_BIG_ENDIAN, size, (u8 *)dataPtr); \ -+ memcpy((void *)&cmdBuff[6], dataPtr, size); \ -+ } while(0) //; -+ -+typedef struct { -+ u32 regAddr; -+ u8 lsbPos; -+ u8 numOfBits; -+} MXL_REG_FIELD_T; -+ -+typedef struct { -+ u32 dataSize; -+ u8 data[MAX_CMD_DATA]; -+} MXL_DEV_CMD_DATA_T; -+ -+typedef enum -+{ -+ MXL_HYDRA_SKU_TYPE_MIN = 0x00, -+ MXL_HYDRA_SKU_TYPE_581 = 0x00, -+ MXL_HYDRA_SKU_TYPE_584 = 0x01, -+ MXL_HYDRA_SKU_TYPE_585 = 0x02, -+ MXL_HYDRA_SKU_TYPE_544 = 0x03, -+ MXL_HYDRA_SKU_TYPE_561 = 0x04, -+ MXL_HYDRA_SKU_TYPE_5xx = 0x05, -+ MXL_HYDRA_SKU_TYPE_5yy = 0x06, -+ MXL_HYDRA_SKU_TYPE_511 = 0x07, -+ MXL_HYDRA_SKU_TYPE_561_DE = 0x08, -+ MXL_HYDRA_SKU_TYPE_582 = 0x09, -+ MXL_HYDRA_SKU_TYPE_541 = 0x0A, -+ MXL_HYDRA_SKU_TYPE_568 = 0x0B, -+ MXL_HYDRA_SKU_TYPE_542 = 0x0C, -+ MXL_HYDRA_SKU_TYPE_MAX = 0x0D, -+} MXL_HYDRA_SKU_TYPE_E; -+ -+typedef struct -+{ -+ MXL_HYDRA_SKU_TYPE_E skuType; -+} MXL_HYDRA_SKU_COMMAND_T; -+ -+ -+typedef enum -+{ -+ MXL_HYDRA_DEMOD_ID_0 = 0, -+ MXL_HYDRA_DEMOD_ID_1, -+ MXL_HYDRA_DEMOD_ID_2, -+ MXL_HYDRA_DEMOD_ID_3, -+ MXL_HYDRA_DEMOD_ID_4, -+ MXL_HYDRA_DEMOD_ID_5, -+ MXL_HYDRA_DEMOD_ID_6, -+ MXL_HYDRA_DEMOD_ID_7, -+ MXL_HYDRA_DEMOD_MAX -+} MXL_HYDRA_DEMOD_ID_E; -+ -+#define MXL_DEMOD_SCRAMBLE_SEQ_LEN 12 -+ -+#define MAX_STEP_SIZE_24_XTAL_102_05_KHZ 195 -+#define MAX_STEP_SIZE_24_XTAL_204_10_KHZ 215 -+#define MAX_STEP_SIZE_24_XTAL_306_15_KHZ 203 -+#define MAX_STEP_SIZE_24_XTAL_408_20_KHZ 177 -+ -+#define MAX_STEP_SIZE_27_XTAL_102_05_KHZ 195 -+#define MAX_STEP_SIZE_27_XTAL_204_10_KHZ 215 -+#define MAX_STEP_SIZE_27_XTAL_306_15_KHZ 203 -+#define MAX_STEP_SIZE_27_XTAL_408_20_KHZ 177 -+ -+#define MXL_HYDRA_SPECTRUM_MIN_FREQ_KHZ 300000 -+#define MXL_HYDRA_SPECTRUM_MAX_FREQ_KHZ 2350000 -+ -+typedef enum -+{ -+ DMD_STANDARD_ADDR = 0, -+ DMD_SPECTRUM_INVERSION_ADDR, -+ DMD_SPECTRUM_ROLL_OFF_ADDR, -+ DMD_SYMBOL_RATE_ADDR, -+ DMD_MODULATION_SCHEME_ADDR, -+ DMD_FEC_CODE_RATE_ADDR, -+ DMD_SNR_ADDR, -+ DMD_FREQ_OFFSET_ADDR, -+ DMD_CTL_FREQ_OFFSET_ADDR, -+ DMD_STR_FREQ_OFFSET_ADDR, -+ DMD_FTL_FREQ_OFFSET_ADDR, -+ DMD_STR_NBC_SYNC_LOCK_ADDR, -+ DMD_CYCLE_SLIP_COUNT_ADDR, -+ DMD_DISPLAY_IQ_ADDR, -+ DMD_DVBS2_CRC_ERRORS_ADDR, -+ DMD_DVBS2_PER_COUNT_ADDR, -+ DMD_DVBS2_PER_WINDOW_ADDR, -+ DMD_DVBS_CORR_RS_ERRORS_ADDR, -+ DMD_DVBS_UNCORR_RS_ERRORS_ADDR, -+ DMD_DVBS_BER_COUNT_ADDR, -+ DMD_DVBS_BER_WINDOW_ADDR, -+ DMD_TUNER_ID_ADDR, -+ DMD_DVBS2_PILOT_ON_OFF_ADDR, -+ DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR, -+ -+ MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE, -+} MXL_DEMOD_CHAN_PARAMS_OFFSET_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TUNER_ID_0 = 0, -+ MXL_HYDRA_TUNER_ID_1, -+ MXL_HYDRA_TUNER_ID_2, -+ MXL_HYDRA_TUNER_ID_3, -+ MXL_HYDRA_TUNER_MAX -+} MXL_HYDRA_TUNER_ID_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_DSS = 0, -+ MXL_HYDRA_DVBS, -+ MXL_HYDRA_DVBS2, -+} MXL_HYDRA_BCAST_STD_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_FEC_AUTO = 0, -+ MXL_HYDRA_FEC_1_2, -+ MXL_HYDRA_FEC_3_5, -+ MXL_HYDRA_FEC_2_3, -+ MXL_HYDRA_FEC_3_4, -+ MXL_HYDRA_FEC_4_5, -+ MXL_HYDRA_FEC_5_6, -+ MXL_HYDRA_FEC_6_7, -+ MXL_HYDRA_FEC_7_8, -+ MXL_HYDRA_FEC_8_9, -+ MXL_HYDRA_FEC_9_10, -+} MXL_HYDRA_FEC_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_MOD_AUTO = 0, -+ MXL_HYDRA_MOD_QPSK, -+ MXL_HYDRA_MOD_8PSK -+} MXL_HYDRA_MODULATION_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_SPECTRUM_AUTO = 0, -+ MXL_HYDRA_SPECTRUM_INVERTED, -+ MXL_HYDRA_SPECTRUM_NON_INVERTED, -+} MXL_HYDRA_SPECTRUM_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_ROLLOFF_AUTO = 0, -+ MXL_HYDRA_ROLLOFF_0_20, -+ MXL_HYDRA_ROLLOFF_0_25, -+ MXL_HYDRA_ROLLOFF_0_35 -+} MXL_HYDRA_ROLLOFF_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_PILOTS_OFF = 0, -+ MXL_HYDRA_PILOTS_ON, -+ MXL_HYDRA_PILOTS_AUTO -+} MXL_HYDRA_PILOTS_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_FORMATTER = 0, -+ MXL_HYDRA_LEGACY_FEC, -+ MXL_HYDRA_FREQ_RECOVERY, -+ MXL_HYDRA_NBC, -+ MXL_HYDRA_CTL, -+ MXL_HYDRA_EQ, -+} MXL_HYDRA_CONSTELLATION_SRC_E; -+ -+typedef struct -+{ -+ int agcLock; // AGC lock info -+ int fecLock; // Demod FEC block lock info -+} MXL_HYDRA_DEMOD_LOCK_T; -+ -+typedef struct -+{ -+ u32 rsErrors; // RS decoder err counter -+ u32 berWindow; // Ber Windows -+ u32 berCount; // BER count -+ u32 berWindow_Iter1; // Ber Windows - post viterbi -+ u32 berCount_Iter1; // BER count - post viterbi -+} MXL_HYDRA_DEMOD_STATUS_DVBS_T; -+ -+typedef struct -+{ -+ u32 rsErrors; // RS decoder err counter -+ u32 berWindow; // Ber Windows -+ u32 berCount; // BER count -+} MXL_HYDRA_DEMOD_STATUS_DSS_T; -+ -+typedef struct -+{ -+ u32 crcErrors; // CRC error counter -+ u32 packetErrorCount; // Number of packet errors -+ u32 totalPackets; // Total packets -+} MXL_HYDRA_DEMOD_STATUS_DVBS2_T; -+ -+typedef struct -+{ -+ MXL_HYDRA_BCAST_STD_E standardMask; // Standard DVB-S, DVB-S2 or DSS -+ -+ union -+ { -+ MXL_HYDRA_DEMOD_STATUS_DVBS_T demodStatus_DVBS; // DVB-S demod status -+ MXL_HYDRA_DEMOD_STATUS_DVBS2_T demodStatus_DVBS2; // DVB-S2 demod status -+ MXL_HYDRA_DEMOD_STATUS_DSS_T demodStatus_DSS; // DSS demod status -+ } u; -+ -+} MXL_HYDRA_DEMOD_STATUS_T; -+ -+typedef struct -+{ -+ s32 carrierOffsetInHz; // CRL offset info -+ s32 symbolOffsetInSymbol; // SRL offset info -+} MXL_HYDRA_DEMOD_SIG_OFFSET_INFO_T; -+ -+typedef struct -+{ -+ u8 scrambleSequence[MXL_DEMOD_SCRAMBLE_SEQ_LEN]; // scramble sequence -+ u32 scrambleCode; // scramble gold code -+} MXL_HYDRA_DEMOD_SCRAMBLE_INFO_T; -+ -+typedef enum -+{ -+ MXL_HYDRA_STEP_SIZE_24_XTAL_102_05KHZ, // 102.05 KHz for 24 MHz XTAL -+ MXL_HYDRA_STEP_SIZE_24_XTAL_204_10KHZ, // 204.10 KHz for 24 MHz XTAL -+ MXL_HYDRA_STEP_SIZE_24_XTAL_306_15KHZ, // 306.15 KHz for 24 MHz XTAL -+ MXL_HYDRA_STEP_SIZE_24_XTAL_408_20KHZ, // 408.20 KHz for 24 MHz XTAL -+ -+ MXL_HYDRA_STEP_SIZE_27_XTAL_102_05KHZ, // 102.05 KHz for 27 MHz XTAL -+ MXL_HYDRA_STEP_SIZE_27_XTAL_204_35KHZ, // 204.35 KHz for 27 MHz XTAL -+ MXL_HYDRA_STEP_SIZE_27_XTAL_306_52KHZ, // 306.52 KHz for 27 MHz XTAL -+ MXL_HYDRA_STEP_SIZE_27_XTAL_408_69KHZ, // 408.69 KHz for 27 MHz XTAL -+ -+} MXL_HYDRA_SPECTRUM_STEP_SIZE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_SPECTRUM_RESOLUTION_00_1_DB, // 0.1 dB -+ MXL_HYDRA_SPECTRUM_RESOLUTION_01_0_DB, // 1.0 dB -+ MXL_HYDRA_SPECTRUM_RESOLUTION_05_0_DB, // 5.0 dB -+ MXL_HYDRA_SPECTRUM_RESOLUTION_10_0_DB, // 10 dB -+} MXL_HYDRA_SPECTRUM_RESOLUTION_E; -+ -+typedef enum -+{ -+ MXL_SPECTRUM_NO_ERROR, -+ MXL_SPECTRUM_INVALID_PARAMETER, -+ MXL_SPECTRUM_INVALID_STEP_SIZE, -+ MXL_SPECTRUM_BW_CANNOT_BE_COVERED, -+ MXL_SPECTRUM_DEMOD_BUSY, -+ MXL_SPECTRUM_TUNER_NOT_ENABLED, -+ -+} MXL_HYDRA_SPECTRUM_ERROR_CODE_E; -+ -+typedef struct -+{ -+ u32 tunerIndex; // TUNER Ctrl: one of MXL58x_TUNER_ID_E -+ u32 demodIndex; // DEMOD Ctrl: one of MXL58x_DEMOD_ID_E -+ MXL_HYDRA_SPECTRUM_STEP_SIZE_E stepSizeInKHz; -+ u32 startingFreqInkHz; -+ u32 totalSteps; -+ MXL_HYDRA_SPECTRUM_RESOLUTION_E spectrumDivision; -+} MXL_HYDRA_SPECTRUM_REQ_T; -+ -+typedef enum -+{ -+ MXL_HYDRA_SEARCH_MAX_OFFSET = 0, // DMD searches for max freq offset (i.e. 5MHz) -+ MXL_HYDRA_SEARCH_BW_PLUS_ROLLOFF, // DMD searches for BW + ROLLOFF/2 -+} MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E; -+ -+typedef struct -+{ -+ u32 demodIndex; -+ MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E searchType; -+} MXL58x_CFG_FREQ_OFF_SEARCH_RANGE_T; -+ -+ -+ -+ -+// there are two slices -+// slice0 - TS0, TS1, TS2 & TS3 -+// slice1 - TS4, TS5, TS6 & TS7 -+#define MXL_HYDRA_TS_SLICE_MAX 2 -+ -+#define MAX_FIXED_PID_NUM 32 -+ -+#define MXL_HYDRA_NCO_CLK 418 // 418 MHz -+ -+#define MXL_HYDRA_MAX_TS_CLOCK 139 // 139 MHz -+ -+#define MXL_HYDRA_TS_FIXED_PID_FILT_SIZE 32 -+ -+#define MXL_HYDRA_SHARED_PID_FILT_SIZE_DEFAULT 33 // Shared PID filter size in 1-1 mux mode -+#define MXL_HYDRA_SHARED_PID_FILT_SIZE_2_TO_1 66 // Shared PID filter size in 2-1 mux mode -+#define MXL_HYDRA_SHARED_PID_FILT_SIZE_4_TO_1 132 // Shared PID filter size in 4-1 mux mode -+ -+typedef enum -+{ -+ MXL_HYDRA_SOFTWARE_PID_BANK = 0, -+ MXL_HYDRA_HARDWARE_PID_BANK, -+} MXL_HYDRA_PID_BANK_TYPE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TS_MUX_PID_REMAP = 0, -+ MXL_HYDRA_TS_MUX_PREFIX_EXTRA_HEADER = 1, -+} MXL_HYDRA_TS_MUX_MODE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TS_MUX_DISABLE = 0, // No Mux ( 1 TSIF to 1 TSIF) -+ MXL_HYDRA_TS_MUX_2_TO_1, // Mux 2 TSIF to 1 TSIF -+ MXL_HYDRA_TS_MUX_4_TO_1, // Mux 4 TSIF to 1 TSIF -+} MXL_HYDRA_TS_MUX_TYPE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TS_GROUP_0_3 = 0, // TS group 0 to 3 (TS0, TS1, TS2 & TS3) -+ MXL_HYDRA_TS_GROUP_4_7, // TS group 0 to 3 (TS4, TS5, TS6 & TS7) -+} MXL_HYDRA_TS_GROUP_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TS_PIDS_ALLOW_ALL = 0, // Allow all pids -+ MXL_HYDRA_TS_PIDS_DROP_ALL, // Drop all pids -+ MXL_HYDRA_TS_INVALIDATE_PID_FILTER, // Delete current PD filter in the device -+ -+} MXL_HYDRA_TS_PID_FLT_CTRL_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TS_PID_FIXED = 0, -+ MXL_HYDRA_TS_PID_REGULAR, -+} MXL_HYDRA_TS_PID_TYPE_E; -+ -+typedef struct -+{ -+ u16 originalPid; // pid from TS -+ u16 remappedPid; // remapped pid -+ MXL_BOOL_E enable; // enable or disable pid -+ MXL_BOOL_E allowOrDrop; // allow or drop pid -+ MXL_BOOL_E enablePidRemap; // enable or disable pid remap -+ u8 bondId; // Bond ID in A0 always 0 - Only for 568 Sku -+ u8 destId; // Output port ID for the PID - Only for 568 Sku -+} MXL_HYDRA_TS_PID_T; -+ -+typedef struct -+{ -+ MXL_BOOL_E enable; -+ u8 numByte; -+ u8 header[12]; -+} MXL_HYDRA_TS_MUX_PREFIX_HEADER_T; -+ -+typedef enum -+{ -+ MXL_HYDRA_PID_BANK_A = 0, -+ MXL_HYDRA_PID_BANK_B, -+} MXL_HYDRA_PID_FILTER_BANK_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_MPEG_SERIAL_MSB_1ST = 0, -+ MXL_HYDRA_MPEG_SERIAL_LSB_1ST, -+ -+ MXL_HYDRA_MPEG_SYNC_WIDTH_BIT = 0, -+ MXL_HYDRA_MPEG_SYNC_WIDTH_BYTE -+} MXL_HYDRA_MPEG_DATA_FMT_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_MPEG_MODE_SERIAL_4_WIRE = 0, // MPEG 4 Wire serial mode -+ MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE, // MPEG 3 Wire serial mode -+ MXL_HYDRA_MPEG_MODE_SERIAL_2_WIRE, // MPEG 2 Wire serial mode -+ MXL_HYDRA_MPEG_MODE_PARALLEL // MPEG parallel mode - valid only for MxL581 -+} MXL_HYDRA_MPEG_MODE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_MPEG_CLK_CONTINUOUS = 0, // Continuous MPEG clock -+ MXL_HYDRA_MPEG_CLK_GAPPED, // Gapped (gated) MPEG clock -+} MXL_HYDRA_MPEG_CLK_TYPE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_MPEG_ACTIVE_LOW = 0, -+ MXL_HYDRA_MPEG_ACTIVE_HIGH, -+ -+ MXL_HYDRA_MPEG_CLK_NEGATIVE = 0, -+ MXL_HYDRA_MPEG_CLK_POSITIVE, -+ -+ MXL_HYDRA_MPEG_CLK_IN_PHASE = 0, -+ MXL_HYDRA_MPEG_CLK_INVERTED, -+} MXL_HYDRA_MPEG_CLK_FMT_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG = 0, -+ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_90_DEG, -+ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_180_DEG, -+ MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_270_DEG -+} MXL_HYDRA_MPEG_CLK_PHASE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_MPEG_ERR_REPLACE_SYNC = 0, -+ MXL_HYDRA_MPEG_ERR_REPLACE_VALID, -+ MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED -+} MXL_HYDRA_MPEG_ERR_INDICATION_E; -+ -+typedef struct -+{ -+ int enable; // Enable or Disable MPEG OUT -+ MXL_HYDRA_MPEG_CLK_TYPE_E mpegClkType; // Continuous or gapped -+ MXL_HYDRA_MPEG_CLK_FMT_E mpegClkPol; // MPEG Clk polarity -+ u8 maxMpegClkRate; // Max MPEG Clk rate (0 – 104 MHz, 139 MHz) -+ MXL_HYDRA_MPEG_CLK_PHASE_E mpegClkPhase; // MPEG Clk phase -+ MXL_HYDRA_MPEG_DATA_FMT_E lsbOrMsbFirst; // LSB first or MSB first in TS transmission -+ MXL_HYDRA_MPEG_DATA_FMT_E mpegSyncPulseWidth; // MPEG SYNC pulse width (1-bit or 1-byte) -+ MXL_HYDRA_MPEG_CLK_FMT_E mpegValidPol; // MPEG VALID polarity -+ MXL_HYDRA_MPEG_CLK_FMT_E mpegSyncPol; // MPEG SYNC polarity -+ MXL_HYDRA_MPEG_MODE_E mpegMode; // config 4/3/2-wire serial or parallel TS out -+ MXL_HYDRA_MPEG_ERR_INDICATION_E mpegErrorIndication; // Enable or Disable MPEG error indication -+} MXL_HYDRA_MPEGOUT_PARAM_T; -+ -+typedef enum -+{ -+ MXL_HYDRA_EXT_TS_IN_0 = 0, -+ MXL_HYDRA_EXT_TS_IN_1, -+ MXL_HYDRA_EXT_TS_IN_2, -+ MXL_HYDRA_EXT_TS_IN_3, -+ MXL_HYDRA_EXT_TS_IN_MAX -+ -+} MXL_HYDRA_EXT_TS_IN_ID_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TS_OUT_0 = 0, -+ MXL_HYDRA_TS_OUT_1, -+ MXL_HYDRA_TS_OUT_2, -+ MXL_HYDRA_TS_OUT_3, -+ MXL_HYDRA_TS_OUT_4, -+ MXL_HYDRA_TS_OUT_5, -+ MXL_HYDRA_TS_OUT_6, -+ MXL_HYDRA_TS_OUT_7, -+ MXL_HYDRA_TS_OUT_MAX -+ -+} MXL_HYDRA_TS_OUT_ID_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_TS_DRIVE_STRENGTH_1x = 0, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_2x, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_3x, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_4x, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_5x, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_6x, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_7x, -+ MXL_HYDRA_TS_DRIVE_STRENGTH_8x -+ -+} MXL_HYDRA_TS_DRIVE_STRENGTH_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_DEVICE_581 = 0, -+ MXL_HYDRA_DEVICE_584, -+ MXL_HYDRA_DEVICE_585, -+ MXL_HYDRA_DEVICE_544, -+ MXL_HYDRA_DEVICE_561, -+ MXL_HYDRA_DEVICE_TEST, -+ MXL_HYDRA_DEVICE_582, -+ MXL_HYDRA_DEVICE_541, -+ MXL_HYDRA_DEVICE_568, -+ MXL_HYDRA_DEVICE_542, -+ MXL_HYDRA_DEVICE_541S, -+ MXL_HYDRA_DEVICE_561S, -+ MXL_HYDRA_DEVICE_581S, -+ MXL_HYDRA_DEVICE_MAX -+} MXL_HYDRA_DEVICE_E; -+ -+ -+// Demod IQ data -+typedef struct -+{ -+ u32 demodId; -+ u32 sourceOfIQ; // ==0, it means I/Q comes from Formatter -+ // ==1, Legacy FEC -+ // ==2, Frequency Recovery -+ // ==3, NBC -+ // ==4, CTL -+ // ==5, EQ -+ // ==6, FPGA -+} MXL_HYDRA_DEMOD_IQ_SRC_T; -+ -+typedef struct -+{ -+ u32 demodId; -+} MXL_HYDRA_DEMOD_ABORT_TUNE_T; -+ -+typedef struct -+{ -+ u8 tunerId; -+ u8 enable; -+} MxL_HYDRA_TUNER_CMD; -+ -+// Demod Para for Channel Tune -+typedef struct -+{ -+ u32 tunerIndex; -+ u32 demodIndex; -+ u32 frequencyInHz; // Frequency -+ u32 standard; // one of MXL_HYDRA_BCAST_STD_E -+ u32 spectrumInversion; // Input : Spectrum inversion. -+ u32 rollOff; /* rollOff (alpha) factor */ -+ u32 symbolRateInHz; /* Symbol rate */ -+ u32 pilots; /* TRUE = pilots enabled */ -+ u32 modulationScheme; // Input : Modulation Scheme is one of MXL_HYDRA_MODULATION_E -+ u32 fecCodeRate; // Input : Forward error correction rate. Is one of MXL_HYDRA_FEC_E -+ u32 maxCarrierOffsetInMHz; // Maximum carrier freq offset in MHz. Same as freqSearchRangeKHz, but in unit of MHz. -+} MXL_HYDRA_DEMOD_PARAM_T; -+ -+typedef struct -+{ -+ u32 demodIndex; -+ u8 scrambleSequence[12]; // scramble sequence -+ u32 scrambleCode; // scramble gold code -+} MXL_HYDRA_DEMOD_SCRAMBLE_CODE_T; -+ -+typedef struct -+{ -+ u32 intrType; -+ u32 intrDurationInNanoSecs; -+ u32 intrMask; -+} MXL_INTR_CFG_T; -+ -+typedef struct -+{ -+ u8 powerMode; // enumeration values are defined in MXL_HYDRA_PWR_MODE_E (device API.h) -+} MxL_HYDRA_POWER_MODE_CMD; -+ -+ -+typedef struct -+{ -+ u32 timeIntervalInSeconds; // in seconds -+ u32 tunerIndex; -+ s32 rssiThreshold; -+ -+} MXL_HYDRA_RF_WAKEUP_PARAM_T; -+ -+typedef struct -+{ -+ u32 tunerCount; -+ MXL_HYDRA_RF_WAKEUP_PARAM_T params; -+} MXL_HYDRA_RF_WAKEUP_CFG_T; -+ -+ -+typedef enum -+{ -+ MXL_HYDRA_AUX_CTRL_MODE_FSK = 0, // Select FSK controller -+ MXL_HYDRA_AUX_CTRL_MODE_DISEQC, // Select DiSEqC controller -+} MXL_HYDRA_AUX_CTRL_MODE_E; -+ -+ -+typedef enum -+{ -+ MXL_HYDRA_DISEQC_ENVELOPE_MODE = 0, -+ MXL_HYDRA_DISEQC_TONE_MODE, -+} MXL_HYDRA_DISEQC_OPMODE_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_DISEQC_1_X = 0, // Config DiSEqC 1.x mode -+ MXL_HYDRA_DISEQC_2_X, // Config DiSEqC 2.x mode -+ MXL_HYDRA_DISEQC_DISABLE // Disable DiSEqC -+} MXL_HYDRA_DISEQC_VER_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_DISEQC_CARRIER_FREQ_22KHZ= 0, // DiSEqC signal frequency of 22 KHz -+ MXL_HYDRA_DISEQC_CARRIER_FREQ_33KHZ, // DiSEqC signal frequency of 33 KHz -+ MXL_HYDRA_DISEQC_CARRIER_FREQ_44KHZ // DiSEqC signal frequency of 44 KHz -+} MXL_HYDRA_DISEQC_CARRIER_FREQ_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_DISEQC_ID_0 = 0, -+ MXL_HYDRA_DISEQC_ID_1, -+ MXL_HYDRA_DISEQC_ID_2, -+ MXL_HYDRA_DISEQC_ID_3 -+} MXL_HYDRA_DISEQC_ID_E; -+ -+typedef enum -+{ -+ MXL_HYDRA_FSK_CFG_TYPE_39KPBS = 0, // 39.0kbps -+ MXL_HYDRA_FSK_CFG_TYPE_39_017KPBS, // 39.017kbps -+ MXL_HYDRA_FSK_CFG_TYPE_115_2KPBS // 115.2kbps -+} MXL_HYDRA_FSK_OP_MODE_E; -+ -+ -+typedef struct -+{ -+ u32 diseqcId; // DSQ 0, 1, 2 or 3 -+ u32 opMode; // Envelope mode (0) or internal tone mode (1) -+ u32 version; // 0: 1.0 , 1: 1.1 , 2: Disable -+ u32 centerFreq; // 0: 22KHz, 1: 33KHz and 2: 44 KHz -+}MXL58x_DSQ_OP_MODE_T; -+ -+typedef struct -+{ -+ u32 diseqcId; -+ u32 contToneFlag; // 1: Enable , 0: Disable -+} MXL_HYDRA_DISEQC_CFG_CONT_TONE_T; -diff --git a/drivers/media/dvb-frontends/mxl5xx_regs.h b/drivers/media/dvb-frontends/mxl5xx_regs.h -new file mode 100644 -index 0000000..e983d0b ---- /dev/null -+++ b/drivers/media/dvb-frontends/mxl5xx_regs.h -@@ -0,0 +1,941 @@ -+/* -+* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved -+* -+* License type: GPLv2 -+* -+* 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. -+* -+* This program is distributed in the hope that it will be useful, but WITHOUT -+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -+* -+* You should have received a copy of the GNU General Public License along with -+* this program; if not, write to the Free Software Foundation, Inc., -+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -+* -+* This program may alternatively be licensed under a proprietary license from -+* MaxLinear, Inc. -+* -+* See terms and conditions defined in file 'LICENSE.txt', which is part of this -+* source code package. -+*/ -+ -+#ifndef __MXL58X_REGISTERS_H__ -+#define __MXL58X_REGISTERS_H__ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define HYDRA_INTR_STATUS_REG 0x80030008 -+#define HYDRA_INTR_MASK_REG 0x8003000C -+ -+#define HYDRA_CRYSTAL_SETTING 0x3FFFC5F0 // 0 - 24 MHz & 1 - 27 MHz -+#define HYDRA_CRYSTAL_CAP 0x3FFFEDA4 // 0 - 24 MHz & 1 - 27 MHz -+ -+#define HYDRA_CPU_RESET_REG 0x8003003C -+#define HYDRA_CPU_RESET_DATA 0x00000400 -+ -+#define HYDRA_RESET_TRANSPORT_FIFO_REG 0x80030028 -+#define HYDRA_RESET_TRANSPORT_FIFO_DATA 0x00000000 -+ -+#define HYDRA_RESET_BBAND_REG 0x80030024 -+#define HYDRA_RESET_BBAND_DATA 0x00000000 -+ -+#define HYDRA_RESET_XBAR_REG 0x80030020 -+#define HYDRA_RESET_XBAR_DATA 0x00000000 -+ -+#define HYDRA_MODULES_CLK_1_REG 0x80030014 -+#define HYDRA_DISABLE_CLK_1 0x00000000 -+ -+#define HYDRA_MODULES_CLK_2_REG 0x8003001C -+#define HYDRA_DISABLE_CLK_2 0x0000000B -+ -+#define HYDRA_PRCM_ROOT_CLK_REG 0x80030018 -+#define HYDRA_PRCM_ROOT_CLK_DISABLE 0x00000000 -+ -+#define HYDRA_CPU_RESET_CHECK_REG 0x80030008 -+#define HYDRA_CPU_RESET_CHECK_OFFSET 0x40000000 // -+ -+#define HYDRA_SKU_ID_REG 0x90000190 -+ -+#define FW_DL_SIGN_ADDR 0x3FFFEAE0 -+ -+// Register to check if FW is running or not -+#define HYDRA_HEAR_BEAT 0x3FFFEDDC -+ -+// Firmware version -+#define HYDRA_FIRMWARE_VERSION 0x3FFFEDB8 -+#define HYDRA_FW_RC_VERSION 0x3FFFCFAC -+ -+// Firmware patch version -+#define HYDRA_FIRMWARE_PATCH_VERSION 0x3FFFEDC2 -+ -+// SOC operating temperature in C -+#define HYDRA_TEMPARATURE 0x3FFFEDB4 -+ -+// Demod & Tuner status registers -+// Demod 0 status base address -+#define HYDRA_DEMOD_0_BASE_ADDR 0x3FFFC64C -+ -+// Tuner 0 status base address -+#define HYDRA_TUNER_0_BASE_ADDR 0x3FFFCE4C -+ -+#define POWER_FROM_ADCRSSI_READBACK 0x3FFFEB6C -+ -+// Macros to determine base address of respective demod or tuner -+#define HYDRA_DMD_STATUS_OFFSET(demodID) ((demodID) * 0x100) -+#define HYDRA_TUNER_STATUS_OFFSET(tunerID) ((tunerID) * 0x40) -+ -+// Demod status address offset from respective demod's base address -+#define HYDRA_DMD_AGC_DIG_LEVEL_ADDR_OFFSET 0x3FFFC64C -+#define HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET 0x3FFFC650 -+#define HYDRA_DMD_ACQ_STATUS_ADDR_OFFSET 0x3FFFC654 -+ -+#define HYDRA_DMD_STANDARD_ADDR_OFFSET 0x3FFFC658 -+#define HYDRA_DMD_SPECTRUM_INVERSION_ADDR_OFFSET 0x3FFFC65C -+#define HYDRA_DMD_SPECTRUM_ROLL_OFF_ADDR_OFFSET 0x3FFFC660 -+#define HYDRA_DMD_SYMBOL_RATE_ADDR_OFFSET 0x3FFFC664 -+#define HYDRA_DMD_MODULATION_SCHEME_ADDR_OFFSET 0x3FFFC668 -+#define HYDRA_DMD_FEC_CODE_RATE_ADDR_OFFSET 0x3FFFC66C -+ -+#define HYDRA_DMD_SNR_ADDR_OFFSET 0x3FFFC670 -+#define HYDRA_DMD_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC674 -+#define HYDRA_DMD_CTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC678 -+#define HYDRA_DMD_STR_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC67C -+#define HYDRA_DMD_FTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC680 -+#define HYDRA_DMD_STR_NBC_SYNC_LOCK_ADDR_OFFSET 0x3FFFC684 -+#define HYDRA_DMD_CYCLE_SLIP_COUNT_ADDR_OFFSET 0x3FFFC688 -+ -+#define HYDRA_DMD_DISPLAY_I_ADDR_OFFSET 0x3FFFC68C -+#define HYDRA_DMD_DISPLAY_Q_ADDR_OFFSET 0x3FFFC68E -+ -+#define HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET 0x3FFFC690 -+#define HYDRA_DMD_DVBS2_PER_COUNT_ADDR_OFFSET 0x3FFFC694 -+#define HYDRA_DMD_DVBS2_PER_WINDOW_ADDR_OFFSET 0x3FFFC698 -+ -+#define HYDRA_DMD_DVBS_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC69C -+#define HYDRA_DMD_DVBS_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6A0 -+#define HYDRA_DMD_DVBS_BER_COUNT_ADDR_OFFSET 0x3FFFC6A4 -+#define HYDRA_DMD_DVBS_BER_WINDOW_ADDR_OFFSET 0x3FFFC6A8 -+ -+// Debug-purpose DVB-S DMD 0 -+#define HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6C8 // corrected RS Errors: 1st iteration -+#define HYDRA_DMD_DVBS_1ST_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6CC // uncorrected RS Errors: 1st iteration -+#define HYDRA_DMD_DVBS_BER_COUNT_1ST_ADDR_OFFSET 0x3FFFC6D0 -+#define HYDRA_DMD_DVBS_BER_WINDOW_1ST_ADDR_OFFSET 0x3FFFC6D4 -+ -+#define HYDRA_DMD_TUNER_ID_ADDR_OFFSET 0x3FFFC6AC -+#define HYDRA_DMD_DVBS2_PILOT_ON_OFF_ADDR_OFFSET 0x3FFFC6B0 -+#define HYDRA_DMD_FREQ_SEARCH_RANGE_KHZ_ADDR_OFFSET 0x3FFFC6B4 -+#define HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET 0x3FFFC6B8 -+#define HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR 0x3FFFC704 -+#define HYDRA_DMD_STATUS_INPUT_POWER_ADDR 0x3FFFC708 -+ -+// DVB-S new scaled_BER_count for a new BER API, see HYDRA-1343 "DVB-S post viterbi information" -+#define DMD0_STATUS_DVBS_1ST_SCALED_BER_COUNT_ADDR 0x3FFFC710 // DMD 0: 1st iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR -+#define DMD0_STATUS_DVBS_SCALED_BER_COUNT_ADDR 0x3FFFC714 // DMD 0: 2nd iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR -+ -+#define DMD0_SPECTRUM_MIN_GAIN_STATUS 0x3FFFC73C -+#define DMD0_SPECTRUM_MIN_GAIN_WB_SAGC_VALUE 0x3FFFC740 -+#define DMD0_SPECTRUM_ MIN_GAIN_NB_SAGC_VALUE 0x3FFFC744 -+ -+#define HYDRA_DMD_STATUS_END_ADDR_OFFSET 0x3FFFC748 -+ -+// Tuner status address offset from respective tuners's base address -+#define HYDRA_TUNER_DEMOD_ID_ADDR_OFFSET 0x3FFFCE4C -+#define HYDRA_TUNER_AGC_LOCK_OFFSET 0x3FFFCE50 -+#define HYDRA_TUNER_SPECTRUM_STATUS_OFFSET 0x3FFFCE54 -+#define HYDRA_TUNER_SPECTRUM_BIN_SIZE_OFFSET 0x3FFFCE58 -+#define HYDRA_TUNER_SPECTRUM_ADDRESS_OFFSET 0x3FFFCE5C -+#define HYDRA_TUNER_ENABLE_COMPLETE 0x3FFFEB78 -+ -+#define HYDRA_DEMOD_STATUS_LOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_YES) -+#define HYDRA_DEMOD_STATUS_UNLOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_NO) -+ -+#define HYDRA_TUNER_STATUS_LOCK(devId,tunerId) MxLWare_HYDRA_WriteRegister(devId,(HYDRA_TUNER_STATUS_LOCK_ADDR_OFFSET + HYDRA_TUNER_STATUS_OFFSET(tunerId)), MXL_YES) -+#define HYDRA_TUNER_STATUS_UNLOCK(devId,tunerId) MxLWare_HYDRA_WriteRegister(devId,(HYDRA_TUNER_STATUS_LOCK_ADDR_OFFSET + HYDRA_TUNER_STATUS_OFFSET(tunerId)), MXL_NO) -+ -+#define HYDRA_VERSION 0x3FFFEDB8 -+#define HYDRA_DEMOD0_VERSION 0x3FFFEDBC -+#define HYDRA_DEMOD1_VERSION 0x3FFFEDC0 -+#define HYDRA_DEMOD2_VERSION 0x3FFFEDC4 -+#define HYDRA_DEMOD3_VERSION 0x3FFFEDC8 -+#define HYDRA_DEMOD4_VERSION 0x3FFFEDCC -+#define HYDRA_DEMOD5_VERSION 0x3FFFEDD0 -+#define HYDRA_DEMOD6_VERSION 0x3FFFEDD4 -+#define HYDRA_DEMOD7_VERSION 0x3FFFEDD8 -+#define HYDRA_HEAR_BEAT 0x3FFFEDDC -+#define HYDRA_SKU_MGMT 0x3FFFEBC0 -+ -+#define MXL_HYDRA_FPGA_A_ADDRESS 0x91C00000 -+#define MXL_HYDRA_FPGA_B_ADDRESS 0x91D00000 -+ -+// TS control base address -+#define HYDRA_TS_CTRL_BASE_ADDR 0x90700000 -+ -+#define MPEG_MUX_MODE_SLICE0_REG HYDRA_TS_CTRL_BASE_ADDR + 0x08 -+#define MPEG_MUX_MODE_SLICE0_OFFSET (0),(2) -+ -+#define MPEG_MUX_MODE_SLICE1_REG HYDRA_TS_CTRL_BASE_ADDR + 0x08 -+#define MPEG_MUX_MODE_SLICE1_OFFSET (2),(2) -+ -+#define PID_BANK_SEL_SLICE0_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190 -+#define PID_BANK_SEL_SLICE1_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0 -+ -+#define SW_REGULAR_PID_SW_BANK_OFFSET 0,1 -+#define SW_FIXED_PID_SW_BANK_OFFSET 1,1 -+ -+#define HW_REGULAR_PID_BANK_OFFSET 8,4 -+#define HW_FIXED_PID_BANK_OFFSET 4,4 -+ -+#define MPEG_CLK_GATED_REG HYDRA_TS_CTRL_BASE_ADDR + 0x20 -+#define MPEG_CLK_GATED_OFFSET 0,1 -+ -+#define MPEG_CLK_ALWAYS_ON_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1D4 -+#define MPEG_CLK_ALWAYS_ON_OFFSET 0,1 -+ -+#define HYDRA_REGULAR_PID_BANK_A_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190 -+#define HYDRA_REGULAR_PID_BAN K_A_OFFSET 0,1 -+ -+#define HYDRA_FIXED_PID_BANK_A_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190 -+#define HYDRA_FIXED_PID_BANK_A_OFFSET 1,1 -+ -+#define HYDRA_REGULAR_PID_BANK_B_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0 -+#define HYDRA_REGULAR_PID_BANK_B_OFFSET 0,1 -+ -+#define HYDRA_FIXED_PID_BANK_B_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0 -+#define HYDRA_FIXED_PID_BANK_B_OFFSET 1,1 -+ -+#define FIXED_PID_TBL_REG_ADDRESS_0 HYDRA_TS_CTRL_BASE_ADDR + 0x9000 -+#define FIXED_PID_TBL_REG_ADDRESS_1 HYDRA_TS_CTRL_BASE_ADDR + 0x9100 -+#define FIXED_PID_TBL_REG_ADDRESS_2 HYDRA_TS_CTRL_BASE_ADDR + 0x9200 -+#define FIXED_PID_TBL_REG_ADDRESS_3 HYDRA_TS_CTRL_BASE_ADDR + 0x9300 -+ -+#define FIXED_PID_TBL_REG_ADDRESS_4 HYDRA_TS_CTRL_BASE_ADDR + 0xB000 -+#define FIXED_PID_TBL_REG_ADDRESS_5 HYDRA_TS_CTRL_BASE_ADDR + 0xB100 -+#define FIXED_PID_TBL_REG_ADDRESS_6 HYDRA_TS_CTRL_BASE_ADDR + 0xB200 -+#define FIXED_PID_TBL_REG_ADDRESS_7 HYDRA_TS_CTRL_BASE_ADDR + 0xB300 -+ -+#define REGULAR_PID_TBL_REG_ADDRESS_0 HYDRA_TS_CTRL_BASE_ADDR + 0x8000 -+#define REGULAR_PID_TBL_REG_ADDRESS_1 HYDRA_TS_CTRL_BASE_ADDR + 0x8200 -+#define REGULAR_PID_TBL_REG_ADDRESS_2 HYDRA_TS_CTRL_BASE_ADDR + 0x8400 -+#define REGULAR_PID_TBL_REG_ADDRESS_3 HYDRA_TS_CTRL_BASE_ADDR + 0x8600 -+ -+#define REGULAR_PID_TBL_REG_ADDRESS_4 HYDRA_TS_CTRL_BASE_ADDR + 0xA000 -+#define REGULAR_PID_TBL_REG_ADDRESS_5 HYDRA_TS_CTRL_BASE_ADDR + 0xA200 -+#define REGULAR_PID_TBL_REG_ADDRESS_6 HYDRA_TS_CTRL_BASE_ADDR + 0xA400 -+#define REGULAR_PID_TBL_REG_ADDRESS_7 HYDRA_TS_CTRL_BASE_ADDR + 0xA600 -+ -+#define PID_VALID_OFFSET 0,1 -+#define PID_DROP_OFFSET 1,1 -+#define PID_REMAP_ENABLE_OFFSET 2,1 -+#define PID_VALUE_OFFSET 4,13 -+#define PID_MASK_OFFSET 19,13 -+ -+#define REGULAR_PID_REMAP_VALUE_OFFSET 0,13 -+#define FIXED_PID_REMAP_VALUE_OFFSET 0,16 -+#define PID_DEMODID_OFFSET 16,3 -+ -+ -+/////////////////////////////////////////////// -+ -+#if 0 -+#define AFE_REG_D2A_TA_ADC_CLK_OUT_FLIP 0x90200004,12,1 -+#define AFE_REG_D2A_TA_RFFE_LNACAPLOAD_1P8 0x90200028,24,4 -+#define AFE_REG_D2A_TA_RFFE_RF1_EN_1P8 0x90200028,5,1 -+#define AFE_REG_D2A_TA_RFFE_SPARE_1P8 0x90200028,8,8 -+#define AFE_REG_D2A_TB_ADC_CLK_OUT_FLIP 0x9020000C,23,1 -+#define AFE_REG_D2A_TB_RFFE_LNACAPLOAD_1P8 0x90200030,16,4 -+#define AFE_REG_D2A_TB_RFFE_RF1_EN_1P8 0x9020002C,21,1 -+#define AFE_REG_D2A_TB_RFFE_SPARE_1P8 0x90200030,0,8 -+#define AFE_REG_D2A_TC_ADC_CLK_OUT_FLIP 0x90200018,7,1 -+#define AFE_REG_D2A_TC_RFFE_LNACAPLOAD_1P8 0x90200038,2,4 -+#define AFE_REG_D2A_TC_RFFE_RF1_EN_1P8 0x90200034,14,1 -+#define AFE_REG_D2A_TC_RFFE_SPARE_1P8 0x90200034,17,8 -+#define AFE_REG_D2A_TD_ADC_CLK_OUT_FLIP 0x90200020,18,1 -+#define AFE_REG_D2A_TD_RFFE_LNACAPLOAD_1P8 0x9020003C,17,4 -+#define AFE_REG_D2A_TD_RFFE_RF1_EN_1P8 0x90200038,29,1 -+#define AFE_REG_D2A_TD_RFFE_SPARE_1P8 0x9020003C,1,8 -+#endif -+#define AFE_REG_D2A_XTAL_EN_CLKOUT_1P8 0x90200054,23,1 -+ -+#define PAD_MUX_TS0_IN_CLK_PINMUX_SEL 0x90000018,0,3 -+#define PAD_MUX_TS0_IN_DATA_PINMUX_SEL 0x90000018,4,3 -+#define PAD_MUX_TS1_IN_CLK_PINMUX_SEL 0x90000018,8,3 -+#define PAD_MUX_TS1_IN_DATA_PINMUX_SEL 0x90000018,12,3 -+#define PAD_MUX_TS2_IN_CLK_PINMUX_SEL 0x90000018,16,3 -+#define PAD_MUX_TS2_IN_DATA_PINMUX_SEL 0x90000018,20,3 -+#define PAD_MUX_TS3_IN_CLK_PINMUX_SEL 0x90000018,24,3 -+#define PAD_MUX_TS3_IN_DATA_PINMUX_SEL 0x90000018,28,3 -+ -+#define PAD_MUX_GPIO_00_SYNC_BASEADDR 0x90000188 -+#define PAD_MUX_GPIO_01_SYNC_IN PAD_MUX_GPIO_00_SYNC_BASEADDR,1,1 -+ -+#define PRCM_AFE_SOC_ID 0x80030004,24,8 -+ -+#define PAD_MUX_UART_RX_C_PINMUX_BASEADDR 0x9000001C -+#define PAD_MUX_UART_RX_C_PINMUX_SEL PAD_MUX_UART_RX_C_PINMUX_BASEADDR,0,3 -+#define PAD_MUX_UART_RX_D_PINMUX_SEL PAD_MUX_UART_RX_C_PINMUX_BASEADDR,4,3 -+#define PAD_MUX_BOND_OPTION 0x90000190,0,3 -+#define PAD_MUX_DIGIO_01_PINMUX_SEL 0x9000016C,4,3 -+#define PAD_MUX_DIGIO_02_PINMUX_SEL 0x9000016C,8,3 -+#define PAD_MUX_DIGIO_03_PINMUX_SEL 0x9000016C,12,3 -+#define PAD_MUX_DIGIO_04_PINMUX_SEL 0x9000016C,16,3 -+#define PAD_MUX_DIGIO_05_PINMUX_SEL 0x9000016C,20,3 -+#define PAD_MUX_DIGIO_06_PINMUX_SEL 0x9000016C,24,3 -+#define PAD_MUX_DIGIO_07_PINMUX_SEL 0x9000016C,28,3 -+#define PAD_MUX_DIGIO_08_PINMUX_SEL 0x90000170,0,3 -+#define PAD_MUX_DIGIO_09_PINMUX_SEL 0x90000170,4,3 -+#define PAD_MUX_DIGIO_10_PINMUX_SEL 0x90000170,8,3 -+#define PAD_MUX_DIGIO_11_PINMUX_SEL 0x90000170,12,3 -+#define PAD_MUX_DIGIO_12_PINMUX_SEL 0x90000170,16,3 -+#define PAD_MUX_DIGIO_13_PINMUX_SEL 0x90000170,20,3 -+#define PAD_MUX_DIGIO_14_PINMUX_SEL 0x90000170,24,3 -+#define PAD_MUX_DIGIO_15_PINMUX_SEL 0x90000170,28,3 -+#define PAD_MUX_DIGIO_16_PINMUX_SEL 0x90000174,0,3 -+#define PAD_MUX_DIGIO_17_PINMUX_SEL 0x90000174,4,3 -+#define PAD_MUX_DIGIO_18_PINMUX_SEL 0x90000174,8,3 -+#define PAD_MUX_DIGIO_19_PINMUX_SEL 0x90000174,12,3 -+#define PAD_MUX_DIGIO_20_PINMUX_SEL 0x90000174,16,3 -+#define PAD_MUX_DIGIO_21_PINMUX_SEL 0x90000174,20,3 -+#define PAD_MUX_DIGIO_22_PINMUX_SEL 0x90000174,24,3 -+#define PAD_MUX_DIGIO_23_PINMUX_SEL 0x90000174,28,3 -+#define PAD_MUX_DIGIO_24_PINMUX_SEL 0x90000178,0,3 -+#define PAD_MUX_DIGIO_25_PINMUX_SEL 0x90000178,4,3 -+#define PAD_MUX_DIGIO_26_PINMUX_SEL 0x90000178,8,3 -+#define PAD_MUX_DIGIO_27_PINMUX_SEL 0x90000178,12,3 -+#define PAD_MUX_DIGIO_28_PINMUX_SEL 0x90000178,16,3 -+#define PAD_MUX_DIGIO_29_PINMUX_SEL 0x90000178,20,3 -+#define PAD_MUX_DIGIO_30_PINMUX_SEL 0x90000178,24,3 -+#define PAD_MUX_DIGIO_31_PINMUX_SEL 0x90000178,28,3 -+#define PAD_MUX_DIGIO_32_PINMUX_SEL 0x9000017C,0,3 -+#define PAD_MUX_DIGIO_33_PINMUX_SEL 0x9000017C,4,3 -+#define PAD_MUX_DIGIO_34_PINMUX_SEL 0x9000017C,8,3 -+#define PAD_MUX_EJTAG_TCK_PINMUX_SEL 0x90000020,0,3 -+#define PAD_MUX_EJTAG_TDI_PINMUX_SEL 0x90000020,8,3 -+#define PAD_MUX_EJTAG_TMS_PINMUX_SEL 0x90000020,4,3 -+#define PAD_MUX_EJTAG_TRSTN_PINMUX_SEL 0x90000020,12,3 -+#define PAD_MUX_PAD_DRV_DIGIO_00 0x90000194,0,3 -+#define PAD_MUX_PAD_DRV_DIGIO_05 0x90000194,20,3 -+#define PAD_MUX_PAD_DRV_DIGIO_06 0x90000194,24,3 -+#define PAD_MUX_PAD_DRV_DIGIO_11 0x90000198,12,3 -+#define PAD_MUX_PAD_DRV_DIGIO_12 0x90000198,16,3 -+#define PAD_MUX_PAD_DRV_DIGIO_13 0x90000198,20,3 -+#define PAD_MUX_PAD_DRV_DIGIO_14 0x90000198,24,3 -+#define PAD_MUX_PAD_DRV_DIGIO_16 0x9000019C,0,3 -+#define PAD_MUX_PAD_DRV_DIGIO_17 0x9000019C,4,3 -+#define PAD_MUX_PAD_DRV_DIGIO_18 0x9000019C,8,3 -+#define PAD_MUX_PAD_DRV_DIGIO_22 0x9000019C,24,3 -+#define PAD_MUX_PAD_DRV_DIGIO_23 0x9000019C,28,3 -+#define PAD_MUX_PAD_DRV_DIGIO_24 0x900001A0,0,3 -+#define PAD_MUX_PAD_DRV_DIGIO_25 0x900001A0,4,3 -+#define PAD_MUX_PAD_DRV_DIGIO_29 0x900001A0,20,3 -+#define PAD_MUX_PAD_DRV_DIGIO_30 0x900001A0,24,3 -+#define PAD_MUX_PAD_DRV_DIGIO_31 0x900001A0,28,3 -+#define PRCM_AFE_REG_CLOCK_ENABLE 0x80030014,9,1 -+#define PRCM_CHIP_VERSION 0x80030000,12,4 -+#define PRCM_AFE_CHIP_MMSK_VER 0x80030004,8,8 -+#define PRCM_PRCM_AFE_REG_SOFT_RST_N 0x8003003C,12,1 -+#define PRCM_PRCM_CPU_SOFT_RST_N 0x8003003C,0,1 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB0 0x80030074,0,20 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB1 0x80030078,0,20 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB2 0x8003007C,0,20 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB3 0x80030080,0,20 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB4 0x80030084,0,20 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB5 0x80030088,0,20 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB6 0x8003008C,0,20 -+#define PRCM_PRCM_DIGRF_APB_DATA_BB7 0x80030090,0,20 -+#define PRCM_PRCM_DIGRF_CAPT_DONE 0x80030070,24,8 -+#define PRCM_PRCM_DIGRF_START_CAPT 0x80030064,2,1 -+#define PRCM_PRCM_PAD_MUX_SOFT_RST_N 0x8003003C,11,1 -+#define PRCM_PRCM_XPT_PARALLEL_FIFO_RST_N 0x80030028,20,1 -+#define XPT_APPEND_BYTES0 0x90700008,4,2 -+#define XPT_APPEND_BYTES1 0x90700008,6,2 -+#define XPT_CLOCK_POLARITY0 0x90700010,16,1 -+#define XPT_CLOCK_POLARITY1 0x90700010,17,1 -+#define XPT_CLOCK_POLARITY2 0x90700010,18,1 -+#define XPT_CLOCK_POLARITY3 0x90700010,19,1 -+#define XPT_CLOCK_POLARITY4 0x90700010,20,1 -+#define XPT_CLOCK_POLARITY5 0x90700010,21,1 -+#define XPT_CLOCK_POLARITY6 0x90700010,22,1 -+#define XPT_CLOCK_POLARITY7 0x90700010,23,1 -+#define XPT_DSS_DVB_ENCAP_EN0 0x90700000,16,1 -+#define XPT_DSS_DVB_ENCAP_EN1 0x90700000,17,1 -+#define XPT_DSS_DVB_ENCAP_EN2 0x90700000,18,1 -+#define XPT_DSS_DVB_ENCAP_EN3 0x90700000,19,1 -+#define XPT_DSS_DVB_ENCAP_EN4 0x90700000,20,1 -+#define XPT_DSS_DVB_ENCAP_EN5 0x90700000,21,1 -+#define XPT_DSS_DVB_ENCAP_EN6 0x90700000,22,1 -+#define XPT_DSS_DVB_ENCAP_EN7 0x90700000,23,1 -+#define XPT_DVB_MATCH_BYTE 0x9070017C,16,8 -+#define XPT_DVB_PACKET_SIZE0 0x90700180,0,8 -+#define XPT_DVB_PACKET_SIZE1 0x90700180,8,8 -+#define XPT_DVB_PACKET_SIZE2 0x90700180,16,8 -+#define XPT_DVB_PACKET_SIZE3 0x90700180,24,8 -+#define XPT_ENABLE_DVB_INPUT0 0x90700178,0,1 -+#define XPT_ENABLE_DVB_INPUT1 0x90700178,1,1 -+#define XPT_ENABLE_DVB_INPUT2 0x90700178,2,1 -+#define XPT_ENABLE_DVB_INPUT3 0x90700178,3,1 -+#define XPT_ENABLE_INPUT0 0x90700000,0,1 -+#define XPT_ENABLE_INPUT1 0x90700000,1,1 -+#define XPT_ENABLE_INPUT2 0x90700000,2,1 -+#define XPT_ENABLE_INPUT3 0x90700000,3,1 -+#define XPT_ENABLE_INPUT4 0x90700000,4,1 -+#define XPT_ENABLE_INPUT5 0x90700000,5,1 -+#define XPT_ENABLE_INPUT6 0x90700000,6,1 -+#define XPT_ENABLE_INPUT7 0x90700000,7,1 -+#define XPT_ENABLE_OUTPUT0 0x9070000C,0,1 -+#define XPT_ENABLE_OUTPUT1 0x9070000C,1,1 -+#define XPT_ENABLE_OUTPUT2 0x9070000C,2,1 -+#define XPT_ENABLE_OUTPUT3 0x9070000C,3,1 -+#define XPT_ENABLE_OUTPUT4 0x9070000C,4,1 -+#define XPT_ENABLE_OUTPUT5 0x9070000C,5,1 -+#define XPT_ENABLE_OUTPUT6 0x9070000C,6,1 -+#define XPT_ENABLE_OUTPUT7 0x9070000C,7,1 -+#define XPT_ENABLE_PARALLEL_OUTPUT 0x90700010,27,1 -+#define XPT_ENABLE_PCR_COUNT 0x90700184,1,1 -+#define XPT_ERROR_REPLACE_SYNC0 0x9070000C,24,1 -+#define XPT_ERROR_REPLACE_SYNC1 0x9070000C,25,1 -+#define XPT_ERROR_REPLACE_SYNC2 0x9070000C,26,1 -+#define XPT_ERROR_REPLACE_SYNC3 0x9070000C,27,1 -+#define XPT_ERROR_REPLACE_SYNC4 0x9070000C,28,1 -+#define XPT_ERROR_REPLACE_SYNC5 0x9070000C,29,1 -+#define XPT_ERROR_REPLACE_SYNC6 0x9070000C,30,1 -+#define XPT_ERROR_REPLACE_SYNC7 0x9070000C,31,1 -+#define XPT_ERROR_REPLACE_VALID0 0x90700014,8,1 -+#define XPT_ERROR_REPLACE_VALID1 0x90700014,9,1 -+#define XPT_ERROR_REPLACE_VALID2 0x90700014,10,1 -+#define XPT_ERROR_REPLACE_VALID3 0x90700014,11,1 -+#define XPT_ERROR_REPLACE_VALID4 0x90700014,12,1 -+#define XPT_ERROR_REPLACE_VALID5 0x90700014,13,1 -+#define XPT_ERROR_REPLACE_VALID6 0x90700014,14,1 -+#define XPT_ERROR_REPLACE_VALID7 0x90700014,15,1 -+#define XPT_INP0_MERGE_HDR0 0x90700058,0,32 -+#define XPT_INP0_MERGE_HDR1 0x9070005C,0,32 -+#define XPT_INP0_MERGE_HDR2 0x90700060,0,32 -+#define XPT_INP1_MERGE_HDR0 0x90700064,0,32 -+#define XPT_INP1_MERGE_HDR1 0x90700068,0,32 -+#define XPT_INP1_MERGE_HDR2 0x9070006C,0,32 -+#define XPT_INP2_MERGE_HDR0 0x90700070,0,32 -+#define XPT_INP2_MERGE_HDR1 0x90700074,0,32 -+#define XPT_INP2_MERGE_HDR2 0x90700078,0,32 -+#define XPT_INP3_MERGE_HDR0 0x9070007C,0,32 -+#define XPT_INP3_MERGE_HDR1 0x90700080,0,32 -+#define XPT_INP3_MERGE_HDR2 0x90700084,0,32 -+#define XPT_INP4_MERGE_HDR0 0x90700088,0,32 -+#define XPT_INP4_MERGE_HDR1 0x9070008C,0,32 -+#define XPT_INP4_MERGE_HDR2 0x90700090,0,32 -+#define XPT_INP5_MERGE_HDR0 0x90700094,0,32 -+#define XPT_INP5_MERGE_HDR1 0x90700098,0,32 -+#define XPT_INP5_MERGE_HDR2 0x9070009C,0,32 -+#define XPT_INP6_MERGE_HDR0 0x907000A0,0,32 -+#define XPT_INP6_MERGE_HDR1 0x907000A4,0,32 -+#define XPT_INP6_MERGE_HDR2 0x907000A8,0,32 -+#define XPT_INP7_MERGE_HDR0 0x907000AC,0,32 -+#define XPT_INP7_MERGE_HDR1 0x907000B0,0,32 -+#define XPT_INP7_MERGE_HDR2 0x907000B4,0,32 -+#define XPT_INP_MODE_DSS0 0x90700000,8,1 -+#define XPT_INP_MODE_DSS1 0x90700000,9,1 -+#define XPT_INP_MODE_DSS2 0x90700000,10,1 -+#define XPT_INP_MODE_DSS3 0x90700000,11,1 -+#define XPT_INP_MODE_DSS4 0x90700000,12,1 -+#define XPT_INP_MODE_DSS5 0x90700000,13,1 -+#define XPT_INP_MODE_DSS6 0x90700000,14,1 -+#define XPT_INP_MODE_DSS7 0x90700000,15,1 -+#define XPT_KNOWN_PID_MUX_SELECT0 0x90700190,8,4 -+#define XPT_KNOWN_PID_MUX_SELECT1 0x907001B0,8,4 -+#define XPT_LSB_FIRST0 0x9070000C,16,1 -+#define XPT_LSB_FIRST1 0x9070000C,17,1 -+#define XPT_LSB_FIRST2 0x9070000C,18,1 -+#define XPT_LSB_FIRST3 0x9070000C,19,1 -+#define XPT_LSB_FIRST4 0x9070000C,20,1 -+#define XPT_LSB_FIRST5 0x9070000C,21,1 -+#define XPT_LSB_FIRST6 0x9070000C,22,1 -+#define XPT_LSB_FIRST7 0x9070000C,23,1 -+#define XPT_MODE_27MHZ 0x90700184,0,1 -+#define XPT_NCO_COUNT_MIN 0x90700044,16,8 -+#define XPT_OUTPUT_MODE_DSS0 0x9070000C,8,1 -+#define XPT_OUTPUT_MODE_DSS1 0x9070000C,9,1 -+#define XPT_OUTPUT_MODE_DSS2 0x9070000C,10,1 -+#define XPT_OUTPUT_MODE_DSS3 0x9070000C,11,1 -+#define XPT_OUTPUT_MODE_DSS4 0x9070000C,12,1 -+#define XPT_OUTPUT_MODE_DSS5 0x9070000C,13,1 -+#define XPT_OUTPUT_MODE_DSS6 0x9070000C,14,1 -+#define XPT_OUTPUT_MODE_DSS7 0x9070000C,15,1 -+#define XPT_OUTPUT_MODE_MUXGATING0 0x90700020,0,1 -+#define XPT_OUTPUT_MODE_MUXGATING1 0x90700020,1,1 -+#define XPT_OUTPUT_MODE_MUXGATING2 0x90700020,2,1 -+#define XPT_OUTPUT_MODE_MUXGATING3 0x90700020,3,1 -+#define XPT_OUTPUT_MODE_MUXGATING4 0x90700020,4,1 -+#define XPT_OUTPUT_MODE_MUXGATING5 0x90700020,5,1 -+#define XPT_OUTPUT_MODE_MUXGATING6 0x90700020,6,1 -+#define XPT_OUTPUT_MODE_MUXGATING7 0x90700020,7,1 -+#define XPT_OUTPUT_MUXSELECT0 0x9070001C,0,3 -+#define XPT_OUTPUT_MUXSELECT1 0x9070001C,4,3 -+#define XPT_OUTPUT_MUXSELECT2 0x9070001C,8,3 -+#define XPT_OUTPUT_MUXSELECT3 0x9070001C,12,3 -+#define XPT_OUTPUT_MUXSELECT4 0x9070001C,16,3 -+#define XPT_OUTPUT_MUXSELECT5 0x9070001C,20,3 -+#define XPT_PCR_RTS_CORRECTION_ENABLE 0x90700008,14,1 -+#define XPT_PID_DEFAULT_DROP0 0x90700190,12,1 -+#define XPT_PID_DEFAULT_DROP1 0x90700190,13,1 -+#define XPT_PID_DEFAULT_DROP2 0x90700190,14,1 -+#define XPT_PID_DEFAULT_DROP3 0x90700190,15,1 -+#define XPT_PID_DEFAULT_DROP4 0x907001B0,12,1 -+#define XPT_PID_DEFAULT_DROP5 0x907001B0,13,1 -+#define XPT_PID_DEFAULT_DROP6 0x907001B0,14,1 -+#define XPT_PID_DEFAULT_DROP7 0x907001B0,15,1 -+#define XPT_PID_MUX_SELECT0 0x90700190,4,4 -+#define XPT_PID_MUX_SELECT1 0x907001B0,4,4 -+#define XPT_STREAM_MUXMODE0 0x90700008,0,2 -+#define XPT_STREAM_MUXMODE1 0x90700008,2,2 -+#define XPT_SYNC_FULL_BYTE0 0x90700010,0,1 -+#define XPT_SYNC_FULL_BYTE1 0x90700010,1,1 -+#define XPT_SYNC_FULL_BYTE2 0x90700010,2,1 -+#define XPT_SYNC_FULL_BYTE3 0x90700010,3,1 -+#define XPT_SYNC_FULL_BYTE4 0x90700010,4,1 -+#define XPT_SYNC_FULL_BYTE5 0x90700010,5,1 -+#define XPT_SYNC_FULL_BYTE6 0x90700010,6,1 -+#define XPT_SYNC_FULL_BYTE7 0x90700010,7,1 -+#define XPT_SYNC_LOCK_THRESHOLD 0x9070017C,0,8 -+#define XPT_SYNC_MISS_THRESHOLD 0x9070017C,8,8 -+#define XPT_SYNC_POLARITY0 0x90700010,8,1 -+#define XPT_SYNC_POLARITY1 0x90700010,9,1 -+#define XPT_SYNC_POLARITY2 0x90700010,10,1 -+#define XPT_SYNC_POLARITY3 0x90700010,11,1 -+#define XPT_SYNC_POLARITY4 0x90700010,12,1 -+#define XPT_SYNC_POLARITY5 0x90700010,13,1 -+#define XPT_SYNC_POLARITY6 0x90700010,14,1 -+#define XPT_SYNC_POLARITY7 0x90700010,15,1 -+#define XPT_TS_CLK_OUT_EN0 0x907001D4,0,1 -+#define XPT_TS_CLK_OUT_EN1 0x907001D4,1,1 -+#define XPT_TS_CLK_OUT_EN2 0x907001D4,2,1 -+#define XPT_TS_CLK_OUT_EN3 0x907001D4,3,1 -+#define XPT_TS_CLK_OUT_EN4 0x907001D4,4,1 -+#define XPT_TS_CLK_OUT_EN5 0x907001D4,5,1 -+#define XPT_TS_CLK_OUT_EN6 0x907001D4,6,1 -+#define XPT_TS_CLK_OUT_EN7 0x907001D4,7,1 -+#define XPT_TS_CLK_OUT_EN_PARALLEL 0x907001D4,8,1 -+#define XPT_TS_CLK_PHASE0 0x90700018,0,3 -+#define XPT_TS_CLK_PHASE1 0x90700018,4,3 -+#define XPT_TS_CLK_PHASE2 0x90700018,8,3 -+#define XPT_TS_CLK_PHASE3 0x90700018,12,3 -+#define XPT_TS_CLK_PHASE4 0x90700018,16,3 -+#define XPT_TS_CLK_PHASE5 0x90700018,20,3 -+#define XPT_TS_CLK_PHASE6 0x90700018,24,3 -+#define XPT_TS_CLK_PHASE7 0x90700018,28,3 -+#define XPT_VALID_POLARITY0 0x90700014,0,1 -+#define XPT_VALID_POLARITY1 0x90700014,1,1 -+#define XPT_VALID_POLARITY2 0x90700014,2,1 -+#define XPT_VALID_POLARITY3 0x90700014,3,1 -+#define XPT_VALID_POLARITY4 0x90700014,4,1 -+#define XPT_VALID_POLARITY5 0x90700014,5,1 -+#define XPT_VALID_POLARITY6 0x90700014,6,1 -+#define XPT_VALID_POLARITY7 0x90700014,7,1 -+#define XPT_ZERO_FILL_COUNT 0x90700008,8,6 -+ -+#define XPT_PACKET_GAP_MIN_BASEADDR 0x90700044 -+#define XPT_PACKET_GAP_MIN_TIMER XPT_PACKET_GAP_MIN_BASEADDR,0,16 -+#define XPT_NCO_COUNT_MIN0 XPT_PACKET_GAP_MIN_BASEADDR,16,8 -+#define XPT_NCO_COUNT_BASEADDR 0x90700238 -+#define XPT_NCO_COUNT_MIN1 XPT_NCO_COUNT_BASEADDR,0,8 -+#define XPT_NCO_COUNT_MIN2 XPT_NCO_COUNT_BASEADDR,8,8 -+#define XPT_NCO_COUNT_MIN3 XPT_NCO_COUNT_BASEADDR,16,8 -+#define XPT_NCO_COUNT_MIN4 XPT_NCO_COUNT_BASEADDR,24,8 -+ -+#define XPT_NCO_COUNT_BASEADDR1 0x9070023C -+#define XPT_NCO_COUNT_MIN5 XPT_NCO_COUNT_BASEADDR1,0,8 -+#define XPT_NCO_COUNT_MIN6 XPT_NCO_COUNT_BASEADDR1,8,8 -+#define XPT_NCO_COUNT_MIN7 XPT_NCO_COUNT_BASEADDR1,16,8 -+ -+// V2 DigRF status register -+#define BB0_DIGRF_CAPT_DONE 0x908000CC,0,1 -+#define PRCM_PRCM_CHIP_ID 0x80030000,0,12 -+ -+#define XPT_PID_BASEADDR 0x90708000 -+#define XPT_PID_VALID0 XPT_PID_BASEADDR,0,1 -+#define XPT_PID_DROP0 XPT_PID_BASEADDR,1,1 -+#define XPT_PID_REMAP0 XPT_PID_BASEADDR,2,1 -+#define XPT_PID_VALUE0 XPT_PID_BASEADDR,4,13 -+#define XPT_PID_MASK0 XPT_PID_BASEADDR,19,13 -+ -+#define XPT_PID_REMAP_BASEADDR 0x90708004 -+#define XPT_PID_REMAP_VALUE0 XPT_PID_REMAP_BASEADDR,0,13 -+#define XPT_PID_PORT_ID0 XPT_PID_REMAP_BASEADDR,16,3 -+ -+#define XPT_KNOWN_PID_BASEADDR 0x90709000 -+#define XPT_KNOWN_PID_VALID0 XPT_KNOWN_PID_BASEADDR,0,1 -+#define XPT_KNOWN_PID_DROP0 XPT_KNOWN_PID_BASEADDR,1,1 -+#define XPT_KNOWN_PID_REMAP0 XPT_KNOWN_PID_BASEADDR,2,1 -+#define XPT_KNOWN_PID_REMAP_VALUE0 XPT_KNOWN_PID_BASEADDR,16,13 -+ -+#define XPT_PID_BASEADDR1 0x9070A000 -+#define XPT_PID_VALID1 XPT_PID_BASEADDR1,0,1 -+#define XPT_PID_DROP1 XPT_PID_BASEADDR1,1,1 -+#define XPT_PID_REMAP1 XPT_PID_BASEADDR1,2,1 -+#define XPT_PID_VALUE1 XPT_PID_BASEADDR1,4,13 -+#define XPT_PID_MASK1 XPT_PID_BASEADDR1,19,13 -+ -+#define XPT_PID_REMAP_BASEADDR1 0x9070A004 -+#define XPT_PID_REMAP_VALUE1 XPT_PID_REMAP_BASEADDR1,0,13 -+ -+#define XPT_KNOWN_PID_BASEADDR1 0x9070B000 -+#define XPT_KNOWN_PID_VALID1 XPT_KNOWN_PID_BASEADDR1,0,1 -+#define XPT_KNOWN_PID_DROP1 XPT_KNOWN_PID_BASEADDR1,1,1 -+#define XPT_KNOWN_PID_REMAP1 XPT_KNOWN_PID_BASEADDR1,2,1 -+#define XPT_KNOWN_PID_REMAP_VALUE1 XPT_KNOWN_PID_BASEADDR1,16,13 -+ -+#define XPT_BERT_LOCK_BASEADDR 0x907000B8 -+#define XPT_BERT_LOCK_THRESHOLD XPT_BERT_LOCK_BASEADDR,0,8 -+#define XPT_BERT_LOCK_WINDOW XPT_BERT_LOCK_BASEADDR,8,8 -+ -+#define XPT_BERT_BASEADDR 0x907000BC -+#define XPT_BERT_ENABLE0 XPT_BERT_BASEADDR,0,1 -+#define XPT_BERT_ENABLE1 XPT_BERT_BASEADDR,1,1 -+#define XPT_BERT_ENABLE2 XPT_BERT_BASEADDR,2,1 -+#define XPT_BERT_ENABLE3 XPT_BERT_BASEADDR,3,1 -+#define XPT_BERT_ENABLE4 XPT_BERT_BASEADDR,4,1 -+#define XPT_BERT_ENABLE5 XPT_BERT_BASEADDR,5,1 -+#define XPT_BERT_ENABLE6 XPT_BERT_BASEADDR,6,1 -+#define XPT_BERT_ENABLE7 XPT_BERT_BASEADDR,7,1 -+#define XPT_BERT_SEQUENCE_PN23_0 XPT_BERT_BASEADDR,8,1 -+#define XPT_BERT_SEQUENCE_PN23_1 XPT_BERT_BASEADDR,9,1 -+#define XPT_BERT_SEQUENCE_PN23_2 XPT_BERT_BASEADDR,10,1 -+#define XPT_BERT_SEQUENCE_PN23_3 XPT_BERT_BASEADDR,11,1 -+#define XPT_BERT_SEQUENCE_PN23_4 XPT_BERT_BASEADDR,12,1 -+#define XPT_BERT_SEQUENCE_PN23_5 XPT_BERT_BASEADDR,13,1 -+#define XPT_BERT_SEQUENCE_PN23_6 XPT_BERT_BASEADDR,14,1 -+#define XPT_BERT_SEQUENCE_PN23_7 XPT_BERT_BASEADDR,15,1 -+#define XPT_LOCK_RESYNC0 XPT_BERT_BASEADDR,16,1 -+#define XPT_LOCK_RESYNC1 XPT_BERT_BASEADDR,17,1 -+#define XPT_LOCK_RESYNC2 XPT_BERT_BASEADDR,18,1 -+#define XPT_LOCK_RESYNC3 XPT_BERT_BASEADDR,19,1 -+#define XPT_LOCK_RESYNC4 XPT_BERT_BASEADDR,20,1 -+#define XPT_LOCK_RESYNC5 XPT_BERT_BASEADDR,21,1 -+#define XPT_LOCK_RESYNC6 XPT_BERT_BASEADDR,22,1 -+#define XPT_LOCK_RESYNC7 XPT_BERT_BASEADDR,23,1 -+#define XPT_BERT_DATA_POLARITY0 XPT_BERT_BASEADDR,24,1 -+#define XPT_BERT_DATA_POLARITY1 XPT_BERT_BASEADDR,25,1 -+#define XPT_BERT_DATA_POLARITY2 XPT_BERT_BASEADDR,26,1 -+#define XPT_BERT_DATA_POLARITY3 XPT_BERT_BASEADDR,27,1 -+#define XPT_BERT_DATA_POLARITY4 XPT_BERT_BASEADDR,28,1 -+#define XPT_BERT_DATA_POLARITY5 XPT_BERT_BASEADDR,29,1 -+#define XPT_BERT_DATA_POLARITY6 XPT_BERT_BASEADDR,30,1 -+#define XPT_BERT_DATA_POLARITY7 XPT_BERT_BASEADDR,31,1 -+ -+#define XPT_BERT_INVERT_BASEADDR 0x907000C0 -+#define XPT_BERT_INVERT_DATA0 XPT_BERT_INVERT_BASEADDR,0,1 -+#define XPT_BERT_INVERT_DATA1 XPT_BERT_INVERT_BASEADDR,1,1 -+#define XPT_BERT_INVERT_DATA2 XPT_BERT_INVERT_BASEADDR,2,1 -+#define XPT_BERT_INVERT_DATA3 XPT_BERT_INVERT_BASEADDR,3,1 -+#define XPT_BERT_INVERT_DATA4 XPT_BERT_INVERT_BASEADDR,4,1 -+#define XPT_BERT_INVERT_DATA5 XPT_BERT_INVERT_BASEADDR,5,1 -+#define XPT_BERT_INVERT_DATA6 XPT_BERT_INVERT_BASEADDR,6,1 -+#define XPT_BERT_INVERT_DATA7 XPT_BERT_INVERT_BASEADDR,7,1 -+#define XPT_BERT_INVERT_SEQUENCE0 XPT_BERT_INVERT_BASEADDR,8,1 -+#define XPT_BERT_INVERT_SEQUENCE1 XPT_BERT_INVERT_BASEADDR,9,1 -+#define XPT_BERT_INVERT_SEQUENCE2 XPT_BERT_INVERT_BASEADDR,10,1 -+#define XPT_BERT_INVERT_SEQUENCE3 XPT_BERT_INVERT_BASEADDR,11,1 -+#define XPT_BERT_INVERT_SEQUENCE4 XPT_BERT_INVERT_BASEADDR,12,1 -+#define XPT_BERT_INVERT_SEQUENCE5 XPT_BERT_INVERT_BASEADDR,13,1 -+#define XPT_BERT_INVERT_SEQUENCE6 XPT_BERT_INVERT_BASEADDR,14,1 -+#define XPT_BERT_INVERT_SEQUENCE7 XPT_BERT_INVERT_BASEADDR,15,1 -+#define XPT_BERT_OUTPUT_POLARITY0 XPT_BERT_INVERT_BASEADDR,16,1 -+#define XPT_BERT_OUTPUT_POLARITY1 XPT_BERT_INVERT_BASEADDR,17,1 -+#define XPT_BERT_OUTPUT_POLARITY2 XPT_BERT_INVERT_BASEADDR,18,1 -+#define XPT_BERT_OUTPUT_POLARITY3 XPT_BERT_INVERT_BASEADDR,19,1 -+#define XPT_BERT_OUTPUT_POLARITY4 XPT_BERT_INVERT_BASEADDR,20,1 -+#define XPT_BERT_OUTPUT_POLARITY5 XPT_BERT_INVERT_BASEADDR,21,1 -+#define XPT_BERT_OUTPUT_POLARITY6 XPT_BERT_INVERT_BASEADDR,22,1 -+#define XPT_BERT_OUTPUT_POLARITY7 XPT_BERT_INVERT_BASEADDR,23,1 -+ -+#define XPT_BERT_HEADER_BASEADDR 0x907000C4 -+#define XPT_BERT_HEADER_MODE0 XPT_BERT_HEADER_BASEADDR,0,2 -+#define XPT_BERT_HEADER_MODE1 XPT_BERT_HEADER_BASEADDR,2,2 -+#define XPT_BERT_HEADER_MODE2 XPT_BERT_HEADER_BASEADDR,4,2 -+#define XPT_BERT_HEADER_MODE3 XPT_BERT_HEADER_BASEADDR,6,2 -+#define XPT_BERT_HEADER_MODE4 XPT_BERT_HEADER_BASEADDR,8,2 -+#define XPT_BERT_HEADER_MODE5 XPT_BERT_HEADER_BASEADDR,10,2 -+#define XPT_BERT_HEADER_MODE6 XPT_BERT_HEADER_BASEADDR,12,2 -+#define XPT_BERT_HEADER_MODE7 XPT_BERT_HEADER_BASEADDR,14,2 -+ -+#define XPT_BERT_BASEADDR1 0x907000C8 -+#define XPT_BERT_LOCKED0 XPT_BERT_BASEADDR1,0,1 -+#define XPT_BERT_LOCKED1 XPT_BERT_BASEADDR1,1,1 -+#define XPT_BERT_LOCKED2 XPT_BERT_BASEADDR1,2,1 -+#define XPT_BERT_LOCKED3 XPT_BERT_BASEADDR1,3,1 -+#define XPT_BERT_LOCKED4 XPT_BERT_BASEADDR1,4,1 -+#define XPT_BERT_LOCKED5 XPT_BERT_BASEADDR1,5,1 -+#define XPT_BERT_LOCKED6 XPT_BERT_BASEADDR1,6,1 -+#define XPT_BERT_LOCKED7 XPT_BERT_BASEADDR1,7,1 -+#define XPT_BERT_BIT_COUNT_SAT0 XPT_BERT_BASEADDR1,8,1 -+#define XPT_BERT_BIT_COUNT_SAT1 XPT_BERT_BASEADDR1,9,1 -+#define XPT_BERT_BIT_COUNT_SAT2 XPT_BERT_BASEADDR1,10,1 -+#define XPT_BERT_BIT_COUNT_SAT3 XPT_BERT_BASEADDR1,11,1 -+#define XPT_BERT_BIT_COUNT_SAT4 XPT_BERT_BASEADDR1,12,1 -+#define XPT_BERT_BIT_COUNT_SAT5 XPT_BERT_BASEADDR1,13,1 -+#define XPT_BERT_BIT_COUNT_SAT6 XPT_BERT_BASEADDR1,14,1 -+#define XPT_BERT_BIT_COUNT_SAT7 XPT_BERT_BASEADDR1,15,1 -+ -+#define XPT_BERT_BIT_COUNT0_BASEADDR 0x907000CC -+#define XPT_BERT_BIT_COUNT0_LO XPT_BERT_BIT_COUNT0_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT0_BASEADDR1 0x907000D0 -+#define XPT_BERT_BIT_COUNT0_HI XPT_BERT_BIT_COUNT0_BASEADDR1,0,18 -+ -+#define XPT_BERT_BIT_COUNT1_BASEADDR 0x907000D4 -+#define XPT_BERT_BIT_COUNT1_LO XPT_BERT_BIT_COUNT1_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT1_BASEADDR1 0x907000D8 -+#define XPT_BERT_BIT_COUNT1_HI XPT_BERT_BIT_COUNT1_BASEADDR1,0,18 -+ -+#define XPT_BERT_BIT_COUNT2_BASEADDR 0x907000DC -+#define XPT_BERT_BIT_COUNT2_LO XPT_BERT_BIT_COUNT2_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT2_BASEADDR1 0x907000E0 -+#define XPT_BERT_BIT_COUNT2_HI XPT_BERT_BIT_COUNT2_BASEADDR1,0,18 -+ -+#define XPT_BERT_BIT_COUNT3_BASEADDR 0x907000E4 -+#define XPT_BERT_BIT_COUNT3_LO XPT_BERT_BIT_COUNT3_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT3_BASEADDR1 0x907000E8 -+#define XPT_BERT_BIT_COUNT3_HI XPT_BERT_BIT_COUNT3_BASEADDR1,0,18 -+ -+#define XPT_BERT_BIT_COUNT4_BASEADDR 0x907000EC -+#define XPT_BERT_BIT_COUNT4_LO XPT_BERT_BIT_COUNT4_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT4_BASEADDR1 0x907000F0 -+#define XPT_BERT_BIT_COUNT4_HI XPT_BERT_BIT_COUNT4_BASEADDR1,0,18 -+ -+#define XPT_BERT_BIT_COUNT5_BASEADDR 0x907000F4 -+#define XPT_BERT_BIT_COUNT5_LO XPT_BERT_BIT_COUNT5_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT5_BASEADDR1 0x907000F8 -+#define XPT_BERT_BIT_COUNT5_HI XPT_BERT_BIT_COUNT5_BASEADDR1,0,18 -+ -+#define XPT_BERT_BIT_COUNT6_BASEADDR 0x907000FC -+#define XPT_BERT_BIT_COUNT6_LO XPT_BERT_BIT_COUNT6_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT6_BASEADDR1 0x90700100 -+#define XPT_BERT_BIT_COUNT6_HI XPT_BERT_BIT_COUNT6_BASEADDR1,0,18 -+ -+#define XPT_BERT_BIT_COUNT7_BASEADDR 0x90700104 -+#define XPT_BERT_BIT_COUNT7_LO XPT_BERT_BIT_COUNT7_BASEADDR,0,32 -+ -+#define XPT_BERT_BIT_COUNT7_BASEADDR1 0x90700108 -+#define XPT_BERT_BIT_COUNT7_HI XPT_BERT_BIT_COUNT7_BASEADDR1,0,18 -+ -+#define XPT_BERT_ERR_COUNT0_BASEADDR 0x9070010C -+#define XPT_BERT_ERR_COUNT0_LO XPT_BERT_ERR_COUNT0_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT0_BASEADDR1 0x90700110 -+#define XPT_BERT_ERR_COUNT0_HI XPT_BERT_ERR_COUNT0_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERR_COUNT1_BASEADDR 0x90700114 -+#define XPT_BERT_ERR_COUNT1_LO XPT_BERT_ERR_COUNT1_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT1_BASEADDR1 0x90700118 -+#define XPT_BERT_ERR_COUNT1_HI XPT_BERT_ERR_COUNT1_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERR_COUNT2_BASEADDR 0x9070011C -+#define XPT_BERT_ERR_COUNT2_LO XPT_BERT_ERR_COUNT2_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT2_BASEADDR1 0x90700120 -+#define XPT_BERT_ERR_COUNT2_HI XPT_BERT_ERR_COUNT2_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERR_COUNT3_BASEADDR 0x90700124 -+#define XPT_BERT_ERR_COUNT3_LO XPT_BERT_ERR_COUNT3_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT3_BASEADDR1 0x90700128 -+#define XPT_BERT_ERR_COUNT3_HI XPT_BERT_ERR_COUNT3_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERR_COUNT4_BASEADDR 0x9070012C -+#define XPT_BERT_ERR_COUNT4_LO XPT_BERT_ERR_COUNT4_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT4_BASEADDR1 0x90700130 -+#define XPT_BERT_ERR_COUNT4_HI XPT_BERT_ERR_COUNT4_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERR_COUNT5_BASEADDR 0x90700134 -+#define XPT_BERT_ERR_COUNT5_LO XPT_BERT_ERR_COUNT5_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT5_BASEADDR1 0x90700138 -+#define XPT_BERT_ERR_COUNT5_HI XPT_BERT_ERR_COUNT5_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERR_COUNT6_BASEADDR 0x9070013C -+#define XPT_BERT_ERR_COUNT6_LO XPT_BERT_ERR_COUNT6_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT6_BASEADDR1 0x90700140 -+#define XPT_BERT_ERR_COUNT6_HI XPT_BERT_ERR_COUNT6_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERR_COUNT7_BASEADDR 0x90700144 -+#define XPT_BERT_ERR_COUNT7_LO XPT_BERT_ERR_COUNT7_BASEADDR,0,32 -+ -+#define XPT_BERT_ERR_COUNT7_BASEADDR1 0x90700148 -+#define XPT_BERT_ERR_COUNT7_HI XPT_BERT_ERR_COUNT7_BASEADDR1,0,8 -+ -+#define XPT_BERT_ERROR_BASEADDR 0x9070014C -+#define XPT_BERT_ERROR_INSERT XPT_BERT_ERROR_BASEADDR,0,24 -+ -+#define XPT_BERT_ANALYZER_BASEADDR 0x90700150 -+#define XPT_BERT_ANALYZER_ENABLE XPT_BERT_ANALYZER_BASEADDR,0,1 -+#define XPT_BERT_ANALYZER_PORT XPT_BERT_ANALYZER_BASEADDR,4,3 -+#define XPT_BERT_ANALYZER_ERR_THRES XPT_BERT_ANALYZER_BASEADDR,15,17 -+ -+#define XPT_BERT_ANALYZER_BASEADDR1 0x90700154 -+#define XPT_BERT_ANALYZER_START XPT_BERT_ANALYZER_BASEADDR1,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR2 0x90700158 -+#define XPT_BERT_ANALYZER_TSTAMP0 XPT_BERT_ANALYZER_BASEADDR2,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR3 0x9070015C -+#define XPT_BERT_ANALYZER_TSTAMP1 XPT_BERT_ANALYZER_BASEADDR3,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR4 0x90700160 -+#define XPT_BERT_ANALYZER_TSTAMP2 XPT_BERT_ANALYZER_BASEADDR4,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR5 0x90700164 -+#define XPT_BERT_ANALYZER_TSTAMP3 XPT_BERT_ANALYZER_BASEADDR5,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR6 0x90700168 -+#define XPT_BERT_ANALYZER_TSTAMP4 XPT_BERT_ANALYZER_BASEADDR6,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR7 0x9070016C -+#define XPT_BERT_ANALYZER_TSTAMP5 XPT_BERT_ANALYZER_BASEADDR7,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR8 0x90700170 -+#define XPT_BERT_ANALYZER_TSTAMP6 XPT_BERT_ANALYZER_BASEADDR8,0,32 -+ -+#define XPT_BERT_ANALYZER_BASEADDR9 0x90700174 -+#define XPT_BERT_ANALYZER_TSTAMP7 XPT_BERT_ANALYZER_BASEADDR9,0,32 -+ -+#define XPT_DMD0_BASEADDR 0x9070024C -+#define XPT_DMD0_SEL XPT_DMD0_BASEADDR,0,3 -+#define XPT_DMD1_SEL XPT_DMD0_BASEADDR,4,3 -+#define XPT_DMD2_SEL XPT_DMD0_BASEADDR,8,3 -+#define XPT_DMD3_SEL XPT_DMD0_BASEADDR,12,3 -+#define XPT_DMD4_SEL XPT_DMD0_BASEADDR,16,3 -+#define XPT_DMD5_SEL XPT_DMD0_BASEADDR,20,3 -+#define XPT_DMD6_SEL XPT_DMD0_BASEADDR,24,3 -+#define XPT_DMD7_SEL XPT_DMD0_BASEADDR,28,3 -+ -+// V2 AGC Gain Freeze & step -+#define DBG_ENABLE_DISABLE_AGC (0x3FFFCF60) // 1: DISABLE, 0:ENABLE -+#define WB_DFE0_DFE_FB_RF1_BASEADDR 0x903004A4 -+#define WB_DFE0_DFE_FB_RF1_BO WB_DFE0_DFE_FB_RF1_BASEADDR,0,3 -+#define WB_DFE0_DFE_FB_RF2_BO WB_DFE0_DFE_FB_RF1_BASEADDR,4,4 -+#define WB_DFE0_DFE_FB_LNA_BO WB_DFE0_DFE_FB_RF1_BASEADDR,8,2 -+ -+#define WB_DFE1_DFE_FB_RF1_BASEADDR 0x904004A4 -+#define WB_DFE1_DFE_FB_RF1_BO WB_DFE1_DFE_FB_RF1_BASEADDR,0,3 -+#define WB_DFE1_DFE_FB_RF2_BO WB_DFE1_DFE_FB_RF1_BASEADDR,4,4 -+#define WB_DFE1_DFE_FB_LNA_BO WB_DFE1_DFE_FB_RF1_BASEADDR,8,2 -+ -+#define WB_DFE2_DFE_FB_RF1_BASEADDR 0x905004A4 -+#define WB_DFE2_DFE_FB_RF1_BO WB_DFE2_DFE_FB_RF1_BASEADDR,0,3 -+#define WB_DFE2_DFE_FB_RF2_BO WB_DFE2_DFE_FB_RF1_BASEADDR,4,4 -+#define WB_DFE2_DFE_FB_LNA_BO WB_DFE2_DFE_FB_RF1_BASEADDR,8,2 -+ -+#define WB_DFE3_DFE_FB_RF1_BASEADDR 0x906004A4 -+#define WB_DFE3_DFE_FB_RF1_BO WB_DFE3_DFE_FB_RF1_BASEADDR,0,3 -+#define WB_DFE3_DFE_FB_RF2_BO WB_DFE3_DFE_FB_RF1_BASEADDR,4,4 -+#define WB_DFE3_DFE_FB_LNA_BO WB_DFE3_DFE_FB_RF1_BASEADDR,8,2 -+ -+#define AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR 0x90200104 -+#define AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,0,1 -+#define AFE_REG_D2A_TA_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,1,1 -+#define AFE_REG_D2A_TB_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,2,1 -+#define AFE_REG_D2A_TB_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,3,1 -+#define AFE_REG_D2A_TC_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,4,1 -+#define AFE_REG_D2A_TC_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,5,1 -+#define AFE_REG_D2A_TD_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,6,1 -+#define AFE_REG_D2A_TD_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,7,1 -+ -+#define AFE_REG_AFE_REG_SPARE_BASEADDR 0x902000A0 -+#define AFE_REG_D2A_TA_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR,13,5 -+ -+#define AFE_REG_AFE_REG_SPARE_BASEADDR1 0x902000B4 -+#define AFE_REG_D2A_TB_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR1,13,5 -+ -+#define AFE_REG_AFE_REG_SPARE_BASEADDR2 0x902000C4 -+#define AFE_REG_D2A_TC_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR2,13,5 -+ -+#define AFE_REG_AFE_REG_SPARE_BASEADDR3 0x902000D4 -+#define AFE_REG_D2A_TD_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR3,13,5 -+ -+#define WB_DFE0_DFE_FB_AGC_BASEADDR 0x90300498 -+#define WB_DFE0_DFE_FB_AGC_APPLY WB_DFE0_DFE_FB_AGC_BASEADDR,0,1 -+ -+#define WB_DFE1_DFE_FB_AGC_BASEADDR 0x90400498 -+#define WB_DFE1_DFE_FB_AGC_APPLY WB_DFE1_DFE_FB_AGC_BASEADDR,0,1 -+ -+#define WB_DFE2_DFE_FB_AGC_BASEADDR 0x90500498 -+#define WB_DFE2_DFE_FB_AGC_APPLY WB_DFE2_DFE_FB_AGC_BASEADDR,0,1 -+ -+#define WB_DFE3_DFE_FB_AGC_BASEADDR 0x90600498 -+#define WB_DFE3_DFE_FB_AGC_APPLY WB_DFE3_DFE_FB_AGC_BASEADDR,0,1 -+ -+#define WDT_WD_INT_BASEADDR 0x8002000C -+#define WDT_WD_INT_STATUS WDT_WD_INT_BASEADDR,0,1 -+ -+#define FSK_TX_FTM_BASEADDR 0x80090000 -+#define FSK_TX_FTM_OE FSK_TX_FTM_BASEADDR,12,1 -+#define FSK_TX_FTM_TX_EN FSK_TX_FTM_BASEADDR,10,1 -+#define FSK_TX_FTM_FORCE_CARRIER_ON FSK_TX_FTM_BASEADDR,1,1 -+#define FSK_TX_FTM_FORCE_MARK_SPACE FSK_TX_FTM_BASEADDR,0,1 -+ -+#define FSK_TX_FTM_TX_CNT_BASEADDR 0x80090018 -+#define FSK_TX_FTM_TX_CNT_INT FSK_TX_FTM_TX_CNT_BASEADDR,8,4 -+#define FSK_TX_FTM_TX_INT_EN FSK_TX_FTM_TX_CNT_BASEADDR,4,1 -+#define FSK_TX_FTM_TX_INT_SRC_SEL FSK_TX_FTM_TX_CNT_BASEADDR,0,2 -+ -+#define AFE_REG_D2A_FSK_BIAS_BASEADDR 0x90200040 -+#define AFE_REG_D2A_FSK_BIAS_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,0,1 -+#define AFE_REG_D2A_FSK_TEST_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,10,1 -+#define AFE_REG_D2A_FSK_TEST_MODE AFE_REG_D2A_FSK_BIAS_BASEADDR,11,4 -+#define AFE_REG_D2A_FSK_TERM_INT_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,15,1 -+#define AFE_REG_D2A_FSK_RESETB_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,16,1 -+#define AFE_REG_D2A_FSK_REG_EN_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,17,1 -+#define AFE_REG_D2A_FSK_REG_EN_LKG_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,18,1 -+#define AFE_REG_D2A_FSK_REG_AMP_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,19,3 -+#define AFE_REG_D2A_FSK_REG_TEST_CTRL_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,22,2 -+#define AFE_REG_D2A_DSQ_RX_MODE AFE_REG_D2A_FSK_BIAS_BASEADDR,24,1 -+#define AFE_REG_D2A_DSQ_RX_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,25,1 -+#define AFE_REG_D2A_DSQ_HYST AFE_REG_D2A_FSK_BIAS_BASEADDR,26,2 -+#define AFE_REG_D2A_DSQ_RESETB_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,28,1 -+#define AFE_REG_D2A_FSK_CLKRX_ENA AFE_REG_D2A_FSK_BIAS_BASEADDR,29,1 -+ -+#define DMD_TEI_BASEADDR 0x3FFFEBE0 -+#define DMD_TEI_ENA DMD_TEI_BASEADDR,0,1 -+ -+#define xpt_shm_input_control0 0x90700270,0,8 -+#define xpt_shm_input_control1 0x90700270,8,8 -+#define xpt_shm_input_control2 0x90700270,16,8 -+#define xpt_shm_input_control3 0x90700270,24,8 -+#define xpt_shm_input_control4 0x90700274,0,8 -+#define xpt_shm_input_control5 0x90700274,8,8 -+#define xpt_shm_input_control6 0x90700274,16,8 -+#define xpt_shm_input_control7 0x90700274,24,8 -+ -+ -+#define xpt_shm_output_control0 0x90700278,0,8 -+#define xpt_shm_output_control1 0x90700278,8,8 -+#define xpt_shm_output_control2 0x90700278,16,8 -+#define xpt_shm_output_control3 0x90700278,24,8 -+#define xpt_shm_output_control4 0x9070027C,0,8 -+#define xpt_shm_output_control5 0x9070027C,8,8 -+#define xpt_shm_output_control6 0x9070027C,16,8 -+#define xpt_shm_output_control7 0x9070027C,24,8 -+ -+#define xpt_mode_27mhz 0x90700184,0,1 -+#define xpt_enable_pcr_count 0x90700184,1,1 -+ -+#define xcpu_ctrl_003c_reg 0x9072003C,0,4 -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif //__MXL58X_REGISTERS_H__ -diff --git a/drivers/media/dvb-frontends/stv0367dd.c b/drivers/media/dvb-frontends/stv0367dd.c -new file mode 100644 -index 0000000..fcb7704 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd.c -@@ -0,0 +1,1874 @@ -+/* -+ * stv0367dd: STV0367 DVB-C/T demodulator driver -+ * -+ * Copyright (C) 2011 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#undef pr_fmt -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "dvb_math.h" -+#include "stv0367dd.h" -+#include "stv0367dd_regs.h" -+ -+#define INTLOG10X100(x) ((u32) (((u64) intlog10(x) * 100) >> 24)) -+ -+enum { QAM_MOD_QAM4 = 0, -+ QAM_MOD_QAM16, -+ QAM_MOD_QAM32, -+ QAM_MOD_QAM64, -+ QAM_MOD_QAM128, -+ QAM_MOD_QAM256, -+ QAM_MOD_QAM512, -+ QAM_MOD_QAM1024 -+}; -+ -+enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED }; -+ -+enum { -+ QAM_FEC_A = 1, /* J83 Annex A */ -+ QAM_FEC_B = (1<<1), /* J83 Annex B */ -+ QAM_FEC_C = (1<<2) /* J83 Annex C */ -+}; -+ -+enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted }; -+ -+struct stv_state { -+ struct dvb_frontend frontend; -+ enum fe_modulation modulation; -+ u32 symbol_rate; -+ u32 bandwidth; -+ struct device *dev; -+ -+ struct i2c_adapter *i2c; -+ u8 adr; -+ u8 cont_clock; -+ void *priv; -+ -+ struct mutex mutex; -+ struct mutex ctlock; -+ -+ u32 master_clock; -+ u32 adc_clock; -+ u8 ID; -+ u8 I2CRPT; -+ enum fe_delivery_system delsys; -+ u8 qam_inversion; -+ -+ s32 IF; -+ -+ s32 m_FECTimeOut; -+ s32 m_DemodTimeOut; -+ s32 m_SignalTimeOut; -+ s32 m_DemodLockTime; -+ s32 m_FFTTimeOut; -+ s32 m_TSTimeOut; -+ -+ bool m_bFirstTimeLock; -+ -+ u8 m_Save_QAM_AGC_CTL; -+ -+ enum EDemodState demod_state; -+ -+ u8 m_OFDM_FFTMode; /* 0 = 2k, 1 = 8k, 2 = 4k */ -+ u8 m_OFDM_Modulation; -+ u8 m_OFDM_FEC; -+ u8 m_OFDM_Guard; -+ -+ u32 ucblocks; -+ u32 ber; -+}; -+ -+struct init_table { -+ u16 adr; -+ u8 data; -+}; -+ -+struct init_table base_init[] = { -+ { R367_IOCFG0, 0x80 }, -+ { R367_DAC0R, 0x00 }, -+ { R367_IOCFG1, 0x00 }, -+ { R367_DAC1R, 0x00 }, -+ { R367_IOCFG2, 0x00 }, -+ { R367_SDFR, 0x00 }, -+ { R367_AUX_CLK, 0x00 }, -+ { R367_FREESYS1, 0x00 }, -+ { R367_FREESYS2, 0x00 }, -+ { R367_FREESYS3, 0x00 }, -+ { R367_GPIO_CFG, 0x55 }, -+ { R367_GPIO_CMD, 0x01 }, -+ { R367_TSTRES, 0x00 }, -+ { R367_ANACTRL, 0x00 }, -+ { R367_TSTBUS, 0x00 }, -+ { R367_RF_AGC2, 0x20 }, -+ { R367_ANADIGCTRL, 0x0b }, -+ { R367_PLLMDIV, 0x01 }, -+ { R367_PLLNDIV, 0x08 }, -+ { R367_PLLSETUP, 0x18 }, -+ { R367_DUAL_AD12, 0x04 }, -+ { R367_TSTBIST, 0x00 }, -+ { 0x0000, 0x00 } -+}; -+ -+struct init_table qam_init[] = { -+ { R367_QAM_CTRL_1, 0x06 }, /* Orginal 0x04 */ -+ { R367_QAM_CTRL_2, 0x03 }, -+ { R367_QAM_IT_STATUS1, 0x2b }, -+ { R367_QAM_IT_STATUS2, 0x08 }, -+ { R367_QAM_IT_EN1, 0x00 }, -+ { R367_QAM_IT_EN2, 0x00 }, -+ { R367_QAM_CTRL_STATUS, 0x04 }, -+ { R367_QAM_TEST_CTL, 0x00 }, -+ { R367_QAM_AGC_CTL, 0x73 }, -+ { R367_QAM_AGC_IF_CFG, 0x50 }, -+ { R367_QAM_AGC_RF_CFG, 0x02 }, /* RF Freeze */ -+ { R367_QAM_AGC_PWM_CFG, 0x03 }, -+ { R367_QAM_AGC_PWR_REF_L, 0x5a }, -+ { R367_QAM_AGC_PWR_REF_H, 0x00 }, -+ { R367_QAM_AGC_RF_TH_L, 0xff }, -+ { R367_QAM_AGC_RF_TH_H, 0x07 }, -+ { R367_QAM_AGC_IF_LTH_L, 0x00 }, -+ { R367_QAM_AGC_IF_LTH_H, 0x08 }, -+ { R367_QAM_AGC_IF_HTH_L, 0xff }, -+ { R367_QAM_AGC_IF_HTH_H, 0x07 }, -+ { R367_QAM_AGC_PWR_RD_L, 0xa0 }, -+ { R367_QAM_AGC_PWR_RD_M, 0xe9 }, -+ { R367_QAM_AGC_PWR_RD_H, 0x03 }, -+ { R367_QAM_AGC_PWM_IFCMD_L, 0xe4 }, -+ { R367_QAM_AGC_PWM_IFCMD_H, 0x00 }, -+ { R367_QAM_AGC_PWM_RFCMD_L, 0xff }, -+ { R367_QAM_AGC_PWM_RFCMD_H, 0x07 }, -+ { R367_QAM_IQDEM_CFG, 0x01 }, -+ { R367_QAM_MIX_NCO_LL, 0x22 }, -+ { R367_QAM_MIX_NCO_HL, 0x96 }, -+ { R367_QAM_MIX_NCO_HH, 0x55 }, -+ { R367_QAM_SRC_NCO_LL, 0xff }, -+ { R367_QAM_SRC_NCO_LH, 0x0c }, -+ { R367_QAM_SRC_NCO_HL, 0xf5 }, -+ { R367_QAM_SRC_NCO_HH, 0x20 }, -+ { R367_QAM_IQDEM_GAIN_SRC_L, 0x06 }, -+ { R367_QAM_IQDEM_GAIN_SRC_H, 0x01 }, -+ { R367_QAM_IQDEM_DCRM_CFG_LL, 0xfe }, -+ { R367_QAM_IQDEM_DCRM_CFG_LH, 0xff }, -+ { R367_QAM_IQDEM_DCRM_CFG_HL, 0x0f }, -+ { R367_QAM_IQDEM_DCRM_CFG_HH, 0x00 }, -+ { R367_QAM_IQDEM_ADJ_COEFF0, 0x34 }, -+ { R367_QAM_IQDEM_ADJ_COEFF1, 0xae }, -+ { R367_QAM_IQDEM_ADJ_COEFF2, 0x46 }, -+ { R367_QAM_IQDEM_ADJ_COEFF3, 0x77 }, -+ { R367_QAM_IQDEM_ADJ_COEFF4, 0x96 }, -+ { R367_QAM_IQDEM_ADJ_COEFF5, 0x69 }, -+ { R367_QAM_IQDEM_ADJ_COEFF6, 0xc7 }, -+ { R367_QAM_IQDEM_ADJ_COEFF7, 0x01 }, -+ { R367_QAM_IQDEM_ADJ_EN, 0x04 }, -+ { R367_QAM_IQDEM_ADJ_AGC_REF, 0x94 }, -+ { R367_QAM_ALLPASSFILT1, 0xc9 }, -+ { R367_QAM_ALLPASSFILT2, 0x2d }, -+ { R367_QAM_ALLPASSFILT3, 0xa3 }, -+ { R367_QAM_ALLPASSFILT4, 0xfb }, -+ { R367_QAM_ALLPASSFILT5, 0xf6 }, -+ { R367_QAM_ALLPASSFILT6, 0x45 }, -+ { R367_QAM_ALLPASSFILT7, 0x6f }, -+ { R367_QAM_ALLPASSFILT8, 0x7e }, -+ { R367_QAM_ALLPASSFILT9, 0x05 }, -+ { R367_QAM_ALLPASSFILT10, 0x0a }, -+ { R367_QAM_ALLPASSFILT11, 0x51 }, -+ { R367_QAM_TRL_AGC_CFG, 0x20 }, -+ { R367_QAM_TRL_LPF_CFG, 0x28 }, -+ { R367_QAM_TRL_LPF_ACQ_GAIN, 0x44 }, -+ { R367_QAM_TRL_LPF_TRK_GAIN, 0x22 }, -+ { R367_QAM_TRL_LPF_OUT_GAIN, 0x03 }, -+ { R367_QAM_TRL_LOCKDET_LTH, 0x04 }, -+ { R367_QAM_TRL_LOCKDET_HTH, 0x11 }, -+ { R367_QAM_TRL_LOCKDET_TRGVAL, 0x20 }, -+ { R367_QAM_IQ_QAM, 0x01 }, -+ { R367_QAM_FSM_STATE, 0xa0 }, -+ { R367_QAM_FSM_CTL, 0x08 }, -+ { R367_QAM_FSM_STS, 0x0c }, -+ { R367_QAM_FSM_SNR0_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR1_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR2_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR0_LTH, 0x00 }, -+ { R367_QAM_FSM_SNR1_LTH, 0x00 }, -+ { R367_QAM_FSM_EQA1_HTH, 0x00 }, -+ { R367_QAM_FSM_TEMPO, 0x32 }, -+ { R367_QAM_FSM_CONFIG, 0x03 }, -+ { R367_QAM_EQU_I_TESTTAP_L, 0x11 }, -+ { R367_QAM_EQU_I_TESTTAP_M, 0x00 }, -+ { R367_QAM_EQU_I_TESTTAP_H, 0x00 }, -+ { R367_QAM_EQU_TESTAP_CFG, 0x00 }, -+ { R367_QAM_EQU_Q_TESTTAP_L, 0xff }, -+ { R367_QAM_EQU_Q_TESTTAP_M, 0x00 }, -+ { R367_QAM_EQU_Q_TESTTAP_H, 0x00 }, -+ { R367_QAM_EQU_TAP_CTRL, 0x00 }, -+ { R367_QAM_EQU_CTR_CRL_CONTROL_L, 0x11 }, -+ { R367_QAM_EQU_CTR_CRL_CONTROL_H, 0x05 }, -+ { R367_QAM_EQU_CTR_HIPOW_L, 0x00 }, -+ { R367_QAM_EQU_CTR_HIPOW_H, 0x00 }, -+ { R367_QAM_EQU_I_EQU_LO, 0xef }, -+ { R367_QAM_EQU_I_EQU_HI, 0x00 }, -+ { R367_QAM_EQU_Q_EQU_LO, 0xee }, -+ { R367_QAM_EQU_Q_EQU_HI, 0x00 }, -+ { R367_QAM_EQU_MAPPER, 0xc5 }, -+ { R367_QAM_EQU_SWEEP_RATE, 0x80 }, -+ { R367_QAM_EQU_SNR_LO, 0x64 }, -+ { R367_QAM_EQU_SNR_HI, 0x03 }, -+ { R367_QAM_EQU_GAMMA_LO, 0x00 }, -+ { R367_QAM_EQU_GAMMA_HI, 0x00 }, -+ { R367_QAM_EQU_ERR_GAIN, 0x36 }, -+ { R367_QAM_EQU_RADIUS, 0xaa }, -+ { R367_QAM_EQU_FFE_MAINTAP, 0x00 }, -+ { R367_QAM_EQU_FFE_LEAKAGE, 0x63 }, -+ { R367_QAM_EQU_FFE_MAINTAP_POS, 0xdf }, -+ { R367_QAM_EQU_GAIN_WIDE, 0x88 }, -+ { R367_QAM_EQU_GAIN_NARROW, 0x41 }, -+ { R367_QAM_EQU_CTR_LPF_GAIN, 0xd1 }, -+ { R367_QAM_EQU_CRL_LPF_GAIN, 0xa7 }, -+ { R367_QAM_EQU_GLOBAL_GAIN, 0x06 }, -+ { R367_QAM_EQU_CRL_LD_SEN, 0x85 }, -+ { R367_QAM_EQU_CRL_LD_VAL, 0xe2 }, -+ { R367_QAM_EQU_CRL_TFR, 0x20 }, -+ { R367_QAM_EQU_CRL_BISTH_LO, 0x00 }, -+ { R367_QAM_EQU_CRL_BISTH_HI, 0x00 }, -+ { R367_QAM_EQU_SWEEP_RANGE_LO, 0x00 }, -+ { R367_QAM_EQU_SWEEP_RANGE_HI, 0x00 }, -+ { R367_QAM_EQU_CRL_LIMITER, 0x40 }, -+ { R367_QAM_EQU_MODULUS_MAP, 0x90 }, -+ { R367_QAM_EQU_PNT_GAIN, 0xa7 }, -+ { R367_QAM_FEC_AC_CTR_0, 0x16 }, -+ { R367_QAM_FEC_AC_CTR_1, 0x0b }, -+ { R367_QAM_FEC_AC_CTR_2, 0x88 }, -+ { R367_QAM_FEC_AC_CTR_3, 0x02 }, -+ { R367_QAM_FEC_STATUS, 0x12 }, -+ { R367_QAM_RS_COUNTER_0, 0x7d }, -+ { R367_QAM_RS_COUNTER_1, 0xd0 }, -+ { R367_QAM_RS_COUNTER_2, 0x19 }, -+ { R367_QAM_RS_COUNTER_3, 0x0b }, -+ { R367_QAM_RS_COUNTER_4, 0xa3 }, -+ { R367_QAM_RS_COUNTER_5, 0x00 }, -+ { R367_QAM_BERT_0, 0x01 }, -+ { R367_QAM_BERT_1, 0x25 }, -+ { R367_QAM_BERT_2, 0x41 }, -+ { R367_QAM_BERT_3, 0x39 }, -+ { R367_QAM_OUTFORMAT_0, 0xc2 }, -+ { R367_QAM_OUTFORMAT_1, 0x22 }, -+ { R367_QAM_SMOOTHER_2, 0x28 }, -+ { R367_QAM_TSMF_CTRL_0, 0x01 }, -+ { R367_QAM_TSMF_CTRL_1, 0xc6 }, -+ { R367_QAM_TSMF_CTRL_3, 0x43 }, -+ { R367_QAM_TS_ON_ID_0, 0x00 }, -+ { R367_QAM_TS_ON_ID_1, 0x00 }, -+ { R367_QAM_TS_ON_ID_2, 0x00 }, -+ { R367_QAM_TS_ON_ID_3, 0x00 }, -+ { R367_QAM_RE_STATUS_0, 0x00 }, -+ { R367_QAM_RE_STATUS_1, 0x00 }, -+ { R367_QAM_RE_STATUS_2, 0x00 }, -+ { R367_QAM_RE_STATUS_3, 0x00 }, -+ { R367_QAM_TS_STATUS_0, 0x00 }, -+ { R367_QAM_TS_STATUS_1, 0x00 }, -+ { R367_QAM_TS_STATUS_2, 0xa0 }, -+ { R367_QAM_TS_STATUS_3, 0x00 }, -+ { R367_QAM_T_O_ID_0, 0x00 }, -+ { R367_QAM_T_O_ID_1, 0x00 }, -+ { R367_QAM_T_O_ID_2, 0x00 }, -+ { R367_QAM_T_O_ID_3, 0x00 }, -+ { 0x0000, 0x00 } /* EOT */ -+}; -+ -+struct init_table ofdm_init[] = { -+ { R367_OFDM_AGC2MAX, 0xff }, -+ { R367_OFDM_AGC2MIN, 0x00 }, -+ { R367_OFDM_AGC1MAX, 0xff }, -+ { R367_OFDM_AGC1MIN, 0x00 }, -+ { R367_OFDM_AGCR, 0xbc }, -+ { R367_OFDM_AGC2TH, 0x00 }, -+ { R367_OFDM_AGCCTRL1, 0x85 }, -+ { R367_OFDM_AGCCTRL2, 0x1f }, -+ { R367_OFDM_AGC1VAL1, 0x00 }, -+ { R367_OFDM_AGC1VAL2, 0x00 }, -+ { R367_OFDM_AGC2VAL1, 0x6f }, -+ { R367_OFDM_AGC2VAL2, 0x05 }, -+ { R367_OFDM_AGC2PGA, 0x00 }, -+ { R367_OFDM_OVF_RATE1, 0x00 }, -+ { R367_OFDM_OVF_RATE2, 0x00 }, -+ { R367_OFDM_GAIN_SRC1, 0x2b }, -+ { R367_OFDM_GAIN_SRC2, 0x04 }, -+ { R367_OFDM_INC_DEROT1, 0x55 }, -+ { R367_OFDM_INC_DEROT2, 0x55 }, -+ { R367_OFDM_PPM_CPAMP_DIR, 0x2c }, -+ { R367_OFDM_PPM_CPAMP_INV, 0x00 }, -+ { R367_OFDM_FREESTFE_1, 0x00 }, -+ { R367_OFDM_FREESTFE_2, 0x1c }, -+ { R367_OFDM_DCOFFSET, 0x00 }, -+ { R367_OFDM_EN_PROCESS, 0x05 }, -+ { R367_OFDM_SDI_SMOOTHER, 0x80 }, -+ { R367_OFDM_FE_LOOP_OPEN, 0x1c }, -+ { R367_OFDM_FREQOFF1, 0x00 }, -+ { R367_OFDM_FREQOFF2, 0x00 }, -+ { R367_OFDM_FREQOFF3, 0x00 }, -+ { R367_OFDM_TIMOFF1, 0x00 }, -+ { R367_OFDM_TIMOFF2, 0x00 }, -+ { R367_OFDM_EPQ, 0x02 }, -+ { R367_OFDM_EPQAUTO, 0x01 }, -+ { R367_OFDM_SYR_UPDATE, 0xf5 }, -+ { R367_OFDM_CHPFREE, 0x00 }, -+ { R367_OFDM_PPM_STATE_MAC, 0x23 }, -+ { R367_OFDM_INR_THRESHOLD, 0xff }, -+ { R367_OFDM_EPQ_TPS_ID_CELL, 0xf9 }, -+ { R367_OFDM_EPQ_CFG, 0x00 }, -+ { R367_OFDM_EPQ_STATUS, 0x01 }, -+ { R367_OFDM_AUTORELOCK, 0x81 }, -+ { R367_OFDM_BER_THR_VMSB, 0x00 }, -+ { R367_OFDM_BER_THR_MSB, 0x00 }, -+ { R367_OFDM_BER_THR_LSB, 0x00 }, -+ { R367_OFDM_CCD, 0x83 }, -+ { R367_OFDM_SPECTR_CFG, 0x00 }, -+ { R367_OFDM_CHC_DUMMY, 0x18 }, -+ { R367_OFDM_INC_CTL, 0x88 }, -+ { R367_OFDM_INCTHRES_COR1, 0xb4 }, -+ { R367_OFDM_INCTHRES_COR2, 0x96 }, -+ { R367_OFDM_INCTHRES_DET1, 0x0e }, -+ { R367_OFDM_INCTHRES_DET2, 0x11 }, -+ { R367_OFDM_IIR_CELLNB, 0x8d }, -+ { R367_OFDM_IIRCX_COEFF1_MSB, 0x00 }, -+ { R367_OFDM_IIRCX_COEFF1_LSB, 0x00 }, -+ { R367_OFDM_IIRCX_COEFF2_MSB, 0x09 }, -+ { R367_OFDM_IIRCX_COEFF2_LSB, 0x18 }, -+ { R367_OFDM_IIRCX_COEFF3_MSB, 0x14 }, -+ { R367_OFDM_IIRCX_COEFF3_LSB, 0x9c }, -+ { R367_OFDM_IIRCX_COEFF4_MSB, 0x00 }, -+ { R367_OFDM_IIRCX_COEFF4_LSB, 0x00 }, -+ { R367_OFDM_IIRCX_COEFF5_MSB, 0x36 }, -+ { R367_OFDM_IIRCX_COEFF5_LSB, 0x42 }, -+ { R367_OFDM_FEPATH_CFG, 0x00 }, -+ { R367_OFDM_PMC1_FUNC, 0x65 }, -+ { R367_OFDM_PMC1_FOR, 0x00 }, -+ { R367_OFDM_PMC2_FUNC, 0x00 }, -+ { R367_OFDM_STATUS_ERR_DA, 0xe0 }, -+ { R367_OFDM_DIG_AGC_R, 0xfe }, -+ { R367_OFDM_COMAGC_TARMSB, 0x0b }, -+ { R367_OFDM_COM_AGC_TAR_ENMODE, 0x41 }, -+ { R367_OFDM_COM_AGC_CFG, 0x3e }, -+ { R367_OFDM_COM_AGC_GAIN1, 0x39 }, -+ { R367_OFDM_AUT_AGC_TARGETMSB, 0x0b }, -+ { R367_OFDM_LOCK_DET_MSB, 0x01 }, -+ { R367_OFDM_AGCTAR_LOCK_LSBS, 0x40 }, -+ { R367_OFDM_AUT_GAIN_EN, 0xf4 }, -+ { R367_OFDM_AUT_CFG, 0xf0 }, -+ { R367_OFDM_LOCKN, 0x23 }, -+ { R367_OFDM_INT_X_3, 0x00 }, -+ { R367_OFDM_INT_X_2, 0x03 }, -+ { R367_OFDM_INT_X_1, 0x8d }, -+ { R367_OFDM_INT_X_0, 0xa0 }, -+ { R367_OFDM_MIN_ERRX_MSB, 0x00 }, -+ { R367_OFDM_COR_CTL, 0x00 }, -+ { R367_OFDM_COR_STAT, 0xf6 }, -+ { R367_OFDM_COR_INTEN, 0x00 }, -+ { R367_OFDM_COR_INTSTAT, 0x3f }, -+ { R367_OFDM_COR_MODEGUARD, 0x03 }, -+ { R367_OFDM_AGC_CTL, 0x08 }, -+ { R367_OFDM_AGC_MANUAL1, 0x00 }, -+ { R367_OFDM_AGC_MANUAL2, 0x00 }, -+ { R367_OFDM_AGC_TARG, 0x16 }, -+ { R367_OFDM_AGC_GAIN1, 0x53 }, -+ { R367_OFDM_AGC_GAIN2, 0x1d }, -+ { R367_OFDM_RESERVED_1, 0x00 }, -+ { R367_OFDM_RESERVED_2, 0x00 }, -+ { R367_OFDM_RESERVED_3, 0x00 }, -+ { R367_OFDM_CAS_CTL, 0x44 }, -+ { R367_OFDM_CAS_FREQ, 0xb3 }, -+ { R367_OFDM_CAS_DAGCGAIN, 0x12 }, -+ { R367_OFDM_SYR_CTL, 0x04 }, -+ { R367_OFDM_SYR_STAT, 0x10 }, -+ { R367_OFDM_SYR_NCO1, 0x00 }, -+ { R367_OFDM_SYR_NCO2, 0x00 }, -+ { R367_OFDM_SYR_OFFSET1, 0x00 }, -+ { R367_OFDM_SYR_OFFSET2, 0x00 }, -+ { R367_OFDM_FFT_CTL, 0x00 }, -+ { R367_OFDM_SCR_CTL, 0x70 }, -+ { R367_OFDM_PPM_CTL1, 0xf8 }, -+ { R367_OFDM_TRL_CTL, 0xac }, -+ { R367_OFDM_TRL_NOMRATE1, 0x1e }, -+ { R367_OFDM_TRL_NOMRATE2, 0x58 }, -+ { R367_OFDM_TRL_TIME1, 0x1d }, -+ { R367_OFDM_TRL_TIME2, 0xfc }, -+ { R367_OFDM_CRL_CTL, 0x24 }, -+ { R367_OFDM_CRL_FREQ1, 0xad }, -+ { R367_OFDM_CRL_FREQ2, 0x9d }, -+ { R367_OFDM_CRL_FREQ3, 0xff }, -+ { R367_OFDM_CHC_CTL, 0x01 }, -+ { R367_OFDM_CHC_SNR, 0xf0 }, -+ { R367_OFDM_BDI_CTL, 0x00 }, -+ { R367_OFDM_DMP_CTL, 0x00 }, -+ { R367_OFDM_TPS_RCVD1, 0x30 }, -+ { R367_OFDM_TPS_RCVD2, 0x02 }, -+ { R367_OFDM_TPS_RCVD3, 0x01 }, -+ { R367_OFDM_TPS_RCVD4, 0x00 }, -+ { R367_OFDM_TPS_ID_CELL1, 0x00 }, -+ { R367_OFDM_TPS_ID_CELL2, 0x00 }, -+ { R367_OFDM_TPS_RCVD5_SET1, 0x02 }, -+ { R367_OFDM_TPS_SET2, 0x02 }, -+ { R367_OFDM_TPS_SET3, 0x01 }, -+ { R367_OFDM_TPS_CTL, 0x00 }, -+ { R367_OFDM_CTL_FFTOSNUM, 0x34 }, -+ { R367_OFDM_TESTSELECT, 0x09 }, -+ { R367_OFDM_MSC_REV, 0x0a }, -+ { R367_OFDM_PIR_CTL, 0x00 }, -+ { R367_OFDM_SNR_CARRIER1, 0xa1 }, -+ { R367_OFDM_SNR_CARRIER2, 0x9a }, -+ { R367_OFDM_PPM_CPAMP, 0x2c }, -+ { R367_OFDM_TSM_AP0, 0x00 }, -+ { R367_OFDM_TSM_AP1, 0x00 }, -+ { R367_OFDM_TSM_AP2, 0x00 }, -+ { R367_OFDM_TSM_AP3, 0x00 }, -+ { R367_OFDM_TSM_AP4, 0x00 }, -+ { R367_OFDM_TSM_AP5, 0x00 }, -+ { R367_OFDM_TSM_AP6, 0x00 }, -+ { R367_OFDM_TSM_AP7, 0x00 }, -+ { R367_OFDM_CONSTMODE, 0x01 }, -+ { R367_OFDM_CONSTCARR1, 0x00 }, -+ { R367_OFDM_CONSTCARR2, 0x00 }, -+ { R367_OFDM_ICONSTEL, 0x0a }, -+ { R367_OFDM_QCONSTEL, 0x15 }, -+ { R367_OFDM_TSTBISTRES0, 0x00 }, -+ { R367_OFDM_TSTBISTRES1, 0x00 }, -+ { R367_OFDM_TSTBISTRES2, 0x28 }, -+ { R367_OFDM_TSTBISTRES3, 0x00 }, -+ { R367_OFDM_SYR_TARGET_FFTADJT_MSB, 0x00 }, -+ { R367_OFDM_SYR_TARGET_FFTADJT_LSB, 0x00 }, -+ { R367_OFDM_SYR_TARGET_CHCADJT_MSB, 0x00 }, -+ { R367_OFDM_SYR_TARGET_CHCADJT_LSB, 0x00 }, -+ { R367_OFDM_SYR_FLAG, 0x00 }, -+ { R367_OFDM_CRL_TARGET1, 0x00 }, -+ { R367_OFDM_CRL_TARGET2, 0x00 }, -+ { R367_OFDM_CRL_TARGET3, 0x00 }, -+ { R367_OFDM_CRL_TARGET4, 0x00 }, -+ { R367_OFDM_CRL_FLAG, 0x00 }, -+ { R367_OFDM_TRL_TARGET1, 0x00 }, -+ { R367_OFDM_TRL_TARGET2, 0x00 }, -+ { R367_OFDM_TRL_CHC, 0x00 }, -+ { R367_OFDM_CHC_SNR_TARG, 0x00 }, -+ { R367_OFDM_TOP_TRACK, 0x00 }, -+ { R367_OFDM_TRACKER_FREE1, 0x00 }, -+ { R367_OFDM_ERROR_CRL1, 0x00 }, -+ { R367_OFDM_ERROR_CRL2, 0x00 }, -+ { R367_OFDM_ERROR_CRL3, 0x00 }, -+ { R367_OFDM_ERROR_CRL4, 0x00 }, -+ { R367_OFDM_DEC_NCO1, 0x2c }, -+ { R367_OFDM_DEC_NCO2, 0x0f }, -+ { R367_OFDM_DEC_NCO3, 0x20 }, -+ { R367_OFDM_SNR, 0xf1 }, -+ { R367_OFDM_SYR_FFTADJ1, 0x00 }, -+ { R367_OFDM_SYR_FFTADJ2, 0x00 }, -+ { R367_OFDM_SYR_CHCADJ1, 0x00 }, -+ { R367_OFDM_SYR_CHCADJ2, 0x00 }, -+ { R367_OFDM_SYR_OFF, 0x00 }, -+ { R367_OFDM_PPM_OFFSET1, 0x00 }, -+ { R367_OFDM_PPM_OFFSET2, 0x03 }, -+ { R367_OFDM_TRACKER_FREE2, 0x00 }, -+ { R367_OFDM_DEBG_LT10, 0x00 }, -+ { R367_OFDM_DEBG_LT11, 0x00 }, -+ { R367_OFDM_DEBG_LT12, 0x00 }, -+ { R367_OFDM_DEBG_LT13, 0x00 }, -+ { R367_OFDM_DEBG_LT14, 0x00 }, -+ { R367_OFDM_DEBG_LT15, 0x00 }, -+ { R367_OFDM_DEBG_LT16, 0x00 }, -+ { R367_OFDM_DEBG_LT17, 0x00 }, -+ { R367_OFDM_DEBG_LT18, 0x00 }, -+ { R367_OFDM_DEBG_LT19, 0x00 }, -+ { R367_OFDM_DEBG_LT1A, 0x00 }, -+ { R367_OFDM_DEBG_LT1B, 0x00 }, -+ { R367_OFDM_DEBG_LT1C, 0x00 }, -+ { R367_OFDM_DEBG_LT1D, 0x00 }, -+ { R367_OFDM_DEBG_LT1E, 0x00 }, -+ { R367_OFDM_DEBG_LT1F, 0x00 }, -+ { R367_OFDM_RCCFGH, 0x00 }, -+ { R367_OFDM_RCCFGM, 0x00 }, -+ { R367_OFDM_RCCFGL, 0x00 }, -+ { R367_OFDM_RCINSDELH, 0x00 }, -+ { R367_OFDM_RCINSDELM, 0x00 }, -+ { R367_OFDM_RCINSDELL, 0x00 }, -+ { R367_OFDM_RCSTATUS, 0x00 }, -+ { R367_OFDM_RCSPEED, 0x6f }, -+ { R367_OFDM_RCDEBUGM, 0xe7 }, -+ { R367_OFDM_RCDEBUGL, 0x9b }, -+ { R367_OFDM_RCOBSCFG, 0x00 }, -+ { R367_OFDM_RCOBSM, 0x00 }, -+ { R367_OFDM_RCOBSL, 0x00 }, -+ { R367_OFDM_RCFECSPY, 0x00 }, -+ { R367_OFDM_RCFSPYCFG, 0x00 }, -+ { R367_OFDM_RCFSPYDATA, 0x00 }, -+ { R367_OFDM_RCFSPYOUT, 0x00 }, -+ { R367_OFDM_RCFSTATUS, 0x00 }, -+ { R367_OFDM_RCFGOODPACK, 0x00 }, -+ { R367_OFDM_RCFPACKCNT, 0x00 }, -+ { R367_OFDM_RCFSPYMISC, 0x00 }, -+ { R367_OFDM_RCFBERCPT4, 0x00 }, -+ { R367_OFDM_RCFBERCPT3, 0x00 }, -+ { R367_OFDM_RCFBERCPT2, 0x00 }, -+ { R367_OFDM_RCFBERCPT1, 0x00 }, -+ { R367_OFDM_RCFBERCPT0, 0x00 }, -+ { R367_OFDM_RCFBERERR2, 0x00 }, -+ { R367_OFDM_RCFBERERR1, 0x00 }, -+ { R367_OFDM_RCFBERERR0, 0x00 }, -+ { R367_OFDM_RCFSTATESM, 0x00 }, -+ { R367_OFDM_RCFSTATESL, 0x00 }, -+ { R367_OFDM_RCFSPYBER, 0x00 }, -+ { R367_OFDM_RCFSPYDISTM, 0x00 }, -+ { R367_OFDM_RCFSPYDISTL, 0x00 }, -+ { R367_OFDM_RCFSPYOBS7, 0x00 }, -+ { R367_OFDM_RCFSPYOBS6, 0x00 }, -+ { R367_OFDM_RCFSPYOBS5, 0x00 }, -+ { R367_OFDM_RCFSPYOBS4, 0x00 }, -+ { R367_OFDM_RCFSPYOBS3, 0x00 }, -+ { R367_OFDM_RCFSPYOBS2, 0x00 }, -+ { R367_OFDM_RCFSPYOBS1, 0x00 }, -+ { R367_OFDM_RCFSPYOBS0, 0x00 }, -+ { R367_OFDM_FECM, 0x01 }, -+ { R367_OFDM_VTH12, 0xff }, -+ { R367_OFDM_VTH23, 0xa1 }, -+ { R367_OFDM_VTH34, 0x64 }, -+ { R367_OFDM_VTH56, 0x40 }, -+ { R367_OFDM_VTH67, 0x00 }, -+ { R367_OFDM_VTH78, 0x2c }, -+ { R367_OFDM_VITCURPUN, 0x12 }, -+ { R367_OFDM_VERROR, 0x01 }, -+ { R367_OFDM_PRVIT, 0x3f }, -+ { R367_OFDM_VAVSRVIT, 0x00 }, -+ { R367_OFDM_VSTATUSVIT, 0xbd }, -+ { R367_OFDM_VTHINUSE, 0xa1 }, -+ { R367_OFDM_KDIV12, 0x20 }, -+ { R367_OFDM_KDIV23, 0x40 }, -+ { R367_OFDM_KDIV34, 0x20 }, -+ { R367_OFDM_KDIV56, 0x30 }, -+ { R367_OFDM_KDIV67, 0x00 }, -+ { R367_OFDM_KDIV78, 0x30 }, -+ { R367_OFDM_SIGPOWER, 0x54 }, -+ { R367_OFDM_DEMAPVIT, 0x40 }, -+ { R367_OFDM_VITSCALE, 0x00 }, -+ { R367_OFDM_FFEC1PRG, 0x00 }, -+ { R367_OFDM_FVITCURPUN, 0x12 }, -+ { R367_OFDM_FVERROR, 0x01 }, -+ { R367_OFDM_FVSTATUSVIT, 0xbd }, -+ { R367_OFDM_DEBUG_LT1, 0x00 }, -+ { R367_OFDM_DEBUG_LT2, 0x00 }, -+ { R367_OFDM_DEBUG_LT3, 0x00 }, -+ { R367_OFDM_TSTSFMET, 0x00 }, -+ { R367_OFDM_SELOUT, 0x00 }, -+ { R367_OFDM_TSYNC, 0x00 }, -+ { R367_OFDM_TSTERR, 0x00 }, -+ { R367_OFDM_TSFSYNC, 0x00 }, -+ { R367_OFDM_TSTSFERR, 0x00 }, -+ { R367_OFDM_TSTTSSF1, 0x01 }, -+ { R367_OFDM_TSTTSSF2, 0x1f }, -+ { R367_OFDM_TSTTSSF3, 0x00 }, -+ { R367_OFDM_TSTTS1, 0x00 }, -+ { R367_OFDM_TSTTS2, 0x1f }, -+ { R367_OFDM_TSTTS3, 0x01 }, -+ { R367_OFDM_TSTTS4, 0x00 }, -+ { R367_OFDM_TSTTSRC, 0x00 }, -+ { R367_OFDM_TSTTSRS, 0x00 }, -+ { R367_OFDM_TSSTATEM, 0xb0 }, -+ { R367_OFDM_TSSTATEL, 0x40 }, -+ { R367_OFDM_TSCFGH, 0x80 }, -+ { R367_OFDM_TSCFGM, 0x00 }, -+ { R367_OFDM_TSCFGL, 0x20 }, -+ { R367_OFDM_TSSYNC, 0x00 }, -+ { R367_OFDM_TSINSDELH, 0x00 }, -+ { R367_OFDM_TSINSDELM, 0x00 }, -+ { R367_OFDM_TSINSDELL, 0x00 }, -+ { R367_OFDM_TSDIVN, 0x03 }, -+ { R367_OFDM_TSDIVPM, 0x00 }, -+ { R367_OFDM_TSDIVPL, 0x00 }, -+ { R367_OFDM_TSDIVQM, 0x00 }, -+ { R367_OFDM_TSDIVQL, 0x00 }, -+ { R367_OFDM_TSDILSTKM, 0x00 }, -+ { R367_OFDM_TSDILSTKL, 0x00 }, -+ { R367_OFDM_TSSPEED, 0x6f }, -+ { R367_OFDM_TSSTATUS, 0x81 }, -+ { R367_OFDM_TSSTATUS2, 0x6a }, -+ { R367_OFDM_TSBITRATEM, 0x0f }, -+ { R367_OFDM_TSBITRATEL, 0xc6 }, -+ { R367_OFDM_TSPACKLENM, 0x00 }, -+ { R367_OFDM_TSPACKLENL, 0xfc }, -+ { R367_OFDM_TSBLOCLENM, 0x0a }, -+ { R367_OFDM_TSBLOCLENL, 0x80 }, -+ { R367_OFDM_TSDLYH, 0x90 }, -+ { R367_OFDM_TSDLYM, 0x68 }, -+ { R367_OFDM_TSDLYL, 0x01 }, -+ { R367_OFDM_TSNPDAV, 0x00 }, -+ { R367_OFDM_TSBUFSTATH, 0x00 }, -+ { R367_OFDM_TSBUFSTATM, 0x00 }, -+ { R367_OFDM_TSBUFSTATL, 0x00 }, -+ { R367_OFDM_TSDEBUGM, 0xcf }, -+ { R367_OFDM_TSDEBUGL, 0x1e }, -+ { R367_OFDM_TSDLYSETH, 0x00 }, -+ { R367_OFDM_TSDLYSETM, 0x68 }, -+ { R367_OFDM_TSDLYSETL, 0x00 }, -+ { R367_OFDM_TSOBSCFG, 0x00 }, -+ { R367_OFDM_TSOBSM, 0x47 }, -+ { R367_OFDM_TSOBSL, 0x1f }, -+ { R367_OFDM_ERRCTRL1, 0x95 }, -+ { R367_OFDM_ERRCNT1H, 0x80 }, -+ { R367_OFDM_ERRCNT1M, 0x00 }, -+ { R367_OFDM_ERRCNT1L, 0x00 }, -+ { R367_OFDM_ERRCTRL2, 0x95 }, -+ { R367_OFDM_ERRCNT2H, 0x00 }, -+ { R367_OFDM_ERRCNT2M, 0x00 }, -+ { R367_OFDM_ERRCNT2L, 0x00 }, -+ { R367_OFDM_FECSPY, 0x88 }, -+ { R367_OFDM_FSPYCFG, 0x2c }, -+ { R367_OFDM_FSPYDATA, 0x3a }, -+ { R367_OFDM_FSPYOUT, 0x06 }, -+ { R367_OFDM_FSTATUS, 0x61 }, -+ { R367_OFDM_FGOODPACK, 0xff }, -+ { R367_OFDM_FPACKCNT, 0xff }, -+ { R367_OFDM_FSPYMISC, 0x66 }, -+ { R367_OFDM_FBERCPT4, 0x00 }, -+ { R367_OFDM_FBERCPT3, 0x00 }, -+ { R367_OFDM_FBERCPT2, 0x36 }, -+ { R367_OFDM_FBERCPT1, 0x36 }, -+ { R367_OFDM_FBERCPT0, 0x14 }, -+ { R367_OFDM_FBERERR2, 0x00 }, -+ { R367_OFDM_FBERERR1, 0x03 }, -+ { R367_OFDM_FBERERR0, 0x28 }, -+ { R367_OFDM_FSTATESM, 0x00 }, -+ { R367_OFDM_FSTATESL, 0x02 }, -+ { R367_OFDM_FSPYBER, 0x00 }, -+ { R367_OFDM_FSPYDISTM, 0x01 }, -+ { R367_OFDM_FSPYDISTL, 0x9f }, -+ { R367_OFDM_FSPYOBS7, 0xc9 }, -+ { R367_OFDM_FSPYOBS6, 0x99 }, -+ { R367_OFDM_FSPYOBS5, 0x08 }, -+ { R367_OFDM_FSPYOBS4, 0xec }, -+ { R367_OFDM_FSPYOBS3, 0x01 }, -+ { R367_OFDM_FSPYOBS2, 0x0f }, -+ { R367_OFDM_FSPYOBS1, 0xf5 }, -+ { R367_OFDM_FSPYOBS0, 0x08 }, -+ { R367_OFDM_SFDEMAP, 0x40 }, -+ { R367_OFDM_SFERROR, 0x00 }, -+ { R367_OFDM_SFAVSR, 0x30 }, -+ { R367_OFDM_SFECSTATUS, 0xcc }, -+ { R367_OFDM_SFKDIV12, 0x20 }, -+ { R367_OFDM_SFKDIV23, 0x40 }, -+ { R367_OFDM_SFKDIV34, 0x20 }, -+ { R367_OFDM_SFKDIV56, 0x20 }, -+ { R367_OFDM_SFKDIV67, 0x00 }, -+ { R367_OFDM_SFKDIV78, 0x20 }, -+ { R367_OFDM_SFDILSTKM, 0x00 }, -+ { R367_OFDM_SFDILSTKL, 0x00 }, -+ { R367_OFDM_SFSTATUS, 0xb5 }, -+ { R367_OFDM_SFDLYH, 0x90 }, -+ { R367_OFDM_SFDLYM, 0x60 }, -+ { R367_OFDM_SFDLYL, 0x01 }, -+ { R367_OFDM_SFDLYSETH, 0xc0 }, -+ { R367_OFDM_SFDLYSETM, 0x60 }, -+ { R367_OFDM_SFDLYSETL, 0x00 }, -+ { R367_OFDM_SFOBSCFG, 0x00 }, -+ { R367_OFDM_SFOBSM, 0x47 }, -+ { R367_OFDM_SFOBSL, 0x05 }, -+ { R367_OFDM_SFECINFO, 0x40 }, -+ { R367_OFDM_SFERRCTRL, 0x74 }, -+ { R367_OFDM_SFERRCNTH, 0x80 }, -+ { R367_OFDM_SFERRCNTM, 0x00 }, -+ { R367_OFDM_SFERRCNTL, 0x00 }, -+ { R367_OFDM_SYMBRATEM, 0x2f }, -+ { R367_OFDM_SYMBRATEL, 0x50 }, -+ { R367_OFDM_SYMBSTATUS, 0x7f }, -+ { R367_OFDM_SYMBCFG, 0x00 }, -+ { R367_OFDM_SYMBFIFOM, 0xf4 }, -+ { R367_OFDM_SYMBFIFOL, 0x0d }, -+ { R367_OFDM_SYMBOFFSM, 0xf0 }, -+ { R367_OFDM_SYMBOFFSL, 0x2d }, -+ { 0x0000, 0x00 } /* EOT */ -+}; -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = { -+ .addr = adr, .flags = 0, .buf = data, .len = len }; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_warn("i2c_write error ([%02x] %04x: %02x)\n", -+ adr, (data[0] << 8) | data[1], -+ (len > 2 ? data[2] : 0)); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int i2c_read(struct i2c_adapter *adap, u8 adr, u16 reg, u8 *val, int count) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = { -+ {.addr = adr, .flags = 0, .buf = msg, .len = 2 }, -+ {.addr = adr, .flags = I2C_M_RD, .buf = val, .len = count } }; -+ -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ pr_warn("i2c_read error ([%02x] %04x)\n", -+ adr, reg); -+ return -EREMOTEIO; -+ } -+ -+ return 0; -+} -+ -+static int writereg(struct stv_state *state, u16 reg, u8 dat) -+{ -+ u8 mm[3] = { (reg >> 8), reg & 0xff, dat }; -+ -+ return i2c_write(state->i2c, state->adr, mm, 3); -+} -+ -+static int readreg(struct stv_state *state, u16 reg, u8 *val) -+{ -+ return i2c_read(state->i2c, state->adr, reg, val, 1); -+} -+ -+static int readregs(struct stv_state *state, u16 reg, u8 *val, int count) -+{ -+ return i2c_read(state->i2c, state->adr, reg, val, count); -+} -+ -+static int write_init_table(struct stv_state *state, struct init_table *tab) -+{ -+ while (1) { -+ if (!tab->adr) -+ break; -+ if (writereg(state, tab->adr, tab->data) < 0) -+ return -EREMOTEIO; -+ tab++; -+ } -+ -+ return 0; -+} -+ -+static int qam_set_modulation(struct stv_state *state) -+{ -+ int stat = 0; -+ -+ switch (state->modulation) { -+ case QAM_16: -+ writereg(state, R367_QAM_EQU_MAPPER, -+ state->qam_inversion | QAM_MOD_QAM16); -+ /* Set analog AGC reference */ -+ writereg(state, R367_QAM_AGC_PWR_REF_L, 0x64); -+ /* Set digital AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF, 0x00); -+ writereg(state, R367_QAM_FSM_STATE, 0x90); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xa7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN, 0x95); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER, 0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN, 0x8a); -+ break; -+ case QAM_32: -+ writereg(state, R367_QAM_EQU_MAPPER, -+ state->qam_inversion | QAM_MOD_QAM32); -+ /* Set analog AGC reference */ -+ writereg(state, R367_QAM_AGC_PWR_REF_L, 0x6e); -+ /* Set digital AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF, 0x00); -+ writereg(state, R367_QAM_FSM_STATE, 0xb0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xb7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN, 0x9d); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER, 0x7f); -+ writereg(state, R367_QAM_EQU_PNT_GAIN, 0xa7); -+ break; -+ case QAM_64: -+ writereg(state, R367_QAM_EQU_MAPPER, -+ state->qam_inversion | QAM_MOD_QAM64); -+ /* Set analog AGC reference */ -+ writereg(state, R367_QAM_AGC_PWR_REF_L, 0x5a); -+ /* Set digital AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF, 0x82); -+ -+ if (state->symbol_rate > 4500000) { -+ writereg(state, R367_QAM_FSM_STATE, 0xb0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xa5); -+ } else if (state->symbol_rate > 2500000) { /* 25000000 */ -+ writereg(state, R367_QAM_FSM_STATE, 0xa0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xa6); -+ } else { -+ writereg(state, R367_QAM_FSM_STATE, 0xa0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xd1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xa7); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN, 0x95); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER, 0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN, 0x99); -+ break; -+ case QAM_128: -+ writereg(state, R367_QAM_EQU_MAPPER, -+ state->qam_inversion | QAM_MOD_QAM128); -+ /* Set analog AGC reference */ -+ writereg(state, R367_QAM_AGC_PWR_REF_L, 0x76); -+ /* Set digital AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF, 0x00); -+ writereg(state, R367_QAM_FSM_STATE, 0x90); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xb1); -+ if (state->symbol_rate > 4500000) { /* 45000000 */ -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xa7); -+ } else if (state->symbol_rate > 2500000) { /* 25000000 */ -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xa6); -+ } else { -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0x97); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN, 0x8e); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER, 0x7f); -+ writereg(state, R367_QAM_EQU_PNT_GAIN, 0xa7); -+ break; -+ case QAM_256: -+ writereg(state, R367_QAM_EQU_MAPPER, -+ state->qam_inversion | QAM_MOD_QAM256); -+ /* Set analog AGC reference */ -+ writereg(state, R367_QAM_AGC_PWR_REF_L, 0x5a); -+ /* Set digital AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF, 0x94); -+ writereg(state, R367_QAM_FSM_STATE, 0xa0); -+ -+ if (state->symbol_rate > 4500000) { /* 45000000 */ -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xc1); -+ } else if (state->symbol_rate > 2500000) { /* 25000000 */ -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xc1); -+ } else { -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, 0xd1); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN, 0xa7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN, 0x85); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER, 0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN, 0xa7); -+ break; -+ default: -+ stat = -EINVAL; -+ break; -+ } -+ return stat; -+} -+ -+static int QAM_SetSymbolRate(struct stv_state *state) -+{ -+ int status = 0; -+ u32 sr = state->symbol_rate; -+ u32 Corr = 0; -+ u32 Temp, Temp1, AdpClk; -+ -+ switch (state->modulation) { -+ default: -+ case QAM_16: -+ Corr = 1032; -+ break; -+ case QAM_32: -+ Corr = 954; -+ break; -+ case QAM_64: -+ Corr = 983; -+ break; -+ case QAM_128: -+ Corr = 957; -+ break; -+ case QAM_256: -+ Corr = 948; -+ break; -+ } -+ -+ /* Transfer ration */ -+ Temp = (256*sr) / state->adc_clock; -+ writereg(state, R367_QAM_EQU_CRL_TFR, (Temp)); -+ -+ /* Symbol rate and SRC gain calculation */ -+ /* TRL works at half the system clock */ -+ AdpClk = (state->master_clock) / 2000; -+ -+ Temp = state->symbol_rate; -+ Temp1 = sr; -+ -+ if (sr < 2097152) { /* 2097152 = 2^21 */ -+ Temp = ((((sr * 2048) / AdpClk) * 16384) / 125) * 8; -+ Temp1 = (((((sr * 2048) / 439) * 256) / AdpClk) -+ * Corr * 9) / 10000000; -+ } else if (sr < 4194304) { /* 4194304 = 2**22 */ -+ Temp = ((((sr * 1024) / AdpClk) * 16384) / 125) * 16; -+ Temp1 = (((((sr * 1024) / 439) * 256) / AdpClk) -+ * Corr * 9) / 5000000; -+ } else if (sr < 8388608) { /* 8388608 = 2**23 */ -+ Temp = ((((sr * 512) / AdpClk) * 16384) / 125) * 32; -+ Temp1 = (((((sr * 512) / 439) * 256) / AdpClk) -+ * Corr * 9) / 2500000; -+ } else { -+ Temp = ((((sr * 256) / AdpClk) * 16384) / 125) * 64; -+ Temp1 = (((((sr * 256) / 439) * 256) / AdpClk) -+ * Corr * 9) / 1250000; -+ } -+ -+ writereg(state, R367_QAM_SRC_NCO_LL, (Temp)); -+ writereg(state, R367_QAM_SRC_NCO_LH, (Temp>>8)); -+ writereg(state, R367_QAM_SRC_NCO_HL, (Temp>>16)); -+ writereg(state, R367_QAM_SRC_NCO_HH, (Temp>>24)); -+ -+ writereg(state, R367_QAM_IQDEM_GAIN_SRC_L, (Temp1)); -+ writereg(state, R367_QAM_IQDEM_GAIN_SRC_H, (Temp1>>8)); -+ return status; -+} -+ -+static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency) -+{ -+ int status = 0; -+ u32 Sampled_IF; -+ -+ do { -+ if (DerotFrequency > state->adc_clock) -+ /* User Alias */ -+ DerotFrequency = DerotFrequency - state->adc_clock; -+ -+ Sampled_IF = ((32768 * (DerotFrequency/1000)) -+ / (state->adc_clock/1000)) * 256; -+ if (Sampled_IF > 8388607) -+ Sampled_IF = 8388607; -+ -+ writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF)); -+ writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8)); -+ writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16)); -+ } while (0); -+ -+ return status; -+} -+ -+static int QAM_Start(struct stv_state *state, s32 offsetFreq, -+ s32 IntermediateFrequency) -+{ -+ int status = 0; -+ u32 AGCTimeOut = 25; -+ u32 TRLTimeOut = 100000000 / state->symbol_rate; -+ u32 CRLSymbols = 0; -+ u32 EQLTimeOut = 100; -+ u32 SearchRange = state->symbol_rate / 25; -+ u32 CRLTimeOut; -+ u8 Temp; -+ -+ if (state->demod_state != QAMSet) { -+ writereg(state, R367_DEBUG_LT4, 0x00); -+ writereg(state, R367_DEBUG_LT5, 0x01); -+ writereg(state, R367_DEBUG_LT6, 0x06); /* R367_QAM_CTRL_1 */ -+ writereg(state, R367_DEBUG_LT7, 0x03); /* R367_QAM_CTRL_2 */ -+ writereg(state, R367_DEBUG_LT8, 0x00); -+ writereg(state, R367_DEBUG_LT9, 0x00); -+ -+ /* Tuner Setup */ -+ /* Buffer Q disabled, I Enabled, signed ADC */ -+ writereg(state, R367_ANADIGCTRL, 0x8B); -+ /* ADCQ disabled */ -+ writereg(state, R367_DUAL_AD12, 0x04); -+ -+ /* Clock setup */ -+ /* PLL bypassed and disabled */ -+ writereg(state, R367_ANACTRL, 0x0D); -+ /* Set QAM */ -+ writereg(state, R367_TOPCTRL, 0x10); -+ -+ /* IC runs at 58 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLMDIV, 27); -+ writereg(state, R367_PLLNDIV, 232); -+ /* ADC clock is equal to system clock */ -+ writereg(state, R367_PLLSETUP, 0x18); -+ -+ msleep(50); -+ /* PLL enabled and used */ -+ writereg(state, R367_ANACTRL, 0x00); -+ -+ state->master_clock = 58000000; -+ state->adc_clock = 58000000; -+ -+ state->demod_state = QAMSet; -+ } -+ -+ state->m_bFirstTimeLock = true; -+ state->m_DemodLockTime = -1; -+ -+ qam_set_modulation(state); -+ QAM_SetSymbolRate(state); -+ -+ /* Will make problems on low symbol rates ( < 2500000 ) */ -+ -+ switch (state->modulation) { -+ default: -+ case QAM_16: -+ CRLSymbols = 150000; -+ break; -+ case QAM_32: -+ CRLSymbols = 250000; -+ break; -+ case QAM_64: -+ CRLSymbols = 200000; -+ break; -+ case QAM_128: -+ CRLSymbols = 250000; -+ break; -+ case QAM_256: -+ CRLSymbols = 250000; -+ break; -+ } -+ -+ CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) -+ / (state->symbol_rate/1000); -+ CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate; -+ if (CRLTimeOut < 50) -+ CRLTimeOut = 50; -+ -+ state->m_FECTimeOut = 20; -+ state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut -+ + EQLTimeOut; -+ state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut; -+ -+ /* QAM_AGC_ACCUMRSTSEL = 0 */ -+ readreg(state, R367_QAM_AGC_CTL, &state->m_Save_QAM_AGC_CTL); -+ writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL & ~0x0F); -+ -+ /* QAM_MODULUSMAP_EN = 0 */ -+ readreg(state, R367_QAM_EQU_PNT_GAIN, &Temp); -+ writereg(state, R367_QAM_EQU_PNT_GAIN, Temp & ~0x40); -+ -+ /* QAM_SWEEP_EN = 0 */ -+ readreg(state, R367_QAM_EQU_CTR_LPF_GAIN, &Temp); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN, Temp & ~0x08); -+ -+ QAM_SetDerotFrequency(state, IntermediateFrequency); -+ -+ /* Release TRL */ -+ writereg(state, R367_QAM_CTRL_1, 0x00); -+ -+ state->IF = IntermediateFrequency; -+ state->demod_state = QAMStarted; -+ -+ return status; -+} -+ -+static int OFDM_Start(struct stv_state *state, s32 offsetFreq, -+ s32 IntermediateFrequency) -+{ -+ int status = 0; -+ u8 GAIN_SRC1; -+ u32 Derot; -+ u8 SYR_CTL; -+ u8 tmp1; -+ u8 tmp2; -+ -+ if (state->demod_state != OFDMSet) { -+ /* QAM Disable */ -+ writereg(state, R367_DEBUG_LT4, 0x00); -+ writereg(state, R367_DEBUG_LT5, 0x00); -+ writereg(state, R367_DEBUG_LT6, 0x00); /* R367_QAM_CTRL_1 */ -+ writereg(state, R367_DEBUG_LT7, 0x00); /* R367_QAM_CTRL_2 */ -+ writereg(state, R367_DEBUG_LT8, 0x00); -+ writereg(state, R367_DEBUG_LT9, 0x00); -+ -+ /* Tuner Setup */ -+ /* Buffer Q disabled, I Enabled, unsigned ADC */ -+ writereg(state, R367_ANADIGCTRL, 0x89); -+ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ -+ -+ /* Clock setup */ -+ /* PLL bypassed and disabled */ -+ writereg(state, R367_ANACTRL, 0x0D); -+ writereg(state, R367_TOPCTRL, 0x00); /* Set OFDM */ -+ -+ /* IC runs at 54 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLMDIV, 1); -+ writereg(state, R367_PLLNDIV, 8); -+ /* ADC clock is equal to system clock */ -+ writereg(state, R367_PLLSETUP, 0x18); -+ -+ msleep(50); -+ /* PLL enabled and used */ -+ writereg(state, R367_ANACTRL, 0x00); -+ -+ state->master_clock = 54000000; -+ state->adc_clock = 54000000; -+ -+ state->demod_state = OFDMSet; -+ } -+ -+ state->m_bFirstTimeLock = true; -+ state->m_DemodLockTime = -1; -+ -+ /* Set inversion in GAIN_SRC1 (fixed from init) -+ * is in GAIN_SRC1, see below -+ */ -+ -+ GAIN_SRC1 = 0xA0; -+ /* Bandwidth */ -+ -+ /* Fixed values for 54 MHz */ -+ switch (state->bandwidth) { -+ case 0: -+ case 8000000: -+ /* Normrate = 44384 */ -+ writereg(state, R367_OFDM_TRL_CTL, 0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1, 0xB0); -+ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56); -+ /* Gain SRC = 2774 */ -+ writereg(state, R367_OFDM_GAIN_SRC1, 0x0A | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2, 0xD6); -+ break; -+ case 7000000: -+ /* Normrate = 38836 */ -+ writereg(state, R367_OFDM_TRL_CTL, 0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1, 0xDA); -+ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x4B); -+ /* Gain SRC = 2427 */ -+ writereg(state, R367_OFDM_GAIN_SRC1, 0x09 | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2, 0x7B); -+ break; -+ case 6000000: -+ /* Normrate = 33288 */ -+ writereg(state, R367_OFDM_TRL_CTL, 0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1, 0x04); -+ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x41); -+ /* Gain SRC = 2080 */ -+ writereg(state, R367_OFDM_GAIN_SRC1, 0x08 | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2, 0x20); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ Derot = ((IntermediateFrequency / 1000) * 65536) -+ / (state->master_clock / 1000); -+ -+ writereg(state, R367_OFDM_INC_DEROT1, (Derot>>8)); -+ writereg(state, R367_OFDM_INC_DEROT2, (Derot)); -+ -+ readreg(state, R367_OFDM_SYR_CTL, &SYR_CTL); -+ SYR_CTL &= ~0x78; -+ writereg(state, R367_OFDM_SYR_CTL, SYR_CTL); /* EchoPos = 0 */ -+ -+ -+ /* Force = 0, Mode = 0, Guard = 3 */ -+ writereg(state, R367_OFDM_COR_MODEGUARD, 0x03); -+ SYR_CTL &= 0x01; -+ writereg(state, R367_OFDM_SYR_CTL, SYR_CTL); /* SYR_TR_DIS = 0 */ -+ -+ usleep_range(5000, 6000); -+ -+ writereg(state, R367_OFDM_COR_CTL, 0x20); /* Start core */ -+ -+ /* -- Begin M.V. -+ * Reset FEC and Read Solomon -+ */ -+ readreg(state, R367_OFDM_SFDLYSETH, &tmp1); -+ readreg(state, R367_TSGENERAL, &tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH, tmp1 | 0x08); -+ writereg(state, R367_TSGENERAL, tmp2 | 0x01); -+ /* -- End M.V. */ -+ -+ state->m_SignalTimeOut = 200; -+ state->IF = IntermediateFrequency; -+ state->demod_state = OFDMStarted; -+ state->m_DemodTimeOut = 0; -+ state->m_FECTimeOut = 0; -+ state->m_TSTimeOut = 0; -+ -+ return status; -+} -+ -+static int QAM_GetSignalToNoise(struct stv_state *state, u16 *snr) -+{ -+ u32 RegValAvg = 0, tmpval; -+ s32 snrval; -+ u8 RegVal[2]; -+ int i; -+ -+ *snr = 0; -+ for (i = 0; i < 10; i += 1) { -+ readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2); -+ RegValAvg += RegVal[0] + 256 * RegVal[1]; -+ } -+ if (RegValAvg != 0) { -+ s32 Power = 1; -+ -+ switch (state->modulation) { -+ case QAM_16: -+ Power = 20480; -+ break; -+ case QAM_32: -+ Power = 23040; -+ break; -+ case QAM_64: -+ Power = 21504; -+ break; -+ case QAM_128: -+ Power = 23616; -+ break; -+ case QAM_256: -+ Power = 21760; -+ break; -+ default: -+ break; -+ } -+ tmpval = (Power * 320) / RegValAvg; -+ snrval = ((tmpval != 0) ? INTLOG10X100(tmpval) : 0); -+ } else { -+ snrval = 380; -+ } -+ -+ *snr = 0xffff & (snrval * 100); -+ return 0; -+} -+ -+static int OFDM_GetSignalToNoise(struct stv_state *state, u16 *snr) -+{ -+ u8 CHC_SNR = 0; -+ -+ *snr = 0; -+ -+ if (readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR) >= 0) { -+ /* Note: very unclear documentation on this. -+ * Datasheet states snr = CHC_SNR/4 dB -> way to high values! -+ * Software snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -+ * -> to low values -+ * Comment in SW states this should be -+ * ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367 -+ * 361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best -+ */ -+ *snr = ((u16)CHC_SNR * 1000) / 8; -+ return 0; -+ } -+ return -EINVAL; -+} -+ -+static int attach_init(struct stv_state *state) -+{ -+ int stat = 0; -+ -+ stat = readreg(state, R367_ID, &state->ID); -+ if (stat < 0 || state->ID != 0x60) -+ return -ENODEV; -+ -+ pr_info("%s demod with ChipID %02X found at adr %02X on %s\n", -+ state->frontend.ops.info.name, state->ID, state->adr, -+ dev_name(&state->i2c->dev)); -+ -+ writereg(state, R367_TOPCTRL, 0x10); -+ write_init_table(state, base_init); -+ write_init_table(state, qam_init); -+ -+ writereg(state, R367_TOPCTRL, 0x00); -+ write_init_table(state, ofdm_init); -+ -+ writereg(state, R367_OFDM_GAIN_SRC1, 0x2A); -+ writereg(state, R367_OFDM_GAIN_SRC2, 0xD6); -+ writereg(state, R367_OFDM_INC_DEROT1, 0x55); -+ writereg(state, R367_OFDM_INC_DEROT2, 0x55); -+ writereg(state, R367_OFDM_TRL_CTL, 0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE); -+ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56); -+ writereg(state, R367_OFDM_FEPATH_CFG, 0x0); -+ -+ /* OFDM TS Setup */ -+ -+ writereg(state, R367_OFDM_TSCFGH, 0x70); -+ writereg(state, R367_OFDM_TSCFGM, 0xC0); -+ writereg(state, R367_OFDM_TSCFGL, 0x20); -+ writereg(state, R367_OFDM_TSSPEED, 0x40); /* Fixed at 54 MHz */ -+ -+ writereg(state, R367_OFDM_TSCFGH, 0x71); -+ -+ if (state->cont_clock) -+ writereg(state, R367_OFDM_TSCFGH, 0xf0); -+ else -+ writereg(state, R367_OFDM_TSCFGH, 0x70); -+ -+ writereg(state, R367_TOPCTRL, 0x10); -+ -+ /* Also needed for QAM */ -+ writereg(state, R367_OFDM_AGC12C, 0x01); /* AGC Pin setup */ -+ -+ writereg(state, R367_OFDM_AGCCTRL1, 0x8A); -+ -+ /* QAM TS setup, note exact format also depends on descrambler */ -+ /* settings */ -+ /* Inverted Clock, Swap, serial */ -+ writereg(state, R367_QAM_OUTFORMAT_0, 0x85); -+ -+ /* Clock setup */ -+ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ -+ -+ if (state->master_clock == 58000000) { -+ /* IC runs at 58 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLMDIV, 27); -+ writereg(state, R367_PLLNDIV, 232); -+ } else { -+ /* IC runs at 54 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLMDIV, 1); -+ writereg(state, R367_PLLNDIV, 8); -+ } -+ -+ /* ADC clock is equal to system clock */ -+ writereg(state, R367_PLLSETUP, 0x18); -+ -+ /* Tuner setup */ -+ /* Buffer Q disabled, I Enabled, signed ADC */ -+ writereg(state, R367_ANADIGCTRL, 0x8b); -+ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ -+ -+ /* Improves the C/N lock limit */ -+ writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); -+ writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */ -+ /* Improving burst noise performances */ -+ writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); -+ /* Improving ACI performances */ -+ writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); -+ -+ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ -+ -+ writereg(state, R367_I2CRPT, state->I2CRPT); -+ state->demod_state = QAMSet; -+ return stat; -+} -+ -+static void release(struct dvb_frontend *fe) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ -+ pr_info("%s()\n", __func__); -+ kfree(state); -+} -+ -+static int gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u8 i2crpt = state->I2CRPT & ~0x80; -+ -+ if (enable) -+ i2crpt |= 0x80; -+ if (writereg(state, R367_I2CRPT, i2crpt) < 0) -+ return -EIO; -+ state->I2CRPT = i2crpt; -+ return 0; -+} -+ -+static int ofdm_lock(struct stv_state *state) -+{ -+ int status = 0; -+ u8 OFDM_Status; -+ s32 DemodTimeOut = 10; -+ s32 FECTimeOut = 0; -+ s32 TSTimeOut = 0; -+ u8 CPAMPMin = 255; -+ u8 CPAMPValue; -+ u8 SYR_STAT; -+ u8 FFTMode; -+ u8 TSStatus; -+ -+ msleep(state->m_SignalTimeOut); -+ readreg(state, R367_OFDM_STATUS, &OFDM_Status); -+ -+ if (!(OFDM_Status & 0x40)) -+ return -EIO; -+ -+ readreg(state, R367_OFDM_SYR_STAT, &SYR_STAT); -+ FFTMode = (SYR_STAT & 0x0C) >> 2; -+ -+ switch (FFTMode) { -+ case 0: /* 2K */ -+ DemodTimeOut = 10; -+ FECTimeOut = 150; -+ TSTimeOut = 125; -+ CPAMPMin = 20; -+ break; -+ case 1: /* 8K */ -+ DemodTimeOut = 55; -+ FECTimeOut = 600; -+ TSTimeOut = 500; -+ CPAMPMin = 80; -+ break; -+ case 2: /* 4K */ -+ DemodTimeOut = 40; -+ FECTimeOut = 300; -+ TSTimeOut = 250; -+ CPAMPMin = 30; -+ break; -+ } -+ state->m_OFDM_FFTMode = FFTMode; -+ readreg(state, R367_OFDM_PPM_CPAMP_DIR, &CPAMPValue); -+ msleep(DemodTimeOut); -+ { -+ /* Release FEC and Read Solomon Reset */ -+ u8 tmp1; -+ u8 tmp2; -+ -+ readreg(state, R367_OFDM_SFDLYSETH, &tmp1); -+ readreg(state, R367_TSGENERAL, &tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH, tmp1 & ~0x08); -+ writereg(state, R367_TSGENERAL, tmp2 & ~0x01); -+ } -+ msleep(FECTimeOut); -+ if ((OFDM_Status & 0x98) != 0x98) -+ ;/* return -1; */ -+ /* printk("lock 2\n"); */ -+ -+ { -+ u8 Guard = (SYR_STAT & 0x03); -+ -+ if (Guard < 2) { -+ u8 tmp; -+ -+ readreg(state, R367_OFDM_SYR_CTL, &tmp); -+ /* Clear AUTO_LE_EN */ -+ writereg(state, R367_OFDM_SYR_CTL, tmp & ~0x04); -+ readreg(state, R367_OFDM_SYR_UPDATE, &tmp); -+ /* Clear SYR_FILTER */ -+ writereg(state, R367_OFDM_SYR_UPDATE, tmp & ~0x10); -+ } else { -+ u8 tmp; -+ -+ readreg(state, R367_OFDM_SYR_CTL, &tmp); -+ /* Set AUTO_LE_EN */ -+ writereg(state, R367_OFDM_SYR_CTL, tmp | 0x04); -+ readreg(state, R367_OFDM_SYR_UPDATE, &tmp); -+ /* Set SYR_FILTER */ -+ writereg(state, R367_OFDM_SYR_UPDATE, tmp | 0x10); -+ } -+ -+ /* apply Sfec workaround if 8K 64QAM CR!=1/2 */ -+ if (FFTMode == 1) { -+ u8 tmp[2]; -+ -+ readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2); -+ if (((tmp[0] & 0x03) == 0x02) && ((tmp[1] & 0x07) != 0)) { -+ writereg(state, R367_OFDM_SFDLYSETH, 0xc0); -+ writereg(state, R367_OFDM_SFDLYSETM, 0x60); -+ writereg(state, R367_OFDM_SFDLYSETL, 0x00); -+ } else { -+ writereg(state, R367_OFDM_SFDLYSETH, 0x00); -+ } -+ } -+ } -+ msleep(TSTimeOut); -+ readreg(state, R367_OFDM_TSSTATUS, &TSStatus); -+ if ((TSStatus & 0x80) != 0x80) -+ return -EIO; -+ -+ return status; -+} -+ -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ int stat; -+ struct stv_state *state = fe->demodulator_priv; -+ u32 OF = 0; -+ u32 IF; -+ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ /* symbol rate 0 might cause an oops */ -+ if (fe->dtv_property_cache.symbol_rate == 0) { -+ pr_err("Invalid symbol rate\n"); -+ return -EINVAL; -+ } -+ break; -+ case SYS_DVBT: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ state->delsys = fe->dtv_property_cache.delivery_system; -+ -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ state->modulation = fe->dtv_property_cache.modulation; -+ state->symbol_rate = fe->dtv_property_cache.symbol_rate; -+ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; -+ fe->ops.tuner_ops.get_if_frequency(fe, &IF); -+ -+ switch (state->delsys) { -+ case SYS_DVBT: -+ stat = OFDM_Start(state, OF, IF); -+ ofdm_lock(state); -+ break; -+ case SYS_DVBC_ANNEX_A: -+ stat = QAM_Start(state, OF, IF); -+ break; -+ default: -+ stat = -EINVAL; -+ } -+ -+ return stat; -+} -+ -+static int read_status(struct dvb_frontend *fe, enum fe_status *status) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ *status = 0; -+ -+ switch (state->demod_state) { -+ case QAMStarted: -+ { -+ u8 FEC_Lock; -+ u8 QAM_Lock; -+ -+ readreg(state, R367_QAM_FSM_STS, &QAM_Lock); -+ QAM_Lock &= 0x0F; -+ if (QAM_Lock > 10) -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI); -+ readreg(state, R367_QAM_FEC_STATUS, &FEC_Lock); -+ if (FEC_Lock&2) -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI -+ | FE_HAS_SYNC -+ | FE_HAS_LOCK); -+ if (state->m_bFirstTimeLock) { -+ state->m_bFirstTimeLock = false; -+ /* QAM_AGC_ACCUMRSTSEL to Tracking */ -+ writereg(state, R367_QAM_AGC_CTL, -+ state->m_Save_QAM_AGC_CTL); -+ } -+ break; -+ } -+ case OFDMStarted: -+ { -+ u8 OFDM_Status; -+ u8 TSStatus; -+ -+ readreg(state, R367_OFDM_TSSTATUS, &TSStatus); -+ -+ readreg(state, R367_OFDM_STATUS, &OFDM_Status); -+ if (OFDM_Status & 0x40) -+ *status |= FE_HAS_SIGNAL; -+ -+ if ((OFDM_Status & 0x98) == 0x98) -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI -+ | FE_HAS_SYNC); -+ -+ if (TSStatus & 0x80) -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI -+ | FE_HAS_SYNC -+ | FE_HAS_LOCK); -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int read_ber_ter(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u32 err; -+ u8 cnth, cntm, cntl; -+ -+ readreg(state, R367_OFDM_SFERRCNTH, &cnth); -+ -+ if (cnth & 0x80) { -+ *ber = state->ber; -+ return 0; -+ } -+ -+ readreg(state, R367_OFDM_SFERRCNTM, &cntm); -+ readreg(state, R367_OFDM_SFERRCNTL, &cntl); -+ -+ err = ((cnth & 0x7f) << 16) | (cntm << 8) | cntl; -+ -+ *ber = state->ber = err; -+ return 0; -+} -+ -+static int read_ber_cab(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u32 err; -+ u8 cntm, cntl, ctrl; -+ -+ readreg(state, R367_QAM_BERT_1, &ctrl); -+ if (!(ctrl & 0x20)) { -+ readreg(state, R367_QAM_BERT_2, &cntl); -+ readreg(state, R367_QAM_BERT_3, &cntm); -+ err = (cntm << 8) | cntl; -+ state->ber = err; -+ writereg(state, R367_QAM_BERT_1, 0x27); -+ } -+ *ber = (u32) state->ber; -+ return 0; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ -+ if (state->demod_state == QAMStarted) -+ return read_ber_cab(fe, ber); -+ if (state->demod_state == OFDMStarted) -+ return read_ber_ter(fe, ber); -+ *ber = 0; -+ return 0; -+} -+ -+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ if (fe->ops.tuner_ops.get_rf_strength) -+ fe->ops.tuner_ops.get_rf_strength(fe, strength); -+ else -+ *strength = 0; -+ return 0; -+} -+ -+static int read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ -+ *snr = 0; -+ -+ switch (state->demod_state) { -+ case QAMStarted: -+ return QAM_GetSignalToNoise(state, snr); -+ case OFDMStarted: -+ return OFDM_GetSignalToNoise(state, snr); -+ default: -+ break; -+ } -+ -+ return -EINVAL; -+} -+ -+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u8 errl, errm, errh; -+ u8 val; -+ -+ switch (state->demod_state) { -+ case QAMStarted: -+ readreg(state, R367_QAM_RS_COUNTER_4, &errl); -+ readreg(state, R367_QAM_RS_COUNTER_5, &errm); -+ *ucblocks = (errm << 8) | errl; -+ break; -+ case OFDMStarted: -+ readreg(state, R367_OFDM_SFERRCNTH, &val); -+ if ((val & 0x80) == 0) { -+ readreg(state, R367_OFDM_ERRCNT1H, &errh); -+ readreg(state, R367_OFDM_ERRCNT1M, &errl); -+ readreg(state, R367_OFDM_ERRCNT1L, &errm); -+ state->ucblocks = (errh << 16) | (errm << 8) | errl; -+ } -+ *ucblocks = state->ucblocks; -+ break; -+ default: -+ *ucblocks = 0; -+ break; -+ } -+ return 0; -+} -+ -+static int c_get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *sets) -+{ -+ sets->min_delay_ms = 3000; -+ sets->max_drift = 0; -+ sets->step_size = 0; -+ return 0; -+} -+ -+static int get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *sets) -+{ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ case SYS_DVBC_ANNEX_C: -+ return c_get_tune_settings(fe, sets); -+ default: -+ /* DVB-T: Use info.frequency_stepsize. */ -+ return -EINVAL; -+ } -+} -+ -+static int get_frontend(struct dvb_frontend *fe, -+ struct dtv_frontend_properties *p) -+{ -+ //struct stv_state *state = fe->demodulator_priv; -+ enum fe_status status = 0; -+ int tmp; -+ u16 snr = 0, strength = 0; -+ u32 ber = 0, ucblocks = 0; -+ -+ tmp = read_status(fe, &status); -+ -+ p->strength.len = 1; -+ p->cnr.len = 1; -+ p->post_bit_error.len = 1; -+ p->block_error.len = 1; -+ -+ if (!(status & FE_HAS_LOCK)) { -+ p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ return 0; -+ } -+ -+ if (read_snr(fe, &snr)) -+ p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->cnr.stat[0].scale = FE_SCALE_DECIBEL; -+ p->cnr.stat[0].svalue = snr; -+ } -+ -+ if (read_signal_strength(fe, &strength)) -+ p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->strength.stat[0].scale = FE_SCALE_RELATIVE; -+ p->strength.stat[0].svalue = strength; -+ } -+ -+ if (read_ber(fe, &ber)) -+ p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->post_bit_error.stat[0].uvalue = ber; -+ } -+ -+ if (read_ucblocks(fe, &ucblocks)) -+ p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->block_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->block_error.stat[0].uvalue = ucblocks; -+ } -+ -+ return 0; -+} -+ -+ -+static struct dvb_frontend_ops common_ops = { -+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT }, -+ .info = { -+ .name = "STV0367 DVB-C DVB-T", -+ .frequency_stepsize = 166667, /* DVB-T only */ -+ .frequency_min = 47000000, /* DVB-T: 47125000 */ -+ .frequency_max = 865000000, /* DVB-C: 862000000 */ -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = /* DVB-C */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | -+ FE_CAN_FEC_AUTO | -+ /* DVB-T */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | -+ 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_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS -+ }, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ -+ .get_tune_settings = get_tune_settings, -+ -+ .set_frontend = set_parameters, -+ .get_frontend = get_frontend, -+ -+ .read_status = read_status, -+}; -+ -+ -+static void init_state(struct stv_state *state, struct stv0367dd_cfg *cfg) -+{ -+ u32 ulENARPTLEVEL = 5; -+ u32 ulQAMInversion = 2; -+ -+ state->delsys = SYS_UNDEFINED; -+ state->adr = cfg->adr; -+ state->cont_clock = cfg->cont_clock; -+ -+ mutex_init(&state->mutex); -+ mutex_init(&state->ctlock); -+ -+ memcpy(&state->frontend.ops, &common_ops, -+ sizeof(struct dvb_frontend_ops)); -+ -+ state->frontend.demodulator_priv = state; -+ -+ state->master_clock = 58000000; -+ state->adc_clock = 58000000; -+ state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4); -+ state->qam_inversion = ((ulQAMInversion & 3) << 6); -+ state->demod_state = Off; -+} -+ -+struct dvb_frontend *stv0367dd_attach(struct i2c_adapter *i2c, -+ struct stv0367dd_cfg *cfg, struct dvb_frontend **fe_t) -+{ -+ struct stv_state *state = NULL; -+ -+ state = kzalloc(sizeof(struct stv_state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->i2c = i2c; -+ init_state(state, cfg); -+ -+ if (attach_init(state) < 0) -+ goto error; -+ return &state->frontend; -+ -+error: -+ pr_err("No supported demodulator found at adr %02X on %s\n", -+ cfg->adr, dev_name(&i2c->dev)); -+ -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL(stv0367dd_attach); -+ -+MODULE_DESCRIPTION("STV0367DD driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/stv0367dd.h b/drivers/media/dvb-frontends/stv0367dd.h -new file mode 100644 -index 0000000..2c0b426 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd.h -@@ -0,0 +1,31 @@ -+#ifndef _STV0367DD_H_ -+#define _STV0367DD_H_ -+ -+#include -+#include -+ -+struct stv0367dd_cfg { -+ u8 adr; -+ u32 xtal; -+ u8 parallel; -+ u8 cont_clock; -+}; -+ -+#if IS_REACHABLE(CONFIG_DVB_STV0367DD) -+ -+extern struct dvb_frontend *stv0367dd_attach(struct i2c_adapter *i2c, -+ struct stv0367dd_cfg *cfg, -+ struct dvb_frontend **fe_t); -+ -+#else -+ -+static inline struct dvb_frontend *stv0367dd_attach(struct i2c_adapter *i2c, -+ struct stv0367dd_cfg *cfg, struct dvb_frontend **fe_t) -+{ -+ pr_warn("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif /* CONFIG_DVB_STV0367DD */ -+ -+#endif /* _STV0367DD_H_ */ -diff --git a/drivers/media/dvb-frontends/stv0367dd_regs.h b/drivers/media/dvb-frontends/stv0367dd_regs.h -new file mode 100644 -index 0000000..4f22ae6 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd_regs.h -@@ -0,0 +1,3429 @@ -+/* @DVB-C/DVB-T STMicroelectronics STV0367 register defintions -+ * Author Manfred Voelkel, Februar 2011 -+ * (c) 2010 DigitalDevices GmbH Germany. All rights reserved -+ * -+ * ====================================================================== -+ * -- Registers Declaration -+ * -- ------------------------- -+ * -- Each register (R367_XXXXX) is defined by its address (2 bytes). -+ * -- -+ * -- Each field (F367_XXXXX)is defined as follow: -+ * -- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] -+ * ====================================================================== -+ */ -+ -+/* ID */ -+#define R367_ID 0xF000 -+#define F367_IDENTIFICATIONREG 0xF00000FF -+ -+/* I2CRPT */ -+#define R367_I2CRPT 0xF001 -+#define F367_I2CT_ON 0xF0010080 -+#define F367_ENARPT_LEVEL 0xF0010070 -+#define F367_SCLT_DELAY 0xF0010008 -+#define F367_SCLT_NOD 0xF0010004 -+#define F367_STOP_ENABLE 0xF0010002 -+#define F367_SDAT_NOD 0xF0010001 -+ -+/* TOPCTRL */ -+#define R367_TOPCTRL 0xF002 -+#define F367_STDBY 0xF0020080 -+#define F367_STDBY_FEC 0xF0020040 -+#define F367_STDBY_CORE 0xF0020020 -+#define F367_QAM_COFDM 0xF0020010 -+#define F367_TS_DIS 0xF0020008 -+#define F367_DIR_CLK_216 0xF0020004 -+#define F367_TUNER_BB 0xF0020002 -+#define F367_DVBT_H 0xF0020001 -+ -+/* IOCFG0 */ -+#define R367_IOCFG0 0xF003 -+#define F367_OP0_SD 0xF0030080 -+#define F367_OP0_VAL 0xF0030040 -+#define F367_OP0_OD 0xF0030020 -+#define F367_OP0_INV 0xF0030010 -+#define F367_OP0_DACVALUE_HI 0xF003000F -+ -+/* DAC0R */ -+#define R367_DAC0R 0xF004 -+#define F367_OP0_DACVALUE_LO 0xF00400FF -+ -+/* IOCFG1 */ -+#define R367_IOCFG1 0xF005 -+#define F367_IP0 0xF0050040 -+#define F367_OP1_OD 0xF0050020 -+#define F367_OP1_INV 0xF0050010 -+#define F367_OP1_DACVALUE_HI 0xF005000F -+ -+/* DAC1R */ -+#define R367_DAC1R 0xF006 -+#define F367_OP1_DACVALUE_LO 0xF00600FF -+ -+/* IOCFG2 */ -+#define R367_IOCFG2 0xF007 -+#define F367_OP2_LOCK_CONF 0xF00700E0 -+#define F367_OP2_OD 0xF0070010 -+#define F367_OP2_VAL 0xF0070008 -+#define F367_OP1_LOCK_CONF 0xF0070007 -+ -+/* SDFR */ -+#define R367_SDFR 0xF008 -+#define F367_OP0_FREQ 0xF00800F0 -+#define F367_OP1_FREQ 0xF008000F -+ -+/* STATUS */ -+#define R367_OFDM_STATUS 0xF009 -+#define F367_TPS_LOCK 0xF0090080 -+#define F367_SYR_LOCK 0xF0090040 -+#define F367_AGC_LOCK 0xF0090020 -+#define F367_PRF 0xF0090010 -+#define F367_LK 0xF0090008 -+#define F367_PR 0xF0090007 -+ -+/* AUX_CLK */ -+#define R367_AUX_CLK 0xF00A -+#define F367_AUXFEC_CTL 0xF00A00C0 -+#define F367_DIS_CKX4 0xF00A0020 -+#define F367_CKSEL 0xF00A0018 -+#define F367_CKDIV_PROG 0xF00A0006 -+#define F367_AUXCLK_ENA 0xF00A0001 -+ -+/* FREESYS1 */ -+#define R367_FREESYS1 0xF00B -+#define F367_FREE_SYS1 0xF00B00FF -+ -+/* FREESYS2 */ -+#define R367_FREESYS2 0xF00C -+#define F367_FREE_SYS2 0xF00C00FF -+ -+/* FREESYS3 */ -+#define R367_FREESYS3 0xF00D -+#define F367_FREE_SYS3 0xF00D00FF -+ -+/* GPIO_CFG */ -+#define R367_GPIO_CFG 0xF00E -+#define F367_GPIO7_NOD 0xF00E0080 -+#define F367_GPIO7_CFG 0xF00E0040 -+#define F367_GPIO6_NOD 0xF00E0020 -+#define F367_GPIO6_CFG 0xF00E0010 -+#define F367_GPIO5_NOD 0xF00E0008 -+#define F367_GPIO5_CFG 0xF00E0004 -+#define F367_GPIO4_NOD 0xF00E0002 -+#define F367_GPIO4_CFG 0xF00E0001 -+ -+/* GPIO_CMD */ -+#define R367_GPIO_CMD 0xF00F -+#define F367_GPIO7_VAL 0xF00F0008 -+#define F367_GPIO6_VAL 0xF00F0004 -+#define F367_GPIO5_VAL 0xF00F0002 -+#define F367_GPIO4_VAL 0xF00F0001 -+ -+/* AGC2MAX */ -+#define R367_OFDM_AGC2MAX 0xF010 -+#define F367_OFDM_AGC2_MAX 0xF01000FF -+ -+/* AGC2MIN */ -+#define R367_OFDM_AGC2MIN 0xF011 -+#define F367_OFDM_AGC2_MIN 0xF01100FF -+ -+/* AGC1MAX */ -+#define R367_OFDM_AGC1MAX 0xF012 -+#define F367_OFDM_AGC1_MAX 0xF01200FF -+ -+/* AGC1MIN */ -+#define R367_OFDM_AGC1MIN 0xF013 -+#define F367_OFDM_AGC1_MIN 0xF01300FF -+ -+/* AGCR */ -+#define R367_OFDM_AGCR 0xF014 -+#define F367_OFDM_RATIO_A 0xF01400E0 -+#define F367_OFDM_RATIO_B 0xF0140018 -+#define F367_OFDM_RATIO_C 0xF0140007 -+ -+/* AGC2TH */ -+#define R367_OFDM_AGC2TH 0xF015 -+#define F367_OFDM_AGC2_THRES 0xF01500FF -+ -+/* AGC12C */ -+#define R367_OFDM_AGC12C 0xF016 -+#define F367_OFDM_AGC1_IV 0xF0160080 -+#define F367_OFDM_AGC1_OD 0xF0160040 -+#define F367_OFDM_AGC1_LOAD 0xF0160020 -+#define F367_OFDM_AGC2_IV 0xF0160010 -+#define F367_OFDM_AGC2_OD 0xF0160008 -+#define F367_OFDM_AGC2_LOAD 0xF0160004 -+#define F367_OFDM_AGC12_MODE 0xF0160003 -+ -+/* AGCCTRL1 */ -+#define R367_OFDM_AGCCTRL1 0xF017 -+#define F367_OFDM_DAGC_ON 0xF0170080 -+#define F367_OFDM_INVERT_AGC12 0xF0170040 -+#define F367_OFDM_AGC1_MODE 0xF0170008 -+#define F367_OFDM_AGC2_MODE 0xF0170007 -+ -+/* AGCCTRL2 */ -+#define R367_OFDM_AGCCTRL2 0xF018 -+#define F367_OFDM_FRZ2_CTRL 0xF0180060 -+#define F367_OFDM_FRZ1_CTRL 0xF0180018 -+#define F367_OFDM_TIME_CST 0xF0180007 -+ -+/* AGC1VAL1 */ -+#define R367_OFDM_AGC1VAL1 0xF019 -+#define F367_OFDM_AGC1_VAL_LO 0xF01900FF -+ -+/* AGC1VAL2 */ -+#define R367_OFDM_AGC1VAL2 0xF01A -+#define F367_OFDM_AGC1_VAL_HI 0xF01A000F -+ -+/* AGC2VAL1 */ -+#define R367_OFDM_AGC2VAL1 0xF01B -+#define F367_OFDM_AGC2_VAL_LO 0xF01B00FF -+ -+/* AGC2VAL2 */ -+#define R367_OFDM_AGC2VAL2 0xF01C -+#define F367_OFDM_AGC2_VAL_HI 0xF01C000F -+ -+/* AGC2PGA */ -+#define R367_OFDM_AGC2PGA 0xF01D -+#define F367_OFDM_AGC2_PGA 0xF01D00FF -+ -+/* OVF_RATE1 */ -+#define R367_OFDM_OVF_RATE1 0xF01E -+#define F367_OFDM_OVF_RATE_HI 0xF01E000F -+ -+/* OVF_RATE2 */ -+#define R367_OFDM_OVF_RATE2 0xF01F -+#define F367_OFDM_OVF_RATE_LO 0xF01F00FF -+ -+/* GAIN_SRC1 */ -+#define R367_OFDM_GAIN_SRC1 0xF020 -+#define F367_OFDM_INV_SPECTR 0xF0200080 -+#define F367_OFDM_IQ_INVERT 0xF0200040 -+#define F367_OFDM_INR_BYPASS 0xF0200020 -+#define F367_OFDM_STATUS_INV_SPECRUM 0xF0200010 -+#define F367_OFDM_GAIN_SRC_HI 0xF020000F -+ -+/* GAIN_SRC2 */ -+#define R367_OFDM_GAIN_SRC2 0xF021 -+#define F367_OFDM_GAIN_SRC_LO 0xF02100FF -+ -+/* INC_DEROT1 */ -+#define R367_OFDM_INC_DEROT1 0xF022 -+#define F367_OFDM_INC_DEROT_HI 0xF02200FF -+ -+/* INC_DEROT2 */ -+#define R367_OFDM_INC_DEROT2 0xF023 -+#define F367_OFDM_INC_DEROT_LO 0xF02300FF -+ -+/* PPM_CPAMP_DIR */ -+#define R367_OFDM_PPM_CPAMP_DIR 0xF024 -+#define F367_OFDM_PPM_CPAMP_DIRECT 0xF02400FF -+ -+/* PPM_CPAMP_INV */ -+#define R367_OFDM_PPM_CPAMP_INV 0xF025 -+#define F367_OFDM_PPM_CPAMP_INVER 0xF02500FF -+ -+/* FREESTFE_1 */ -+#define R367_OFDM_FREESTFE_1 0xF026 -+#define F367_OFDM_SYMBOL_NUMBER_INC 0xF02600C0 -+#define F367_OFDM_SEL_LSB 0xF0260004 -+#define F367_OFDM_AVERAGE_ON 0xF0260002 -+#define F367_OFDM_DC_ADJ 0xF0260001 -+ -+/* FREESTFE_2 */ -+#define R367_OFDM_FREESTFE_2 0xF027 -+#define F367_OFDM_SEL_SRCOUT 0xF02700C0 -+#define F367_OFDM_SEL_SYRTHR 0xF027001F -+ -+/* DCOFFSET */ -+#define R367_OFDM_DCOFFSET 0xF028 -+#define F367_OFDM_SELECT_I_Q 0xF0280080 -+#define F367_OFDM_DC_OFFSET 0xF028007F -+ -+/* EN_PROCESS */ -+#define R367_OFDM_EN_PROCESS 0xF029 -+#define F367_OFDM_FREE 0xF02900F0 -+#define F367_OFDM_ENAB_MANUAL 0xF0290001 -+ -+/* SDI_SMOOTHER */ -+#define R367_OFDM_SDI_SMOOTHER 0xF02A -+#define F367_OFDM_DIS_SMOOTH 0xF02A0080 -+#define F367_OFDM_SDI_INC_SMOOTHER 0xF02A007F -+ -+/* FE_LOOP_OPEN */ -+#define R367_OFDM_FE_LOOP_OPEN 0xF02B -+#define F367_OFDM_TRL_LOOP_OP 0xF02B0002 -+#define F367_OFDM_CRL_LOOP_OP 0xF02B0001 -+ -+/* FREQOFF1 */ -+#define R367_OFDM_FREQOFF1 0xF02C -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI 0xF02C00FF -+ -+/* FREQOFF2 */ -+#define R367_OFDM_FREQOFF2 0xF02D -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI 0xF02D00FF -+ -+/* FREQOFF3 */ -+#define R367_OFDM_FREQOFF3 0xF02E -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO 0xF02E00FF -+ -+/* TIMOFF1 */ -+#define R367_OFDM_TIMOFF1 0xF02F -+#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI 0xF02F00FF -+ -+/* TIMOFF2 */ -+#define R367_OFDM_TIMOFF2 0xF030 -+#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO 0xF03000FF -+ -+/* EPQ */ -+#define R367_OFDM_EPQ 0xF031 -+#define F367_OFDM_EPQ1 0xF03100FF -+ -+/* EPQAUTO */ -+#define R367_OFDM_EPQAUTO 0xF032 -+#define F367_OFDM_EPQ2 0xF03200FF -+ -+/* SYR_UPDATE */ -+#define R367_OFDM_SYR_UPDATE 0xF033 -+#define F367_OFDM_SYR_PROTV 0xF0330080 -+#define F367_OFDM_SYR_PROTV_GAIN 0xF0330060 -+#define F367_OFDM_SYR_FILTER 0xF0330010 -+#define F367_OFDM_SYR_TRACK_THRES 0xF033000C -+ -+/* CHPFREE */ -+#define R367_OFDM_CHPFREE 0xF034 -+#define F367_OFDM_CHP_FREE 0xF03400FF -+ -+/* PPM_STATE_MAC */ -+#define R367_OFDM_PPM_STATE_MAC 0xF035 -+#define F367_OFDM_PPM_STATE_MACHINE_DECODER 0xF035003F -+ -+/* INR_THRESHOLD */ -+#define R367_OFDM_INR_THRESHOLD 0xF036 -+#define F367_OFDM_INR_THRESH 0xF03600FF -+ -+/* EPQ_TPS_ID_CELL */ -+#define R367_OFDM_EPQ_TPS_ID_CELL 0xF037 -+#define F367_OFDM_ENABLE_LGTH_TO_CF 0xF0370080 -+#define F367_OFDM_DIS_TPS_RSVD 0xF0370040 -+#define F367_OFDM_DIS_BCH 0xF0370020 -+#define F367_OFDM_DIS_ID_CEL 0xF0370010 -+#define F367_OFDM_TPS_ADJUST_SYM 0xF037000F -+ -+/* EPQ_CFG */ -+#define R367_OFDM_EPQ_CFG 0xF038 -+#define F367_OFDM_EPQ_RANGE 0xF0380002 -+#define F367_OFDM_EPQ_SOFT 0xF0380001 -+ -+/* EPQ_STATUS */ -+#define R367_OFDM_EPQ_STATUS 0xF039 -+#define F367_OFDM_SLOPE_INC 0xF03900FC -+#define F367_OFDM_TPS_FIELD 0xF0390003 -+ -+/* AUTORELOCK */ -+#define R367_OFDM_AUTORELOCK 0xF03A -+#define F367_OFDM_BYPASS_BER_TEMPO 0xF03A0080 -+#define F367_OFDM_BER_TEMPO 0xF03A0070 -+#define F367_OFDM_BYPASS_COFDM_TEMPO 0xF03A0008 -+#define F367_OFDM_COFDM_TEMPO 0xF03A0007 -+ -+/* BER_THR_VMSB */ -+#define R367_OFDM_BER_THR_VMSB 0xF03B -+#define F367_OFDM_BER_THRESHOLD_HI 0xF03B00FF -+ -+/* BER_THR_MSB */ -+#define R367_OFDM_BER_THR_MSB 0xF03C -+#define F367_OFDM_BER_THRESHOLD_MID 0xF03C00FF -+ -+/* BER_THR_LSB */ -+#define R367_OFDM_BER_THR_LSB 0xF03D -+#define F367_OFDM_BER_THRESHOLD_LO 0xF03D00FF -+ -+/* CCD */ -+#define R367_OFDM_CCD 0xF03E -+#define F367_OFDM_CCD_DETECTED 0xF03E0080 -+#define F367_OFDM_CCD_RESET 0xF03E0040 -+#define F367_OFDM_CCD_THRESHOLD 0xF03E000F -+ -+/* SPECTR_CFG */ -+#define R367_OFDM_SPECTR_CFG 0xF03F -+#define F367_OFDM_SPECT_CFG 0xF03F0003 -+ -+/* CONSTMU_MSB */ -+#define R367_OFDM_CONSTMU_MSB 0xF040 -+#define F367_OFDM_CONSTMU_FREEZE 0xF0400080 -+#define F367_OFDM_CONSTNU_FORCE_EN 0xF0400040 -+#define F367_OFDM_CONST_MU_MSB 0xF040003F -+ -+/* CONSTMU_LSB */ -+#define R367_OFDM_CONSTMU_LSB 0xF041 -+#define F367_OFDM_CONST_MU_LSB 0xF04100FF -+ -+/* CONSTMU_MAX_MSB */ -+#define R367_OFDM_CONSTMU_MAX_MSB 0xF042 -+#define F367_OFDM_CONST_MU_MAX_MSB 0xF042003F -+ -+/* CONSTMU_MAX_LSB */ -+#define R367_OFDM_CONSTMU_MAX_LSB 0xF043 -+#define F367_OFDM_CONST_MU_MAX_LSB 0xF04300FF -+ -+/* ALPHANOISE */ -+#define R367_OFDM_ALPHANOISE 0xF044 -+#define F367_OFDM_USE_ALLFILTER 0xF0440080 -+#define F367_OFDM_INTER_ON 0xF0440040 -+#define F367_OFDM_ALPHA_NOISE 0xF044001F -+ -+/* MAXGP_MSB */ -+#define R367_OFDM_MAXGP_MSB 0xF045 -+#define F367_OFDM_MUFILTER_LENGTH 0xF04500F0 -+#define F367_OFDM_MAX_GP_MSB 0xF045000F -+ -+/* MAXGP_LSB */ -+#define R367_OFDM_MAXGP_LSB 0xF046 -+#define F367_OFDM_MAX_GP_LSB 0xF04600FF -+ -+/* ALPHAMSB */ -+#define R367_OFDM_ALPHAMSB 0xF047 -+#define F367_OFDM_CHC_DATARATE 0xF04700C0 -+#define F367_OFDM_ALPHA_MSB 0xF047003F -+ -+/* ALPHALSB */ -+#define R367_OFDM_ALPHALSB 0xF048 -+#define F367_OFDM_ALPHA_LSB 0xF04800FF -+ -+/* PILOT_ACCU */ -+#define R367_OFDM_PILOT_ACCU 0xF049 -+#define F367_OFDM_USE_SCAT4ADDAPT 0xF0490080 -+#define F367_OFDM_PILOT_ACC 0xF049001F -+ -+/* PILOTMU_ACCU */ -+#define R367_OFDM_PILOTMU_ACCU 0xF04A -+#define F367_OFDM_DISCARD_BAD_SP 0xF04A0080 -+#define F367_OFDM_DISCARD_BAD_CP 0xF04A0040 -+#define F367_OFDM_PILOT_MU_ACCU 0xF04A001F -+ -+/* FILT_CHANNEL_EST */ -+#define R367_OFDM_FILT_CHANNEL_EST 0xF04B -+#define F367_OFDM_USE_FILT_PILOT 0xF04B0080 -+#define F367_OFDM_FILT_CHANNEL 0xF04B007F -+ -+/* ALPHA_NOPISE_FREQ */ -+#define R367_OFDM_ALPHA_NOPISE_FREQ 0xF04C -+#define F367_OFDM_NOISE_FREQ_FILT 0xF04C0040 -+#define F367_OFDM_ALPHA_NOISE_FREQ 0xF04C003F -+ -+/* RATIO_PILOT */ -+#define R367_OFDM_RATIO_PILOT 0xF04D -+#define F367_OFDM_RATIO_MEAN_SP 0xF04D00F0 -+#define F367_OFDM_RATIO_MEAN_CP 0xF04D000F -+ -+/* CHC_CTL */ -+#define R367_OFDM_CHC_CTL 0xF04E -+#define F367_OFDM_TRACK_EN 0xF04E0080 -+#define F367_OFDM_NOISE_NORM_EN 0xF04E0040 -+#define F367_OFDM_FORCE_CHC_RESET 0xF04E0020 -+#define F367_OFDM_SHORT_TIME 0xF04E0010 -+#define F367_OFDM_FORCE_STATE_EN 0xF04E0008 -+#define F367_OFDM_FORCE_STATE 0xF04E0007 -+ -+/* EPQ_ADJUST */ -+#define R367_OFDM_EPQ_ADJUST 0xF04F -+#define F367_OFDM_ADJUST_SCAT_IND 0xF04F00C0 -+#define F367_OFDM_ONE_SYMBOL 0xF04F0010 -+#define F367_OFDM_EPQ_DECAY 0xF04F000E -+#define F367_OFDM_HOLD_SLOPE 0xF04F0001 -+ -+/* EPQ_THRES */ -+#define R367_OFDM_EPQ_THRES 0xF050 -+#define F367_OFDM_EPQ_THR 0xF05000FF -+ -+/* OMEGA_CTL */ -+#define R367_OFDM_OMEGA_CTL 0xF051 -+#define F367_OFDM_OMEGA_RST 0xF0510080 -+#define F367_OFDM_FREEZE_OMEGA 0xF0510040 -+#define F367_OFDM_OMEGA_SEL 0xF051003F -+ -+/* GP_CTL */ -+#define R367_OFDM_GP_CTL 0xF052 -+#define F367_OFDM_CHC_STATE 0xF05200E0 -+#define F367_OFDM_FREEZE_GP 0xF0520010 -+#define F367_OFDM_GP_SEL 0xF052000F -+ -+/* MUMSB */ -+#define R367_OFDM_MUMSB 0xF053 -+#define F367_OFDM_MU_MSB 0xF053007F -+ -+/* MULSB */ -+#define R367_OFDM_MULSB 0xF054 -+#define F367_OFDM_MU_LSB 0xF05400FF -+ -+/* GPMSB */ -+#define R367_OFDM_GPMSB 0xF055 -+#define F367_OFDM_CSI_THRESHOLD 0xF05500E0 -+#define F367_OFDM_GP_MSB 0xF055000F -+ -+/* GPLSB */ -+#define R367_OFDM_GPLSB 0xF056 -+#define F367_OFDM_GP_LSB 0xF05600FF -+ -+/* OMEGAMSB */ -+#define R367_OFDM_OMEGAMSB 0xF057 -+#define F367_OFDM_OMEGA_MSB 0xF057007F -+ -+/* OMEGALSB */ -+#define R367_OFDM_OMEGALSB 0xF058 -+#define F367_OFDM_OMEGA_LSB 0xF05800FF -+ -+/* SCAT_NB */ -+#define R367_OFDM_SCAT_NB 0xF059 -+#define F367_OFDM_CHC_TEST 0xF05900F8 -+#define F367_OFDM_SCAT_NUMB 0xF0590003 -+ -+/* CHC_DUMMY */ -+#define R367_OFDM_CHC_DUMMY 0xF05A -+#define F367_OFDM_CHC_DUM 0xF05A00FF -+ -+/* INC_CTL */ -+#define R367_OFDM_INC_CTL 0xF05B -+#define F367_OFDM_INC_BYPASS 0xF05B0080 -+#define F367_OFDM_INC_NDEPTH 0xF05B000C -+#define F367_OFDM_INC_MADEPTH 0xF05B0003 -+ -+/* INCTHRES_COR1 */ -+#define R367_OFDM_INCTHRES_COR1 0xF05C -+#define F367_OFDM_INC_THRES_COR1 0xF05C00FF -+ -+/* INCTHRES_COR2 */ -+#define R367_OFDM_INCTHRES_COR2 0xF05D -+#define F367_OFDM_INC_THRES_COR2 0xF05D00FF -+ -+/* INCTHRES_DET1 */ -+#define R367_OFDM_INCTHRES_DET1 0xF05E -+#define F367_OFDM_INC_THRES_DET1 0xF05E003F -+ -+/* INCTHRES_DET2 */ -+#define R367_OFDM_INCTHRES_DET2 0xF05F -+#define F367_OFDM_INC_THRES_DET2 0xF05F003F -+ -+/* IIR_CELLNB */ -+#define R367_OFDM_IIR_CELLNB 0xF060 -+#define F367_OFDM_NRST_IIR 0xF0600080 -+#define F367_OFDM_IIR_CELL_NB 0xF0600007 -+ -+/* IIRCX_COEFF1_MSB */ -+#define R367_OFDM_IIRCX_COEFF1_MSB 0xF061 -+#define F367_OFDM_IIR_CX_COEFF1_MSB 0xF06100FF -+ -+/* IIRCX_COEFF1_LSB */ -+#define R367_OFDM_IIRCX_COEFF1_LSB 0xF062 -+#define F367_OFDM_IIR_CX_COEFF1_LSB 0xF06200FF -+ -+/* IIRCX_COEFF2_MSB */ -+#define R367_OFDM_IIRCX_COEFF2_MSB 0xF063 -+#define F367_OFDM_IIR_CX_COEFF2_MSB 0xF06300FF -+ -+/* IIRCX_COEFF2_LSB */ -+#define R367_OFDM_IIRCX_COEFF2_LSB 0xF064 -+#define F367_OFDM_IIR_CX_COEFF2_LSB 0xF06400FF -+ -+/* IIRCX_COEFF3_MSB */ -+#define R367_OFDM_IIRCX_COEFF3_MSB 0xF065 -+#define F367_OFDM_IIR_CX_COEFF3_MSB 0xF06500FF -+ -+/* IIRCX_COEFF3_LSB */ -+#define R367_OFDM_IIRCX_COEFF3_LSB 0xF066 -+#define F367_OFDM_IIR_CX_COEFF3_LSB 0xF06600FF -+ -+/* IIRCX_COEFF4_MSB */ -+#define R367_OFDM_IIRCX_COEFF4_MSB 0xF067 -+#define F367_OFDM_IIR_CX_COEFF4_MSB 0xF06700FF -+ -+/* IIRCX_COEFF4_LSB */ -+#define R367_OFDM_IIRCX_COEFF4_LSB 0xF068 -+#define F367_OFDM_IIR_CX_COEFF4_LSB 0xF06800FF -+ -+/* IIRCX_COEFF5_MSB */ -+#define R367_OFDM_IIRCX_COEFF5_MSB 0xF069 -+#define F367_OFDM_IIR_CX_COEFF5_MSB 0xF06900FF -+ -+/* IIRCX_COEFF5_LSB */ -+#define R367_OFDM_IIRCX_COEFF5_LSB 0xF06A -+#define F367_OFDM_IIR_CX_COEFF5_LSB 0xF06A00FF -+ -+/* FEPATH_CFG */ -+#define R367_OFDM_FEPATH_CFG 0xF06B -+#define F367_OFDM_DEMUX_SWAP 0xF06B0004 -+#define F367_OFDM_DIGAGC_SWAP 0xF06B0002 -+#define F367_OFDM_LONGPATH_IF 0xF06B0001 -+ -+/* PMC1_FUNC */ -+#define R367_OFDM_PMC1_FUNC 0xF06C -+#define F367_OFDM_SOFT_RSTN 0xF06C0080 -+#define F367_OFDM_PMC1_AVERAGE_TIME 0xF06C0078 -+#define F367_OFDM_PMC1_WAIT_TIME 0xF06C0006 -+#define F367_OFDM_PMC1_2N_SEL 0xF06C0001 -+ -+/* PMC1_FOR */ -+#define R367_OFDM_PMC1_FOR 0xF06D -+#define F367_OFDM_PMC1_FORCE 0xF06D0080 -+#define F367_OFDM_PMC1_FORCE_VALUE 0xF06D007C -+ -+/* PMC2_FUNC */ -+#define R367_OFDM_PMC2_FUNC 0xF06E -+#define F367_OFDM_PMC2_SOFT_STN 0xF06E0080 -+#define F367_OFDM_PMC2_ACCU_TIME 0xF06E0070 -+#define F367_OFDM_PMC2_CMDP_MN 0xF06E0008 -+#define F367_OFDM_PMC2_SWAP 0xF06E0004 -+ -+/* STATUS_ERR_DA */ -+#define R367_OFDM_STATUS_ERR_DA 0xF06F -+#define F367_OFDM_COM_USEGAINTRK 0xF06F0080 -+#define F367_OFDM_COM_AGCLOCK 0xF06F0040 -+#define F367_OFDM_AUT_AGCLOCK 0xF06F0020 -+#define F367_OFDM_MIN_ERR_X_LSB 0xF06F000F -+ -+/* DIG_AGC_R */ -+#define R367_OFDM_DIG_AGC_R 0xF070 -+#define F367_OFDM_COM_SOFT_RSTN 0xF0700080 -+#define F367_OFDM_COM_AGC_ON 0xF0700040 -+#define F367_OFDM_COM_EARLY 0xF0700020 -+#define F367_OFDM_AUT_SOFT_RESETN 0xF0700010 -+#define F367_OFDM_AUT_AGC_ON 0xF0700008 -+#define F367_OFDM_AUT_EARLY 0xF0700004 -+#define F367_OFDM_AUT_ROT_EN 0xF0700002 -+#define F367_OFDM_LOCK_SOFT_RESETN 0xF0700001 -+ -+/* COMAGC_TARMSB */ -+#define R367_OFDM_COMAGC_TARMSB 0xF071 -+#define F367_OFDM_COM_AGC_TARGET_MSB 0xF07100FF -+ -+/* COM_AGC_TAR_ENMODE */ -+#define R367_OFDM_COM_AGC_TAR_ENMODE 0xF072 -+#define F367_OFDM_COM_AGC_TARGET_LSB 0xF07200F0 -+#define F367_OFDM_COM_ENMODE 0xF072000F -+ -+/* COM_AGC_CFG */ -+#define R367_OFDM_COM_AGC_CFG 0xF073 -+#define F367_OFDM_COM_N 0xF07300F8 -+#define F367_OFDM_COM_STABMODE 0xF0730006 -+#define F367_OFDM_ERR_SEL 0xF0730001 -+ -+/* COM_AGC_GAIN1 */ -+#define R367_OFDM_COM_AGC_GAIN1 0xF074 -+#define F367_OFDM_COM_GAIN1ACK 0xF07400F0 -+#define F367_OFDM_COM_GAIN1TRK 0xF074000F -+ -+/* AUT_AGC_TARGETMSB */ -+#define R367_OFDM_AUT_AGC_TARGETMSB 0xF075 -+#define F367_OFDM_AUT_AGC_TARGET_MSB 0xF07500FF -+ -+/* LOCK_DET_MSB */ -+#define R367_OFDM_LOCK_DET_MSB 0xF076 -+#define F367_OFDM_LOCK_DETECT_MSB 0xF07600FF -+ -+/* AGCTAR_LOCK_LSBS */ -+#define R367_OFDM_AGCTAR_LOCK_LSBS 0xF077 -+#define F367_OFDM_AUT_AGC_TARGET_LSB 0xF07700F0 -+#define F367_OFDM_LOCK_DETECT_LSB 0xF077000F -+ -+/* AUT_GAIN_EN */ -+#define R367_OFDM_AUT_GAIN_EN 0xF078 -+#define F367_OFDM_AUT_ENMODE 0xF07800F0 -+#define F367_OFDM_AUT_GAIN2 0xF078000F -+ -+/* AUT_CFG */ -+#define R367_OFDM_AUT_CFG 0xF079 -+#define F367_OFDM_AUT_N 0xF07900F8 -+#define F367_OFDM_INT_CHOICE 0xF0790006 -+#define F367_OFDM_INT_LOAD 0xF0790001 -+ -+/* LOCKN */ -+#define R367_OFDM_LOCKN 0xF07A -+#define F367_OFDM_LOCK_N 0xF07A00F8 -+#define F367_OFDM_SEL_IQNTAR 0xF07A0004 -+#define F367_OFDM_LOCK_DETECT_CHOICE 0xF07A0003 -+ -+/* INT_X_3 */ -+#define R367_OFDM_INT_X_3 0xF07B -+#define F367_OFDM_INT_X3 0xF07B00FF -+ -+/* INT_X_2 */ -+#define R367_OFDM_INT_X_2 0xF07C -+#define F367_OFDM_INT_X2 0xF07C00FF -+ -+/* INT_X_1 */ -+#define R367_OFDM_INT_X_1 0xF07D -+#define F367_OFDM_INT_X1 0xF07D00FF -+ -+/* INT_X_0 */ -+#define R367_OFDM_INT_X_0 0xF07E -+#define F367_OFDM_INT_X0 0xF07E00FF -+ -+/* MIN_ERRX_MSB */ -+#define R367_OFDM_MIN_ERRX_MSB 0xF07F -+#define F367_OFDM_MIN_ERR_X_MSB 0xF07F00FF -+ -+/* COR_CTL */ -+#define R367_OFDM_COR_CTL 0xF080 -+#define F367_OFDM_CORE_ACTIVE 0xF0800020 -+#define F367_OFDM_HOLD 0xF0800010 -+#define F367_OFDM_CORE_STATE_CTL 0xF080000F -+ -+/* COR_STAT */ -+#define R367_OFDM_COR_STAT 0xF081 -+#define F367_OFDM_SCATT_LOCKED 0xF0810080 -+#define F367_OFDM_TPS_LOCKED 0xF0810040 -+#define F367_OFDM_SYR_LOCKED_COR 0xF0810020 -+#define F367_OFDM_AGC_LOCKED_STAT 0xF0810010 -+#define F367_OFDM_CORE_STATE_STAT 0xF081000F -+ -+/* COR_INTEN */ -+#define R367_OFDM_COR_INTEN 0xF082 -+#define F367_OFDM_INTEN 0xF0820080 -+#define F367_OFDM_INTEN_SYR 0xF0820020 -+#define F367_OFDM_INTEN_FFT 0xF0820010 -+#define F367_OFDM_INTEN_AGC 0xF0820008 -+#define F367_OFDM_INTEN_TPS1 0xF0820004 -+#define F367_OFDM_INTEN_TPS2 0xF0820002 -+#define F367_OFDM_INTEN_TPS3 0xF0820001 -+ -+/* COR_INTSTAT */ -+#define R367_OFDM_COR_INTSTAT 0xF083 -+#define F367_OFDM_INTSTAT_SYR 0xF0830020 -+#define F367_OFDM_INTSTAT_FFT 0xF0830010 -+#define F367_OFDM_INTSAT_AGC 0xF0830008 -+#define F367_OFDM_INTSTAT_TPS1 0xF0830004 -+#define F367_OFDM_INTSTAT_TPS2 0xF0830002 -+#define F367_OFDM_INTSTAT_TPS3 0xF0830001 -+ -+/* COR_MODEGUARD */ -+#define R367_OFDM_COR_MODEGUARD 0xF084 -+#define F367_OFDM_FORCE 0xF0840010 -+#define F367_OFDM_MODE 0xF084000C -+#define F367_OFDM_GUARD 0xF0840003 -+ -+/* AGC_CTL */ -+#define R367_OFDM_AGC_CTL 0xF085 -+#define F367_OFDM_AGC_TIMING_FACTOR 0xF08500E0 -+#define F367_OFDM_AGC_LAST 0xF0850010 -+#define F367_OFDM_AGC_GAIN 0xF085000C -+#define F367_OFDM_AGC_NEG 0xF0850002 -+#define F367_OFDM_AGC_SET 0xF0850001 -+ -+/* AGC_MANUAL1 */ -+#define R367_OFDM_AGC_MANUAL1 0xF086 -+#define F367_OFDM_AGC_VAL_LO 0xF08600FF -+ -+/* AGC_MANUAL2 */ -+#define R367_OFDM_AGC_MANUAL2 0xF087 -+#define F367_OFDM_AGC_VAL_HI 0xF087000F -+ -+/* AGC_TARG */ -+#define R367_OFDM_AGC_TARG 0xF088 -+#define F367_OFDM_AGC_TARGET 0xF08800FF -+ -+/* AGC_GAIN1 */ -+#define R367_OFDM_AGC_GAIN1 0xF089 -+#define F367_OFDM_AGC_GAIN_LO 0xF08900FF -+ -+/* AGC_GAIN2 */ -+#define R367_OFDM_AGC_GAIN2 0xF08A -+#define F367_OFDM_AGC_LOCKED_GAIN2 0xF08A0010 -+#define F367_OFDM_AGC_GAIN_HI 0xF08A000F -+ -+/* RESERVED_1 */ -+#define R367_OFDM_RESERVED_1 0xF08B -+#define F367_OFDM_RESERVED1 0xF08B00FF -+ -+/* RESERVED_2 */ -+#define R367_OFDM_RESERVED_2 0xF08C -+#define F367_OFDM_RESERVED2 0xF08C00FF -+ -+/* RESERVED_3 */ -+#define R367_OFDM_RESERVED_3 0xF08D -+#define F367_OFDM_RESERVED3 0xF08D00FF -+ -+/* CAS_CTL */ -+#define R367_OFDM_CAS_CTL 0xF08E -+#define F367_OFDM_CCS_ENABLE 0xF08E0080 -+#define F367_OFDM_ACS_DISABLE 0xF08E0040 -+#define F367_OFDM_DAGC_DIS 0xF08E0020 -+#define F367_OFDM_DAGC_GAIN 0xF08E0018 -+#define F367_OFDM_CCSMU 0xF08E0007 -+ -+/* CAS_FREQ */ -+#define R367_OFDM_CAS_FREQ 0xF08F -+#define F367_OFDM_CCS_FREQ 0xF08F00FF -+ -+/* CAS_DAGCGAIN */ -+#define R367_OFDM_CAS_DAGCGAIN 0xF090 -+#define F367_OFDM_CAS_DAGC_GAIN 0xF09000FF -+ -+/* SYR_CTL */ -+#define R367_OFDM_SYR_CTL 0xF091 -+#define F367_OFDM_SICTH_ENABLE 0xF0910080 -+#define F367_OFDM_LONG_ECHO 0xF0910078 -+#define F367_OFDM_AUTO_LE_EN 0xF0910004 -+#define F367_OFDM_SYR_BYPASS 0xF0910002 -+#define F367_OFDM_SYR_TR_DIS 0xF0910001 -+ -+/* SYR_STAT */ -+#define R367_OFDM_SYR_STAT 0xF092 -+#define F367_OFDM_SYR_LOCKED_STAT 0xF0920010 -+#define F367_OFDM_SYR_MODE 0xF092000C -+#define F367_OFDM_SYR_GUARD 0xF0920003 -+ -+/* SYR_NCO1 */ -+#define R367_OFDM_SYR_NCO1 0xF093 -+#define F367_OFDM_SYR_NCO_LO 0xF09300FF -+ -+/* SYR_NCO2 */ -+#define R367_OFDM_SYR_NCO2 0xF094 -+#define F367_OFDM_SYR_NCO_HI 0xF094003F -+ -+/* SYR_OFFSET1 */ -+#define R367_OFDM_SYR_OFFSET1 0xF095 -+#define F367_OFDM_SYR_OFFSET_LO 0xF09500FF -+ -+/* SYR_OFFSET2 */ -+#define R367_OFDM_SYR_OFFSET2 0xF096 -+#define F367_OFDM_SYR_OFFSET_HI 0xF096003F -+ -+/* FFT_CTL */ -+#define R367_OFDM_FFT_CTL 0xF097 -+#define F367_OFDM_SHIFT_FFT_TRIG 0xF0970018 -+#define F367_OFDM_FFT_TRIGGER 0xF0970004 -+#define F367_OFDM_FFT_MANUAL 0xF0970002 -+#define F367_OFDM_IFFT_MODE 0xF0970001 -+ -+/* SCR_CTL */ -+#define R367_OFDM_SCR_CTL 0xF098 -+#define F367_OFDM_SYRADJDECAY 0xF0980070 -+#define F367_OFDM_SCR_CPEDIS 0xF0980002 -+#define F367_OFDM_SCR_DIS 0xF0980001 -+ -+/* PPM_CTL1 */ -+#define R367_OFDM_PPM_CTL1 0xF099 -+#define F367_OFDM_PPM_MAXFREQ 0xF0990030 -+#define F367_OFDM_PPM_MAXTIM 0xF0990008 -+#define F367_OFDM_PPM_INVSEL 0xF0990004 -+#define F367_OFDM_PPM_SCATDIS 0xF0990002 -+#define F367_OFDM_PPM_BYP 0xF0990001 -+ -+/* TRL_CTL */ -+#define R367_OFDM_TRL_CTL 0xF09A -+#define F367_OFDM_TRL_NOMRATE_LSB 0xF09A0080 -+#define F367_OFDM_TRL_GAIN_FACTOR 0xF09A0078 -+#define F367_OFDM_TRL_LOOPGAIN 0xF09A0007 -+ -+/* TRL_NOMRATE1 */ -+#define R367_OFDM_TRL_NOMRATE1 0xF09B -+#define F367_OFDM_TRL_NOMRATE_LO 0xF09B00FF -+ -+/* TRL_NOMRATE2 */ -+#define R367_OFDM_TRL_NOMRATE2 0xF09C -+#define F367_OFDM_TRL_NOMRATE_HI 0xF09C00FF -+ -+/* TRL_TIME1 */ -+#define R367_OFDM_TRL_TIME1 0xF09D -+#define F367_OFDM_TRL_TOFFSET_LO 0xF09D00FF -+ -+/* TRL_TIME2 */ -+#define R367_OFDM_TRL_TIME2 0xF09E -+#define F367_OFDM_TRL_TOFFSET_HI 0xF09E00FF -+ -+/* CRL_CTL */ -+#define R367_OFDM_CRL_CTL 0xF09F -+#define F367_OFDM_CRL_DIS 0xF09F0080 -+#define F367_OFDM_CRL_GAIN_FACTOR 0xF09F0078 -+#define F367_OFDM_CRL_LOOPGAIN 0xF09F0007 -+ -+/* CRL_FREQ1 */ -+#define R367_OFDM_CRL_FREQ1 0xF0A0 -+#define F367_OFDM_CRL_FOFFSET_LO 0xF0A000FF -+ -+/* CRL_FREQ2 */ -+#define R367_OFDM_CRL_FREQ2 0xF0A1 -+#define F367_OFDM_CRL_FOFFSET_HI 0xF0A100FF -+ -+/* CRL_FREQ3 */ -+#define R367_OFDM_CRL_FREQ3 0xF0A2 -+#define F367_OFDM_CRL_FOFFSET_VHI 0xF0A200FF -+ -+/* TPS_SFRAME_CTL */ -+#define R367_OFDM_TPS_SFRAME_CTL 0xF0A3 -+#define F367_OFDM_TPS_SFRAME_SYNC 0xF0A30001 -+ -+/* CHC_SNR */ -+#define R367_OFDM_CHC_SNR 0xF0A4 -+#define F367_OFDM_CHCSNR 0xF0A400FF -+ -+/* BDI_CTL */ -+#define R367_OFDM_BDI_CTL 0xF0A5 -+#define F367_OFDM_BDI_LPSEL 0xF0A50002 -+#define F367_OFDM_BDI_SERIAL 0xF0A50001 -+ -+/* DMP_CTL */ -+#define R367_OFDM_DMP_CTL 0xF0A6 -+#define F367_OFDM_DMP_SCALING_FACTOR 0xF0A6001E -+#define F367_OFDM_DMP_SDDIS 0xF0A60001 -+ -+/* TPS_RCVD1 */ -+#define R367_OFDM_TPS_RCVD1 0xF0A7 -+#define F367_OFDM_TPS_CHANGE 0xF0A70040 -+#define F367_OFDM_BCH_OK 0xF0A70020 -+#define F367_OFDM_TPS_SYNC 0xF0A70010 -+#define F367_OFDM_TPS_FRAME 0xF0A70003 -+ -+/* TPS_RCVD2 */ -+#define R367_OFDM_TPS_RCVD2 0xF0A8 -+#define F367_OFDM_TPS_HIERMODE 0xF0A80070 -+#define F367_OFDM_TPS_CONST 0xF0A80003 -+ -+/* TPS_RCVD3 */ -+#define R367_OFDM_TPS_RCVD3 0xF0A9 -+#define F367_OFDM_TPS_LPCODE 0xF0A90070 -+#define F367_OFDM_TPS_HPCODE 0xF0A90007 -+ -+/* TPS_RCVD4 */ -+#define R367_OFDM_TPS_RCVD4 0xF0AA -+#define F367_OFDM_TPS_GUARD 0xF0AA0030 -+#define F367_OFDM_TPS_MODE 0xF0AA0003 -+ -+/* TPS_ID_CELL1 */ -+#define R367_OFDM_TPS_ID_CELL1 0xF0AB -+#define F367_OFDM_TPS_ID_CELL_LO 0xF0AB00FF -+ -+/* TPS_ID_CELL2 */ -+#define R367_OFDM_TPS_ID_CELL2 0xF0AC -+#define F367_OFDM_TPS_ID_CELL_HI 0xF0AC00FF -+ -+/* TPS_RCVD5_SET1 */ -+#define R367_OFDM_TPS_RCVD5_SET1 0xF0AD -+#define F367_OFDM_TPS_NA 0xF0AD00FC -+#define F367_OFDM_TPS_SETFRAME 0xF0AD0003 -+ -+/* TPS_SET2 */ -+#define R367_OFDM_TPS_SET2 0xF0AE -+#define F367_OFDM_TPS_SETHIERMODE 0xF0AE0070 -+#define F367_OFDM_TPS_SETCONST 0xF0AE0003 -+ -+/* TPS_SET3 */ -+#define R367_OFDM_TPS_SET3 0xF0AF -+#define F367_OFDM_TPS_SETLPCODE 0xF0AF0070 -+#define F367_OFDM_TPS_SETHPCODE 0xF0AF0007 -+ -+/* TPS_CTL */ -+#define R367_OFDM_TPS_CTL 0xF0B0 -+#define F367_OFDM_TPS_IMM 0xF0B00004 -+#define F367_OFDM_TPS_BCHDIS 0xF0B00002 -+#define F367_OFDM_TPS_UPDDIS 0xF0B00001 -+ -+/* CTL_FFTOSNUM */ -+#define R367_OFDM_CTL_FFTOSNUM 0xF0B1 -+#define F367_OFDM_SYMBOL_NUMBER 0xF0B1007F -+ -+/* TESTSELECT */ -+#define R367_OFDM_TESTSELECT 0xF0B2 -+#define F367_OFDM_TEST_SELECT 0xF0B2001F -+ -+/* MSC_REV */ -+#define R367_OFDM_MSC_REV 0xF0B3 -+#define F367_OFDM_REV_NUMBER 0xF0B300FF -+ -+/* PIR_CTL */ -+#define R367_OFDM_PIR_CTL 0xF0B4 -+#define F367_OFDM_FREEZE 0xF0B40001 -+ -+/* SNR_CARRIER1 */ -+#define R367_OFDM_SNR_CARRIER1 0xF0B5 -+#define F367_OFDM_SNR_CARRIER_LO 0xF0B500FF -+ -+/* SNR_CARRIER2 */ -+#define R367_OFDM_SNR_CARRIER2 0xF0B6 -+#define F367_OFDM_MEAN 0xF0B600C0 -+#define F367_OFDM_SNR_CARRIER_HI 0xF0B6001F -+ -+/* PPM_CPAMP */ -+#define R367_OFDM_PPM_CPAMP 0xF0B7 -+#define F367_OFDM_PPM_CPC 0xF0B700FF -+ -+/* TSM_AP0 */ -+#define R367_OFDM_TSM_AP0 0xF0B8 -+#define F367_OFDM_ADDRESS_BYTE_0 0xF0B800FF -+ -+/* TSM_AP1 */ -+#define R367_OFDM_TSM_AP1 0xF0B9 -+#define F367_OFDM_ADDRESS_BYTE_1 0xF0B900FF -+ -+/* TSM_AP2 */ -+#define R367_OFDM_TSM_AP2 0xF0BA -+#define F367_OFDM_DATA_BYTE_0 0xF0BA00FF -+ -+/* TSM_AP3 */ -+#define R367_OFDM_TSM_AP3 0xF0BB -+#define F367_OFDM_DATA_BYTE_1 0xF0BB00FF -+ -+/* TSM_AP4 */ -+#define R367_OFDM_TSM_AP4 0xF0BC -+#define F367_OFDM_DATA_BYTE_2 0xF0BC00FF -+ -+/* TSM_AP5 */ -+#define R367_OFDM_TSM_AP5 0xF0BD -+#define F367_OFDM_DATA_BYTE_3 0xF0BD00FF -+ -+/* TSM_AP6 */ -+#define R367_OFDM_TSM_AP6 0xF0BE -+#define F367_OFDM_TSM_AP_6 0xF0BE00FF -+ -+/* TSM_AP7 */ -+#define R367_OFDM_TSM_AP7 0xF0BF -+#define F367_OFDM_MEM_SELECT_BYTE 0xF0BF00FF -+ -+/* TSTRES */ -+#define R367_TSTRES 0xF0C0 -+#define F367_FRES_DISPLAY 0xF0C00080 -+#define F367_FRES_FIFO_AD 0xF0C00020 -+#define F367_FRESRS 0xF0C00010 -+#define F367_FRESACS 0xF0C00008 -+#define F367_FRESFEC 0xF0C00004 -+#define F367_FRES_PRIF 0xF0C00002 -+#define F367_FRESCORE 0xF0C00001 -+ -+/* ANACTRL */ -+#define R367_ANACTRL 0xF0C1 -+#define F367_BYPASS_XTAL 0xF0C10040 -+#define F367_BYPASS_PLLXN 0xF0C1000C -+#define F367_DIS_PAD_OSC 0xF0C10002 -+#define F367_STDBY_PLLXN 0xF0C10001 -+ -+/* TSTBUS */ -+#define R367_TSTBUS 0xF0C2 -+#define F367_TS_BYTE_CLK_INV 0xF0C20080 -+#define F367_CFG_IP 0xF0C20070 -+#define F367_CFG_TST 0xF0C2000F -+ -+/* TSTRATE */ -+#define R367_TSTRATE 0xF0C6 -+#define F367_FORCEPHA 0xF0C60080 -+#define F367_FNEWPHA 0xF0C60010 -+#define F367_FROT90 0xF0C60008 -+#define F367_FR 0xF0C60007 -+ -+/* CONSTMODE */ -+#define R367_OFDM_CONSTMODE 0xF0CB -+#define F367_OFDM_TST_PRIF 0xF0CB00E0 -+#define F367_OFDM_CAR_TYPE 0xF0CB0018 -+#define F367_OFDM_CONST_MODE 0xF0CB0003 -+ -+/* CONSTCARR1 */ -+#define R367_OFDM_CONSTCARR1 0xF0CC -+#define F367_OFDM_CONST_CARR_LO 0xF0CC00FF -+ -+/* CONSTCARR2 */ -+#define R367_OFDM_CONSTCARR2 0xF0CD -+#define F367_OFDM_CONST_CARR_HI 0xF0CD001F -+ -+/* ICONSTEL */ -+#define R367_OFDM_ICONSTEL 0xF0CE -+#define F367_OFDM_PICONSTEL 0xF0CE00FF -+ -+/* QCONSTEL */ -+#define R367_OFDM_QCONSTEL 0xF0CF -+#define F367_OFDM_PQCONSTEL 0xF0CF00FF -+ -+/* TSTBISTRES0 */ -+#define R367_OFDM_TSTBISTRES0 0xF0D0 -+#define F367_OFDM_BEND_PPM 0xF0D00080 -+#define F367_OFDM_BBAD_PPM 0xF0D00040 -+#define F367_OFDM_BEND_FFTW 0xF0D00020 -+#define F367_OFDM_BBAD_FFTW 0xF0D00010 -+#define F367_OFDM_BEND_FFT_BUF 0xF0D00008 -+#define F367_OFDM_BBAD_FFT_BUF 0xF0D00004 -+#define F367_OFDM_BEND_SYR 0xF0D00002 -+#define F367_OFDM_BBAD_SYR 0xF0D00001 -+ -+/* TSTBISTRES1 */ -+#define R367_OFDM_TSTBISTRES1 0xF0D1 -+#define F367_OFDM_BEND_CHC_CP 0xF0D10080 -+#define F367_OFDM_BBAD_CHC_CP 0xF0D10040 -+#define F367_OFDM_BEND_CHCI 0xF0D10020 -+#define F367_OFDM_BBAD_CHCI 0xF0D10010 -+#define F367_OFDM_BEND_BDI 0xF0D10008 -+#define F367_OFDM_BBAD_BDI 0xF0D10004 -+#define F367_OFDM_BEND_SDI 0xF0D10002 -+#define F367_OFDM_BBAD_SDI 0xF0D10001 -+ -+/* TSTBISTRES2 */ -+#define R367_OFDM_TSTBISTRES2 0xF0D2 -+#define F367_OFDM_BEND_CHC_INC 0xF0D20080 -+#define F367_OFDM_BBAD_CHC_INC 0xF0D20040 -+#define F367_OFDM_BEND_CHC_SPP 0xF0D20020 -+#define F367_OFDM_BBAD_CHC_SPP 0xF0D20010 -+#define F367_OFDM_BEND_CHC_CPP 0xF0D20008 -+#define F367_OFDM_BBAD_CHC_CPP 0xF0D20004 -+#define F367_OFDM_BEND_CHC_SP 0xF0D20002 -+#define F367_OFDM_BBAD_CHC_SP 0xF0D20001 -+ -+/* TSTBISTRES3 */ -+#define R367_OFDM_TSTBISTRES3 0xF0D3 -+#define F367_OFDM_BEND_QAM 0xF0D30080 -+#define F367_OFDM_BBAD_QAM 0xF0D30040 -+#define F367_OFDM_BEND_SFEC_VIT 0xF0D30020 -+#define F367_OFDM_BBAD_SFEC_VIT 0xF0D30010 -+#define F367_OFDM_BEND_SFEC_DLINE 0xF0D30008 -+#define F367_OFDM_BBAD_SFEC_DLINE 0xF0D30004 -+#define F367_OFDM_BEND_SFEC_HW 0xF0D30002 -+#define F367_OFDM_BBAD_SFEC_HW 0xF0D30001 -+ -+/* RF_AGC1 */ -+#define R367_RF_AGC1 0xF0D4 -+#define F367_RF_AGC1_LEVEL_HI 0xF0D400FF -+ -+/* RF_AGC2 */ -+#define R367_RF_AGC2 0xF0D5 -+#define F367_REF_ADGP 0xF0D50080 -+#define F367_STDBY_ADCGP 0xF0D50020 -+#define F367_CHANNEL_SEL 0xF0D5001C -+#define F367_RF_AGC1_LEVEL_LO 0xF0D50003 -+ -+/* ANADIGCTRL */ -+#define R367_ANADIGCTRL 0xF0D7 -+#define F367_SEL_CLKDEM 0xF0D70020 -+#define F367_EN_BUFFER_Q 0xF0D70010 -+#define F367_EN_BUFFER_I 0xF0D70008 -+#define F367_ADC_RIS_EGDE 0xF0D70004 -+#define F367_SGN_ADC 0xF0D70002 -+#define F367_SEL_AD12_SYNC 0xF0D70001 -+ -+/* PLLMDIV */ -+#define R367_PLLMDIV 0xF0D8 -+#define F367_PLL_MDIV 0xF0D800FF -+ -+/* PLLNDIV */ -+#define R367_PLLNDIV 0xF0D9 -+#define F367_PLL_NDIV 0xF0D900FF -+ -+/* PLLSETUP */ -+#define R367_PLLSETUP 0xF0DA -+#define F367_PLL_PDIV 0xF0DA0070 -+#define F367_PLL_KDIV 0xF0DA000F -+ -+/* DUAL_AD12 */ -+#define R367_DUAL_AD12 0xF0DB -+#define F367_FS20M 0xF0DB0020 -+#define F367_FS50M 0xF0DB0010 -+#define F367_INMODE0 0xF0DB0008 -+#define F367_POFFQ 0xF0DB0004 -+#define F367_POFFI 0xF0DB0002 -+#define F367_INMODE1 0xF0DB0001 -+ -+/* TSTBIST */ -+#define R367_TSTBIST 0xF0DC -+#define F367_TST_BYP_CLK 0xF0DC0080 -+#define F367_TST_GCLKENA_STD 0xF0DC0040 -+#define F367_TST_GCLKENA 0xF0DC0020 -+#define F367_TST_MEMBIST 0xF0DC001F -+ -+/* PAD_COMP_CTRL */ -+#define R367_PAD_COMP_CTRL 0xF0DD -+#define F367_COMPTQ 0xF0DD0010 -+#define F367_COMPEN 0xF0DD0008 -+#define F367_FREEZE2 0xF0DD0004 -+#define F367_SLEEP_INHBT 0xF0DD0002 -+#define F367_CHIP_SLEEP 0xF0DD0001 -+ -+/* PAD_COMP_WR */ -+#define R367_PAD_COMP_WR 0xF0DE -+#define F367_WR_ASRC 0xF0DE007F -+ -+/* PAD_COMP_RD */ -+#define R367_PAD_COMP_RD 0xF0DF -+#define F367_COMPOK 0xF0DF0080 -+#define F367_RD_ASRC 0xF0DF007F -+ -+/* SYR_TARGET_FFTADJT_MSB */ -+#define R367_OFDM_SYR_TARGET_FFTADJT_MSB 0xF100 -+#define F367_OFDM_SYR_START 0xF1000080 -+#define F367_OFDM_SYR_TARGET_FFTADJ_HI 0xF100000F -+ -+/* SYR_TARGET_FFTADJT_LSB */ -+#define R367_OFDM_SYR_TARGET_FFTADJT_LSB 0xF101 -+#define F367_OFDM_SYR_TARGET_FFTADJ_LO 0xF10100FF -+ -+/* SYR_TARGET_CHCADJT_MSB */ -+#define R367_OFDM_SYR_TARGET_CHCADJT_MSB 0xF102 -+#define F367_OFDM_SYR_TARGET_CHCADJ_HI 0xF102000F -+ -+/* SYR_TARGET_CHCADJT_LSB */ -+#define R367_OFDM_SYR_TARGET_CHCADJT_LSB 0xF103 -+#define F367_OFDM_SYR_TARGET_CHCADJ_LO 0xF10300FF -+ -+/* SYR_FLAG */ -+#define R367_OFDM_SYR_FLAG 0xF104 -+#define F367_OFDM_TRIG_FLG1 0xF1040080 -+#define F367_OFDM_TRIG_FLG0 0xF1040040 -+#define F367_OFDM_FFT_FLG1 0xF1040008 -+#define F367_OFDM_FFT_FLG0 0xF1040004 -+#define F367_OFDM_CHC_FLG1 0xF1040002 -+#define F367_OFDM_CHC_FLG0 0xF1040001 -+ -+/* CRL_TARGET1 */ -+#define R367_OFDM_CRL_TARGET1 0xF105 -+#define F367_OFDM_CRL_START 0xF1050080 -+#define F367_OFDM_CRL_TARGET_VHI 0xF105000F -+ -+/* CRL_TARGET2 */ -+#define R367_OFDM_CRL_TARGET2 0xF106 -+#define F367_OFDM_CRL_TARGET_HI 0xF10600FF -+ -+/* CRL_TARGET3 */ -+#define R367_OFDM_CRL_TARGET3 0xF107 -+#define F367_OFDM_CRL_TARGET_LO 0xF10700FF -+ -+/* CRL_TARGET4 */ -+#define R367_OFDM_CRL_TARGET4 0xF108 -+#define F367_OFDM_CRL_TARGET_VLO 0xF10800FF -+ -+/* CRL_FLAG */ -+#define R367_OFDM_CRL_FLAG 0xF109 -+#define F367_OFDM_CRL_FLAG1 0xF1090002 -+#define F367_OFDM_CRL_FLAG0 0xF1090001 -+ -+/* TRL_TARGET1 */ -+#define R367_OFDM_TRL_TARGET1 0xF10A -+#define F367_OFDM_TRL_TARGET_HI 0xF10A00FF -+ -+/* TRL_TARGET2 */ -+#define R367_OFDM_TRL_TARGET2 0xF10B -+#define F367_OFDM_TRL_TARGET_LO 0xF10B00FF -+ -+/* TRL_CHC */ -+#define R367_OFDM_TRL_CHC 0xF10C -+#define F367_OFDM_TRL_START 0xF10C0080 -+#define F367_OFDM_CHC_START 0xF10C0040 -+#define F367_OFDM_TRL_FLAG1 0xF10C0002 -+#define F367_OFDM_TRL_FLAG0 0xF10C0001 -+ -+/* CHC_SNR_TARG */ -+#define R367_OFDM_CHC_SNR_TARG 0xF10D -+#define F367_OFDM_CHC_SNR_TARGET 0xF10D00FF -+ -+/* TOP_TRACK */ -+#define R367_OFDM_TOP_TRACK 0xF10E -+#define F367_OFDM_TOP_START 0xF10E0080 -+#define F367_OFDM_FIRST_FLAG 0xF10E0070 -+#define F367_OFDM_TOP_FLAG1 0xF10E0008 -+#define F367_OFDM_TOP_FLAG0 0xF10E0004 -+#define F367_OFDM_CHC_FLAG1 0xF10E0002 -+#define F367_OFDM_CHC_FLAG0 0xF10E0001 -+ -+/* TRACKER_FREE1 */ -+#define R367_OFDM_TRACKER_FREE1 0xF10F -+#define F367_OFDM_TRACKER_FREE_1 0xF10F00FF -+ -+/* ERROR_CRL1 */ -+#define R367_OFDM_ERROR_CRL1 0xF110 -+#define F367_OFDM_ERROR_CRL_VHI 0xF11000FF -+ -+/* ERROR_CRL2 */ -+#define R367_OFDM_ERROR_CRL2 0xF111 -+#define F367_OFDM_ERROR_CRL_HI 0xF11100FF -+ -+/* ERROR_CRL3 */ -+#define R367_OFDM_ERROR_CRL3 0xF112 -+#define F367_OFDM_ERROR_CRL_LOI 0xF11200FF -+ -+/* ERROR_CRL4 */ -+#define R367_OFDM_ERROR_CRL4 0xF113 -+#define F367_OFDM_ERROR_CRL_VLO 0xF11300FF -+ -+/* DEC_NCO1 */ -+#define R367_OFDM_DEC_NCO1 0xF114 -+#define F367_OFDM_DEC_NCO_VHI 0xF11400FF -+ -+/* DEC_NCO2 */ -+#define R367_OFDM_DEC_NCO2 0xF115 -+#define F367_OFDM_DEC_NCO_HI 0xF11500FF -+ -+/* DEC_NCO3 */ -+#define R367_OFDM_DEC_NCO3 0xF116 -+#define F367_OFDM_DEC_NCO_LO 0xF11600FF -+ -+/* SNR */ -+#define R367_OFDM_SNR 0xF117 -+#define F367_OFDM_SNRATIO 0xF11700FF -+ -+/* SYR_FFTADJ1 */ -+#define R367_OFDM_SYR_FFTADJ1 0xF118 -+#define F367_OFDM_SYR_FFTADJ_HI 0xF11800FF -+ -+/* SYR_FFTADJ2 */ -+#define R367_OFDM_SYR_FFTADJ2 0xF119 -+#define F367_OFDM_SYR_FFTADJ_LO 0xF11900FF -+ -+/* SYR_CHCADJ1 */ -+#define R367_OFDM_SYR_CHCADJ1 0xF11A -+#define F367_OFDM_SYR_CHCADJ_HI 0xF11A00FF -+ -+/* SYR_CHCADJ2 */ -+#define R367_OFDM_SYR_CHCADJ2 0xF11B -+#define F367_OFDM_SYR_CHCADJ_LO 0xF11B00FF -+ -+/* SYR_OFF */ -+#define R367_OFDM_SYR_OFF 0xF11C -+#define F367_OFDM_SYR_OFFSET 0xF11C00FF -+ -+/* PPM_OFFSET1 */ -+#define R367_OFDM_PPM_OFFSET1 0xF11D -+#define F367_OFDM_PPM_OFFSET_HI 0xF11D00FF -+ -+/* PPM_OFFSET2 */ -+#define R367_OFDM_PPM_OFFSET2 0xF11E -+#define F367_OFDM_PPM_OFFSET_LO 0xF11E00FF -+ -+/* TRACKER_FREE2 */ -+#define R367_OFDM_TRACKER_FREE2 0xF11F -+#define F367_OFDM_TRACKER_FREE_2 0xF11F00FF -+ -+/* DEBG_LT10 */ -+#define R367_OFDM_DEBG_LT10 0xF120 -+#define F367_OFDM_DEBUG_LT10 0xF12000FF -+ -+/* DEBG_LT11 */ -+#define R367_OFDM_DEBG_LT11 0xF121 -+#define F367_OFDM_DEBUG_LT11 0xF12100FF -+ -+/* DEBG_LT12 */ -+#define R367_OFDM_DEBG_LT12 0xF122 -+#define F367_OFDM_DEBUG_LT12 0xF12200FF -+ -+/* DEBG_LT13 */ -+#define R367_OFDM_DEBG_LT13 0xF123 -+#define F367_OFDM_DEBUG_LT13 0xF12300FF -+ -+/* DEBG_LT14 */ -+#define R367_OFDM_DEBG_LT14 0xF124 -+#define F367_OFDM_DEBUG_LT14 0xF12400FF -+ -+/* DEBG_LT15 */ -+#define R367_OFDM_DEBG_LT15 0xF125 -+#define F367_OFDM_DEBUG_LT15 0xF12500FF -+ -+/* DEBG_LT16 */ -+#define R367_OFDM_DEBG_LT16 0xF126 -+#define F367_OFDM_DEBUG_LT16 0xF12600FF -+ -+/* DEBG_LT17 */ -+#define R367_OFDM_DEBG_LT17 0xF127 -+#define F367_OFDM_DEBUG_LT17 0xF12700FF -+ -+/* DEBG_LT18 */ -+#define R367_OFDM_DEBG_LT18 0xF128 -+#define F367_OFDM_DEBUG_LT18 0xF12800FF -+ -+/* DEBG_LT19 */ -+#define R367_OFDM_DEBG_LT19 0xF129 -+#define F367_OFDM_DEBUG_LT19 0xF12900FF -+ -+/* DEBG_LT1A */ -+#define R367_OFDM_DEBG_LT1A 0xF12A -+#define F367_OFDM_DEBUG_LT1A 0xF12A00FF -+ -+/* DEBG_LT1B */ -+#define R367_OFDM_DEBG_LT1B 0xF12B -+#define F367_OFDM_DEBUG_LT1B 0xF12B00FF -+ -+/* DEBG_LT1C */ -+#define R367_OFDM_DEBG_LT1C 0xF12C -+#define F367_OFDM_DEBUG_LT1C 0xF12C00FF -+ -+/* DEBG_LT1D */ -+#define R367_OFDM_DEBG_LT1D 0xF12D -+#define F367_OFDM_DEBUG_LT1D 0xF12D00FF -+ -+/* DEBG_LT1E */ -+#define R367_OFDM_DEBG_LT1E 0xF12E -+#define F367_OFDM_DEBUG_LT1E 0xF12E00FF -+ -+/* DEBG_LT1F */ -+#define R367_OFDM_DEBG_LT1F 0xF12F -+#define F367_OFDM_DEBUG_LT1F 0xF12F00FF -+ -+/* RCCFGH */ -+#define R367_OFDM_RCCFGH 0xF200 -+#define F367_OFDM_TSRCFIFO_DVBCI 0xF2000080 -+#define F367_OFDM_TSRCFIFO_SERIAL 0xF2000040 -+#define F367_OFDM_TSRCFIFO_DISABLE 0xF2000020 -+#define F367_OFDM_TSFIFO_2TORC 0xF2000010 -+#define F367_OFDM_TSRCFIFO_HSGNLOUT 0xF2000008 -+#define F367_OFDM_TSRCFIFO_ERRMODE 0xF2000006 -+#define F367_OFDM_RCCFGH_0 0xF2000001 -+ -+/* RCCFGM */ -+#define R367_OFDM_RCCFGM 0xF201 -+#define F367_OFDM_TSRCFIFO_MANSPEED 0xF20100C0 -+#define F367_OFDM_TSRCFIFO_PERMDATA 0xF2010020 -+#define F367_OFDM_TSRCFIFO_NONEWSGNL 0xF2010010 -+#define F367_OFDM_RCBYTE_OVERSAMPLING 0xF201000E -+#define F367_OFDM_TSRCFIFO_INVDATA 0xF2010001 -+ -+/* RCCFGL */ -+#define R367_OFDM_RCCFGL 0xF202 -+#define F367_OFDM_TSRCFIFO_BCLKDEL1CK 0xF20200C0 -+#define F367_OFDM_RCCFGL_5 0xF2020020 -+#define F367_OFDM_TSRCFIFO_DUTY50 0xF2020010 -+#define F367_OFDM_TSRCFIFO_NSGNL2DATA 0xF2020008 -+#define F367_OFDM_TSRCFIFO_DISSERMUX 0xF2020004 -+#define F367_OFDM_RCCFGL_1 0xF2020002 -+#define F367_OFDM_TSRCFIFO_STOPCKDIS 0xF2020001 -+ -+/* RCINSDELH */ -+#define R367_OFDM_RCINSDELH 0xF203 -+#define F367_OFDM_TSRCDEL_SYNCBYTE 0xF2030080 -+#define F367_OFDM_TSRCDEL_XXHEADER 0xF2030040 -+#define F367_OFDM_TSRCDEL_BBHEADER 0xF2030020 -+#define F367_OFDM_TSRCDEL_DATAFIELD 0xF2030010 -+#define F367_OFDM_TSRCINSDEL_ISCR 0xF2030008 -+#define F367_OFDM_TSRCINSDEL_NPD 0xF2030004 -+#define F367_OFDM_TSRCINSDEL_RSPARITY 0xF2030002 -+#define F367_OFDM_TSRCINSDEL_CRC8 0xF2030001 -+ -+/* RCINSDELM */ -+#define R367_OFDM_RCINSDELM 0xF204 -+#define F367_OFDM_TSRCINS_BBPADDING 0xF2040080 -+#define F367_OFDM_TSRCINS_BCHFEC 0xF2040040 -+#define F367_OFDM_TSRCINS_LDPCFEC 0xF2040020 -+#define F367_OFDM_TSRCINS_EMODCOD 0xF2040010 -+#define F367_OFDM_TSRCINS_TOKEN 0xF2040008 -+#define F367_OFDM_TSRCINS_XXXERR 0xF2040004 -+#define F367_OFDM_TSRCINS_MATYPE 0xF2040002 -+#define F367_OFDM_TSRCINS_UPL 0xF2040001 -+ -+/* RCINSDELL */ -+#define R367_OFDM_RCINSDELL 0xF205 -+#define F367_OFDM_TSRCINS_DFL 0xF2050080 -+#define F367_OFDM_TSRCINS_SYNCD 0xF2050040 -+#define F367_OFDM_TSRCINS_BLOCLEN 0xF2050020 -+#define F367_OFDM_TSRCINS_SIGPCOUNT 0xF2050010 -+#define F367_OFDM_TSRCINS_FIFO 0xF2050008 -+#define F367_OFDM_TSRCINS_REALPACK 0xF2050004 -+#define F367_OFDM_TSRCINS_TSCONFIG 0xF2050002 -+#define F367_OFDM_TSRCINS_LATENCY 0xF2050001 -+ -+/* RCSTATUS */ -+#define R367_OFDM_RCSTATUS 0xF206 -+#define F367_OFDM_TSRCFIFO_LINEOK 0xF2060080 -+#define F367_OFDM_TSRCFIFO_ERROR 0xF2060040 -+#define F367_OFDM_TSRCFIFO_DATA7 0xF2060020 -+#define F367_OFDM_RCSTATUS_4 0xF2060010 -+#define F367_OFDM_TSRCFIFO_DEMODSEL 0xF2060008 -+#define F367_OFDM_TSRC1FIFOSPEED_STORE 0xF2060004 -+#define F367_OFDM_RCSTATUS_1 0xF2060002 -+#define F367_OFDM_TSRCSERIAL_IMPOSSIBLE 0xF2060001 -+ -+/* RCSPEED */ -+#define R367_OFDM_RCSPEED 0xF207 -+#define F367_OFDM_TSRCFIFO_OUTSPEED 0xF20700FF -+ -+/* RCDEBUGM */ -+#define R367_OFDM_RCDEBUGM 0xF208 -+#define F367_OFDM_SD_UNSYNC 0xF2080080 -+#define F367_OFDM_ULFLOCK_DETECTM 0xF2080040 -+#define F367_OFDM_SUL_SELECTOS 0xF2080020 -+#define F367_OFDM_DILUL_NOSCRBLE 0xF2080010 -+#define F367_OFDM_NUL_SCRB 0xF2080008 -+#define F367_OFDM_UL_SCRB 0xF2080004 -+#define F367_OFDM_SCRAULBAD 0xF2080002 -+#define F367_OFDM_SCRAUL_UNSYNC 0xF2080001 -+ -+/* RCDEBUGL */ -+#define R367_OFDM_RCDEBUGL 0xF209 -+#define F367_OFDM_RS_ERR 0xF2090080 -+#define F367_OFDM_LLFLOCK_DETECTM 0xF2090040 -+#define F367_OFDM_NOT_SUL_SELECTOS 0xF2090020 -+#define F367_OFDM_DILLL_NOSCRBLE 0xF2090010 -+#define F367_OFDM_NLL_SCRB 0xF2090008 -+#define F367_OFDM_LL_SCRB 0xF2090004 -+#define F367_OFDM_SCRALLBAD 0xF2090002 -+#define F367_OFDM_SCRALL_UNSYNC 0xF2090001 -+ -+/* RCOBSCFG */ -+#define R367_OFDM_RCOBSCFG 0xF20A -+#define F367_OFDM_TSRCFIFO_OBSCFG 0xF20A00FF -+ -+/* RCOBSM */ -+#define R367_OFDM_RCOBSM 0xF20B -+#define F367_OFDM_TSRCFIFO_OBSDATA_HI 0xF20B00FF -+ -+/* RCOBSL */ -+#define R367_OFDM_RCOBSL 0xF20C -+#define F367_OFDM_TSRCFIFO_OBSDATA_LO 0xF20C00FF -+ -+/* RCFECSPY */ -+#define R367_OFDM_RCFECSPY 0xF210 -+#define F367_OFDM_SPYRC_ENABLE 0xF2100080 -+#define F367_OFDM_RCNO_SYNCBYTE 0xF2100040 -+#define F367_OFDM_RCSERIAL_MODE 0xF2100020 -+#define F367_OFDM_RCUNUSUAL_PACKET 0xF2100010 -+#define F367_OFDM_BERRCMETER_DATAMODE 0xF210000C -+#define F367_OFDM_BERRCMETER_LMODE 0xF2100002 -+#define F367_OFDM_BERRCMETER_RESET 0xF2100001 -+ -+/* RCFSPYCFG */ -+#define R367_OFDM_RCFSPYCFG 0xF211 -+#define F367_OFDM_FECSPYRC_INPUT 0xF21100C0 -+#define F367_OFDM_RCRST_ON_ERROR 0xF2110020 -+#define F367_OFDM_RCONE_SHOT 0xF2110010 -+#define F367_OFDM_RCI2C_MODE 0xF211000C -+#define F367_OFDM_SPYRC_HSTERESIS 0xF2110003 -+ -+/* RCFSPYDATA */ -+#define R367_OFDM_RCFSPYDATA 0xF212 -+#define F367_OFDM_SPYRC_STUFFING 0xF2120080 -+#define F367_OFDM_RCNOERR_PKTJITTER 0xF2120040 -+#define F367_OFDM_SPYRC_CNULLPKT 0xF2120020 -+#define F367_OFDM_SPYRC_OUTDATA_MODE 0xF212001F -+ -+/* RCFSPYOUT */ -+#define R367_OFDM_RCFSPYOUT 0xF213 -+#define F367_OFDM_FSPYRC_DIRECT 0xF2130080 -+#define F367_OFDM_RCFSPYOUT_6 0xF2130040 -+#define F367_OFDM_SPYRC_OUTDATA_BUS 0xF2130038 -+#define F367_OFDM_RCSTUFF_MODE 0xF2130007 -+ -+/* RCFSTATUS */ -+#define R367_OFDM_RCFSTATUS 0xF214 -+#define F367_OFDM_SPYRC_ENDSIM 0xF2140080 -+#define F367_OFDM_RCVALID_SIM 0xF2140040 -+#define F367_OFDM_RCFOUND_SIGNAL 0xF2140020 -+#define F367_OFDM_RCDSS_SYNCBYTE 0xF2140010 -+#define F367_OFDM_RCRESULT_STATE 0xF214000F -+ -+/* RCFGOODPACK */ -+#define R367_OFDM_RCFGOODPACK 0xF215 -+#define F367_OFDM_RCGOOD_PACKET 0xF21500FF -+ -+/* RCFPACKCNT */ -+#define R367_OFDM_RCFPACKCNT 0xF216 -+#define F367_OFDM_RCPACKET_COUNTER 0xF21600FF -+ -+/* RCFSPYMISC */ -+#define R367_OFDM_RCFSPYMISC 0xF217 -+#define F367_OFDM_RCLABEL_COUNTER 0xF21700FF -+ -+/* RCFBERCPT4 */ -+#define R367_OFDM_RCFBERCPT4 0xF218 -+#define F367_OFDM_FBERRCMETER_CPT_MMMMSB 0xF21800FF -+ -+/* RCFBERCPT3 */ -+#define R367_OFDM_RCFBERCPT3 0xF219 -+#define F367_OFDM_FBERRCMETER_CPT_MMMSB 0xF21900FF -+ -+/* RCFBERCPT2 */ -+#define R367_OFDM_RCFBERCPT2 0xF21A -+#define F367_OFDM_FBERRCMETER_CPT_MMSB 0xF21A00FF -+ -+/* RCFBERCPT1 */ -+#define R367_OFDM_RCFBERCPT1 0xF21B -+#define F367_OFDM_FBERRCMETER_CPT_MSB 0xF21B00FF -+ -+/* RCFBERCPT0 */ -+#define R367_OFDM_RCFBERCPT0 0xF21C -+#define F367_OFDM_FBERRCMETER_CPT_LSB 0xF21C00FF -+ -+/* RCFBERERR2 */ -+#define R367_OFDM_RCFBERERR2 0xF21D -+#define F367_OFDM_FBERRCMETER_ERR_HI 0xF21D00FF -+ -+/* RCFBERERR1 */ -+#define R367_OFDM_RCFBERERR1 0xF21E -+#define F367_OFDM_FBERRCMETER_ERR 0xF21E00FF -+ -+/* RCFBERERR0 */ -+#define R367_OFDM_RCFBERERR0 0xF21F -+#define F367_OFDM_FBERRCMETER_ERR_LO 0xF21F00FF -+ -+/* RCFSTATESM */ -+#define R367_OFDM_RCFSTATESM 0xF220 -+#define F367_OFDM_RCRSTATE_F 0xF2200080 -+#define F367_OFDM_RCRSTATE_E 0xF2200040 -+#define F367_OFDM_RCRSTATE_D 0xF2200020 -+#define F367_OFDM_RCRSTATE_C 0xF2200010 -+#define F367_OFDM_RCRSTATE_B 0xF2200008 -+#define F367_OFDM_RCRSTATE_A 0xF2200004 -+#define F367_OFDM_RCRSTATE_9 0xF2200002 -+#define F367_OFDM_RCRSTATE_8 0xF2200001 -+ -+/* RCFSTATESL */ -+#define R367_OFDM_RCFSTATESL 0xF221 -+#define F367_OFDM_RCRSTATE_7 0xF2210080 -+#define F367_OFDM_RCRSTATE_6 0xF2210040 -+#define F367_OFDM_RCRSTATE_5 0xF2210020 -+#define F367_OFDM_RCRSTATE_4 0xF2210010 -+#define F367_OFDM_RCRSTATE_3 0xF2210008 -+#define F367_OFDM_RCRSTATE_2 0xF2210004 -+#define F367_OFDM_RCRSTATE_1 0xF2210002 -+#define F367_OFDM_RCRSTATE_0 0xF2210001 -+ -+/* RCFSPYBER */ -+#define R367_OFDM_RCFSPYBER 0xF222 -+#define F367_OFDM_RCFSPYBER_7 0xF2220080 -+#define F367_OFDM_SPYRCOBS_XORREAD 0xF2220040 -+#define F367_OFDM_FSPYRCBER_OBSMODE 0xF2220020 -+#define F367_OFDM_FSPYRCBER_SYNCBYT 0xF2220010 -+#define F367_OFDM_FSPYRCBER_UNSYNC 0xF2220008 -+#define F367_OFDM_FSPYRCBER_CTIME 0xF2220007 -+ -+/* RCFSPYDISTM */ -+#define R367_OFDM_RCFSPYDISTM 0xF223 -+#define F367_OFDM_RCPKTTIME_DISTANCE_HI 0xF22300FF -+ -+/* RCFSPYDISTL */ -+#define R367_OFDM_RCFSPYDISTL 0xF224 -+#define F367_OFDM_RCPKTTIME_DISTANCE_LO 0xF22400FF -+ -+/* RCFSPYOBS7 */ -+#define R367_OFDM_RCFSPYOBS7 0xF228 -+#define F367_OFDM_RCSPYOBS_SPYFAIL 0xF2280080 -+#define F367_OFDM_RCSPYOBS_SPYFAIL1 0xF2280040 -+#define F367_OFDM_RCSPYOBS_ERROR 0xF2280020 -+#define F367_OFDM_RCSPYOBS_STROUT 0xF2280010 -+#define F367_OFDM_RCSPYOBS_RESULTSTATE1 0xF228000F -+ -+/* RCFSPYOBS6 */ -+#define R367_OFDM_RCFSPYOBS6 0xF229 -+#define F367_OFDM_RCSPYOBS_RESULTSTATE0 0xF22900F0 -+#define F367_OFDM_RCSPYOBS_RESULTSTATEM1 0xF229000F -+ -+/* RCFSPYOBS5 */ -+#define R367_OFDM_RCFSPYOBS5 0xF22A -+#define F367_OFDM_RCSPYOBS_BYTEOFPACKET1 0xF22A00FF -+ -+/* RCFSPYOBS4 */ -+#define R367_OFDM_RCFSPYOBS4 0xF22B -+#define F367_OFDM_RCSPYOBS_BYTEVALUE1 0xF22B00FF -+ -+/* RCFSPYOBS3 */ -+#define R367_OFDM_RCFSPYOBS3 0xF22C -+#define F367_OFDM_RCSPYOBS_DATA1 0xF22C00FF -+ -+/* RCFSPYOBS2 */ -+#define R367_OFDM_RCFSPYOBS2 0xF22D -+#define F367_OFDM_RCSPYOBS_DATA0 0xF22D00FF -+ -+/* RCFSPYOBS1 */ -+#define R367_OFDM_RCFSPYOBS1 0xF22E -+#define F367_OFDM_RCSPYOBS_DATAM1 0xF22E00FF -+ -+/* RCFSPYOBS0 */ -+#define R367_OFDM_RCFSPYOBS0 0xF22F -+#define F367_OFDM_RCSPYOBS_DATAM2 0xF22F00FF -+ -+/* TSGENERAL */ -+#define R367_TSGENERAL 0xF230 -+#define F367_TSGENERAL_7 0xF2300080 -+#define F367_TSGENERAL_6 0xF2300040 -+#define F367_TSFIFO_BCLK1ALL 0xF2300020 -+#define F367_TSGENERAL_4 0xF2300010 -+#define F367_MUXSTREAM_OUTMODE 0xF2300008 -+#define F367_TSFIFO_PERMPARAL 0xF2300006 -+#define F367_RST_REEDSOLO 0xF2300001 -+ -+/* RC1SPEED */ -+#define R367_RC1SPEED 0xF231 -+#define F367_TSRCFIFO1_OUTSPEED 0xF23100FF -+ -+/* TSGSTATUS */ -+#define R367_TSGSTATUS 0xF232 -+#define F367_TSGSTATUS_7 0xF2320080 -+#define F367_TSGSTATUS_6 0xF2320040 -+#define F367_RSMEM_FULL 0xF2320020 -+#define F367_RS_MULTCALC 0xF2320010 -+#define F367_RSIN_OVERTIME 0xF2320008 -+#define F367_TSFIFO3_DEMODSEL 0xF2320004 -+#define F367_TSFIFO2_DEMODSEL 0xF2320002 -+#define F367_TSFIFO1_DEMODSEL 0xF2320001 -+ -+ -+/* FECM */ -+#define R367_OFDM_FECM 0xF233 -+#define F367_OFDM_DSS_DVB 0xF2330080 -+#define F367_OFDM_DEMOD_BYPASS 0xF2330040 -+#define F367_OFDM_CMP_SLOWMODE 0xF2330020 -+#define F367_OFDM_DSS_SRCH 0xF2330010 -+#define F367_OFDM_FECM_3 0xF2330008 -+#define F367_OFDM_DIFF_MODEVIT 0xF2330004 -+#define F367_OFDM_SYNCVIT 0xF2330002 -+#define F367_OFDM_I2CSYM 0xF2330001 -+ -+/* VTH12 */ -+#define R367_OFDM_VTH12 0xF234 -+#define F367_OFDM_VTH_12 0xF23400FF -+ -+/* VTH23 */ -+#define R367_OFDM_VTH23 0xF235 -+#define F367_OFDM_VTH_23 0xF23500FF -+ -+/* VTH34 */ -+#define R367_OFDM_VTH34 0xF236 -+#define F367_OFDM_VTH_34 0xF23600FF -+ -+/* VTH56 */ -+#define R367_OFDM_VTH56 0xF237 -+#define F367_OFDM_VTH_56 0xF23700FF -+ -+/* VTH67 */ -+#define R367_OFDM_VTH67 0xF238 -+#define F367_OFDM_VTH_67 0xF23800FF -+ -+/* VTH78 */ -+#define R367_OFDM_VTH78 0xF239 -+#define F367_OFDM_VTH_78 0xF23900FF -+ -+/* VITCURPUN */ -+#define R367_OFDM_VITCURPUN 0xF23A -+#define F367_OFDM_VIT_MAPPING 0xF23A00E0 -+#define F367_OFDM_VIT_CURPUN 0xF23A001F -+ -+/* VERROR */ -+#define R367_OFDM_VERROR 0xF23B -+#define F367_OFDM_REGERR_VIT 0xF23B00FF -+ -+/* PRVIT */ -+#define R367_OFDM_PRVIT 0xF23C -+#define F367_OFDM_PRVIT_7 0xF23C0080 -+#define F367_OFDM_DIS_VTHLOCK 0xF23C0040 -+#define F367_OFDM_E7_8VIT 0xF23C0020 -+#define F367_OFDM_E6_7VIT 0xF23C0010 -+#define F367_OFDM_E5_6VIT 0xF23C0008 -+#define F367_OFDM_E3_4VIT 0xF23C0004 -+#define F367_OFDM_E2_3VIT 0xF23C0002 -+#define F367_OFDM_E1_2VIT 0xF23C0001 -+ -+/* VAVSRVIT */ -+#define R367_OFDM_VAVSRVIT 0xF23D -+#define F367_OFDM_AMVIT 0xF23D0080 -+#define F367_OFDM_FROZENVIT 0xF23D0040 -+#define F367_OFDM_SNVIT 0xF23D0030 -+#define F367_OFDM_TOVVIT 0xF23D000C -+#define F367_OFDM_HYPVIT 0xF23D0003 -+ -+/* VSTATUSVIT */ -+#define R367_OFDM_VSTATUSVIT 0xF23E -+#define F367_OFDM_VITERBI_ON 0xF23E0080 -+#define F367_OFDM_END_LOOPVIT 0xF23E0040 -+#define F367_OFDM_VITERBI_DEPRF 0xF23E0020 -+#define F367_OFDM_PRFVIT 0xF23E0010 -+#define F367_OFDM_LOCKEDVIT 0xF23E0008 -+#define F367_OFDM_VITERBI_DELOCK 0xF23E0004 -+#define F367_OFDM_VIT_DEMODSEL 0xF23E0002 -+#define F367_OFDM_VITERBI_COMPOUT 0xF23E0001 -+ -+/* VTHINUSE */ -+#define R367_OFDM_VTHINUSE 0xF23F -+#define F367_OFDM_VIT_INUSE 0xF23F00FF -+ -+/* KDIV12 */ -+#define R367_OFDM_KDIV12 0xF240 -+#define F367_OFDM_KDIV12_MANUAL 0xF2400080 -+#define F367_OFDM_K_DIVIDER_12 0xF240007F -+ -+/* KDIV23 */ -+#define R367_OFDM_KDIV23 0xF241 -+#define F367_OFDM_KDIV23_MANUAL 0xF2410080 -+#define F367_OFDM_K_DIVIDER_23 0xF241007F -+ -+/* KDIV34 */ -+#define R367_OFDM_KDIV34 0xF242 -+#define F367_OFDM_KDIV34_MANUAL 0xF2420080 -+#define F367_OFDM_K_DIVIDER_34 0xF242007F -+ -+/* KDIV56 */ -+#define R367_OFDM_KDIV56 0xF243 -+#define F367_OFDM_KDIV56_MANUAL 0xF2430080 -+#define F367_OFDM_K_DIVIDER_56 0xF243007F -+ -+/* KDIV67 */ -+#define R367_OFDM_KDIV67 0xF244 -+#define F367_OFDM_KDIV67_MANUAL 0xF2440080 -+#define F367_OFDM_K_DIVIDER_67 0xF244007F -+ -+/* KDIV78 */ -+#define R367_OFDM_KDIV78 0xF245 -+#define F367_OFDM_KDIV78_MANUAL 0xF2450080 -+#define F367_OFDM_K_DIVIDER_78 0xF245007F -+ -+/* SIGPOWER */ -+#define R367_OFDM_SIGPOWER 0xF246 -+#define F367_OFDM_SIGPOWER_MANUAL 0xF2460080 -+#define F367_OFDM_SIG_POWER 0xF246007F -+ -+/* DEMAPVIT */ -+#define R367_OFDM_DEMAPVIT 0xF247 -+#define F367_OFDM_DEMAPVIT_7 0xF2470080 -+#define F367_OFDM_K_DIVIDER_VIT 0xF247007F -+ -+/* VITSCALE */ -+#define R367_OFDM_VITSCALE 0xF248 -+#define F367_OFDM_NVTH_NOSRANGE 0xF2480080 -+#define F367_OFDM_VERROR_MAXMODE 0xF2480040 -+#define F367_OFDM_KDIV_MODE 0xF2480030 -+#define F367_OFDM_NSLOWSN_LOCKED 0xF2480008 -+#define F367_OFDM_DELOCK_PRFLOSS 0xF2480004 -+#define F367_OFDM_DIS_RSFLOCK 0xF2480002 -+#define F367_OFDM_VITSCALE_0 0xF2480001 -+ -+/* FFEC1PRG */ -+#define R367_OFDM_FFEC1PRG 0xF249 -+#define F367_OFDM_FDSS_DVB 0xF2490080 -+#define F367_OFDM_FDSS_SRCH 0xF2490040 -+#define F367_OFDM_FFECPROG_5 0xF2490020 -+#define F367_OFDM_FFECPROG_4 0xF2490010 -+#define F367_OFDM_FFECPROG_3 0xF2490008 -+#define F367_OFDM_FFECPROG_2 0xF2490004 -+#define F367_OFDM_FTS1_DISABLE 0xF2490002 -+#define F367_OFDM_FTS2_DISABLE 0xF2490001 -+ -+/* FVITCURPUN */ -+#define R367_OFDM_FVITCURPUN 0xF24A -+#define F367_OFDM_FVIT_MAPPING 0xF24A00E0 -+#define F367_OFDM_FVIT_CURPUN 0xF24A001F -+ -+/* FVERROR */ -+#define R367_OFDM_FVERROR 0xF24B -+#define F367_OFDM_FREGERR_VIT 0xF24B00FF -+ -+/* FVSTATUSVIT */ -+#define R367_OFDM_FVSTATUSVIT 0xF24C -+#define F367_OFDM_FVITERBI_ON 0xF24C0080 -+#define F367_OFDM_F1END_LOOPVIT 0xF24C0040 -+#define F367_OFDM_FVITERBI_DEPRF 0xF24C0020 -+#define F367_OFDM_FPRFVIT 0xF24C0010 -+#define F367_OFDM_FLOCKEDVIT 0xF24C0008 -+#define F367_OFDM_FVITERBI_DELOCK 0xF24C0004 -+#define F367_OFDM_FVIT_DEMODSEL 0xF24C0002 -+#define F367_OFDM_FVITERBI_COMPOUT 0xF24C0001 -+ -+/* DEBUG_LT1 */ -+#define R367_OFDM_DEBUG_LT1 0xF24D -+#define F367_OFDM_DBG_LT1 0xF24D00FF -+ -+/* DEBUG_LT2 */ -+#define R367_OFDM_DEBUG_LT2 0xF24E -+#define F367_OFDM_DBG_LT2 0xF24E00FF -+ -+/* DEBUG_LT3 */ -+#define R367_OFDM_DEBUG_LT3 0xF24F -+#define F367_OFDM_DBG_LT3 0xF24F00FF -+ -+ /* TSTSFMET */ -+#define R367_OFDM_TSTSFMET 0xF250 -+#define F367_OFDM_TSTSFEC_METRIQUES 0xF25000FF -+ -+ /* SELOUT */ -+#define R367_OFDM_SELOUT 0xF252 -+#define F367_OFDM_EN_SYNC 0xF2520080 -+#define F367_OFDM_EN_TBUSDEMAP 0xF2520040 -+#define F367_OFDM_SELOUT_5 0xF2520020 -+#define F367_OFDM_SELOUT_4 0xF2520010 -+#define F367_OFDM_TSTSYNCHRO_MODE 0xF2520002 -+ -+ /* TSYNC */ -+#define R367_OFDM_TSYNC 0xF253 -+#define F367_OFDM_CURPUN_INCMODE 0xF2530080 -+#define F367_OFDM_CERR_TSTMODE 0xF2530040 -+#define F367_OFDM_SHIFTSOF_MODE 0xF2530030 -+#define F367_OFDM_SLOWPHA_MODE 0xF2530008 -+#define F367_OFDM_PXX_BYPALL 0xF2530004 -+#define F367_OFDM_FROTA45_FIRST 0xF2530002 -+#define F367_OFDM_TST_BCHERROR 0xF2530001 -+ -+ /* TSTERR */ -+#define R367_OFDM_TSTERR 0xF254 -+#define F367_OFDM_TST_LONGPKT 0xF2540080 -+#define F367_OFDM_TST_ISSYION 0xF2540040 -+#define F367_OFDM_TST_NPDON 0xF2540020 -+#define F367_OFDM_TSTERR_4 0xF2540010 -+#define F367_OFDM_TRACEBACK_MODE 0xF2540008 -+#define F367_OFDM_TST_RSPARITY 0xF2540004 -+#define F367_OFDM_METRIQUE_MODE 0xF2540003 -+ -+ /* TSFSYNC */ -+#define R367_OFDM_TSFSYNC 0xF255 -+#define F367_OFDM_EN_SFECSYNC 0xF2550080 -+#define F367_OFDM_EN_SFECDEMAP 0xF2550040 -+#define F367_OFDM_SFCERR_TSTMODE 0xF2550020 -+#define F367_OFDM_SFECPXX_BYPALL 0xF2550010 -+#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F -+ -+ /* TSTSFERR */ -+#define R367_OFDM_TSTSFERR 0xF256 -+#define F367_OFDM_TSTSTERR_7 0xF2560080 -+#define F367_OFDM_TSTSTERR_6 0xF2560040 -+#define F367_OFDM_TSTSTERR_5 0xF2560020 -+#define F367_OFDM_TSTSTERR_4 0xF2560010 -+#define F367_OFDM_SFECTRACEBACK_MODE 0xF2560008 -+#define F367_OFDM_SFEC_NCONVPROG 0xF2560004 -+#define F367_OFDM_SFECMETRIQUE_MODE 0xF2560003 -+ -+ /* TSTTSSF1 */ -+#define R367_OFDM_TSTTSSF1 0xF258 -+#define F367_OFDM_TSTERSSF 0xF2580080 -+#define F367_OFDM_TSTTSSFEN 0xF2580040 -+#define F367_OFDM_SFEC_OUTMODE 0xF2580030 -+#define F367_OFDM_XLSF_NOFTHRESHOLD 0xF2580008 -+#define F367_OFDM_TSTTSSF_STACKSEL 0xF2580007 -+ -+ /* TSTTSSF2 */ -+#define R367_OFDM_TSTTSSF2 0xF259 -+#define F367_OFDM_DILSF_DBBHEADER 0xF2590080 -+#define F367_OFDM_TSTTSSF_DISBUG 0xF2590040 -+#define F367_OFDM_TSTTSSF_NOBADSTART 0xF2590020 -+#define F367_OFDM_TSTTSSF_SELECT 0xF259001F -+ -+ /* TSTTSSF3 */ -+#define R367_OFDM_TSTTSSF3 0xF25A -+#define F367_OFDM_TSTTSSF3_7 0xF25A0080 -+#define F367_OFDM_TSTTSSF3_6 0xF25A0040 -+#define F367_OFDM_TSTTSSF3_5 0xF25A0020 -+#define F367_OFDM_TSTTSSF3_4 0xF25A0010 -+#define F367_OFDM_TSTTSSF3_3 0xF25A0008 -+#define F367_OFDM_TSTTSSF3_2 0xF25A0004 -+#define F367_OFDM_TSTTSSF3_1 0xF25A0002 -+#define F367_OFDM_DISSF_CLKENABLE 0xF25A0001 -+ -+ /* TSTTS1 */ -+#define R367_OFDM_TSTTS1 0xF25C -+#define F367_OFDM_TSTERS 0xF25C0080 -+#define F367_OFDM_TSFIFO_DSSSYNCB 0xF25C0040 -+#define F367_OFDM_TSTTS_FSPYBEFRS 0xF25C0020 -+#define F367_OFDM_NFORCE_SYNCBYTE 0xF25C0010 -+#define F367_OFDM_XL_NOFTHRESHOLD 0xF25C0008 -+#define F367_OFDM_TSTTS_FRFORCEPKT 0xF25C0004 -+#define F367_OFDM_DESCR_NOTAUTO 0xF25C0002 -+#define F367_OFDM_TSTTSEN 0xF25C0001 -+ -+ /* TSTTS2 */ -+#define R367_OFDM_TSTTS2 0xF25D -+#define F367_OFDM_DIL_DBBHEADER 0xF25D0080 -+#define F367_OFDM_TSTTS_NOBADXXX 0xF25D0040 -+#define F367_OFDM_TSFIFO_DELSPEEDUP 0xF25D0020 -+#define F367_OFDM_TSTTS_SELECT 0xF25D001F -+ -+ /* TSTTS3 */ -+#define R367_OFDM_TSTTS3 0xF25E -+#define F367_OFDM_TSTTS_NOPKTGAIN 0xF25E0080 -+#define F367_OFDM_TSTTS_NOPKTENE 0xF25E0040 -+#define F367_OFDM_TSTTS_ISOLATION 0xF25E0020 -+#define F367_OFDM_TSTTS_DISBUG 0xF25E0010 -+#define F367_OFDM_TSTTS_NOBADSTART 0xF25E0008 -+#define F367_OFDM_TSTTS_STACKSEL 0xF25E0007 -+ -+ /* TSTTS4 */ -+#define R367_OFDM_TSTTS4 0xF25F -+#define F367_OFDM_TSTTS4_7 0xF25F0080 -+#define F367_OFDM_TSTTS4_6 0xF25F0040 -+#define F367_OFDM_TSTTS4_5 0xF25F0020 -+#define F367_OFDM_TSTTS_DISDSTATE 0xF25F0010 -+#define F367_OFDM_TSTTS_FASTNOSYNC 0xF25F0008 -+#define F367_OFDM_EXT_FECSPYIN 0xF25F0004 -+#define F367_OFDM_TSTTS_NODPZERO 0xF25F0002 -+#define F367_OFDM_TSTTS_NODIV3 0xF25F0001 -+ -+ /* TSTTSRC */ -+#define R367_OFDM_TSTTSRC 0xF26C -+#define F367_OFDM_TSTTSRC_7 0xF26C0080 -+#define F367_OFDM_TSRCFIFO_DSSSYNCB 0xF26C0040 -+#define F367_OFDM_TSRCFIFO_DPUNACTIVE 0xF26C0020 -+#define F367_OFDM_TSRCFIFO_DELSPEEDUP 0xF26C0010 -+#define F367_OFDM_TSTTSRC_NODIV3 0xF26C0008 -+#define F367_OFDM_TSTTSRC_FRFORCEPKT 0xF26C0004 -+#define F367_OFDM_SAT25_SDDORIGINE 0xF26C0002 -+#define F367_OFDM_TSTTSRC_INACTIVE 0xF26C0001 -+ -+ /* TSTTSRS */ -+#define R367_OFDM_TSTTSRS 0xF26D -+#define F367_OFDM_TSTTSRS_7 0xF26D0080 -+#define F367_OFDM_TSTTSRS_6 0xF26D0040 -+#define F367_OFDM_TSTTSRS_5 0xF26D0020 -+#define F367_OFDM_TSTTSRS_4 0xF26D0010 -+#define F367_OFDM_TSTTSRS_3 0xF26D0008 -+#define F367_OFDM_TSTTSRS_2 0xF26D0004 -+#define F367_OFDM_TSTRS_DISRS2 0xF26D0002 -+#define F367_OFDM_TSTRS_DISRS1 0xF26D0001 -+ -+/* TSSTATEM */ -+#define R367_OFDM_TSSTATEM 0xF270 -+#define F367_OFDM_TSDIL_ON 0xF2700080 -+#define F367_OFDM_TSSKIPRS_ON 0xF2700040 -+#define F367_OFDM_TSRS_ON 0xF2700020 -+#define F367_OFDM_TSDESCRAMB_ON 0xF2700010 -+#define F367_OFDM_TSFRAME_MODE 0xF2700008 -+#define F367_OFDM_TS_DISABLE 0xF2700004 -+#define F367_OFDM_TSACM_MODE 0xF2700002 -+#define F367_OFDM_TSOUT_NOSYNC 0xF2700001 -+ -+/* TSSTATEL */ -+#define R367_OFDM_TSSTATEL 0xF271 -+#define F367_OFDM_TSNOSYNCBYTE 0xF2710080 -+#define F367_OFDM_TSPARITY_ON 0xF2710040 -+#define F367_OFDM_TSSYNCOUTRS_ON 0xF2710020 -+#define F367_OFDM_TSDVBS2_MODE 0xF2710010 -+#define F367_OFDM_TSISSYI_ON 0xF2710008 -+#define F367_OFDM_TSNPD_ON 0xF2710004 -+#define F367_OFDM_TSCRC8_ON 0xF2710002 -+#define F367_OFDM_TSDSS_PACKET 0xF2710001 -+ -+/* TSCFGH */ -+#define R367_OFDM_TSCFGH 0xF272 -+#define F367_OFDM_TSFIFO_DVBCI 0xF2720080 -+#define F367_OFDM_TSFIFO_SERIAL 0xF2720040 -+#define F367_OFDM_TSFIFO_TEIUPDATE 0xF2720020 -+#define F367_OFDM_TSFIFO_DUTY50 0xF2720010 -+#define F367_OFDM_TSFIFO_HSGNLOUT 0xF2720008 -+#define F367_OFDM_TSFIFO_ERRMODE 0xF2720006 -+#define F367_OFDM_RST_HWARE 0xF2720001 -+ -+/* TSCFGM */ -+#define R367_OFDM_TSCFGM 0xF273 -+#define F367_OFDM_TSFIFO_MANSPEED 0xF27300C0 -+#define F367_OFDM_TSFIFO_PERMDATA 0xF2730020 -+#define F367_OFDM_TSFIFO_NONEWSGNL 0xF2730010 -+#define F367_OFDM_TSFIFO_BITSPEED 0xF2730008 -+#define F367_OFDM_NPD_SPECDVBS2 0xF2730004 -+#define F367_OFDM_TSFIFO_STOPCKDIS 0xF2730002 -+#define F367_OFDM_TSFIFO_INVDATA 0xF2730001 -+ -+/* TSCFGL */ -+#define R367_OFDM_TSCFGL 0xF274 -+#define F367_OFDM_TSFIFO_BCLKDEL1CK 0xF27400C0 -+#define F367_OFDM_BCHERROR_MODE 0xF2740030 -+#define F367_OFDM_TSFIFO_NSGNL2DATA 0xF2740008 -+#define F367_OFDM_TSFIFO_EMBINDVB 0xF2740004 -+#define F367_OFDM_TSFIFO_DPUNACT 0xF2740002 -+#define F367_OFDM_TSFIFO_NPDOFF 0xF2740001 -+ -+/* TSSYNC */ -+#define R367_OFDM_TSSYNC 0xF275 -+#define F367_OFDM_TSFIFO_PERMUTE 0xF2750080 -+#define F367_OFDM_TSFIFO_FISCR3B 0xF2750060 -+#define F367_OFDM_TSFIFO_SYNCMODE 0xF2750018 -+#define F367_OFDM_TSFIFO_SYNCSEL 0xF2750007 -+ -+/* TSINSDELH */ -+#define R367_OFDM_TSINSDELH 0xF276 -+#define F367_OFDM_TSDEL_SYNCBYTE 0xF2760080 -+#define F367_OFDM_TSDEL_XXHEADER 0xF2760040 -+#define F367_OFDM_TSDEL_BBHEADER 0xF2760020 -+#define F367_OFDM_TSDEL_DATAFIELD 0xF2760010 -+#define F367_OFDM_TSINSDEL_ISCR 0xF2760008 -+#define F367_OFDM_TSINSDEL_NPD 0xF2760004 -+#define F367_OFDM_TSINSDEL_RSPARITY 0xF2760002 -+#define F367_OFDM_TSINSDEL_CRC8 0xF2760001 -+ -+/* TSINSDELM */ -+#define R367_OFDM_TSINSDELM 0xF277 -+#define F367_OFDM_TSINS_BBPADDING 0xF2770080 -+#define F367_OFDM_TSINS_BCHFEC 0xF2770040 -+#define F367_OFDM_TSINS_LDPCFEC 0xF2770020 -+#define F367_OFDM_TSINS_EMODCOD 0xF2770010 -+#define F367_OFDM_TSINS_TOKEN 0xF2770008 -+#define F367_OFDM_TSINS_XXXERR 0xF2770004 -+#define F367_OFDM_TSINS_MATYPE 0xF2770002 -+#define F367_OFDM_TSINS_UPL 0xF2770001 -+ -+/* TSINSDELL */ -+#define R367_OFDM_TSINSDELL 0xF278 -+#define F367_OFDM_TSINS_DFL 0xF2780080 -+#define F367_OFDM_TSINS_SYNCD 0xF2780040 -+#define F367_OFDM_TSINS_BLOCLEN 0xF2780020 -+#define F367_OFDM_TSINS_SIGPCOUNT 0xF2780010 -+#define F367_OFDM_TSINS_FIFO 0xF2780008 -+#define F367_OFDM_TSINS_REALPACK 0xF2780004 -+#define F367_OFDM_TSINS_TSCONFIG 0xF2780002 -+#define F367_OFDM_TSINS_LATENCY 0xF2780001 -+ -+/* TSDIVN */ -+#define R367_OFDM_TSDIVN 0xF279 -+#define F367_OFDM_TSFIFO_LOWSPEED 0xF2790080 -+#define F367_OFDM_BYTE_OVERSAMPLING 0xF2790070 -+#define F367_OFDM_TSMANUAL_PACKETNBR 0xF279000F -+ -+/* TSDIVPM */ -+#define R367_OFDM_TSDIVPM 0xF27A -+#define F367_OFDM_TSMANUAL_P_HI 0xF27A00FF -+ -+/* TSDIVPL */ -+#define R367_OFDM_TSDIVPL 0xF27B -+#define F367_OFDM_TSMANUAL_P_LO 0xF27B00FF -+ -+/* TSDIVQM */ -+#define R367_OFDM_TSDIVQM 0xF27C -+#define F367_OFDM_TSMANUAL_Q_HI 0xF27C00FF -+ -+/* TSDIVQL */ -+#define R367_OFDM_TSDIVQL 0xF27D -+#define F367_OFDM_TSMANUAL_Q_LO 0xF27D00FF -+ -+/* TSDILSTKM */ -+#define R367_OFDM_TSDILSTKM 0xF27E -+#define F367_OFDM_TSFIFO_DILSTK_HI 0xF27E00FF -+ -+/* TSDILSTKL */ -+#define R367_OFDM_TSDILSTKL 0xF27F -+#define F367_OFDM_TSFIFO_DILSTK_LO 0xF27F00FF -+ -+/* TSSPEED */ -+#define R367_OFDM_TSSPEED 0xF280 -+#define F367_OFDM_TSFIFO_OUTSPEED 0xF28000FF -+ -+/* TSSTATUS */ -+#define R367_OFDM_TSSTATUS 0xF281 -+#define F367_OFDM_TSFIFO_LINEOK 0xF2810080 -+#define F367_OFDM_TSFIFO_ERROR 0xF2810040 -+#define F367_OFDM_TSFIFO_DATA7 0xF2810020 -+#define F367_OFDM_TSFIFO_NOSYNC 0xF2810010 -+#define F367_OFDM_ISCR_INITIALIZED 0xF2810008 -+#define F367_OFDM_ISCR_UPDATED 0xF2810004 -+#define F367_OFDM_SOFFIFO_UNREGUL 0xF2810002 -+#define F367_OFDM_DIL_READY 0xF2810001 -+ -+/* TSSTATUS2 */ -+#define R367_OFDM_TSSTATUS2 0xF282 -+#define F367_OFDM_TSFIFO_DEMODSEL 0xF2820080 -+#define F367_OFDM_TSFIFOSPEED_STORE 0xF2820040 -+#define F367_OFDM_DILXX_RESET 0xF2820020 -+#define F367_OFDM_TSSERIAL_IMPOSSIBLE 0xF2820010 -+#define F367_OFDM_TSFIFO_UNDERSPEED 0xF2820008 -+#define F367_OFDM_BITSPEED_EVENT 0xF2820004 -+#define F367_OFDM_UL_SCRAMBDETECT 0xF2820002 -+#define F367_OFDM_ULDTV67_FALSELOCK 0xF2820001 -+ -+/* TSBITRATEM */ -+#define R367_OFDM_TSBITRATEM 0xF283 -+#define F367_OFDM_TSFIFO_BITRATE_HI 0xF28300FF -+ -+/* TSBITRATEL */ -+#define R367_OFDM_TSBITRATEL 0xF284 -+#define F367_OFDM_TSFIFO_BITRATE_LO 0xF28400FF -+ -+/* TSPACKLENM */ -+#define R367_OFDM_TSPACKLENM 0xF285 -+#define F367_OFDM_TSFIFO_PACKCPT 0xF28500E0 -+#define F367_OFDM_DIL_RPLEN_HI 0xF285001F -+ -+/* TSPACKLENL */ -+#define R367_OFDM_TSPACKLENL 0xF286 -+#define F367_OFDM_DIL_RPLEN_LO 0xF28600FF -+ -+/* TSBLOCLENM */ -+#define R367_OFDM_TSBLOCLENM 0xF287 -+#define F367_OFDM_TSFIFO_PFLEN_HI 0xF28700FF -+ -+/* TSBLOCLENL */ -+#define R367_OFDM_TSBLOCLENL 0xF288 -+#define F367_OFDM_TSFIFO_PFLEN_LO 0xF28800FF -+ -+/* TSDLYH */ -+#define R367_OFDM_TSDLYH 0xF289 -+#define F367_OFDM_SOFFIFO_TSTIMEVALID 0xF2890080 -+#define F367_OFDM_SOFFIFO_SPEEDUP 0xF2890040 -+#define F367_OFDM_SOFFIFO_STOP 0xF2890020 -+#define F367_OFDM_SOFFIFO_REGULATED 0xF2890010 -+#define F367_OFDM_SOFFIFO_REALSBOFF_HI 0xF289000F -+ -+/* TSDLYM */ -+#define R367_OFDM_TSDLYM 0xF28A -+#define F367_OFDM_SOFFIFO_REALSBOFF_MED 0xF28A00FF -+ -+/* TSDLYL */ -+#define R367_OFDM_TSDLYL 0xF28B -+#define F367_OFDM_SOFFIFO_REALSBOFF_LO 0xF28B00FF -+ -+/* TSNPDAV */ -+#define R367_OFDM_TSNPDAV 0xF28C -+#define F367_OFDM_TSNPD_AVERAGE 0xF28C00FF -+ -+/* TSBUFSTATH */ -+#define R367_OFDM_TSBUFSTATH 0xF28D -+#define F367_OFDM_TSISCR_3BYTES 0xF28D0080 -+#define F367_OFDM_TSISCR_NEWDATA 0xF28D0040 -+#define F367_OFDM_TSISCR_BUFSTAT_HI 0xF28D003F -+ -+/* TSBUFSTATM */ -+#define R367_OFDM_TSBUFSTATM 0xF28E -+#define F367_OFDM_TSISCR_BUFSTAT_MED 0xF28E00FF -+ -+/* TSBUFSTATL */ -+#define R367_OFDM_TSBUFSTATL 0xF28F -+#define F367_OFDM_TSISCR_BUFSTAT_LO 0xF28F00FF -+ -+/* TSDEBUGM */ -+#define R367_OFDM_TSDEBUGM 0xF290 -+#define F367_OFDM_TSFIFO_ILLPACKET 0xF2900080 -+#define F367_OFDM_DIL_NOSYNC 0xF2900040 -+#define F367_OFDM_DIL_ISCR 0xF2900020 -+#define F367_OFDM_DILOUT_BSYNCB 0xF2900010 -+#define F367_OFDM_TSFIFO_EMPTYPKT 0xF2900008 -+#define F367_OFDM_TSFIFO_EMPTYRD 0xF2900004 -+#define F367_OFDM_SOFFIFO_STOPM 0xF2900002 -+#define F367_OFDM_SOFFIFO_SPEEDUPM 0xF2900001 -+ -+/* TSDEBUGL */ -+#define R367_OFDM_TSDEBUGL 0xF291 -+#define F367_OFDM_TSFIFO_PACKLENFAIL 0xF2910080 -+#define F367_OFDM_TSFIFO_SYNCBFAIL 0xF2910040 -+#define F367_OFDM_TSFIFO_VITLIBRE 0xF2910020 -+#define F367_OFDM_TSFIFO_BOOSTSPEEDM 0xF2910010 -+#define F367_OFDM_TSFIFO_UNDERSPEEDM 0xF2910008 -+#define F367_OFDM_TSFIFO_ERROR_EVNT 0xF2910004 -+#define F367_OFDM_TSFIFO_FULL 0xF2910002 -+#define F367_OFDM_TSFIFO_OVERFLOWM 0xF2910001 -+ -+/* TSDLYSETH */ -+#define R367_OFDM_TSDLYSETH 0xF292 -+#define F367_OFDM_SOFFIFO_OFFSET 0xF29200E0 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_HI 0xF292001F -+ -+/* TSDLYSETM */ -+#define R367_OFDM_TSDLYSETM 0xF293 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_MED 0xF29300FF -+ -+/* TSDLYSETL */ -+#define R367_OFDM_TSDLYSETL 0xF294 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_LO 0xF29400FF -+ -+/* TSOBSCFG */ -+#define R367_OFDM_TSOBSCFG 0xF295 -+#define F367_OFDM_TSFIFO_OBSCFG 0xF29500FF -+ -+/* TSOBSM */ -+#define R367_OFDM_TSOBSM 0xF296 -+#define F367_OFDM_TSFIFO_OBSDATA_HI 0xF29600FF -+ -+/* TSOBSL */ -+#define R367_OFDM_TSOBSL 0xF297 -+#define F367_OFDM_TSFIFO_OBSDATA_LO 0xF29700FF -+ -+/* ERRCTRL1 */ -+#define R367_OFDM_ERRCTRL1 0xF298 -+#define F367_OFDM_ERR_SRC1 0xF29800F0 -+#define F367_OFDM_ERRCTRL1_3 0xF2980008 -+#define F367_OFDM_NUM_EVT1 0xF2980007 -+ -+/* ERRCNT1H */ -+#define R367_OFDM_ERRCNT1H 0xF299 -+#define F367_OFDM_ERRCNT1_OLDVALUE 0xF2990080 -+#define F367_OFDM_ERR_CNT1 0xF299007F -+ -+/* ERRCNT1M */ -+#define R367_OFDM_ERRCNT1M 0xF29A -+#define F367_OFDM_ERR_CNT1_HI 0xF29A00FF -+ -+/* ERRCNT1L */ -+#define R367_OFDM_ERRCNT1L 0xF29B -+#define F367_OFDM_ERR_CNT1_LO 0xF29B00FF -+ -+/* ERRCTRL2 */ -+#define R367_OFDM_ERRCTRL2 0xF29C -+#define F367_OFDM_ERR_SRC2 0xF29C00F0 -+#define F367_OFDM_ERRCTRL2_3 0xF29C0008 -+#define F367_OFDM_NUM_EVT2 0xF29C0007 -+ -+/* ERRCNT2H */ -+#define R367_OFDM_ERRCNT2H 0xF29D -+#define F367_OFDM_ERRCNT2_OLDVALUE 0xF29D0080 -+#define F367_OFDM_ERR_CNT2_HI 0xF29D007F -+ -+/* ERRCNT2M */ -+#define R367_OFDM_ERRCNT2M 0xF29E -+#define F367_OFDM_ERR_CNT2_MED 0xF29E00FF -+ -+/* ERRCNT2L */ -+#define R367_OFDM_ERRCNT2L 0xF29F -+#define F367_OFDM_ERR_CNT2_LO 0xF29F00FF -+ -+/* FECSPY */ -+#define R367_OFDM_FECSPY 0xF2A0 -+#define F367_OFDM_SPY_ENABLE 0xF2A00080 -+#define F367_OFDM_NO_SYNCBYTE 0xF2A00040 -+#define F367_OFDM_SERIAL_MODE 0xF2A00020 -+#define F367_OFDM_UNUSUAL_PACKET 0xF2A00010 -+#define F367_OFDM_BERMETER_DATAMODE 0xF2A0000C -+#define F367_OFDM_BERMETER_LMODE 0xF2A00002 -+#define F367_OFDM_BERMETER_RESET 0xF2A00001 -+ -+/* FSPYCFG */ -+#define R367_OFDM_FSPYCFG 0xF2A1 -+#define F367_OFDM_FECSPY_INPUT 0xF2A100C0 -+#define F367_OFDM_RST_ON_ERROR 0xF2A10020 -+#define F367_OFDM_ONE_SHOT 0xF2A10010 -+#define F367_OFDM_I2C_MOD 0xF2A1000C -+#define F367_OFDM_SPY_HYSTERESIS 0xF2A10003 -+ -+/* FSPYDATA */ -+#define R367_OFDM_FSPYDATA 0xF2A2 -+#define F367_OFDM_SPY_STUFFING 0xF2A20080 -+#define F367_OFDM_NOERROR_PKTJITTER 0xF2A20040 -+#define F367_OFDM_SPY_CNULLPKT 0xF2A20020 -+#define F367_OFDM_SPY_OUTDATA_MODE 0xF2A2001F -+ -+/* FSPYOUT */ -+#define R367_OFDM_FSPYOUT 0xF2A3 -+#define F367_OFDM_FSPY_DIRECT 0xF2A30080 -+#define F367_OFDM_FSPYOUT_6 0xF2A30040 -+#define F367_OFDM_SPY_OUTDATA_BUS 0xF2A30038 -+#define F367_OFDM_STUFF_MODE 0xF2A30007 -+ -+/* FSTATUS */ -+#define R367_OFDM_FSTATUS 0xF2A4 -+#define F367_OFDM_SPY_ENDSIM 0xF2A40080 -+#define F367_OFDM_VALID_SIM 0xF2A40040 -+#define F367_OFDM_FOUND_SIGNAL 0xF2A40020 -+#define F367_OFDM_DSS_SYNCBYTE 0xF2A40010 -+#define F367_OFDM_RESULT_STATE 0xF2A4000F -+ -+/* FGOODPACK */ -+#define R367_OFDM_FGOODPACK 0xF2A5 -+#define F367_OFDM_FGOOD_PACKET 0xF2A500FF -+ -+/* FPACKCNT */ -+#define R367_OFDM_FPACKCNT 0xF2A6 -+#define F367_OFDM_FPACKET_COUNTER 0xF2A600FF -+ -+/* FSPYMISC */ -+#define R367_OFDM_FSPYMISC 0xF2A7 -+#define F367_OFDM_FLABEL_COUNTER 0xF2A700FF -+ -+/* FBERCPT4 */ -+#define R367_OFDM_FBERCPT4 0xF2A8 -+#define F367_OFDM_FBERMETER_CPT5 0xF2A800FF -+ -+/* FBERCPT3 */ -+#define R367_OFDM_FBERCPT3 0xF2A9 -+#define F367_OFDM_FBERMETER_CPT4 0xF2A900FF -+ -+/* FBERCPT2 */ -+#define R367_OFDM_FBERCPT2 0xF2AA -+#define F367_OFDM_FBERMETER_CPT3 0xF2AA00FF -+ -+/* FBERCPT1 */ -+#define R367_OFDM_FBERCPT1 0xF2AB -+#define F367_OFDM_FBERMETER_CPT2 0xF2AB00FF -+ -+/* FBERCPT0 */ -+#define R367_OFDM_FBERCPT0 0xF2AC -+#define F367_OFDM_FBERMETER_CPT1 0xF2AC00FF -+ -+/* FBERERR2 */ -+#define R367_OFDM_FBERERR2 0xF2AD -+#define F367_OFDM_FBERMETER_ERR_HI 0xF2AD00FF -+ -+/* FBERERR1 */ -+#define R367_OFDM_FBERERR1 0xF2AE -+#define F367_OFDM_FBERMETER_ERR_MED 0xF2AE00FF -+ -+/* FBERERR0 */ -+#define R367_OFDM_FBERERR0 0xF2AF -+#define F367_OFDM_FBERMETER_ERR_LO 0xF2AF00FF -+ -+/* FSTATESM */ -+#define R367_OFDM_FSTATESM 0xF2B0 -+#define F367_OFDM_RSTATE_F 0xF2B00080 -+#define F367_OFDM_RSTATE_E 0xF2B00040 -+#define F367_OFDM_RSTATE_D 0xF2B00020 -+#define F367_OFDM_RSTATE_C 0xF2B00010 -+#define F367_OFDM_RSTATE_B 0xF2B00008 -+#define F367_OFDM_RSTATE_A 0xF2B00004 -+#define F367_OFDM_RSTATE_9 0xF2B00002 -+#define F367_OFDM_RSTATE_8 0xF2B00001 -+ -+/* FSTATESL */ -+#define R367_OFDM_FSTATESL 0xF2B1 -+#define F367_OFDM_RSTATE_7 0xF2B10080 -+#define F367_OFDM_RSTATE_6 0xF2B10040 -+#define F367_OFDM_RSTATE_5 0xF2B10020 -+#define F367_OFDM_RSTATE_4 0xF2B10010 -+#define F367_OFDM_RSTATE_3 0xF2B10008 -+#define F367_OFDM_RSTATE_2 0xF2B10004 -+#define F367_OFDM_RSTATE_1 0xF2B10002 -+#define F367_OFDM_RSTATE_0 0xF2B10001 -+ -+/* FSPYBER */ -+#define R367_OFDM_FSPYBER 0xF2B2 -+#define F367_OFDM_FSPYBER_7 0xF2B20080 -+#define F367_OFDM_FSPYOBS_XORREAD 0xF2B20040 -+#define F367_OFDM_FSPYBER_OBSMODE 0xF2B20020 -+#define F367_OFDM_FSPYBER_SYNCBYTE 0xF2B20010 -+#define F367_OFDM_FSPYBER_UNSYNC 0xF2B20008 -+#define F367_OFDM_FSPYBER_CTIME 0xF2B20007 -+ -+/* FSPYDISTM */ -+#define R367_OFDM_FSPYDISTM 0xF2B3 -+#define F367_OFDM_PKTTIME_DISTANCE_HI 0xF2B300FF -+ -+/* FSPYDISTL */ -+#define R367_OFDM_FSPYDISTL 0xF2B4 -+#define F367_OFDM_PKTTIME_DISTANCE_LO 0xF2B400FF -+ -+/* FSPYOBS7 */ -+#define R367_OFDM_FSPYOBS7 0xF2B8 -+#define F367_OFDM_FSPYOBS_SPYFAIL 0xF2B80080 -+#define F367_OFDM_FSPYOBS_SPYFAIL1 0xF2B80040 -+#define F367_OFDM_FSPYOBS_ERROR 0xF2B80020 -+#define F367_OFDM_FSPYOBS_STROUT 0xF2B80010 -+#define F367_OFDM_FSPYOBS_RESULTSTATE1 0xF2B8000F -+ -+/* FSPYOBS6 */ -+#define R367_OFDM_FSPYOBS6 0xF2B9 -+#define F367_OFDM_FSPYOBS_RESULTSTATE0 0xF2B900F0 -+#define F367_OFDM_FSPYOBS_RESULTSTATEM1 0xF2B9000F -+ -+/* FSPYOBS5 */ -+#define R367_OFDM_FSPYOBS5 0xF2BA -+#define F367_OFDM_FSPYOBS_BYTEOFPACKET1 0xF2BA00FF -+ -+/* FSPYOBS4 */ -+#define R367_OFDM_FSPYOBS4 0xF2BB -+#define F367_OFDM_FSPYOBS_BYTEVALUE1 0xF2BB00FF -+ -+/* FSPYOBS3 */ -+#define R367_OFDM_FSPYOBS3 0xF2BC -+#define F367_OFDM_FSPYOBS_DATA1 0xF2BC00FF -+ -+/* FSPYOBS2 */ -+#define R367_OFDM_FSPYOBS2 0xF2BD -+#define F367_OFDM_FSPYOBS_DATA0 0xF2BD00FF -+ -+/* FSPYOBS1 */ -+#define R367_OFDM_FSPYOBS1 0xF2BE -+#define F367_OFDM_FSPYOBS_DATAM1 0xF2BE00FF -+ -+/* FSPYOBS0 */ -+#define R367_OFDM_FSPYOBS0 0xF2BF -+#define F367_OFDM_FSPYOBS_DATAM2 0xF2BF00FF -+ -+/* SFDEMAP */ -+#define R367_OFDM_SFDEMAP 0xF2C0 -+#define F367_OFDM_SFDEMAP_7 0xF2C00080 -+#define F367_OFDM_SFEC_K_DIVIDER_VIT 0xF2C0007F -+ -+/* SFERROR */ -+#define R367_OFDM_SFERROR 0xF2C1 -+#define F367_OFDM_SFEC_REGERR_VIT 0xF2C100FF -+ -+/* SFAVSR */ -+#define R367_OFDM_SFAVSR 0xF2C2 -+#define F367_OFDM_SFEC_SUMERRORS 0xF2C20080 -+#define F367_OFDM_SERROR_MAXMODE 0xF2C20040 -+#define F367_OFDM_SN_SFEC 0xF2C20030 -+#define F367_OFDM_KDIV_MODE_SFEC 0xF2C2000C -+#define F367_OFDM_SFAVSR_1 0xF2C20002 -+#define F367_OFDM_SFAVSR_0 0xF2C20001 -+ -+/* SFECSTATUS */ -+#define R367_OFDM_SFECSTATUS 0xF2C3 -+#define F367_OFDM_SFEC_ON 0xF2C30080 -+#define F367_OFDM_SFSTATUS_6 0xF2C30040 -+#define F367_OFDM_SFSTATUS_5 0xF2C30020 -+#define F367_OFDM_SFSTATUS_4 0xF2C30010 -+#define F367_OFDM_LOCKEDSFEC 0xF2C30008 -+#define F367_OFDM_SFEC_DELOCK 0xF2C30004 -+#define F367_OFDM_SFEC_DEMODSEL1 0xF2C30002 -+#define F367_OFDM_SFEC_OVFON 0xF2C30001 -+ -+/* SFKDIV12 */ -+#define R367_OFDM_SFKDIV12 0xF2C4 -+#define F367_OFDM_SFECKDIV12_MAN 0xF2C40080 -+#define F367_OFDM_SFEC_K_DIVIDER_12 0xF2C4007F -+ -+/* SFKDIV23 */ -+#define R367_OFDM_SFKDIV23 0xF2C5 -+#define F367_OFDM_SFECKDIV23_MAN 0xF2C50080 -+#define F367_OFDM_SFEC_K_DIVIDER_23 0xF2C5007F -+ -+/* SFKDIV34 */ -+#define R367_OFDM_SFKDIV34 0xF2C6 -+#define F367_OFDM_SFECKDIV34_MAN 0xF2C60080 -+#define F367_OFDM_SFEC_K_DIVIDER_34 0xF2C6007F -+ -+/* SFKDIV56 */ -+#define R367_OFDM_SFKDIV56 0xF2C7 -+#define F367_OFDM_SFECKDIV56_MAN 0xF2C70080 -+#define F367_OFDM_SFEC_K_DIVIDER_56 0xF2C7007F -+ -+/* SFKDIV67 */ -+#define R367_OFDM_SFKDIV67 0xF2C8 -+#define F367_OFDM_SFECKDIV67_MAN 0xF2C80080 -+#define F367_OFDM_SFEC_K_DIVIDER_67 0xF2C8007F -+ -+/* SFKDIV78 */ -+#define R367_OFDM_SFKDIV78 0xF2C9 -+#define F367_OFDM_SFECKDIV78_MAN 0xF2C90080 -+#define F367_OFDM_SFEC_K_DIVIDER_78 0xF2C9007F -+ -+/* SFDILSTKM */ -+#define R367_OFDM_SFDILSTKM 0xF2CA -+#define F367_OFDM_SFEC_PACKCPT 0xF2CA00E0 -+#define F367_OFDM_SFEC_DILSTK_HI 0xF2CA001F -+ -+/* SFDILSTKL */ -+#define R367_OFDM_SFDILSTKL 0xF2CB -+#define F367_OFDM_SFEC_DILSTK_LO 0xF2CB00FF -+ -+/* SFSTATUS */ -+#define R367_OFDM_SFSTATUS 0xF2CC -+#define F367_OFDM_SFEC_LINEOK 0xF2CC0080 -+#define F367_OFDM_SFEC_ERROR 0xF2CC0040 -+#define F367_OFDM_SFEC_DATA7 0xF2CC0020 -+#define F367_OFDM_SFEC_OVERFLOW 0xF2CC0010 -+#define F367_OFDM_SFEC_DEMODSEL2 0xF2CC0008 -+#define F367_OFDM_SFEC_NOSYNC 0xF2CC0004 -+#define F367_OFDM_SFEC_UNREGULA 0xF2CC0002 -+#define F367_OFDM_SFEC_READY 0xF2CC0001 -+ -+/* SFDLYH */ -+#define R367_OFDM_SFDLYH 0xF2CD -+#define F367_OFDM_SFEC_TSTIMEVALID 0xF2CD0080 -+#define F367_OFDM_SFEC_SPEEDUP 0xF2CD0040 -+#define F367_OFDM_SFEC_STOP 0xF2CD0020 -+#define F367_OFDM_SFEC_REGULATED 0xF2CD0010 -+#define F367_OFDM_SFEC_REALSYMBOFFSET 0xF2CD000F -+ -+/* SFDLYM */ -+#define R367_OFDM_SFDLYM 0xF2CE -+#define F367_OFDM_SFEC_REALSYMBOFFSET_HI 0xF2CE00FF -+ -+/* SFDLYL */ -+#define R367_OFDM_SFDLYL 0xF2CF -+#define F367_OFDM_SFEC_REALSYMBOFFSET_LO 0xF2CF00FF -+ -+/* SFDLYSETH */ -+#define R367_OFDM_SFDLYSETH 0xF2D0 -+#define F367_OFDM_SFEC_OFFSET 0xF2D000E0 -+#define F367_OFDM_SFECDLYSETH_4 0xF2D00010 -+#define F367_OFDM_RST_SFEC 0xF2D00008 -+#define F367_OFDM_SFECDLYSETH_2 0xF2D00004 -+#define F367_OFDM_SFEC_DISABLE 0xF2D00002 -+#define F367_OFDM_SFEC_UNREGUL 0xF2D00001 -+ -+/* SFDLYSETM */ -+#define R367_OFDM_SFDLYSETM 0xF2D1 -+#define F367_OFDM_SFECDLYSETM_7 0xF2D10080 -+#define F367_OFDM_SFEC_SYMBOFFSET_HI 0xF2D1007F -+ -+/* SFDLYSETL */ -+#define R367_OFDM_SFDLYSETL 0xF2D2 -+#define F367_OFDM_SFEC_SYMBOFFSET_LO 0xF2D200FF -+ -+/* SFOBSCFG */ -+#define R367_OFDM_SFOBSCFG 0xF2D3 -+#define F367_OFDM_SFEC_OBSCFG 0xF2D300FF -+ -+/* SFOBSM */ -+#define R367_OFDM_SFOBSM 0xF2D4 -+#define F367_OFDM_SFEC_OBSDATA_HI 0xF2D400FF -+ -+/* SFOBSL */ -+#define R367_OFDM_SFOBSL 0xF2D5 -+#define F367_OFDM_SFEC_OBSDATA_LO 0xF2D500FF -+ -+/* SFECINFO */ -+#define R367_OFDM_SFECINFO 0xF2D6 -+#define F367_OFDM_SFECINFO_7 0xF2D60080 -+#define F367_OFDM_SFEC_SYNCDLSB 0xF2D60070 -+#define F367_OFDM_SFCE_S1CPHASE 0xF2D6000F -+ -+/* SFERRCTRL */ -+#define R367_OFDM_SFERRCTRL 0xF2D8 -+#define F367_OFDM_SFEC_ERR_SOURCE 0xF2D800F0 -+#define F367_OFDM_SFERRCTRL_3 0xF2D80008 -+#define F367_OFDM_SFEC_NUM_EVENT 0xF2D80007 -+ -+/* SFERRCNTH */ -+#define R367_OFDM_SFERRCNTH 0xF2D9 -+#define F367_OFDM_SFERRC_OLDVALUE 0xF2D90080 -+#define F367_OFDM_SFEC_ERR_CNT 0xF2D9007F -+ -+/* SFERRCNTM */ -+#define R367_OFDM_SFERRCNTM 0xF2DA -+#define F367_OFDM_SFEC_ERR_CNT_HI 0xF2DA00FF -+ -+/* SFERRCNTL */ -+#define R367_OFDM_SFERRCNTL 0xF2DB -+#define F367_OFDM_SFEC_ERR_CNT_LO 0xF2DB00FF -+ -+/* SYMBRATEM */ -+#define R367_OFDM_SYMBRATEM 0xF2E0 -+#define F367_OFDM_DEFGEN_SYMBRATE_HI 0xF2E000FF -+ -+/* SYMBRATEL */ -+#define R367_OFDM_SYMBRATEL 0xF2E1 -+#define F367_OFDM_DEFGEN_SYMBRATE_LO 0xF2E100FF -+ -+/* SYMBSTATUS */ -+#define R367_OFDM_SYMBSTATUS 0xF2E2 -+#define F367_OFDM_SYMBDLINE2_OFF 0xF2E20080 -+#define F367_OFDM_SDDL_REINIT1 0xF2E20040 -+#define F367_OFDM_SDD_REINIT1 0xF2E20020 -+#define F367_OFDM_TOKENID_ERROR 0xF2E20010 -+#define F367_OFDM_SYMBRATE_OVERFLOW 0xF2E20008 -+#define F367_OFDM_SYMBRATE_UNDERFLOW 0xF2E20004 -+#define F367_OFDM_TOKENID_RSTEVENT 0xF2E20002 -+#define F367_OFDM_TOKENID_RESET1 0xF2E20001 -+ -+/* SYMBCFG */ -+#define R367_OFDM_SYMBCFG 0xF2E3 -+#define F367_OFDM_SYMBCFG_7 0xF2E30080 -+#define F367_OFDM_SYMBCFG_6 0xF2E30040 -+#define F367_OFDM_SYMBCFG_5 0xF2E30020 -+#define F367_OFDM_SYMBCFG_4 0xF2E30010 -+#define F367_OFDM_SYMRATE_FSPEED 0xF2E3000C -+#define F367_OFDM_SYMRATE_SSPEED 0xF2E30003 -+ -+/* SYMBFIFOM */ -+#define R367_OFDM_SYMBFIFOM 0xF2E4 -+#define F367_OFDM_SYMBFIFOM_7 0xF2E40080 -+#define F367_OFDM_SYMBFIFOM_6 0xF2E40040 -+#define F367_OFDM_DEFGEN_SYMFIFO_HI 0xF2E4003F -+ -+/* SYMBFIFOL */ -+#define R367_OFDM_SYMBFIFOL 0xF2E5 -+#define F367_OFDM_DEFGEN_SYMFIFO_LO 0xF2E500FF -+ -+/* SYMBOFFSM */ -+#define R367_OFDM_SYMBOFFSM 0xF2E6 -+#define F367_OFDM_TOKENID_RESET2 0xF2E60080 -+#define F367_OFDM_SDDL_REINIT2 0xF2E60040 -+#define F367_OFDM_SDD_REINIT2 0xF2E60020 -+#define F367_OFDM_SYMBOFFSM_4 0xF2E60010 -+#define F367_OFDM_SYMBOFFSM_3 0xF2E60008 -+#define F367_OFDM_DEFGEN_SYMBOFFSET_HI 0xF2E60007 -+ -+/* SYMBOFFSL */ -+#define R367_OFDM_SYMBOFFSL 0xF2E7 -+#define F367_OFDM_DEFGEN_SYMBOFFSET_LO 0xF2E700FF -+ -+/* DEBUG_LT4 */ -+#define R367_DEBUG_LT4 0xF400 -+#define F367_F_DEBUG_LT4 0xF40000FF -+ -+/* DEBUG_LT5 */ -+#define R367_DEBUG_LT5 0xF401 -+#define F367_F_DEBUG_LT5 0xF40100FF -+ -+/* DEBUG_LT6 */ -+#define R367_DEBUG_LT6 0xF402 -+#define F367_F_DEBUG_LT6 0xF40200FF -+ -+/* DEBUG_LT7 */ -+#define R367_DEBUG_LT7 0xF403 -+#define F367_F_DEBUG_LT7 0xF40300FF -+ -+/* DEBUG_LT8 */ -+#define R367_DEBUG_LT8 0xF404 -+#define F367_F_DEBUG_LT8 0xF40400FF -+ -+/* DEBUG_LT9 */ -+#define R367_DEBUG_LT9 0xF405 -+#define F367_F_DEBUG_LT9 0xF40500FF -+ -+/* CTRL_1 */ -+#define R367_QAM_CTRL_1 0xF402 -+#define F367_QAM_SOFT_RST 0xF4020080 -+#define F367_QAM_EQU_RST 0xF4020008 -+#define F367_QAM_CRL_RST 0xF4020004 -+#define F367_QAM_TRL_RST 0xF4020002 -+#define F367_QAM_AGC_RST 0xF4020001 -+ -+/* CTRL_2 */ -+#define R367_QAM_CTRL_2 0xF403 -+#define F367_QAM_DEINT_RST 0xF4030008 -+#define F367_QAM_RS_RST 0xF4030004 -+ -+/* IT_STATUS1 */ -+#define R367_QAM_IT_STATUS1 0xF408 -+#define F367_QAM_SWEEP_OUT 0xF4080080 -+#define F367_QAM_FSM_CRL 0xF4080040 -+#define F367_QAM_CRL_LOCK 0xF4080020 -+#define F367_QAM_MFSM 0xF4080010 -+#define F367_QAM_TRL_LOCK 0xF4080008 -+#define F367_QAM_TRL_AGC_LIMIT 0xF4080004 -+#define F367_QAM_ADJ_AGC_LOCK 0xF4080002 -+#define F367_QAM_AGC_QAM_LOCK 0xF4080001 -+ -+/* IT_STATUS2 */ -+#define R367_QAM_IT_STATUS2 0xF409 -+#define F367_QAM_TSMF_CNT 0xF4090080 -+#define F367_QAM_TSMF_EOF 0xF4090040 -+#define F367_QAM_TSMF_RDY 0xF4090020 -+#define F367_QAM_FEC_NOCORR 0xF4090010 -+#define F367_QAM_SYNCSTATE 0xF4090008 -+#define F367_QAM_DEINT_LOCK 0xF4090004 -+#define F367_QAM_FADDING_FRZ 0xF4090002 -+#define F367_QAM_TAPMON_ALARM 0xF4090001 -+ -+/* IT_EN1 */ -+#define R367_QAM_IT_EN1 0xF40A -+#define F367_QAM_SWEEP_OUTE 0xF40A0080 -+#define F367_QAM_FSM_CRLE 0xF40A0040 -+#define F367_QAM_CRL_LOCKE 0xF40A0020 -+#define F367_QAM_MFSME 0xF40A0010 -+#define F367_QAM_TRL_LOCKE 0xF40A0008 -+#define F367_QAM_TRL_AGC_LIMITE 0xF40A0004 -+#define F367_QAM_ADJ_AGC_LOCKE 0xF40A0002 -+#define F367_QAM_AGC_LOCKE 0xF40A0001 -+ -+/* IT_EN2 */ -+#define R367_QAM_IT_EN2 0xF40B -+#define F367_QAM_TSMF_CNTE 0xF40B0080 -+#define F367_QAM_TSMF_EOFE 0xF40B0040 -+#define F367_QAM_TSMF_RDYE 0xF40B0020 -+#define F367_QAM_FEC_NOCORRE 0xF40B0010 -+#define F367_QAM_SYNCSTATEE 0xF40B0008 -+#define F367_QAM_DEINT_LOCKE 0xF40B0004 -+#define F367_QAM_FADDING_FRZE 0xF40B0002 -+#define F367_QAM_TAPMON_ALARME 0xF40B0001 -+ -+/* CTRL_STATUS */ -+#define R367_QAM_CTRL_STATUS 0xF40C -+#define F367_QAM_QAMFEC_LOCK 0xF40C0004 -+#define F367_QAM_TSMF_LOCK 0xF40C0002 -+#define F367_QAM_TSMF_ERROR 0xF40C0001 -+ -+/* TEST_CTL */ -+#define R367_QAM_TEST_CTL 0xF40F -+#define F367_QAM_TST_BLK_SEL 0xF40F0060 -+#define F367_QAM_TST_BUS_SEL 0xF40F001F -+ -+/* AGC_CTL */ -+#define R367_QAM_AGC_CTL 0xF410 -+#define F367_QAM_AGC_LCK_TH 0xF41000F0 -+#define F367_QAM_AGC_ACCUMRSTSEL 0xF4100007 -+ -+/* AGC_IF_CFG */ -+#define R367_QAM_AGC_IF_CFG 0xF411 -+#define F367_QAM_AGC_IF_BWSEL 0xF41100F0 -+#define F367_QAM_AGC_IF_FREEZE 0xF4110002 -+ -+/* AGC_RF_CFG */ -+#define R367_QAM_AGC_RF_CFG 0xF412 -+#define F367_QAM_AGC_RF_BWSEL 0xF4120070 -+#define F367_QAM_AGC_RF_FREEZE 0xF4120002 -+ -+/* AGC_PWM_CFG */ -+#define R367_QAM_AGC_PWM_CFG 0xF413 -+#define F367_QAM_AGC_RF_PWM_TST 0xF4130080 -+#define F367_QAM_AGC_RF_PWM_INV 0xF4130040 -+#define F367_QAM_AGC_IF_PWM_TST 0xF4130008 -+#define F367_QAM_AGC_IF_PWM_INV 0xF4130004 -+#define F367_QAM_AGC_PWM_CLKDIV 0xF4130003 -+ -+/* AGC_PWR_REF_L */ -+#define R367_QAM_AGC_PWR_REF_L 0xF414 -+#define F367_QAM_AGC_PWRREF_LO 0xF41400FF -+ -+/* AGC_PWR_REF_H */ -+#define R367_QAM_AGC_PWR_REF_H 0xF415 -+#define F367_QAM_AGC_PWRREF_HI 0xF4150003 -+ -+/* AGC_RF_TH_L */ -+#define R367_QAM_AGC_RF_TH_L 0xF416 -+#define F367_QAM_AGC_RF_TH_LO 0xF41600FF -+ -+/* AGC_RF_TH_H */ -+#define R367_QAM_AGC_RF_TH_H 0xF417 -+#define F367_QAM_AGC_RF_TH_HI 0xF417000F -+ -+/* AGC_IF_LTH_L */ -+#define R367_QAM_AGC_IF_LTH_L 0xF418 -+#define F367_QAM_AGC_IF_THLO_LO 0xF41800FF -+ -+/* AGC_IF_LTH_H */ -+#define R367_QAM_AGC_IF_LTH_H 0xF419 -+#define F367_QAM_AGC_IF_THLO_HI 0xF419000F -+ -+/* AGC_IF_HTH_L */ -+#define R367_QAM_AGC_IF_HTH_L 0xF41A -+#define F367_QAM_AGC_IF_THHI_LO 0xF41A00FF -+ -+/* AGC_IF_HTH_H */ -+#define R367_QAM_AGC_IF_HTH_H 0xF41B -+#define F367_QAM_AGC_IF_THHI_HI 0xF41B000F -+ -+/* AGC_PWR_RD_L */ -+#define R367_QAM_AGC_PWR_RD_L 0xF41C -+#define F367_QAM_AGC_PWR_WORD_LO 0xF41C00FF -+ -+/* AGC_PWR_RD_M */ -+#define R367_QAM_AGC_PWR_RD_M 0xF41D -+#define F367_QAM_AGC_PWR_WORD_ME 0xF41D00FF -+ -+/* AGC_PWR_RD_H */ -+#define R367_QAM_AGC_PWR_RD_H 0xF41E -+#define F367_QAM_AGC_PWR_WORD_HI 0xF41E0003 -+ -+/* AGC_PWM_IFCMD_L */ -+#define R367_QAM_AGC_PWM_IFCMD_L 0xF420 -+#define F367_QAM_AGC_IF_PWMCMD_LO 0xF42000FF -+ -+/* AGC_PWM_IFCMD_H */ -+#define R367_QAM_AGC_PWM_IFCMD_H 0xF421 -+#define F367_QAM_AGC_IF_PWMCMD_HI 0xF421000F -+ -+/* AGC_PWM_RFCMD_L */ -+#define R367_QAM_AGC_PWM_RFCMD_L 0xF422 -+#define F367_QAM_AGC_RF_PWMCMD_LO 0xF42200FF -+ -+/* AGC_PWM_RFCMD_H */ -+#define R367_QAM_AGC_PWM_RFCMD_H 0xF423 -+#define F367_QAM_AGC_RF_PWMCMD_HI 0xF423000F -+ -+/* IQDEM_CFG */ -+#define R367_QAM_IQDEM_CFG 0xF424 -+#define F367_QAM_IQDEM_CLK_SEL 0xF4240004 -+#define F367_QAM_IQDEM_INVIQ 0xF4240002 -+#define F367_QAM_IQDEM_A2DTYPE 0xF4240001 -+ -+/* MIX_NCO_LL */ -+#define R367_QAM_MIX_NCO_LL 0xF425 -+#define F367_QAM_MIX_NCO_INC_LL 0xF42500FF -+ -+/* MIX_NCO_HL */ -+#define R367_QAM_MIX_NCO_HL 0xF426 -+#define F367_QAM_MIX_NCO_INC_HL 0xF42600FF -+ -+/* MIX_NCO_HH */ -+#define R367_QAM_MIX_NCO_HH 0xF427 -+#define F367_QAM_MIX_NCO_INVCNST 0xF4270080 -+#define F367_QAM_MIX_NCO_INC_HH 0xF427007F -+ -+/* SRC_NCO_LL */ -+#define R367_QAM_SRC_NCO_LL 0xF428 -+#define F367_QAM_SRC_NCO_INC_LL 0xF42800FF -+ -+/* SRC_NCO_LH */ -+#define R367_QAM_SRC_NCO_LH 0xF429 -+#define F367_QAM_SRC_NCO_INC_LH 0xF42900FF -+ -+/* SRC_NCO_HL */ -+#define R367_QAM_SRC_NCO_HL 0xF42A -+#define F367_QAM_SRC_NCO_INC_HL 0xF42A00FF -+ -+/* SRC_NCO_HH */ -+#define R367_QAM_SRC_NCO_HH 0xF42B -+#define F367_QAM_SRC_NCO_INC_HH 0xF42B007F -+ -+/* IQDEM_GAIN_SRC_L */ -+#define R367_QAM_IQDEM_GAIN_SRC_L 0xF42C -+#define F367_QAM_GAIN_SRC_LO 0xF42C00FF -+ -+/* IQDEM_GAIN_SRC_H */ -+#define R367_QAM_IQDEM_GAIN_SRC_H 0xF42D -+#define F367_QAM_GAIN_SRC_HI 0xF42D0003 -+ -+/* IQDEM_DCRM_CFG_LL */ -+#define R367_QAM_IQDEM_DCRM_CFG_LL 0xF430 -+#define F367_QAM_DCRM0_DCIN_L 0xF43000FF -+ -+/* IQDEM_DCRM_CFG_LH */ -+#define R367_QAM_IQDEM_DCRM_CFG_LH 0xF431 -+#define F367_QAM_DCRM1_I_DCIN_L 0xF43100FC -+#define F367_QAM_DCRM0_DCIN_H 0xF4310003 -+ -+/* IQDEM_DCRM_CFG_HL */ -+#define R367_QAM_IQDEM_DCRM_CFG_HL 0xF432 -+#define F367_QAM_DCRM1_Q_DCIN_L 0xF43200F0 -+#define F367_QAM_DCRM1_I_DCIN_H 0xF432000F -+ -+/* IQDEM_DCRM_CFG_HH */ -+#define R367_QAM_IQDEM_DCRM_CFG_HH 0xF433 -+#define F367_QAM_DCRM1_FRZ 0xF4330080 -+#define F367_QAM_DCRM0_FRZ 0xF4330040 -+#define F367_QAM_DCRM1_Q_DCIN_H 0xF433003F -+ -+/* IQDEM_ADJ_COEFF0 */ -+#define R367_QAM_IQDEM_ADJ_COEFF0 0xF434 -+#define F367_QAM_ADJIIR_COEFF10_L 0xF43400FF -+ -+/* IQDEM_ADJ_COEFF1 */ -+#define R367_QAM_IQDEM_ADJ_COEFF1 0xF435 -+#define F367_QAM_ADJIIR_COEFF11_L 0xF43500FC -+#define F367_QAM_ADJIIR_COEFF10_H 0xF4350003 -+ -+/* IQDEM_ADJ_COEFF2 */ -+#define R367_QAM_IQDEM_ADJ_COEFF2 0xF436 -+#define F367_QAM_ADJIIR_COEFF12_L 0xF43600F0 -+#define F367_QAM_ADJIIR_COEFF11_H 0xF436000F -+ -+/* IQDEM_ADJ_COEFF3 */ -+#define R367_QAM_IQDEM_ADJ_COEFF3 0xF437 -+#define F367_QAM_ADJIIR_COEFF20_L 0xF43700C0 -+#define F367_QAM_ADJIIR_COEFF12_H 0xF437003F -+ -+/* IQDEM_ADJ_COEFF4 */ -+#define R367_QAM_IQDEM_ADJ_COEFF4 0xF438 -+#define F367_QAM_ADJIIR_COEFF20_H 0xF43800FF -+ -+/* IQDEM_ADJ_COEFF5 */ -+#define R367_QAM_IQDEM_ADJ_COEFF5 0xF439 -+#define F367_QAM_ADJIIR_COEFF21_L 0xF43900FF -+ -+/* IQDEM_ADJ_COEFF6 */ -+#define R367_QAM_IQDEM_ADJ_COEFF6 0xF43A -+#define F367_QAM_ADJIIR_COEFF22_L 0xF43A00FC -+#define F367_QAM_ADJIIR_COEFF21_H 0xF43A0003 -+ -+/* IQDEM_ADJ_COEFF7 */ -+#define R367_QAM_IQDEM_ADJ_COEFF7 0xF43B -+#define F367_QAM_ADJIIR_COEFF22_H 0xF43B000F -+ -+/* IQDEM_ADJ_EN */ -+#define R367_QAM_IQDEM_ADJ_EN 0xF43C -+#define F367_QAM_ALLPASSFILT_EN 0xF43C0008 -+#define F367_QAM_ADJ_AGC_EN 0xF43C0004 -+#define F367_QAM_ADJ_COEFF_FRZ 0xF43C0002 -+#define F367_QAM_ADJ_EN 0xF43C0001 -+ -+/* IQDEM_ADJ_AGC_REF */ -+#define R367_QAM_IQDEM_ADJ_AGC_REF 0xF43D -+#define F367_QAM_ADJ_AGC_REF 0xF43D00FF -+ -+/* ALLPASSFILT1 */ -+#define R367_QAM_ALLPASSFILT1 0xF440 -+#define F367_QAM_ALLPASSFILT_COEFF1_LO 0xF44000FF -+ -+/* ALLPASSFILT2 */ -+#define R367_QAM_ALLPASSFILT2 0xF441 -+#define F367_QAM_ALLPASSFILT_COEFF1_ME 0xF44100FF -+ -+/* ALLPASSFILT3 */ -+#define R367_QAM_ALLPASSFILT3 0xF442 -+#define F367_QAM_ALLPASSFILT_COEFF2_LO 0xF44200C0 -+#define F367_QAM_ALLPASSFILT_COEFF1_HI 0xF442003F -+ -+/* ALLPASSFILT4 */ -+#define R367_QAM_ALLPASSFILT4 0xF443 -+#define F367_QAM_ALLPASSFILT_COEFF2_MEL 0xF44300FF -+ -+/* ALLPASSFILT5 */ -+#define R367_QAM_ALLPASSFILT5 0xF444 -+#define F367_QAM_ALLPASSFILT_COEFF2_MEH 0xF44400FF -+ -+/* ALLPASSFILT6 */ -+#define R367_QAM_ALLPASSFILT6 0xF445 -+#define F367_QAM_ALLPASSFILT_COEFF3_LO 0xF44500F0 -+#define F367_QAM_ALLPASSFILT_COEFF2_HI 0xF445000F -+ -+/* ALLPASSFILT7 */ -+#define R367_QAM_ALLPASSFILT7 0xF446 -+#define F367_QAM_ALLPASSFILT_COEFF3_MEL 0xF44600FF -+ -+/* ALLPASSFILT8 */ -+#define R367_QAM_ALLPASSFILT8 0xF447 -+#define F367_QAM_ALLPASSFILT_COEFF3_MEH 0xF44700FF -+ -+/* ALLPASSFILT9 */ -+#define R367_QAM_ALLPASSFILT9 0xF448 -+#define F367_QAM_ALLPASSFILT_COEFF4_LO 0xF44800FC -+#define F367_QAM_ALLPASSFILT_COEFF3_HI 0xF4480003 -+ -+/* ALLPASSFILT10 */ -+#define R367_QAM_ALLPASSFILT10 0xF449 -+#define F367_QAM_ALLPASSFILT_COEFF4_ME 0xF44900FF -+ -+/* ALLPASSFILT11 */ -+#define R367_QAM_ALLPASSFILT11 0xF44A -+#define F367_QAM_ALLPASSFILT_COEFF4_HI 0xF44A00FF -+ -+/* TRL_AGC_CFG */ -+#define R367_QAM_TRL_AGC_CFG 0xF450 -+#define F367_QAM_TRL_AGC_FREEZE 0xF4500080 -+#define F367_QAM_TRL_AGC_REF 0xF450007F -+ -+/* TRL_LPF_CFG */ -+#define R367_QAM_TRL_LPF_CFG 0xF454 -+#define F367_QAM_NYQPOINT_INV 0xF4540040 -+#define F367_QAM_TRL_SHIFT 0xF4540030 -+#define F367_QAM_NYQ_COEFF_SEL 0xF454000C -+#define F367_QAM_TRL_LPF_FREEZE 0xF4540002 -+#define F367_QAM_TRL_LPF_CRT 0xF4540001 -+ -+/* TRL_LPF_ACQ_GAIN */ -+#define R367_QAM_TRL_LPF_ACQ_GAIN 0xF455 -+#define F367_QAM_TRL_GDIR_ACQ 0xF4550070 -+#define F367_QAM_TRL_GINT_ACQ 0xF4550007 -+ -+/* TRL_LPF_TRK_GAIN */ -+#define R367_QAM_TRL_LPF_TRK_GAIN 0xF456 -+#define F367_QAM_TRL_GDIR_TRK 0xF4560070 -+#define F367_QAM_TRL_GINT_TRK 0xF4560007 -+ -+/* TRL_LPF_OUT_GAIN */ -+#define R367_QAM_TRL_LPF_OUT_GAIN 0xF457 -+#define F367_QAM_TRL_GAIN_OUT 0xF4570007 -+ -+/* TRL_LOCKDET_LTH */ -+#define R367_QAM_TRL_LOCKDET_LTH 0xF458 -+#define F367_QAM_TRL_LCK_THLO 0xF4580007 -+ -+/* TRL_LOCKDET_HTH */ -+#define R367_QAM_TRL_LOCKDET_HTH 0xF459 -+#define F367_QAM_TRL_LCK_THHI 0xF45900FF -+ -+/* TRL_LOCKDET_TRGVAL */ -+#define R367_QAM_TRL_LOCKDET_TRGVAL 0xF45A -+#define F367_QAM_TRL_LCK_TRG 0xF45A00FF -+ -+/* IQ_QAM */ -+#define R367_QAM_IQ_QAM 0xF45C -+#define F367_QAM_IQ_INPUT 0xF45C0008 -+#define F367_QAM_DETECT_MODE 0xF45C0007 -+ -+/* FSM_STATE */ -+#define R367_QAM_FSM_STATE 0xF460 -+#define F367_QAM_CRL_DFE 0xF4600080 -+#define F367_QAM_DFE_START 0xF4600040 -+#define F367_QAM_CTRLG_START 0xF4600030 -+#define F367_QAM_FSM_FORCESTATE 0xF460000F -+ -+/* FSM_CTL */ -+#define R367_QAM_FSM_CTL 0xF461 -+#define F367_QAM_FEC2_EN 0xF4610040 -+#define F367_QAM_SIT_EN 0xF4610020 -+#define F367_QAM_TRL_AHEAD 0xF4610010 -+#define F367_QAM_TRL2_EN 0xF4610008 -+#define F367_QAM_FSM_EQA1_EN 0xF4610004 -+#define F367_QAM_FSM_BKP_DIS 0xF4610002 -+#define F367_QAM_FSM_FORCE_EN 0xF4610001 -+ -+/* FSM_STS */ -+#define R367_QAM_FSM_STS 0xF462 -+#define F367_QAM_FSM_STATUS 0xF462000F -+ -+/* FSM_SNR0_HTH */ -+#define R367_QAM_FSM_SNR0_HTH 0xF463 -+#define F367_QAM_SNR0_HTH 0xF46300FF -+ -+/* FSM_SNR1_HTH */ -+#define R367_QAM_FSM_SNR1_HTH 0xF464 -+#define F367_QAM_SNR1_HTH 0xF46400FF -+ -+/* FSM_SNR2_HTH */ -+#define R367_QAM_FSM_SNR2_HTH 0xF465 -+#define F367_QAM_SNR2_HTH 0xF46500FF -+ -+/* FSM_SNR0_LTH */ -+#define R367_QAM_FSM_SNR0_LTH 0xF466 -+#define F367_QAM_SNR0_LTH 0xF46600FF -+ -+/* FSM_SNR1_LTH */ -+#define R367_QAM_FSM_SNR1_LTH 0xF467 -+#define F367_QAM_SNR1_LTH 0xF46700FF -+ -+/* FSM_EQA1_HTH */ -+#define R367_QAM_FSM_EQA1_HTH 0xF468 -+#define F367_QAM_SNR3_HTH_LO 0xF46800F0 -+#define F367_QAM_EQA1_HTH 0xF468000F -+ -+/* FSM_TEMPO */ -+#define R367_QAM_FSM_TEMPO 0xF469 -+#define F367_QAM_SIT 0xF46900C0 -+#define F367_QAM_WST 0xF4690038 -+#define F367_QAM_ELT 0xF4690006 -+#define F367_QAM_SNR3_HTH_HI 0xF4690001 -+ -+/* FSM_CONFIG */ -+#define R367_QAM_FSM_CONFIG 0xF46A -+#define F367_QAM_FEC2_DFEOFF 0xF46A0004 -+#define F367_QAM_PRIT_STATE 0xF46A0002 -+#define F367_QAM_MODMAP_STATE 0xF46A0001 -+ -+/* EQU_I_TESTTAP_L */ -+#define R367_QAM_EQU_I_TESTTAP_L 0xF474 -+#define F367_QAM_I_TEST_TAP_L 0xF47400FF -+ -+/* EQU_I_TESTTAP_M */ -+#define R367_QAM_EQU_I_TESTTAP_M 0xF475 -+#define F367_QAM_I_TEST_TAP_M 0xF47500FF -+ -+/* EQU_I_TESTTAP_H */ -+#define R367_QAM_EQU_I_TESTTAP_H 0xF476 -+#define F367_QAM_I_TEST_TAP_H 0xF476001F -+ -+/* EQU_TESTAP_CFG */ -+#define R367_QAM_EQU_TESTAP_CFG 0xF477 -+#define F367_QAM_TEST_FFE_DFE_SEL 0xF4770040 -+#define F367_QAM_TEST_TAP_SELECT 0xF477003F -+ -+/* EQU_Q_TESTTAP_L */ -+#define R367_QAM_EQU_Q_TESTTAP_L 0xF478 -+#define F367_QAM_Q_TEST_TAP_L 0xF47800FF -+ -+/* EQU_Q_TESTTAP_M */ -+#define R367_QAM_EQU_Q_TESTTAP_M 0xF479 -+#define F367_QAM_Q_TEST_TAP_M 0xF47900FF -+ -+/* EQU_Q_TESTTAP_H */ -+#define R367_QAM_EQU_Q_TESTTAP_H 0xF47A -+#define F367_QAM_Q_TEST_TAP_H 0xF47A001F -+ -+/* EQU_TAP_CTRL */ -+#define R367_QAM_EQU_TAP_CTRL 0xF47B -+#define F367_QAM_MTAP_FRZ 0xF47B0010 -+#define F367_QAM_PRE_FREEZE 0xF47B0008 -+#define F367_QAM_DFE_TAPMON_EN 0xF47B0004 -+#define F367_QAM_FFE_TAPMON_EN 0xF47B0002 -+#define F367_QAM_MTAP_ONLY 0xF47B0001 -+ -+/* EQU_CTR_CRL_CONTROL_L */ -+#define R367_QAM_EQU_CTR_CRL_CONTROL_L 0xF47C -+#define F367_QAM_EQU_CTR_CRL_CONTROL_LO 0xF47C00FF -+ -+/* EQU_CTR_CRL_CONTROL_H */ -+#define R367_QAM_EQU_CTR_CRL_CONTROL_H 0xF47D -+#define F367_QAM_EQU_CTR_CRL_CONTROL_HI 0xF47D00FF -+ -+/* EQU_CTR_HIPOW_L */ -+#define R367_QAM_EQU_CTR_HIPOW_L 0xF47E -+#define F367_QAM_CTR_HIPOW_L 0xF47E00FF -+ -+/* EQU_CTR_HIPOW_H */ -+#define R367_QAM_EQU_CTR_HIPOW_H 0xF47F -+#define F367_QAM_CTR_HIPOW_H 0xF47F00FF -+ -+/* EQU_I_EQU_LO */ -+#define R367_QAM_EQU_I_EQU_LO 0xF480 -+#define F367_QAM_EQU_I_EQU_L 0xF48000FF -+ -+/* EQU_I_EQU_HI */ -+#define R367_QAM_EQU_I_EQU_HI 0xF481 -+#define F367_QAM_EQU_I_EQU_H 0xF4810003 -+ -+/* EQU_Q_EQU_LO */ -+#define R367_QAM_EQU_Q_EQU_LO 0xF482 -+#define F367_QAM_EQU_Q_EQU_L 0xF48200FF -+ -+/* EQU_Q_EQU_HI */ -+#define R367_QAM_EQU_Q_EQU_HI 0xF483 -+#define F367_QAM_EQU_Q_EQU_H 0xF4830003 -+ -+/* EQU_MAPPER */ -+#define R367_QAM_EQU_MAPPER 0xF484 -+#define F367_QAM_QUAD_AUTO 0xF4840080 -+#define F367_QAM_QUAD_INV 0xF4840040 -+#define F367_QAM_QAM_MODE 0xF4840007 -+ -+/* EQU_SWEEP_RATE */ -+#define R367_QAM_EQU_SWEEP_RATE 0xF485 -+#define F367_QAM_SNR_PER 0xF48500C0 -+#define F367_QAM_SWEEP_RATE 0xF485003F -+ -+/* EQU_SNR_LO */ -+#define R367_QAM_EQU_SNR_LO 0xF486 -+#define F367_QAM_SNR_LO 0xF48600FF -+ -+/* EQU_SNR_HI */ -+#define R367_QAM_EQU_SNR_HI 0xF487 -+#define F367_QAM_SNR_HI 0xF48700FF -+ -+/* EQU_GAMMA_LO */ -+#define R367_QAM_EQU_GAMMA_LO 0xF488 -+#define F367_QAM_GAMMA_LO 0xF48800FF -+ -+/* EQU_GAMMA_HI */ -+#define R367_QAM_EQU_GAMMA_HI 0xF489 -+#define F367_QAM_GAMMA_ME 0xF48900FF -+ -+/* EQU_ERR_GAIN */ -+#define R367_QAM_EQU_ERR_GAIN 0xF48A -+#define F367_QAM_EQA1MU 0xF48A0070 -+#define F367_QAM_CRL2MU 0xF48A000E -+#define F367_QAM_GAMMA_HI 0xF48A0001 -+ -+/* EQU_RADIUS */ -+#define R367_QAM_EQU_RADIUS 0xF48B -+#define F367_QAM_RADIUS 0xF48B00FF -+ -+/* EQU_FFE_MAINTAP */ -+#define R367_QAM_EQU_FFE_MAINTAP 0xF48C -+#define F367_QAM_FFE_MAINTAP_INIT 0xF48C00FF -+ -+/* EQU_FFE_LEAKAGE */ -+#define R367_QAM_EQU_FFE_LEAKAGE 0xF48E -+#define F367_QAM_LEAK_PER 0xF48E00F0 -+#define F367_QAM_EQU_OUTSEL 0xF48E0002 -+#define F367_QAM_PNT2DFE 0xF48E0001 -+ -+/* EQU_FFE_MAINTAP_POS */ -+#define R367_QAM_EQU_FFE_MAINTAP_POS 0xF48F -+#define F367_QAM_FFE_LEAK_EN 0xF48F0080 -+#define F367_QAM_DFE_LEAK_EN 0xF48F0040 -+#define F367_QAM_FFE_MAINTAP_POS 0xF48F003F -+ -+/* EQU_GAIN_WIDE */ -+#define R367_QAM_EQU_GAIN_WIDE 0xF490 -+#define F367_QAM_DFE_GAIN_WIDE 0xF49000F0 -+#define F367_QAM_FFE_GAIN_WIDE 0xF490000F -+ -+/* EQU_GAIN_NARROW */ -+#define R367_QAM_EQU_GAIN_NARROW 0xF491 -+#define F367_QAM_DFE_GAIN_NARROW 0xF49100F0 -+#define F367_QAM_FFE_GAIN_NARROW 0xF491000F -+ -+/* EQU_CTR_LPF_GAIN */ -+#define R367_QAM_EQU_CTR_LPF_GAIN 0xF492 -+#define F367_QAM_CTR_GTO 0xF4920080 -+#define F367_QAM_CTR_GDIR 0xF4920070 -+#define F367_QAM_SWEEP_EN 0xF4920008 -+#define F367_QAM_CTR_GINT 0xF4920007 -+ -+/* EQU_CRL_LPF_GAIN */ -+#define R367_QAM_EQU_CRL_LPF_GAIN 0xF493 -+#define F367_QAM_CRL_GTO 0xF4930080 -+#define F367_QAM_CRL_GDIR 0xF4930070 -+#define F367_QAM_SWEEP_DIR 0xF4930008 -+#define F367_QAM_CRL_GINT 0xF4930007 -+ -+/* EQU_GLOBAL_GAIN */ -+#define R367_QAM_EQU_GLOBAL_GAIN 0xF494 -+#define F367_QAM_CRL_GAIN 0xF49400F8 -+#define F367_QAM_CTR_INC_GAIN 0xF4940004 -+#define F367_QAM_CTR_FRAC 0xF4940003 -+ -+/* EQU_CRL_LD_SEN */ -+#define R367_QAM_EQU_CRL_LD_SEN 0xF495 -+#define F367_QAM_CTR_BADPOINT_EN 0xF4950080 -+#define F367_QAM_CTR_GAIN 0xF4950070 -+#define F367_QAM_LIMANEN 0xF4950008 -+#define F367_QAM_CRL_LD_SEN 0xF4950007 -+ -+/* EQU_CRL_LD_VAL */ -+#define R367_QAM_EQU_CRL_LD_VAL 0xF496 -+#define F367_QAM_CRL_BISTH_LIMIT 0xF4960080 -+#define F367_QAM_CARE_EN 0xF4960040 -+#define F367_QAM_CRL_LD_PER 0xF4960030 -+#define F367_QAM_CRL_LD_WST 0xF496000C -+#define F367_QAM_CRL_LD_TFS 0xF4960003 -+ -+/* EQU_CRL_TFR */ -+#define R367_QAM_EQU_CRL_TFR 0xF497 -+#define F367_QAM_CRL_LD_TFR 0xF49700FF -+ -+/* EQU_CRL_BISTH_LO */ -+#define R367_QAM_EQU_CRL_BISTH_LO 0xF498 -+#define F367_QAM_CRL_BISTH_LO 0xF49800FF -+ -+/* EQU_CRL_BISTH_HI */ -+#define R367_QAM_EQU_CRL_BISTH_HI 0xF499 -+#define F367_QAM_CRL_BISTH_HI 0xF49900FF -+ -+/* EQU_SWEEP_RANGE_LO */ -+#define R367_QAM_EQU_SWEEP_RANGE_LO 0xF49A -+#define F367_QAM_SWEEP_RANGE_LO 0xF49A00FF -+ -+/* EQU_SWEEP_RANGE_HI */ -+#define R367_QAM_EQU_SWEEP_RANGE_HI 0xF49B -+#define F367_QAM_SWEEP_RANGE_HI 0xF49B00FF -+ -+/* EQU_CRL_LIMITER */ -+#define R367_QAM_EQU_CRL_LIMITER 0xF49C -+#define F367_QAM_BISECTOR_EN 0xF49C0080 -+#define F367_QAM_PHEST128_EN 0xF49C0040 -+#define F367_QAM_CRL_LIM 0xF49C003F -+ -+/* EQU_MODULUS_MAP */ -+#define R367_QAM_EQU_MODULUS_MAP 0xF49D -+#define F367_QAM_PNT_DEPTH 0xF49D00E0 -+#define F367_QAM_MODULUS_CMP 0xF49D001F -+ -+/* EQU_PNT_GAIN */ -+#define R367_QAM_EQU_PNT_GAIN 0xF49E -+#define F367_QAM_PNT_EN 0xF49E0080 -+#define F367_QAM_MODULUSMAP_EN 0xF49E0040 -+#define F367_QAM_PNT_GAIN 0xF49E003F -+ -+/* FEC_AC_CTR_0 */ -+#define R367_QAM_FEC_AC_CTR_0 0xF4A8 -+#define F367_QAM_BE_BYPASS 0xF4A80020 -+#define F367_QAM_REFRESH47 0xF4A80010 -+#define F367_QAM_CT_NBST 0xF4A80008 -+#define F367_QAM_TEI_ENA 0xF4A80004 -+#define F367_QAM_DS_ENA 0xF4A80002 -+#define F367_QAM_TSMF_EN 0xF4A80001 -+ -+/* FEC_AC_CTR_1 */ -+#define R367_QAM_FEC_AC_CTR_1 0xF4A9 -+#define F367_QAM_DEINT_DEPTH 0xF4A900FF -+ -+/* FEC_AC_CTR_2 */ -+#define R367_QAM_FEC_AC_CTR_2 0xF4AA -+#define F367_QAM_DEINT_M 0xF4AA00F8 -+#define F367_QAM_DIS_UNLOCK 0xF4AA0004 -+#define F367_QAM_DESCR_MODE 0xF4AA0003 -+ -+/* FEC_AC_CTR_3 */ -+#define R367_QAM_FEC_AC_CTR_3 0xF4AB -+#define F367_QAM_DI_UNLOCK 0xF4AB0080 -+#define F367_QAM_DI_FREEZE 0xF4AB0040 -+#define F367_QAM_MISMATCH 0xF4AB0030 -+#define F367_QAM_ACQ_MODE 0xF4AB000C -+#define F367_QAM_TRK_MODE 0xF4AB0003 -+ -+/* FEC_STATUS */ -+#define R367_QAM_FEC_STATUS 0xF4AC -+#define F367_QAM_DEINT_SMCNTR 0xF4AC00E0 -+#define F367_QAM_DEINT_SYNCSTATE 0xF4AC0018 -+#define F367_QAM_DEINT_SYNLOST 0xF4AC0004 -+#define F367_QAM_DESCR_SYNCSTATE 0xF4AC0002 -+ -+/* RS_COUNTER_0 */ -+#define R367_QAM_RS_COUNTER_0 0xF4AE -+#define F367_QAM_BK_CT_L 0xF4AE00FF -+ -+/* RS_COUNTER_1 */ -+#define R367_QAM_RS_COUNTER_1 0xF4AF -+#define F367_QAM_BK_CT_H 0xF4AF00FF -+ -+/* RS_COUNTER_2 */ -+#define R367_QAM_RS_COUNTER_2 0xF4B0 -+#define F367_QAM_CORR_CT_L 0xF4B000FF -+ -+/* RS_COUNTER_3 */ -+#define R367_QAM_RS_COUNTER_3 0xF4B1 -+#define F367_QAM_CORR_CT_H 0xF4B100FF -+ -+/* RS_COUNTER_4 */ -+#define R367_QAM_RS_COUNTER_4 0xF4B2 -+#define F367_QAM_UNCORR_CT_L 0xF4B200FF -+ -+/* RS_COUNTER_5 */ -+#define R367_QAM_RS_COUNTER_5 0xF4B3 -+#define F367_QAM_UNCORR_CT_H 0xF4B300FF -+ -+/* BERT_0 */ -+#define R367_QAM_BERT_0 0xF4B4 -+#define F367_QAM_RS_NOCORR 0xF4B40004 -+#define F367_QAM_CT_HOLD 0xF4B40002 -+#define F367_QAM_CT_CLEAR 0xF4B40001 -+ -+/* BERT_1 */ -+#define R367_QAM_BERT_1 0xF4B5 -+#define F367_QAM_BERT_ON 0xF4B50020 -+#define F367_QAM_BERT_ERR_SRC 0xF4B50010 -+#define F367_QAM_BERT_ERR_MODE 0xF4B50008 -+#define F367_QAM_BERT_NBYTE 0xF4B50007 -+ -+/* BERT_2 */ -+#define R367_QAM_BERT_2 0xF4B6 -+#define F367_QAM_BERT_ERRCOUNT_L 0xF4B600FF -+ -+/* BERT_3 */ -+#define R367_QAM_BERT_3 0xF4B7 -+#define F367_QAM_BERT_ERRCOUNT_H 0xF4B700FF -+ -+/* OUTFORMAT_0 */ -+#define R367_QAM_OUTFORMAT_0 0xF4B8 -+#define F367_QAM_CLK_POLARITY 0xF4B80080 -+#define F367_QAM_FEC_TYPE 0xF4B80040 -+#define F367_QAM_SYNC_STRIP 0xF4B80008 -+#define F367_QAM_TS_SWAP 0xF4B80004 -+#define F367_QAM_OUTFORMAT 0xF4B80003 -+ -+/* OUTFORMAT_1 */ -+#define R367_QAM_OUTFORMAT_1 0xF4B9 -+#define F367_QAM_CI_DIVRANGE 0xF4B900FF -+ -+/* SMOOTHER_2 */ -+#define R367_QAM_SMOOTHER_2 0xF4BE -+#define F367_QAM_FIFO_BYPASS 0xF4BE0020 -+ -+/* TSMF_CTRL_0 */ -+#define R367_QAM_TSMF_CTRL_0 0xF4C0 -+#define F367_QAM_TS_NUMBER 0xF4C0001E -+#define F367_QAM_SEL_MODE 0xF4C00001 -+ -+/* TSMF_CTRL_1 */ -+#define R367_QAM_TSMF_CTRL_1 0xF4C1 -+#define F367_QAM_CHECK_ERROR_BIT 0xF4C10080 -+#define F367_QAM_CHCK_F_SYNC 0xF4C10040 -+#define F367_QAM_H_MODE 0xF4C10008 -+#define F367_QAM_D_V_MODE 0xF4C10004 -+#define F367_QAM_MODE 0xF4C10003 -+ -+/* TSMF_CTRL_3 */ -+#define R367_QAM_TSMF_CTRL_3 0xF4C3 -+#define F367_QAM_SYNC_IN_COUNT 0xF4C300F0 -+#define F367_QAM_SYNC_OUT_COUNT 0xF4C3000F -+ -+/* TS_ON_ID_0 */ -+#define R367_QAM_TS_ON_ID_0 0xF4C4 -+#define F367_QAM_TS_ID_L 0xF4C400FF -+ -+/* TS_ON_ID_1 */ -+#define R367_QAM_TS_ON_ID_1 0xF4C5 -+#define F367_QAM_TS_ID_H 0xF4C500FF -+ -+/* TS_ON_ID_2 */ -+#define R367_QAM_TS_ON_ID_2 0xF4C6 -+#define F367_QAM_ON_ID_L 0xF4C600FF -+ -+/* TS_ON_ID_3 */ -+#define R367_QAM_TS_ON_ID_3 0xF4C7 -+#define F367_QAM_ON_ID_H 0xF4C700FF -+ -+/* RE_STATUS_0 */ -+#define R367_QAM_RE_STATUS_0 0xF4C8 -+#define F367_QAM_RECEIVE_STATUS_L 0xF4C800FF -+ -+/* RE_STATUS_1 */ -+#define R367_QAM_RE_STATUS_1 0xF4C9 -+#define F367_QAM_RECEIVE_STATUS_LH 0xF4C900FF -+ -+/* RE_STATUS_2 */ -+#define R367_QAM_RE_STATUS_2 0xF4CA -+#define F367_QAM_RECEIVE_STATUS_HL 0xF4CA00FF -+ -+/* RE_STATUS_3 */ -+#define R367_QAM_RE_STATUS_3 0xF4CB -+#define F367_QAM_RECEIVE_STATUS_HH 0xF4CB003F -+ -+/* TS_STATUS_0 */ -+#define R367_QAM_TS_STATUS_0 0xF4CC -+#define F367_QAM_TS_STATUS_L 0xF4CC00FF -+ -+/* TS_STATUS_1 */ -+#define R367_QAM_TS_STATUS_1 0xF4CD -+#define F367_QAM_TS_STATUS_H 0xF4CD007F -+ -+/* TS_STATUS_2 */ -+#define R367_QAM_TS_STATUS_2 0xF4CE -+#define F367_QAM_ERROR 0xF4CE0080 -+#define F367_QAM_EMERGENCY 0xF4CE0040 -+#define F367_QAM_CRE_TS 0xF4CE0030 -+#define F367_QAM_VER 0xF4CE000E -+#define F367_QAM_M_LOCK 0xF4CE0001 -+ -+/* TS_STATUS_3 */ -+#define R367_QAM_TS_STATUS_3 0xF4CF -+#define F367_QAM_UPDATE_READY 0xF4CF0080 -+#define F367_QAM_END_FRAME_HEADER 0xF4CF0040 -+#define F367_QAM_CONTCNT 0xF4CF0020 -+#define F367_QAM_TS_IDENTIFIER_SEL 0xF4CF000F -+ -+/* T_O_ID_0 */ -+#define R367_QAM_T_O_ID_0 0xF4D0 -+#define F367_QAM_ON_ID_I_L 0xF4D000FF -+ -+/* T_O_ID_1 */ -+#define R367_QAM_T_O_ID_1 0xF4D1 -+#define F367_QAM_ON_ID_I_H 0xF4D100FF -+ -+/* T_O_ID_2 */ -+#define R367_QAM_T_O_ID_2 0xF4D2 -+#define F367_QAM_TS_ID_I_L 0xF4D200FF -+ -+/* T_O_ID_3 */ -+#define R367_QAM_T_O_ID_3 0xF4D3 -+#define F367_QAM_TS_ID_I_H 0xF4D300FF -diff --git a/drivers/media/dvb-frontends/stv0910.c b/drivers/media/dvb-frontends/stv0910.c -new file mode 100644 -index 0000000..730ba5f ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0910.c -@@ -0,0 +1,1526 @@ -+/* -+ * Driver for the ST STV0910 DVB-S/S2 demodulator. -+ * -+ * Copyright (C) 2014-2015 Ralph Metzler -+ * Marcus Metzler -+ * developed for Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#undef pr_fmt -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_math.h" -+#include "dvb_frontend.h" -+#include "stv0910.h" -+#include "stv0910_regs.h" -+ -+#define INTLOG10X100(x) ((u32) (((u64) intlog10(x) * 100) >> 24)) -+ -+#define TUNING_DELAY 200 -+#define BER_SRC_S 0x20 -+#define BER_SRC_S2 0x20 -+ -+LIST_HEAD(stvlist); -+ -+enum ReceiveMode { Mode_None, Mode_DVBS, Mode_DVBS2, Mode_Auto }; -+ -+enum DVBS2_FECType { DVBS2_64K, DVBS2_16K }; -+ -+enum DVBS2_ModCod { -+ DVBS2_DUMMY_PLF, DVBS2_QPSK_1_4, DVBS2_QPSK_1_3, DVBS2_QPSK_2_5, -+ DVBS2_QPSK_1_2, DVBS2_QPSK_3_5, DVBS2_QPSK_2_3, DVBS2_QPSK_3_4, -+ DVBS2_QPSK_4_5, DVBS2_QPSK_5_6, DVBS2_QPSK_8_9, DVBS2_QPSK_9_10, -+ DVBS2_8PSK_3_5, DVBS2_8PSK_2_3, DVBS2_8PSK_3_4, DVBS2_8PSK_5_6, -+ DVBS2_8PSK_8_9, DVBS2_8PSK_9_10, DVBS2_16APSK_2_3, DVBS2_16APSK_3_4, -+ DVBS2_16APSK_4_5, DVBS2_16APSK_5_6, DVBS2_16APSK_8_9, DVBS2_16APSK_9_10, -+ DVBS2_32APSK_3_4, DVBS2_32APSK_4_5, DVBS2_32APSK_5_6, DVBS2_32APSK_8_9, -+ DVBS2_32APSK_9_10 -+}; -+ -+enum FE_STV0910_ModCod { -+ FE_DUMMY_PLF, FE_QPSK_14, FE_QPSK_13, FE_QPSK_25, -+ FE_QPSK_12, FE_QPSK_35, FE_QPSK_23, FE_QPSK_34, -+ FE_QPSK_45, FE_QPSK_56, FE_QPSK_89, FE_QPSK_910, -+ FE_8PSK_35, FE_8PSK_23, FE_8PSK_34, FE_8PSK_56, -+ FE_8PSK_89, FE_8PSK_910, FE_16APSK_23, FE_16APSK_34, -+ FE_16APSK_45, FE_16APSK_56, FE_16APSK_89, FE_16APSK_910, -+ FE_32APSK_34, FE_32APSK_45, FE_32APSK_56, FE_32APSK_89, -+ FE_32APSK_910 -+}; -+ -+enum FE_STV0910_RollOff { FE_SAT_35, FE_SAT_25, FE_SAT_20, FE_SAT_15 }; -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+struct stv_base { -+ struct list_head stvlist; -+ -+ u8 adr; -+ struct i2c_adapter *i2c; -+ struct mutex i2c_lock; -+ struct mutex reg_lock; -+ int count; -+ -+ u32 extclk; -+ u32 mclk; -+}; -+ -+struct stv { -+ struct stv_base *base; -+ struct dvb_frontend fe; -+ int nr; -+ u16 regoff; -+ u8 i2crpt; -+ u8 tscfgh; -+ u8 tsgeneral; -+ u8 tsspeed; -+ unsigned long tune_time; -+ -+ s32 SearchRange; -+ u32 Started; -+ u32 DemodLockTime; -+ enum ReceiveMode ReceiveMode; -+ u32 DemodTimeout; -+ u32 FecTimeout; -+ u32 FirstTimeLock; -+ u8 DEMOD; -+ u32 SymbolRate; -+ -+ u8 LastViterbiRate; -+ enum fe_code_rate PunctureRate; -+ enum FE_STV0910_ModCod ModCod; -+ enum DVBS2_FECType FECType; -+ u32 Pilots; -+ enum FE_STV0910_RollOff FERollOff; -+ -+ u32 LastBERNumerator; -+ u32 LastBERDenominator; -+ u8 BERScale; -+}; -+ -+struct SInitTable { -+ u16 Address; -+ u8 Data; -+}; -+ -+struct SLookup { -+ s16 Value; -+ u16 RegValue; -+}; -+ -+static inline int i2c_write(struct i2c_adapter *adap, u8 adr, -+ u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_warn("i2c_write_error ([%02x] %04x: %02x)\n", -+ adr, (data[0] << 8) | data[1], -+ (len > 2 ? data[2] : 0)); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, u16 reg, u8 val) -+{ -+ u8 msg[3] = {reg >> 8, reg & 0xff, val}; -+ -+ return i2c_write(adap, adr, msg, 3); -+} -+ -+static int write_reg(struct stv *state, u16 reg, u8 val) -+{ -+ return i2c_write_reg16(state->base->i2c, state->base->adr, reg, val); -+} -+ -+static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr, -+ u16 reg, u8 *val, int count) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = count } }; -+ -+ if (i2c_transfer(adapter, msgs, 2) != 2) { -+ pr_warn("i2c_read error ([%02x] %04x)\n", -+ adr, reg); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int read_reg(struct stv *state, u16 reg, u8 *val) -+{ -+ return i2c_read_regs16(state->base->i2c, state->base->adr, -+ reg, val, 1); -+} -+ -+static int read_regs(struct stv *state, u16 reg, u8 *val, int len) -+{ -+ return i2c_read_regs16(state->base->i2c, state->base->adr, -+ reg, val, len); -+} -+ -+struct SLookup S1_SN_Lookup[] = { -+ { 0, 9242 }, /*C/N= 0dB*/ -+ { 05, 9105 }, /*C/N=0.5dB*/ -+ { 10, 8950 }, /*C/N=1.0dB*/ -+ { 15, 8780 }, /*C/N=1.5dB*/ -+ { 20, 8566 }, /*C/N=2.0dB*/ -+ { 25, 8366 }, /*C/N=2.5dB*/ -+ { 30, 8146 }, /*C/N=3.0dB*/ -+ { 35, 7908 }, /*C/N=3.5dB*/ -+ { 40, 7666 }, /*C/N=4.0dB*/ -+ { 45, 7405 }, /*C/N=4.5dB*/ -+ { 50, 7136 }, /*C/N=5.0dB*/ -+ { 55, 6861 }, /*C/N=5.5dB*/ -+ { 60, 6576 }, /*C/N=6.0dB*/ -+ { 65, 6330 }, /*C/N=6.5dB*/ -+ { 70, 6048 }, /*C/N=7.0dB*/ -+ { 75, 5768 }, /*C/N=7.5dB*/ -+ { 80, 5492 }, /*C/N=8.0dB*/ -+ { 85, 5224 }, /*C/N=8.5dB*/ -+ { 90, 4959 }, /*C/N=9.0dB*/ -+ { 95, 4709 }, /*C/N=9.5dB*/ -+ { 100, 4467 }, /*C/N=10.0dB*/ -+ { 105, 4236 }, /*C/N=10.5dB*/ -+ { 110, 4013 }, /*C/N=11.0dB*/ -+ { 115, 3800 }, /*C/N=11.5dB*/ -+ { 120, 3598 }, /*C/N=12.0dB*/ -+ { 125, 3406 }, /*C/N=12.5dB*/ -+ { 130, 3225 }, /*C/N=13.0dB*/ -+ { 135, 3052 }, /*C/N=13.5dB*/ -+ { 140, 2889 }, /*C/N=14.0dB*/ -+ { 145, 2733 }, /*C/N=14.5dB*/ -+ { 150, 2587 }, /*C/N=15.0dB*/ -+ { 160, 2318 }, /*C/N=16.0dB*/ -+ { 170, 2077 }, /*C/N=17.0dB*/ -+ { 180, 1862 }, /*C/N=18.0dB*/ -+ { 190, 1670 }, /*C/N=19.0dB*/ -+ { 200, 1499 }, /*C/N=20.0dB*/ -+ { 210, 1347 }, /*C/N=21.0dB*/ -+ { 220, 1213 }, /*C/N=22.0dB*/ -+ { 230, 1095 }, /*C/N=23.0dB*/ -+ { 240, 992 }, /*C/N=24.0dB*/ -+ { 250, 900 }, /*C/N=25.0dB*/ -+ { 260, 826 }, /*C/N=26.0dB*/ -+ { 270, 758 }, /*C/N=27.0dB*/ -+ { 280, 702 }, /*C/N=28.0dB*/ -+ { 290, 653 }, /*C/N=29.0dB*/ -+ { 300, 613 }, /*C/N=30.0dB*/ -+ { 310, 579 }, /*C/N=31.0dB*/ -+ { 320, 550 }, /*C/N=32.0dB*/ -+ { 330, 526 }, /*C/N=33.0dB*/ -+ { 350, 490 }, /*C/N=33.0dB*/ -+ { 400, 445 }, /*C/N=40.0dB*/ -+ { 450, 430 }, /*C/N=45.0dB*/ -+ { 500, 426 }, /*C/N=50.0dB*/ -+ { 510, 425 } /*C/N=51.0dB*/ -+}; -+ -+struct SLookup S2_SN_Lookup[] = { -+ { -30, 13950 }, /*C/N=-2.5dB*/ -+ { -25, 13580 }, /*C/N=-2.5dB*/ -+ { -20, 13150 }, /*C/N=-2.0dB*/ -+ { -15, 12760 }, /*C/N=-1.5dB*/ -+ { -10, 12345 }, /*C/N=-1.0dB*/ -+ { -05, 11900 }, /*C/N=-0.5dB*/ -+ { 0, 11520 }, /*C/N= 0dB*/ -+ { 05, 11080 }, /*C/N= 0.5dB*/ -+ { 10, 10630 }, /*C/N= 1.0dB*/ -+ { 15, 10210 }, /*C/N= 1.5dB*/ -+ { 20, 9790 }, /*C/N= 2.0dB*/ -+ { 25, 9390 }, /*C/N= 2.5dB*/ -+ { 30, 8970 }, /*C/N= 3.0dB*/ -+ { 35, 8575 }, /*C/N= 3.5dB*/ -+ { 40, 8180 }, /*C/N= 4.0dB*/ -+ { 45, 7800 }, /*C/N= 4.5dB*/ -+ { 50, 7430 }, /*C/N= 5.0dB*/ -+ { 55, 7080 }, /*C/N= 5.5dB*/ -+ { 60, 6720 }, /*C/N= 6.0dB*/ -+ { 65, 6320 }, /*C/N= 6.5dB*/ -+ { 70, 6060 }, /*C/N= 7.0dB*/ -+ { 75, 5760 }, /*C/N= 7.5dB*/ -+ { 80, 5480 }, /*C/N= 8.0dB*/ -+ { 85, 5200 }, /*C/N= 8.5dB*/ -+ { 90, 4930 }, /*C/N= 9.0dB*/ -+ { 95, 4680 }, /*C/N= 9.5dB*/ -+ { 100, 4425 }, /*C/N=10.0dB*/ -+ { 105, 4210 }, /*C/N=10.5dB*/ -+ { 110, 3980 }, /*C/N=11.0dB*/ -+ { 115, 3765 }, /*C/N=11.5dB*/ -+ { 120, 3570 }, /*C/N=12.0dB*/ -+ { 125, 3315 }, /*C/N=12.5dB*/ -+ { 130, 3140 }, /*C/N=13.0dB*/ -+ { 135, 2980 }, /*C/N=13.5dB*/ -+ { 140, 2820 }, /*C/N=14.0dB*/ -+ { 145, 2670 }, /*C/N=14.5dB*/ -+ { 150, 2535 }, /*C/N=15.0dB*/ -+ { 160, 2270 }, /*C/N=16.0dB*/ -+ { 170, 2035 }, /*C/N=17.0dB*/ -+ { 180, 1825 }, /*C/N=18.0dB*/ -+ { 190, 1650 }, /*C/N=19.0dB*/ -+ { 200, 1485 }, /*C/N=20.0dB*/ -+ { 210, 1340 }, /*C/N=21.0dB*/ -+ { 220, 1212 }, /*C/N=22.0dB*/ -+ { 230, 1100 }, /*C/N=23.0dB*/ -+ { 240, 1000 }, /*C/N=24.0dB*/ -+ { 250, 910 }, /*C/N=25.0dB*/ -+ { 260, 836 }, /*C/N=26.0dB*/ -+ { 270, 772 }, /*C/N=27.0dB*/ -+ { 280, 718 }, /*C/N=28.0dB*/ -+ { 290, 671 }, /*C/N=29.0dB*/ -+ { 300, 635 }, /*C/N=30.0dB*/ -+ { 310, 602 }, /*C/N=31.0dB*/ -+ { 320, 575 }, /*C/N=32.0dB*/ -+ { 330, 550 }, /*C/N=33.0dB*/ -+ { 350, 517 }, /*C/N=35.0dB*/ -+ { 400, 480 }, /*C/N=40.0dB*/ -+ { 450, 466 }, /*C/N=45.0dB*/ -+ { 500, 464 }, /*C/N=50.0dB*/ -+ { 510, 463 }, /*C/N=51.0dB*/ -+}; -+ -+/********************************************************************* -+ * Tracking carrier loop carrier QPSK 1/4 to 8PSK 9/10 long Frame -+ *********************************************************************/ -+static u8 S2CarLoop[] = { -+ /* Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff -+ * 20MPon 20MPoff 30MPon 30MPoff -+ */ -+ -+ /* FE_QPSK_14 */ -+ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x2A, 0x1C, 0x3A, 0x3B, -+ /* FE_QPSK_13 */ -+ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x3A, 0x0C, 0x3A, 0x2B, -+ /* FE_QPSK_25 */ -+ 0x1C, 0x3C, 0x1B, 0x3C, 0x3A, 0x1C, 0x3A, 0x3B, 0x3A, 0x2B, -+ /* FE_QPSK_12 */ -+ 0x0C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, -+ /* FE_QPSK_35 */ -+ 0x1C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, -+ /* FE_QPSK_23 */ -+ 0x2C, 0x2C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, -+ /* FE_QPSK_34 */ -+ 0x3C, 0x2C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, -+ /* FE_QPSK_45 */ -+ 0x0D, 0x3C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, -+ /* FE_QPSK_56 */ -+ 0x1D, 0x3C, 0x0C, 0x2C, 0x2B, 0x1C, 0x1B, 0x3B, 0x0B, 0x1B, -+ /* FE_QPSK_89 */ -+ 0x3D, 0x0D, 0x0C, 0x2C, 0x2B, 0x0C, 0x2B, 0x2B, 0x0B, 0x0B, -+ /* FE_QPSK_910 */ -+ 0x1E, 0x0D, 0x1C, 0x2C, 0x3B, 0x0C, 0x2B, 0x2B, 0x1B, 0x0B, -+ /* FE_8PSK_35 */ -+ 0x28, 0x09, 0x28, 0x09, 0x28, 0x09, 0x28, 0x08, 0x28, 0x27, -+ /* FE_8PSK_23 */ -+ 0x19, 0x29, 0x19, 0x29, 0x19, 0x29, 0x38, 0x19, 0x28, 0x09, -+ /* FE_8PSK_34 */ -+ 0x1A, 0x0B, 0x1A, 0x3A, 0x0A, 0x2A, 0x39, 0x2A, 0x39, 0x1A, -+ /* FE_8PSK_56 */ -+ 0x2B, 0x2B, 0x1B, 0x1B, 0x0B, 0x1B, 0x1A, 0x0B, 0x1A, 0x1A, -+ /* FE_8PSK_89 */ -+ 0x0C, 0x0C, 0x3B, 0x3B, 0x1B, 0x1B, 0x2A, 0x0B, 0x2A, 0x2A, -+ /* FE_8PSK_910 */ -+ 0x0C, 0x1C, 0x0C, 0x3B, 0x2B, 0x1B, 0x3A, 0x0B, 0x2A, 0x2A, -+ -+ /********************************************************************** -+ * Tracking carrier loop carrier 16APSK 2/3 to 32APSK 9/10 long Frame -+ **********************************************************************/ -+ -+ /* Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon -+ * 20MPoff 30MPon 30MPoff -+ */ -+ -+ /* FE_16APSK_23 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x0A, 0x39, 0x0A, 0x29, 0x0A, -+ /* FE_16APSK_34 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0A, 0x2A, 0x0A, 0x1A, 0x0A, -+ /* FE_16APSK_45 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, -+ /* FE_16APSK_56 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, -+ /* FE_16APSK_89 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, -+ /* FE_16APSK_910 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, -+ /* FE_32APSK_34 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_45 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_56 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_89 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_910 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+}; -+ -+static u8 get_optim_cloop(struct stv *state, -+ enum FE_STV0910_ModCod ModCod, u32 Pilots) -+{ -+ int i = 0; -+ -+ if (ModCod >= FE_32APSK_910) -+ i = ((int)FE_32APSK_910 - (int)FE_QPSK_14) * 10; -+ else if (ModCod >= FE_QPSK_14) -+ i = ((int)ModCod - (int)FE_QPSK_14) * 10; -+ -+ if (state->SymbolRate <= 3000000) -+ i += 0; -+ else if (state->SymbolRate <= 7000000) -+ i += 2; -+ else if (state->SymbolRate <= 15000000) -+ i += 4; -+ else if (state->SymbolRate <= 25000000) -+ i += 6; -+ else -+ i += 8; -+ -+ if (!Pilots) -+ i += 1; -+ -+ return S2CarLoop[i]; -+} -+ -+static int GetCurSymbolRate(struct stv *state, u32 *pSymbolRate) -+{ -+ int status = 0; -+ u8 SymbFreq0; -+ u8 SymbFreq1; -+ u8 SymbFreq2; -+ u8 SymbFreq3; -+ u8 TimOffs0; -+ u8 TimOffs1; -+ u8 TimOffs2; -+ u32 SymbolRate; -+ s32 TimingOffset; -+ -+ *pSymbolRate = 0; -+ if (!state->Started) -+ return status; -+ -+ read_reg(state, RSTV0910_P2_SFR3 + state->regoff, &SymbFreq3); -+ read_reg(state, RSTV0910_P2_SFR2 + state->regoff, &SymbFreq2); -+ read_reg(state, RSTV0910_P2_SFR1 + state->regoff, &SymbFreq1); -+ read_reg(state, RSTV0910_P2_SFR0 + state->regoff, &SymbFreq0); -+ read_reg(state, RSTV0910_P2_TMGREG2 + state->regoff, &TimOffs2); -+ read_reg(state, RSTV0910_P2_TMGREG1 + state->regoff, &TimOffs1); -+ read_reg(state, RSTV0910_P2_TMGREG0 + state->regoff, &TimOffs0); -+ -+ SymbolRate = ((u32) SymbFreq3 << 24) | ((u32) SymbFreq2 << 16) | -+ ((u32) SymbFreq1 << 8) | (u32) SymbFreq0; -+ TimingOffset = ((u32) TimOffs2 << 16) | ((u32) TimOffs1 << 8) | -+ (u32) TimOffs0; -+ -+ if ((TimingOffset & (1<<23)) != 0) -+ TimingOffset |= 0xFF000000; /* Sign extent */ -+ -+ SymbolRate = (u32) (((u64) SymbolRate * state->base->mclk) >> 32); -+ TimingOffset = (s32) (((s64) SymbolRate * (s64) TimingOffset) >> 29); -+ -+ *pSymbolRate = SymbolRate + TimingOffset; -+ -+ return 0; -+} -+ -+static int GetSignalParameters(struct stv *state) -+{ -+ if (!state->Started) -+ return -EINVAL; -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ u8 tmp; -+ u8 rolloff; -+ -+ read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); -+ state->ModCod = (enum FE_STV0910_ModCod) ((tmp & 0x7c) >> 2); -+ state->Pilots = (tmp & 0x01) != 0; -+ state->FECType = (enum DVBS2_FECType) ((tmp & 0x02) >> 1); -+ -+ read_reg(state, RSTV0910_P2_TMGOBS + state->regoff, &rolloff); -+ rolloff = rolloff >> 6; -+ state->FERollOff = (enum FE_STV0910_RollOff) rolloff; -+ -+ } else if (state->ReceiveMode == Mode_DVBS) { -+ /* todo */ -+ } -+ return 0; -+} -+ -+static int TrackingOptimization(struct stv *state) -+{ -+ u32 SymbolRate = 0; -+ u8 tmp; -+ -+ GetCurSymbolRate(state, &SymbolRate); -+ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, &tmp); -+ tmp &= ~0xC0; -+ -+ switch (state->ReceiveMode) { -+ case Mode_DVBS: -+ tmp |= 0x40; break; -+ case Mode_DVBS2: -+ tmp |= 0x80; break; -+ default: -+ tmp |= 0xC0; break; -+ } -+ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, tmp); -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ /* force to PRE BCH Rate */ -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ BER_SRC_S2 | state->BERScale); -+ -+ if (state->FECType == DVBS2_64K) { -+ u8 aclc = get_optim_cloop(state, state->ModCod, -+ state->Pilots); -+ -+ if (state->ModCod <= FE_QPSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, aclc); -+ } else if (state->ModCod <= FE_8PSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, 0x2a); -+ write_reg(state, RSTV0910_P2_ACLC2S28 + -+ state->regoff, aclc); -+ } else if (state->ModCod <= FE_16APSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, 0x2a); -+ write_reg(state, RSTV0910_P2_ACLC2S216A + -+ state->regoff, aclc); -+ } else if (state->ModCod <= FE_32APSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, 0x2a); -+ write_reg(state, RSTV0910_P2_ACLC2S232A + -+ state->regoff, aclc); -+ } -+ } -+ } -+ if (state->ReceiveMode == Mode_DVBS) { -+ u8 tmp; -+ -+ read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); -+ state->PunctureRate = FEC_NONE; -+ switch (tmp & 0x1F) { -+ case 0x0d: -+ state->PunctureRate = FEC_1_2; -+ break; -+ case 0x12: -+ state->PunctureRate = FEC_2_3; -+ break; -+ case 0x15: -+ state->PunctureRate = FEC_3_4; -+ break; -+ case 0x18: -+ state->PunctureRate = FEC_5_6; -+ break; -+ case 0x1A: -+ state->PunctureRate = FEC_7_8; -+ break; -+ } -+ } -+ return 0; -+} -+ -+static s32 TableLookup(struct SLookup *Table, -+ int TableSize, u16 RegValue) -+{ -+ s32 Value; -+ int imin = 0; -+ int imax = TableSize - 1; -+ int i; -+ s32 RegDiff; -+ -+ /* Assumes Table[0].RegValue > Table[imax].RegValue */ -+ if (RegValue >= Table[0].RegValue) -+ Value = Table[0].Value; -+ else if (RegValue <= Table[imax].RegValue) -+ Value = Table[imax].Value; -+ else { -+ while (imax-imin > 1) { -+ i = (imax + imin) / 2; -+ if ((Table[imin].RegValue >= RegValue) && -+ (RegValue >= Table[i].RegValue)) -+ imax = i; -+ else -+ imin = i; -+ } -+ -+ RegDiff = Table[imax].RegValue - Table[imin].RegValue; -+ Value = Table[imin].Value; -+ if (RegDiff != 0) -+ Value += ((s32)(RegValue - Table[imin].RegValue) * -+ (s32)(Table[imax].Value -+ - Table[imin].Value)) -+ / (RegDiff); -+ } -+ -+ return Value; -+} -+ -+static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise) -+{ -+ u8 Data0; -+ u8 Data1; -+ u16 Data; -+ int nLookup; -+ struct SLookup *Lookup; -+ -+ *SignalToNoise = 0; -+ -+ if (!state->Started) -+ return 0; -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ read_reg(state, RSTV0910_P2_NNOSPLHT1 + state->regoff, &Data1); -+ read_reg(state, RSTV0910_P2_NNOSPLHT0 + state->regoff, &Data0); -+ nLookup = ARRAY_SIZE(S2_SN_Lookup); -+ Lookup = S2_SN_Lookup; -+ } else { -+ read_reg(state, RSTV0910_P2_NNOSDATAT1 + state->regoff, &Data1); -+ read_reg(state, RSTV0910_P2_NNOSDATAT0 + state->regoff, &Data0); -+ nLookup = ARRAY_SIZE(S1_SN_Lookup); -+ Lookup = S1_SN_Lookup; -+ } -+ Data = (((u16)Data1) << 8) | (u16) Data0; -+ *SignalToNoise = TableLookup(Lookup, nLookup, Data); -+ return 0; -+} -+ -+static int GetBitErrorRateS(struct stv *state, u32 *BERNumerator, -+ u32 *BERDenominator) -+{ -+ u8 Regs[3]; -+ -+ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, -+ Regs, 3); -+ -+ if (status) -+ return -EINVAL; -+ -+ if ((Regs[0] & 0x80) == 0) { -+ state->LastBERDenominator = 1 << ((state->BERScale * 2) + -+ 10 + 3); -+ state->LastBERNumerator = ((u32) (Regs[0] & 0x7F) << 16) | -+ ((u32) Regs[1] << 8) | Regs[2]; -+ if (state->LastBERNumerator < 256 && state->BERScale < 6) { -+ state->BERScale += 1; -+ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + -+ state->regoff, -+ 0x20 | state->BERScale); -+ } else if (state->LastBERNumerator > 1024 && -+ state->BERScale > 2) { -+ state->BERScale -= 1; -+ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + -+ state->regoff, 0x20 | -+ state->BERScale); -+ } -+ } -+ *BERNumerator = state->LastBERNumerator; -+ *BERDenominator = state->LastBERDenominator; -+ return 0; -+} -+ -+static u32 DVBS2_nBCH(enum DVBS2_ModCod ModCod, enum DVBS2_FECType FECType) -+{ -+ static u32 nBCH[][2] = { -+ {16200, 3240}, /* QPSK_1_4, */ -+ {21600, 5400}, /* QPSK_1_3, */ -+ {25920, 6480}, /* QPSK_2_5, */ -+ {32400, 7200}, /* QPSK_1_2, */ -+ {38880, 9720}, /* QPSK_3_5, */ -+ {43200, 10800}, /* QPSK_2_3, */ -+ {48600, 11880}, /* QPSK_3_4, */ -+ {51840, 12600}, /* QPSK_4_5, */ -+ {54000, 13320}, /* QPSK_5_6, */ -+ {57600, 14400}, /* QPSK_8_9, */ -+ {58320, 16000}, /* QPSK_9_10, */ -+ {43200, 9720}, /* 8PSK_3_5, */ -+ {48600, 10800}, /* 8PSK_2_3, */ -+ {51840, 11880}, /* 8PSK_3_4, */ -+ {54000, 13320}, /* 8PSK_5_6, */ -+ {57600, 14400}, /* 8PSK_8_9, */ -+ {58320, 16000}, /* 8PSK_9_10, */ -+ {43200, 10800}, /* 16APSK_2_3, */ -+ {48600, 11880}, /* 16APSK_3_4, */ -+ {51840, 12600}, /* 16APSK_4_5, */ -+ {54000, 13320}, /* 16APSK_5_6, */ -+ {57600, 14400}, /* 16APSK_8_9, */ -+ {58320, 16000}, /* 16APSK_9_10 */ -+ {48600, 11880}, /* 32APSK_3_4, */ -+ {51840, 12600}, /* 32APSK_4_5, */ -+ {54000, 13320}, /* 32APSK_5_6, */ -+ {57600, 14400}, /* 32APSK_8_9, */ -+ {58320, 16000}, /* 32APSK_9_10 */ -+ }; -+ -+ if (ModCod >= DVBS2_QPSK_1_4 && -+ ModCod <= DVBS2_32APSK_9_10 && FECType <= DVBS2_16K) -+ return nBCH[FECType][ModCod]; -+ return 64800; -+} -+ -+static int GetBitErrorRateS2(struct stv *state, u32 *BERNumerator, -+ u32 *BERDenominator) -+{ -+ u8 Regs[3]; -+ -+ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, -+ Regs, 3); -+ -+ if (status) -+ return -EINVAL; -+ -+ if ((Regs[0] & 0x80) == 0) { -+ state->LastBERDenominator = -+ DVBS2_nBCH((enum DVBS2_ModCod) state->ModCod, -+ state->FECType) << -+ (state->BERScale * 2); -+ state->LastBERNumerator = (((u32) Regs[0] & 0x7F) << 16) | -+ ((u32) Regs[1] << 8) | Regs[2]; -+ if (state->LastBERNumerator < 256 && state->BERScale < 6) { -+ state->BERScale += 1; -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ 0x20 | state->BERScale); -+ } else if (state->LastBERNumerator > 1024 && -+ state->BERScale > 2) { -+ state->BERScale -= 1; -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ 0x20 | state->BERScale); -+ } -+ } -+ *BERNumerator = state->LastBERNumerator; -+ *BERDenominator = state->LastBERDenominator; -+ return status; -+} -+ -+static int GetBitErrorRate(struct stv *state, u32 *BERNumerator, -+ u32 *BERDenominator) -+{ -+ *BERNumerator = 0; -+ *BERDenominator = 1; -+ -+ switch (state->ReceiveMode) { -+ case Mode_DVBS: -+ return GetBitErrorRateS(state, BERNumerator, BERDenominator); -+ case Mode_DVBS2: -+ return GetBitErrorRateS2(state, BERNumerator, BERDenominator); -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static int set_mclock(struct stv *state, u32 MasterClock) -+{ -+ u32 idf = 1; -+ u32 odf = 4; -+ u32 quartz = state->base->extclk / 1000000; -+ u32 Fphi = MasterClock / 1000000; -+ u32 ndiv = (Fphi * odf * idf) / quartz; -+ u32 cp = 7; -+ u32 fvco; -+ -+ if (ndiv >= 7 && ndiv <= 71) -+ cp = 7; -+ else if (ndiv >= 72 && ndiv <= 79) -+ cp = 8; -+ else if (ndiv >= 80 && ndiv <= 87) -+ cp = 9; -+ else if (ndiv >= 88 && ndiv <= 95) -+ cp = 10; -+ else if (ndiv >= 96 && ndiv <= 103) -+ cp = 11; -+ else if (ndiv >= 104 && ndiv <= 111) -+ cp = 12; -+ else if (ndiv >= 112 && ndiv <= 119) -+ cp = 13; -+ else if (ndiv >= 120 && ndiv <= 127) -+ cp = 14; -+ else if (ndiv >= 128 && ndiv <= 135) -+ cp = 15; -+ else if (ndiv >= 136 && ndiv <= 143) -+ cp = 16; -+ else if (ndiv >= 144 && ndiv <= 151) -+ cp = 17; -+ else if (ndiv >= 152 && ndiv <= 159) -+ cp = 18; -+ else if (ndiv >= 160 && ndiv <= 167) -+ cp = 19; -+ else if (ndiv >= 168 && ndiv <= 175) -+ cp = 20; -+ else if (ndiv >= 176 && ndiv <= 183) -+ cp = 21; -+ else if (ndiv >= 184 && ndiv <= 191) -+ cp = 22; -+ else if (ndiv >= 192 && ndiv <= 199) -+ cp = 23; -+ else if (ndiv >= 200 && ndiv <= 207) -+ cp = 24; -+ else if (ndiv >= 208 && ndiv <= 215) -+ cp = 25; -+ else if (ndiv >= 216 && ndiv <= 223) -+ cp = 26; -+ else if (ndiv >= 224 && ndiv <= 225) -+ cp = 27; -+ -+ write_reg(state, RSTV0910_NCOARSE, (cp << 3) | idf); -+ write_reg(state, RSTV0910_NCOARSE2, odf); -+ write_reg(state, RSTV0910_NCOARSE1, ndiv); -+ -+ fvco = (quartz * 2 * ndiv) / idf; -+ state->base->mclk = fvco / (2 * odf) * 1000000; -+ -+ return 0; -+} -+ -+static int Stop(struct stv *state) -+{ -+ if (state->Started) { -+ u8 tmp; -+ -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh | 0x01); -+ read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); -+ tmp &= ~0x01; /*release reset DVBS2 packet delin*/ -+ write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); -+ /* Blind optim*/ -+ write_reg(state, RSTV0910_P2_AGC2O + state->regoff, 0x5B); -+ /* Stop the demod */ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5c); -+ state->Started = 0; -+ } -+ state->ReceiveMode = Mode_None; -+ return 0; -+} -+ -+ -+static int Start(struct stv *state, struct dtv_frontend_properties *p) -+{ -+ s32 Freq; -+ u8 regDMDCFGMD; -+ u16 symb; -+ -+ if (p->symbol_rate < 100000 || p->symbol_rate > 70000000) -+ return -EINVAL; -+ -+ state->ReceiveMode = Mode_None; -+ state->DemodLockTime = 0; -+ -+ /* Demod Stop*/ -+ if (state->Started) -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5C); -+ -+ if (p->symbol_rate <= 1000000) { /*SR <=1Msps*/ -+ state->DemodTimeout = 3000; -+ state->FecTimeout = 2000; -+ } else if (p->symbol_rate <= 2000000) { /*1Msps < SR <=2Msps*/ -+ state->DemodTimeout = 2500; -+ state->FecTimeout = 1300; -+ } else if (p->symbol_rate <= 5000000) { /*2Msps< SR <=5Msps*/ -+ state->DemodTimeout = 1000; -+ state->FecTimeout = 650; -+ } else if (p->symbol_rate <= 10000000) { /*5Msps< SR <=10Msps*/ -+ state->DemodTimeout = 700; -+ state->FecTimeout = 350; -+ } else if (p->symbol_rate < 20000000) { /*10Msps< SR <=20Msps*/ -+ state->DemodTimeout = 400; -+ state->FecTimeout = 200; -+ } else { /*SR >=20Msps*/ -+ state->DemodTimeout = 300; -+ state->FecTimeout = 200; -+ } -+ -+ /* Set the Init Symbol rate*/ -+ symb = MulDiv32(p->symbol_rate, 65536, state->base->mclk); -+ write_reg(state, RSTV0910_P2_SFRINIT1 + state->regoff, -+ ((symb >> 8) & 0x7F)); -+ write_reg(state, RSTV0910_P2_SFRINIT0 + state->regoff, (symb & 0xFF)); -+ -+ state->DEMOD |= 0x80; -+ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, state->DEMOD); -+ -+ /* FE_STV0910_SetSearchStandard */ -+ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ®DMDCFGMD); -+ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, -+ regDMDCFGMD |= 0xC0); -+ -+ /* Disable DSS */ -+ write_reg(state, RSTV0910_P2_FECM + state->regoff, 0x00); -+ write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2F); -+ -+ /* 8PSK 3/5, 8PSK 2/3 Poff tracking optimization WA*/ -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + state->regoff, 0x0B); -+ write_reg(state, RSTV0910_P2_ACLC2S28 + state->regoff, 0x0A); -+ write_reg(state, RSTV0910_P2_BCLC2S2Q + state->regoff, 0x84); -+ write_reg(state, RSTV0910_P2_BCLC2S28 + state->regoff, 0x84); -+ write_reg(state, RSTV0910_P2_CARHDR + state->regoff, 0x1C); -+ /* Reset demod */ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); -+ -+ write_reg(state, RSTV0910_P2_CARCFG + state->regoff, 0x46); -+ -+ Freq = (state->SearchRange / 2000) + 600; -+ if (p->symbol_rate <= 5000000) -+ Freq -= (600 + 80); -+ Freq = (Freq << 16) / (state->base->mclk / 1000); -+ -+ write_reg(state, RSTV0910_P2_CFRUP1 + state->regoff, -+ (Freq >> 8) & 0xff); -+ write_reg(state, RSTV0910_P2_CFRUP0 + state->regoff, (Freq & 0xff)); -+ /*CFR Low Setting*/ -+ Freq = -Freq; -+ write_reg(state, RSTV0910_P2_CFRLOW1 + state->regoff, -+ (Freq >> 8) & 0xff); -+ write_reg(state, RSTV0910_P2_CFRLOW0 + state->regoff, (Freq & 0xff)); -+ -+ /* init the demod frequency offset to 0 */ -+ write_reg(state, RSTV0910_P2_CFRINIT1 + state->regoff, 0); -+ write_reg(state, RSTV0910_P2_CFRINIT0 + state->regoff, 0); -+ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); -+ /* Trigger acq */ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x15); -+ -+ state->DemodLockTime += TUNING_DELAY; -+ state->Started = 1; -+ -+ return 0; -+} -+ -+static int init_diseqc(struct stv *state) -+{ -+ u16 offs = state->nr ? 0x40 : 0; /* Address offset */ -+ u8 Freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); -+ -+ /* Disable receiver */ -+ write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ -+ write_reg(state, RSTV0910_P1_DISTXF22 + offs, Freq); -+ return 0; -+} -+ -+static int probe(struct stv *state) -+{ -+ u8 id; -+ -+ state->ReceiveMode = Mode_None; -+ state->Started = 0; -+ -+ if (read_reg(state, RSTV0910_MID, &id) < 0) -+ return -ENODEV; -+ -+ if (id != 0x51) -+ return -EINVAL; -+ -+ /* Configure the I2C repeater to off */ -+ write_reg(state, RSTV0910_P1_I2CRPT, 0x24); -+ /* Configure the I2C repeater to off */ -+ write_reg(state, RSTV0910_P2_I2CRPT, 0x24); -+ /* Set the I2C to oversampling ratio */ -+ write_reg(state, RSTV0910_I2CCFG, 0x88); -+ -+ write_reg(state, RSTV0910_OUTCFG, 0x00); /* OUTCFG */ -+ write_reg(state, RSTV0910_PADCFG, 0x05); /* RF AGC Pads Dev = 05 */ -+ write_reg(state, RSTV0910_SYNTCTRL, 0x02); /* SYNTCTRL */ -+ write_reg(state, RSTV0910_TSGENERAL, state->tsgeneral); /* TSGENERAL */ -+ write_reg(state, RSTV0910_CFGEXT, 0x02); /* CFGEXT */ -+ write_reg(state, RSTV0910_GENCFG, 0x15); /* GENCFG */ -+ -+ -+ write_reg(state, RSTV0910_TSTRES0, 0x80); /* LDPC Reset */ -+ write_reg(state, RSTV0910_TSTRES0, 0x00); -+ -+ set_mclock(state, 135000000); -+ -+ /* TS output */ -+ write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh); -+ write_reg(state, RSTV0910_P1_TSCFGM, 0xC0); /* Manual speed */ -+ write_reg(state, RSTV0910_P1_TSCFGL, 0x20); -+ -+ /* Speed = 67.5 MHz */ -+ write_reg(state, RSTV0910_P1_TSSPEED, state->tsspeed); -+ -+ write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh); -+ write_reg(state, RSTV0910_P2_TSCFGM, 0xC0); /* Manual speed */ -+ write_reg(state, RSTV0910_P2_TSCFGL, 0x20); -+ -+ /* Speed = 67.5 MHz */ -+ write_reg(state, RSTV0910_P2_TSSPEED, state->tsspeed); -+ -+ /* Reset stream merger */ -+ write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh); -+ write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh); -+ -+ write_reg(state, RSTV0910_P1_I2CRPT, state->i2crpt); -+ write_reg(state, RSTV0910_P2_I2CRPT, state->i2crpt); -+ -+ init_diseqc(state); -+ return 0; -+} -+ -+ -+static int gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u8 i2crpt = state->i2crpt & ~0x86; -+ -+ if (enable) -+ mutex_lock(&state->base->i2c_lock); -+ -+ if (enable) -+ i2crpt |= 0x80; -+ else -+ i2crpt |= 0x02; -+ -+ if (write_reg(state, state->nr ? RSTV0910_P2_I2CRPT : -+ RSTV0910_P1_I2CRPT, i2crpt) < 0) -+ return -EIO; -+ -+ state->i2crpt = i2crpt; -+ -+ if (!enable) -+ mutex_unlock(&state->base->i2c_lock); -+ return 0; -+} -+ -+static void release(struct dvb_frontend *fe) -+{ -+ struct stv *state = fe->demodulator_priv; -+ -+ state->base->count--; -+ if (state->base->count == 0) { -+ list_del(&state->base->stvlist); -+ kfree(state->base); -+ } -+ kfree(state); -+} -+ -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ int stat = 0; -+ struct stv *state = fe->demodulator_priv; -+ u32 IF; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ -+ Stop(state); -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ if (fe->ops.tuner_ops.get_if_frequency) -+ fe->ops.tuner_ops.get_if_frequency(fe, &IF); -+ state->SymbolRate = p->symbol_rate; -+ stat = Start(state, p); -+ return stat; -+} -+ -+static int read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct stv *state = fe->demodulator_priv; -+ s32 SNR; -+ -+ *snr = 0; -+ if (GetSignalToNoise(state, &SNR)) -+ return -EIO; -+ -+ *snr = 100 * SNR; -+ -+ return 0; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber, u32 *n, u32 *d) -+{ -+ struct stv *state = fe->demodulator_priv; -+ -+ *n = 0; -+ *d = 1; -+ -+ GetBitErrorRate(state, n, d); -+ if (d) -+ *ber = *n / *d; -+ else -+ *ber = 0; -+ -+ return 0; -+} -+ -+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u8 Reg[2]; -+ s32 bbgain; -+ s32 Power = 0; -+ int i; -+ -+ read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2); -+ -+ *strength = (((u32) Reg[0]) << 8) | Reg[1]; -+ -+ for (i = 0; i < 5; i += 1) { -+ read_regs(state, RSTV0910_P2_POWERI + state->regoff, Reg, 2); -+ Power += (u32) Reg[0] * (u32) Reg[0] -+ + (u32) Reg[1] * (u32) Reg[1]; -+ usleep_range(3000, 4000); -+ } -+ Power /= 5; -+ -+ bbgain = (465 - INTLOG10X100(Power)) * 10; -+ -+ if (fe->ops.tuner_ops.get_rf_strength) -+ fe->ops.tuner_ops.get_rf_strength(fe, strength); -+ else -+ *strength = 0; -+ -+ if (bbgain < (s32) *strength) -+ *strength -= bbgain; -+ else -+ *strength = 0; -+ -+ if (*strength > 0) -+ *strength = 10 * (s64) (s16) *strength - 108750; -+ -+ return 0; -+} -+ -+static int read_status(struct dvb_frontend *fe, enum fe_status *status) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u8 DmdState = 0; -+ u8 DStatus = 0; -+ enum ReceiveMode CurReceiveMode = Mode_None; -+ u32 FECLock = 0; -+ -+ read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &DmdState); -+ -+ if (DmdState & 0x40) { -+ read_reg(state, RSTV0910_P2_DSTATUS + state->regoff, &DStatus); -+ if (DStatus & 0x08) -+ CurReceiveMode = (DmdState & 0x20) ? -+ Mode_DVBS : Mode_DVBS2; -+ } -+ if (CurReceiveMode == Mode_None) { -+ *status = 0; -+ return 0; -+ } -+ -+ *status |= (FE_HAS_SIGNAL -+ | FE_HAS_CARRIER -+ | FE_HAS_VITERBI -+ | FE_HAS_SYNC); -+ -+ if (state->ReceiveMode == Mode_None) { -+ state->ReceiveMode = CurReceiveMode; -+ state->DemodLockTime = jiffies; -+ state->FirstTimeLock = 1; -+ -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh); -+ usleep_range(3000, 4000); -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh); -+ } -+ if (DmdState & 0x40) { -+ if (state->ReceiveMode == Mode_DVBS2) { -+ u8 PDELStatus; -+ -+ read_reg(state, -+ RSTV0910_P2_PDELSTATUS1 + state->regoff, -+ &PDELStatus); -+ FECLock = (PDELStatus & 0x02) != 0; -+ } else { -+ u8 VStatus; -+ -+ read_reg(state, -+ RSTV0910_P2_VSTATUSVIT + state->regoff, -+ &VStatus); -+ FECLock = (VStatus & 0x08) != 0; -+ } -+ } -+ -+ if (!FECLock) -+ return 0; -+ -+ *status |= FE_HAS_LOCK; -+ -+ if (state->FirstTimeLock) { -+ u8 tmp; -+ -+ state->FirstTimeLock = 0; -+ GetSignalParameters(state); -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ /* FSTV0910_P2_MANUALSX_ROLLOFF, -+ * FSTV0910_P2_MANUALS2_ROLLOFF = 0 -+ */ -+ state->DEMOD &= ~0x84; -+ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, -+ state->DEMOD); -+ read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, -+ &tmp); -+ /*reset DVBS2 packet delinator error counter */ -+ tmp |= 0x40; -+ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, -+ tmp); -+ /*reset DVBS2 packet delinator error counter */ -+ tmp &= ~0x40; -+ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, -+ tmp); -+ -+ state->BERScale = 2; -+ state->LastBERNumerator = 0; -+ state->LastBERDenominator = 1; -+ /* force to PRE BCH Rate */ -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ BER_SRC_S2 | state->BERScale); -+ } else { -+ state->BERScale = 2; -+ state->LastBERNumerator = 0; -+ state->LastBERDenominator = 1; -+ /* force to PRE RS Rate */ -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ BER_SRC_S | state->BERScale); -+ } -+ /*Reset the Total packet counter */ -+ write_reg(state, RSTV0910_P2_FBERCPT4 + state->regoff, 0x00); -+ /* Reset the packet Error counter2 (and Set it to -+ * infinit error count mode ) -+ */ -+ write_reg(state, RSTV0910_P2_ERRCTRL2 + state->regoff, 0xc1); -+ -+ TrackingOptimization(state); -+ } -+ return 0; -+} -+ -+static int get_frontend(struct dvb_frontend *fe, -+ struct dtv_frontend_properties *p) -+{ -+ struct stv *state = fe->demodulator_priv; -+ enum fe_status status; -+ u16 snr = 0, strength = 0; -+ u32 ber = 0, bernom = 0, berdenom = 0; -+ u8 tmp; -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ u32 mc; -+ enum fe_modulation modcod2mod[0x20] = { -+ QPSK, QPSK, QPSK, QPSK, -+ QPSK, QPSK, QPSK, QPSK, -+ QPSK, QPSK, QPSK, QPSK, -+ PSK_8, PSK_8, PSK_8, PSK_8, -+ PSK_8, PSK_8, APSK_16, APSK_16, -+ APSK_16, APSK_16, APSK_16, APSK_16, -+ APSK_32, APSK_32, APSK_32, APSK_32, -+ APSK_32, -+ }; -+ enum fe_code_rate modcod2fec[0x20] = { -+ FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5, -+ FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4, -+ FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, -+ FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6, -+ FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4, -+ FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, -+ FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9, -+ FEC_9_10 -+ }; -+ read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); -+ mc = ((tmp & 0x7c) >> 2); -+ p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF; -+ p->modulation = modcod2mod[mc]; -+ p->fec_inner = modcod2fec[mc]; -+ } else if (state->ReceiveMode == Mode_DVBS) { -+ read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); -+ switch (tmp & 0x1F) { -+ case 0x0d: -+ p->fec_inner = FEC_1_2; -+ break; -+ case 0x12: -+ p->fec_inner = FEC_2_3; -+ break; -+ case 0x15: -+ p->fec_inner = FEC_3_4; -+ break; -+ case 0x18: -+ p->fec_inner = FEC_5_6; -+ break; -+ case 0x1a: -+ p->fec_inner = FEC_7_8; -+ break; -+ default: -+ p->fec_inner = FEC_NONE; -+ break; -+ } -+ p->rolloff = ROLLOFF_35; -+ } -+ -+ tmp = read_status(fe, &status); -+ -+ p->strength.len = 1; -+ p->cnr.len = 1; -+ p->pre_bit_error.len = 1; -+ p->pre_bit_count.len = 1; -+ p->post_bit_error.len = 1; -+ -+ if (!(status & FE_HAS_LOCK)) { -+ p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ p->cnr.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; -+ return 0; -+ } -+ -+ if (read_snr(fe, &snr)) -+ p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->cnr.stat[0].scale = FE_SCALE_DECIBEL; -+ p->cnr.stat[0].svalue = snr; -+ } -+ -+ if (read_signal_strength(fe, &strength)) -+ p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ else { -+ p->strength.stat[0].scale = FE_SCALE_DECIBEL; -+ p->strength.stat[0].svalue = strength; -+ } -+ -+ if (read_ber(fe, &ber, &bernom, &berdenom)) { -+ 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; -+ } else { -+ p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->pre_bit_error.stat[0].uvalue = bernom; -+ p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; -+ p->pre_bit_count.stat[0].uvalue = berdenom; -+ p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; -+ p->post_bit_error.stat[0].uvalue = ber; -+ } -+ -+ return 0; -+} -+ -+static int tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, -+ unsigned int *delay, enum fe_status *status) -+{ -+ struct stv *state = fe->demodulator_priv; -+ int r; -+ -+ if (re_tune) { -+ r = set_parameters(fe); -+ if (r) -+ return r; -+ state->tune_time = jiffies; -+ } -+ if (*status & FE_HAS_LOCK) -+ return 0; -+ *delay = HZ; -+ -+ r = read_status(fe, status); -+ if (r) -+ return r; -+ return 0; -+} -+ -+ -+static int get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+ -+static int set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u16 offs = state->nr ? 0x40 : 0; -+ -+ switch (tone) { -+ case SEC_TONE_ON: -+ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x38); -+ case SEC_TONE_OFF: -+ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3a); -+ default: -+ break; -+ } -+ return -EINVAL; -+} -+ -+static int wait_dis(struct stv *state, u8 flag, u8 val) -+{ -+ int i; -+ u8 stat; -+ u16 offs = state->nr ? 0x40 : 0; -+ -+ for (i = 0; i < 10; i++) { -+ read_reg(state, RSTV0910_P1_DISTXSTATUS + offs, &stat); -+ if ((stat & flag) == val) -+ return 0; -+ usleep_range(10000, 11000); -+ } -+ return -ETIMEDOUT; -+} -+ -+static int send_master_cmd(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *cmd) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u16 offs = state->nr ? 0x40 : 0; -+ int i; -+ -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E); -+ for (i = 0; i < cmd->msg_len; i++) { -+ wait_dis(state, 0x40, 0x00); -+ write_reg(state, RSTV0910_P1_DISTXFIFO + offs, cmd->msg[i]); -+ } -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); -+ wait_dis(state, 0x20, 0x20); -+ return 0; -+} -+ -+static int sleep(struct dvb_frontend *fe) -+{ -+ struct stv *state = fe->demodulator_priv; -+ -+ Stop(state); -+ return 0; -+} -+ -+static struct dvb_frontend_ops stv0910_ops = { -+ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, -+ .info = { -+ .name = "STV0910", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_stepsize = 0, -+ .frequency_tolerance = 0, -+ .symbol_rate_min = 1000000, -+ .symbol_rate_max = 70000000, -+ .caps = FE_CAN_INVERSION_AUTO | -+ FE_CAN_FEC_AUTO | -+ FE_CAN_QPSK | -+ FE_CAN_2G_MODULATION -+ }, -+ .sleep = sleep, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ .get_frontend_algo = get_algo, -+ .get_frontend = get_frontend, -+ .tune = tune, -+ .read_status = read_status, -+ .set_tone = set_tone, -+ -+ .diseqc_send_master_cmd = send_master_cmd, -+}; -+ -+static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr) -+{ -+ struct stv_base *p; -+ -+ list_for_each_entry(p, &stvlist, stvlist) -+ if (p->i2c == i2c && p->adr == adr) -+ return p; -+ return NULL; -+} -+ -+struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, -+ struct stv0910_cfg *cfg, -+ int nr) -+{ -+ struct stv *state; -+ struct stv_base *base; -+ -+ state = kzalloc(sizeof(struct stv), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40); -+ state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00; -+ state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4); -+ state->tsspeed = 0x28; -+ state->nr = nr; -+ state->regoff = state->nr ? 0 : 0x200; -+ state->SearchRange = 16000000; -+ state->DEMOD = 0x10; /* Inversion : Auto with reset to 0 */ -+ state->ReceiveMode = Mode_None; -+ -+ base = match_base(i2c, cfg->adr); -+ if (base) { -+ base->count++; -+ state->base = base; -+ } else { -+ base = kzalloc(sizeof(struct stv_base), GFP_KERNEL); -+ if (!base) -+ goto fail; -+ base->i2c = i2c; -+ base->adr = cfg->adr; -+ base->count = 1; -+ base->extclk = cfg->clk ? cfg->clk : 30000000; -+ -+ mutex_init(&base->i2c_lock); -+ mutex_init(&base->reg_lock); -+ state->base = base; -+ if (probe(state) < 0) { -+ kfree(base); -+ goto fail; -+ } -+ list_add(&base->stvlist, &stvlist); -+ } -+ state->fe.ops = stv0910_ops; -+ state->fe.demodulator_priv = state; -+ state->nr = nr; -+ -+ return &state->fe; -+ -+fail: -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(stv0910_attach); -+ -+MODULE_DESCRIPTION("STV0910 driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/stv0910.h b/drivers/media/dvb-frontends/stv0910.h -new file mode 100644 -index 0000000..de73fb9 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0910.h -@@ -0,0 +1,31 @@ -+#ifndef _STV0910_H_ -+#define _STV0910_H_ -+ -+#include -+#include -+ -+struct stv0910_cfg { -+ u32 clk; -+ u8 adr; -+ u8 parallel; -+ u8 rptlvl; -+}; -+ -+#if IS_REACHABLE(CONFIG_DVB_STV0910) -+ -+extern struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, -+ struct stv0910_cfg *cfg, int nr); -+ -+#else -+ -+static inline struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, -+ struct stv0910_cfg *cfg, -+ int nr) -+{ -+ pr_warn("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif /* CONFIG_DVB_STV0910 */ -+ -+#endif /* _STV0910_H_ */ -diff --git a/drivers/media/dvb-frontends/stv0910_regs.h b/drivers/media/dvb-frontends/stv0910_regs.h -new file mode 100644 -index 0000000..33cb481 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0910_regs.h -@@ -0,0 +1,3997 @@ -+/* @DVB-S/DVB-S2 STMicroelectronics STV0900 register defintions -+ * Author Manfred Voelkel, August 2013 -+ * (c) 2013 Digital Devices GmbH Germany. All rights reserved -+ * -+ * ======================================================================= -+ * Registers Declaration (Internal ST, All Applications ) -+ * ------------------------- -+ * Each register (RSTV0910__XXXXX) is defined by its address (2 bytes). -+ * -+ * Each field (FSTV0910__XXXXX)is defined as follow: -+ * [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] -+ * ====================================================================== -+ */ -+ -+/*MID*/ -+#define RSTV0910_MID 0xf100 -+#define FSTV0910_MCHIP_IDENT 0xf10000f0 -+#define FSTV0910_MRELEASE 0xf100000f -+ -+/*DID*/ -+#define RSTV0910_DID 0xf101 -+#define FSTV0910_DEVICE_ID 0xf10100ff -+ -+/*DACR1*/ -+#define RSTV0910_DACR1 0xf113 -+#define FSTV0910_DAC_MODE 0xf11300e0 -+#define FSTV0910_DAC_VALUE1 0xf113000f -+ -+/*DACR2*/ -+#define RSTV0910_DACR2 0xf114 -+#define FSTV0910_DAC_VALUE0 0xf11400ff -+ -+/*PADCFG*/ -+#define RSTV0910_PADCFG 0xf11a -+#define FSTV0910_AGCRF2_OPD 0xf11a0008 -+#define FSTV0910_AGCRF2_XOR 0xf11a0004 -+#define FSTV0910_AGCRF1_OPD 0xf11a0002 -+#define FSTV0910_AGCRF1_XOR 0xf11a0001 -+ -+/*OUTCFG2*/ -+#define RSTV0910_OUTCFG2 0xf11b -+#define FSTV0910_TS2_ERROR_XOR 0xf11b0080 -+#define FSTV0910_TS2_DPN_XOR 0xf11b0040 -+#define FSTV0910_TS2_STROUT_XOR 0xf11b0020 -+#define FSTV0910_TS2_CLOCKOUT_XOR 0xf11b0010 -+#define FSTV0910_TS1_ERROR_XOR 0xf11b0008 -+#define FSTV0910_TS1_DPN_XOR 0xf11b0004 -+#define FSTV0910_TS1_STROUT_XOR 0xf11b0002 -+#define FSTV0910_TS1_CLOCKOUT_XOR 0xf11b0001 -+ -+/*OUTCFG*/ -+#define RSTV0910_OUTCFG 0xf11c -+#define FSTV0910_INV_DATA6 0xf11c0080 -+#define FSTV0910_TS2_OUTSER_HZ 0xf11c0020 -+#define FSTV0910_TS1_OUTSER_HZ 0xf11c0010 -+#define FSTV0910_TS2_OUTPAR_HZ 0xf11c0008 -+#define FSTV0910_TS1_OUTPAR_HZ 0xf11c0004 -+#define FSTV0910_TS_SERDATA0 0xf11c0002 -+ -+/*IRQSTATUS3*/ -+#define RSTV0910_IRQSTATUS3 0xf120 -+#define FSTV0910_SPLL_LOCK 0xf1200020 -+#define FSTV0910_SSTREAM_LCK_1 0xf1200010 -+#define FSTV0910_SSTREAM_LCK_2 0xf1200008 -+#define FSTV0910_SDVBS1_PRF_2 0xf1200002 -+#define FSTV0910_SDVBS1_PRF_1 0xf1200001 -+ -+/*IRQSTATUS2*/ -+#define RSTV0910_IRQSTATUS2 0xf121 -+#define FSTV0910_SSPY_ENDSIM_1 0xf1210080 -+#define FSTV0910_SSPY_ENDSIM_2 0xf1210040 -+#define FSTV0910_SPKTDEL_ERROR_2 0xf1210010 -+#define FSTV0910_SPKTDEL_LOCKB_2 0xf1210008 -+#define FSTV0910_SPKTDEL_LOCK_2 0xf1210004 -+#define FSTV0910_SPKTDEL_ERROR_1 0xf1210002 -+#define FSTV0910_SPKTDEL_LOCKB_1 0xf1210001 -+ -+/*IRQSTATUS1*/ -+#define RSTV0910_IRQSTATUS1 0xf122 -+#define FSTV0910_SPKTDEL_LOCK_1 0xf1220080 -+#define FSTV0910_SFEC_LOCKB_2 0xf1220040 -+#define FSTV0910_SFEC_LOCK_2 0xf1220020 -+#define FSTV0910_SFEC_LOCKB_1 0xf1220010 -+#define FSTV0910_SFEC_LOCK_1 0xf1220008 -+#define FSTV0910_SDEMOD_LOCKB_2 0xf1220004 -+#define FSTV0910_SDEMOD_LOCK_2 0xf1220002 -+#define FSTV0910_SDEMOD_IRQ_2 0xf1220001 -+ -+/*IRQSTATUS0*/ -+#define RSTV0910_IRQSTATUS0 0xf123 -+#define FSTV0910_SDEMOD_LOCKB_1 0xf1230080 -+#define FSTV0910_SDEMOD_LOCK_1 0xf1230040 -+#define FSTV0910_SDEMOD_IRQ_1 0xf1230020 -+#define FSTV0910_SBCH_ERRFLAG 0xf1230010 -+#define FSTV0910_SECW2_IRQ 0xf1230008 -+#define FSTV0910_SDISEQC2_IRQ 0xf1230004 -+#define FSTV0910_SECW1_IRQ 0xf1230002 -+#define FSTV0910_SDISEQC1_IRQ 0xf1230001 -+ -+/*IRQMASK3*/ -+#define RSTV0910_IRQMASK3 0xf124 -+#define FSTV0910_MPLL_LOCK 0xf1240020 -+#define FSTV0910_MSTREAM_LCK_1 0xf1240010 -+#define FSTV0910_MSTREAM_LCK_2 0xf1240008 -+#define FSTV0910_MDVBS1_PRF_2 0xf1240002 -+#define FSTV0910_MDVBS1_PRF_1 0xf1240001 -+ -+/*IRQMASK2*/ -+#define RSTV0910_IRQMASK2 0xf125 -+#define FSTV0910_MSPY_ENDSIM_1 0xf1250080 -+#define FSTV0910_MSPY_ENDSIM_2 0xf1250040 -+#define FSTV0910_MPKTDEL_ERROR_2 0xf1250010 -+#define FSTV0910_MPKTDEL_LOCKB_2 0xf1250008 -+#define FSTV0910_MPKTDEL_LOCK_2 0xf1250004 -+#define FSTV0910_MPKTDEL_ERROR_1 0xf1250002 -+#define FSTV0910_MPKTDEL_LOCKB_1 0xf1250001 -+ -+/*IRQMASK1*/ -+#define RSTV0910_IRQMASK1 0xf126 -+#define FSTV0910_MPKTDEL_LOCK_1 0xf1260080 -+#define FSTV0910_MFEC_LOCKB_2 0xf1260040 -+#define FSTV0910_MFEC_LOCK_2 0xf1260020 -+#define FSTV0910_MFEC_LOCKB_1 0xf1260010 -+#define FSTV0910_MFEC_LOCK_1 0xf1260008 -+#define FSTV0910_MDEMOD_LOCKB_2 0xf1260004 -+#define FSTV0910_MDEMOD_LOCK_2 0xf1260002 -+#define FSTV0910_MDEMOD_IRQ_2 0xf1260001 -+ -+/*IRQMASK0*/ -+#define RSTV0910_IRQMASK0 0xf127 -+#define FSTV0910_MDEMOD_LOCKB_1 0xf1270080 -+#define FSTV0910_MDEMOD_LOCK_1 0xf1270040 -+#define FSTV0910_MDEMOD_IRQ_1 0xf1270020 -+#define FSTV0910_MBCH_ERRFLAG 0xf1270010 -+#define FSTV0910_MECW2_IRQ 0xf1270008 -+#define FSTV0910_MDISEQC2_IRQ 0xf1270004 -+#define FSTV0910_MECW1_IRQ 0xf1270002 -+#define FSTV0910_MDISEQC1_IRQ 0xf1270001 -+ -+/*I2CCFG*/ -+#define RSTV0910_I2CCFG 0xf129 -+#define FSTV0910_I2C2_FASTMODE 0xf1290080 -+#define FSTV0910_STATUS_WR2 0xf1290040 -+#define FSTV0910_I2C2ADDR_INC 0xf1290030 -+#define FSTV0910_I2C_FASTMODE 0xf1290008 -+#define FSTV0910_STATUS_WR 0xf1290004 -+#define FSTV0910_I2CADDR_INC 0xf1290003 -+ -+/*P1_I2CRPT*/ -+#define RSTV0910_P1_I2CRPT 0xf12a -+#define FSTV0910_P1_I2CT_ON 0xf12a0080 -+#define FSTV0910_P1_ENARPT_LEVEL 0xf12a0070 -+#define FSTV0910_P1_SCLT_DELAY 0xf12a0008 -+#define FSTV0910_P1_STOP_ENABLE 0xf12a0004 -+#define FSTV0910_P1_STOP_SDAT2SDA 0xf12a0002 -+ -+/*P2_I2CRPT*/ -+#define RSTV0910_P2_I2CRPT 0xf12b -+#define FSTV0910_P2_I2CT_ON 0xf12b0080 -+#define FSTV0910_P2_ENARPT_LEVEL 0xf12b0070 -+#define FSTV0910_P2_SCLT_DELAY 0xf12b0008 -+#define FSTV0910_P2_STOP_ENABLE 0xf12b0004 -+#define FSTV0910_P2_STOP_SDAT2SDA 0xf12b0002 -+ -+/*GPIO0CFG*/ -+#define RSTV0910_GPIO0CFG 0xf140 -+#define FSTV0910_GPIO0_OPD 0xf1400080 -+#define FSTV0910_GPIO0_CONFIG 0xf140007e -+#define FSTV0910_GPIO0_XOR 0xf1400001 -+ -+/*GPIO1CFG*/ -+#define RSTV0910_GPIO1CFG 0xf141 -+#define FSTV0910_GPIO1_OPD 0xf1410080 -+#define FSTV0910_GPIO1_CONFIG 0xf141007e -+#define FSTV0910_GPIO1_XOR 0xf1410001 -+ -+/*GPIO2CFG*/ -+#define RSTV0910_GPIO2CFG 0xf142 -+#define FSTV0910_GPIO2_OPD 0xf1420080 -+#define FSTV0910_GPIO2_CONFIG 0xf142007e -+#define FSTV0910_GPIO2_XOR 0xf1420001 -+ -+/*GPIO3CFG*/ -+#define RSTV0910_GPIO3CFG 0xf143 -+#define FSTV0910_GPIO3_OPD 0xf1430080 -+#define FSTV0910_GPIO3_CONFIG 0xf143007e -+#define FSTV0910_GPIO3_XOR 0xf1430001 -+ -+/*GPIO4CFG*/ -+#define RSTV0910_GPIO4CFG 0xf144 -+#define FSTV0910_GPIO4_OPD 0xf1440080 -+#define FSTV0910_GPIO4_CONFIG 0xf144007e -+#define FSTV0910_GPIO4_XOR 0xf1440001 -+ -+/*GPIO5CFG*/ -+#define RSTV0910_GPIO5CFG 0xf145 -+#define FSTV0910_GPIO5_OPD 0xf1450080 -+#define FSTV0910_GPIO5_CONFIG 0xf145007e -+#define FSTV0910_GPIO5_XOR 0xf1450001 -+ -+/*GPIO6CFG*/ -+#define RSTV0910_GPIO6CFG 0xf146 -+#define FSTV0910_GPIO6_OPD 0xf1460080 -+#define FSTV0910_GPIO6_CONFIG 0xf146007e -+#define FSTV0910_GPIO6_XOR 0xf1460001 -+ -+/*GPIO7CFG*/ -+#define RSTV0910_GPIO7CFG 0xf147 -+#define FSTV0910_GPIO7_OPD 0xf1470080 -+#define FSTV0910_GPIO7_CONFIG 0xf147007e -+#define FSTV0910_GPIO7_XOR 0xf1470001 -+ -+/*GPIO8CFG*/ -+#define RSTV0910_GPIO8CFG 0xf148 -+#define FSTV0910_GPIO8_OPD 0xf1480080 -+#define FSTV0910_GPIO8_CONFIG 0xf148007e -+#define FSTV0910_GPIO8_XOR 0xf1480001 -+ -+/*GPIO9CFG*/ -+#define RSTV0910_GPIO9CFG 0xf149 -+#define FSTV0910_GPIO9_OPD 0xf1490080 -+#define FSTV0910_GPIO9_CONFIG 0xf149007e -+#define FSTV0910_GPIO9_XOR 0xf1490001 -+ -+/*GPIO10CFG*/ -+#define RSTV0910_GPIO10CFG 0xf14a -+#define FSTV0910_GPIO10_OPD 0xf14a0080 -+#define FSTV0910_GPIO10_CONFIG 0xf14a007e -+#define FSTV0910_GPIO10_XOR 0xf14a0001 -+ -+/*GPIO11CFG*/ -+#define RSTV0910_GPIO11CFG 0xf14b -+#define FSTV0910_GPIO11_OPD 0xf14b0080 -+#define FSTV0910_GPIO11_CONFIG 0xf14b007e -+#define FSTV0910_GPIO11_XOR 0xf14b0001 -+ -+/*GPIO12CFG*/ -+#define RSTV0910_GPIO12CFG 0xf14c -+#define FSTV0910_GPIO12_OPD 0xf14c0080 -+#define FSTV0910_GPIO12_CONFIG 0xf14c007e -+#define FSTV0910_GPIO12_XOR 0xf14c0001 -+ -+/*GPIO13CFG*/ -+#define RSTV0910_GPIO13CFG 0xf14d -+#define FSTV0910_GPIO13_OPD 0xf14d0080 -+#define FSTV0910_GPIO13_CONFIG 0xf14d007e -+#define FSTV0910_GPIO13_XOR 0xf14d0001 -+ -+/*GPIO14CFG*/ -+#define RSTV0910_GPIO14CFG 0xf14e -+#define FSTV0910_GPIO14_OPD 0xf14e0080 -+#define FSTV0910_GPIO14_CONFIG 0xf14e007e -+#define FSTV0910_GPIO14_XOR 0xf14e0001 -+ -+/*GPIO15CFG*/ -+#define RSTV0910_GPIO15CFG 0xf14f -+#define FSTV0910_GPIO15_OPD 0xf14f0080 -+#define FSTV0910_GPIO15_CONFIG 0xf14f007e -+#define FSTV0910_GPIO15_XOR 0xf14f0001 -+ -+/*GPIO16CFG*/ -+#define RSTV0910_GPIO16CFG 0xf150 -+#define FSTV0910_GPIO16_OPD 0xf1500080 -+#define FSTV0910_GPIO16_CONFIG 0xf150007e -+#define FSTV0910_GPIO16_XOR 0xf1500001 -+ -+/*GPIO17CFG*/ -+#define RSTV0910_GPIO17CFG 0xf151 -+#define FSTV0910_GPIO17_OPD 0xf1510080 -+#define FSTV0910_GPIO17_CONFIG 0xf151007e -+#define FSTV0910_GPIO17_XOR 0xf1510001 -+ -+/*GPIO18CFG*/ -+#define RSTV0910_GPIO18CFG 0xf152 -+#define FSTV0910_GPIO18_OPD 0xf1520080 -+#define FSTV0910_GPIO18_CONFIG 0xf152007e -+#define FSTV0910_GPIO18_XOR 0xf1520001 -+ -+/*GPIO19CFG*/ -+#define RSTV0910_GPIO19CFG 0xf153 -+#define FSTV0910_GPIO19_OPD 0xf1530080 -+#define FSTV0910_GPIO19_CONFIG 0xf153007e -+#define FSTV0910_GPIO19_XOR 0xf1530001 -+ -+/*GPIO20CFG*/ -+#define RSTV0910_GPIO20CFG 0xf154 -+#define FSTV0910_GPIO20_OPD 0xf1540080 -+#define FSTV0910_GPIO20_CONFIG 0xf154007e -+#define FSTV0910_GPIO20_XOR 0xf1540001 -+ -+/*GPIO21CFG*/ -+#define RSTV0910_GPIO21CFG 0xf155 -+#define FSTV0910_GPIO21_OPD 0xf1550080 -+#define FSTV0910_GPIO21_CONFIG 0xf155007e -+#define FSTV0910_GPIO21_XOR 0xf1550001 -+ -+/*GPIO22CFG*/ -+#define RSTV0910_GPIO22CFG 0xf156 -+#define FSTV0910_GPIO22_OPD 0xf1560080 -+#define FSTV0910_GPIO22_CONFIG 0xf156007e -+#define FSTV0910_GPIO22_XOR 0xf1560001 -+ -+/*STRSTATUS1*/ -+#define RSTV0910_STRSTATUS1 0xf16a -+#define FSTV0910_STRSTATUS_SEL2 0xf16a00f0 -+#define FSTV0910_STRSTATUS_SEL1 0xf16a000f -+ -+/*STRSTATUS2*/ -+#define RSTV0910_STRSTATUS2 0xf16b -+#define FSTV0910_STRSTATUS_SEL4 0xf16b00f0 -+#define FSTV0910_STRSTATUS_SEL3 0xf16b000f -+ -+/*STRSTATUS3*/ -+#define RSTV0910_STRSTATUS3 0xf16c -+#define FSTV0910_STRSTATUS_SEL6 0xf16c00f0 -+#define FSTV0910_STRSTATUS_SEL5 0xf16c000f -+ -+/*FSKTFC2*/ -+#define RSTV0910_FSKTFC2 0xf170 -+#define FSTV0910_FSKT_KMOD 0xf17000fc -+#define FSTV0910_FSKT_CAR2 0xf1700003 -+ -+/*FSKTFC1*/ -+#define RSTV0910_FSKTFC1 0xf171 -+#define FSTV0910_FSKT_CAR1 0xf17100ff -+ -+/*FSKTFC0*/ -+#define RSTV0910_FSKTFC0 0xf172 -+#define FSTV0910_FSKT_CAR0 0xf17200ff -+ -+/*FSKTDELTAF1*/ -+#define RSTV0910_FSKTDELTAF1 0xf173 -+#define FSTV0910_FSKT_DELTAF1 0xf173000f -+ -+/*FSKTDELTAF0*/ -+#define RSTV0910_FSKTDELTAF0 0xf174 -+#define FSTV0910_FSKT_DELTAF0 0xf17400ff -+ -+/*FSKTCTRL*/ -+#define RSTV0910_FSKTCTRL 0xf175 -+#define FSTV0910_FSKT_PINSEL 0xf1750080 -+#define FSTV0910_FSKT_EN_SGN 0xf1750040 -+#define FSTV0910_FSKT_MOD_SGN 0xf1750020 -+#define FSTV0910_FSKT_MOD_EN 0xf175001c -+#define FSTV0910_FSKT_DACMODE 0xf1750003 -+ -+/*FSKRFC2*/ -+#define RSTV0910_FSKRFC2 0xf176 -+#define FSTV0910_FSKR_DETSGN 0xf1760040 -+#define FSTV0910_FSKR_OUTSGN 0xf1760020 -+#define FSTV0910_FSKR_KAGC 0xf176001c -+#define FSTV0910_FSKR_CAR2 0xf1760003 -+ -+/*FSKRFC1*/ -+#define RSTV0910_FSKRFC1 0xf177 -+#define FSTV0910_FSKR_CAR1 0xf17700ff -+ -+/*FSKRFC0*/ -+#define RSTV0910_FSKRFC0 0xf178 -+#define FSTV0910_FSKR_CAR0 0xf17800ff -+ -+/*FSKRK1*/ -+#define RSTV0910_FSKRK1 0xf179 -+#define FSTV0910_FSKR_K1_EXP 0xf17900e0 -+#define FSTV0910_FSKR_K1_MANT 0xf179001f -+ -+/*FSKRK2*/ -+#define RSTV0910_FSKRK2 0xf17a -+#define FSTV0910_FSKR_K2_EXP 0xf17a00e0 -+#define FSTV0910_FSKR_K2_MANT 0xf17a001f -+ -+/*FSKRAGCR*/ -+#define RSTV0910_FSKRAGCR 0xf17b -+#define FSTV0910_FSKR_OUTCTL 0xf17b00c0 -+#define FSTV0910_FSKR_AGC_REF 0xf17b003f -+ -+/*FSKRAGC*/ -+#define RSTV0910_FSKRAGC 0xf17c -+#define FSTV0910_FSKR_AGC_ACCU 0xf17c00ff -+ -+/*FSKRALPHA*/ -+#define RSTV0910_FSKRALPHA 0xf17d -+#define FSTV0910_FSKR_ALPHA_EXP 0xf17d001c -+#define FSTV0910_FSKR_ALPHA_M 0xf17d0003 -+ -+/*FSKRPLTH1*/ -+#define RSTV0910_FSKRPLTH1 0xf17e -+#define FSTV0910_FSKR_BETA 0xf17e00f0 -+#define FSTV0910_FSKR_PLL_TRESH1 0xf17e000f -+ -+/*FSKRPLTH0*/ -+#define RSTV0910_FSKRPLTH0 0xf17f -+#define FSTV0910_FSKR_PLL_TRESH0 0xf17f00ff -+ -+/*FSKRDF1*/ -+#define RSTV0910_FSKRDF1 0xf180 -+#define FSTV0910_FSKR_OUT 0xf1800080 -+#define FSTV0910_FSKR_STATE 0xf1800060 -+#define FSTV0910_FSKR_DELTAF1 0xf180001f -+ -+/*FSKRDF0*/ -+#define RSTV0910_FSKRDF0 0xf181 -+#define FSTV0910_FSKR_DELTAF0 0xf18100ff -+ -+/*FSKRSTEPP*/ -+#define RSTV0910_FSKRSTEPP 0xf182 -+#define FSTV0910_FSKR_STEP_PLUS 0xf18200ff -+ -+/*FSKRSTEPM*/ -+#define RSTV0910_FSKRSTEPM 0xf183 -+#define FSTV0910_FSKR_STEP_MINUS 0xf18300ff -+ -+/*FSKRDET1*/ -+#define RSTV0910_FSKRDET1 0xf184 -+#define FSTV0910_FSKR_DETECT 0xf1840080 -+#define FSTV0910_FSKR_CARDET_ACCU1 0xf184000f -+ -+/*FSKRDET0*/ -+#define RSTV0910_FSKRDET0 0xf185 -+#define FSTV0910_FSKR_CARDET_ACCU0 0xf18500ff -+ -+/*FSKRDTH1*/ -+#define RSTV0910_FSKRDTH1 0xf186 -+#define FSTV0910_FSKR_CARLOSS_THRESH1 0xf18600f0 -+#define FSTV0910_FSKR_CARDET_THRESH1 0xf186000f -+ -+/*FSKRDTH0*/ -+#define RSTV0910_FSKRDTH0 0xf187 -+#define FSTV0910_FSKR_CARDET_THRESH0 0xf18700ff -+ -+/*FSKRLOSS*/ -+#define RSTV0910_FSKRLOSS 0xf188 -+#define FSTV0910_FSKR_CARLOSS_THRESH0 0xf18800ff -+ -+/*NCOARSE*/ -+#define RSTV0910_NCOARSE 0xf1b3 -+#define FSTV0910_CP 0xf1b300f8 -+#define FSTV0910_IDF 0xf1b30007 -+ -+/*NCOARSE1*/ -+#define RSTV0910_NCOARSE1 0xf1b4 -+#define FSTV0910_N_DIV 0xf1b400ff -+ -+/*NCOARSE2*/ -+#define RSTV0910_NCOARSE2 0xf1b5 -+#define FSTV0910_ODF 0xf1b5003f -+ -+/*SYNTCTRL*/ -+#define RSTV0910_SYNTCTRL 0xf1b6 -+#define FSTV0910_STANDBY 0xf1b60080 -+#define FSTV0910_BYPASSPLLCORE 0xf1b60040 -+#define FSTV0910_STOP_PLL 0xf1b60008 -+#define FSTV0910_OSCI_E 0xf1b60002 -+ -+/*FILTCTRL*/ -+#define RSTV0910_FILTCTRL 0xf1b7 -+#define FSTV0910_INV_CLKFSK 0xf1b70002 -+#define FSTV0910_BYPASS_APPLI 0xf1b70001 -+ -+/*PLLSTAT*/ -+#define RSTV0910_PLLSTAT 0xf1b8 -+#define FSTV0910_PLL_BIST_END 0xf1b80004 -+#define FSTV0910_PLLLOCK 0xf1b80001 -+ -+/*STOPCLK1*/ -+#define RSTV0910_STOPCLK1 0xf1c2 -+#define FSTV0910_INV_CLKADCI2 0xf1c20004 -+#define FSTV0910_INV_CLKADCI1 0xf1c20001 -+ -+/*STOPCLK2*/ -+#define RSTV0910_STOPCLK2 0xf1c3 -+#define FSTV0910_STOP_DVBS2FEC2 0xf1c30020 -+#define FSTV0910_STOP_DVBS2FEC 0xf1c30010 -+#define FSTV0910_STOP_DVBS1FEC2 0xf1c30008 -+#define FSTV0910_STOP_DVBS1FEC 0xf1c30004 -+#define FSTV0910_STOP_DEMOD2 0xf1c30002 -+#define FSTV0910_STOP_DEMOD 0xf1c30001 -+ -+/*PREGCTL*/ -+#define RSTV0910_PREGCTL 0xf1c8 -+#define FSTV0910_REG3V3TO2V5_POFF 0xf1c80080 -+ -+/*TSTTNR0*/ -+#define RSTV0910_TSTTNR0 0xf1df -+#define FSTV0910_FSK_PON 0xf1df0004 -+#define FSTV0910_FSK_OPENLOOP 0xf1df0002 -+ -+/*TSTTNR1*/ -+#define RSTV0910_TSTTNR1 0xf1e0 -+#define FSTV0910_BYPASS_ADC1 0xf1e00080 -+#define FSTV0910_INVADC1_CKOUT 0xf1e00040 -+#define FSTV0910_SELIQSRC1 0xf1e00030 -+#define FSTV0910_DEMOD2_SELADC 0xf1e00008 -+#define FSTV0910_DEMOD1_SELADC 0xf1e00004 -+#define FSTV0910_ADC1_PON 0xf1e00002 -+ -+/*TSTTNR2*/ -+#define RSTV0910_TSTTNR2 0xf1e1 -+#define FSTV0910_I2C_DISEQC_BYPASS 0xf1e10080 -+#define FSTV0910_I2C_DISEQC_ENCH 0xf1e10040 -+#define FSTV0910_I2C_DISEQC_PON 0xf1e10020 -+#define FSTV0910_DISEQC_CLKDIV 0xf1e1000f -+ -+/*TSTTNR3*/ -+#define RSTV0910_TSTTNR3 0xf1e2 -+#define FSTV0910_BYPASS_ADC2 0xf1e20080 -+#define FSTV0910_INVADC2_CKOUT 0xf1e20040 -+#define FSTV0910_SELIQSRC2 0xf1e20030 -+#define FSTV0910_ADC2_PON 0xf1e20002 -+ -+/*P2_IQCONST*/ -+#define RSTV0910_P2_IQCONST 0xf200 -+#define FSTV0910_P2_CONSTEL_SELECT 0xf2000060 -+#define FSTV0910_P2_IQSYMB_SEL 0xf200001f -+ -+/*P2_NOSCFG*/ -+#define RSTV0910_P2_NOSCFG 0xf201 -+#define FSTV0910_P2_DIS_ACMRATIO 0xf2010080 -+#define FSTV0910_P2_NOSIN_EGALSEL 0xf2010040 -+#define FSTV0910_P2_DUMMYPL_NOSDATA 0xf2010020 -+#define FSTV0910_P2_NOSPLH_BETA 0xf2010018 -+#define FSTV0910_P2_NOSDATA_BETA 0xf2010007 -+ -+/*P2_ISYMB*/ -+#define RSTV0910_P2_ISYMB 0xf202 -+#define FSTV0910_P2_I_SYMBOL 0xf20201ff -+ -+/*P2_QSYMB*/ -+#define RSTV0910_P2_QSYMB 0xf203 -+#define FSTV0910_P2_Q_SYMBOL 0xf20301ff -+ -+/*P2_AGC1CFG*/ -+#define RSTV0910_P2_AGC1CFG 0xf204 -+#define FSTV0910_P2_DC_FROZEN 0xf2040080 -+#define FSTV0910_P2_DC_CORRECT 0xf2040040 -+#define FSTV0910_P2_AMM_FROZEN 0xf2040020 -+#define FSTV0910_P2_AMM_CORRECT 0xf2040010 -+#define FSTV0910_P2_QUAD_FROZEN 0xf2040008 -+#define FSTV0910_P2_QUAD_CORRECT 0xf2040004 -+#define FSTV0910_P2_DCCOMP_SLOW 0xf2040002 -+#define FSTV0910_P2_IQMISM_SLOW 0xf2040001 -+ -+/*P2_AGC1CN*/ -+#define RSTV0910_P2_AGC1CN 0xf206 -+#define FSTV0910_P2_AGC1_LOCKED 0xf2060080 -+#define FSTV0910_P2_AGC1_OVERFLOW 0xf2060040 -+#define FSTV0910_P2_AGC1_NOSLOWLK 0xf2060020 -+#define FSTV0910_P2_AGC1_MINPOWER 0xf2060010 -+#define FSTV0910_P2_AGCOUT_FAST 0xf2060008 -+#define FSTV0910_P2_AGCIQ_BETA 0xf2060007 -+ -+/*P2_AGC1REF*/ -+#define RSTV0910_P2_AGC1REF 0xf207 -+#define FSTV0910_P2_AGCIQ_REF 0xf20700ff -+ -+/*P2_IDCCOMP*/ -+#define RSTV0910_P2_IDCCOMP 0xf208 -+#define FSTV0910_P2_IAVERAGE_ADJ 0xf20801ff -+ -+/*P2_QDCCOMP*/ -+#define RSTV0910_P2_QDCCOMP 0xf209 -+#define FSTV0910_P2_QAVERAGE_ADJ 0xf20901ff -+ -+/*P2_POWERI*/ -+#define RSTV0910_P2_POWERI 0xf20a -+#define FSTV0910_P2_POWER_I 0xf20a00ff -+ -+/*P2_POWERQ*/ -+#define RSTV0910_P2_POWERQ 0xf20b -+#define FSTV0910_P2_POWER_Q 0xf20b00ff -+ -+/*P2_AGC1AMM*/ -+#define RSTV0910_P2_AGC1AMM 0xf20c -+#define FSTV0910_P2_AMM_VALUE 0xf20c00ff -+ -+/*P2_AGC1QUAD*/ -+#define RSTV0910_P2_AGC1QUAD 0xf20d -+#define FSTV0910_P2_QUAD_VALUE 0xf20d01ff -+ -+/*P2_AGCIQIN1*/ -+#define RSTV0910_P2_AGCIQIN1 0xf20e -+#define FSTV0910_P2_AGCIQ_VALUE1 0xf20e00ff -+ -+/*P2_AGCIQIN0*/ -+#define RSTV0910_P2_AGCIQIN0 0xf20f -+#define FSTV0910_P2_AGCIQ_VALUE0 0xf20f00ff -+ -+/*P2_DEMOD*/ -+#define RSTV0910_P2_DEMOD 0xf210 -+#define FSTV0910_P2_MANUALS2_ROLLOFF 0xf2100080 -+#define FSTV0910_P2_SPECINV_CONTROL 0xf2100030 -+#define FSTV0910_P2_MANUALSX_ROLLOFF 0xf2100004 -+#define FSTV0910_P2_ROLLOFF_CONTROL 0xf2100003 -+ -+/*P2_DMDMODCOD*/ -+#define RSTV0910_P2_DMDMODCOD 0xf211 -+#define FSTV0910_P2_MANUAL_MODCOD 0xf2110080 -+#define FSTV0910_P2_DEMOD_MODCOD 0xf211007c -+#define FSTV0910_P2_DEMOD_TYPE 0xf2110003 -+ -+/*P2_DSTATUS*/ -+#define RSTV0910_P2_DSTATUS 0xf212 -+#define FSTV0910_P2_CAR_LOCK 0xf2120080 -+#define FSTV0910_P2_TMGLOCK_QUALITY 0xf2120060 -+#define FSTV0910_P2_SDVBS1_ENABLE 0xf2120010 -+#define FSTV0910_P2_LOCK_DEFINITIF 0xf2120008 -+#define FSTV0910_P2_TIMING_IS_LOCKED 0xf2120004 -+#define FSTV0910_P2_DEMOD_SYSCFG 0xf2120002 -+#define FSTV0910_P2_OVADC_DETECT 0xf2120001 -+ -+/*P2_DSTATUS2*/ -+#define RSTV0910_P2_DSTATUS2 0xf213 -+#define FSTV0910_P2_DEMOD_DELOCK 0xf2130080 -+#define FSTV0910_P2_DEMOD_TIMEOUT 0xf2130040 -+#define FSTV0910_P2_MODCODRQ_SYNCTAG 0xf2130020 -+#define FSTV0910_P2_POLYPH_SATEVENT 0xf2130010 -+#define FSTV0910_P2_AGC1_NOSIGNALACK 0xf2130008 -+#define FSTV0910_P2_AGC2_OVERFLOW 0xf2130004 -+#define FSTV0910_P2_CFR_OVERFLOW 0xf2130002 -+#define FSTV0910_P2_GAMMA_OVERUNDER 0xf2130001 -+ -+/*P2_DMDCFGMD*/ -+#define RSTV0910_P2_DMDCFGMD 0xf214 -+#define FSTV0910_P2_DVBS2_ENABLE 0xf2140080 -+#define FSTV0910_P2_DVBS1_ENABLE 0xf2140040 -+#define FSTV0910_P2_SCAN_ENABLE 0xf2140010 -+#define FSTV0910_P2_CFR_AUTOSCAN 0xf2140008 -+#define FSTV0910_P2_NOFORCE_RELOCK 0xf2140004 -+#define FSTV0910_P2_TUN_RNG 0xf2140003 -+ -+/*P2_DMDCFG2*/ -+#define RSTV0910_P2_DMDCFG2 0xf215 -+#define FSTV0910_P2_AGC1_WAITLOCK 0xf2150080 -+#define FSTV0910_P2_S1S2_SEQUENTIAL 0xf2150040 -+#define FSTV0910_P2_BLINDPEA_MODE 0xf2150020 -+#define FSTV0910_P2_INFINITE_RELOCK 0xf2150010 -+#define FSTV0910_P2_BWOFFSET_COLDWARM 0xf2150008 -+#define FSTV0910_P2_TMGLOCK_NSCANSTOP 0xf2150004 -+#define FSTV0910_P2_COARSE_LK3MODE 0xf2150002 -+#define FSTV0910_P2_COARSE_LK2MODE 0xf2150001 -+ -+/*P2_DMDISTATE*/ -+#define RSTV0910_P2_DMDISTATE 0xf216 -+#define FSTV0910_P2_I2C_NORESETDMODE 0xf2160080 -+#define FSTV0910_P2_FORCE_ETAPED 0xf2160040 -+#define FSTV0910_P2_SDMDRST_DIRCLK 0xf2160020 -+#define FSTV0910_P2_I2C_DEMOD_MODE 0xf216001f -+ -+/*P2_DMDT0M*/ -+#define RSTV0910_P2_DMDT0M 0xf217 -+#define FSTV0910_P2_DMDT0_MIN 0xf21700ff -+ -+/*P2_DMDSTATE*/ -+#define RSTV0910_P2_DMDSTATE 0xf21b -+#define FSTV0910_P2_DEMOD_LOCKED 0xf21b0080 -+#define FSTV0910_P2_HEADER_MODE 0xf21b0060 -+#define FSTV0910_P2_DEMOD_MODE 0xf21b001f -+ -+/*P2_DMDFLYW*/ -+#define RSTV0910_P2_DMDFLYW 0xf21c -+#define FSTV0910_P2_I2C_IRQVAL 0xf21c00f0 -+#define FSTV0910_P2_FLYWHEEL_CPT 0xf21c000f -+ -+/*P2_DSTATUS3*/ -+#define RSTV0910_P2_DSTATUS3 0xf21d -+#define FSTV0910_P2_CFR_ZIGZAG 0xf21d0080 -+#define FSTV0910_P2_DEMOD_CFGMODE 0xf21d0060 -+#define FSTV0910_P2_GAMMA_LOWBAUDRATE 0xf21d0010 -+#define FSTV0910_P2_RELOCK_MODE 0xf21d0008 -+#define FSTV0910_P2_DEMOD_FAIL 0xf21d0004 -+#define FSTV0910_P2_ETAPE1A_DVBXMEM 0xf21d0003 -+ -+/*P2_DMDCFG3*/ -+#define RSTV0910_P2_DMDCFG3 0xf21e -+#define FSTV0910_P2_DVBS1_TMGWAIT 0xf21e0080 -+#define FSTV0910_P2_NO_BWCENTERING 0xf21e0040 -+#define FSTV0910_P2_INV_SEQSRCH 0xf21e0020 -+#define FSTV0910_P2_DIS_SFRUPLOW_TRK 0xf21e0010 -+#define FSTV0910_P2_NOSTOP_FIFOFULL 0xf21e0008 -+#define FSTV0910_P2_LOCKTIME_MODE 0xf21e0007 -+ -+/*P2_DMDCFG4*/ -+#define RSTV0910_P2_DMDCFG4 0xf21f -+#define FSTV0910_P2_DIS_VITLOCK 0xf21f0080 -+#define FSTV0910_P2_S1S2TOUT_FAST 0xf21f0040 -+#define FSTV0910_P2_DEMOD_FASTLOCK 0xf21f0020 -+#define FSTV0910_P2_S1HIER_ENABLE 0xf21f0010 -+#define FSTV0910_P2_TUNER_NRELAUNCH 0xf21f0008 -+#define FSTV0910_P2_DIS_CLKENABLE 0xf21f0004 -+#define FSTV0910_P2_DIS_HDRDIVLOCK 0xf21f0002 -+#define FSTV0910_P2_NO_TNRWBINIT 0xf21f0001 -+ -+/*P2_CORRELMANT*/ -+#define RSTV0910_P2_CORRELMANT 0xf220 -+#define FSTV0910_P2_CORREL_MANT 0xf22000ff -+ -+/*P2_CORRELABS*/ -+#define RSTV0910_P2_CORRELABS 0xf221 -+#define FSTV0910_P2_CORREL_ABS 0xf22100ff -+ -+/*P2_CORRELEXP*/ -+#define RSTV0910_P2_CORRELEXP 0xf222 -+#define FSTV0910_P2_CORREL_ABSEXP 0xf22200f0 -+#define FSTV0910_P2_CORREL_EXP 0xf222000f -+ -+/*P2_PLHMODCOD*/ -+#define RSTV0910_P2_PLHMODCOD 0xf224 -+#define FSTV0910_P2_SPECINV_DEMOD 0xf2240080 -+#define FSTV0910_P2_PLH_MODCOD 0xf224007c -+#define FSTV0910_P2_PLH_TYPE 0xf2240003 -+ -+/*P2_DMDREG*/ -+#define RSTV0910_P2_DMDREG 0xf225 -+#define FSTV0910_P2_EXTPSK_MODE 0xf2250080 -+#define FSTV0910_P2_HIER_SHORTFRAME 0xf2250002 -+#define FSTV0910_P2_DECIM_PLFRAMES 0xf2250001 -+ -+/*P2_AGC2O*/ -+#define RSTV0910_P2_AGC2O 0xf22c -+#define FSTV0910_P2_CSTENV_MODE 0xf22c00c0 -+#define FSTV0910_P2_AGC2_LKSQRT 0xf22c0020 -+#define FSTV0910_P2_AGC2_LKMODE 0xf22c0010 -+#define FSTV0910_P2_AGC2_LKEQUA 0xf22c0008 -+#define FSTV0910_P2_AGC2_COEF 0xf22c0007 -+ -+/*P2_AGC2REF*/ -+#define RSTV0910_P2_AGC2REF 0xf22d -+#define FSTV0910_P2_AGC2_REF 0xf22d00ff -+ -+/*P2_AGC1ADJ*/ -+#define RSTV0910_P2_AGC1ADJ 0xf22e -+#define FSTV0910_P2_AGC1ADJ_MANUAL 0xf22e0080 -+#define FSTV0910_P2_AGC1_ADJUSTED 0xf22e007f -+ -+/*P2_AGC2I1*/ -+#define RSTV0910_P2_AGC2I1 0xf236 -+#define FSTV0910_P2_AGC2_INTEGRATOR1 0xf23600ff -+ -+/*P2_AGC2I0*/ -+#define RSTV0910_P2_AGC2I0 0xf237 -+#define FSTV0910_P2_AGC2_INTEGRATOR0 0xf23700ff -+ -+/*P2_CARCFG*/ -+#define RSTV0910_P2_CARCFG 0xf238 -+#define FSTV0910_P2_CFRUPLOW_AUTO 0xf2380080 -+#define FSTV0910_P2_CFRUPLOW_TEST 0xf2380040 -+#define FSTV0910_P2_WIDE_FREQDET 0xf2380020 -+#define FSTV0910_P2_CARHDR_NODIV8 0xf2380010 -+#define FSTV0910_P2_I2C_ROTA 0xf2380008 -+#define FSTV0910_P2_ROTAON 0xf2380004 -+#define FSTV0910_P2_PH_DET_ALGO 0xf2380003 -+ -+/*P2_ACLC*/ -+#define RSTV0910_P2_ACLC 0xf239 -+#define FSTV0910_P2_CARS1_ANOSAUTO 0xf2390040 -+#define FSTV0910_P2_CAR_ALPHA_MANT 0xf2390030 -+#define FSTV0910_P2_CAR_ALPHA_EXP 0xf239000f -+ -+/*P2_BCLC*/ -+#define RSTV0910_P2_BCLC 0xf23a -+#define FSTV0910_P2_CARS1_BNOSAUTO 0xf23a0040 -+#define FSTV0910_P2_CAR_BETA_MANT 0xf23a0030 -+#define FSTV0910_P2_CAR_BETA_EXP 0xf23a000f -+ -+/*P2_CARFREQ*/ -+#define RSTV0910_P2_CARFREQ 0xf23d -+#define FSTV0910_P2_KC_COARSE_EXP 0xf23d00f0 -+#define FSTV0910_P2_BETA_FREQ 0xf23d000f -+ -+/*P2_CARHDR*/ -+#define RSTV0910_P2_CARHDR 0xf23e -+#define FSTV0910_P2_K_FREQ_HDR 0xf23e00ff -+ -+/*P2_LDT*/ -+#define RSTV0910_P2_LDT 0xf23f -+#define FSTV0910_P2_CARLOCK_THRES 0xf23f01ff -+ -+/*P2_LDT2*/ -+#define RSTV0910_P2_LDT2 0xf240 -+#define FSTV0910_P2_CARLOCK_THRES2 0xf24001ff -+ -+/*P2_CFRICFG*/ -+#define RSTV0910_P2_CFRICFG 0xf241 -+#define FSTV0910_P2_CFRINIT_UNVALRNG 0xf2410080 -+#define FSTV0910_P2_CFRINIT_LUNVALCPT 0xf2410040 -+#define FSTV0910_P2_CFRINIT_ABORTDBL 0xf2410020 -+#define FSTV0910_P2_CFRINIT_ABORTPRED 0xf2410010 -+#define FSTV0910_P2_CFRINIT_UNVALSKIP 0xf2410008 -+#define FSTV0910_P2_CFRINIT_CSTINC 0xf2410004 -+#define FSTV0910_P2_CFRIROLL_GARDER 0xf2410002 -+#define FSTV0910_P2_NEG_CFRSTEP 0xf2410001 -+ -+/*P2_CFRUP1*/ -+#define RSTV0910_P2_CFRUP1 0xf242 -+#define FSTV0910_P2_CFR_UP1 0xf24201ff -+ -+/*P2_CFRUP0*/ -+#define RSTV0910_P2_CFRUP0 0xf243 -+#define FSTV0910_P2_CFR_UP0 0xf24300ff -+ -+/*P2_CFRIBASE1*/ -+#define RSTV0910_P2_CFRIBASE1 0xf244 -+#define FSTV0910_P2_CFRINIT_BASE1 0xf24400ff -+ -+/*P2_CFRIBASE0*/ -+#define RSTV0910_P2_CFRIBASE0 0xf245 -+#define FSTV0910_P2_CFRINIT_BASE0 0xf24500ff -+ -+/*P2_CFRLOW1*/ -+#define RSTV0910_P2_CFRLOW1 0xf246 -+#define FSTV0910_P2_CFR_LOW1 0xf24601ff -+ -+/*P2_CFRLOW0*/ -+#define RSTV0910_P2_CFRLOW0 0xf247 -+#define FSTV0910_P2_CFR_LOW0 0xf24700ff -+ -+/*P2_CFRINIT1*/ -+#define RSTV0910_P2_CFRINIT1 0xf248 -+#define FSTV0910_P2_CFR_INIT1 0xf24801ff -+ -+/*P2_CFRINIT0*/ -+#define RSTV0910_P2_CFRINIT0 0xf249 -+#define FSTV0910_P2_CFR_INIT0 0xf24900ff -+ -+/*P2_CFRINC1*/ -+#define RSTV0910_P2_CFRINC1 0xf24a -+#define FSTV0910_P2_MANUAL_CFRINC 0xf24a0080 -+#define FSTV0910_P2_CFR_INC1 0xf24a003f -+ -+/*P2_CFRINC0*/ -+#define RSTV0910_P2_CFRINC0 0xf24b -+#define FSTV0910_P2_CFR_INC0 0xf24b00ff -+ -+/*P2_CFR2*/ -+#define RSTV0910_P2_CFR2 0xf24c -+#define FSTV0910_P2_CAR_FREQ2 0xf24c01ff -+ -+/*P2_CFR1*/ -+#define RSTV0910_P2_CFR1 0xf24d -+#define FSTV0910_P2_CAR_FREQ1 0xf24d00ff -+ -+/*P2_CFR0*/ -+#define RSTV0910_P2_CFR0 0xf24e -+#define FSTV0910_P2_CAR_FREQ0 0xf24e00ff -+ -+/*P2_LDI*/ -+#define RSTV0910_P2_LDI 0xf24f -+#define FSTV0910_P2_LOCK_DET_INTEGR 0xf24f01ff -+ -+/*P2_TMGCFG*/ -+#define RSTV0910_P2_TMGCFG 0xf250 -+#define FSTV0910_P2_TMGLOCK_BETA 0xf25000c0 -+#define FSTV0910_P2_DO_TIMING_CORR 0xf2500010 -+#define FSTV0910_P2_MANUAL_SCAN 0xf250000c -+#define FSTV0910_P2_TMG_MINFREQ 0xf2500003 -+ -+/*P2_RTC*/ -+#define RSTV0910_P2_RTC 0xf251 -+#define FSTV0910_P2_TMGALPHA_EXP 0xf25100f0 -+#define FSTV0910_P2_TMGBETA_EXP 0xf251000f -+ -+/*P2_RTCS2*/ -+#define RSTV0910_P2_RTCS2 0xf252 -+#define FSTV0910_P2_TMGALPHAS2_EXP 0xf25200f0 -+#define FSTV0910_P2_TMGBETAS2_EXP 0xf252000f -+ -+/*P2_TMGTHRISE*/ -+#define RSTV0910_P2_TMGTHRISE 0xf253 -+#define FSTV0910_P2_TMGLOCK_THRISE 0xf25300ff -+ -+/*P2_TMGTHFALL*/ -+#define RSTV0910_P2_TMGTHFALL 0xf254 -+#define FSTV0910_P2_TMGLOCK_THFALL 0xf25400ff -+ -+/*P2_SFRUPRATIO*/ -+#define RSTV0910_P2_SFRUPRATIO 0xf255 -+#define FSTV0910_P2_SFR_UPRATIO 0xf25500ff -+ -+/*P2_SFRLOWRATIO*/ -+#define RSTV0910_P2_SFRLOWRATIO 0xf256 -+#define FSTV0910_P2_SFR_LOWRATIO 0xf25600ff -+ -+/*P2_KTTMG*/ -+#define RSTV0910_P2_KTTMG 0xf257 -+#define FSTV0910_P2_KT_TMG_EXP 0xf25700f0 -+ -+/*P2_KREFTMG*/ -+#define RSTV0910_P2_KREFTMG 0xf258 -+#define FSTV0910_P2_KREF_TMG 0xf25800ff -+ -+/*P2_SFRSTEP*/ -+#define RSTV0910_P2_SFRSTEP 0xf259 -+#define FSTV0910_P2_SFR_SCANSTEP 0xf25900f0 -+#define FSTV0910_P2_SFR_CENTERSTEP 0xf259000f -+ -+/*P2_TMGCFG2*/ -+#define RSTV0910_P2_TMGCFG2 0xf25a -+#define FSTV0910_P2_KREFTMG2_DECMODE 0xf25a00c0 -+#define FSTV0910_P2_DIS_AUTOSAMP 0xf25a0008 -+#define FSTV0910_P2_SCANINIT_QUART 0xf25a0004 -+#define FSTV0910_P2_NOTMG_DVBS1DERAT 0xf25a0002 -+#define FSTV0910_P2_SFRRATIO_FINE 0xf25a0001 -+ -+/*P2_KREFTMG2*/ -+#define RSTV0910_P2_KREFTMG2 0xf25b -+#define FSTV0910_P2_KREF_TMG2 0xf25b00ff -+ -+/*P2_TMGCFG3*/ -+#define RSTV0910_P2_TMGCFG3 0xf25d -+#define FSTV0910_P2_CFRINC_MODE 0xf25d0070 -+#define FSTV0910_P2_CONT_TMGCENTER 0xf25d0008 -+#define FSTV0910_P2_AUTO_GUP 0xf25d0004 -+#define FSTV0910_P2_AUTO_GLOW 0xf25d0002 -+#define FSTV0910_P2_SFRVAL_MINMODE 0xf25d0001 -+ -+/*P2_SFRINIT1*/ -+#define RSTV0910_P2_SFRINIT1 0xf25e -+#define FSTV0910_P2_SFR_INIT1 0xf25e00ff -+ -+/*P2_SFRINIT0*/ -+#define RSTV0910_P2_SFRINIT0 0xf25f -+#define FSTV0910_P2_SFR_INIT0 0xf25f00ff -+ -+/*P2_SFRUP1*/ -+#define RSTV0910_P2_SFRUP1 0xf260 -+#define FSTV0910_P2_SYMB_FREQ_UP1 0xf26000ff -+ -+/*P2_SFRUP0*/ -+#define RSTV0910_P2_SFRUP0 0xf261 -+#define FSTV0910_P2_SYMB_FREQ_UP0 0xf26100ff -+ -+/*P2_SFRLOW1*/ -+#define RSTV0910_P2_SFRLOW1 0xf262 -+#define FSTV0910_P2_SYMB_FREQ_LOW1 0xf26200ff -+ -+/*P2_SFRLOW0*/ -+#define RSTV0910_P2_SFRLOW0 0xf263 -+#define FSTV0910_P2_SYMB_FREQ_LOW0 0xf26300ff -+ -+/*P2_SFR3*/ -+#define RSTV0910_P2_SFR3 0xf264 -+#define FSTV0910_P2_SYMB_FREQ3 0xf26400ff -+ -+/*P2_SFR2*/ -+#define RSTV0910_P2_SFR2 0xf265 -+#define FSTV0910_P2_SYMB_FREQ2 0xf26500ff -+ -+/*P2_SFR1*/ -+#define RSTV0910_P2_SFR1 0xf266 -+#define FSTV0910_P2_SYMB_FREQ1 0xf26600ff -+ -+/*P2_SFR0*/ -+#define RSTV0910_P2_SFR0 0xf267 -+#define FSTV0910_P2_SYMB_FREQ0 0xf26700ff -+ -+/*P2_TMGREG2*/ -+#define RSTV0910_P2_TMGREG2 0xf268 -+#define FSTV0910_P2_TMGREG2 0xf26800ff -+ -+/*P2_TMGREG1*/ -+#define RSTV0910_P2_TMGREG1 0xf269 -+#define FSTV0910_P2_TMGREG1 0xf26900ff -+ -+/*P2_TMGREG0*/ -+#define RSTV0910_P2_TMGREG0 0xf26a -+#define FSTV0910_P2_TMGREG0 0xf26a00ff -+ -+/*P2_TMGLOCK1*/ -+#define RSTV0910_P2_TMGLOCK1 0xf26b -+#define FSTV0910_P2_TMGLOCK_LEVEL1 0xf26b01ff -+ -+/*P2_TMGLOCK0*/ -+#define RSTV0910_P2_TMGLOCK0 0xf26c -+#define FSTV0910_P2_TMGLOCK_LEVEL0 0xf26c00ff -+ -+/*P2_TMGOBS*/ -+#define RSTV0910_P2_TMGOBS 0xf26d -+#define FSTV0910_P2_ROLLOFF_STATUS 0xf26d00c0 -+#define FSTV0910_P2_SCAN_SIGN 0xf26d0030 -+#define FSTV0910_P2_TMG_SCANNING 0xf26d0008 -+#define FSTV0910_P2_CHCENTERING_MODE 0xf26d0004 -+#define FSTV0910_P2_TMG_SCANFAIL 0xf26d0002 -+ -+/*P2_EQUALCFG*/ -+#define RSTV0910_P2_EQUALCFG 0xf26f -+#define FSTV0910_P2_NOTMG_NEGALWAIT 0xf26f0080 -+#define FSTV0910_P2_EQUAL_ON 0xf26f0040 -+#define FSTV0910_P2_SEL_EQUALCOR 0xf26f0038 -+#define FSTV0910_P2_MU_EQUALDFE 0xf26f0007 -+ -+/*P2_EQUAI1*/ -+#define RSTV0910_P2_EQUAI1 0xf270 -+#define FSTV0910_P2_EQUA_ACCI1 0xf27001ff -+ -+/*P2_EQUAQ1*/ -+#define RSTV0910_P2_EQUAQ1 0xf271 -+#define FSTV0910_P2_EQUA_ACCQ1 0xf27101ff -+ -+/*P2_EQUAI2*/ -+#define RSTV0910_P2_EQUAI2 0xf272 -+#define FSTV0910_P2_EQUA_ACCI2 0xf27201ff -+ -+/*P2_EQUAQ2*/ -+#define RSTV0910_P2_EQUAQ2 0xf273 -+#define FSTV0910_P2_EQUA_ACCQ2 0xf27301ff -+ -+/*P2_EQUAI3*/ -+#define RSTV0910_P2_EQUAI3 0xf274 -+#define FSTV0910_P2_EQUA_ACCI3 0xf27401ff -+ -+/*P2_EQUAQ3*/ -+#define RSTV0910_P2_EQUAQ3 0xf275 -+#define FSTV0910_P2_EQUA_ACCQ3 0xf27501ff -+ -+/*P2_EQUAI4*/ -+#define RSTV0910_P2_EQUAI4 0xf276 -+#define FSTV0910_P2_EQUA_ACCI4 0xf27601ff -+ -+/*P2_EQUAQ4*/ -+#define RSTV0910_P2_EQUAQ4 0xf277 -+#define FSTV0910_P2_EQUA_ACCQ4 0xf27701ff -+ -+/*P2_EQUAI5*/ -+#define RSTV0910_P2_EQUAI5 0xf278 -+#define FSTV0910_P2_EQUA_ACCI5 0xf27801ff -+ -+/*P2_EQUAQ5*/ -+#define RSTV0910_P2_EQUAQ5 0xf279 -+#define FSTV0910_P2_EQUA_ACCQ5 0xf27901ff -+ -+/*P2_EQUAI6*/ -+#define RSTV0910_P2_EQUAI6 0xf27a -+#define FSTV0910_P2_EQUA_ACCI6 0xf27a01ff -+ -+/*P2_EQUAQ6*/ -+#define RSTV0910_P2_EQUAQ6 0xf27b -+#define FSTV0910_P2_EQUA_ACCQ6 0xf27b01ff -+ -+/*P2_EQUAI7*/ -+#define RSTV0910_P2_EQUAI7 0xf27c -+#define FSTV0910_P2_EQUA_ACCI7 0xf27c01ff -+ -+/*P2_EQUAQ7*/ -+#define RSTV0910_P2_EQUAQ7 0xf27d -+#define FSTV0910_P2_EQUA_ACCQ7 0xf27d01ff -+ -+/*P2_EQUAI8*/ -+#define RSTV0910_P2_EQUAI8 0xf27e -+#define FSTV0910_P2_EQUA_ACCI8 0xf27e01ff -+ -+/*P2_EQUAQ8*/ -+#define RSTV0910_P2_EQUAQ8 0xf27f -+#define FSTV0910_P2_EQUA_ACCQ8 0xf27f01ff -+ -+/*P2_NNOSDATAT1*/ -+#define RSTV0910_P2_NNOSDATAT1 0xf280 -+#define FSTV0910_P2_NOSDATAT_NORMED1 0xf28000ff -+ -+/*P2_NNOSDATAT0*/ -+#define RSTV0910_P2_NNOSDATAT0 0xf281 -+#define FSTV0910_P2_NOSDATAT_NORMED0 0xf28100ff -+ -+/*P2_NNOSDATA1*/ -+#define RSTV0910_P2_NNOSDATA1 0xf282 -+#define FSTV0910_P2_NOSDATA_NORMED1 0xf28200ff -+ -+/*P2_NNOSDATA0*/ -+#define RSTV0910_P2_NNOSDATA0 0xf283 -+#define FSTV0910_P2_NOSDATA_NORMED0 0xf28300ff -+ -+/*P2_NNOSPLHT1*/ -+#define RSTV0910_P2_NNOSPLHT1 0xf284 -+#define FSTV0910_P2_NOSPLHT_NORMED1 0xf28400ff -+ -+/*P2_NNOSPLHT0*/ -+#define RSTV0910_P2_NNOSPLHT0 0xf285 -+#define FSTV0910_P2_NOSPLHT_NORMED0 0xf28500ff -+ -+/*P2_NNOSPLH1*/ -+#define RSTV0910_P2_NNOSPLH1 0xf286 -+#define FSTV0910_P2_NOSPLH_NORMED1 0xf28600ff -+ -+/*P2_NNOSPLH0*/ -+#define RSTV0910_P2_NNOSPLH0 0xf287 -+#define FSTV0910_P2_NOSPLH_NORMED0 0xf28700ff -+ -+/*P2_NOSDATAT1*/ -+#define RSTV0910_P2_NOSDATAT1 0xf288 -+#define FSTV0910_P2_NOSDATAT_UNNORMED1 0xf28800ff -+ -+/*P2_NOSDATAT0*/ -+#define RSTV0910_P2_NOSDATAT0 0xf289 -+#define FSTV0910_P2_NOSDATAT_UNNORMED0 0xf28900ff -+ -+/*P2_NNOSFRAME1*/ -+#define RSTV0910_P2_NNOSFRAME1 0xf28a -+#define FSTV0910_P2_NOSFRAME_NORMED1 0xf28a00ff -+ -+/*P2_NNOSFRAME0*/ -+#define RSTV0910_P2_NNOSFRAME0 0xf28b -+#define FSTV0910_P2_NOSFRAME_NORMED0 0xf28b00ff -+ -+/*P2_NNOSRAD1*/ -+#define RSTV0910_P2_NNOSRAD1 0xf28c -+#define FSTV0910_P2_NOSRADIAL_NORMED1 0xf28c00ff -+ -+/*P2_NNOSRAD0*/ -+#define RSTV0910_P2_NNOSRAD0 0xf28d -+#define FSTV0910_P2_NOSRADIAL_NORMED0 0xf28d00ff -+ -+/*P2_NOSCFGF1*/ -+#define RSTV0910_P2_NOSCFGF1 0xf28e -+#define FSTV0910_P2_LOWNOISE_MESURE 0xf28e0080 -+#define FSTV0910_P2_NOS_DELFRAME 0xf28e0040 -+#define FSTV0910_P2_NOSDATA_MODE 0xf28e0030 -+#define FSTV0910_P2_FRAMESEL_TYPESEL 0xf28e000c -+#define FSTV0910_P2_FRAMESEL_TYPE 0xf28e0003 -+ -+/*P2_CAR2CFG*/ -+#define RSTV0910_P2_CAR2CFG 0xf290 -+#define FSTV0910_P2_DESCRAMB_OFF 0xf2900080 -+#define FSTV0910_P2_EN_PHNOSRAM 0xf2900020 -+#define FSTV0910_P2_STOP_CFR2UPDATE 0xf2900010 -+#define FSTV0910_P2_STOP_NCO2UPDATE 0xf2900008 -+#define FSTV0910_P2_ROTA2ON 0xf2900004 -+#define FSTV0910_P2_PH_DET_ALGO2 0xf2900003 -+ -+/*P2_CFR2CFR1*/ -+#define RSTV0910_P2_CFR2CFR1 0xf291 -+#define FSTV0910_P2_CFR2_S2CONTROL 0xf29100c0 -+#define FSTV0910_P2_EN_S2CAR2CENTER 0xf2910020 -+#define FSTV0910_P2_BCHERRCFR2_MODE 0xf2910018 -+#define FSTV0910_P2_CFR2TOCFR1_BETA 0xf2910007 -+ -+/*P2_CAR3CFG*/ -+#define RSTV0910_P2_CAR3CFG 0xf292 -+#define FSTV0910_P2_CARRIER23_MODE 0xf29200c0 -+#define FSTV0910_P2_CAR3INTERM_DVBS1 0xf2920020 -+#define FSTV0910_P2_ABAMPLIF_MODE 0xf2920018 -+#define FSTV0910_P2_CARRIER3_ALPHA3DL 0xf2920007 -+ -+/*P2_CFR22*/ -+#define RSTV0910_P2_CFR22 0xf293 -+#define FSTV0910_P2_CAR2_FREQ2 0xf29301ff -+ -+/*P2_CFR21*/ -+#define RSTV0910_P2_CFR21 0xf294 -+#define FSTV0910_P2_CAR2_FREQ1 0xf29400ff -+ -+/*P2_CFR20*/ -+#define RSTV0910_P2_CFR20 0xf295 -+#define FSTV0910_P2_CAR2_FREQ0 0xf29500ff -+ -+/*P2_ACLC2S2Q*/ -+#define RSTV0910_P2_ACLC2S2Q 0xf297 -+#define FSTV0910_P2_ENAB_SPSKSYMB 0xf2970080 -+#define FSTV0910_P2_CAR2S2_QANOSAUTO 0xf2970040 -+#define FSTV0910_P2_CAR2S2_Q_ALPH_M 0xf2970030 -+#define FSTV0910_P2_CAR2S2_Q_ALPH_E 0xf297000f -+ -+/*P2_ACLC2S28*/ -+#define RSTV0910_P2_ACLC2S28 0xf298 -+#define FSTV0910_P2_OLDI3Q_MODE 0xf2980080 -+#define FSTV0910_P2_CAR2S2_8ANOSAUTO 0xf2980040 -+#define FSTV0910_P2_CAR2S2_8_ALPH_M 0xf2980030 -+#define FSTV0910_P2_CAR2S2_8_ALPH_E 0xf298000f -+ -+/*P2_ACLC2S216A*/ -+#define RSTV0910_P2_ACLC2S216A 0xf299 -+#define FSTV0910_P2_CAR2S2_16ANOSAUTO 0xf2990040 -+#define FSTV0910_P2_CAR2S2_16A_ALPH_M 0xf2990030 -+#define FSTV0910_P2_CAR2S2_16A_ALPH_E 0xf299000f -+ -+/*P2_ACLC2S232A*/ -+#define RSTV0910_P2_ACLC2S232A 0xf29a -+#define FSTV0910_P2_CAR2S2_32ANOSUATO 0xf29a0040 -+#define FSTV0910_P2_CAR2S2_32A_ALPH_M 0xf29a0030 -+#define FSTV0910_P2_CAR2S2_32A_ALPH_E 0xf29a000f -+ -+/*P2_BCLC2S2Q*/ -+#define RSTV0910_P2_BCLC2S2Q 0xf29c -+#define FSTV0910_P2_DVBS2S2Q_NIP 0xf29c0080 -+#define FSTV0910_P2_CAR2S2_QBNOSAUTO 0xf29c0040 -+#define FSTV0910_P2_CAR2S2_Q_BETA_M 0xf29c0030 -+#define FSTV0910_P2_CAR2S2_Q_BETA_E 0xf29c000f -+ -+/*P2_BCLC2S28*/ -+#define RSTV0910_P2_BCLC2S28 0xf29d -+#define FSTV0910_P2_DVBS2S28_NIP 0xf29d0080 -+#define FSTV0910_P2_CAR2S2_8BNOSAUTO 0xf29d0040 -+#define FSTV0910_P2_CAR2S2_8_BETA_M 0xf29d0030 -+#define FSTV0910_P2_CAR2S2_8_BETA_E 0xf29d000f -+ -+/*P2_PLROOT2*/ -+#define RSTV0910_P2_PLROOT2 0xf2ac -+#define FSTV0910_P2_PLHAUTO_DISPLH 0xf2ac0040 -+#define FSTV0910_P2_PLHAUTO_FASTMODE 0xf2ac0020 -+#define FSTV0910_P2_PLHAUTO_ENABLE 0xf2ac0010 -+#define FSTV0910_P2_PLSCRAMB_MODE 0xf2ac000c -+#define FSTV0910_P2_PLSCRAMB_ROOT2 0xf2ac0003 -+ -+/*P2_PLROOT1*/ -+#define RSTV0910_P2_PLROOT1 0xf2ad -+#define FSTV0910_P2_PLSCRAMB_ROOT1 0xf2ad00ff -+ -+/*P2_PLROOT0*/ -+#define RSTV0910_P2_PLROOT0 0xf2ae -+#define FSTV0910_P2_PLSCRAMB_ROOT0 0xf2ae00ff -+ -+/*P2_MODCODLST7*/ -+#define RSTV0910_P2_MODCODLST7 0xf2b7 -+#define FSTV0910_P2_MODCOD_NNOSFILTER 0xf2b70080 -+#define FSTV0910_P2_MODCODLST_NOSTYPE 0xf2b70040 -+#define FSTV0910_P2_DIS_8PSK_9_10 0xf2b70030 -+#define FSTV0910_P2_DIS_8P_8_9 0xf2b7000f -+ -+/*P2_MODCODLST8*/ -+#define RSTV0910_P2_MODCODLST8 0xf2b8 -+#define FSTV0910_P2_DIS_8P_5_6 0xf2b800f0 -+#define FSTV0910_P2_DIS_8P_3_4 0xf2b8000f -+ -+/*P2_MODCODLST9*/ -+#define RSTV0910_P2_MODCODLST9 0xf2b9 -+#define FSTV0910_P2_DIS_8P_2_3 0xf2b900f0 -+#define FSTV0910_P2_DIS_8P_3_5 0xf2b9000f -+ -+/*P2_MODCODLSTA*/ -+#define RSTV0910_P2_MODCODLSTA 0xf2ba -+#define FSTV0910_P2_NOSFILTER_LIMITE 0xf2ba0080 -+#define FSTV0910_P2_NOSFILTER_MODE 0xf2ba0040 -+#define FSTV0910_P2_DIS_QPSK_9_10 0xf2ba0030 -+#define FSTV0910_P2_DIS_QP_8_9 0xf2ba000f -+ -+/*P2_MODCODLSTB*/ -+#define RSTV0910_P2_MODCODLSTB 0xf2bb -+#define FSTV0910_P2_DIS_QP_5_6 0xf2bb00f0 -+#define FSTV0910_P2_DIS_QP_4_5 0xf2bb000f -+ -+/*P2_MODCODLSTC*/ -+#define RSTV0910_P2_MODCODLSTC 0xf2bc -+#define FSTV0910_P2_DIS_QP_3_4 0xf2bc00f0 -+#define FSTV0910_P2_DIS_QP_2_3 0xf2bc000f -+ -+/*P2_MODCODLSTD*/ -+#define RSTV0910_P2_MODCODLSTD 0xf2bd -+#define FSTV0910_P2_DIS_QPSK_3_5 0xf2bd00f0 -+#define FSTV0910_P2_DIS_QPSK_1_2 0xf2bd000f -+ -+/*P2_GAUSSR0*/ -+#define RSTV0910_P2_GAUSSR0 0xf2c0 -+#define FSTV0910_P2_EN_CCIMODE 0xf2c00080 -+#define FSTV0910_P2_R0_GAUSSIEN 0xf2c0007f -+ -+/*P2_CCIR0*/ -+#define RSTV0910_P2_CCIR0 0xf2c1 -+#define FSTV0910_P2_CCIDETECT_PLHONLY 0xf2c10080 -+#define FSTV0910_P2_R0_CCI 0xf2c1007f -+ -+/*P2_CCIQUANT*/ -+#define RSTV0910_P2_CCIQUANT 0xf2c2 -+#define FSTV0910_P2_CCI_BETA 0xf2c200e0 -+#define FSTV0910_P2_CCI_QUANT 0xf2c2001f -+ -+/*P2_CCITHRES*/ -+#define RSTV0910_P2_CCITHRES 0xf2c3 -+#define FSTV0910_P2_CCI_THRESHOLD 0xf2c300ff -+ -+/*P2_CCIACC*/ -+#define RSTV0910_P2_CCIACC 0xf2c4 -+#define FSTV0910_P2_CCI_VALUE 0xf2c400ff -+ -+/*P2_DSTATUS4*/ -+#define RSTV0910_P2_DSTATUS4 0xf2c5 -+#define FSTV0910_P2_RAINFADE_DETECT 0xf2c50080 -+#define FSTV0910_P2_NOTHRES2_FAIL 0xf2c50040 -+#define FSTV0910_P2_NOTHRES1_FAIL 0xf2c50020 -+#define FSTV0910_P2_PILOT_FAILDETECT 0xf2c50010 -+#define FSTV0910_P2_HIER_DETECT 0xf2c50008 -+#define FSTV0910_P2_DMDPROG_ERROR 0xf2c50004 -+#define FSTV0910_P2_CSTENV_DETECT 0xf2c50002 -+#define FSTV0910_P2_DETECTION_TRIAX 0xf2c50001 -+ -+/*P2_DMDRESCFG*/ -+#define RSTV0910_P2_DMDRESCFG 0xf2c6 -+#define FSTV0910_P2_DMDRES_RESET 0xf2c60080 -+#define FSTV0910_P2_DMDRES_NOISESQR 0xf2c60010 -+#define FSTV0910_P2_DMDRES_STRALL 0xf2c60008 -+#define FSTV0910_P2_DMDRES_NEWONLY 0xf2c60004 -+#define FSTV0910_P2_DMDRES_NOSTORE 0xf2c60002 -+#define FSTV0910_P2_DMDRES_AGC2MEM 0xf2c60001 -+ -+/*P2_DMDRESADR*/ -+#define RSTV0910_P2_DMDRESADR 0xf2c7 -+#define FSTV0910_P2_SUSP_PREDCANAL 0xf2c70080 -+#define FSTV0910_P2_DMDRES_VALIDCFR 0xf2c70040 -+#define FSTV0910_P2_DMDRES_MEMFULL 0xf2c70030 -+#define FSTV0910_P2_DMDRES_RESNBR 0xf2c7000f -+ -+/*P2_DMDRESDATA7*/ -+#define RSTV0910_P2_DMDRESDATA7 0xf2c8 -+#define FSTV0910_P2_DMDRES_DATA7 0xf2c800ff -+ -+/*P2_DMDRESDATA6*/ -+#define RSTV0910_P2_DMDRESDATA6 0xf2c9 -+#define FSTV0910_P2_DMDRES_DATA6 0xf2c900ff -+ -+/*P2_DMDRESDATA5*/ -+#define RSTV0910_P2_DMDRESDATA5 0xf2ca -+#define FSTV0910_P2_DMDRES_DATA5 0xf2ca00ff -+ -+/*P2_DMDRESDATA4*/ -+#define RSTV0910_P2_DMDRESDATA4 0xf2cb -+#define FSTV0910_P2_DMDRES_DATA4 0xf2cb00ff -+ -+/*P2_DMDRESDATA3*/ -+#define RSTV0910_P2_DMDRESDATA3 0xf2cc -+#define FSTV0910_P2_DMDRES_DATA3 0xf2cc00ff -+ -+/*P2_DMDRESDATA2*/ -+#define RSTV0910_P2_DMDRESDATA2 0xf2cd -+#define FSTV0910_P2_DMDRES_DATA2 0xf2cd00ff -+ -+/*P2_DMDRESDATA1*/ -+#define RSTV0910_P2_DMDRESDATA1 0xf2ce -+#define FSTV0910_P2_DMDRES_DATA1 0xf2ce00ff -+ -+/*P2_DMDRESDATA0*/ -+#define RSTV0910_P2_DMDRESDATA0 0xf2cf -+#define FSTV0910_P2_DMDRES_DATA0 0xf2cf00ff -+ -+/*P2_FFEI1*/ -+#define RSTV0910_P2_FFEI1 0xf2d0 -+#define FSTV0910_P2_FFE_ACCI1 0xf2d001ff -+ -+/*P2_FFEQ1*/ -+#define RSTV0910_P2_FFEQ1 0xf2d1 -+#define FSTV0910_P2_FFE_ACCQ1 0xf2d101ff -+ -+/*P2_FFEI2*/ -+#define RSTV0910_P2_FFEI2 0xf2d2 -+#define FSTV0910_P2_FFE_ACCI2 0xf2d201ff -+ -+/*P2_FFEQ2*/ -+#define RSTV0910_P2_FFEQ2 0xf2d3 -+#define FSTV0910_P2_FFE_ACCQ2 0xf2d301ff -+ -+/*P2_FFEI3*/ -+#define RSTV0910_P2_FFEI3 0xf2d4 -+#define FSTV0910_P2_FFE_ACCI3 0xf2d401ff -+ -+/*P2_FFEQ3*/ -+#define RSTV0910_P2_FFEQ3 0xf2d5 -+#define FSTV0910_P2_FFE_ACCQ3 0xf2d501ff -+ -+/*P2_FFEI4*/ -+#define RSTV0910_P2_FFEI4 0xf2d6 -+#define FSTV0910_P2_FFE_ACCI4 0xf2d601ff -+ -+/*P2_FFEQ4*/ -+#define RSTV0910_P2_FFEQ4 0xf2d7 -+#define FSTV0910_P2_FFE_ACCQ4 0xf2d701ff -+ -+/*P2_FFECFG*/ -+#define RSTV0910_P2_FFECFG 0xf2d8 -+#define FSTV0910_P2_EQUALFFE_ON 0xf2d80040 -+#define FSTV0910_P2_EQUAL_USEDSYMB 0xf2d80030 -+#define FSTV0910_P2_MU_EQUALFFE 0xf2d80007 -+ -+/*P2_TNRCFG2*/ -+#define RSTV0910_P2_TNRCFG2 0xf2e1 -+#define FSTV0910_P2_TUN_IQSWAP 0xf2e10080 -+#define FSTV0910_P2_STB6110_STEP2MHZ 0xf2e10040 -+#define FSTV0910_P2_STB6120_DBLI2C 0xf2e10020 -+#define FSTV0910_P2_TUNER_WIDEBAND 0xf2e10010 -+#define FSTV0910_P2_TUNER_OBSPAGE 0xf2e10008 -+#define FSTV0910_P2_DIS_BWCALC 0xf2e10004 -+#define FSTV0910_P2_SHORT_WAITSTATES 0xf2e10002 -+#define FSTV0910_P2_DIS_2BWAGC1 0xf2e10001 -+ -+/*P2_SMAPCOEF7*/ -+#define RSTV0910_P2_SMAPCOEF7 0xf300 -+#define FSTV0910_P2_DIS_QSCALE 0xf3000080 -+#define FSTV0910_P2_SMAPCOEF_Q_LLR12 0xf300017f -+ -+/*P2_SMAPCOEF6*/ -+#define RSTV0910_P2_SMAPCOEF6 0xf301 -+#define FSTV0910_P2_DIS_AGC2SCALE 0xf3010080 -+#define FSTV0910_P2_DIS_16IQMULT 0xf3010040 -+#define FSTV0910_P2_OLD_16APSK47 0xf3010020 -+#define FSTV0910_P2_OLD_16APSK12 0xf3010010 -+#define FSTV0910_P2_DIS_NEWSCALE 0xf3010008 -+#define FSTV0910_P2_ADJ_8PSKLLR1 0xf3010004 -+#define FSTV0910_P2_OLD_8PSKLLR1 0xf3010002 -+#define FSTV0910_P2_DIS_AB8PSK 0xf3010001 -+ -+/*P2_SMAPCOEF5*/ -+#define RSTV0910_P2_SMAPCOEF5 0xf302 -+#define FSTV0910_P2_DIS_8SCALE 0xf3020080 -+#define FSTV0910_P2_SMAPCOEF_8P_LLR23 0xf302017f -+ -+/*P2_NOSTHRES1*/ -+#define RSTV0910_P2_NOSTHRES1 0xf309 -+#define FSTV0910_P2_NOS_THRESHOLD1 0xf30900ff -+ -+/*P2_NOSTHRES2*/ -+#define RSTV0910_P2_NOSTHRES2 0xf30a -+#define FSTV0910_P2_NOS_THRESHOLD2 0xf30a00ff -+ -+/*P2_NOSDIFF1*/ -+#define RSTV0910_P2_NOSDIFF1 0xf30b -+#define FSTV0910_P2_NOSTHRES1_DIFF 0xf30b00ff -+ -+/*P2_RAINFADE*/ -+#define RSTV0910_P2_RAINFADE 0xf30c -+#define FSTV0910_P2_NOSTHRES_DATAT 0xf30c0080 -+#define FSTV0910_P2_RAINFADE_CNLIMIT 0xf30c0070 -+#define FSTV0910_P2_RAINFADE_TIMEOUT 0xf30c0007 -+ -+/*P2_NOSRAMCFG*/ -+#define RSTV0910_P2_NOSRAMCFG 0xf30d -+#define FSTV0910_P2_NOSRAM_DVBS2DATA 0xf30d0080 -+#define FSTV0910_P2_NOSRAM_QUADRAT 0xf30d0040 -+#define FSTV0910_P2_NOSRAM_ACTIVATION 0xf30d0030 -+#define FSTV0910_P2_NOSRAM_CNRONLY 0xf30d0008 -+#define FSTV0910_P2_NOSRAM_LGNCNR1 0xf30d0007 -+ -+/*P2_NOSRAMPOS*/ -+#define RSTV0910_P2_NOSRAMPOS 0xf30e -+#define FSTV0910_P2_NOSRAM_LGNCNR0 0xf30e00f0 -+#define FSTV0910_P2_NOSRAM_VALIDE 0xf30e0004 -+#define FSTV0910_P2_NOSRAM_CNRVAL1 0xf30e0003 -+ -+/*P2_NOSRAMVAL*/ -+#define RSTV0910_P2_NOSRAMVAL 0xf30f -+#define FSTV0910_P2_NOSRAM_CNRVAL0 0xf30f00ff -+ -+/*P2_DMDPLHSTAT*/ -+#define RSTV0910_P2_DMDPLHSTAT 0xf320 -+#define FSTV0910_P2_PLH_STATISTIC 0xf32000ff -+ -+/*P2_LOCKTIME3*/ -+#define RSTV0910_P2_LOCKTIME3 0xf322 -+#define FSTV0910_P2_DEMOD_LOCKTIME3 0xf32200ff -+ -+/*P2_LOCKTIME2*/ -+#define RSTV0910_P2_LOCKTIME2 0xf323 -+#define FSTV0910_P2_DEMOD_LOCKTIME2 0xf32300ff -+ -+/*P2_LOCKTIME1*/ -+#define RSTV0910_P2_LOCKTIME1 0xf324 -+#define FSTV0910_P2_DEMOD_LOCKTIME1 0xf32400ff -+ -+/*P2_LOCKTIME0*/ -+#define RSTV0910_P2_LOCKTIME0 0xf325 -+#define FSTV0910_P2_DEMOD_LOCKTIME0 0xf32500ff -+ -+/*P2_VITSCALE*/ -+#define RSTV0910_P2_VITSCALE 0xf332 -+#define FSTV0910_P2_NVTH_NOSRANGE 0xf3320080 -+#define FSTV0910_P2_VERROR_MAXMODE 0xf3320040 -+#define FSTV0910_P2_KDIV_MODE 0xf3320030 -+#define FSTV0910_P2_NSLOWSN_LOCKED 0xf3320008 -+#define FSTV0910_P2_DELOCK_PRFLOSS 0xf3320004 -+#define FSTV0910_P2_DIS_RSFLOCK 0xf3320002 -+ -+/*P2_FECM*/ -+#define RSTV0910_P2_FECM 0xf333 -+#define FSTV0910_P2_DSS_DVB 0xf3330080 -+#define FSTV0910_P2_DEMOD_BYPASS 0xf3330040 -+#define FSTV0910_P2_CMP_SLOWMODE 0xf3330020 -+#define FSTV0910_P2_DSS_SRCH 0xf3330010 -+#define FSTV0910_P2_DIFF_MODEVIT 0xf3330004 -+#define FSTV0910_P2_SYNCVIT 0xf3330002 -+#define FSTV0910_P2_IQINV 0xf3330001 -+ -+/*P2_VTH12*/ -+#define RSTV0910_P2_VTH12 0xf334 -+#define FSTV0910_P2_VTH12 0xf33400ff -+ -+/*P2_VTH23*/ -+#define RSTV0910_P2_VTH23 0xf335 -+#define FSTV0910_P2_VTH23 0xf33500ff -+ -+/*P2_VTH34*/ -+#define RSTV0910_P2_VTH34 0xf336 -+#define FSTV0910_P2_VTH34 0xf33600ff -+ -+/*P2_VTH56*/ -+#define RSTV0910_P2_VTH56 0xf337 -+#define FSTV0910_P2_VTH56 0xf33700ff -+ -+/*P2_VTH67*/ -+#define RSTV0910_P2_VTH67 0xf338 -+#define FSTV0910_P2_VTH67 0xf33800ff -+ -+/*P2_VTH78*/ -+#define RSTV0910_P2_VTH78 0xf339 -+#define FSTV0910_P2_VTH78 0xf33900ff -+ -+/*P2_VITCURPUN*/ -+#define RSTV0910_P2_VITCURPUN 0xf33a -+#define FSTV0910_P2_CYCLESLIP_VIT 0xf33a0080 -+#define FSTV0910_P2_VIT_ROTA180 0xf33a0040 -+#define FSTV0910_P2_VIT_ROTA90 0xf33a0020 -+#define FSTV0910_P2_VIT_CURPUN 0xf33a001f -+ -+/*P2_VERROR*/ -+#define RSTV0910_P2_VERROR 0xf33b -+#define FSTV0910_P2_REGERR_VIT 0xf33b00ff -+ -+/*P2_PRVIT*/ -+#define RSTV0910_P2_PRVIT 0xf33c -+#define FSTV0910_P2_DIS_VTHLOCK 0xf33c0040 -+#define FSTV0910_P2_E7_8VIT 0xf33c0020 -+#define FSTV0910_P2_E6_7VIT 0xf33c0010 -+#define FSTV0910_P2_E5_6VIT 0xf33c0008 -+#define FSTV0910_P2_E3_4VIT 0xf33c0004 -+#define FSTV0910_P2_E2_3VIT 0xf33c0002 -+#define FSTV0910_P2_E1_2VIT 0xf33c0001 -+ -+/*P2_VAVSRVIT*/ -+#define RSTV0910_P2_VAVSRVIT 0xf33d -+#define FSTV0910_P2_AMVIT 0xf33d0080 -+#define FSTV0910_P2_FROZENVIT 0xf33d0040 -+#define FSTV0910_P2_SNVIT 0xf33d0030 -+#define FSTV0910_P2_TOVVIT 0xf33d000c -+#define FSTV0910_P2_HYPVIT 0xf33d0003 -+ -+/*P2_VSTATUSVIT*/ -+#define RSTV0910_P2_VSTATUSVIT 0xf33e -+#define FSTV0910_P2_VITERBI_ON 0xf33e0080 -+#define FSTV0910_P2_END_LOOPVIT 0xf33e0040 -+#define FSTV0910_P2_VITERBI_DEPRF 0xf33e0020 -+#define FSTV0910_P2_PRFVIT 0xf33e0010 -+#define FSTV0910_P2_LOCKEDVIT 0xf33e0008 -+#define FSTV0910_P2_VITERBI_DELOCK 0xf33e0004 -+#define FSTV0910_P2_VIT_DEMODSEL 0xf33e0002 -+#define FSTV0910_P2_VITERBI_COMPOUT 0xf33e0001 -+ -+/*P2_VTHINUSE*/ -+#define RSTV0910_P2_VTHINUSE 0xf33f -+#define FSTV0910_P2_VIT_INUSE 0xf33f00ff -+ -+/*P2_KDIV12*/ -+#define RSTV0910_P2_KDIV12 0xf340 -+#define FSTV0910_P2_KDIV12_MANUAL 0xf3400080 -+#define FSTV0910_P2_K_DIVIDER_12 0xf340007f -+ -+/*P2_KDIV23*/ -+#define RSTV0910_P2_KDIV23 0xf341 -+#define FSTV0910_P2_KDIV23_MANUAL 0xf3410080 -+#define FSTV0910_P2_K_DIVIDER_23 0xf341007f -+ -+/*P2_KDIV34*/ -+#define RSTV0910_P2_KDIV34 0xf342 -+#define FSTV0910_P2_KDIV34_MANUAL 0xf3420080 -+#define FSTV0910_P2_K_DIVIDER_34 0xf342007f -+ -+/*P2_KDIV56*/ -+#define RSTV0910_P2_KDIV56 0xf343 -+#define FSTV0910_P2_KDIV56_MANUAL 0xf3430080 -+#define FSTV0910_P2_K_DIVIDER_56 0xf343007f -+ -+/*P2_KDIV67*/ -+#define RSTV0910_P2_KDIV67 0xf344 -+#define FSTV0910_P2_KDIV67_MANUAL 0xf3440080 -+#define FSTV0910_P2_K_DIVIDER_67 0xf344007f -+ -+/*P2_KDIV78*/ -+#define RSTV0910_P2_KDIV78 0xf345 -+#define FSTV0910_P2_KDIV78_MANUAL 0xf3450080 -+#define FSTV0910_P2_K_DIVIDER_78 0xf345007f -+ -+/*P2_PDELCTRL0*/ -+#define RSTV0910_P2_PDELCTRL0 0xf34f -+#define FSTV0910_P2_ISIOBS_MODE 0xf34f0030 -+#define FSTV0910_P2_PDELDIS_BITWISE 0xf34f0004 -+ -+/*P2_PDELCTRL1*/ -+#define RSTV0910_P2_PDELCTRL1 0xf350 -+#define FSTV0910_P2_INV_MISMASK 0xf3500080 -+#define FSTV0910_P2_FORCE_ACCEPTED 0xf3500040 -+#define FSTV0910_P2_FILTER_EN 0xf3500020 -+#define FSTV0910_P2_FORCE_PKTDELINUSE 0xf3500010 -+#define FSTV0910_P2_HYSTEN 0xf3500008 -+#define FSTV0910_P2_HYSTSWRST 0xf3500004 -+#define FSTV0910_P2_EN_MIS00 0xf3500002 -+#define FSTV0910_P2_ALGOSWRST 0xf3500001 -+ -+/*P2_PDELCTRL2*/ -+#define RSTV0910_P2_PDELCTRL2 0xf351 -+#define FSTV0910_P2_FORCE_CONTINUOUS 0xf3510080 -+#define FSTV0910_P2_RESET_UPKO_COUNT 0xf3510040 -+#define FSTV0910_P2_USER_PKTDELIN_NB 0xf3510020 -+#define FSTV0910_P2_DATA_UNBBSCRAMBLED 0xf3510008 -+#define FSTV0910_P2_FORCE_LONGPKT 0xf3510004 -+#define FSTV0910_P2_FRAME_MODE 0xf3510002 -+ -+/*P2_HYSTTHRESH*/ -+#define RSTV0910_P2_HYSTTHRESH 0xf354 -+#define FSTV0910_P2_DELIN_LOCKTHRES 0xf35400f0 -+#define FSTV0910_P2_DELIN_UNLOCKTHRES 0xf354000f -+ -+/*P2_ISIENTRY*/ -+#define RSTV0910_P2_ISIENTRY 0xf35e -+#define FSTV0910_P2_ISI_ENTRY 0xf35e00ff -+ -+/*P2_ISIBITENA*/ -+#define RSTV0910_P2_ISIBITENA 0xf35f -+#define FSTV0910_P2_ISI_BIT_EN 0xf35f00ff -+ -+/*P2_MATSTR1*/ -+#define RSTV0910_P2_MATSTR1 0xf360 -+#define FSTV0910_P2_MATYPE_CURRENT1 0xf36000ff -+ -+/*P2_MATSTR0*/ -+#define RSTV0910_P2_MATSTR0 0xf361 -+#define FSTV0910_P2_MATYPE_CURRENT0 0xf36100ff -+ -+/*P2_UPLSTR1*/ -+#define RSTV0910_P2_UPLSTR1 0xf362 -+#define FSTV0910_P2_UPL_CURRENT1 0xf36200ff -+ -+/*P2_UPLSTR0*/ -+#define RSTV0910_P2_UPLSTR0 0xf363 -+#define FSTV0910_P2_UPL_CURRENT0 0xf36300ff -+ -+/*P2_DFLSTR1*/ -+#define RSTV0910_P2_DFLSTR1 0xf364 -+#define FSTV0910_P2_DFL_CURRENT1 0xf36400ff -+ -+/*P2_DFLSTR0*/ -+#define RSTV0910_P2_DFLSTR0 0xf365 -+#define FSTV0910_P2_DFL_CURRENT0 0xf36500ff -+ -+/*P2_SYNCSTR*/ -+#define RSTV0910_P2_SYNCSTR 0xf366 -+#define FSTV0910_P2_SYNC_CURRENT 0xf36600ff -+ -+/*P2_SYNCDSTR1*/ -+#define RSTV0910_P2_SYNCDSTR1 0xf367 -+#define FSTV0910_P2_SYNCD_CURRENT1 0xf36700ff -+ -+/*P2_SYNCDSTR0*/ -+#define RSTV0910_P2_SYNCDSTR0 0xf368 -+#define FSTV0910_P2_SYNCD_CURRENT0 0xf36800ff -+ -+/*P2_PDELSTATUS1*/ -+#define RSTV0910_P2_PDELSTATUS1 0xf369 -+#define FSTV0910_P2_PKTDELIN_DELOCK 0xf3690080 -+#define FSTV0910_P2_SYNCDUPDFL_BADDFL 0xf3690040 -+#define FSTV0910_P2_CONTINUOUS_STREAM 0xf3690020 -+#define FSTV0910_P2_UNACCEPTED_STREAM 0xf3690010 -+#define FSTV0910_P2_BCH_ERROR_FLAG 0xf3690008 -+#define FSTV0910_P2_BBHCRCKO 0xf3690004 -+#define FSTV0910_P2_PKTDELIN_LOCK 0xf3690002 -+#define FSTV0910_P2_FIRST_LOCK 0xf3690001 -+ -+/*P2_PDELSTATUS2*/ -+#define RSTV0910_P2_PDELSTATUS2 0xf36a -+#define FSTV0910_P2_PKTDEL_DEMODSEL 0xf36a0080 -+#define FSTV0910_P2_FRAME_MODCOD 0xf36a007c -+#define FSTV0910_P2_FRAME_TYPE 0xf36a0003 -+ -+/*P2_BBFCRCKO1*/ -+#define RSTV0910_P2_BBFCRCKO1 0xf36b -+#define FSTV0910_P2_BBHCRC_KOCNT1 0xf36b00ff -+ -+/*P2_BBFCRCKO0*/ -+#define RSTV0910_P2_BBFCRCKO0 0xf36c -+#define FSTV0910_P2_BBHCRC_KOCNT0 0xf36c00ff -+ -+/*P2_UPCRCKO1*/ -+#define RSTV0910_P2_UPCRCKO1 0xf36d -+#define FSTV0910_P2_PKTCRC_KOCNT1 0xf36d00ff -+ -+/*P2_UPCRCKO0*/ -+#define RSTV0910_P2_UPCRCKO0 0xf36e -+#define FSTV0910_P2_PKTCRC_KOCNT0 0xf36e00ff -+ -+/*P2_PDELCTRL3*/ -+#define RSTV0910_P2_PDELCTRL3 0xf36f -+#define FSTV0910_P2_PKTDEL_CONTFAIL 0xf36f0080 -+#define FSTV0910_P2_PKTDEL_ENLONGPKT 0xf36f0040 -+#define FSTV0910_P2_NOFIFO_BCHERR 0xf36f0020 -+#define FSTV0910_P2_PKTDELIN_DELACMERR 0xf36f0010 -+#define FSTV0910_P2_SATURATE_BBPKTKO 0xf36f0004 -+#define FSTV0910_P2_PKTDEL_BCHERRCONT 0xf36f0002 -+#define FSTV0910_P2_ETHERNET_DISFCS 0xf36f0001 -+ -+/*P2_TSSTATEM*/ -+#define RSTV0910_P2_TSSTATEM 0xf370 -+#define FSTV0910_P2_TSDIL_ON 0xf3700080 -+#define FSTV0910_P2_TSSKIPRS_ON 0xf3700040 -+#define FSTV0910_P2_TSRS_ON 0xf3700020 -+#define FSTV0910_P2_TSDESCRAMB_ON 0xf3700010 -+#define FSTV0910_P2_TSFRAME_MODE 0xf3700008 -+#define FSTV0910_P2_TS_DISABLE 0xf3700004 -+#define FSTV0910_P2_TSACM_MODE 0xf3700002 -+#define FSTV0910_P2_TSOUT_NOSYNC 0xf3700001 -+ -+/*P2_TSCFGH*/ -+#define RSTV0910_P2_TSCFGH 0xf372 -+#define FSTV0910_P2_TSFIFO_DVBCI 0xf3720080 -+#define FSTV0910_P2_TSFIFO_SERIAL 0xf3720040 -+#define FSTV0910_P2_TSFIFO_TEIUPDATE 0xf3720020 -+#define FSTV0910_P2_TSFIFO_DUTY50 0xf3720010 -+#define FSTV0910_P2_TSFIFO_HSGNLOUT 0xf3720008 -+#define FSTV0910_P2_TSFIFO_ERRMODE 0xf3720006 -+#define FSTV0910_P2_RST_HWARE 0xf3720001 -+ -+/*P2_TSCFGM*/ -+#define RSTV0910_P2_TSCFGM 0xf373 -+#define FSTV0910_P2_TSFIFO_MANSPEED 0xf37300c0 -+#define FSTV0910_P2_TSFIFO_PERMDATA 0xf3730020 -+#define FSTV0910_P2_TSFIFO_NONEWSGNL 0xf3730010 -+#define FSTV0910_P2_NPD_SPECDVBS2 0xf3730004 -+#define FSTV0910_P2_TSFIFO_DPUNACTIVE 0xf3730002 -+#define FSTV0910_P2_TSFIFO_INVDATA 0xf3730001 -+ -+/*P2_TSCFGL*/ -+#define RSTV0910_P2_TSCFGL 0xf374 -+#define FSTV0910_P2_TSFIFO_BCLKDEL1CK 0xf37400c0 -+#define FSTV0910_P2_BCHERROR_MODE 0xf3740030 -+#define FSTV0910_P2_TSFIFO_NSGNL2DATA 0xf3740008 -+#define FSTV0910_P2_TSFIFO_EMBINDVB 0xf3740004 -+#define FSTV0910_P2_TSFIFO_BITSPEED 0xf3740003 -+ -+/*P2_TSINSDELH*/ -+#define RSTV0910_P2_TSINSDELH 0xf376 -+#define FSTV0910_P2_TSDEL_SYNCBYTE 0xf3760080 -+#define FSTV0910_P2_TSDEL_XXHEADER 0xf3760040 -+#define FSTV0910_P2_TSDEL_BBHEADER 0xf3760020 -+#define FSTV0910_P2_TSDEL_DATAFIELD 0xf3760010 -+#define FSTV0910_P2_TSINSDEL_ISCR 0xf3760008 -+#define FSTV0910_P2_TSINSDEL_NPD 0xf3760004 -+#define FSTV0910_P2_TSINSDEL_RSPARITY 0xf3760002 -+#define FSTV0910_P2_TSINSDEL_CRC8 0xf3760001 -+ -+/*P2_TSDIVN*/ -+#define RSTV0910_P2_TSDIVN 0xf379 -+#define FSTV0910_P2_TSFIFO_SPEEDMODE 0xf37900c0 -+#define FSTV0910_P2_BYTE_OVERSAMPLING 0xf3790038 -+#define FSTV0910_P2_TSFIFO_RISEOK 0xf3790007 -+ -+/*P2_TSCFG4*/ -+#define RSTV0910_P2_TSCFG4 0xf37a -+#define FSTV0910_P2_TSFIFO_TSSPEEDMODE 0xf37a00c0 -+#define FSTV0910_P2_TSFIFO_HIERSEL 0xf37a0020 -+#define FSTV0910_P2_TSFIFO_SPECTOKEN 0xf37a0010 -+#define FSTV0910_P2_TSFIFO_MAXMODE 0xf37a0008 -+#define FSTV0910_P2_TSFIFO_FRFORCEPKT 0xf37a0004 -+#define FSTV0910_P2_EXT_FECSPYIN 0xf37a0002 -+#define FSTV0910_P2_TSFIFO_DELSPEEDUP 0xf37a0001 -+ -+/*P2_TSSPEED*/ -+#define RSTV0910_P2_TSSPEED 0xf380 -+#define FSTV0910_P2_TSFIFO_OUTSPEED 0xf38000ff -+ -+/*P2_TSSTATUS*/ -+#define RSTV0910_P2_TSSTATUS 0xf381 -+#define FSTV0910_P2_TSFIFO_LINEOK 0xf3810080 -+#define FSTV0910_P2_TSFIFO_ERROR 0xf3810040 -+#define FSTV0910_P2_TSFIFO_DATA7 0xf3810020 -+#define FSTV0910_P2_TSFIFO_NOSYNC 0xf3810010 -+#define FSTV0910_P2_ISCR_INITIALIZED 0xf3810008 -+#define FSTV0910_P2_TSREGUL_ERROR 0xf3810004 -+#define FSTV0910_P2_SOFFIFO_UNREGUL 0xf3810002 -+#define FSTV0910_P2_DIL_READY 0xf3810001 -+ -+/*P2_TSSTATUS2*/ -+#define RSTV0910_P2_TSSTATUS2 0xf382 -+#define FSTV0910_P2_TSFIFO_DEMODSEL 0xf3820080 -+#define FSTV0910_P2_TSFIFOSPEED_STORE 0xf3820040 -+#define FSTV0910_P2_DILXX_RESET 0xf3820020 -+#define FSTV0910_P2_TSSPEED_IMPOSSIBLE 0xf3820010 -+#define FSTV0910_P2_TSFIFO_LINENOK 0xf3820008 -+#define FSTV0910_P2_TSFIFO_MUXSTREAM 0xf3820004 -+#define FSTV0910_P2_SCRAMBDETECT 0xf3820002 -+#define FSTV0910_P2_ULDTV67_FALSELOCK 0xf3820001 -+ -+/*P2_TSBITRATE1*/ -+#define RSTV0910_P2_TSBITRATE1 0xf383 -+#define FSTV0910_P2_TSFIFO_BITRATE1 0xf38300ff -+ -+/*P2_TSBITRATE0*/ -+#define RSTV0910_P2_TSBITRATE0 0xf384 -+#define FSTV0910_P2_TSFIFO_BITRATE0 0xf38400ff -+ -+/*P2_ERRCTRL1*/ -+#define RSTV0910_P2_ERRCTRL1 0xf398 -+#define FSTV0910_P2_ERR_SOURCE1 0xf39800f0 -+#define FSTV0910_P2_NUM_EVENT1 0xf3980007 -+ -+/*P2_ERRCNT12*/ -+#define RSTV0910_P2_ERRCNT12 0xf399 -+#define FSTV0910_P2_ERRCNT1_OLDVALUE 0xf3990080 -+#define FSTV0910_P2_ERR_CNT12 0xf399007f -+ -+/*P2_ERRCNT11*/ -+#define RSTV0910_P2_ERRCNT11 0xf39a -+#define FSTV0910_P2_ERR_CNT11 0xf39a00ff -+ -+/*P2_ERRCNT10*/ -+#define RSTV0910_P2_ERRCNT10 0xf39b -+#define FSTV0910_P2_ERR_CNT10 0xf39b00ff -+ -+/*P2_ERRCTRL2*/ -+#define RSTV0910_P2_ERRCTRL2 0xf39c -+#define FSTV0910_P2_ERR_SOURCE2 0xf39c00f0 -+#define FSTV0910_P2_NUM_EVENT2 0xf39c0007 -+ -+/*P2_ERRCNT22*/ -+#define RSTV0910_P2_ERRCNT22 0xf39d -+#define FSTV0910_P2_ERRCNT2_OLDVALUE 0xf39d0080 -+#define FSTV0910_P2_ERR_CNT22 0xf39d007f -+ -+/*P2_ERRCNT21*/ -+#define RSTV0910_P2_ERRCNT21 0xf39e -+#define FSTV0910_P2_ERR_CNT21 0xf39e00ff -+ -+/*P2_ERRCNT20*/ -+#define RSTV0910_P2_ERRCNT20 0xf39f -+#define FSTV0910_P2_ERR_CNT20 0xf39f00ff -+ -+/*P2_FECSPY*/ -+#define RSTV0910_P2_FECSPY 0xf3a0 -+#define FSTV0910_P2_SPY_ENABLE 0xf3a00080 -+#define FSTV0910_P2_NO_SYNCBYTE 0xf3a00040 -+#define FSTV0910_P2_SERIAL_MODE 0xf3a00020 -+#define FSTV0910_P2_UNUSUAL_PACKET 0xf3a00010 -+#define FSTV0910_P2_BERMETER_DATAMODE 0xf3a0000c -+#define FSTV0910_P2_BERMETER_LMODE 0xf3a00002 -+#define FSTV0910_P2_BERMETER_RESET 0xf3a00001 -+ -+/*P2_FSPYCFG*/ -+#define RSTV0910_P2_FSPYCFG 0xf3a1 -+#define FSTV0910_P2_FECSPY_INPUT 0xf3a100c0 -+#define FSTV0910_P2_RST_ON_ERROR 0xf3a10020 -+#define FSTV0910_P2_ONE_SHOT 0xf3a10010 -+#define FSTV0910_P2_I2C_MODE 0xf3a1000c -+#define FSTV0910_P2_SPY_HYSTERESIS 0xf3a10003 -+ -+/*P2_FSPYDATA*/ -+#define RSTV0910_P2_FSPYDATA 0xf3a2 -+#define FSTV0910_P2_SPY_STUFFING 0xf3a20080 -+#define FSTV0910_P2_NOERROR_PKTJITTER 0xf3a20040 -+#define FSTV0910_P2_SPY_CNULLPKT 0xf3a20020 -+#define FSTV0910_P2_SPY_OUTDATA_MODE 0xf3a2001f -+ -+/*P2_FSPYOUT*/ -+#define RSTV0910_P2_FSPYOUT 0xf3a3 -+#define FSTV0910_P2_FSPY_DIRECT 0xf3a30080 -+#define FSTV0910_P2_SPY_OUTDATA_BUS 0xf3a30038 -+#define FSTV0910_P2_STUFF_MODE 0xf3a30007 -+ -+/*P2_FSTATUS*/ -+#define RSTV0910_P2_FSTATUS 0xf3a4 -+#define FSTV0910_P2_SPY_ENDSIM 0xf3a40080 -+#define FSTV0910_P2_VALID_SIM 0xf3a40040 -+#define FSTV0910_P2_FOUND_SIGNAL 0xf3a40020 -+#define FSTV0910_P2_DSS_SYNCBYTE 0xf3a40010 -+#define FSTV0910_P2_RESULT_STATE 0xf3a4000f -+ -+/*P2_FBERCPT4*/ -+#define RSTV0910_P2_FBERCPT4 0xf3a8 -+#define FSTV0910_P2_FBERMETER_CPT4 0xf3a800ff -+ -+/*P2_FBERCPT3*/ -+#define RSTV0910_P2_FBERCPT3 0xf3a9 -+#define FSTV0910_P2_FBERMETER_CPT3 0xf3a900ff -+ -+/*P2_FBERCPT2*/ -+#define RSTV0910_P2_FBERCPT2 0xf3aa -+#define FSTV0910_P2_FBERMETER_CPT2 0xf3aa00ff -+ -+/*P2_FBERCPT1*/ -+#define RSTV0910_P2_FBERCPT1 0xf3ab -+#define FSTV0910_P2_FBERMETER_CPT1 0xf3ab00ff -+ -+/*P2_FBERCPT0*/ -+#define RSTV0910_P2_FBERCPT0 0xf3ac -+#define FSTV0910_P2_FBERMETER_CPT0 0xf3ac00ff -+ -+/*P2_FBERERR2*/ -+#define RSTV0910_P2_FBERERR2 0xf3ad -+#define FSTV0910_P2_FBERMETER_ERR2 0xf3ad00ff -+ -+/*P2_FBERERR1*/ -+#define RSTV0910_P2_FBERERR1 0xf3ae -+#define FSTV0910_P2_FBERMETER_ERR1 0xf3ae00ff -+ -+/*P2_FBERERR0*/ -+#define RSTV0910_P2_FBERERR0 0xf3af -+#define FSTV0910_P2_FBERMETER_ERR0 0xf3af00ff -+ -+/*P2_FSPYBER*/ -+#define RSTV0910_P2_FSPYBER 0xf3b2 -+#define FSTV0910_P2_FSPYOBS_XORREAD 0xf3b20040 -+#define FSTV0910_P2_FSPYBER_OBSMODE 0xf3b20020 -+#define FSTV0910_P2_FSPYBER_SYNCBYTE 0xf3b20010 -+#define FSTV0910_P2_FSPYBER_UNSYNC 0xf3b20008 -+#define FSTV0910_P2_FSPYBER_CTIME 0xf3b20007 -+ -+/*P2_SFERROR*/ -+#define RSTV0910_P2_SFERROR 0xf3c1 -+#define FSTV0910_P2_SFEC_REGERR_VIT 0xf3c100ff -+ -+/*P2_SFECSTATUS*/ -+#define RSTV0910_P2_SFECSTATUS 0xf3c3 -+#define FSTV0910_P2_SFEC_ON 0xf3c30080 -+#define FSTV0910_P2_SFEC_OFF 0xf3c30040 -+#define FSTV0910_P2_LOCKEDSFEC 0xf3c30008 -+#define FSTV0910_P2_SFEC_DELOCK 0xf3c30004 -+#define FSTV0910_P2_SFEC_DEMODSEL 0xf3c30002 -+#define FSTV0910_P2_SFEC_OVFON 0xf3c30001 -+ -+/*P2_SFKDIV12*/ -+#define RSTV0910_P2_SFKDIV12 0xf3c4 -+#define FSTV0910_P2_SFECKDIV12_MAN 0xf3c40080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_12 0xf3c4007f -+ -+/*P2_SFKDIV23*/ -+#define RSTV0910_P2_SFKDIV23 0xf3c5 -+#define FSTV0910_P2_SFECKDIV23_MAN 0xf3c50080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_23 0xf3c5007f -+ -+/*P2_SFKDIV34*/ -+#define RSTV0910_P2_SFKDIV34 0xf3c6 -+#define FSTV0910_P2_SFECKDIV34_MAN 0xf3c60080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_34 0xf3c6007f -+ -+/*P2_SFKDIV56*/ -+#define RSTV0910_P2_SFKDIV56 0xf3c7 -+#define FSTV0910_P2_SFECKDIV56_MAN 0xf3c70080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_56 0xf3c7007f -+ -+/*P2_SFKDIV67*/ -+#define RSTV0910_P2_SFKDIV67 0xf3c8 -+#define FSTV0910_P2_SFECKDIV67_MAN 0xf3c80080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_67 0xf3c8007f -+ -+/*P2_SFKDIV78*/ -+#define RSTV0910_P2_SFKDIV78 0xf3c9 -+#define FSTV0910_P2_SFECKDIV78_MAN 0xf3c90080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_78 0xf3c9007f -+ -+/*P2_SFSTATUS*/ -+#define RSTV0910_P2_SFSTATUS 0xf3cc -+#define FSTV0910_P2_SFEC_LINEOK 0xf3cc0080 -+#define FSTV0910_P2_SFEC_ERROR 0xf3cc0040 -+#define FSTV0910_P2_SFEC_DATA7 0xf3cc0020 -+#define FSTV0910_P2_SFEC_PKTDNBRFAIL 0xf3cc0010 -+#define FSTV0910_P2_TSSFEC_DEMODSEL 0xf3cc0008 -+#define FSTV0910_P2_SFEC_NOSYNC 0xf3cc0004 -+#define FSTV0910_P2_SFEC_UNREGULA 0xf3cc0002 -+#define FSTV0910_P2_SFEC_READY 0xf3cc0001 -+ -+/*P2_SFDLYSET2*/ -+#define RSTV0910_P2_SFDLYSET2 0xf3d0 -+#define FSTV0910_P2_SFEC_OFFSET 0xf3d000c0 -+#define FSTV0910_P2_RST_SFEC 0xf3d00008 -+#define FSTV0910_P2_DILDLINE_ERROR 0xf3d00004 -+#define FSTV0910_P2_SFEC_DISABLE 0xf3d00002 -+#define FSTV0910_P2_SFEC_UNREGUL 0xf3d00001 -+ -+/*P2_SFERRCTRL*/ -+#define RSTV0910_P2_SFERRCTRL 0xf3d8 -+#define FSTV0910_P2_SFEC_ERR_SOURCE 0xf3d800f0 -+#define FSTV0910_P2_SFEC_NUM_EVENT 0xf3d80007 -+ -+/*P2_SFERRCNT2*/ -+#define RSTV0910_P2_SFERRCNT2 0xf3d9 -+#define FSTV0910_P2_SFERRC_OLDVALUE 0xf3d90080 -+#define FSTV0910_P2_SFEC_ERR_CNT2 0xf3d9007f -+ -+/*P2_SFERRCNT1*/ -+#define RSTV0910_P2_SFERRCNT1 0xf3da -+#define FSTV0910_P2_SFEC_ERR_CNT1 0xf3da00ff -+ -+/*P2_SFERRCNT0*/ -+#define RSTV0910_P2_SFERRCNT0 0xf3db -+#define FSTV0910_P2_SFEC_ERR_CNT0 0xf3db00ff -+ -+/*P1_IQCONST*/ -+#define RSTV0910_P1_IQCONST 0xf400 -+#define FSTV0910_P1_CONSTEL_SELECT 0xf4000060 -+#define FSTV0910_P1_IQSYMB_SEL 0xf400001f -+ -+/*P1_NOSCFG*/ -+#define RSTV0910_P1_NOSCFG 0xf401 -+#define FSTV0910_P1_DIS_ACMRATIO 0xf4010080 -+#define FSTV0910_P1_NOSIN_EGALSEL 0xf4010040 -+#define FSTV0910_P1_DUMMYPL_NOSDATA 0xf4010020 -+#define FSTV0910_P1_NOSPLH_BETA 0xf4010018 -+#define FSTV0910_P1_NOSDATA_BETA 0xf4010007 -+ -+/*P1_ISYMB*/ -+#define RSTV0910_P1_ISYMB 0xf402 -+#define FSTV0910_P1_I_SYMBOL 0xf40201ff -+ -+/*P1_QSYMB*/ -+#define RSTV0910_P1_QSYMB 0xf403 -+#define FSTV0910_P1_Q_SYMBOL 0xf40301ff -+ -+/*P1_AGC1CFG*/ -+#define RSTV0910_P1_AGC1CFG 0xf404 -+#define FSTV0910_P1_DC_FROZEN 0xf4040080 -+#define FSTV0910_P1_DC_CORRECT 0xf4040040 -+#define FSTV0910_P1_AMM_FROZEN 0xf4040020 -+#define FSTV0910_P1_AMM_CORRECT 0xf4040010 -+#define FSTV0910_P1_QUAD_FROZEN 0xf4040008 -+#define FSTV0910_P1_QUAD_CORRECT 0xf4040004 -+#define FSTV0910_P1_DCCOMP_SLOW 0xf4040002 -+#define FSTV0910_P1_IQMISM_SLOW 0xf4040001 -+ -+/*P1_AGC1CN*/ -+#define RSTV0910_P1_AGC1CN 0xf406 -+#define FSTV0910_P1_AGC1_LOCKED 0xf4060080 -+#define FSTV0910_P1_AGC1_OVERFLOW 0xf4060040 -+#define FSTV0910_P1_AGC1_NOSLOWLK 0xf4060020 -+#define FSTV0910_P1_AGC1_MINPOWER 0xf4060010 -+#define FSTV0910_P1_AGCOUT_FAST 0xf4060008 -+#define FSTV0910_P1_AGCIQ_BETA 0xf4060007 -+ -+/*P1_AGC1REF*/ -+#define RSTV0910_P1_AGC1REF 0xf407 -+#define FSTV0910_P1_AGCIQ_REF 0xf40700ff -+ -+/*P1_IDCCOMP*/ -+#define RSTV0910_P1_IDCCOMP 0xf408 -+#define FSTV0910_P1_IAVERAGE_ADJ 0xf40801ff -+ -+/*P1_QDCCOMP*/ -+#define RSTV0910_P1_QDCCOMP 0xf409 -+#define FSTV0910_P1_QAVERAGE_ADJ 0xf40901ff -+ -+/*P1_POWERI*/ -+#define RSTV0910_P1_POWERI 0xf40a -+#define FSTV0910_P1_POWER_I 0xf40a00ff -+ -+/*P1_POWERQ*/ -+#define RSTV0910_P1_POWERQ 0xf40b -+#define FSTV0910_P1_POWER_Q 0xf40b00ff -+ -+/*P1_AGC1AMM*/ -+#define RSTV0910_P1_AGC1AMM 0xf40c -+#define FSTV0910_P1_AMM_VALUE 0xf40c00ff -+ -+/*P1_AGC1QUAD*/ -+#define RSTV0910_P1_AGC1QUAD 0xf40d -+#define FSTV0910_P1_QUAD_VALUE 0xf40d01ff -+ -+/*P1_AGCIQIN1*/ -+#define RSTV0910_P1_AGCIQIN1 0xf40e -+#define FSTV0910_P1_AGCIQ_VALUE1 0xf40e00ff -+ -+/*P1_AGCIQIN0*/ -+#define RSTV0910_P1_AGCIQIN0 0xf40f -+#define FSTV0910_P1_AGCIQ_VALUE0 0xf40f00ff -+ -+/*P1_DEMOD*/ -+#define RSTV0910_P1_DEMOD 0xf410 -+#define FSTV0910_P1_MANUALS2_ROLLOFF 0xf4100080 -+#define FSTV0910_P1_SPECINV_CONTROL 0xf4100030 -+#define FSTV0910_P1_MANUALSX_ROLLOFF 0xf4100004 -+#define FSTV0910_P1_ROLLOFF_CONTROL 0xf4100003 -+ -+/*P1_DMDMODCOD*/ -+#define RSTV0910_P1_DMDMODCOD 0xf411 -+#define FSTV0910_P1_MANUAL_MODCOD 0xf4110080 -+#define FSTV0910_P1_DEMOD_MODCOD 0xf411007c -+#define FSTV0910_P1_DEMOD_TYPE 0xf4110003 -+ -+/*P1_DSTATUS*/ -+#define RSTV0910_P1_DSTATUS 0xf412 -+#define FSTV0910_P1_CAR_LOCK 0xf4120080 -+#define FSTV0910_P1_TMGLOCK_QUALITY 0xf4120060 -+#define FSTV0910_P1_SDVBS1_ENABLE 0xf4120010 -+#define FSTV0910_P1_LOCK_DEFINITIF 0xf4120008 -+#define FSTV0910_P1_TIMING_IS_LOCKED 0xf4120004 -+#define FSTV0910_P1_DEMOD_SYSCFG 0xf4120002 -+#define FSTV0910_P1_OVADC_DETECT 0xf4120001 -+ -+/*P1_DSTATUS2*/ -+#define RSTV0910_P1_DSTATUS2 0xf413 -+#define FSTV0910_P1_DEMOD_DELOCK 0xf4130080 -+#define FSTV0910_P1_DEMOD_TIMEOUT 0xf4130040 -+#define FSTV0910_P1_MODCODRQ_SYNCTAG 0xf4130020 -+#define FSTV0910_P1_POLYPH_SATEVENT 0xf4130010 -+#define FSTV0910_P1_AGC1_NOSIGNALACK 0xf4130008 -+#define FSTV0910_P1_AGC2_OVERFLOW 0xf4130004 -+#define FSTV0910_P1_CFR_OVERFLOW 0xf4130002 -+#define FSTV0910_P1_GAMMA_OVERUNDER 0xf4130001 -+ -+/*P1_DMDCFGMD*/ -+#define RSTV0910_P1_DMDCFGMD 0xf414 -+#define FSTV0910_P1_DVBS2_ENABLE 0xf4140080 -+#define FSTV0910_P1_DVBS1_ENABLE 0xf4140040 -+#define FSTV0910_P1_SCAN_ENABLE 0xf4140010 -+#define FSTV0910_P1_CFR_AUTOSCAN 0xf4140008 -+#define FSTV0910_P1_NOFORCE_RELOCK 0xf4140004 -+#define FSTV0910_P1_TUN_RNG 0xf4140003 -+ -+/*P1_DMDCFG2*/ -+#define RSTV0910_P1_DMDCFG2 0xf415 -+#define FSTV0910_P1_AGC1_WAITLOCK 0xf4150080 -+#define FSTV0910_P1_S1S2_SEQUENTIAL 0xf4150040 -+#define FSTV0910_P1_BLINDPEA_MODE 0xf4150020 -+#define FSTV0910_P1_INFINITE_RELOCK 0xf4150010 -+#define FSTV0910_P1_BWOFFSET_COLDWARM 0xf4150008 -+#define FSTV0910_P1_TMGLOCK_NSCANSTOP 0xf4150004 -+#define FSTV0910_P1_COARSE_LK3MODE 0xf4150002 -+#define FSTV0910_P1_COARSE_LK2MODE 0xf4150001 -+ -+/*P1_DMDISTATE*/ -+#define RSTV0910_P1_DMDISTATE 0xf416 -+#define FSTV0910_P1_I2C_NORESETDMODE 0xf4160080 -+#define FSTV0910_P1_FORCE_ETAPED 0xf4160040 -+#define FSTV0910_P1_SDMDRST_DIRCLK 0xf4160020 -+#define FSTV0910_P1_I2C_DEMOD_MODE 0xf416001f -+ -+/*P1_DMDT0M*/ -+#define RSTV0910_P1_DMDT0M 0xf417 -+#define FSTV0910_P1_DMDT0_MIN 0xf41700ff -+ -+/*P1_DMDSTATE*/ -+#define RSTV0910_P1_DMDSTATE 0xf41b -+#define FSTV0910_P1_DEMOD_LOCKED 0xf41b0080 -+#define FSTV0910_P1_HEADER_MODE 0xf41b0060 -+#define FSTV0910_P1_DEMOD_MODE 0xf41b001f -+ -+/*P1_DMDFLYW*/ -+#define RSTV0910_P1_DMDFLYW 0xf41c -+#define FSTV0910_P1_I2C_IRQVAL 0xf41c00f0 -+#define FSTV0910_P1_FLYWHEEL_CPT 0xf41c000f -+ -+/*P1_DSTATUS3*/ -+#define RSTV0910_P1_DSTATUS3 0xf41d -+#define FSTV0910_P1_CFR_ZIGZAG 0xf41d0080 -+#define FSTV0910_P1_DEMOD_CFGMODE 0xf41d0060 -+#define FSTV0910_P1_GAMMA_LOWBAUDRATE 0xf41d0010 -+#define FSTV0910_P1_RELOCK_MODE 0xf41d0008 -+#define FSTV0910_P1_DEMOD_FAIL 0xf41d0004 -+#define FSTV0910_P1_ETAPE1A_DVBXMEM 0xf41d0003 -+ -+/*P1_DMDCFG3*/ -+#define RSTV0910_P1_DMDCFG3 0xf41e -+#define FSTV0910_P1_DVBS1_TMGWAIT 0xf41e0080 -+#define FSTV0910_P1_NO_BWCENTERING 0xf41e0040 -+#define FSTV0910_P1_INV_SEQSRCH 0xf41e0020 -+#define FSTV0910_P1_DIS_SFRUPLOW_TRK 0xf41e0010 -+#define FSTV0910_P1_NOSTOP_FIFOFULL 0xf41e0008 -+#define FSTV0910_P1_LOCKTIME_MODE 0xf41e0007 -+ -+/*P1_DMDCFG4*/ -+#define RSTV0910_P1_DMDCFG4 0xf41f -+#define FSTV0910_P1_DIS_VITLOCK 0xf41f0080 -+#define FSTV0910_P1_S1S2TOUT_FAST 0xf41f0040 -+#define FSTV0910_P1_DEMOD_FASTLOCK 0xf41f0020 -+#define FSTV0910_P1_S1HIER_ENABLE 0xf41f0010 -+#define FSTV0910_P1_TUNER_NRELAUNCH 0xf41f0008 -+#define FSTV0910_P1_DIS_CLKENABLE 0xf41f0004 -+#define FSTV0910_P1_DIS_HDRDIVLOCK 0xf41f0002 -+#define FSTV0910_P1_NO_TNRWBINIT 0xf41f0001 -+ -+/*P1_CORRELMANT*/ -+#define RSTV0910_P1_CORRELMANT 0xf420 -+#define FSTV0910_P1_CORREL_MANT 0xf42000ff -+ -+/*P1_CORRELABS*/ -+#define RSTV0910_P1_CORRELABS 0xf421 -+#define FSTV0910_P1_CORREL_ABS 0xf42100ff -+ -+/*P1_CORRELEXP*/ -+#define RSTV0910_P1_CORRELEXP 0xf422 -+#define FSTV0910_P1_CORREL_ABSEXP 0xf42200f0 -+#define FSTV0910_P1_CORREL_EXP 0xf422000f -+ -+/*P1_PLHMODCOD*/ -+#define RSTV0910_P1_PLHMODCOD 0xf424 -+#define FSTV0910_P1_SPECINV_DEMOD 0xf4240080 -+#define FSTV0910_P1_PLH_MODCOD 0xf424007c -+#define FSTV0910_P1_PLH_TYPE 0xf4240003 -+ -+/*P1_DMDREG*/ -+#define RSTV0910_P1_DMDREG 0xf425 -+#define FSTV0910_P1_EXTPSK_MODE 0xf4250080 -+#define FSTV0910_P1_HIER_SHORTFRAME 0xf4250002 -+#define FSTV0910_P1_DECIM_PLFRAMES 0xf4250001 -+ -+/*P1_AGC2O*/ -+#define RSTV0910_P1_AGC2O 0xf42c -+#define FSTV0910_P1_CSTENV_MODE 0xf42c00c0 -+#define FSTV0910_P1_AGC2_LKSQRT 0xf42c0020 -+#define FSTV0910_P1_AGC2_LKMODE 0xf42c0010 -+#define FSTV0910_P1_AGC2_LKEQUA 0xf42c0008 -+#define FSTV0910_P1_AGC2_COEF 0xf42c0007 -+ -+/*P1_AGC2REF*/ -+#define RSTV0910_P1_AGC2REF 0xf42d -+#define FSTV0910_P1_AGC2_REF 0xf42d00ff -+ -+/*P1_AGC1ADJ*/ -+#define RSTV0910_P1_AGC1ADJ 0xf42e -+#define FSTV0910_P1_AGC1ADJ_MANUAL 0xf42e0080 -+#define FSTV0910_P1_AGC1_ADJUSTED 0xf42e007f -+ -+/*P1_AGC2I1*/ -+#define RSTV0910_P1_AGC2I1 0xf436 -+#define FSTV0910_P1_AGC2_INTEGRATOR1 0xf43600ff -+ -+/*P1_AGC2I0*/ -+#define RSTV0910_P1_AGC2I0 0xf437 -+#define FSTV0910_P1_AGC2_INTEGRATOR0 0xf43700ff -+ -+/*P1_CARCFG*/ -+#define RSTV0910_P1_CARCFG 0xf438 -+#define FSTV0910_P1_CFRUPLOW_AUTO 0xf4380080 -+#define FSTV0910_P1_CFRUPLOW_TEST 0xf4380040 -+#define FSTV0910_P1_WIDE_FREQDET 0xf4380020 -+#define FSTV0910_P1_CARHDR_NODIV8 0xf4380010 -+#define FSTV0910_P1_I2C_ROTA 0xf4380008 -+#define FSTV0910_P1_ROTAON 0xf4380004 -+#define FSTV0910_P1_PH_DET_ALGO 0xf4380003 -+ -+/*P1_ACLC*/ -+#define RSTV0910_P1_ACLC 0xf439 -+#define FSTV0910_P1_CARS1_ANOSAUTO 0xf4390040 -+#define FSTV0910_P1_CAR_ALPHA_MANT 0xf4390030 -+#define FSTV0910_P1_CAR_ALPHA_EXP 0xf439000f -+ -+/*P1_BCLC*/ -+#define RSTV0910_P1_BCLC 0xf43a -+#define FSTV0910_P1_CARS1_BNOSAUTO 0xf43a0040 -+#define FSTV0910_P1_CAR_BETA_MANT 0xf43a0030 -+#define FSTV0910_P1_CAR_BETA_EXP 0xf43a000f -+ -+/*P1_CARFREQ*/ -+#define RSTV0910_P1_CARFREQ 0xf43d -+#define FSTV0910_P1_KC_COARSE_EXP 0xf43d00f0 -+#define FSTV0910_P1_BETA_FREQ 0xf43d000f -+ -+/*P1_CARHDR*/ -+#define RSTV0910_P1_CARHDR 0xf43e -+#define FSTV0910_P1_K_FREQ_HDR 0xf43e00ff -+ -+/*P1_LDT*/ -+#define RSTV0910_P1_LDT 0xf43f -+#define FSTV0910_P1_CARLOCK_THRES 0xf43f01ff -+ -+/*P1_LDT2*/ -+#define RSTV0910_P1_LDT2 0xf440 -+#define FSTV0910_P1_CARLOCK_THRES2 0xf44001ff -+ -+/*P1_CFRICFG*/ -+#define RSTV0910_P1_CFRICFG 0xf441 -+#define FSTV0910_P1_CFRINIT_UNVALRNG 0xf4410080 -+#define FSTV0910_P1_CFRINIT_LUNVALCPT 0xf4410040 -+#define FSTV0910_P1_CFRINIT_ABORTDBL 0xf4410020 -+#define FSTV0910_P1_CFRINIT_ABORTPRED 0xf4410010 -+#define FSTV0910_P1_CFRINIT_UNVALSKIP 0xf4410008 -+#define FSTV0910_P1_CFRINIT_CSTINC 0xf4410004 -+#define FSTV0910_P1_CFRIROLL_GARDER 0xf4410002 -+#define FSTV0910_P1_NEG_CFRSTEP 0xf4410001 -+ -+/*P1_CFRUP1*/ -+#define RSTV0910_P1_CFRUP1 0xf442 -+#define FSTV0910_P1_CFR_UP1 0xf44201ff -+ -+/*P1_CFRUP0*/ -+#define RSTV0910_P1_CFRUP0 0xf443 -+#define FSTV0910_P1_CFR_UP0 0xf44300ff -+ -+/*P1_CFRIBASE1*/ -+#define RSTV0910_P1_CFRIBASE1 0xf444 -+#define FSTV0910_P1_CFRINIT_BASE1 0xf44400ff -+ -+/*P1_CFRIBASE0*/ -+#define RSTV0910_P1_CFRIBASE0 0xf445 -+#define FSTV0910_P1_CFRINIT_BASE0 0xf44500ff -+ -+/*P1_CFRLOW1*/ -+#define RSTV0910_P1_CFRLOW1 0xf446 -+#define FSTV0910_P1_CFR_LOW1 0xf44601ff -+ -+/*P1_CFRLOW0*/ -+#define RSTV0910_P1_CFRLOW0 0xf447 -+#define FSTV0910_P1_CFR_LOW0 0xf44700ff -+ -+/*P1_CFRINIT1*/ -+#define RSTV0910_P1_CFRINIT1 0xf448 -+#define FSTV0910_P1_CFR_INIT1 0xf44801ff -+ -+/*P1_CFRINIT0*/ -+#define RSTV0910_P1_CFRINIT0 0xf449 -+#define FSTV0910_P1_CFR_INIT0 0xf44900ff -+ -+/*P1_CFRINC1*/ -+#define RSTV0910_P1_CFRINC1 0xf44a -+#define FSTV0910_P1_MANUAL_CFRINC 0xf44a0080 -+#define FSTV0910_P1_CFR_INC1 0xf44a003f -+ -+/*P1_CFRINC0*/ -+#define RSTV0910_P1_CFRINC0 0xf44b -+#define FSTV0910_P1_CFR_INC0 0xf44b00ff -+ -+/*P1_CFR2*/ -+#define RSTV0910_P1_CFR2 0xf44c -+#define FSTV0910_P1_CAR_FREQ2 0xf44c01ff -+ -+/*P1_CFR1*/ -+#define RSTV0910_P1_CFR1 0xf44d -+#define FSTV0910_P1_CAR_FREQ1 0xf44d00ff -+ -+/*P1_CFR0*/ -+#define RSTV0910_P1_CFR0 0xf44e -+#define FSTV0910_P1_CAR_FREQ0 0xf44e00ff -+ -+/*P1_LDI*/ -+#define RSTV0910_P1_LDI 0xf44f -+#define FSTV0910_P1_LOCK_DET_INTEGR 0xf44f01ff -+ -+/*P1_TMGCFG*/ -+#define RSTV0910_P1_TMGCFG 0xf450 -+#define FSTV0910_P1_TMGLOCK_BETA 0xf45000c0 -+#define FSTV0910_P1_DO_TIMING_CORR 0xf4500010 -+#define FSTV0910_P1_MANUAL_SCAN 0xf450000c -+#define FSTV0910_P1_TMG_MINFREQ 0xf4500003 -+ -+/*P1_RTC*/ -+#define RSTV0910_P1_RTC 0xf451 -+#define FSTV0910_P1_TMGALPHA_EXP 0xf45100f0 -+#define FSTV0910_P1_TMGBETA_EXP 0xf451000f -+ -+/*P1_RTCS2*/ -+#define RSTV0910_P1_RTCS2 0xf452 -+#define FSTV0910_P1_TMGALPHAS2_EXP 0xf45200f0 -+#define FSTV0910_P1_TMGBETAS2_EXP 0xf452000f -+ -+/*P1_TMGTHRISE*/ -+#define RSTV0910_P1_TMGTHRISE 0xf453 -+#define FSTV0910_P1_TMGLOCK_THRISE 0xf45300ff -+ -+/*P1_TMGTHFALL*/ -+#define RSTV0910_P1_TMGTHFALL 0xf454 -+#define FSTV0910_P1_TMGLOCK_THFALL 0xf45400ff -+ -+/*P1_SFRUPRATIO*/ -+#define RSTV0910_P1_SFRUPRATIO 0xf455 -+#define FSTV0910_P1_SFR_UPRATIO 0xf45500ff -+ -+/*P1_SFRLOWRATIO*/ -+#define RSTV0910_P1_SFRLOWRATIO 0xf456 -+#define FSTV0910_P1_SFR_LOWRATIO 0xf45600ff -+ -+/*P1_KTTMG*/ -+#define RSTV0910_P1_KTTMG 0xf457 -+#define FSTV0910_P1_KT_TMG_EXP 0xf45700f0 -+ -+/*P1_KREFTMG*/ -+#define RSTV0910_P1_KREFTMG 0xf458 -+#define FSTV0910_P1_KREF_TMG 0xf45800ff -+ -+/*P1_SFRSTEP*/ -+#define RSTV0910_P1_SFRSTEP 0xf459 -+#define FSTV0910_P1_SFR_SCANSTEP 0xf45900f0 -+#define FSTV0910_P1_SFR_CENTERSTEP 0xf459000f -+ -+/*P1_TMGCFG2*/ -+#define RSTV0910_P1_TMGCFG2 0xf45a -+#define FSTV0910_P1_KREFTMG2_DECMODE 0xf45a00c0 -+#define FSTV0910_P1_DIS_AUTOSAMP 0xf45a0008 -+#define FSTV0910_P1_SCANINIT_QUART 0xf45a0004 -+#define FSTV0910_P1_NOTMG_DVBS1DERAT 0xf45a0002 -+#define FSTV0910_P1_SFRRATIO_FINE 0xf45a0001 -+ -+/*P1_KREFTMG2*/ -+#define RSTV0910_P1_KREFTMG2 0xf45b -+#define FSTV0910_P1_KREF_TMG2 0xf45b00ff -+ -+/*P1_TMGCFG3*/ -+#define RSTV0910_P1_TMGCFG3 0xf45d -+#define FSTV0910_P1_CFRINC_MODE 0xf45d0070 -+#define FSTV0910_P1_CONT_TMGCENTER 0xf45d0008 -+#define FSTV0910_P1_AUTO_GUP 0xf45d0004 -+#define FSTV0910_P1_AUTO_GLOW 0xf45d0002 -+#define FSTV0910_P1_SFRVAL_MINMODE 0xf45d0001 -+ -+/*P1_SFRINIT1*/ -+#define RSTV0910_P1_SFRINIT1 0xf45e -+#define FSTV0910_P1_SFR_INIT1 0xf45e00ff -+ -+/*P1_SFRINIT0*/ -+#define RSTV0910_P1_SFRINIT0 0xf45f -+#define FSTV0910_P1_SFR_INIT0 0xf45f00ff -+ -+/*P1_SFRUP1*/ -+#define RSTV0910_P1_SFRUP1 0xf460 -+#define FSTV0910_P1_SYMB_FREQ_UP1 0xf46000ff -+ -+/*P1_SFRUP0*/ -+#define RSTV0910_P1_SFRUP0 0xf461 -+#define FSTV0910_P1_SYMB_FREQ_UP0 0xf46100ff -+ -+/*P1_SFRLOW1*/ -+#define RSTV0910_P1_SFRLOW1 0xf462 -+#define FSTV0910_P1_SYMB_FREQ_LOW1 0xf46200ff -+ -+/*P1_SFRLOW0*/ -+#define RSTV0910_P1_SFRLOW0 0xf463 -+#define FSTV0910_P1_SYMB_FREQ_LOW0 0xf46300ff -+ -+/*P1_SFR3*/ -+#define RSTV0910_P1_SFR3 0xf464 -+#define FSTV0910_P1_SYMB_FREQ3 0xf46400ff -+ -+/*P1_SFR2*/ -+#define RSTV0910_P1_SFR2 0xf465 -+#define FSTV0910_P1_SYMB_FREQ2 0xf46500ff -+ -+/*P1_SFR1*/ -+#define RSTV0910_P1_SFR1 0xf466 -+#define FSTV0910_P1_SYMB_FREQ1 0xf46600ff -+ -+/*P1_SFR0*/ -+#define RSTV0910_P1_SFR0 0xf467 -+#define FSTV0910_P1_SYMB_FREQ0 0xf46700ff -+ -+/*P1_TMGREG2*/ -+#define RSTV0910_P1_TMGREG2 0xf468 -+#define FSTV0910_P1_TMGREG2 0xf46800ff -+ -+/*P1_TMGREG1*/ -+#define RSTV0910_P1_TMGREG1 0xf469 -+#define FSTV0910_P1_TMGREG1 0xf46900ff -+ -+/*P1_TMGREG0*/ -+#define RSTV0910_P1_TMGREG0 0xf46a -+#define FSTV0910_P1_TMGREG0 0xf46a00ff -+ -+/*P1_TMGLOCK1*/ -+#define RSTV0910_P1_TMGLOCK1 0xf46b -+#define FSTV0910_P1_TMGLOCK_LEVEL1 0xf46b01ff -+ -+/*P1_TMGLOCK0*/ -+#define RSTV0910_P1_TMGLOCK0 0xf46c -+#define FSTV0910_P1_TMGLOCK_LEVEL0 0xf46c00ff -+ -+/*P1_TMGOBS*/ -+#define RSTV0910_P1_TMGOBS 0xf46d -+#define FSTV0910_P1_ROLLOFF_STATUS 0xf46d00c0 -+#define FSTV0910_P1_SCAN_SIGN 0xf46d0030 -+#define FSTV0910_P1_TMG_SCANNING 0xf46d0008 -+#define FSTV0910_P1_CHCENTERING_MODE 0xf46d0004 -+#define FSTV0910_P1_TMG_SCANFAIL 0xf46d0002 -+ -+/*P1_EQUALCFG*/ -+#define RSTV0910_P1_EQUALCFG 0xf46f -+#define FSTV0910_P1_NOTMG_NEGALWAIT 0xf46f0080 -+#define FSTV0910_P1_EQUAL_ON 0xf46f0040 -+#define FSTV0910_P1_SEL_EQUALCOR 0xf46f0038 -+#define FSTV0910_P1_MU_EQUALDFE 0xf46f0007 -+ -+/*P1_EQUAI1*/ -+#define RSTV0910_P1_EQUAI1 0xf470 -+#define FSTV0910_P1_EQUA_ACCI1 0xf47001ff -+ -+/*P1_EQUAQ1*/ -+#define RSTV0910_P1_EQUAQ1 0xf471 -+#define FSTV0910_P1_EQUA_ACCQ1 0xf47101ff -+ -+/*P1_EQUAI2*/ -+#define RSTV0910_P1_EQUAI2 0xf472 -+#define FSTV0910_P1_EQUA_ACCI2 0xf47201ff -+ -+/*P1_EQUAQ2*/ -+#define RSTV0910_P1_EQUAQ2 0xf473 -+#define FSTV0910_P1_EQUA_ACCQ2 0xf47301ff -+ -+/*P1_EQUAI3*/ -+#define RSTV0910_P1_EQUAI3 0xf474 -+#define FSTV0910_P1_EQUA_ACCI3 0xf47401ff -+ -+/*P1_EQUAQ3*/ -+#define RSTV0910_P1_EQUAQ3 0xf475 -+#define FSTV0910_P1_EQUA_ACCQ3 0xf47501ff -+ -+/*P1_EQUAI4*/ -+#define RSTV0910_P1_EQUAI4 0xf476 -+#define FSTV0910_P1_EQUA_ACCI4 0xf47601ff -+ -+/*P1_EQUAQ4*/ -+#define RSTV0910_P1_EQUAQ4 0xf477 -+#define FSTV0910_P1_EQUA_ACCQ4 0xf47701ff -+ -+/*P1_EQUAI5*/ -+#define RSTV0910_P1_EQUAI5 0xf478 -+#define FSTV0910_P1_EQUA_ACCI5 0xf47801ff -+ -+/*P1_EQUAQ5*/ -+#define RSTV0910_P1_EQUAQ5 0xf479 -+#define FSTV0910_P1_EQUA_ACCQ5 0xf47901ff -+ -+/*P1_EQUAI6*/ -+#define RSTV0910_P1_EQUAI6 0xf47a -+#define FSTV0910_P1_EQUA_ACCI6 0xf47a01ff -+ -+/*P1_EQUAQ6*/ -+#define RSTV0910_P1_EQUAQ6 0xf47b -+#define FSTV0910_P1_EQUA_ACCQ6 0xf47b01ff -+ -+/*P1_EQUAI7*/ -+#define RSTV0910_P1_EQUAI7 0xf47c -+#define FSTV0910_P1_EQUA_ACCI7 0xf47c01ff -+ -+/*P1_EQUAQ7*/ -+#define RSTV0910_P1_EQUAQ7 0xf47d -+#define FSTV0910_P1_EQUA_ACCQ7 0xf47d01ff -+ -+/*P1_EQUAI8*/ -+#define RSTV0910_P1_EQUAI8 0xf47e -+#define FSTV0910_P1_EQUA_ACCI8 0xf47e01ff -+ -+/*P1_EQUAQ8*/ -+#define RSTV0910_P1_EQUAQ8 0xf47f -+#define FSTV0910_P1_EQUA_ACCQ8 0xf47f01ff -+ -+/*P1_NNOSDATAT1*/ -+#define RSTV0910_P1_NNOSDATAT1 0xf480 -+#define FSTV0910_P1_NOSDATAT_NORMED1 0xf48000ff -+ -+/*P1_NNOSDATAT0*/ -+#define RSTV0910_P1_NNOSDATAT0 0xf481 -+#define FSTV0910_P1_NOSDATAT_NORMED0 0xf48100ff -+ -+/*P1_NNOSDATA1*/ -+#define RSTV0910_P1_NNOSDATA1 0xf482 -+#define FSTV0910_P1_NOSDATA_NORMED1 0xf48200ff -+ -+/*P1_NNOSDATA0*/ -+#define RSTV0910_P1_NNOSDATA0 0xf483 -+#define FSTV0910_P1_NOSDATA_NORMED0 0xf48300ff -+ -+/*P1_NNOSPLHT1*/ -+#define RSTV0910_P1_NNOSPLHT1 0xf484 -+#define FSTV0910_P1_NOSPLHT_NORMED1 0xf48400ff -+ -+/*P1_NNOSPLHT0*/ -+#define RSTV0910_P1_NNOSPLHT0 0xf485 -+#define FSTV0910_P1_NOSPLHT_NORMED0 0xf48500ff -+ -+/*P1_NNOSPLH1*/ -+#define RSTV0910_P1_NNOSPLH1 0xf486 -+#define FSTV0910_P1_NOSPLH_NORMED1 0xf48600ff -+ -+/*P1_NNOSPLH0*/ -+#define RSTV0910_P1_NNOSPLH0 0xf487 -+#define FSTV0910_P1_NOSPLH_NORMED0 0xf48700ff -+ -+/*P1_NOSDATAT1*/ -+#define RSTV0910_P1_NOSDATAT1 0xf488 -+#define FSTV0910_P1_NOSDATAT_UNNORMED1 0xf48800ff -+ -+/*P1_NOSDATAT0*/ -+#define RSTV0910_P1_NOSDATAT0 0xf489 -+#define FSTV0910_P1_NOSDATAT_UNNORMED0 0xf48900ff -+ -+/*P1_NNOSFRAME1*/ -+#define RSTV0910_P1_NNOSFRAME1 0xf48a -+#define FSTV0910_P1_NOSFRAME_NORMED1 0xf48a00ff -+ -+/*P1_NNOSFRAME0*/ -+#define RSTV0910_P1_NNOSFRAME0 0xf48b -+#define FSTV0910_P1_NOSFRAME_NORMED0 0xf48b00ff -+ -+/*P1_NNOSRAD1*/ -+#define RSTV0910_P1_NNOSRAD1 0xf48c -+#define FSTV0910_P1_NOSRADIAL_NORMED1 0xf48c00ff -+ -+/*P1_NNOSRAD0*/ -+#define RSTV0910_P1_NNOSRAD0 0xf48d -+#define FSTV0910_P1_NOSRADIAL_NORMED0 0xf48d00ff -+ -+/*P1_NOSCFGF1*/ -+#define RSTV0910_P1_NOSCFGF1 0xf48e -+#define FSTV0910_P1_LOWNOISE_MESURE 0xf48e0080 -+#define FSTV0910_P1_NOS_DELFRAME 0xf48e0040 -+#define FSTV0910_P1_NOSDATA_MODE 0xf48e0030 -+#define FSTV0910_P1_FRAMESEL_TYPESEL 0xf48e000c -+#define FSTV0910_P1_FRAMESEL_TYPE 0xf48e0003 -+ -+/*P1_CAR2CFG*/ -+#define RSTV0910_P1_CAR2CFG 0xf490 -+#define FSTV0910_P1_DESCRAMB_OFF 0xf4900080 -+#define FSTV0910_P1_EN_PHNOSRAM 0xf4900020 -+#define FSTV0910_P1_STOP_CFR2UPDATE 0xf4900010 -+#define FSTV0910_P1_STOP_NCO2UPDATE 0xf4900008 -+#define FSTV0910_P1_ROTA2ON 0xf4900004 -+#define FSTV0910_P1_PH_DET_ALGO2 0xf4900003 -+ -+/*P1_CFR2CFR1*/ -+#define RSTV0910_P1_CFR2CFR1 0xf491 -+#define FSTV0910_P1_CFR2_S2CONTROL 0xf49100c0 -+#define FSTV0910_P1_EN_S2CAR2CENTER 0xf4910020 -+#define FSTV0910_P1_BCHERRCFR2_MODE 0xf4910018 -+#define FSTV0910_P1_CFR2TOCFR1_BETA 0xf4910007 -+ -+/*P1_CAR3CFG*/ -+#define RSTV0910_P1_CAR3CFG 0xf492 -+#define FSTV0910_P1_CARRIER23_MODE 0xf49200c0 -+#define FSTV0910_P1_CAR3INTERM_DVBS1 0xf4920020 -+#define FSTV0910_P1_ABAMPLIF_MODE 0xf4920018 -+#define FSTV0910_P1_CARRIER3_ALPHA3DL 0xf4920007 -+ -+/*P1_CFR22*/ -+#define RSTV0910_P1_CFR22 0xf493 -+#define FSTV0910_P1_CAR2_FREQ2 0xf49301ff -+ -+/*P1_CFR21*/ -+#define RSTV0910_P1_CFR21 0xf494 -+#define FSTV0910_P1_CAR2_FREQ1 0xf49400ff -+ -+/*P1_CFR20*/ -+#define RSTV0910_P1_CFR20 0xf495 -+#define FSTV0910_P1_CAR2_FREQ0 0xf49500ff -+ -+/*P1_ACLC2S2Q*/ -+#define RSTV0910_P1_ACLC2S2Q 0xf497 -+#define FSTV0910_P1_ENAB_SPSKSYMB 0xf4970080 -+#define FSTV0910_P1_CAR2S2_QANOSAUTO 0xf4970040 -+#define FSTV0910_P1_CAR2S2_Q_ALPH_M 0xf4970030 -+#define FSTV0910_P1_CAR2S2_Q_ALPH_E 0xf497000f -+ -+/*P1_ACLC2S28*/ -+#define RSTV0910_P1_ACLC2S28 0xf498 -+#define FSTV0910_P1_OLDI3Q_MODE 0xf4980080 -+#define FSTV0910_P1_CAR2S2_8ANOSAUTO 0xf4980040 -+#define FSTV0910_P1_CAR2S2_8_ALPH_M 0xf4980030 -+#define FSTV0910_P1_CAR2S2_8_ALPH_E 0xf498000f -+ -+/*P1_ACLC2S216A*/ -+#define RSTV0910_P1_ACLC2S216A 0xf499 -+#define FSTV0910_P1_CAR2S2_16ANOSAUTO 0xf4990040 -+#define FSTV0910_P1_CAR2S2_16A_ALPH_M 0xf4990030 -+#define FSTV0910_P1_CAR2S2_16A_ALPH_E 0xf499000f -+ -+/*P1_ACLC2S232A*/ -+#define RSTV0910_P1_ACLC2S232A 0xf49a -+#define FSTV0910_P1_CAR2S2_32ANOSUATO 0xf49a0040 -+#define FSTV0910_P1_CAR2S2_32A_ALPH_M 0xf49a0030 -+#define FSTV0910_P1_CAR2S2_32A_ALPH_E 0xf49a000f -+ -+/*P1_BCLC2S2Q*/ -+#define RSTV0910_P1_BCLC2S2Q 0xf49c -+#define FSTV0910_P1_DVBS2S2Q_NIP 0xf49c0080 -+#define FSTV0910_P1_CAR2S2_QBNOSAUTO 0xf49c0040 -+#define FSTV0910_P1_CAR2S2_Q_BETA_M 0xf49c0030 -+#define FSTV0910_P1_CAR2S2_Q_BETA_E 0xf49c000f -+ -+/*P1_BCLC2S28*/ -+#define RSTV0910_P1_BCLC2S28 0xf49d -+#define FSTV0910_P1_DVBS2S28_NIP 0xf49d0080 -+#define FSTV0910_P1_CAR2S2_8BNOSAUTO 0xf49d0040 -+#define FSTV0910_P1_CAR2S2_8_BETA_M 0xf49d0030 -+#define FSTV0910_P1_CAR2S2_8_BETA_E 0xf49d000f -+ -+/*P1_PLROOT2*/ -+#define RSTV0910_P1_PLROOT2 0xf4ac -+#define FSTV0910_P1_PLHAUTO_DISPLH 0xf4ac0040 -+#define FSTV0910_P1_PLHAUTO_FASTMODE 0xf4ac0020 -+#define FSTV0910_P1_PLHAUTO_ENABLE 0xf4ac0010 -+#define FSTV0910_P1_PLSCRAMB_MODE 0xf4ac000c -+#define FSTV0910_P1_PLSCRAMB_ROOT2 0xf4ac0003 -+ -+/*P1_PLROOT1*/ -+#define RSTV0910_P1_PLROOT1 0xf4ad -+#define FSTV0910_P1_PLSCRAMB_ROOT1 0xf4ad00ff -+ -+/*P1_PLROOT0*/ -+#define RSTV0910_P1_PLROOT0 0xf4ae -+#define FSTV0910_P1_PLSCRAMB_ROOT0 0xf4ae00ff -+ -+/*P1_MODCODLST7*/ -+#define RSTV0910_P1_MODCODLST7 0xf4b7 -+#define FSTV0910_P1_MODCOD_NNOSFILTER 0xf4b70080 -+#define FSTV0910_P1_MODCODLST_NOSTYPE 0xf4b70040 -+#define FSTV0910_P1_DIS_8PSK_9_10 0xf4b70030 -+#define FSTV0910_P1_DIS_8P_8_9 0xf4b7000f -+ -+/*P1_MODCODLST8*/ -+#define RSTV0910_P1_MODCODLST8 0xf4b8 -+#define FSTV0910_P1_DIS_8P_5_6 0xf4b800f0 -+#define FSTV0910_P1_DIS_8P_3_4 0xf4b8000f -+ -+/*P1_MODCODLST9*/ -+#define RSTV0910_P1_MODCODLST9 0xf4b9 -+#define FSTV0910_P1_DIS_8P_2_3 0xf4b900f0 -+#define FSTV0910_P1_DIS_8P_3_5 0xf4b9000f -+ -+/*P1_MODCODLSTA*/ -+#define RSTV0910_P1_MODCODLSTA 0xf4ba -+#define FSTV0910_P1_NOSFILTER_LIMITE 0xf4ba0080 -+#define FSTV0910_P1_NOSFILTER_MODE 0xf4ba0040 -+#define FSTV0910_P1_DIS_QPSK_9_10 0xf4ba0030 -+#define FSTV0910_P1_DIS_QP_8_9 0xf4ba000f -+ -+/*P1_MODCODLSTB*/ -+#define RSTV0910_P1_MODCODLSTB 0xf4bb -+#define FSTV0910_P1_DIS_QP_5_6 0xf4bb00f0 -+#define FSTV0910_P1_DIS_QP_4_5 0xf4bb000f -+ -+/*P1_MODCODLSTC*/ -+#define RSTV0910_P1_MODCODLSTC 0xf4bc -+#define FSTV0910_P1_DIS_QP_3_4 0xf4bc00f0 -+#define FSTV0910_P1_DIS_QP_2_3 0xf4bc000f -+ -+/*P1_MODCODLSTD*/ -+#define RSTV0910_P1_MODCODLSTD 0xf4bd -+#define FSTV0910_P1_DIS_QPSK_3_5 0xf4bd00f0 -+#define FSTV0910_P1_DIS_QPSK_1_2 0xf4bd000f -+ -+/*P1_GAUSSR0*/ -+#define RSTV0910_P1_GAUSSR0 0xf4c0 -+#define FSTV0910_P1_EN_CCIMODE 0xf4c00080 -+#define FSTV0910_P1_R0_GAUSSIEN 0xf4c0007f -+ -+/*P1_CCIR0*/ -+#define RSTV0910_P1_CCIR0 0xf4c1 -+#define FSTV0910_P1_CCIDETECT_PLHONLY 0xf4c10080 -+#define FSTV0910_P1_R0_CCI 0xf4c1007f -+ -+/*P1_CCIQUANT*/ -+#define RSTV0910_P1_CCIQUANT 0xf4c2 -+#define FSTV0910_P1_CCI_BETA 0xf4c200e0 -+#define FSTV0910_P1_CCI_QUANT 0xf4c2001f -+ -+/*P1_CCITHRES*/ -+#define RSTV0910_P1_CCITHRES 0xf4c3 -+#define FSTV0910_P1_CCI_THRESHOLD 0xf4c300ff -+ -+/*P1_CCIACC*/ -+#define RSTV0910_P1_CCIACC 0xf4c4 -+#define FSTV0910_P1_CCI_VALUE 0xf4c400ff -+ -+/*P1_DSTATUS4*/ -+#define RSTV0910_P1_DSTATUS4 0xf4c5 -+#define FSTV0910_P1_RAINFADE_DETECT 0xf4c50080 -+#define FSTV0910_P1_NOTHRES2_FAIL 0xf4c50040 -+#define FSTV0910_P1_NOTHRES1_FAIL 0xf4c50020 -+#define FSTV0910_P1_PILOT_FAILDETECT 0xf4c50010 -+#define FSTV0910_P1_HIER_DETECT 0xf4c50008 -+#define FSTV0910_P1_DMDPROG_ERROR 0xf4c50004 -+#define FSTV0910_P1_CSTENV_DETECT 0xf4c50002 -+#define FSTV0910_P1_DETECTION_TRIAX 0xf4c50001 -+ -+/*P1_DMDRESCFG*/ -+#define RSTV0910_P1_DMDRESCFG 0xf4c6 -+#define FSTV0910_P1_DMDRES_RESET 0xf4c60080 -+#define FSTV0910_P1_DMDRES_NOISESQR 0xf4c60010 -+#define FSTV0910_P1_DMDRES_STRALL 0xf4c60008 -+#define FSTV0910_P1_DMDRES_NEWONLY 0xf4c60004 -+#define FSTV0910_P1_DMDRES_NOSTORE 0xf4c60002 -+#define FSTV0910_P1_DMDRES_AGC2MEM 0xf4c60001 -+ -+/*P1_DMDRESADR*/ -+#define RSTV0910_P1_DMDRESADR 0xf4c7 -+#define FSTV0910_P1_SUSP_PREDCANAL 0xf4c70080 -+#define FSTV0910_P1_DMDRES_VALIDCFR 0xf4c70040 -+#define FSTV0910_P1_DMDRES_MEMFULL 0xf4c70030 -+#define FSTV0910_P1_DMDRES_RESNBR 0xf4c7000f -+ -+/*P1_DMDRESDATA7*/ -+#define RSTV0910_P1_DMDRESDATA7 0xf4c8 -+#define FSTV0910_P1_DMDRES_DATA7 0xf4c800ff -+ -+/*P1_DMDRESDATA6*/ -+#define RSTV0910_P1_DMDRESDATA6 0xf4c9 -+#define FSTV0910_P1_DMDRES_DATA6 0xf4c900ff -+ -+/*P1_DMDRESDATA5*/ -+#define RSTV0910_P1_DMDRESDATA5 0xf4ca -+#define FSTV0910_P1_DMDRES_DATA5 0xf4ca00ff -+ -+/*P1_DMDRESDATA4*/ -+#define RSTV0910_P1_DMDRESDATA4 0xf4cb -+#define FSTV0910_P1_DMDRES_DATA4 0xf4cb00ff -+ -+/*P1_DMDRESDATA3*/ -+#define RSTV0910_P1_DMDRESDATA3 0xf4cc -+#define FSTV0910_P1_DMDRES_DATA3 0xf4cc00ff -+ -+/*P1_DMDRESDATA2*/ -+#define RSTV0910_P1_DMDRESDATA2 0xf4cd -+#define FSTV0910_P1_DMDRES_DATA2 0xf4cd00ff -+ -+/*P1_DMDRESDATA1*/ -+#define RSTV0910_P1_DMDRESDATA1 0xf4ce -+#define FSTV0910_P1_DMDRES_DATA1 0xf4ce00ff -+ -+/*P1_DMDRESDATA0*/ -+#define RSTV0910_P1_DMDRESDATA0 0xf4cf -+#define FSTV0910_P1_DMDRES_DATA0 0xf4cf00ff -+ -+/*P1_FFEI1*/ -+#define RSTV0910_P1_FFEI1 0xf4d0 -+#define FSTV0910_P1_FFE_ACCI1 0xf4d001ff -+ -+/*P1_FFEQ1*/ -+#define RSTV0910_P1_FFEQ1 0xf4d1 -+#define FSTV0910_P1_FFE_ACCQ1 0xf4d101ff -+ -+/*P1_FFEI2*/ -+#define RSTV0910_P1_FFEI2 0xf4d2 -+#define FSTV0910_P1_FFE_ACCI2 0xf4d201ff -+ -+/*P1_FFEQ2*/ -+#define RSTV0910_P1_FFEQ2 0xf4d3 -+#define FSTV0910_P1_FFE_ACCQ2 0xf4d301ff -+ -+/*P1_FFEI3*/ -+#define RSTV0910_P1_FFEI3 0xf4d4 -+#define FSTV0910_P1_FFE_ACCI3 0xf4d401ff -+ -+/*P1_FFEQ3*/ -+#define RSTV0910_P1_FFEQ3 0xf4d5 -+#define FSTV0910_P1_FFE_ACCQ3 0xf4d501ff -+ -+/*P1_FFEI4*/ -+#define RSTV0910_P1_FFEI4 0xf4d6 -+#define FSTV0910_P1_FFE_ACCI4 0xf4d601ff -+ -+/*P1_FFEQ4*/ -+#define RSTV0910_P1_FFEQ4 0xf4d7 -+#define FSTV0910_P1_FFE_ACCQ4 0xf4d701ff -+ -+/*P1_FFECFG*/ -+#define RSTV0910_P1_FFECFG 0xf4d8 -+#define FSTV0910_P1_EQUALFFE_ON 0xf4d80040 -+#define FSTV0910_P1_EQUAL_USEDSYMB 0xf4d80030 -+#define FSTV0910_P1_MU_EQUALFFE 0xf4d80007 -+ -+/*P1_TNRCFG2*/ -+#define RSTV0910_P1_TNRCFG2 0xf4e1 -+#define FSTV0910_P1_TUN_IQSWAP 0xf4e10080 -+#define FSTV0910_P1_STB6110_STEP2MHZ 0xf4e10040 -+#define FSTV0910_P1_STB6120_DBLI2C 0xf4e10020 -+#define FSTV0910_P1_TUNER_WIDEBAND 0xf4e10010 -+#define FSTV0910_P1_TUNER_OBSPAGE 0xf4e10008 -+#define FSTV0910_P1_DIS_BWCALC 0xf4e10004 -+#define FSTV0910_P1_SHORT_WAITSTATES 0xf4e10002 -+#define FSTV0910_P1_DIS_2BWAGC1 0xf4e10001 -+ -+/*P1_SMAPCOEF7*/ -+#define RSTV0910_P1_SMAPCOEF7 0xf500 -+#define FSTV0910_P1_DIS_QSCALE 0xf5000080 -+#define FSTV0910_P1_SMAPCOEF_Q_LLR12 0xf500017f -+ -+/*P1_SMAPCOEF6*/ -+#define RSTV0910_P1_SMAPCOEF6 0xf501 -+#define FSTV0910_P1_DIS_AGC2SCALE 0xf5010080 -+#define FSTV0910_P1_DIS_16IQMULT 0xf5010040 -+#define FSTV0910_P1_OLD_16APSK47 0xf5010020 -+#define FSTV0910_P1_OLD_16APSK12 0xf5010010 -+#define FSTV0910_P1_DIS_NEWSCALE 0xf5010008 -+#define FSTV0910_P1_ADJ_8PSKLLR1 0xf5010004 -+#define FSTV0910_P1_OLD_8PSKLLR1 0xf5010002 -+#define FSTV0910_P1_DIS_AB8PSK 0xf5010001 -+ -+/*P1_SMAPCOEF5*/ -+#define RSTV0910_P1_SMAPCOEF5 0xf502 -+#define FSTV0910_P1_DIS_8SCALE 0xf5020080 -+#define FSTV0910_P1_SMAPCOEF_8P_LLR23 0xf502017f -+ -+/*P1_NOSTHRES1*/ -+#define RSTV0910_P1_NOSTHRES1 0xf509 -+#define FSTV0910_P1_NOS_THRESHOLD1 0xf50900ff -+ -+/*P1_NOSTHRES2*/ -+#define RSTV0910_P1_NOSTHRES2 0xf50a -+#define FSTV0910_P1_NOS_THRESHOLD2 0xf50a00ff -+ -+/*P1_NOSDIFF1*/ -+#define RSTV0910_P1_NOSDIFF1 0xf50b -+#define FSTV0910_P1_NOSTHRES1_DIFF 0xf50b00ff -+ -+/*P1_RAINFADE*/ -+#define RSTV0910_P1_RAINFADE 0xf50c -+#define FSTV0910_P1_NOSTHRES_DATAT 0xf50c0080 -+#define FSTV0910_P1_RAINFADE_CNLIMIT 0xf50c0070 -+#define FSTV0910_P1_RAINFADE_TIMEOUT 0xf50c0007 -+ -+/*P1_NOSRAMCFG*/ -+#define RSTV0910_P1_NOSRAMCFG 0xf50d -+#define FSTV0910_P1_NOSRAM_DVBS2DATA 0xf50d0080 -+#define FSTV0910_P1_NOSRAM_QUADRAT 0xf50d0040 -+#define FSTV0910_P1_NOSRAM_ACTIVATION 0xf50d0030 -+#define FSTV0910_P1_NOSRAM_CNRONLY 0xf50d0008 -+#define FSTV0910_P1_NOSRAM_LGNCNR1 0xf50d0007 -+ -+/*P1_NOSRAMPOS*/ -+#define RSTV0910_P1_NOSRAMPOS 0xf50e -+#define FSTV0910_P1_NOSRAM_LGNCNR0 0xf50e00f0 -+#define FSTV0910_P1_NOSRAM_VALIDE 0xf50e0004 -+#define FSTV0910_P1_NOSRAM_CNRVAL1 0xf50e0003 -+ -+/*P1_NOSRAMVAL*/ -+#define RSTV0910_P1_NOSRAMVAL 0xf50f -+#define FSTV0910_P1_NOSRAM_CNRVAL0 0xf50f00ff -+ -+/*P1_DMDPLHSTAT*/ -+#define RSTV0910_P1_DMDPLHSTAT 0xf520 -+#define FSTV0910_P1_PLH_STATISTIC 0xf52000ff -+ -+/*P1_LOCKTIME3*/ -+#define RSTV0910_P1_LOCKTIME3 0xf522 -+#define FSTV0910_P1_DEMOD_LOCKTIME3 0xf52200ff -+ -+/*P1_LOCKTIME2*/ -+#define RSTV0910_P1_LOCKTIME2 0xf523 -+#define FSTV0910_P1_DEMOD_LOCKTIME2 0xf52300ff -+ -+/*P1_LOCKTIME1*/ -+#define RSTV0910_P1_LOCKTIME1 0xf524 -+#define FSTV0910_P1_DEMOD_LOCKTIME1 0xf52400ff -+ -+/*P1_LOCKTIME0*/ -+#define RSTV0910_P1_LOCKTIME0 0xf525 -+#define FSTV0910_P1_DEMOD_LOCKTIME0 0xf52500ff -+ -+/*P1_VITSCALE*/ -+#define RSTV0910_P1_VITSCALE 0xf532 -+#define FSTV0910_P1_NVTH_NOSRANGE 0xf5320080 -+#define FSTV0910_P1_VERROR_MAXMODE 0xf5320040 -+#define FSTV0910_P1_KDIV_MODE 0xf5320030 -+#define FSTV0910_P1_NSLOWSN_LOCKED 0xf5320008 -+#define FSTV0910_P1_DELOCK_PRFLOSS 0xf5320004 -+#define FSTV0910_P1_DIS_RSFLOCK 0xf5320002 -+ -+/*P1_FECM*/ -+#define RSTV0910_P1_FECM 0xf533 -+#define FSTV0910_P1_DSS_DVB 0xf5330080 -+#define FSTV0910_P1_DEMOD_BYPASS 0xf5330040 -+#define FSTV0910_P1_CMP_SLOWMODE 0xf5330020 -+#define FSTV0910_P1_DSS_SRCH 0xf5330010 -+#define FSTV0910_P1_DIFF_MODEVIT 0xf5330004 -+#define FSTV0910_P1_SYNCVIT 0xf5330002 -+#define FSTV0910_P1_IQINV 0xf5330001 -+ -+/*P1_VTH12*/ -+#define RSTV0910_P1_VTH12 0xf534 -+#define FSTV0910_P1_VTH12 0xf53400ff -+ -+/*P1_VTH23*/ -+#define RSTV0910_P1_VTH23 0xf535 -+#define FSTV0910_P1_VTH23 0xf53500ff -+ -+/*P1_VTH34*/ -+#define RSTV0910_P1_VTH34 0xf536 -+#define FSTV0910_P1_VTH34 0xf53600ff -+ -+/*P1_VTH56*/ -+#define RSTV0910_P1_VTH56 0xf537 -+#define FSTV0910_P1_VTH56 0xf53700ff -+ -+/*P1_VTH67*/ -+#define RSTV0910_P1_VTH67 0xf538 -+#define FSTV0910_P1_VTH67 0xf53800ff -+ -+/*P1_VTH78*/ -+#define RSTV0910_P1_VTH78 0xf539 -+#define FSTV0910_P1_VTH78 0xf53900ff -+ -+/*P1_VITCURPUN*/ -+#define RSTV0910_P1_VITCURPUN 0xf53a -+#define FSTV0910_P1_CYCLESLIP_VIT 0xf53a0080 -+#define FSTV0910_P1_VIT_ROTA180 0xf53a0040 -+#define FSTV0910_P1_VIT_ROTA90 0xf53a0020 -+#define FSTV0910_P1_VIT_CURPUN 0xf53a001f -+ -+/*P1_VERROR*/ -+#define RSTV0910_P1_VERROR 0xf53b -+#define FSTV0910_P1_REGERR_VIT 0xf53b00ff -+ -+/*P1_PRVIT*/ -+#define RSTV0910_P1_PRVIT 0xf53c -+#define FSTV0910_P1_DIS_VTHLOCK 0xf53c0040 -+#define FSTV0910_P1_E7_8VIT 0xf53c0020 -+#define FSTV0910_P1_E6_7VIT 0xf53c0010 -+#define FSTV0910_P1_E5_6VIT 0xf53c0008 -+#define FSTV0910_P1_E3_4VIT 0xf53c0004 -+#define FSTV0910_P1_E2_3VIT 0xf53c0002 -+#define FSTV0910_P1_E1_2VIT 0xf53c0001 -+ -+/*P1_VAVSRVIT*/ -+#define RSTV0910_P1_VAVSRVIT 0xf53d -+#define FSTV0910_P1_AMVIT 0xf53d0080 -+#define FSTV0910_P1_FROZENVIT 0xf53d0040 -+#define FSTV0910_P1_SNVIT 0xf53d0030 -+#define FSTV0910_P1_TOVVIT 0xf53d000c -+#define FSTV0910_P1_HYPVIT 0xf53d0003 -+ -+/*P1_VSTATUSVIT*/ -+#define RSTV0910_P1_VSTATUSVIT 0xf53e -+#define FSTV0910_P1_VITERBI_ON 0xf53e0080 -+#define FSTV0910_P1_END_LOOPVIT 0xf53e0040 -+#define FSTV0910_P1_VITERBI_DEPRF 0xf53e0020 -+#define FSTV0910_P1_PRFVIT 0xf53e0010 -+#define FSTV0910_P1_LOCKEDVIT 0xf53e0008 -+#define FSTV0910_P1_VITERBI_DELOCK 0xf53e0004 -+#define FSTV0910_P1_VIT_DEMODSEL 0xf53e0002 -+#define FSTV0910_P1_VITERBI_COMPOUT 0xf53e0001 -+ -+/*P1_VTHINUSE*/ -+#define RSTV0910_P1_VTHINUSE 0xf53f -+#define FSTV0910_P1_VIT_INUSE 0xf53f00ff -+ -+/*P1_KDIV12*/ -+#define RSTV0910_P1_KDIV12 0xf540 -+#define FSTV0910_P1_KDIV12_MANUAL 0xf5400080 -+#define FSTV0910_P1_K_DIVIDER_12 0xf540007f -+ -+/*P1_KDIV23*/ -+#define RSTV0910_P1_KDIV23 0xf541 -+#define FSTV0910_P1_KDIV23_MANUAL 0xf5410080 -+#define FSTV0910_P1_K_DIVIDER_23 0xf541007f -+ -+/*P1_KDIV34*/ -+#define RSTV0910_P1_KDIV34 0xf542 -+#define FSTV0910_P1_KDIV34_MANUAL 0xf5420080 -+#define FSTV0910_P1_K_DIVIDER_34 0xf542007f -+ -+/*P1_KDIV56*/ -+#define RSTV0910_P1_KDIV56 0xf543 -+#define FSTV0910_P1_KDIV56_MANUAL 0xf5430080 -+#define FSTV0910_P1_K_DIVIDER_56 0xf543007f -+ -+/*P1_KDIV67*/ -+#define RSTV0910_P1_KDIV67 0xf544 -+#define FSTV0910_P1_KDIV67_MANUAL 0xf5440080 -+#define FSTV0910_P1_K_DIVIDER_67 0xf544007f -+ -+/*P1_KDIV78*/ -+#define RSTV0910_P1_KDIV78 0xf545 -+#define FSTV0910_P1_KDIV78_MANUAL 0xf5450080 -+#define FSTV0910_P1_K_DIVIDER_78 0xf545007f -+ -+/*P1_PDELCTRL0*/ -+#define RSTV0910_P1_PDELCTRL0 0xf54f -+#define FSTV0910_P1_ISIOBS_MODE 0xf54f0030 -+#define FSTV0910_P1_PDELDIS_BITWISE 0xf54f0004 -+ -+/*P1_PDELCTRL1*/ -+#define RSTV0910_P1_PDELCTRL1 0xf550 -+#define FSTV0910_P1_INV_MISMASK 0xf5500080 -+#define FSTV0910_P1_FORCE_ACCEPTED 0xf5500040 -+#define FSTV0910_P1_FILTER_EN 0xf5500020 -+#define FSTV0910_P1_FORCE_PKTDELINUSE 0xf5500010 -+#define FSTV0910_P1_HYSTEN 0xf5500008 -+#define FSTV0910_P1_HYSTSWRST 0xf5500004 -+#define FSTV0910_P1_EN_MIS00 0xf5500002 -+#define FSTV0910_P1_ALGOSWRST 0xf5500001 -+ -+/*P1_PDELCTRL2*/ -+#define RSTV0910_P1_PDELCTRL2 0xf551 -+#define FSTV0910_P1_FORCE_CONTINUOUS 0xf5510080 -+#define FSTV0910_P1_RESET_UPKO_COUNT 0xf5510040 -+#define FSTV0910_P1_USER_PKTDELIN_NB 0xf5510020 -+#define FSTV0910_P1_DATA_UNBBSCRAMBLED 0xf5510008 -+#define FSTV0910_P1_FORCE_LONGPKT 0xf5510004 -+#define FSTV0910_P1_FRAME_MODE 0xf5510002 -+ -+/*P1_HYSTTHRESH*/ -+#define RSTV0910_P1_HYSTTHRESH 0xf554 -+#define FSTV0910_P1_DELIN_LOCKTHRES 0xf55400f0 -+#define FSTV0910_P1_DELIN_UNLOCKTHRES 0xf554000f -+ -+/*P1_ISIENTRY*/ -+#define RSTV0910_P1_ISIENTRY 0xf55e -+#define FSTV0910_P1_ISI_ENTRY 0xf55e00ff -+ -+/*P1_ISIBITENA*/ -+#define RSTV0910_P1_ISIBITENA 0xf55f -+#define FSTV0910_P1_ISI_BIT_EN 0xf55f00ff -+ -+/*P1_MATSTR1*/ -+#define RSTV0910_P1_MATSTR1 0xf560 -+#define FSTV0910_P1_MATYPE_CURRENT1 0xf56000ff -+ -+/*P1_MATSTR0*/ -+#define RSTV0910_P1_MATSTR0 0xf561 -+#define FSTV0910_P1_MATYPE_CURRENT0 0xf56100ff -+ -+/*P1_UPLSTR1*/ -+#define RSTV0910_P1_UPLSTR1 0xf562 -+#define FSTV0910_P1_UPL_CURRENT1 0xf56200ff -+ -+/*P1_UPLSTR0*/ -+#define RSTV0910_P1_UPLSTR0 0xf563 -+#define FSTV0910_P1_UPL_CURRENT0 0xf56300ff -+ -+/*P1_DFLSTR1*/ -+#define RSTV0910_P1_DFLSTR1 0xf564 -+#define FSTV0910_P1_DFL_CURRENT1 0xf56400ff -+ -+/*P1_DFLSTR0*/ -+#define RSTV0910_P1_DFLSTR0 0xf565 -+#define FSTV0910_P1_DFL_CURRENT0 0xf56500ff -+ -+/*P1_SYNCSTR*/ -+#define RSTV0910_P1_SYNCSTR 0xf566 -+#define FSTV0910_P1_SYNC_CURRENT 0xf56600ff -+ -+/*P1_SYNCDSTR1*/ -+#define RSTV0910_P1_SYNCDSTR1 0xf567 -+#define FSTV0910_P1_SYNCD_CURRENT1 0xf56700ff -+ -+/*P1_SYNCDSTR0*/ -+#define RSTV0910_P1_SYNCDSTR0 0xf568 -+#define FSTV0910_P1_SYNCD_CURRENT0 0xf56800ff -+ -+/*P1_PDELSTATUS1*/ -+#define RSTV0910_P1_PDELSTATUS1 0xf569 -+#define FSTV0910_P1_PKTDELIN_DELOCK 0xf5690080 -+#define FSTV0910_P1_SYNCDUPDFL_BADDFL 0xf5690040 -+#define FSTV0910_P1_CONTINUOUS_STREAM 0xf5690020 -+#define FSTV0910_P1_UNACCEPTED_STREAM 0xf5690010 -+#define FSTV0910_P1_BCH_ERROR_FLAG 0xf5690008 -+#define FSTV0910_P1_BBHCRCKO 0xf5690004 -+#define FSTV0910_P1_PKTDELIN_LOCK 0xf5690002 -+#define FSTV0910_P1_FIRST_LOCK 0xf5690001 -+ -+/*P1_PDELSTATUS2*/ -+#define RSTV0910_P1_PDELSTATUS2 0xf56a -+#define FSTV0910_P1_PKTDEL_DEMODSEL 0xf56a0080 -+#define FSTV0910_P1_FRAME_MODCOD 0xf56a007c -+#define FSTV0910_P1_FRAME_TYPE 0xf56a0003 -+ -+/*P1_BBFCRCKO1*/ -+#define RSTV0910_P1_BBFCRCKO1 0xf56b -+#define FSTV0910_P1_BBHCRC_KOCNT1 0xf56b00ff -+ -+/*P1_BBFCRCKO0*/ -+#define RSTV0910_P1_BBFCRCKO0 0xf56c -+#define FSTV0910_P1_BBHCRC_KOCNT0 0xf56c00ff -+ -+/*P1_UPCRCKO1*/ -+#define RSTV0910_P1_UPCRCKO1 0xf56d -+#define FSTV0910_P1_PKTCRC_KOCNT1 0xf56d00ff -+ -+/*P1_UPCRCKO0*/ -+#define RSTV0910_P1_UPCRCKO0 0xf56e -+#define FSTV0910_P1_PKTCRC_KOCNT0 0xf56e00ff -+ -+/*P1_PDELCTRL3*/ -+#define RSTV0910_P1_PDELCTRL3 0xf56f -+#define FSTV0910_P1_PKTDEL_CONTFAIL 0xf56f0080 -+#define FSTV0910_P1_PKTDEL_ENLONGPKT 0xf56f0040 -+#define FSTV0910_P1_NOFIFO_BCHERR 0xf56f0020 -+#define FSTV0910_P1_PKTDELIN_DELACMERR 0xf56f0010 -+#define FSTV0910_P1_SATURATE_BBPKTKO 0xf56f0004 -+#define FSTV0910_P1_PKTDEL_BCHERRCONT 0xf56f0002 -+#define FSTV0910_P1_ETHERNET_DISFCS 0xf56f0001 -+ -+/*P1_TSSTATEM*/ -+#define RSTV0910_P1_TSSTATEM 0xf570 -+#define FSTV0910_P1_TSDIL_ON 0xf5700080 -+#define FSTV0910_P1_TSSKIPRS_ON 0xf5700040 -+#define FSTV0910_P1_TSRS_ON 0xf5700020 -+#define FSTV0910_P1_TSDESCRAMB_ON 0xf5700010 -+#define FSTV0910_P1_TSFRAME_MODE 0xf5700008 -+#define FSTV0910_P1_TS_DISABLE 0xf5700004 -+#define FSTV0910_P1_TSACM_MODE 0xf5700002 -+#define FSTV0910_P1_TSOUT_NOSYNC 0xf5700001 -+ -+/*P1_TSCFGH*/ -+#define RSTV0910_P1_TSCFGH 0xf572 -+#define FSTV0910_P1_TSFIFO_DVBCI 0xf5720080 -+#define FSTV0910_P1_TSFIFO_SERIAL 0xf5720040 -+#define FSTV0910_P1_TSFIFO_TEIUPDATE 0xf5720020 -+#define FSTV0910_P1_TSFIFO_DUTY50 0xf5720010 -+#define FSTV0910_P1_TSFIFO_HSGNLOUT 0xf5720008 -+#define FSTV0910_P1_TSFIFO_ERRMODE 0xf5720006 -+#define FSTV0910_P1_RST_HWARE 0xf5720001 -+ -+/*P1_TSCFGM*/ -+#define RSTV0910_P1_TSCFGM 0xf573 -+#define FSTV0910_P1_TSFIFO_MANSPEED 0xf57300c0 -+#define FSTV0910_P1_TSFIFO_PERMDATA 0xf5730020 -+#define FSTV0910_P1_TSFIFO_NONEWSGNL 0xf5730010 -+#define FSTV0910_P1_NPD_SPECDVBS2 0xf5730004 -+#define FSTV0910_P1_TSFIFO_DPUNACTIVE 0xf5730002 -+#define FSTV0910_P1_TSFIFO_INVDATA 0xf5730001 -+ -+/*P1_TSCFGL*/ -+#define RSTV0910_P1_TSCFGL 0xf574 -+#define FSTV0910_P1_TSFIFO_BCLKDEL1CK 0xf57400c0 -+#define FSTV0910_P1_BCHERROR_MODE 0xf5740030 -+#define FSTV0910_P1_TSFIFO_NSGNL2DATA 0xf5740008 -+#define FSTV0910_P1_TSFIFO_EMBINDVB 0xf5740004 -+#define FSTV0910_P1_TSFIFO_BITSPEED 0xf5740003 -+ -+/*P1_TSINSDELH*/ -+#define RSTV0910_P1_TSINSDELH 0xf576 -+#define FSTV0910_P1_TSDEL_SYNCBYTE 0xf5760080 -+#define FSTV0910_P1_TSDEL_XXHEADER 0xf5760040 -+#define FSTV0910_P1_TSDEL_BBHEADER 0xf5760020 -+#define FSTV0910_P1_TSDEL_DATAFIELD 0xf5760010 -+#define FSTV0910_P1_TSINSDEL_ISCR 0xf5760008 -+#define FSTV0910_P1_TSINSDEL_NPD 0xf5760004 -+#define FSTV0910_P1_TSINSDEL_RSPARITY 0xf5760002 -+#define FSTV0910_P1_TSINSDEL_CRC8 0xf5760001 -+ -+/*P1_TSDIVN*/ -+#define RSTV0910_P1_TSDIVN 0xf579 -+#define FSTV0910_P1_TSFIFO_SPEEDMODE 0xf57900c0 -+#define FSTV0910_P1_BYTE_OVERSAMPLING 0xf5790038 -+#define FSTV0910_P1_TSFIFO_RISEOK 0xf5790007 -+ -+/*P1_TSCFG4*/ -+#define RSTV0910_P1_TSCFG4 0xf57a -+#define FSTV0910_P1_TSFIFO_TSSPEEDMODE 0xf57a00c0 -+#define FSTV0910_P1_TSFIFO_HIERSEL 0xf57a0020 -+#define FSTV0910_P1_TSFIFO_SPECTOKEN 0xf57a0010 -+#define FSTV0910_P1_TSFIFO_MAXMODE 0xf57a0008 -+#define FSTV0910_P1_TSFIFO_FRFORCEPKT 0xf57a0004 -+#define FSTV0910_P1_EXT_FECSPYIN 0xf57a0002 -+#define FSTV0910_P1_TSFIFO_DELSPEEDUP 0xf57a0001 -+ -+/*P1_TSSPEED*/ -+#define RSTV0910_P1_TSSPEED 0xf580 -+#define FSTV0910_P1_TSFIFO_OUTSPEED 0xf58000ff -+ -+/*P1_TSSTATUS*/ -+#define RSTV0910_P1_TSSTATUS 0xf581 -+#define FSTV0910_P1_TSFIFO_LINEOK 0xf5810080 -+#define FSTV0910_P1_TSFIFO_ERROR 0xf5810040 -+#define FSTV0910_P1_TSFIFO_DATA7 0xf5810020 -+#define FSTV0910_P1_TSFIFO_NOSYNC 0xf5810010 -+#define FSTV0910_P1_ISCR_INITIALIZED 0xf5810008 -+#define FSTV0910_P1_TSREGUL_ERROR 0xf5810004 -+#define FSTV0910_P1_SOFFIFO_UNREGUL 0xf5810002 -+#define FSTV0910_P1_DIL_READY 0xf5810001 -+ -+/*P1_TSSTATUS2*/ -+#define RSTV0910_P1_TSSTATUS2 0xf582 -+#define FSTV0910_P1_TSFIFO_DEMODSEL 0xf5820080 -+#define FSTV0910_P1_TSFIFOSPEED_STORE 0xf5820040 -+#define FSTV0910_P1_DILXX_RESET 0xf5820020 -+#define FSTV0910_P1_TSSPEED_IMPOSSIBLE 0xf5820010 -+#define FSTV0910_P1_TSFIFO_LINENOK 0xf5820008 -+#define FSTV0910_P1_TSFIFO_MUXSTREAM 0xf5820004 -+#define FSTV0910_P1_SCRAMBDETECT 0xf5820002 -+#define FSTV0910_P1_ULDTV67_FALSELOCK 0xf5820001 -+ -+/*P1_TSBITRATE1*/ -+#define RSTV0910_P1_TSBITRATE1 0xf583 -+#define FSTV0910_P1_TSFIFO_BITRATE1 0xf58300ff -+ -+/*P1_TSBITRATE0*/ -+#define RSTV0910_P1_TSBITRATE0 0xf584 -+#define FSTV0910_P1_TSFIFO_BITRATE0 0xf58400ff -+ -+/*P1_ERRCTRL1*/ -+#define RSTV0910_P1_ERRCTRL1 0xf598 -+#define FSTV0910_P1_ERR_SOURCE1 0xf59800f0 -+#define FSTV0910_P1_NUM_EVENT1 0xf5980007 -+ -+/*P1_ERRCNT12*/ -+#define RSTV0910_P1_ERRCNT12 0xf599 -+#define FSTV0910_P1_ERRCNT1_OLDVALUE 0xf5990080 -+#define FSTV0910_P1_ERR_CNT12 0xf599007f -+ -+/*P1_ERRCNT11*/ -+#define RSTV0910_P1_ERRCNT11 0xf59a -+#define FSTV0910_P1_ERR_CNT11 0xf59a00ff -+ -+/*P1_ERRCNT10*/ -+#define RSTV0910_P1_ERRCNT10 0xf59b -+#define FSTV0910_P1_ERR_CNT10 0xf59b00ff -+ -+/*P1_ERRCTRL2*/ -+#define RSTV0910_P1_ERRCTRL2 0xf59c -+#define FSTV0910_P1_ERR_SOURCE2 0xf59c00f0 -+#define FSTV0910_P1_NUM_EVENT2 0xf59c0007 -+ -+/*P1_ERRCNT22*/ -+#define RSTV0910_P1_ERRCNT22 0xf59d -+#define FSTV0910_P1_ERRCNT2_OLDVALUE 0xf59d0080 -+#define FSTV0910_P1_ERR_CNT22 0xf59d007f -+ -+/*P1_ERRCNT21*/ -+#define RSTV0910_P1_ERRCNT21 0xf59e -+#define FSTV0910_P1_ERR_CNT21 0xf59e00ff -+ -+/*P1_ERRCNT20*/ -+#define RSTV0910_P1_ERRCNT20 0xf59f -+#define FSTV0910_P1_ERR_CNT20 0xf59f00ff -+ -+/*P1_FECSPY*/ -+#define RSTV0910_P1_FECSPY 0xf5a0 -+#define FSTV0910_P1_SPY_ENABLE 0xf5a00080 -+#define FSTV0910_P1_NO_SYNCBYTE 0xf5a00040 -+#define FSTV0910_P1_SERIAL_MODE 0xf5a00020 -+#define FSTV0910_P1_UNUSUAL_PACKET 0xf5a00010 -+#define FSTV0910_P1_BERMETER_DATAMODE 0xf5a0000c -+#define FSTV0910_P1_BERMETER_LMODE 0xf5a00002 -+#define FSTV0910_P1_BERMETER_RESET 0xf5a00001 -+ -+/*P1_FSPYCFG*/ -+#define RSTV0910_P1_FSPYCFG 0xf5a1 -+#define FSTV0910_P1_FECSPY_INPUT 0xf5a100c0 -+#define FSTV0910_P1_RST_ON_ERROR 0xf5a10020 -+#define FSTV0910_P1_ONE_SHOT 0xf5a10010 -+#define FSTV0910_P1_I2C_MODE 0xf5a1000c -+#define FSTV0910_P1_SPY_HYSTERESIS 0xf5a10003 -+ -+/*P1_FSPYDATA*/ -+#define RSTV0910_P1_FSPYDATA 0xf5a2 -+#define FSTV0910_P1_SPY_STUFFING 0xf5a20080 -+#define FSTV0910_P1_NOERROR_PKTJITTER 0xf5a20040 -+#define FSTV0910_P1_SPY_CNULLPKT 0xf5a20020 -+#define FSTV0910_P1_SPY_OUTDATA_MODE 0xf5a2001f -+ -+/*P1_FSPYOUT*/ -+#define RSTV0910_P1_FSPYOUT 0xf5a3 -+#define FSTV0910_P1_FSPY_DIRECT 0xf5a30080 -+#define FSTV0910_P1_SPY_OUTDATA_BUS 0xf5a30038 -+#define FSTV0910_P1_STUFF_MODE 0xf5a30007 -+ -+/*P1_FSTATUS*/ -+#define RSTV0910_P1_FSTATUS 0xf5a4 -+#define FSTV0910_P1_SPY_ENDSIM 0xf5a40080 -+#define FSTV0910_P1_VALID_SIM 0xf5a40040 -+#define FSTV0910_P1_FOUND_SIGNAL 0xf5a40020 -+#define FSTV0910_P1_DSS_SYNCBYTE 0xf5a40010 -+#define FSTV0910_P1_RESULT_STATE 0xf5a4000f -+ -+/*P1_FBERCPT4*/ -+#define RSTV0910_P1_FBERCPT4 0xf5a8 -+#define FSTV0910_P1_FBERMETER_CPT4 0xf5a800ff -+ -+/*P1_FBERCPT3*/ -+#define RSTV0910_P1_FBERCPT3 0xf5a9 -+#define FSTV0910_P1_FBERMETER_CPT3 0xf5a900ff -+ -+/*P1_FBERCPT2*/ -+#define RSTV0910_P1_FBERCPT2 0xf5aa -+#define FSTV0910_P1_FBERMETER_CPT2 0xf5aa00ff -+ -+/*P1_FBERCPT1*/ -+#define RSTV0910_P1_FBERCPT1 0xf5ab -+#define FSTV0910_P1_FBERMETER_CPT1 0xf5ab00ff -+ -+/*P1_FBERCPT0*/ -+#define RSTV0910_P1_FBERCPT0 0xf5ac -+#define FSTV0910_P1_FBERMETER_CPT0 0xf5ac00ff -+ -+/*P1_FBERERR2*/ -+#define RSTV0910_P1_FBERERR2 0xf5ad -+#define FSTV0910_P1_FBERMETER_ERR2 0xf5ad00ff -+ -+/*P1_FBERERR1*/ -+#define RSTV0910_P1_FBERERR1 0xf5ae -+#define FSTV0910_P1_FBERMETER_ERR1 0xf5ae00ff -+ -+/*P1_FBERERR0*/ -+#define RSTV0910_P1_FBERERR0 0xf5af -+#define FSTV0910_P1_FBERMETER_ERR0 0xf5af00ff -+ -+/*P1_FSPYBER*/ -+#define RSTV0910_P1_FSPYBER 0xf5b2 -+#define FSTV0910_P1_FSPYOBS_XORREAD 0xf5b20040 -+#define FSTV0910_P1_FSPYBER_OBSMODE 0xf5b20020 -+#define FSTV0910_P1_FSPYBER_SYNCBYTE 0xf5b20010 -+#define FSTV0910_P1_FSPYBER_UNSYNC 0xf5b20008 -+#define FSTV0910_P1_FSPYBER_CTIME 0xf5b20007 -+ -+/*P1_SFERROR*/ -+#define RSTV0910_P1_SFERROR 0xf5c1 -+#define FSTV0910_P1_SFEC_REGERR_VIT 0xf5c100ff -+ -+/*P1_SFECSTATUS*/ -+#define RSTV0910_P1_SFECSTATUS 0xf5c3 -+#define FSTV0910_P1_SFEC_ON 0xf5c30080 -+#define FSTV0910_P1_SFEC_OFF 0xf5c30040 -+#define FSTV0910_P1_LOCKEDSFEC 0xf5c30008 -+#define FSTV0910_P1_SFEC_DELOCK 0xf5c30004 -+#define FSTV0910_P1_SFEC_DEMODSEL 0xf5c30002 -+#define FSTV0910_P1_SFEC_OVFON 0xf5c30001 -+ -+/*P1_SFKDIV12*/ -+#define RSTV0910_P1_SFKDIV12 0xf5c4 -+#define FSTV0910_P1_SFECKDIV12_MAN 0xf5c40080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_12 0xf5c4007f -+ -+/*P1_SFKDIV23*/ -+#define RSTV0910_P1_SFKDIV23 0xf5c5 -+#define FSTV0910_P1_SFECKDIV23_MAN 0xf5c50080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_23 0xf5c5007f -+ -+/*P1_SFKDIV34*/ -+#define RSTV0910_P1_SFKDIV34 0xf5c6 -+#define FSTV0910_P1_SFECKDIV34_MAN 0xf5c60080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_34 0xf5c6007f -+ -+/*P1_SFKDIV56*/ -+#define RSTV0910_P1_SFKDIV56 0xf5c7 -+#define FSTV0910_P1_SFECKDIV56_MAN 0xf5c70080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_56 0xf5c7007f -+ -+/*P1_SFKDIV67*/ -+#define RSTV0910_P1_SFKDIV67 0xf5c8 -+#define FSTV0910_P1_SFECKDIV67_MAN 0xf5c80080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_67 0xf5c8007f -+ -+/*P1_SFKDIV78*/ -+#define RSTV0910_P1_SFKDIV78 0xf5c9 -+#define FSTV0910_P1_SFECKDIV78_MAN 0xf5c90080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_78 0xf5c9007f -+ -+/*P1_SFSTATUS*/ -+#define RSTV0910_P1_SFSTATUS 0xf5cc -+#define FSTV0910_P1_SFEC_LINEOK 0xf5cc0080 -+#define FSTV0910_P1_SFEC_ERROR 0xf5cc0040 -+#define FSTV0910_P1_SFEC_DATA7 0xf5cc0020 -+#define FSTV0910_P1_SFEC_PKTDNBRFAIL 0xf5cc0010 -+#define FSTV0910_P1_TSSFEC_DEMODSEL 0xf5cc0008 -+#define FSTV0910_P1_SFEC_NOSYNC 0xf5cc0004 -+#define FSTV0910_P1_SFEC_UNREGULA 0xf5cc0002 -+#define FSTV0910_P1_SFEC_READY 0xf5cc0001 -+ -+/*P1_SFDLYSET2*/ -+#define RSTV0910_P1_SFDLYSET2 0xf5d0 -+#define FSTV0910_P1_SFEC_OFFSET 0xf5d000c0 -+#define FSTV0910_P1_RST_SFEC 0xf5d00008 -+#define FSTV0910_P1_DILDLINE_ERROR 0xf5d00004 -+#define FSTV0910_P1_SFEC_DISABLE 0xf5d00002 -+#define FSTV0910_P1_SFEC_UNREGUL 0xf5d00001 -+ -+/*P1_SFERRCTRL*/ -+#define RSTV0910_P1_SFERRCTRL 0xf5d8 -+#define FSTV0910_P1_SFEC_ERR_SOURCE 0xf5d800f0 -+#define FSTV0910_P1_SFEC_NUM_EVENT 0xf5d80007 -+ -+/*P1_SFERRCNT2*/ -+#define RSTV0910_P1_SFERRCNT2 0xf5d9 -+#define FSTV0910_P1_SFERRC_OLDVALUE 0xf5d90080 -+#define FSTV0910_P1_SFEC_ERR_CNT2 0xf5d9007f -+ -+/*P1_SFERRCNT1*/ -+#define RSTV0910_P1_SFERRCNT1 0xf5da -+#define FSTV0910_P1_SFEC_ERR_CNT1 0xf5da00ff -+ -+/*P1_SFERRCNT0*/ -+#define RSTV0910_P1_SFERRCNT0 0xf5db -+#define FSTV0910_P1_SFEC_ERR_CNT0 0xf5db00ff -+ -+/*TSGENERAL*/ -+#define RSTV0910_TSGENERAL 0xf630 -+#define FSTV0910_EN_LGNERROR 0xf6300080 -+#define FSTV0910_TSFIFO_DISTS2PAR 0xf6300040 -+#define FSTV0910_MUXSTREAM_COMPMOSE 0xf6300030 -+#define FSTV0910_MUXSTREAM_OUTMODE 0xf6300008 -+#define FSTV0910_TSFIFO_PERMPARAL 0xf6300006 -+#define FSTV0910_RST_REEDSOLO 0xf6300001 -+ -+/*P1_DISIRQCFG*/ -+#define RSTV0910_P1_DISIRQCFG 0xf700 -+#define FSTV0910_P1_ENRXEND 0xf7000040 -+#define FSTV0910_P1_ENRXFIFO8B 0xf7000020 -+#define FSTV0910_P1_ENTRFINISH 0xf7000010 -+#define FSTV0910_P1_ENTIMEOUT 0xf7000008 -+#define FSTV0910_P1_ENTXEND 0xf7000004 -+#define FSTV0910_P1_ENTXFIFO64B 0xf7000002 -+#define FSTV0910_P1_ENGAPBURST 0xf7000001 -+ -+/*P1_DISIRQSTAT*/ -+#define RSTV0910_P1_DISIRQSTAT 0xf701 -+#define FSTV0910_P1_IRQRXEND 0xf7010040 -+#define FSTV0910_P1_IRQRXFIFO8B 0xf7010020 -+#define FSTV0910_P1_IRQTRFINISH 0xf7010010 -+#define FSTV0910_P1_IRQTIMEOUT 0xf7010008 -+#define FSTV0910_P1_IRQTXEND 0xf7010004 -+#define FSTV0910_P1_IRQTXFIFO64B 0xf7010002 -+#define FSTV0910_P1_IRQGAPBURST 0xf7010001 -+ -+/*P1_DISTXCFG*/ -+#define RSTV0910_P1_DISTXCFG 0xf702 -+#define FSTV0910_P1_DISTX_RESET 0xf7020080 -+#define FSTV0910_P1_TIM_OFF 0xf7020040 -+#define FSTV0910_P1_TIM_CMD 0xf7020030 -+#define FSTV0910_P1_ENVELOP 0xf7020008 -+#define FSTV0910_P1_DIS_PRECHARGE 0xf7020004 -+#define FSTV0910_P1_DISEQC_MODE 0xf7020003 -+ -+/*P1_DISTXSTATUS*/ -+#define RSTV0910_P1_DISTXSTATUS 0xf703 -+#define FSTV0910_P1_TX_FIFO_FULL 0xf7030040 -+#define FSTV0910_P1_TX_IDLE 0xf7030020 -+#define FSTV0910_P1_GAP_BURST 0xf7030010 -+#define FSTV0910_P1_TX_FIFO64B 0xf7030008 -+#define FSTV0910_P1_TX_END 0xf7030004 -+#define FSTV0910_P1_TR_TIMEOUT 0xf7030002 -+#define FSTV0910_P1_TR_FINISH 0xf7030001 -+ -+/*P1_DISTXBYTES*/ -+#define RSTV0910_P1_DISTXBYTES 0xf704 -+#define FSTV0910_P1_TXFIFO_BYTES 0xf70400ff -+ -+/*P1_DISTXFIFO*/ -+#define RSTV0910_P1_DISTXFIFO 0xf705 -+#define FSTV0910_P1_DISEQC_TX_FIFO 0xf70500ff -+ -+/*P1_DISTXF22*/ -+#define RSTV0910_P1_DISTXF22 0xf706 -+#define FSTV0910_P1_F22TX 0xf70600ff -+ -+/*P1_DISTIMEOCFG*/ -+#define RSTV0910_P1_DISTIMEOCFG 0xf708 -+#define FSTV0910_P1_RXCHOICE 0xf7080006 -+#define FSTV0910_P1_TIMEOUT_OFF 0xf7080001 -+ -+/*P1_DISTIMEOUT*/ -+#define RSTV0910_P1_DISTIMEOUT 0xf709 -+#define FSTV0910_P1_TIMEOUT_COUNT 0xf70900ff -+ -+/*P1_DISRXCFG*/ -+#define RSTV0910_P1_DISRXCFG 0xf70a -+#define FSTV0910_P1_DISRX_RESET 0xf70a0080 -+#define FSTV0910_P1_EXTENVELOP 0xf70a0040 -+#define FSTV0910_P1_PINSELECT 0xf70a0038 -+#define FSTV0910_P1_IGNORE_SHORT22K 0xf70a0004 -+#define FSTV0910_P1_SIGNED_RXIN 0xf70a0002 -+#define FSTV0910_P1_DISRX_ON 0xf70a0001 -+ -+/*P1_DISRXSTAT1*/ -+#define RSTV0910_P1_DISRXSTAT1 0xf70b -+#define FSTV0910_P1_RXEND 0xf70b0080 -+#define FSTV0910_P1_RXACTIVE 0xf70b0040 -+#define FSTV0910_P1_RXDETECT 0xf70b0020 -+#define FSTV0910_P1_CONTTONE 0xf70b0010 -+#define FSTV0910_P1_8BFIFOREADY 0xf70b0008 -+#define FSTV0910_P1_FIFOEMPTY 0xf70b0004 -+ -+/*P1_DISRXSTAT0*/ -+#define RSTV0910_P1_DISRXSTAT0 0xf70c -+#define FSTV0910_P1_RXFAIL 0xf70c0080 -+#define FSTV0910_P1_FIFOPFAIL 0xf70c0040 -+#define FSTV0910_P1_RXNONBYTE 0xf70c0020 -+#define FSTV0910_P1_FIFOOVF 0xf70c0010 -+#define FSTV0910_P1_SHORT22K 0xf70c0008 -+#define FSTV0910_P1_RXMSGLOST 0xf70c0004 -+ -+/*P1_DISRXBYTES*/ -+#define RSTV0910_P1_DISRXBYTES 0xf70d -+#define FSTV0910_P1_RXFIFO_BYTES 0xf70d001f -+ -+/*P1_DISRXPARITY1*/ -+#define RSTV0910_P1_DISRXPARITY1 0xf70e -+#define FSTV0910_P1_DISRX_PARITY1 0xf70e00ff -+ -+/*P1_DISRXPARITY0*/ -+#define RSTV0910_P1_DISRXPARITY0 0xf70f -+#define FSTV0910_P1_DISRX_PARITY0 0xf70f00ff -+ -+/*P1_DISRXFIFO*/ -+#define RSTV0910_P1_DISRXFIFO 0xf710 -+#define FSTV0910_P1_DISEQC_RX_FIFO 0xf71000ff -+ -+/*P1_DISRXDC1*/ -+#define RSTV0910_P1_DISRXDC1 0xf711 -+#define FSTV0910_P1_DC_VALUE1 0xf7110103 -+ -+/*P1_DISRXDC0*/ -+#define RSTV0910_P1_DISRXDC0 0xf712 -+#define FSTV0910_P1_DC_VALUE0 0xf71200ff -+ -+/*P1_DISRXF221*/ -+#define RSTV0910_P1_DISRXF221 0xf714 -+#define FSTV0910_P1_F22RX1 0xf714000f -+ -+/*P1_DISRXF220*/ -+#define RSTV0910_P1_DISRXF220 0xf715 -+#define FSTV0910_P1_F22RX0 0xf71500ff -+ -+/*P1_DISRXF100*/ -+#define RSTV0910_P1_DISRXF100 0xf716 -+#define FSTV0910_P1_F100RX 0xf71600ff -+ -+/*P1_DISRXSHORT22K*/ -+#define RSTV0910_P1_DISRXSHORT22K 0xf71c -+#define FSTV0910_P1_SHORT22K_LENGTH 0xf71c001f -+ -+/*P1_ACRPRESC*/ -+#define RSTV0910_P1_ACRPRESC 0xf71e -+#define FSTV0910_P1_ACR_CODFRDY 0xf71e0008 -+#define FSTV0910_P1_ACR_PRESC 0xf71e0007 -+ -+/*P1_ACRDIV*/ -+#define RSTV0910_P1_ACRDIV 0xf71f -+#define FSTV0910_P1_ACR_DIV 0xf71f00ff -+ -+/*P2_DISIRQCFG*/ -+#define RSTV0910_P2_DISIRQCFG 0xf740 -+#define FSTV0910_P2_ENRXEND 0xf7400040 -+#define FSTV0910_P2_ENRXFIFO8B 0xf7400020 -+#define FSTV0910_P2_ENTRFINISH 0xf7400010 -+#define FSTV0910_P2_ENTIMEOUT 0xf7400008 -+#define FSTV0910_P2_ENTXEND 0xf7400004 -+#define FSTV0910_P2_ENTXFIFO64B 0xf7400002 -+#define FSTV0910_P2_ENGAPBURST 0xf7400001 -+ -+/*P2_DISIRQSTAT*/ -+#define RSTV0910_P2_DISIRQSTAT 0xf741 -+#define FSTV0910_P2_IRQRXEND 0xf7410040 -+#define FSTV0910_P2_IRQRXFIFO8B 0xf7410020 -+#define FSTV0910_P2_IRQTRFINISH 0xf7410010 -+#define FSTV0910_P2_IRQTIMEOUT 0xf7410008 -+#define FSTV0910_P2_IRQTXEND 0xf7410004 -+#define FSTV0910_P2_IRQTXFIFO64B 0xf7410002 -+#define FSTV0910_P2_IRQGAPBURST 0xf7410001 -+ -+/*P2_DISTXCFG*/ -+#define RSTV0910_P2_DISTXCFG 0xf742 -+#define FSTV0910_P2_DISTX_RESET 0xf7420080 -+#define FSTV0910_P2_TIM_OFF 0xf7420040 -+#define FSTV0910_P2_TIM_CMD 0xf7420030 -+#define FSTV0910_P2_ENVELOP 0xf7420008 -+#define FSTV0910_P2_DIS_PRECHARGE 0xf7420004 -+#define FSTV0910_P2_DISEQC_MODE 0xf7420003 -+ -+/*P2_DISTXSTATUS*/ -+#define RSTV0910_P2_DISTXSTATUS 0xf743 -+#define FSTV0910_P2_TX_FIFO_FULL 0xf7430040 -+#define FSTV0910_P2_TX_IDLE 0xf7430020 -+#define FSTV0910_P2_GAP_BURST 0xf7430010 -+#define FSTV0910_P2_TX_FIFO64B 0xf7430008 -+#define FSTV0910_P2_TX_END 0xf7430004 -+#define FSTV0910_P2_TR_TIMEOUT 0xf7430002 -+#define FSTV0910_P2_TR_FINISH 0xf7430001 -+ -+/*P2_DISTXBYTES*/ -+#define RSTV0910_P2_DISTXBYTES 0xf744 -+#define FSTV0910_P2_TXFIFO_BYTES 0xf74400ff -+ -+/*P2_DISTXFIFO*/ -+#define RSTV0910_P2_DISTXFIFO 0xf745 -+#define FSTV0910_P2_DISEQC_TX_FIFO 0xf74500ff -+ -+/*P2_DISTXF22*/ -+#define RSTV0910_P2_DISTXF22 0xf746 -+#define FSTV0910_P2_F22TX 0xf74600ff -+ -+/*P2_DISTIMEOCFG*/ -+#define RSTV0910_P2_DISTIMEOCFG 0xf748 -+#define FSTV0910_P2_RXCHOICE 0xf7480006 -+#define FSTV0910_P2_TIMEOUT_OFF 0xf7480001 -+ -+/*P2_DISTIMEOUT*/ -+#define RSTV0910_P2_DISTIMEOUT 0xf749 -+#define FSTV0910_P2_TIMEOUT_COUNT 0xf74900ff -+ -+/*P2_DISRXCFG*/ -+#define RSTV0910_P2_DISRXCFG 0xf74a -+#define FSTV0910_P2_DISRX_RESET 0xf74a0080 -+#define FSTV0910_P2_EXTENVELOP 0xf74a0040 -+#define FSTV0910_P2_PINSELECT 0xf74a0038 -+#define FSTV0910_P2_IGNORE_SHORT22K 0xf74a0004 -+#define FSTV0910_P2_SIGNED_RXIN 0xf74a0002 -+#define FSTV0910_P2_DISRX_ON 0xf74a0001 -+ -+/*P2_DISRXSTAT1*/ -+#define RSTV0910_P2_DISRXSTAT1 0xf74b -+#define FSTV0910_P2_RXEND 0xf74b0080 -+#define FSTV0910_P2_RXACTIVE 0xf74b0040 -+#define FSTV0910_P2_RXDETECT 0xf74b0020 -+#define FSTV0910_P2_CONTTONE 0xf74b0010 -+#define FSTV0910_P2_8BFIFOREADY 0xf74b0008 -+#define FSTV0910_P2_FIFOEMPTY 0xf74b0004 -+ -+/*P2_DISRXSTAT0*/ -+#define RSTV0910_P2_DISRXSTAT0 0xf74c -+#define FSTV0910_P2_RXFAIL 0xf74c0080 -+#define FSTV0910_P2_FIFOPFAIL 0xf74c0040 -+#define FSTV0910_P2_RXNONBYTE 0xf74c0020 -+#define FSTV0910_P2_FIFOOVF 0xf74c0010 -+#define FSTV0910_P2_SHORT22K 0xf74c0008 -+#define FSTV0910_P2_RXMSGLOST 0xf74c0004 -+ -+/*P2_DISRXBYTES*/ -+#define RSTV0910_P2_DISRXBYTES 0xf74d -+#define FSTV0910_P2_RXFIFO_BYTES 0xf74d001f -+ -+/*P2_DISRXPARITY1*/ -+#define RSTV0910_P2_DISRXPARITY1 0xf74e -+#define FSTV0910_P2_DISRX_PARITY1 0xf74e00ff -+ -+/*P2_DISRXPARITY0*/ -+#define RSTV0910_P2_DISRXPARITY0 0xf74f -+#define FSTV0910_P2_DISRX_PARITY0 0xf74f00ff -+ -+/*P2_DISRXFIFO*/ -+#define RSTV0910_P2_DISRXFIFO 0xf750 -+#define FSTV0910_P2_DISEQC_RX_FIFO 0xf75000ff -+ -+/*P2_DISRXDC1*/ -+#define RSTV0910_P2_DISRXDC1 0xf751 -+#define FSTV0910_P2_DC_VALUE1 0xf7510103 -+ -+/*P2_DISRXDC0*/ -+#define RSTV0910_P2_DISRXDC0 0xf752 -+#define FSTV0910_P2_DC_VALUE0 0xf75200ff -+ -+/*P2_DISRXF221*/ -+#define RSTV0910_P2_DISRXF221 0xf754 -+#define FSTV0910_P2_F22RX1 0xf754000f -+ -+/*P2_DISRXF220*/ -+#define RSTV0910_P2_DISRXF220 0xf755 -+#define FSTV0910_P2_F22RX0 0xf75500ff -+ -+/*P2_DISRXF100*/ -+#define RSTV0910_P2_DISRXF100 0xf756 -+#define FSTV0910_P2_F100RX 0xf75600ff -+ -+/*P2_DISRXSHORT22K*/ -+#define RSTV0910_P2_DISRXSHORT22K 0xf75c -+#define FSTV0910_P2_SHORT22K_LENGTH 0xf75c001f -+ -+/*P2_ACRPRESC*/ -+#define RSTV0910_P2_ACRPRESC 0xf75e -+#define FSTV0910_P2_ACR_CODFRDY 0xf75e0008 -+#define FSTV0910_P2_ACR_PRESC 0xf75e0007 -+ -+/*P2_ACRDIV*/ -+#define RSTV0910_P2_ACRDIV 0xf75f -+#define FSTV0910_P2_ACR_DIV 0xf75f00ff -+ -+/*P1_NBITER_NF4*/ -+#define RSTV0910_P1_NBITER_NF4 0xfa03 -+#define FSTV0910_P1_NBITER_NF_QPSK_1_2 0xfa0300ff -+ -+/*P1_NBITER_NF5*/ -+#define RSTV0910_P1_NBITER_NF5 0xfa04 -+#define FSTV0910_P1_NBITER_NF_QPSK_3_5 0xfa0400ff -+ -+/*P1_NBITER_NF6*/ -+#define RSTV0910_P1_NBITER_NF6 0xfa05 -+#define FSTV0910_P1_NBITER_NF_QPSK_2_3 0xfa0500ff -+ -+/*P1_NBITER_NF7*/ -+#define RSTV0910_P1_NBITER_NF7 0xfa06 -+#define FSTV0910_P1_NBITER_NF_QPSK_3_4 0xfa0600ff -+ -+/*P1_NBITER_NF8*/ -+#define RSTV0910_P1_NBITER_NF8 0xfa07 -+#define FSTV0910_P1_NBITER_NF_QPSK_4_5 0xfa0700ff -+ -+/*P1_NBITER_NF9*/ -+#define RSTV0910_P1_NBITER_NF9 0xfa08 -+#define FSTV0910_P1_NBITER_NF_QPSK_5_6 0xfa0800ff -+ -+/*P1_NBITER_NF10*/ -+#define RSTV0910_P1_NBITER_NF10 0xfa09 -+#define FSTV0910_P1_NBITER_NF_QPSK_8_9 0xfa0900ff -+ -+/*P1_NBITER_NF11*/ -+#define RSTV0910_P1_NBITER_NF11 0xfa0a -+#define FSTV0910_P1_NBITER_NF_QPSK_9_10 0xfa0a00ff -+ -+/*P1_NBITER_NF12*/ -+#define RSTV0910_P1_NBITER_NF12 0xfa0b -+#define FSTV0910_P1_NBITER_NF_8PSK_3_5 0xfa0b00ff -+ -+/*P1_NBITER_NF13*/ -+#define RSTV0910_P1_NBITER_NF13 0xfa0c -+#define FSTV0910_P1_NBITER_NF_8PSK_2_3 0xfa0c00ff -+ -+/*P1_NBITER_NF14*/ -+#define RSTV0910_P1_NBITER_NF14 0xfa0d -+#define FSTV0910_P1_NBITER_NF_8PSK_3_4 0xfa0d00ff -+ -+/*P1_NBITER_NF15*/ -+#define RSTV0910_P1_NBITER_NF15 0xfa0e -+#define FSTV0910_P1_NBITER_NF_8PSK_5_6 0xfa0e00ff -+ -+/*P1_NBITER_NF16*/ -+#define RSTV0910_P1_NBITER_NF16 0xfa0f -+#define FSTV0910_P1_NBITER_NF_8PSK_8_9 0xfa0f00ff -+ -+/*P1_NBITER_NF17*/ -+#define RSTV0910_P1_NBITER_NF17 0xfa10 -+#define FSTV0910_P1_NBITER_NF_8PSK_9_10 0xfa1000ff -+ -+/*GAINLLR_NF4*/ -+#define RSTV0910_GAINLLR_NF4 0xfa43 -+#define FSTV0910_GAINLLR_NF_QPSK_1_2 0xfa43007f -+ -+/*GAINLLR_NF5*/ -+#define RSTV0910_GAINLLR_NF5 0xfa44 -+#define FSTV0910_GAINLLR_NF_QPSK_3_5 0xfa44007f -+ -+/*GAINLLR_NF6*/ -+#define RSTV0910_GAINLLR_NF6 0xfa45 -+#define FSTV0910_GAINLLR_NF_QPSK_2_3 0xfa45007f -+ -+/*GAINLLR_NF7*/ -+#define RSTV0910_GAINLLR_NF7 0xfa46 -+#define FSTV0910_GAINLLR_NF_QPSK_3_4 0xfa46007f -+ -+/*GAINLLR_NF8*/ -+#define RSTV0910_GAINLLR_NF8 0xfa47 -+#define FSTV0910_GAINLLR_NF_QPSK_4_5 0xfa47007f -+ -+/*GAINLLR_NF9*/ -+#define RSTV0910_GAINLLR_NF9 0xfa48 -+#define FSTV0910_GAINLLR_NF_QPSK_5_6 0xfa48007f -+ -+/*GAINLLR_NF10*/ -+#define RSTV0910_GAINLLR_NF10 0xfa49 -+#define FSTV0910_GAINLLR_NF_QPSK_8_9 0xfa49007f -+ -+/*GAINLLR_NF11*/ -+#define RSTV0910_GAINLLR_NF11 0xfa4a -+#define FSTV0910_GAINLLR_NF_QPSK_9_10 0xfa4a007f -+ -+/*GAINLLR_NF12*/ -+#define RSTV0910_GAINLLR_NF12 0xfa4b -+#define FSTV0910_GAINLLR_NF_8PSK_3_5 0xfa4b007f -+ -+/*GAINLLR_NF13*/ -+#define RSTV0910_GAINLLR_NF13 0xfa4c -+#define FSTV0910_GAINLLR_NF_8PSK_2_3 0xfa4c007f -+ -+/*GAINLLR_NF14*/ -+#define RSTV0910_GAINLLR_NF14 0xfa4d -+#define FSTV0910_GAINLLR_NF_8PSK_3_4 0xfa4d007f -+ -+/*GAINLLR_NF15*/ -+#define RSTV0910_GAINLLR_NF15 0xfa4e -+#define FSTV0910_GAINLLR_NF_8PSK_5_6 0xfa4e007f -+ -+/*GAINLLR_NF16*/ -+#define RSTV0910_GAINLLR_NF16 0xfa4f -+#define FSTV0910_GAINLLR_NF_8PSK_8_9 0xfa4f007f -+ -+/*GAINLLR_NF17*/ -+#define RSTV0910_GAINLLR_NF17 0xfa50 -+#define FSTV0910_GAINLLR_NF_8PSK_9_10 0xfa50007f -+ -+/*CFGEXT*/ -+#define RSTV0910_CFGEXT 0xfa80 -+#define FSTV0910_BYPFIFOBCH 0xfa800080 -+#define FSTV0910_BYPBCH 0xfa800040 -+#define FSTV0910_BYPLDPC 0xfa800020 -+#define FSTV0910_BYPFIFOBCHF 0xfa800010 -+#define FSTV0910_INVLLRSIGN 0xfa800008 -+#define FSTV0910_SHORTMULT 0xfa800004 -+#define FSTV0910_ENSTOPDEC 0xfa800002 -+ -+/*GENCFG*/ -+#define RSTV0910_GENCFG 0xfa86 -+#define FSTV0910_LEG_ITER 0xfa860040 -+#define FSTV0910_NOSHFRD1 0xfa860020 -+#define FSTV0910_BROADCAST 0xfa860010 -+#define FSTV0910_NOSHFRD2 0xfa860008 -+#define FSTV0910_BCHERRFLAG 0xfa860004 -+#define FSTV0910_CROSSINPUT 0xfa860002 -+#define FSTV0910_DDEMOD 0xfa860001 -+ -+/*LDPCERR1*/ -+#define RSTV0910_LDPCERR1 0xfa96 -+#define FSTV0910_LDPC_ERRORS1 0xfa9600ff -+ -+/*LDPCERR0*/ -+#define RSTV0910_LDPCERR0 0xfa97 -+#define FSTV0910_LDPC_ERRORS0 0xfa9700ff -+ -+/*BCHERR*/ -+#define RSTV0910_BCHERR 0xfa98 -+#define FSTV0910_ERRORFLAG 0xfa980010 -+#define FSTV0910_BCH_ERRORS_COUNTER 0xfa98000f -+ -+/*P1_MAXEXTRAITER*/ -+#define RSTV0910_P1_MAXEXTRAITER 0xfab1 -+#define FSTV0910_P1_MAX_EXTRA_ITER 0xfab100ff -+ -+/*P2_MAXEXTRAITER*/ -+#define RSTV0910_P2_MAXEXTRAITER 0xfab6 -+#define FSTV0910_P2_MAX_EXTRA_ITER 0xfab600ff -+ -+/*P1_STATUSITER*/ -+#define RSTV0910_P1_STATUSITER 0xfabc -+#define FSTV0910_P1_STATUS_ITER 0xfabc00ff -+ -+/*P1_STATUSMAXITER*/ -+#define RSTV0910_P1_STATUSMAXITER 0xfabd -+#define FSTV0910_P1_STATUS_MAX_ITER 0xfabd00ff -+ -+/*P2_STATUSITER*/ -+#define RSTV0910_P2_STATUSITER 0xfabe -+#define FSTV0910_P2_STATUS_ITER 0xfabe00ff -+ -+/*P2_STATUSMAXITER*/ -+#define RSTV0910_P2_STATUSMAXITER 0xfabf -+#define FSTV0910_P2_STATUS_MAX_ITER 0xfabf00ff -+ -+/*P2_NBITER_NF4*/ -+#define RSTV0910_P2_NBITER_NF4 0xfac3 -+#define FSTV0910_P2_NBITER_NF_QPSK_1_2 0xfac300ff -+ -+/*P2_NBITER_NF5*/ -+#define RSTV0910_P2_NBITER_NF5 0xfac4 -+#define FSTV0910_P2_NBITER_NF_QPSK_3_5 0xfac400ff -+ -+/*P2_NBITER_NF6*/ -+#define RSTV0910_P2_NBITER_NF6 0xfac5 -+#define FSTV0910_P2_NBITER_NF_QPSK_2_3 0xfac500ff -+ -+/*P2_NBITER_NF7*/ -+#define RSTV0910_P2_NBITER_NF7 0xfac6 -+#define FSTV0910_P2_NBITER_NF_QPSK_3_4 0xfac600ff -+ -+/*P2_NBITER_NF8*/ -+#define RSTV0910_P2_NBITER_NF8 0xfac7 -+#define FSTV0910_P2_NBITER_NF_QPSK_4_5 0xfac700ff -+ -+/*P2_NBITER_NF9*/ -+#define RSTV0910_P2_NBITER_NF9 0xfac8 -+#define FSTV0910_P2_NBITER_NF_QPSK_5_6 0xfac800ff -+ -+/*P2_NBITER_NF10*/ -+#define RSTV0910_P2_NBITER_NF10 0xfac9 -+#define FSTV0910_P2_NBITER_NF_QPSK_8_9 0xfac900ff -+ -+/*P2_NBITER_NF11*/ -+#define RSTV0910_P2_NBITER_NF11 0xfaca -+#define FSTV0910_P2_NBITER_NF_QPSK_9_10 0xfaca00ff -+ -+/*P2_NBITER_NF12*/ -+#define RSTV0910_P2_NBITER_NF12 0xfacb -+#define FSTV0910_P2_NBITER_NF_8PSK_3_5 0xfacb00ff -+ -+/*P2_NBITER_NF13*/ -+#define RSTV0910_P2_NBITER_NF13 0xfacc -+#define FSTV0910_P2_NBITER_NF_8PSK_2_3 0xfacc00ff -+ -+/*P2_NBITER_NF14*/ -+#define RSTV0910_P2_NBITER_NF14 0xfacd -+#define FSTV0910_P2_NBITER_NF_8PSK_3_4 0xfacd00ff -+ -+/*P2_NBITER_NF15*/ -+#define RSTV0910_P2_NBITER_NF15 0xface -+#define FSTV0910_P2_NBITER_NF_8PSK_5_6 0xface00ff -+ -+/*P2_NBITER_NF16*/ -+#define RSTV0910_P2_NBITER_NF16 0xfacf -+#define FSTV0910_P2_NBITER_NF_8PSK_8_9 0xfacf00ff -+ -+/*P2_NBITER_NF17*/ -+#define RSTV0910_P2_NBITER_NF17 0xfad0 -+#define FSTV0910_P2_NBITER_NF_8PSK_9_10 0xfad000ff -+ -+/*TSTRES0*/ -+#define RSTV0910_TSTRES0 0xff11 -+#define FSTV0910_FRESFEC 0xff110080 -+#define FSTV0910_FRESTS 0xff110040 -+#define FSTV0910_FRESVIT1 0xff110020 -+#define FSTV0910_FRESVIT2 0xff110010 -+#define FSTV0910_FRESSYM1 0xff110008 -+#define FSTV0910_FRESSYM2 0xff110004 -+#define FSTV0910_FRESMAS 0xff110002 -+#define FSTV0910_FRESINT 0xff110001 -+ -+/*P2_TCTL4*/ -+#define RSTV0910_P2_TCTL4 0xff28 -+#define FSTV0910_P2_CFR2TOCFR1_DVBS1 0xff2800c0 -+#define FSTV0910_P2_TSTINV_PHERR 0xff280020 -+#define FSTV0910_P2_EN_PLHCALC 0xff280010 -+#define FSTV0910_P2_TETA3L_RSTTETA3D 0xff280008 -+#define FSTV0910_P2_DIS_FORCEBETA2 0xff280004 -+#define FSTV0910_P2_CAR3_NOTRACEBACK 0xff280002 -+#define FSTV0910_P2_CAR3_NOFORWARD 0xff280001 -+ -+/*P1_TCTL4*/ -+#define RSTV0910_P1_TCTL4 0xff48 -+#define FSTV0910_P1_CFR2TOCFR1_DVBS1 0xff4800c0 -+#define FSTV0910_P1_TSTINV_PHERR 0xff480020 -+#define FSTV0910_P1_EN_PLHCALC 0xff480010 -+#define FSTV0910_P1_TETA3L_RSTTETA3D 0xff480008 -+#define FSTV0910_P1_DIS_FORCEBETA2 0xff480004 -+#define FSTV0910_P1_CAR3_NOTRACEBACK 0xff480002 -+#define FSTV0910_P1_CAR3_NOFORWARD 0xff480001 -+ -+#define STV0910_NBREGS 735 -+#define STV0910_NBFIELDS 1776 -diff --git a/drivers/media/dvb-frontends/stv6111.c b/drivers/media/dvb-frontends/stv6111.c -new file mode 100644 -index 0000000..827fe48 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv6111.c -@@ -0,0 +1,684 @@ -+/* -+ * Driver for the ST STV6111 tuner -+ * -+ * Copyright (C) 2014 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#undef pr_fmt -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+ -+struct stv { -+ struct i2c_adapter *i2c; -+ u8 adr; -+ -+ u8 reg[11]; -+ u32 ref_freq; -+ u32 Frequency; -+}; -+ -+struct SLookup { -+ s16 Value; -+ u16 RegValue; -+}; -+ -+static struct SLookup LNAGain_NF_LookUp[] = { -+ /*Gain *100dB*/ /*Reg*/ -+ { 2572, 0 }, -+ { 2575, 1 }, -+ { 2580, 2 }, -+ { 2588, 3 }, -+ { 2596, 4 }, -+ { 2611, 5 }, -+ { 2633, 6 }, -+ { 2664, 7 }, -+ { 2701, 8 }, -+ { 2753, 9 }, -+ { 2816, 10 }, -+ { 2902, 11 }, -+ { 2995, 12 }, -+ { 3104, 13 }, -+ { 3215, 14 }, -+ { 3337, 15 }, -+ { 3492, 16 }, -+ { 3614, 17 }, -+ { 3731, 18 }, -+ { 3861, 19 }, -+ { 3988, 20 }, -+ { 4124, 21 }, -+ { 4253, 22 }, -+ { 4386, 23 }, -+ { 4505, 24 }, -+ { 4623, 25 }, -+ { 4726, 26 }, -+ { 4821, 27 }, -+ { 4903, 28 }, -+ { 4979, 29 }, -+ { 5045, 30 }, -+ { 5102, 31 } -+}; -+ -+static struct SLookup LNAGain_IIP3_LookUp[] = { -+ /*Gain *100dB*/ /*reg*/ -+ { 1548, 0 }, -+ { 1552, 1 }, -+ { 1569, 2 }, -+ { 1565, 3 }, -+ { 1577, 4 }, -+ { 1594, 5 }, -+ { 1627, 6 }, -+ { 1656, 7 }, -+ { 1700, 8 }, -+ { 1748, 9 }, -+ { 1805, 10 }, -+ { 1896, 11 }, -+ { 1995, 12 }, -+ { 2113, 13 }, -+ { 2233, 14 }, -+ { 2366, 15 }, -+ { 2543, 16 }, -+ { 2687, 17 }, -+ { 2842, 18 }, -+ { 2999, 19 }, -+ { 3167, 20 }, -+ { 3342, 21 }, -+ { 3507, 22 }, -+ { 3679, 23 }, -+ { 3827, 24 }, -+ { 3970, 25 }, -+ { 4094, 26 }, -+ { 4210, 27 }, -+ { 4308, 28 }, -+ { 4396, 29 }, -+ { 4468, 30 }, -+ { 4535, 31 } -+}; -+ -+static struct SLookup Gain_RFAGC_LookUp[] = { -+ /*Gain *100dB*/ /*reg*/ -+ { 4870, 0x3000 }, -+ { 4850, 0x3C00 }, -+ { 4800, 0x4500 }, -+ { 4750, 0x4800 }, -+ { 4700, 0x4B00 }, -+ { 4650, 0x4D00 }, -+ { 4600, 0x4F00 }, -+ { 4550, 0x5100 }, -+ { 4500, 0x5200 }, -+ { 4420, 0x5500 }, -+ { 4316, 0x5800 }, -+ { 4200, 0x5B00 }, -+ { 4119, 0x5D00 }, -+ { 3999, 0x6000 }, -+ { 3950, 0x6100 }, -+ { 3876, 0x6300 }, -+ { 3755, 0x6600 }, -+ { 3641, 0x6900 }, -+ { 3567, 0x6B00 }, -+ { 3425, 0x6F00 }, -+ { 3350, 0x7100 }, -+ { 3236, 0x7400 }, -+ { 3118, 0x7700 }, -+ { 3004, 0x7A00 }, -+ { 2917, 0x7C00 }, -+ { 2776, 0x7F00 }, -+ { 2635, 0x8200 }, -+ { 2516, 0x8500 }, -+ { 2406, 0x8800 }, -+ { 2290, 0x8B00 }, -+ { 2170, 0x8E00 }, -+ { 2073, 0x9100 }, -+ { 1949, 0x9400 }, -+ { 1836, 0x9700 }, -+ { 1712, 0x9A00 }, -+ { 1631, 0x9C00 }, -+ { 1515, 0x9F00 }, -+ { 1400, 0xA200 }, -+ { 1323, 0xA400 }, -+ { 1203, 0xA700 }, -+ { 1091, 0xAA00 }, -+ { 1011, 0xAC00 }, -+ { 904, 0xAF00 }, -+ { 787, 0xB200 }, -+ { 685, 0xB500 }, -+ { 571, 0xB800 }, -+ { 464, 0xBB00 }, -+ { 374, 0xBE00 }, -+ { 275, 0xC200 }, -+ { 181, 0xC600 }, -+ { 102, 0xCC00 }, -+ { 49, 0xD900 } -+}; -+ -+/* -+ * This table is 6 dB too low comapred to the others (probably created with -+ * a different BB_MAG setting) -+*/ -+static struct SLookup Gain_Channel_AGC_NF_LookUp[] = { -+ /*Gain *100dB*/ /*reg*/ -+ { 7082, 0x3000 }, -+ { 7052, 0x4000 }, -+ { 7007, 0x4600 }, -+ { 6954, 0x4A00 }, -+ { 6909, 0x4D00 }, -+ { 6833, 0x5100 }, -+ { 6753, 0x5400 }, -+ { 6659, 0x5700 }, -+ { 6561, 0x5A00 }, -+ { 6472, 0x5C00 }, -+ { 6366, 0x5F00 }, -+ { 6259, 0x6100 }, -+ { 6151, 0x6400 }, -+ { 6026, 0x6700 }, -+ { 5920, 0x6900 }, -+ { 5835, 0x6B00 }, -+ { 5770, 0x6C00 }, -+ { 5681, 0x6E00 }, -+ { 5596, 0x7000 }, -+ { 5503, 0x7200 }, -+ { 5429, 0x7300 }, -+ { 5319, 0x7500 }, -+ { 5220, 0x7700 }, -+ { 5111, 0x7900 }, -+ { 4983, 0x7B00 }, -+ { 4876, 0x7D00 }, -+ { 4755, 0x7F00 }, -+ { 4635, 0x8100 }, -+ { 4499, 0x8300 }, -+ { 4405, 0x8500 }, -+ { 4323, 0x8600 }, -+ { 4233, 0x8800 }, -+ { 4156, 0x8A00 }, -+ { 4038, 0x8C00 }, -+ { 3935, 0x8E00 }, -+ { 3823, 0x9000 }, -+ { 3712, 0x9200 }, -+ { 3601, 0x9500 }, -+ { 3511, 0x9700 }, -+ { 3413, 0x9900 }, -+ { 3309, 0x9B00 }, -+ { 3213, 0x9D00 }, -+ { 3088, 0x9F00 }, -+ { 2992, 0xA100 }, -+ { 2878, 0xA400 }, -+ { 2769, 0xA700 }, -+ { 2645, 0xAA00 }, -+ { 2538, 0xAD00 }, -+ { 2441, 0xB000 }, -+ { 2350, 0xB600 }, -+ { 2237, 0xBA00 }, -+ { 2137, 0xBF00 }, -+ { 2039, 0xC500 }, -+ { 1938, 0xDF00 }, -+ { 1927, 0xFF00 } -+}; -+ -+static struct SLookup Gain_Channel_AGC_IIP3_LookUp[] = { -+ /*Gain *100dB*/ /*reg*/ -+ { 7070, 0x3000 }, -+ { 7028, 0x4000 }, -+ { 7019, 0x4600 }, -+ { 6900, 0x4A00 }, -+ { 6811, 0x4D00 }, -+ { 6763, 0x5100 }, -+ { 6690, 0x5400 }, -+ { 6644, 0x5700 }, -+ { 6617, 0x5A00 }, -+ { 6598, 0x5C00 }, -+ { 6462, 0x5F00 }, -+ { 6348, 0x6100 }, -+ { 6197, 0x6400 }, -+ { 6154, 0x6700 }, -+ { 6098, 0x6900 }, -+ { 5893, 0x6B00 }, -+ { 5812, 0x6C00 }, -+ { 5773, 0x6E00 }, -+ { 5723, 0x7000 }, -+ { 5661, 0x7200 }, -+ { 5579, 0x7300 }, -+ { 5460, 0x7500 }, -+ { 5308, 0x7700 }, -+ { 5099, 0x7900 }, -+ { 4910, 0x7B00 }, -+ { 4800, 0x7D00 }, -+ { 4785, 0x7F00 }, -+ { 4635, 0x8100 }, -+ { 4466, 0x8300 }, -+ { 4314, 0x8500 }, -+ { 4295, 0x8600 }, -+ { 4144, 0x8800 }, -+ { 3920, 0x8A00 }, -+ { 3889, 0x8C00 }, -+ { 3771, 0x8E00 }, -+ { 3655, 0x9000 }, -+ { 3446, 0x9200 }, -+ { 3298, 0x9500 }, -+ { 3083, 0x9700 }, -+ { 3015, 0x9900 }, -+ { 2833, 0x9B00 }, -+ { 2746, 0x9D00 }, -+ { 2632, 0x9F00 }, -+ { 2598, 0xA100 }, -+ { 2480, 0xA400 }, -+ { 2236, 0xA700 }, -+ { 2171, 0xAA00 }, -+ { 2060, 0xAD00 }, -+ { 1999, 0xB000 }, -+ { 1974, 0xB600 }, -+ { 1820, 0xBA00 }, -+ { 1741, 0xBF00 }, -+ { 1655, 0xC500 }, -+ { 1444, 0xDF00 }, -+ { 1325, 0xFF00 }, -+}; -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ pr_err("i2c_read error\n"); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_err("i2c_write error\n"); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int write_regs(struct stv *state, int reg, int len) -+{ -+ u8 d[12]; -+ -+ memcpy(&d[1], &state->reg[reg], len); -+ d[0] = reg; -+ return i2c_write(state->i2c, state->adr, d, len + 1); -+} -+ -+static int write_reg(struct stv *state, u8 reg, u8 val) -+{ -+ u8 d[2] = {reg, val}; -+ -+ return i2c_write(state->i2c, state->adr, d, 2); -+} -+ -+static int read_reg(struct stv *state, u8 reg, u8 *val) -+{ -+ return i2c_read(state->i2c, state->adr, ®, 1, val, 1); -+} -+ -+static int wait_for_call_done(struct stv *state, u8 mask) -+{ -+ int status = 0; -+ u32 LockRetryCount = 10; -+ -+ while (LockRetryCount > 0) { -+ u8 Status; -+ -+ status = read_reg(state, 9, &Status); -+ if (status < 0) -+ return status; -+ -+ if ((Status & mask) == 0) -+ break; -+ usleep_range(4000, 6000); -+ LockRetryCount -= 1; -+ -+ status = -EIO; -+ } -+ return status; -+} -+ -+static void init_state(struct stv *state) -+{ -+ u32 clkdiv = 0; -+ u32 agcmode = 0; -+ u32 agcref = 2; -+ u32 agcset = 0xffffffff; -+ u32 bbmode = 0xffffffff; -+ -+ state->reg[0] = 0x08; -+ state->reg[1] = 0x41; -+ state->reg[2] = 0x8f; -+ state->reg[3] = 0x00; -+ state->reg[4] = 0xce; -+ state->reg[5] = 0x54; -+ state->reg[6] = 0x55; -+ state->reg[7] = 0x45; -+ state->reg[8] = 0x46; -+ state->reg[9] = 0xbd; -+ state->reg[10] = 0x11; -+ -+ state->ref_freq = 16000; -+ -+ if (clkdiv <= 3) -+ state->reg[0x00] |= (clkdiv & 0x03); -+ if (agcmode <= 3) { -+ state->reg[0x03] |= (agcmode << 5); -+ if (agcmode == 0x01) -+ state->reg[0x01] |= 0x30; -+ } -+ if (bbmode <= 3) -+ state->reg[0x01] = (state->reg[0x01] & ~0x30) | (bbmode << 4); -+ if (agcref <= 7) -+ state->reg[0x03] |= agcref; -+ if (agcset <= 31) -+ state->reg[0x02] = (state->reg[0x02] & ~0x1F) | agcset | 0x40; -+} -+ -+static int attach_init(struct stv *state) -+{ -+ if (write_regs(state, 0, 11)) -+ return -ENODEV; -+ return 0; -+} -+ -+static int release(struct dvb_frontend *fe) -+{ -+ kfree(fe->tuner_priv); -+ fe->tuner_priv = NULL; -+ return 0; -+} -+ -+static int set_bandwidth(struct dvb_frontend *fe, u32 CutOffFrequency) -+{ -+ struct stv *state = fe->tuner_priv; -+ u32 index = (CutOffFrequency + 999999) / 1000000; -+ -+ if (index < 6) -+ index = 6; -+ if (index > 50) -+ index = 50; -+ if ((state->reg[0x08] & ~0xFC) == ((index-6) << 2)) -+ return 0; -+ -+ state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index-6) << 2); -+ state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x08; -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ write_regs(state, 0x08, 2); -+ wait_for_call_done(state, 0x08); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ return 0; -+} -+ -+static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency) -+{ -+ u32 index = (CutOffFrequency + 999999) / 1000000; -+ u32 Frequency = (LocalFrequency + 500) / 1000; -+ u32 p = 1, psel = 0, fvco, div, frac; -+ u8 Icp, tmp; -+ -+ if (index < 6) -+ index = 6; -+ if (index > 50) -+ index = 50; -+ -+ if (Frequency <= 1300000) { -+ p = 4; -+ psel = 1; -+ } else { -+ p = 2; -+ psel = 0; -+ } -+ fvco = Frequency * p; -+ div = fvco / state->ref_freq; -+ frac = fvco % state->ref_freq; -+ frac = MulDiv32(frac, 0x40000, state->ref_freq); -+ -+ Icp = 0; -+ if (fvco < 2700000) -+ Icp = 0; -+ else if (fvco < 2950000) -+ Icp = 1; -+ else if (fvco < 3300000) -+ Icp = 2; -+ else if (fvco < 3700000) -+ Icp = 3; -+ else if (fvco < 4200000) -+ Icp = 5; -+ else if (fvco < 4800000) -+ Icp = 6; -+ else -+ Icp = 7; -+ -+ state->reg[0x02] |= 0x80; /* LNA IIP3 Mode */ -+ -+ state->reg[0x03] = (state->reg[0x03] & ~0x80) | (psel << 7); -+ state->reg[0x04] = (div & 0xFF); -+ state->reg[0x05] = (((div >> 8) & 0x01) | ((frac & 0x7F) << 1)) & 0xff; -+ state->reg[0x06] = ((frac >> 7) & 0xFF); -+ state->reg[0x07] = (state->reg[0x07] & ~0x07) | ((frac >> 15) & 0x07); -+ state->reg[0x07] = (state->reg[0x07] & ~0xE0) | (Icp << 5); -+ -+ state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index - 6) << 2); -+ /* Start cal vco,CF */ -+ state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x0C; -+ write_regs(state, 2, 8); -+ -+ wait_for_call_done(state, 0x0C); -+ -+ usleep_range(10000, 12000); -+ -+ read_reg(state, 0x03, &tmp); -+ if (tmp & 0x10) { -+ state->reg[0x02] &= ~0x80; /* LNA NF Mode */ -+ write_regs(state, 2, 1); -+ } -+ read_reg(state, 0x08, &tmp); -+ -+ state->Frequency = Frequency; -+ -+ return 0; -+} -+ -+static int set_params(struct dvb_frontend *fe) -+{ -+ struct stv *state = fe->tuner_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ u32 freq, symb, cutoff; -+ -+ if (p->delivery_system != SYS_DVBS && p->delivery_system != SYS_DVBS2) -+ return -EINVAL; -+ -+ freq = p->frequency * 1000; -+ symb = p->symbol_rate; -+ cutoff = 5000000 + MulDiv32(p->symbol_rate, 135, 200); -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ set_lof(state, freq, cutoff); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ return 0; -+} -+ -+static s32 TableLookup(struct SLookup *Table, int TableSize, u16 RegValue) -+{ -+ s32 Gain; -+ s32 RegDiff; -+ int imin = 0; -+ int imax = TableSize - 1; -+ int i; -+ -+ /* Assumes Table[0].RegValue < Table[imax].RegValue */ -+ if (RegValue <= Table[0].RegValue) -+ Gain = Table[0].Value; -+ else if (RegValue >= Table[imax].RegValue) -+ Gain = Table[imax].Value; -+ else { -+ while (imax-imin > 1) { -+ i = (imax + imin) / 2; -+ if ((Table[imin].RegValue <= RegValue) && -+ (RegValue <= Table[i].RegValue)) -+ imax = i; -+ else -+ imin = i; -+ } -+ RegDiff = Table[imax].RegValue - Table[imin].RegValue; -+ Gain = Table[imin].Value; -+ if (RegDiff != 0) -+ Gain += ((s32) (RegValue - Table[imin].RegValue) * -+ (s32)(Table[imax].Value -+ - Table[imin].Value))/(RegDiff); -+ } -+ return Gain; -+} -+ -+static int get_rf_strength(struct dvb_frontend *fe, u16 *st) -+{ -+ struct stv *state = fe->tuner_priv; -+ u16 RFAgc = *st; -+ s32 Gain; -+ -+ if ((state->reg[0x03] & 0x60) == 0) { -+ /* RF Mode, Read AGC ADC */ -+ u8 Reg = 0; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ write_reg(state, 0x02, state->reg[0x02] | 0x20); -+ read_reg(state, 2, &Reg); -+ if (Reg & 0x20) -+ read_reg(state, 2, &Reg); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ -+ if ((state->reg[0x02] & 0x80) == 0) -+ /* NF */ -+ Gain = TableLookup(LNAGain_NF_LookUp, -+ ARRAY_SIZE(LNAGain_NF_LookUp), Reg & 0x1F); -+ else -+ /* IIP3 */ -+ Gain = TableLookup(LNAGain_IIP3_LookUp, -+ ARRAY_SIZE(LNAGain_IIP3_LookUp), Reg & 0x1F); -+ -+ Gain += TableLookup(Gain_RFAGC_LookUp, -+ ARRAY_SIZE(Gain_RFAGC_LookUp), RFAgc); -+ Gain -= 2400; -+ } else { -+ /* Channel Mode */ -+ if ((state->reg[0x02] & 0x80) == 0) { -+ /* NF */ -+ Gain = TableLookup(Gain_Channel_AGC_NF_LookUp, -+ ARRAY_SIZE(Gain_Channel_AGC_NF_LookUp), RFAgc); -+ Gain += 600; -+ } else { -+ /* IIP3 */ -+ Gain = TableLookup(Gain_Channel_AGC_IIP3_LookUp, -+ ARRAY_SIZE(Gain_Channel_AGC_IIP3_LookUp), -+ RFAgc); -+ } -+ } -+ -+ if (state->Frequency > 0) -+ /* Tilt correction ( 0.00016 dB/MHz ) */ -+ Gain -= ((((s32)(state->Frequency / 1000) - 1550) * 2) / 12); -+ -+ /* + (BBGain * 10); */ -+ Gain += (s32)((state->reg[0x01] & 0xC0) >> 6) * 600 - 1300; -+ -+ if (Gain < 0) -+ Gain = 0; -+ else if (Gain > 10000) -+ Gain = 10000; -+ -+ *st = 10000 - Gain; -+ -+ return 0; -+} -+ -+static struct dvb_tuner_ops tuner_ops = { -+ .info = { -+ .name = "STV6111", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_step = 0 -+ }, -+ .set_params = set_params, -+ .release = release, -+ .get_rf_strength = get_rf_strength, -+ .set_bandwidth = set_bandwidth, -+}; -+ -+struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr) -+{ -+ struct stv *state; -+ int stat; -+ -+ state = kzalloc(sizeof(struct stv), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ state->adr = adr; -+ state->i2c = i2c; -+ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); -+ init_state(state); -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ stat = attach_init(state); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ if (stat < 0) { -+ kfree(state); -+ return 0; -+ } -+ fe->tuner_priv = state; -+ return fe; -+} -+EXPORT_SYMBOL_GPL(stv6111_attach); -+ -+MODULE_DESCRIPTION("STV6111 driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/stv6111.h b/drivers/media/dvb-frontends/stv6111.h -new file mode 100644 -index 0000000..55b5ddc ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv6111.h -@@ -0,0 +1,20 @@ -+#ifndef _STV6111_H_ -+#define _STV6111_H_ -+ -+#if IS_REACHABLE(CONFIG_DVB_STV6111) -+ -+extern struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr); -+ -+#else -+ -+static inline struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr); -+{ -+ pr_warn("%s: Driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif /* CONFIG_DVB_STV6111 */ -+ -+#endif /* _STV6111_H_ */ -diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig -index 44e5dc1..eed08a4 100644 ---- a/drivers/media/pci/ddbridge/Kconfig -+++ b/drivers/media/pci/ddbridge/Kconfig -@@ -1,11 +1,20 @@ - config DVB_DDBRIDGE - tristate "Digital Devices bridge support" - depends on DVB_CORE && PCI && I2C -+ select STAGING_MEDIA -+ select DVB_CXD2099 - select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_STV6111 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_STV0910 if MEDIA_SUBDRV_AUTOSELECT - select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT -+ select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT - select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_STV0367DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_MXL5XX if MEDIA_SUBDRV_AUTOSELECT - ---help--- - Support for cards with the Digital Devices PCI express bridge: - - Octopus PCIe Bridge -@@ -13,6 +22,24 @@ config DVB_DDBRIDGE - - Octopus LE - - DuoFlex S2 Octopus - - DuoFlex CT Octopus -- - cineS2(v6) -+ - cineS2(v6.x) -+ - cineCT(v6.x, v7) -+ - Max A8 C2/T2 -+ - Max S8 - - Say Y if you own such a card and want to use it. -+ -+config DVB_DDBRIDGE_MSIENABLE -+ bool "Enable Message Signaled Interrupts (MSI) per default (EXPERIMENTAL)" -+ depends on DVB_DDBRIDGE -+ depends on PCI_MSI -+ default n -+ ---help--- -+ Use PCI MSI (Message Signaled Interrupts) per default. Enabling this -+ might lead to I2C errors originating from the bridge in conjunction -+ with certain SATA controllers, requiring a reload of the ddbridge -+ module. MSI can still be disabled by passing msi=0 as option, as -+ this will just change the msi option default value. -+ -+ If you're unsure, concerned about stability and don't want to pass -+ module options in case of troubles, say N. -diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile -index 7446c8b..28e89f0 100644 ---- a/drivers/media/pci/ddbridge/Makefile -+++ b/drivers/media/pci/ddbridge/Makefile -@@ -2,9 +2,7 @@ - # Makefile for the ddbridge device driver - # - --ddbridge-objs := ddbridge-core.o -- --obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o -+obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o octonet.o - - ccflags-y += -Idrivers/media/dvb-core/ - ccflags-y += -Idrivers/media/dvb-frontends/ -diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c -index 47def73..82c1938 100644 ---- a/drivers/media/pci/ddbridge/ddbridge-core.c -+++ b/drivers/media/pci/ddbridge/ddbridge-core.c -@@ -1,7 +1,10 @@ - /* -- * ddbridge.c: Digital Devices PCIe bridge driver -+ * ddbridge-core.c: Digital Devices bridge core functions -+ * -+ * Copyright (C) 2010-2015 Digital Devices GmbH -+ * Marcus Metzler -+ * Ralph Metzler - * -- * Copyright (C) 2010-2011 Digital Devices GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -21,306 +24,289 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include "ddbridge.h" -- --#include "ddbridge-regs.h" -- --#include "tda18271c2dd.h" --#include "stv6110x.h" --#include "stv090x.h" --#include "lnbh24.h" --#include "drxk.h" -+DEFINE_MUTEX(redirect_lock); -+ -+static int ci_bitrate = 72000; -+module_param(ci_bitrate, int, 0444); -+MODULE_PARM_DESC(ci_bitrate, " Bitrate for output to CI."); -+ -+static int ts_loop = -1; -+module_param(ts_loop, int, 0444); -+MODULE_PARM_DESC(ts_loop, "TS in/out test loop on port ts_loop"); -+ -+static int vlan; -+module_param(vlan, int, 0444); -+MODULE_PARM_DESC(vlan, "VLAN and QoS IDs enabled"); -+ -+static int tt; -+module_param(tt, int, 0444); -+MODULE_PARM_DESC(tt, ""); -+ -+static int fmode; -+module_param(fmode, int, 0444); -+MODULE_PARM_DESC(fmode, "frontend emulation mode"); -+ -+static int old_quattro; -+module_param(old_quattro, int, 0444); -+MODULE_PARM_DESC(old_quattro, "old quattro LNB input order "); -+ -+#define DDB_MAX_ADAPTER 64 -+static struct ddb *ddbs[DDB_MAX_ADAPTER]; - - DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - --/* MSI had problems with lost interrupts, fixed but needs testing */ --#undef CONFIG_PCI_MSI -+#include "ddbridge-mod.c" -+#include "ddbridge-i2c.c" -+#include "ddbridge-ns.c" - --/******************************************************************************/ - --static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) -+static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma) - { -- struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -- .buf = val, .len = 1 } }; -- return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; --} -+ u32 i, base; -+ u64 mem; - --static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) --{ -- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -- .buf = ®, .len = 1 }, -- {.addr = adr, .flags = I2C_M_RD, -- .buf = val, .len = 1 } }; -- return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+ if (!dma) -+ return; -+ base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100; -+ for (i = 0; i < dma->num; i++) { -+ mem = dma->pbuf[i]; -+ ddbwritel(dev, mem & 0xffffffff, base + i * 8); -+ ddbwritel(dev, mem >> 32, base + i * 8 + 4); -+ } -+ dma->bufreg = (dma->div << 16) | -+ ((dma->num & 0x1f) << 11) | -+ ((dma->size >> 7) & 0x7ff); - } - --static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, -- u16 reg, u8 *val) -+static void ddb_set_dma_tables(struct ddb *dev) - { -- u8 msg[2] = {reg>>8, reg&0xff}; -- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -- .buf = msg, .len = 2}, -- {.addr = adr, .flags = I2C_M_RD, -- .buf = val, .len = 1} }; -- return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+ u32 i; -+ -+ for (i = 0; i < dev->link[0].info->port_num * 2; i++) -+ ddb_set_dma_table(dev, dev->input[i].dma); -+ for (i = 0; i < dev->link[0].info->port_num; i++) -+ ddb_set_dma_table(dev, dev->output[i].dma); - } - --static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) --{ -- struct ddb *dev = i2c->dev; -- long stat; -- u32 val; - -- i2c->done = 0; -- ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); -- stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); -- if (stat == 0) { -- printk(KERN_ERR "I2C timeout\n"); -- { /* MSI debugging*/ -- u32 istat = ddbreadl(INTERRUPT_STATUS); -- printk(KERN_ERR "IRS %08x\n", istat); -- ddbwritel(istat, INTERRUPT_ACK); -- } -- return -EIO; -- } -- val = ddbreadl(i2c->regs+I2C_COMMAND); -- if (val & 0x70000) -- return -EIO; -- return 0; --} -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ - --static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, -- struct i2c_msg msg[], int num) -+static void ddb_redirect_dma(struct ddb *dev, -+ struct ddb_dma *sdma, -+ struct ddb_dma *ddma) - { -- struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter); -- struct ddb *dev = i2c->dev; -- u8 addr = 0; -- -- if (num) -- addr = msg[0].addr; -+ u32 i, base; -+ u64 mem; - -- if (num == 2 && msg[1].flags & I2C_M_RD && -- !(msg[0].flags & I2C_M_RD)) { -- memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, -- msg[0].buf, msg[0].len); -- ddbwritel(msg[0].len|(msg[1].len << 16), -- i2c->regs+I2C_TASKLENGTH); -- if (!ddb_i2c_cmd(i2c, addr, 1)) { -- memcpy_fromio(msg[1].buf, -- dev->regs + I2C_TASKMEM_BASE + i2c->rbuf, -- msg[1].len); -- return num; -- } -+ sdma->bufreg = ddma->bufreg; -+ base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100; -+ for (i = 0; i < ddma->num; i++) { -+ mem = ddma->pbuf[i]; -+ ddbwritel(dev, mem & 0xffffffff, base + i * 8); -+ ddbwritel(dev, mem >> 32, base + i * 8 + 4); - } -+} - -- if (num == 1 && !(msg[0].flags & I2C_M_RD)) { -- ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); -- ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH); -- if (!ddb_i2c_cmd(i2c, addr, 2)) -- return num; -+static int ddb_unredirect(struct ddb_port *port) -+{ -+ struct ddb_input *oredi, *iredi = 0; -+ struct ddb_output *iredo = 0; -+ -+ /*pr_info("unredirect %d.%d\n", port->dev->nr, port->nr);*/ -+ mutex_lock(&redirect_lock); -+ if (port->output->dma->running) { -+ mutex_unlock(&redirect_lock); -+ return -EBUSY; - } -- if (num == 1 && (msg[0].flags & I2C_M_RD)) { -- ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); -- if (!ddb_i2c_cmd(i2c, addr, 3)) { -- ddbcpyfrom(msg[0].buf, -- I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); -- return num; -+ oredi = port->output->redi; -+ if (!oredi) -+ goto done; -+ if (port->input[0]) { -+ iredi = port->input[0]->redi; -+ iredo = port->input[0]->redo; -+ -+ if (iredo) { -+ iredo->port->output->redi = oredi; -+ if (iredo->port->input[0]) { -+ iredo->port->input[0]->redi = iredi; -+ ddb_redirect_dma(oredi->port->dev, -+ oredi->dma, iredo->dma); -+ } -+ port->input[0]->redo = 0; -+ ddb_set_dma_table(port->dev, port->input[0]->dma); - } -+ oredi->redi = iredi; -+ port->input[0]->redi = 0; - } -- return -EIO; --} -+ oredi->redo = 0; -+ port->output->redi = 0; - -+ ddb_set_dma_table(oredi->port->dev, oredi->dma); -+done: -+ mutex_unlock(&redirect_lock); -+ return 0; -+} - --static u32 ddb_i2c_functionality(struct i2c_adapter *adap) -+static int ddb_redirect(u32 i, u32 p) - { -- return I2C_FUNC_SMBUS_EMUL; --} -+ struct ddb *idev = ddbs[(i >> 4) & 0x1f]; -+ struct ddb_input *input, *input2; -+ struct ddb *pdev = ddbs[(p >> 4) & 0x1f]; -+ struct ddb_port *port; - --static struct i2c_algorithm ddb_i2c_algo = { -- .master_xfer = ddb_i2c_master_xfer, -- .functionality = ddb_i2c_functionality, --}; -+ if (!idev->has_dma || !pdev->has_dma) -+ return -EINVAL; -+ if (!idev || !pdev) -+ return -EINVAL; - --static void ddb_i2c_release(struct ddb *dev) --{ -- int i; -- struct ddb_i2c *i2c; -- struct i2c_adapter *adap; -+ port = &pdev->port[p & 0x0f]; -+ if (!port->output) -+ return -EINVAL; -+ if (ddb_unredirect(port)) -+ return -EBUSY; - -- for (i = 0; i < dev->info->port_num; i++) { -- i2c = &dev->i2c[i]; -- adap = &i2c->adap; -- i2c_del_adapter(adap); -- } --} -+ if (i == 8) -+ return 0; - --static int ddb_i2c_init(struct ddb *dev) --{ -- int i, j, stat = 0; -- struct ddb_i2c *i2c; -- struct i2c_adapter *adap; -+ input = &idev->input[i & 7]; -+ if (!input) -+ return -EINVAL; - -- for (i = 0; i < dev->info->port_num; i++) { -- i2c = &dev->i2c[i]; -- i2c->dev = dev; -- i2c->nr = i; -- i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4); -- i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8); -- i2c->regs = 0x80 + i * 0x20; -- ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING); -- ddbwritel((i2c->rbuf << 16) | i2c->wbuf, -- i2c->regs + I2C_TASKADDRESS); -- init_waitqueue_head(&i2c->wq); -- -- adap = &i2c->adap; -- i2c_set_adapdata(adap, i2c); --#ifdef I2C_ADAP_CLASS_TV_DIGITAL -- adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG; --#else --#ifdef I2C_CLASS_TV_ANALOG -- adap->class = I2C_CLASS_TV_ANALOG; --#endif --#endif -- strcpy(adap->name, "ddbridge"); -- adap->algo = &ddb_i2c_algo; -- adap->algo_data = (void *)i2c; -- adap->dev.parent = &dev->pdev->dev; -- stat = i2c_add_adapter(adap); -- if (stat) -- break; -+ mutex_lock(&redirect_lock); -+ if (port->output->dma->running || input->dma->running) { -+ mutex_unlock(&redirect_lock); -+ return -EBUSY; - } -- if (stat) -- for (j = 0; j < i; j++) { -- i2c = &dev->i2c[j]; -- adap = &i2c->adap; -- i2c_del_adapter(adap); -- } -- return stat; --} -+ input2 = port->input[0]; -+ if (input2) { -+ if (input->redi) { -+ input2->redi = input->redi; -+ input->redi = 0; -+ } else -+ input2->redi = input; -+ } -+ input->redo = port->output; -+ port->output->redi = input; - -+ ddb_redirect_dma(input->port->dev, input->dma, port->output->dma); -+ mutex_unlock(&redirect_lock); -+ return 0; -+} - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ - --#if 0 --static void set_table(struct ddb *dev, u32 off, -- dma_addr_t *pbuf, u32 num) -+#ifdef DDB_ALT_DMA -+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { -- u32 i, base; -- u64 mem; -+ int i; - -- base = DMA_BASE_ADDRESS_TABLE + off; -- for (i = 0; i < num; i++) { -- mem = pbuf[i]; -- ddbwritel(mem & 0xffffffff, base + i * 8); -- ddbwritel(mem >> 32, base + i * 8 + 4); -+ if (!dma) -+ return; -+ for (i = 0; i < dma->num; i++) { -+ if (dma->vbuf[i]) { -+ dma_unmap_single(&pdev->dev, dma->pbuf[i], -+ dma->size, -+ dir ? DMA_TO_DEVICE : -+ DMA_FROM_DEVICE); -+ kfree(dma->vbuf[i]); -+ dma->vbuf[i] = NULL; -+ } - } - } --#endif - --static void ddb_address_table(struct ddb *dev) -+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { -- u32 i, j, base; -- u64 mem; -- dma_addr_t *pbuf; -- -- for (i = 0; i < dev->info->port_num * 2; i++) { -- base = DMA_BASE_ADDRESS_TABLE + i * 0x100; -- pbuf = dev->input[i].pbuf; -- for (j = 0; j < dev->input[i].dma_buf_num; j++) { -- mem = pbuf[j]; -- ddbwritel(mem & 0xffffffff, base + j * 8); -- ddbwritel(mem >> 32, base + j * 8 + 4); -- } -- } -- for (i = 0; i < dev->info->port_num; i++) { -- base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100; -- pbuf = dev->output[i].pbuf; -- for (j = 0; j < dev->output[i].dma_buf_num; j++) { -- mem = pbuf[j]; -- ddbwritel(mem & 0xffffffff, base + j * 8); -- ddbwritel(mem >> 32, base + j * 8 + 4); -+ int i; -+ -+ if (!dma) -+ return 0; -+ for (i = 0; i < dma->num; i++) { -+ dma->vbuf[i] = kmalloc(dma->size, __GFP_REPEAT); -+ if (!dma->vbuf[i]) -+ return -ENOMEM; -+ dma->pbuf[i] = dma_map_single(&pdev->dev, dma->vbuf[i], -+ dma->size, -+ dir ? DMA_TO_DEVICE : -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(&pdev->dev, dma->pbuf[i])) { -+ kfree(dma->vbuf[i]); -+ return -ENOMEM; - } - } -+ return 0; - } -+#else - --static void io_free(struct pci_dev *pdev, u8 **vbuf, -- dma_addr_t *pbuf, u32 size, int num) -+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { - int i; - -- for (i = 0; i < num; i++) { -- if (vbuf[i]) { -- pci_free_consistent(pdev, size, vbuf[i], pbuf[i]); -- vbuf[i] = NULL; -+ if (!dma) -+ return; -+ for (i = 0; i < dma->num; i++) { -+ if (dma->vbuf[i]) { -+ dma_free_coherent(&pdev->dev, dma->size, -+ dma->vbuf[i], dma->pbuf[i]); -+ dma->vbuf[i] = NULL; - } - } - } - --static int io_alloc(struct pci_dev *pdev, u8 **vbuf, -- dma_addr_t *pbuf, u32 size, int num) -+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { - int i; - -- for (i = 0; i < num; i++) { -- vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]); -- if (!vbuf[i]) -+ if (!dma) -+ return 0; -+ for (i = 0; i < dma->num; i++) { -+ dma->vbuf[i] = dma_alloc_coherent(&pdev->dev, dma->size, -+ &dma->pbuf[i], GFP_KERNEL); -+ if (!dma->vbuf[i]) - return -ENOMEM; - } - return 0; - } -+#endif - - static int ddb_buffers_alloc(struct ddb *dev) - { - int i; - struct ddb_port *port; - -- for (i = 0; i < dev->info->port_num; i++) { -+ for (i = 0; i < dev->link[0].info->port_num; i++) { - port = &dev->port[i]; - switch (port->class) { - case DDB_PORT_TUNER: -- if (io_alloc(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num) < 0) -- return -1; -- if (io_alloc(dev->pdev, port->input[1]->vbuf, -- port->input[1]->pbuf, -- port->input[1]->dma_buf_size, -- port->input[1]->dma_buf_num) < 0) -- return -1; -+ if (port->input[0]->dma) -+ if (dma_alloc(dev->pdev, port->input[0]->dma, 0) -+ < 0) -+ return -1; -+ if (port->input[1]->dma) -+ if (dma_alloc(dev->pdev, port->input[1]->dma, 0) -+ < 0) -+ return -1; - break; - case DDB_PORT_CI: -- if (io_alloc(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num) < 0) -- return -1; -- if (io_alloc(dev->pdev, port->output->vbuf, -- port->output->pbuf, -- port->output->dma_buf_size, -- port->output->dma_buf_num) < 0) -- return -1; -+ case DDB_PORT_LOOP: -+ if (port->input[0]->dma) -+ if (dma_alloc(dev->pdev, port->input[0]->dma, 0) -+ < 0) -+ return -1; -+ case DDB_PORT_MOD: -+ if (port->output->dma) -+ if (dma_alloc(dev->pdev, port->output->dma, 1) -+ < 0) -+ return -1; - break; - default: - break; - } - } -- ddb_address_table(dev); -+ ddb_set_dma_tables(dev); - return 0; - } - -@@ -329,111 +315,198 @@ static void ddb_buffers_free(struct ddb *dev) - int i; - struct ddb_port *port; - -- for (i = 0; i < dev->info->port_num; i++) { -+ for (i = 0; i < dev->link[0].info->port_num; i++) { - port = &dev->port[i]; -- io_free(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num); -- io_free(dev->pdev, port->input[1]->vbuf, -- port->input[1]->pbuf, -- port->input[1]->dma_buf_size, -- port->input[1]->dma_buf_num); -- io_free(dev->pdev, port->output->vbuf, -- port->output->pbuf, -- port->output->dma_buf_size, -- port->output->dma_buf_num); -+ -+ if (port->input[0] && port->input[0]->dma) -+ dma_free(dev->pdev, port->input[0]->dma, 0); -+ if (port->input[1] && port->input[1]->dma) -+ dma_free(dev->pdev, port->input[1]->dma, 0); -+ if (port->output && port->output->dma) -+ dma_free(dev->pdev, port->output->dma, 1); - } - } - --static void ddb_input_start(struct ddb_input *input) -+static void ddb_output_start(struct ddb_output *output) - { -- struct ddb *dev = input->port->dev; -+ struct ddb *dev = output->port->dev; -+ u32 con2; - -- spin_lock_irq(&input->lock); -- input->cbuf = 0; -- input->coff = 0; -+ con2 = ((output->port->obr << 13) + 71999) / 72000; -+ con2 = (con2 << 16) | output->port->gap; - -- /* reset */ -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(2, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -+ if (output->dma) { -+ spin_lock_irq(&output->dma->lock); -+ output->dma->cbuf = 0; -+ output->dma->coff = 0; -+ output->dma->stat = 0; -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); -+ } -+ if (output->port->class == DDB_PORT_MOD) -+ ddbridge_mod_output_start(output); -+ else { -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, con2, TS_OUTPUT_CONTROL2(output->nr)); -+ } -+ if (output->dma) { -+ ddbwritel(dev, output->dma->bufreg, -+ DMA_BUFFER_SIZE(output->dma->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); -+ ddbwritel(dev, 1, DMA_BASE_READ); -+ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr)); -+ } -+ if (output->port->class != DDB_PORT_MOD) { -+ if (output->port->input[0]->port->class == DDB_PORT_LOOP) -+ ddbwritel(dev, (1 << 13) | 0x15, -+ TS_OUTPUT_CONTROL(output->nr)); -+ else -+ ddbwritel(dev, 0x11d, TS_OUTPUT_CONTROL(output->nr)); -+ } -+ if (output->dma) { -+ output->dma->running = 1; -+ spin_unlock_irq(&output->dma->lock); -+ } -+} - -- ddbwritel((1 << 16) | -- (input->dma_buf_num << 11) | -- (input->dma_buf_size >> 7), -- DMA_BUFFER_SIZE(input->nr)); -- ddbwritel(0, DMA_BUFFER_ACK(input->nr)); -+static void ddb_output_stop(struct ddb_output *output) -+{ -+ struct ddb *dev = output->port->dev; - -- ddbwritel(1, DMA_BASE_WRITE); -- ddbwritel(3, DMA_BUFFER_CONTROL(input->nr)); -- ddbwritel(9, TS_INPUT_CONTROL(input->nr)); -- input->running = 1; -- spin_unlock_irq(&input->lock); -+ if (output->dma) -+ spin_lock_irq(&output->dma->lock); -+ if (output->port->class == DDB_PORT_MOD) -+ ddbridge_mod_output_stop(output); -+ else -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ if (output->dma) { -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); -+ output->dma->running = 0; -+ spin_unlock_irq(&output->dma->lock); -+ } - } - - static void ddb_input_stop(struct ddb_input *input) - { - struct ddb *dev = input->port->dev; -+ u32 tag = DDB_LINK_TAG(input->port->lnr); -+ -+ if (input->dma) -+ spin_lock_irq(&input->dma->lock); -+ ddbwritel(dev, 0, tag | TS_INPUT_CONTROL(input->nr)); -+ if (input->dma) { -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); -+ input->dma->running = 0; -+ spin_unlock_irq(&input->dma->lock); -+ } -+} -+ -+static void ddb_input_start(struct ddb_input *input) -+{ -+ struct ddb *dev = input->port->dev; -+ /* u32 tsbase = TS_INPUT_BASE + input->nr * 0x10; */ -+ u32 tag = DDB_LINK_TAG(input->port->lnr); -+ -+ if (input->dma) { -+ spin_lock_irq(&input->dma->lock); -+ input->dma->cbuf = 0; -+ input->dma->coff = 0; -+ input->dma->stat = 0; -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); -+ } -+ ddbwritel(dev, 0, tag | TS_INPUT_CONTROL2(input->nr)); -+ ddbwritel(dev, 0, tag | TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 2, tag | TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 0, tag | TS_INPUT_CONTROL(input->nr)); -+ -+ if (input->dma) { -+ ddbwritel(dev, input->dma->bufreg, -+ DMA_BUFFER_SIZE(input->dma->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); -+ ddbwritel(dev, 1, DMA_BASE_WRITE); -+ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr)); -+ } -+ if (dev->link[0].info->type == DDB_OCTONET) -+ ddbwritel(dev, 0x01, tag | TS_INPUT_CONTROL(input->nr)); -+ else -+ ddbwritel(dev, 0x09, tag | TS_INPUT_CONTROL(input->nr)); -+ if (input->dma) { -+ input->dma->running = 1; -+ spin_unlock_irq(&input->dma->lock); -+ } -+} - -- spin_lock_irq(&input->lock); -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(0, DMA_BUFFER_CONTROL(input->nr)); -- input->running = 0; -- spin_unlock_irq(&input->lock); -+ -+static int ddb_dvb_ns_input_start(struct ddb_input *input) -+{ -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ -+ if (!dvb->users) -+ ddb_input_start(input); -+ -+ return ++dvb->users; - } - --static void ddb_output_start(struct ddb_output *output) -+static int ddb_dvb_ns_input_stop(struct ddb_input *input) - { -- struct ddb *dev = output->port->dev; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ -+ if (--dvb->users) -+ return dvb->users; - -- spin_lock_irq(&output->lock); -- output->cbuf = 0; -- output->coff = 0; -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(2, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel((1 << 16) | -- (output->dma_buf_num << 11) | -- (output->dma_buf_size >> 7), -- DMA_BUFFER_SIZE(output->nr + 8)); -- ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8)); -- -- ddbwritel(1, DMA_BASE_READ); -- ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8)); -- /* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */ -- ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr)); -- output->running = 1; -- spin_unlock_irq(&output->lock); -+ ddb_input_stop(input); -+ return 0; - } - --static void ddb_output_stop(struct ddb_output *output) -+static void ddb_input_start_all(struct ddb_input *input) - { -- struct ddb *dev = output->port->dev; -+ struct ddb_input *i = input; -+ struct ddb_output *o; -+ -+ mutex_lock(&redirect_lock); -+ while (i && (o = i->redo)) { -+ ddb_output_start(o); -+ i = o->port->input[0]; -+ if (i) -+ ddb_input_start(i); -+ } -+ ddb_input_start(input); -+ mutex_unlock(&redirect_lock); -+} -+ -+static void ddb_input_stop_all(struct ddb_input *input) -+{ -+ struct ddb_input *i = input; -+ struct ddb_output *o; - -- spin_lock_irq(&output->lock); -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8)); -- output->running = 0; -- spin_unlock_irq(&output->lock); -+ mutex_lock(&redirect_lock); -+ ddb_input_stop(input); -+ while (i && (o = i->redo)) { -+ ddb_output_stop(o); -+ i = o->port->input[0]; -+ if (i) -+ ddb_input_stop(i); -+ } -+ mutex_unlock(&redirect_lock); - } - - static u32 ddb_output_free(struct ddb_output *output) - { -- u32 idx, off, stat = output->stat; -+ u32 idx, off, stat = output->dma->stat; - s32 diff; - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - -- if (output->cbuf != idx) { -- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && -- (output->dma_buf_size - output->coff <= 188)) -+ if (output->dma->cbuf != idx) { -+ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && -+ (output->dma->size - output->dma->coff <= 188)) - return 0; - return 188; - } -- diff = off - output->coff; -+ diff = off - output->dma->coff; - if (diff <= 0 || diff > 188) - return 188; - return 0; -@@ -443,46 +516,53 @@ static ssize_t ddb_output_write(struct ddb_output *output, - const __user u8 *buf, size_t count) - { - struct ddb *dev = output->port->dev; -- u32 idx, off, stat = output->stat; -+ u32 idx, off, stat = output->dma->stat; - u32 left = count, len; - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - - while (left) { -- len = output->dma_buf_size - output->coff; -- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && -+ len = output->dma->size - output->dma->coff; -+ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && - (off == 0)) { - if (len <= 188) - break; - len -= 188; - } -- if (output->cbuf == idx) { -- if (off > output->coff) { --#if 1 -- len = off - output->coff; -+ if (output->dma->cbuf == idx) { -+ if (off > output->dma->coff) { -+ len = off - output->dma->coff; - len -= (len % 188); - if (len <= 188) -- --#endif - break; - len -= 188; - } - } - if (len > left) - len = left; -- if (copy_from_user(output->vbuf[output->cbuf] + output->coff, -+ if (copy_from_user(output->dma->vbuf[output->dma->cbuf] + -+ output->dma->coff, - buf, len)) - return -EIO; -+#ifdef DDB_ALT_DMA -+ dma_sync_single_for_device(dev->dev, -+ output->dma->pbuf[ -+ output->dma->cbuf], -+ output->dma->size, DMA_TO_DEVICE); -+#endif - left -= len; - buf += len; -- output->coff += len; -- if (output->coff == output->dma_buf_size) { -- output->coff = 0; -- output->cbuf = ((output->cbuf + 1) % output->dma_buf_num); -+ output->dma->coff += len; -+ if (output->dma->coff == output->dma->size) { -+ output->dma->coff = 0; -+ output->dma->cbuf = ((output->dma->cbuf + 1) % -+ output->dma->num); - } -- ddbwritel((output->cbuf << 11) | (output->coff >> 7), -- DMA_BUFFER_ACK(output->nr + 8)); -+ ddbwritel(dev, -+ (output->dma->cbuf << 11) | -+ (output->dma->coff >> 7), -+ DMA_BUFFER_ACK(output->dma->nr)); - } - return count - left; - } -@@ -490,81 +570,276 @@ static ssize_t ddb_output_write(struct ddb_output *output, - static u32 ddb_input_avail(struct ddb_input *input) - { - struct ddb *dev = input->port->dev; -- u32 idx, off, stat = input->stat; -- u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr)); -+ u32 idx, off, stat = input->dma->stat; -+ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - - if (ctrl & 4) { -- printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl); -- ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr)); -+ pr_err("IA %d %d %08x\n", idx, off, ctrl); -+ ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr)); - return 0; - } -- if (input->cbuf != idx) -+ if (input->dma->cbuf != idx) - return 188; - return 0; - } - --static ssize_t ddb_input_read(struct ddb_input *input, __user u8 *buf, size_t count) -+static size_t ddb_input_read(struct ddb_input *input, -+ __user u8 *buf, size_t count) - { - struct ddb *dev = input->port->dev; - u32 left = count; -- u32 idx, free, stat = input->stat; -+ u32 idx, off, free, stat = input->dma->stat; - int ret; - - idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; - - while (left) { -- if (input->cbuf == idx) -+ if (input->dma->cbuf == idx) - return count - left; -- free = input->dma_buf_size - input->coff; -+ free = input->dma->size - input->dma->coff; - if (free > left) - free = left; -- ret = copy_to_user(buf, input->vbuf[input->cbuf] + -- input->coff, free); -+#ifdef DDB_ALT_DMA -+ dma_sync_single_for_cpu(dev->dev, -+ input->dma->pbuf[input->dma->cbuf], -+ input->dma->size, DMA_FROM_DEVICE); -+#endif -+ ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] + -+ input->dma->coff, free); - if (ret) - return -EFAULT; -- input->coff += free; -- if (input->coff == input->dma_buf_size) { -- input->coff = 0; -- input->cbuf = (input->cbuf+1) % input->dma_buf_num; -+ input->dma->coff += free; -+ if (input->dma->coff == input->dma->size) { -+ input->dma->coff = 0; -+ input->dma->cbuf = (input->dma->cbuf + 1) % -+ input->dma->num; - } - left -= free; -- ddbwritel((input->cbuf << 11) | (input->coff >> 7), -- DMA_BUFFER_ACK(input->nr)); -+ ddbwritel(dev, -+ (input->dma->cbuf << 11) | (input->dma->coff >> 7), -+ DMA_BUFFER_ACK(input->dma->nr)); - } - return count; - } - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static ssize_t ts_write(struct file *file, const __user char *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb *dev = output->port->dev; -+ size_t left = count; -+ int stat; -+ -+ if (!dev->has_dma) -+ return -EINVAL; -+ while (left) { -+ if (ddb_output_free(output) < 188) { -+ if (file->f_flags & O_NONBLOCK) -+ break; -+ if (wait_event_interruptible( -+ output->dma->wq, -+ ddb_output_free(output) >= 188) < 0) -+ break; -+ } -+ stat = ddb_output_write(output, buf, left); -+ if (stat < 0) -+ return stat; -+ buf += stat; -+ left -= stat; -+ } -+ return (left == count) ? -EAGAIN : (count - left); -+} -+ -+static ssize_t ts_read(struct file *file, __user char *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ struct ddb *dev = output->port->dev; -+ size_t left = count; -+ int stat; -+ -+ if (!dev->has_dma) -+ return -EINVAL; -+ while (left) { -+ if (ddb_input_avail(input) < 188) { -+ if (file->f_flags & O_NONBLOCK) -+ break; -+ if (wait_event_interruptible( -+ input->dma->wq, -+ ddb_input_avail(input) >= 188) < 0) -+ break; -+ } -+ stat = ddb_input_read(input, buf, left); -+ if (stat < 0) -+ return stat; -+ left -= stat; -+ buf += stat; -+ } -+ return (count && (left == count)) ? -EAGAIN : (count - left); -+} -+ -+static unsigned int ts_poll(struct file *file, poll_table *wait) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ -+ unsigned int mask = 0; -+ -+ poll_wait(file, &input->dma->wq, wait); -+ poll_wait(file, &output->dma->wq, wait); -+ if (ddb_input_avail(input) >= 188) -+ mask |= POLLIN | POLLRDNORM; -+ if (ddb_output_free(output) >= 188) -+ mask |= POLLOUT | POLLWRNORM; -+ return mask; -+} - --#if 0 --static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe) -+static int ts_release(struct inode *inode, struct file *file) - { -- int i; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; - -- for (i = 0; i < dev->info->port_num * 2; i++) { -- if (dev->input[i].fe == fe) -- return &dev->input[i]; -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -+ if (!input) -+ return -EINVAL; -+ ddb_input_stop(input); -+ } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ ddb_output_stop(output); - } -- return NULL; -+ return dvb_generic_release(inode, file); - } --#endif - --static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -+static int ts_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -+ if (!input) -+ return -EINVAL; -+ if (input->redo || input->redi) -+ return -EBUSY; -+ } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ } else -+ return -EINVAL; -+ err = dvb_generic_open(inode, file); -+ if (err < 0) -+ return err; -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ ddb_input_start(input); -+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY) -+ ddb_output_start(output); -+ return err; -+} -+ -+static int mod_release(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ -+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ ddb_output_stop(output); -+ } -+ return dvb_generic_release(inode, file); -+} -+ -+static int mod_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ -+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ } -+ err = dvb_generic_open(inode, file); -+ if (err < 0) -+ return err; -+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) -+ ddb_output_start(output); -+ return err; -+} -+static const struct file_operations ci_fops = { -+ .owner = THIS_MODULE, -+ .read = ts_read, -+ .write = ts_write, -+ .open = ts_open, -+ .release = ts_release, -+ .poll = ts_poll, -+ .mmap = 0, -+}; -+ -+static struct dvb_device dvbdev_ci = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 2, -+ .fops = &ci_fops, -+}; -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static long mod_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl); -+} -+ -+static const struct file_operations mod_fops = { -+ .owner = THIS_MODULE, -+ .read = ts_read, -+ .write = ts_write, -+ .open = mod_open, -+ .release = mod_release, -+ .poll = ts_poll, -+ .mmap = 0, -+ .unlocked_ioctl = mod_ioctl, -+}; -+ -+static struct dvb_device dvbdev_mod = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 2, -+ .fops = &mod_fops, -+}; -+ -+ -+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct ddb_input *input = fe->sec_priv; - struct ddb_port *port = input->port; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; - int status; - - if (enable) { - mutex_lock(&port->i2c_gate_lock); -- status = input->gate_ctrl(fe, 1); -+ status = dvb->i2c_gate_ctrl(fe, 1); - } else { -- status = input->gate_ctrl(fe, 0); -+ status = dvb->i2c_gate_ctrl(fe, 0); - mutex_unlock(&port->i2c_gate_lock); - } - return status; -@@ -573,45 +848,158 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) - static int demod_attach_drxk(struct ddb_input *input) - { - struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - struct dvb_frontend *fe; - struct drxk_config config; - - memset(&config, 0, sizeof(config)); -- config.microcode_name = "drxk_a3.mc"; -- config.qam_demod_parameter_count = 4; - config.adr = 0x29 + (input->nr & 1); -+ config.microcode_name = "drxk_a3.mc"; - -- fe = input->fe = dvb_attach(drxk_attach, &config, i2c); -- if (!input->fe) { -- printk(KERN_ERR "No DRXK found!\n"); -+ fe = dvb->fe = dvb_attach(drxk_attach, &config, i2c); -+ if (!fe) { -+ pr_err("No DRXK found!\n"); - return -ENODEV; - } - fe->sec_priv = input; -- input->gate_ctrl = fe->ops.i2c_gate_ctrl; -- fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; -+ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; - return 0; - } - --static int tuner_attach_tda18271(struct ddb_input *input) --{ -- struct i2c_adapter *i2c = &input->port->i2c->adap; -- struct dvb_frontend *fe; -+struct cxd2843_cfg cxd2843_0 = { -+ .adr = 0x6c, -+ .ts_clock = 1, -+}; - -- if (input->fe->ops.i2c_gate_ctrl) -- input->fe->ops.i2c_gate_ctrl(input->fe, 1); -- fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60); -+struct cxd2843_cfg cxd2843_1 = { -+ .adr = 0x6d, -+ .ts_clock = 1, -+}; -+ -+struct cxd2843_cfg cxd2843p_0 = { -+ .adr = 0x6c, -+ .parallel = 1, -+}; -+ -+struct cxd2843_cfg cxd2843p_1 = { -+ .adr = 0x6d, -+ .parallel = 1, -+}; -+ -+static int demod_attach_cxd2843(struct ddb_input *input, int par) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ -+ if (par) -+ fe = dvb->fe = dvb_attach(cxd2843_attach, i2c, -+ (input->nr & 1) ? -+ &cxd2843p_1 : &cxd2843p_0); -+ else -+ fe = dvb->fe = dvb_attach(cxd2843_attach, i2c, -+ (input->nr & 1) ? -+ &cxd2843_1 : &cxd2843_0); -+ if (!dvb->fe) { -+ pr_err("No cxd2837/38/43 found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+static int demod_attach_stv0367dd(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ struct stv0367dd_cfg cfg = { .cont_clock = 0 }; -+ -+ cfg.adr = 0x1f - (input->nr & 1); -+ if (input->port->dev->link[input->port->lnr].info->con_clock) -+ cfg.cont_clock = 1; -+ fe = dvb->fe = dvb_attach(stv0367dd_attach, i2c, -+ &cfg, -+ &dvb->fe2); -+ if (!dvb->fe) { -+ pr_err("No stv0367 found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+static int tuner_attach_tda18271(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ -+ if (dvb->fe->ops.i2c_gate_ctrl) -+ dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 1); -+ fe = dvb_attach(tda18271c2dd_attach, dvb->fe, i2c, 0x60); -+ if (dvb->fe->ops.i2c_gate_ctrl) -+ dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 0); - if (!fe) { -- printk(KERN_ERR "No TDA18271 found!\n"); -+ pr_err("No TDA18271 found!\n"); - return -ENODEV; - } -- if (input->fe->ops.i2c_gate_ctrl) -- input->fe->ops.i2c_gate_ctrl(input->fe, 0); - return 0; - } - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+static int tuner_attach_tda18212(struct ddb_input *input) -+{ -+ struct i2c_adapter *adapter = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct i2c_client *client; -+ struct tda18212_config config = { -+ .fe = dvb->fe, -+ .if_dvbt_6 = 3550, -+ .if_dvbt_7 = 3700, -+ .if_dvbt_8 = 4150, -+ .if_dvbt2_6 = 3250, -+ .if_dvbt2_7 = 4000, -+ .if_dvbt2_8 = 4000, -+ .if_dvbc = 5000, -+ .init_flags = TDA18212_INIT_RETRY, -+ }; -+ struct i2c_board_info board_info = { -+ .type = "tda18212", -+ .platform_data = &config, -+ }; -+ -+ if (input->nr & 1) -+ board_info.addr = 0x63; -+ else -+ board_info.addr = 0x60; -+ -+ request_module(board_info.type); -+ -+ client = i2c_new_device(adapter, &board_info); -+ if (client == NULL || client->dev.driver == NULL) -+ goto err; -+ -+ if (!try_module_get(client->dev.driver->owner)) { -+ i2c_unregister_device(client); -+ goto err; -+ } -+ -+ dvb->i2c_client[0] = client; -+ -+ return 0; -+err: -+ dev_notice(input->port->dev->dev, "TDA18212 tuner not found. Device is not fully operational.\n"); -+ return -ENODEV; -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ - - static struct stv090x_config stv0900 = { - .device = STV0900, -@@ -624,6 +1012,9 @@ static struct stv090x_config stv0900 = { - .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - -+ .ts1_tei = 1, -+ .ts2_tei = 1, -+ - .repeater_level = STV090x_RPTLEVEL_16, - - .adc1_range = STV090x_ADC_1Vpp, -@@ -643,6 +1034,9 @@ static struct stv090x_config stv0900_aa = { - .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - -+ .ts1_tei = 1, -+ .ts2_tei = 1, -+ - .repeater_level = STV090x_RPTLEVEL_16, - - .adc1_range = STV090x_ADC_1Vpp, -@@ -667,18 +1061,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) - { - struct i2c_adapter *i2c = &input->port->i2c->adap; - struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - -- input->fe = dvb_attach(stv090x_attach, feconf, i2c, -- (input->nr & 1) ? STV090x_DEMODULATOR_1 -- : STV090x_DEMODULATOR_0); -- if (!input->fe) { -- printk(KERN_ERR "No STV0900 found!\n"); -+ dvb->fe = dvb_attach(stv090x_attach, feconf, i2c, -+ (input->nr & 1) ? STV090x_DEMODULATOR_1 -+ : STV090x_DEMODULATOR_0); -+ if (!dvb->fe) { -+ pr_err("No STV0900 found!\n"); - return -ENODEV; - } -- if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0, -+ if (!dvb_attach(lnbh24_attach, dvb->fe, i2c, 0, - 0, (input->nr & 1) ? - (0x09 - type) : (0x0b - type))) { -- printk(KERN_ERR "No LNBH24 found!\n"); -+ pr_err("No LNBH24 found!\n"); - return -ENODEV; - } - return 0; -@@ -687,18 +1082,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) - static int tuner_attach_stv6110(struct ddb_input *input, int type) - { - struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; - struct stv6110x_config *tunerconf = (input->nr & 1) ? - &stv6110b : &stv6110a; - const struct stv6110x_devctl *ctl; - -- ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); -+ ctl = dvb_attach(stv6110x_attach, dvb->fe, tunerconf, i2c); - if (!ctl) { -- printk(KERN_ERR "No STV6110X found!\n"); -+ pr_err("No STV6110X found!\n"); - return -ENODEV; - } -- printk(KERN_INFO "attach tuner input %d adr %02x\n", -- input->nr, tunerconf->addr); -+ pr_info("attach tuner input %d adr %02x\n", -+ input->nr, tunerconf->addr); - - feconf->tuner_init = ctl->tuner_init; - feconf->tuner_sleep = ctl->tuner_sleep; -@@ -715,10 +1111,431 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) - return 0; - } - -+static struct stv0910_cfg stv0910_p = { -+ .adr = 0x68, -+ .parallel = 1, -+ .rptlvl = 4, -+ .clk = 30000000, -+}; -+ -+static struct lnbh25_config lnbh25_conf_0_0 = { -+ .i2c_address = 0x0c << 1, -+ .data2_config = LNBH25_TEN | LNBH25_EXTM -+}; -+ -+static struct lnbh25_config lnbh25_conf_0_1 = { -+ .i2c_address = 0x0d << 1, -+ .data2_config = LNBH25_TEN | LNBH25_EXTM -+}; -+ -+static struct lnbh25_config lnbh25_conf_1_0 = { -+ .i2c_address = 0x08 << 1, -+ .data2_config = LNBH25_TEN | LNBH25_EXTM -+}; -+ -+static struct lnbh25_config lnbh25_conf_1_1 = { -+ .i2c_address = 0x09 << 1, -+ .data2_config = LNBH25_TEN | LNBH25_EXTM -+}; -+ -+ -+static int demod_attach_stv0910(struct ddb_input *input, int type) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct stv0910_cfg cfg = stv0910_p; -+ -+ if (type) -+ cfg.parallel = 2; -+ dvb->fe = dvb_attach(stv0910_attach, i2c, &cfg, (input->nr & 1)); -+ if (!dvb->fe) { -+ cfg.adr = 0x6c; -+ dvb->fe = dvb_attach(stv0910_attach, i2c, -+ &cfg, (input->nr & 1)); -+ } -+ if (!dvb->fe) { -+ pr_err("No STV0910 found!\n"); -+ return -ENODEV; -+ } -+ -+ if (!dvb_attach(lnbh25_attach, dvb->fe, -+ ((input->nr & 1) ? &lnbh25_conf_0_1 : &lnbh25_conf_0_0), -+ i2c)) { -+ if (!dvb_attach(lnbh25_attach, dvb->fe, -+ ((input->nr & 1) ? &lnbh25_conf_1_1 : &lnbh25_conf_1_0), -+ i2c)) { -+ pr_err("No LNBH25 found!\n"); -+ return -ENODEV; -+ } -+ } -+ -+ return 0; -+} -+ -+static int tuner_attach_stv6111(struct ddb_input *input, int type) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ u8 adr = (type ? 0 : 4) + ((input->nr & 1) ? 0x63 : 0x60); -+ -+ fe = dvb_attach(stv6111_attach, dvb->fe, i2c, adr); -+ if (!fe) { -+ fe = dvb_attach(stv6111_attach, dvb->fe, i2c, adr & ~4); -+ if (!fe) { -+ pr_err("No STV6111 found at 0x%02x!\n", adr); -+ return -ENODEV; -+ } -+ } -+ return 0; -+} -+ -+static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) -+{ -+ u32 c, v = 0, tag = DDB_LINK_TAG(link); -+ -+ v = LNB_TONE & (dev->link[link].lnb.tone << (15 - lnb)); -+ ddbwritel(dev, cmd | v, tag | LNB_CONTROL(lnb)); -+ for (c = 0; c < 10; c++) { -+ v = ddbreadl(dev, tag | LNB_CONTROL(lnb)); -+ if ((v & LNB_BUSY) == 0) -+ break; -+ msleep(20); -+ } -+ if (c == 10) -+ pr_info("lnb_command lnb = %08x cmd = %08x\n", lnb, cmd); -+ return 0; -+} -+ -+static int max_send_master_cmd(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *cmd) -+{ -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb *dev = port->dev; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ u32 tag = DDB_LINK_TAG(port->lnr); -+ int i; -+ u32 fmode = dev->link[port->lnr].lnb.fmode; -+ -+ if (fmode == 2 || fmode == 1) -+ return 0; -+ if (dvb->diseqc_send_master_cmd) -+ dvb->diseqc_send_master_cmd(fe, cmd); -+ -+ mutex_lock(&dev->link[port->lnr].lnb.lock); -+ ddbwritel(dev, 0, tag | LNB_BUF_LEVEL(dvb->input)); -+ for (i = 0; i < cmd->msg_len; i++) -+ ddbwritel(dev, cmd->msg[i], tag | LNB_BUF_WRITE(dvb->input)); -+ lnb_command(dev, port->lnr, dvb->input, LNB_CMD_DISEQC); -+ mutex_unlock(&dev->link[port->lnr].lnb.lock); -+ return 0; -+} -+ -+static int lnb_set_tone(struct ddb *dev, u32 link, u32 input, -+ enum fe_sec_tone_mode tone) -+{ -+ int s = 0; -+ u32 mask = (1ULL << input); -+ -+ switch (tone) { -+ case SEC_TONE_OFF: -+ if (!(dev->link[link].lnb.tone & mask)) -+ return 0; -+ dev->link[link].lnb.tone &= ~(1ULL << input); -+ break; -+ case SEC_TONE_ON: -+ if (dev->link[link].lnb.tone & mask) -+ return 0; -+ dev->link[link].lnb.tone |= (1ULL << input); -+ break; -+ default: -+ s = -EINVAL; -+ break; -+ }; -+ if (!s) -+ s = lnb_command(dev, link, input, LNB_CMD_NOP); -+ return s; -+} -+ -+static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input, -+ enum fe_sec_voltage voltage) -+{ -+ int s = 0; -+ -+ if (dev->link[link].lnb.oldvoltage[input] == voltage) -+ return 0; -+ switch (voltage) { -+ case SEC_VOLTAGE_OFF: -+ if (dev->link[link].lnb.voltage[input]) -+ return 0; -+ lnb_command(dev, link, input, LNB_CMD_OFF); -+ break; -+ case SEC_VOLTAGE_13: -+ lnb_command(dev, link, input, LNB_CMD_LOW); -+ break; -+ case SEC_VOLTAGE_18: -+ lnb_command(dev, link, input, LNB_CMD_HIGH); -+ break; -+ default: -+ s = -EINVAL; -+ break; -+ }; -+ dev->link[link].lnb.oldvoltage[input] = voltage; -+ return s; -+} -+ -+static int max_set_input_unlocked(struct dvb_frontend *fe, int in) -+{ -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb *dev = port->dev; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ int res = 0; -+ -+ if (in > 3) -+ return -EINVAL; -+ if (dvb->input != in) { -+ u32 bit = (1ULL << input->nr); -+ u32 obit = dev->link[port->lnr].lnb.voltage[dvb->input] & bit; -+ -+ dev->link[port->lnr].lnb.voltage[dvb->input] &= ~bit; -+ dvb->input = in; -+ dev->link[port->lnr].lnb.voltage[dvb->input] |= obit; -+ } -+ res = dvb->set_input(fe, in); -+ return res; -+} -+ -+static int max_set_input(struct dvb_frontend *fe, int in) -+{ -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb *dev = input->port->dev; -+ int res; -+ -+ mutex_lock(&dev->link[port->lnr].lnb.lock); -+ res = max_set_input_unlocked(fe, in); -+ mutex_unlock(&dev->link[port->lnr].lnb.lock); -+ return res; -+} -+ -+static int max_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) -+{ -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb *dev = port->dev; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ int tuner = 0; -+ int res = 0; -+ u32 fmode = dev->link[port->lnr].lnb.fmode; -+ -+ mutex_lock(&dev->link[port->lnr].lnb.lock); -+ dvb->tone = tone; -+ switch (fmode) { -+ default: -+ case 0: -+ case 3: -+ res = lnb_set_tone(dev, port->lnr, dvb->input, tone); -+ break; -+ case 1: -+ case 2: -+ if (old_quattro) { -+ if (dvb->tone == SEC_TONE_ON) -+ tuner |= 2; -+ if (dvb->voltage == SEC_VOLTAGE_18) -+ tuner |= 1; -+ } else { -+ if (dvb->tone == SEC_TONE_ON) -+ tuner |= 1; -+ if (dvb->voltage == SEC_VOLTAGE_18) -+ tuner |= 2; -+ } -+ res = max_set_input_unlocked(fe, tuner); -+ break; -+ } -+ mutex_unlock(&dev->link[port->lnr].lnb.lock); -+ return res; -+} -+ -+static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) -+{ -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb *dev = port->dev; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ int tuner = 0; -+ u32 nv, ov = dev->link[port->lnr].lnb.voltages; -+ int res = 0; -+ u32 fmode = dev->link[port->lnr].lnb.fmode; -+ -+ mutex_lock(&dev->link[port->lnr].lnb.lock); -+ dvb->voltage = voltage; -+ -+ switch (fmode) { -+ case 3: -+ default: -+ case 0: -+ if (fmode == 3) -+ max_set_input_unlocked(fe, 0); -+ if (voltage == SEC_VOLTAGE_OFF) -+ dev->link[port->lnr].lnb.voltage[dvb->input] &= ~(1ULL << input->nr); -+ else -+ dev->link[port->lnr].lnb.voltage[dvb->input] |= (1ULL << input->nr); -+ -+ res = lnb_set_voltage(dev, port->lnr, dvb->input, voltage); -+ break; -+ case 1: -+ case 2: -+ if (voltage == SEC_VOLTAGE_OFF) -+ dev->link[port->lnr].lnb.voltages &= ~(1ULL << input->nr); -+ else -+ dev->link[port->lnr].lnb.voltages |= (1ULL << input->nr); -+ nv = dev->link[port->lnr].lnb.voltages; -+ -+ if (old_quattro) { -+ if (dvb->tone == SEC_TONE_ON) -+ tuner |= 2; -+ if (dvb->voltage == SEC_VOLTAGE_18) -+ tuner |= 1; -+ } else { -+ if (dvb->tone == SEC_TONE_ON) -+ tuner |= 1; -+ if (dvb->voltage == SEC_VOLTAGE_18) -+ tuner |= 2; -+ } -+ res = max_set_input_unlocked(fe, tuner); -+ -+ if (nv != ov) { -+ if (nv) { -+ lnb_set_voltage(dev, port->lnr, 0, SEC_VOLTAGE_13); -+ if (fmode == 1) { -+ lnb_set_voltage(dev, port->lnr, 0, SEC_VOLTAGE_13); -+ if (old_quattro) { -+ lnb_set_voltage(dev, port->lnr, 1, SEC_VOLTAGE_18); -+ lnb_set_voltage(dev, port->lnr, 2, SEC_VOLTAGE_13); -+ } else { -+ lnb_set_voltage(dev, port->lnr, 1, SEC_VOLTAGE_13); -+ lnb_set_voltage(dev, port->lnr, 2, SEC_VOLTAGE_18); -+ } -+ lnb_set_voltage(dev, port->lnr, 3, SEC_VOLTAGE_18); -+ } -+ } else { -+ lnb_set_voltage(dev, port->lnr, 0, SEC_VOLTAGE_OFF); -+ if (fmode == 1) { -+ lnb_set_voltage(dev, port->lnr, 1, SEC_VOLTAGE_OFF); -+ lnb_set_voltage(dev, port->lnr, 2, SEC_VOLTAGE_OFF); -+ lnb_set_voltage(dev, port->lnr, 3, SEC_VOLTAGE_OFF); -+ } -+ } -+ } -+ break; -+ } -+ mutex_unlock(&dev->link[port->lnr].lnb.lock); -+ return res; -+} -+ -+static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) -+{ -+ -+ return 0; -+} -+ -+static int max_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) -+{ -+ return 0; -+} -+ -+static int mxl_fw_read(void *priv, u8 *buf, u32 len) -+{ -+ struct ddb_link *link = priv; -+ struct ddb *dev = link->dev; -+ -+ pr_info("Read mxl_fw from link %u\n", link->nr); -+ -+ return ddbridge_flashread(dev, link->nr, buf, 0xc0000, len); -+} -+ -+static int lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm) -+{ -+ u32 l = link->nr; -+ -+ if (link->lnb.fmode == fm) -+ return 0; -+ pr_info("Set fmode link %u = %u\n", l, fm); -+ mutex_lock(&link->lnb.lock); -+ if (fm == 2 || fm == 1) { -+ lnb_set_tone(dev, l, 0, SEC_TONE_OFF); -+ if (old_quattro) { -+ lnb_set_tone(dev, l, 1, SEC_TONE_OFF); -+ lnb_set_tone(dev, l, 2, SEC_TONE_ON); -+ } else { -+ lnb_set_tone(dev, l, 1, SEC_TONE_ON); -+ lnb_set_tone(dev, l, 2, SEC_TONE_OFF); -+ } -+ lnb_set_tone(dev, l, 3, SEC_TONE_ON); -+ } -+ link->lnb.fmode = fm; -+ mutex_unlock(&link->lnb.lock); -+ return 0; -+} -+ -+static struct mxl5xx_cfg mxl5xx = { -+ .adr = 0x60, -+ .type = 0x01, -+ .clk = 27000000, -+ .ts_clk = 139, -+ .cap = 12, -+ .fw_read = mxl_fw_read, -+}; -+ -+static int fe_attach_mxl5xx(struct ddb_input *input) -+{ -+ struct ddb *dev = input->port->dev; -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct ddb_port *port = input->port; -+ struct ddb_link *link = &dev->link[port->lnr]; -+ struct mxl5xx_cfg cfg; -+ int demod, tuner; -+ -+ cfg = mxl5xx; -+ cfg.fw_priv = link; -+ if (dev->link[0].info->type == DDB_OCTONET) -+ ; /* cfg.ts_clk = 69; */ -+ -+ demod = input->nr; -+ tuner = demod & 3; -+ if (fmode == 3) -+ tuner = 0; -+ dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, demod, tuner); -+ if (!dvb->fe) { -+ pr_err("No MXL5XX found!\n"); -+ return -ENODEV; -+ } -+ if (input->nr < 4) { -+ lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT); -+ lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF); -+ } -+ lnb_init_fmode(dev, link, fmode); -+ -+ dvb->fe->ops.set_voltage = max_set_voltage; -+ dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage; -+ dvb->fe->ops.set_tone = max_set_tone; -+ dvb->diseqc_send_master_cmd = dvb->fe->ops.diseqc_send_master_cmd; -+ dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd; -+ dvb->fe->ops.diseqc_send_burst = max_send_burst; -+ dvb->fe->sec_priv = input; -+ dvb->set_input = dvb->fe->ops.set_input; -+ dvb->fe->ops.set_input = max_set_input; -+ dvb->input = tuner; -+ return 0; -+} -+ - static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, -- int (*start_feed)(struct dvb_demux_feed *), -- int (*stop_feed)(struct dvb_demux_feed *), -- void *priv) -+ int (*start_feed)(struct dvb_demux_feed *), -+ int (*stop_feed)(struct dvb_demux_feed *), -+ void *priv) - { - dvbdemux->priv = priv; - -@@ -734,10 +1551,10 @@ static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, - } - - static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, -- struct dvb_demux *dvbdemux, -- struct dmx_frontend *hw_frontend, -- struct dmx_frontend *mem_frontend, -- struct dvb_adapter *dvb_adapter) -+ struct dvb_demux *dvbdemux, -+ struct dmx_frontend *hw_frontend, -+ struct dmx_frontend *mem_frontend, -+ struct dvb_adapter *dvb_adapter) - { - int ret; - -@@ -759,999 +1576,3010 @@ static int start_feed(struct dvb_demux_feed *dvbdmxfeed) - { - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ddb_input *input = dvbdmx->priv; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - -- if (!input->users) -- ddb_input_start(input); -+ if (!dvb->users) -+ ddb_input_start_all(input); - -- return ++input->users; -+ return ++dvb->users; - } - - static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) - { - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ddb_input *input = dvbdmx->priv; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - -- if (--input->users) -- return input->users; -+ if (--dvb->users) -+ return dvb->users; - -- ddb_input_stop(input); -+ ddb_input_stop_all(input); - return 0; - } - -- - static void dvb_input_detach(struct ddb_input *input) - { -- struct dvb_adapter *adap = &input->adap; -- struct dvb_demux *dvbdemux = &input->demux; -- -- switch (input->attached) { -- case 5: -- if (input->fe2) -- dvb_unregister_frontend(input->fe2); -- if (input->fe) { -- dvb_unregister_frontend(input->fe); -- dvb_frontend_detach(input->fe); -- input->fe = NULL; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_demux *dvbdemux = &dvb->demux; -+ struct i2c_client *client; -+ -+ switch (dvb->attached) { -+ case 0x31: -+ client = dvb->i2c_client[0]; -+ if (client) { -+ module_put(client->dev.driver->owner); -+ i2c_unregister_device(client); - } -- case 4: -- dvb_net_release(&input->dvbnet); -- -- case 3: -+ if (dvb->fe2) -+ dvb_unregister_frontend(dvb->fe2); -+ if (dvb->fe) -+ dvb_unregister_frontend(dvb->fe); -+ /* fallthrough */ -+ case 0x30: -+ if (dvb->fe2) -+ dvb_frontend_detach(dvb->fe2); -+ if (dvb->fe) -+ dvb_frontend_detach(dvb->fe); -+ dvb->fe = dvb->fe2 = NULL; -+ /* fallthrough */ -+ case 0x21: -+ if (input->port->dev->ns_num) -+ dvb_netstream_release(&dvb->dvbns); -+ /* fallthrough */ -+ case 0x20: -+ dvb_net_release(&dvb->dvbnet); -+ /* fallthrough */ -+ case 0x11: - dvbdemux->dmx.close(&dvbdemux->dmx); - dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -- &input->hw_frontend); -+ &dvb->hw_frontend); - dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -- &input->mem_frontend); -- dvb_dmxdev_release(&input->dmxdev); -+ &dvb->mem_frontend); -+ dvb_dmxdev_release(&dvb->dmxdev); -+ /* fallthrough */ -+ case 0x10: -+ dvb_dmx_release(&dvb->demux); -+ /* fallthrough */ -+ case 0x01: -+ break; -+ } -+ dvb->attached = 0x00; -+} - -- case 2: -- dvb_dmx_release(&input->demux); -+static int dvb_register_adapters(struct ddb *dev) -+{ -+ int i, ret = 0; -+ struct ddb_port *port; -+ struct dvb_adapter *adap; -+ -+ if (adapter_alloc == 3 || dev->link[0].info->type == DDB_MOD || -+ dev->link[0].info->type == DDB_OCTONET) { -+ port = &dev->port[0]; -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ for (i = 0; i < dev->port_num; i++) { -+ port = &dev->port[i]; -+ port->dvb[0].adap = adap; -+ port->dvb[1].adap = adap; -+ } -+ return 0; -+ } - -- case 1: -- dvb_unregister_adapter(adap); -+ for (i = 0; i < dev->port_num; i++) { -+ port = &dev->port[i]; -+ switch (port->class) { -+ case DDB_PORT_TUNER: -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ -+ if (adapter_alloc > 0) { -+ port->dvb[1].adap = port->dvb[0].adap; -+ break; -+ } -+ adap = port->dvb[1].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[1].adap_registered = 1; -+ break; -+ -+ case DDB_PORT_CI: -+ case DDB_PORT_LOOP: -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ break; -+ default: -+ if (adapter_alloc < 2) -+ break; -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ break; -+ } -+ } -+ return ret; -+} -+ -+static void dvb_unregister_adapters(struct ddb *dev) -+{ -+ int i; -+ struct ddb_port *port; -+ struct ddb_dvb *dvb; -+ -+ for (i = 0; i < dev->link[0].info->port_num; i++) { -+ port = &dev->port[i]; -+ -+ dvb = &port->dvb[0]; -+ if (dvb->adap_registered) -+ dvb_unregister_adapter(dvb->adap); -+ dvb->adap_registered = 0; -+ -+ dvb = &port->dvb[1]; -+ if (dvb->adap_registered) -+ dvb_unregister_adapter(dvb->adap); -+ dvb->adap_registered = 0; - } -- input->attached = 0; - } - - static int dvb_input_attach(struct ddb_input *input) - { -- int ret; -+ int ret = 0; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - struct ddb_port *port = input->port; -- struct dvb_adapter *adap = &input->adap; -- struct dvb_demux *dvbdemux = &input->demux; -- -- ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -- &input->port->dev->pdev->dev, -- adapter_nr); -- if (ret < 0) { -- printk(KERN_ERR "ddbridge: Could not register adapter." -- "Check if you enabled enough adapters in dvb-core!\n"); -- return ret; -- } -- input->attached = 1; -+ struct dvb_adapter *adap = dvb->adap; -+ struct dvb_demux *dvbdemux = &dvb->demux; -+ int par = 0; -+ -+ dvb->attached = 0x01; - - ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", - start_feed, - stop_feed, input); - if (ret < 0) - return ret; -- input->attached = 2; -+ dvb->attached = 0x10; - -- ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux, -- &input->hw_frontend, -- &input->mem_frontend, adap); -+ ret = my_dvb_dmxdev_ts_card_init(&dvb->dmxdev, -+ &dvb->demux, -+ &dvb->hw_frontend, -+ &dvb->mem_frontend, adap); - if (ret < 0) - return ret; -- input->attached = 3; -+ dvb->attached = 0x11; - -- ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux); -+ ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux); - if (ret < 0) - return ret; -- input->attached = 4; -+ dvb->attached = 0x20; - -- input->fe = NULL; -+ if (input->port->dev->ns_num) { -+ ret = netstream_init(input); -+ if (ret < 0) -+ return ret; -+ dvb->attached = 0x21; -+ } -+ dvb->fe = dvb->fe2 = NULL; - switch (port->type) { -+ case DDB_TUNER_MXL5XX: -+ if (fe_attach_mxl5xx(input) < 0) -+ return -ENODEV; -+ break; - case DDB_TUNER_DVBS_ST: - if (demod_attach_stv0900(input, 0) < 0) - return -ENODEV; - if (tuner_attach_stv6110(input, 0) < 0) - return -ENODEV; -- if (input->fe) { -- if (dvb_register_frontend(adap, input->fe) < 0) -- return -ENODEV; -- } - break; - case DDB_TUNER_DVBS_ST_AA: - if (demod_attach_stv0900(input, 1) < 0) - return -ENODEV; - if (tuner_attach_stv6110(input, 1) < 0) - return -ENODEV; -- if (input->fe) { -- if (dvb_register_frontend(adap, input->fe) < 0) -- return -ENODEV; -- } - break; -- case DDB_TUNER_DVBCT_TR: -- if (demod_attach_drxk(input) < 0) -+ case DDB_TUNER_DVBS_STV0910: -+ if (demod_attach_stv0910(input, 0) < 0) -+ return -ENODEV; -+ if (tuner_attach_stv6111(input, 0) < 0) -+ return -ENODEV; -+ break; -+ case DDB_TUNER_DVBS_STV0910_PR: -+ if (demod_attach_stv0910(input, 1) < 0) -+ return -ENODEV; -+ if (tuner_attach_stv6111(input, 1) < 0) -+ return -ENODEV; -+ break; -+ case DDB_TUNER_DVBS_STV0910_P: -+ if (demod_attach_stv0910(input, 0) < 0) -+ return -ENODEV; -+ if (tuner_attach_stv6111(input, 1) < 0) -+ return -ENODEV; -+ break; -+ case DDB_TUNER_DVBCT_TR: -+ if (demod_attach_drxk(input) < 0) - return -ENODEV; - if (tuner_attach_tda18271(input) < 0) - return -ENODEV; -- if (dvb_register_frontend(adap, input->fe) < 0) -+ break; -+ case DDB_TUNER_DVBCT_ST: -+ if (demod_attach_stv0367dd(input) < 0) -+ return -ENODEV; -+ if (tuner_attach_tda18212(input) < 0) -+ { -+ if(dvb->fe2) -+ dvb_frontend_detach(dvb->fe2); -+ if(dvb->fe) -+ dvb_frontend_detach(dvb->fe); -+ return -ENODEV; -+ } -+ break; -+ case DDB_TUNER_DVBCT2_SONY_P: -+ case DDB_TUNER_DVBC2T2_SONY_P: -+ case DDB_TUNER_ISDBT_SONY_P: -+ if (input->port->dev->link[input->port->lnr].info->ts_quirks -+ & TS_QUIRK_SERIAL) -+ par = 0; -+ else -+ par = 1; -+ case DDB_TUNER_DVBCT2_SONY: -+ case DDB_TUNER_DVBC2T2_SONY: -+ case DDB_TUNER_ISDBT_SONY: -+ if (demod_attach_cxd2843(input, par) < 0) -+ return -ENODEV; -+ if (tuner_attach_tda18212(input) < 0) -+ { -+ if(dvb->fe2) -+ dvb_frontend_detach(dvb->fe2); -+ if(dvb->fe) -+ dvb_frontend_detach(dvb->fe); -+ return -ENODEV; -+ } -+ break; -+ default: -+ return 0; -+ } -+ dvb->attached = 0x30; -+ if (dvb->fe) { -+ if (dvb_register_frontend(adap, dvb->fe) < 0) -+ return -ENODEV; -+ } -+ if (dvb->fe2) { -+ if (dvb_register_frontend(adap, dvb->fe2) < 0) - return -ENODEV; -- if (input->fe2) { -- if (dvb_register_frontend(adap, input->fe2) < 0) -- return -ENODEV; -- input->fe2->tuner_priv = input->fe->tuner_priv; -- memcpy(&input->fe2->ops.tuner_ops, -- &input->fe->ops.tuner_ops, -- sizeof(struct dvb_tuner_ops)); -+ dvb->fe2->tuner_priv = dvb->fe->tuner_priv; -+ memcpy(&dvb->fe2->ops.tuner_ops, -+ &dvb->fe->ops.tuner_ops, -+ sizeof(struct dvb_tuner_ops)); -+ } -+ dvb->attached = 0x31; -+ return 0; -+} -+ -+ -+static int port_has_encti(struct ddb_port *port) -+{ -+ u8 val; -+ int ret = i2c_read_reg(&port->i2c->adap, 0x20, 0, &val); -+ -+ if (!ret) -+ pr_info("[0x20]=0x%02x\n", val); -+ return ret ? 0 : 1; -+} -+ -+static int port_has_cxd(struct ddb_port *port, u8 *type) -+{ -+ u8 val; -+ u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4]; -+ struct i2c_msg msgs[2] = {{ .addr = 0x40, .flags = 0, -+ .buf = probe, .len = 4 }, -+ { .addr = 0x40, .flags = I2C_M_RD, -+ .buf = data, .len = 4 } }; -+ val = i2c_transfer(&port->i2c->adap, msgs, 2); -+ if (val != 2) -+ return 0; -+ -+ if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43) -+ *type = 2; -+ else -+ *type = 1; -+ return 1; -+} -+ -+static int port_has_xo2(struct ddb_port *port, u8 *type, u8 *id) -+{ -+ u8 probe[1] = { 0x00 }, data[4]; -+ -+ if (i2c_io(&port->i2c->adap, 0x10, probe, 1, data, 4)) -+ return 0; -+ if (data[0] == 'D' && data[1] == 'F') { -+ *id = data[2]; -+ *type = 1; -+ return 1; -+ } -+ if (data[0] == 'C' && data[1] == 'I') { -+ *id = data[2]; -+ *type = 2; -+ return 1; -+ } -+ return 0; -+} -+ -+static int port_has_stv0900(struct ddb_port *port) -+{ -+ u8 val; -+ -+ if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0) -+ return 0; -+ return 1; -+} -+ -+static int port_has_stv0900_aa(struct ddb_port *port, u8 *id) -+{ -+ if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, id) < 0) -+ return 0; -+ return 1; -+} -+ -+static int port_has_drxks(struct ddb_port *port) -+{ -+ u8 val; -+ -+ if (i2c_read(&port->i2c->adap, 0x29, &val) < 0) -+ return 0; -+ if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0) -+ return 0; -+ return 1; -+} -+ -+static int port_has_stv0367(struct ddb_port *port) -+{ -+ u8 val; -+ -+ if (i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ if (i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ return 1; -+} -+ -+static int init_xo2(struct ddb_port *port) -+{ -+ struct i2c_adapter *i2c = &port->i2c->adap; -+ struct ddb *dev = port->dev; -+ u8 val, data[2]; -+ int res; -+ -+ res = i2c_read_regs(i2c, 0x10, 0x04, data, 2); -+ if (res < 0) -+ return res; -+ -+ if (data[0] != 0x01) { -+ pr_info("Port %d: invalid XO2\n", port->nr); -+ return -1; -+ } -+ -+ i2c_read_reg(i2c, 0x10, 0x08, &val); -+ if (val != 0) { -+ i2c_write_reg(i2c, 0x10, 0x08, 0x00); -+ msleep(100); -+ } -+ /* Enable tuner power, disable pll, reset demods */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x04); -+ usleep_range(2000, 3000); -+ /* Release demod resets */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x07); -+ -+ /* speed: 0=55,1=75,2=90,3=104 MBit/s */ -+ i2c_write_reg(i2c, 0x10, 0x09, 2); -+ -+ if (dev->link[port->lnr].info->con_clock) { -+ pr_info("Setting continuous clock for XO2\n"); -+ i2c_write_reg(i2c, 0x10, 0x0a, 0x03); -+ i2c_write_reg(i2c, 0x10, 0x0b, 0x03); -+ } else { -+ i2c_write_reg(i2c, 0x10, 0x0a, 0x01); -+ i2c_write_reg(i2c, 0x10, 0x0b, 0x01); -+ } -+ -+ usleep_range(2000, 3000); -+ /* Start XO2 PLL */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x87); -+ -+ return 0; -+} -+ -+static int init_xo2_ci(struct ddb_port *port) -+{ -+ struct i2c_adapter *i2c = &port->i2c->adap; -+ struct ddb *dev = port->dev; -+ u8 val, data[2]; -+ int res; -+ -+ res = i2c_read_regs(i2c, 0x10, 0x04, data, 2); -+ if (res < 0) -+ return res; -+ -+ if (data[0] > 1) { -+ pr_info("Port %d: invalid XO2 CI %02x\n", -+ port->nr, data[0]); -+ return -1; -+ } -+ pr_info("Port %d: DuoFlex CI %u.%u\n", port->nr, data[0], data[1]); -+ -+ i2c_read_reg(i2c, 0x10, 0x08, &val); -+ if (val != 0) { -+ i2c_write_reg(i2c, 0x10, 0x08, 0x00); -+ msleep(100); -+ } -+ /* Enable both CI */ -+ i2c_write_reg(i2c, 0x10, 0x08, 3); -+ usleep_range(2000, 3000); -+ -+ -+ /* speed: 0=55,1=75,2=90,3=104 MBit/s */ -+ i2c_write_reg(i2c, 0x10, 0x09, 1); -+ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x83); -+ usleep_range(2000, 3000); -+ -+ if (dev->link[port->lnr].info->con_clock) { -+ pr_info("Setting continuous clock for DuoFLex CI\n"); -+ i2c_write_reg(i2c, 0x10, 0x0a, 0x03); -+ i2c_write_reg(i2c, 0x10, 0x0b, 0x03); -+ } else { -+ i2c_write_reg(i2c, 0x10, 0x0a, 0x01); -+ i2c_write_reg(i2c, 0x10, 0x0b, 0x01); -+ } -+ return 0; -+} -+ -+static int port_has_cxd28xx(struct ddb_port *port, u8 *id) -+{ -+ struct i2c_adapter *i2c = &port->i2c->adap; -+ int status; -+ -+ status = i2c_write_reg(&port->i2c->adap, 0x6e, 0, 0); -+ if (status) -+ return 0; -+ status = i2c_read_reg(i2c, 0x6e, 0xfd, id); -+ if (status) -+ return 0; -+ return 1; -+} -+ -+static char *xo2names[] = { -+ "DUAL DVB-S2", "DUAL DVB-C/T/T2", -+ "DUAL DVB-ISDBT", "DUAL DVB-C/C2/T/T2", -+ "DUAL ATSC", "DUAL DVB-C/C2/T/T2", -+ "", "" -+}; -+ -+static char *xo2types[] = { -+ "DVBS_ST", "DVBCT2_SONY", -+ "ISDBT_SONY", "DVBC2T2_SONY", -+ "ATSC_ST", "DVBC2T2_ST" -+}; -+ -+static void ddb_port_probe(struct ddb_port *port) -+{ -+ struct ddb *dev = port->dev; -+ u32 l = port->lnr; -+ u8 id, type; -+ -+ port->name = "NO MODULE"; -+ port->type_name = "NONE"; -+ port->class = DDB_PORT_NONE; -+ -+ /* Handle missing ports and ports without I2C */ -+ -+ if (port->nr == ts_loop) { -+ port->name = "TS LOOP"; -+ port->class = DDB_PORT_LOOP; -+ return; -+ } -+ -+ if (port->nr == 1 && dev->link[l].info->type == DDB_OCTOPUS_CI && -+ dev->link[l].info->i2c_mask == 1) { -+ port->name = "NO TAB"; -+ port->class = DDB_PORT_NONE; -+ return; -+ } -+ -+ if (dev->link[l].info->type == DDB_OCTOPUS_MAX) { -+ port->name = "DUAL DVB-S2 MAX"; -+ port->type_name = "MXL5XX"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_MXL5XX; -+ if (port->i2c) -+ ddbwritel(dev, I2C_SPEED_400, -+ port->i2c->regs + I2C_TIMING); -+ return; -+ } -+ -+ if (dev->link[l].info->type == DDB_MOD) { -+ port->name = "MOD"; -+ port->class = DDB_PORT_MOD; -+ return; -+ } -+ -+ if (port->nr > 1 && dev->link[l].info->type == DDB_OCTOPUS_CI) { -+ port->name = "CI internal"; -+ port->type_name = "INTERNAL"; -+ port->class = DDB_PORT_CI; -+ port->type = DDB_CI_INTERNAL; -+ } -+ -+ if (!port->i2c) -+ return; -+ -+ /* Probe ports with I2C */ -+ -+ if (port_has_cxd(port, &id)) { -+ if (id == 1) { -+ port->name = "CI"; -+ port->type_name = "CXD2099"; -+ port->class = DDB_PORT_CI; -+ port->type = DDB_CI_EXTERNAL_SONY; -+ ddbwritel(dev, I2C_SPEED_400, -+ port->i2c->regs + I2C_TIMING); -+ } else { -+ pr_info("Port %d: Uninitialized DuoFlex\n", -+ port->nr); -+ return; -+ } -+ } else if (port_has_xo2(port, &type, &id)) { -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ /*pr_info("XO2 ID %02x\n", id);*/ -+ if (type == 2) { -+ port->name = "DuoFlex CI"; -+ port->class = DDB_PORT_CI; -+ port->type = DDB_CI_EXTERNAL_XO2; -+ port->type_name = "CI_XO2"; -+ init_xo2_ci(port); -+ return; -+ } -+ id >>= 2; -+ if (id > 5) { -+ port->name = "unknown XO2 DuoFlex"; -+ port->type_name = "UNKNOWN"; -+ } else { -+ port->name = xo2names[id]; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_XO2 + id; -+ port->type_name = xo2types[id]; -+ init_xo2(port); -+ } -+ } else if (port_has_cxd28xx(port, &id)) { -+ switch (id) { -+ case 0xa4: -+ port->name = "DUAL DVB-C2T2 CXD2843"; -+ port->type = DDB_TUNER_DVBC2T2_SONY_P; -+ port->type_name = "DVBC2T2_SONY"; -+ break; -+ case 0xb1: -+ port->name = "DUAL DVB-CT2 CXD2837"; -+ port->type = DDB_TUNER_DVBCT2_SONY_P; -+ port->type_name = "DVBCT2_SONY"; -+ break; -+ case 0xb0: -+ port->name = "DUAL ISDB-T CXD2838"; -+ port->type = DDB_TUNER_ISDBT_SONY_P; -+ port->type_name = "ISDBT_SONY"; -+ break; -+ default: -+ return; -+ } -+ port->class = DDB_PORT_TUNER; -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_stv0900(port)) { -+ port->name = "DUAL DVB-S2"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBS_ST; -+ port->type_name = "DVBS_ST"; -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_stv0900_aa(port, &id)) { -+ port->name = "DUAL DVB-S2"; -+ port->class = DDB_PORT_TUNER; -+ if (id == 0x51) { -+ if (port->nr == 0 && -+ dev->link[l].info->ts_quirks & TS_QUIRK_REVERSED) -+ port->type = DDB_TUNER_DVBS_STV0910_PR; -+ else -+ port->type = DDB_TUNER_DVBS_STV0910_P; -+ port->type_name = "DVBS_ST_0910"; -+ } else { -+ port->type = DDB_TUNER_DVBS_ST_AA; -+ port->type_name = "DVBS_ST_AA"; - } -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_drxks(port)) { -+ port->name = "DUAL DVB-C/T"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBCT_TR; -+ port->type_name = "DVBCT_TR"; -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_stv0367(port)) { -+ port->name = "DUAL DVB-C/T"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBCT_ST; -+ port->type_name = "DVBCT_ST"; -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_encti(port)) { -+ port->name = "ENCTI"; -+ port->class = DDB_PORT_LOOP; -+ } -+} -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static int wait_ci_ready(struct ddb_ci *ci) -+{ -+ u32 count = 10; -+ -+ ndelay(500); -+ do { -+ if (ddbreadl(ci->port->dev, -+ CI_CONTROL(ci->nr)) & CI_READY) -+ break; -+ usleep_range(1, 2); -+ if ((--count) == 0) -+ return -1; -+ } while (1); -+ return 0; -+} -+ -+static int read_attribute_mem(struct dvb_ca_en50221 *ca, -+ int slot, int address) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1); -+ -+ if (address > CI_BUFFER_SIZE) -+ return -1; -+ ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, -+ CI_DO_READ_ATTRIBUTES(ci->nr)); -+ wait_ci_ready(ci); -+ val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); -+ return val; -+} -+ -+static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, -+ int address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, -+ CI_DO_ATTRIBUTE_RW(ci->nr)); -+ wait_ci_ready(ci); -+ return 0; -+} -+ -+static int read_cam_control(struct dvb_ca_en50221 *ca, -+ int slot, u8 address) -+{ -+ u32 count = 100; -+ struct ddb_ci *ci = ca->data; -+ u32 res; -+ -+ ddbwritel(ci->port->dev, CI_READ_CMD | address, -+ CI_DO_IO_RW(ci->nr)); -+ ndelay(500); -+ do { -+ res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); -+ if (res & CI_READY) -+ break; -+ usleep_range(1, 2); -+ if ((--count) == 0) -+ return -1; -+ } while (1); -+ return 0xff & res; -+} -+ -+static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, -+ u8 address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, -+ CI_DO_IO_RW(ci->nr)); -+ wait_ci_ready(ci); -+ return 0; -+} -+ -+static int slot_reset(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_POWER_ON, -+ CI_CONTROL(ci->nr)); -+ msleep(100); -+ ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, -+ CI_CONTROL(ci->nr)); -+ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, -+ CI_CONTROL(ci->nr)); -+ udelay(20); -+ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, -+ CI_CONTROL(ci->nr)); -+ return 0; -+} -+ -+static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); -+ msleep(300); -+ return 0; -+} -+ -+static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); -+ -+ ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, -+ CI_CONTROL(ci->nr)); -+ return 0; -+} -+ -+static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); -+ int stat = 0; -+ -+ if (val & CI_CAM_DETECT) -+ stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; -+ if (val & CI_CAM_READY) -+ stat |= DVB_CA_EN50221_POLL_CAM_READY; -+ return stat; -+} -+ -+static struct dvb_ca_en50221 en_templ = { -+ .read_attribute_mem = read_attribute_mem, -+ .write_attribute_mem = write_attribute_mem, -+ .read_cam_control = read_cam_control, -+ .write_cam_control = write_cam_control, -+ .slot_reset = slot_reset, -+ .slot_shutdown = slot_shutdown, -+ .slot_ts_enable = slot_ts_enable, -+ .poll_slot_status = poll_slot_status, -+}; -+ -+static void ci_attach(struct ddb_port *port) -+{ -+ struct ddb_ci *ci = 0; -+ -+ ci = kzalloc(sizeof(*ci), GFP_KERNEL); -+ if (!ci) -+ return; -+ memcpy(&ci->en, &en_templ, sizeof(en_templ)); -+ ci->en.data = ci; -+ port->en = &ci->en; -+ ci->port = port; -+ ci->nr = port->nr - 2; -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static int write_creg(struct ddb_ci *ci, u8 data, u8 mask) -+{ -+ struct i2c_adapter *i2c = &ci->port->i2c->adap; -+ u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; -+ -+ ci->port->creg = (ci->port->creg & ~mask) | data; -+ return i2c_write_reg(i2c, adr, 0x02, ci->port->creg); -+} -+ -+static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca, -+ int slot, int address) -+{ -+ struct ddb_ci *ci = ca->data; -+ struct i2c_adapter *i2c = &ci->port->i2c->adap; -+ u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; -+ int res; -+ u8 val; -+ -+ res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val); -+ return res ? res : val; -+} -+ -+static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot, -+ int address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ struct i2c_adapter *i2c = &ci->port->i2c->adap; -+ u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; -+ -+ return i2c_write_reg16(i2c, adr, 0x8000 | address, value); -+} -+ -+static int read_cam_control_xo2(struct dvb_ca_en50221 *ca, -+ int slot, u8 address) -+{ -+ struct ddb_ci *ci = ca->data; -+ struct i2c_adapter *i2c = &ci->port->i2c->adap; -+ u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; -+ u8 val; -+ int res; -+ -+ res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val); -+ return res ? res : val; -+} -+ -+static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot, -+ u8 address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ struct i2c_adapter *i2c = &ci->port->i2c->adap; -+ u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; -+ -+ return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value); -+} -+ -+static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ pr_info("%s\n", __func__); -+ write_creg(ci, 0x01, 0x01); -+ write_creg(ci, 0x04, 0x04); -+ msleep(20); -+ write_creg(ci, 0x02, 0x02); -+ write_creg(ci, 0x00, 0x04); -+ write_creg(ci, 0x18, 0x18); -+ return 0; -+} -+ -+static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ pr_info("%s\n", __func__); -+ write_creg(ci, 0x10, 0xff); -+ write_creg(ci, 0x08, 0x08); -+ return 0; -+} -+ -+static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ pr_info("%s\n", __func__); -+ write_creg(ci, 0x00, 0x10); -+ return 0; -+} -+ -+static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open) -+{ -+ struct ddb_ci *ci = ca->data; -+ struct i2c_adapter *i2c = &ci->port->i2c->adap; -+ u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; -+ u8 val = 0; -+ int stat = 0; -+ -+ i2c_read_reg(i2c, adr, 0x01, &val); -+ -+ if (val & 2) -+ stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; -+ if (val & 1) -+ stat |= DVB_CA_EN50221_POLL_CAM_READY; -+ return stat; -+} -+ -+static struct dvb_ca_en50221 en_xo2_templ = { -+ .read_attribute_mem = read_attribute_mem_xo2, -+ .write_attribute_mem = write_attribute_mem_xo2, -+ .read_cam_control = read_cam_control_xo2, -+ .write_cam_control = write_cam_control_xo2, -+ .slot_reset = slot_reset_xo2, -+ .slot_shutdown = slot_shutdown_xo2, -+ .slot_ts_enable = slot_ts_enable_xo2, -+ .poll_slot_status = poll_slot_status_xo2, -+}; -+ -+static void ci_xo2_attach(struct ddb_port *port) -+{ -+ struct ddb_ci *ci = 0; -+ struct i2c_adapter *i2c; -+ -+ ci = kzalloc(sizeof(*ci), GFP_KERNEL); -+ if (!ci) -+ return; -+ memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ)); -+ ci->en.data = ci; -+ port->en = &ci->en; -+ ci->port = port; -+ ci->nr = port->nr - 2; -+ ci->port->creg = 0; -+ i2c = &ci->port->i2c->adap; -+ write_creg(ci, 0x10, 0xff); -+ write_creg(ci, 0x08, 0x08); -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+ -+struct cxd2099_cfg cxd_cfg = { -+ .bitrate = 72000, -+ .adr = 0x40, -+ .polarity = 1, -+ .clock_mode = 1, -+ .max_i2c = 512, -+}; -+ -+static int ddb_ci_attach(struct ddb_port *port) -+{ -+ switch (port->type) { -+ case DDB_CI_EXTERNAL_SONY: -+ cxd_cfg.bitrate = ci_bitrate; -+ port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); -+ if (!port->en) -+ return -ENODEV; -+ dvb_ca_en50221_init(port->dvb[0].adap, -+ port->en, 0, 1); -+ break; -+ -+ case DDB_CI_EXTERNAL_XO2: -+ case DDB_CI_EXTERNAL_XO2_B: -+ ci_xo2_attach(port); -+ if (!port->en) -+ return -ENODEV; -+ dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); -+ break; -+ -+ case DDB_CI_INTERNAL: -+ ci_attach(port); -+ if (!port->en) -+ return -ENODEV; -+ dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); -+ break; -+ } -+ return 0; -+} -+ -+static int ddb_port_attach(struct ddb_port *port) -+{ -+ int ret = 0; -+ -+ switch (port->class) { -+ case DDB_PORT_TUNER: -+ ret = dvb_input_attach(port->input[0]); -+ if (ret < 0) -+ break; -+ ret = dvb_input_attach(port->input[1]); -+ if (ret < 0) -+ break; -+ port->input[0]->redi = port->input[0]; -+ port->input[1]->redi = port->input[1]; -+ break; -+ case DDB_PORT_CI: -+ ret = ddb_ci_attach(port); -+ if (ret < 0) -+ break; -+ case DDB_PORT_LOOP: -+ ret = dvb_register_device(port->dvb[0].adap, -+ &port->dvb[0].dev, -+ &dvbdev_ci, (void *) port->output, -+ DVB_DEVICE_CI, 0); -+ break; -+ case DDB_PORT_MOD: -+ ret = dvb_register_device(port->dvb[0].adap, -+ &port->dvb[0].dev, -+ &dvbdev_mod, (void *) port->output, -+ DVB_DEVICE_MOD, 0); -+ break; -+ default: -+ break; -+ } -+ if (ret < 0) -+ pr_err("port_attach on port %d failed\n", port->nr); -+ return ret; -+} -+ -+static int ddb_ports_attach(struct ddb *dev) -+{ -+ int i, ret = 0; -+ struct ddb_port *port; -+ -+ dev->ns_num = dev->link[0].info->ns_num; -+ for (i = 0; i < dev->ns_num; i++) -+ dev->ns[i].nr = i; -+ pr_info("%d netstream channels\n", dev->ns_num); -+ -+ if (dev->port_num) { -+ ret = dvb_register_adapters(dev); -+ if (ret < 0) { -+ pr_err("Registering adapters failed. Check DVB_MAX_ADAPTERS in config.\n"); -+ return ret; -+ } -+ } -+ for (i = 0; i < dev->port_num; i++) { -+ port = &dev->port[i]; -+ ret = ddb_port_attach(port); -+ } -+ return ret; -+} -+ -+static void ddb_ports_detach(struct ddb *dev) -+{ -+ int i; -+ struct ddb_port *port; -+ -+ for (i = 0; i < dev->port_num; i++) { -+ port = &dev->port[i]; -+ -+ switch (port->class) { -+ case DDB_PORT_TUNER: -+ dvb_input_detach(port->input[0]); -+ dvb_input_detach(port->input[1]); -+ break; -+ case DDB_PORT_CI: -+ case DDB_PORT_LOOP: -+ if (port->dvb[0].dev) -+ dvb_unregister_device(port->dvb[0].dev); -+ if (port->en) { -+ dvb_ca_en50221_release(port->en); -+ kfree(port->en); -+ port->en = NULL; -+ } -+ break; -+ case DDB_PORT_MOD: -+ if (port->dvb[0].dev) -+ dvb_unregister_device(port->dvb[0].dev); -+ break; -+ } -+ } -+ dvb_unregister_adapters(dev); -+} -+ -+ -+/* Copy input DMA pointers to output DMA and ACK. */ -+ -+static void input_write_output(struct ddb_input *input, -+ struct ddb_output *output) -+{ -+ ddbwritel(output->port->dev, -+ input->dma->stat, DMA_BUFFER_ACK(output->dma->nr)); -+ output->dma->cbuf = (input->dma->stat >> 11) & 0x1f; -+ output->dma->coff = (input->dma->stat & 0x7ff) << 7; -+} -+ -+static void output_ack_input(struct ddb_output *output, -+ struct ddb_input *input) -+{ -+ ddbwritel(input->port->dev, -+ output->dma->stat, DMA_BUFFER_ACK(input->dma->nr)); -+} -+ -+static void input_write_dvb(struct ddb_input *input, -+ struct ddb_input *input2) -+{ -+ struct ddb_dvb *dvb = &input2->port->dvb[input2->nr & 1]; -+ struct ddb_dma *dma, *dma2; -+ struct ddb *dev = input->port->dev; -+ int ack = 1; -+ -+ dma = dma2 = input->dma; -+ /* if there also is an output connected, do not ACK. -+ * input_write_output will ACK. -+ */ -+ if (input->redo) { -+ dma2 = input->redo->dma; -+ ack = 0; -+ } -+ while (dma->cbuf != ((dma->stat >> 11) & 0x1f) -+ || (4 & dma->ctrl)) { -+ if (4 & dma->ctrl) { -+ /*pr_err("Overflow dma %d\n", dma->nr);*/ -+ ack = 1; -+ } -+#ifdef DDB_ALT_DMA -+ dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], -+ dma2->size, DMA_FROM_DEVICE); -+#endif -+ dvb_dmx_swfilter_packets(&dvb->demux, -+ dma2->vbuf[dma->cbuf], -+ dma2->size / 188); -+ dma->cbuf = (dma->cbuf + 1) % dma2->num; -+ if (ack) -+ ddbwritel(dev, (dma->cbuf << 11), -+ DMA_BUFFER_ACK(dma->nr)); -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ } -+} -+ -+#ifdef DDB_USE_WORK -+static void input_work(struct work_struct *work) -+{ -+ struct ddb_dma *dma = container_of(work, struct ddb_dma, work); -+ struct ddb_input *input = (struct ddb_input *) dma->io; -+#else -+static void input_tasklet(unsigned long data) -+{ -+ struct ddb_input *input = (struct ddb_input *) data; -+ struct ddb_dma *dma = input->dma; -+#endif -+ struct ddb *dev = input->port->dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dma->lock, flags); -+ if (!dma->running) { -+ spin_unlock_irqrestore(&dma->lock, flags); -+ return; -+ } -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ -+ if (input->redi) -+ input_write_dvb(input, input->redi); -+ if (input->redo) -+ input_write_output(input, input->redo); -+ wake_up(&dma->wq); -+ spin_unlock_irqrestore(&dma->lock, flags); -+} -+ -+static void input_handler(unsigned long data) -+{ -+ struct ddb_input *input = (struct ddb_input *) data; -+ struct ddb_dma *dma = input->dma; -+ -+ -+ /* If there is no input connected, input_tasklet() will -+ * just copy pointers and ACK. So, there is no need to go -+ * through the tasklet scheduler. -+ */ -+#ifdef DDB_USE_WORK -+ if (input->redi) -+ queue_work(ddb_wq, &dma->work); -+ else -+ input_work(&dma->work); -+#else -+ if (input->redi) -+ tasklet_schedule(&dma->tasklet); -+ else -+ input_tasklet(data); -+#endif -+} -+ -+static void output_handler(unsigned long data) -+{ -+ struct ddb_output *output = (struct ddb_output *) data; -+ struct ddb_dma *dma = output->dma; -+ struct ddb *dev = output->port->dev; -+ -+ spin_lock(&dma->lock); -+ if (!dma->running) { -+ spin_unlock(&dma->lock); -+ return; -+ } -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ if (output->redi) -+ output_ack_input(output, output->redi); -+ wake_up(&dma->wq); -+ spin_unlock(&dma->lock); -+} -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+ -+static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out) -+{ -+#ifndef DDB_USE_WORK -+ unsigned long priv = (unsigned long) io; -+#endif -+ -+ dma->io = io; -+ dma->nr = nr; -+ spin_lock_init(&dma->lock); -+ init_waitqueue_head(&dma->wq); -+ if (out) { -+ dma->num = OUTPUT_DMA_BUFS; -+ dma->size = OUTPUT_DMA_SIZE; -+ dma->div = OUTPUT_DMA_IRQ_DIV; -+ } else { -+#ifdef DDB_USE_WORK -+ INIT_WORK(&dma->work, input_work); -+#else -+ tasklet_init(&dma->tasklet, input_tasklet, priv); -+#endif -+ dma->num = INPUT_DMA_BUFS; -+ dma->size = INPUT_DMA_SIZE; -+ dma->div = INPUT_DMA_IRQ_DIV; -+ } -+} -+ -+static void ddb_input_init(struct ddb_port *port, int nr, int pnr, -+ int dma_nr, int anr) -+{ -+ struct ddb *dev = port->dev; -+ struct ddb_input *input = &dev->input[anr]; -+ -+ if (dev->has_dma) { -+ dev->handler[dma_nr + 8] = input_handler; -+ dev->handler_data[dma_nr + 8] = (unsigned long) input; -+ } -+ port->input[pnr] = input; -+ input->nr = nr; -+ input->port = port; -+ if (dev->has_dma) { -+ input->dma = &dev->dma[dma_nr]; -+ ddb_dma_init(input->dma, dma_nr, (void *) input, 0); -+ } -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); -+ ddbwritel(dev, 2, TS_INPUT_CONTROL(nr)); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); -+ if (input->dma) -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); -+} -+ -+static void ddb_output_init(struct ddb_port *port, int nr, int dma_nr) -+{ -+ struct ddb *dev = port->dev; -+ struct ddb_output *output = &dev->output[nr]; -+ -+ if (dev->has_dma) { -+ dev->handler[dma_nr + 8] = output_handler; -+ dev->handler_data[dma_nr + 8] = (unsigned long) output; -+ } -+ port->output = output; -+ output->nr = nr; -+ output->port = port; -+ if (dev->has_dma) { -+ output->dma = &dev->dma[dma_nr]; -+ ddb_dma_init(output->dma, dma_nr, (void *) output, 1); -+ } -+ if (output->port->class == DDB_PORT_MOD) { -+ /*ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));*/ -+ } else { -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); -+ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr)); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); -+ } -+ if (output->dma) -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); -+} -+ -+static int ddb_port_match_i2c(struct ddb_port *port) -+{ -+ struct ddb *dev = port->dev; -+ u32 i; -+ -+ for (i = 0; i < dev->i2c_num; i++) { -+ if (dev->i2c[i].link == port->lnr && -+ dev->i2c[i].nr == port->nr) { -+ port->i2c = &dev->i2c[i]; -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+static void ddb_ports_init(struct ddb *dev) -+{ -+ u32 i, l, p, li2c; -+ struct ddb_port *port; -+ struct ddb_info *info; -+ struct ddb_regmap *rm; -+ int portmatch; -+ -+ for (p = l = 0; l < DDB_MAX_LINK; l++) { -+ info = dev->link[l].info; -+ if (!info) -+ continue; -+ rm = info->regmap; -+ if (!rm) -+ continue; -+ for (li2c = 0; li2c < dev->i2c_num; li2c++) -+ if (dev->i2c[li2c].link == l) -+ break; -+ for (i = 0; i < info->port_num; i++, p++) { -+ port = &dev->port[p]; -+ port->dev = dev; -+ port->nr = i; -+ port->lnr = l; -+ port->pnr = p; -+ port->gap = 4; -+ port->obr = ci_bitrate; -+ mutex_init(&port->i2c_gate_lock); -+ -+ portmatch = ddb_port_match_i2c(port); -+ if (!portmatch) { -+ if (info->type == DDB_OCTOPUS_MAX) -+ port->i2c = &dev->i2c[li2c]; -+ } -+ -+ ddb_port_probe(port); -+ -+ port->dvb[0].adap = &dev->adap[2 * p]; -+ port->dvb[1].adap = &dev->adap[2 * p + 1]; -+ -+ if ((port->class == DDB_PORT_NONE) && i && -+ dev->port[p - 1].type == DDB_CI_EXTERNAL_XO2) { -+ port->class = DDB_PORT_CI; -+ port->type = DDB_CI_EXTERNAL_XO2_B; -+ port->name = "DuoFlex CI_B"; -+ port->i2c = dev->port[p - 1].i2c; -+ } -+ -+ pr_info("Port %u: Link %u, Link Port %u (TAB %u): %s\n", -+ port->pnr, port->lnr, port->nr, port->nr + 1, -+ port->name); -+ -+ if (port->class == DDB_PORT_CI && -+ port->type == DDB_CI_EXTERNAL_XO2) { -+ ddb_input_init(port, 2 * i, 0, 2 * i, 2 * i); -+ ddb_output_init(port, i, i + 8); -+ continue; -+ } -+ -+ if (port->class == DDB_PORT_CI && -+ port->type == DDB_CI_EXTERNAL_XO2_B) { -+ ddb_input_init(port, 2 * i - 1, 0, 2 * i - 1, -+ 2 * i - 1); -+ ddb_output_init(port, i, i + 8); -+ continue; -+ } -+ -+ switch (dev->link[l].info->type) { -+ case DDB_OCTOPUS_CI: -+ if (i >= 2) { -+ ddb_input_init(port, 2 + i, 0, 2 + i, -+ 2 + i); -+ ddb_input_init(port, 4 + i, 1, 4 + i, -+ 4 + i); -+ ddb_output_init(port, i, i + 8); -+ break; -+ } /* fallthrough */ -+ case DDB_OCTONET: -+ case DDB_OCTOPUS: -+ ddb_input_init(port, 2 * i, 0, 2 * i, 2 * i); -+ ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1, -+ 2 * i + 1); -+ ddb_output_init(port, i, i + 8); -+ break; -+ case DDB_OCTOPUS_MAX: -+ case DDB_OCTOPUS_MAX_CT: -+ ddb_input_init(port, 2 * i, 0, 2 * i, 2 * p); -+ ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1, -+ 2 * p + 1); -+ break; -+ case DDB_MOD: -+ ddb_output_init(port, i, i); -+ dev->handler[i + 18] = ddbridge_mod_rate_handler; -+ dev->handler_data[i + 18] = -+ (unsigned long) &dev->output[i]; -+ break; -+ default: -+ break; -+ } -+ } -+ } -+ dev->port_num = p; -+} -+ -+static void ddb_ports_release(struct ddb *dev) -+{ -+ int i; -+ struct ddb_port *port; -+ -+ for (i = 0; i < dev->port_num; i++) { -+ port = &dev->port[i]; -+#ifdef DDB_USE_WORK -+ if (port->input[0] && port->input[0]->dma) -+ cancel_work_sync(&port->input[0]->dma->work); -+ if (port->input[1] && port->input[1]->dma) -+ cancel_work_sync(&port->input[1]->dma->work); -+ if (port->output && port->output->dma) -+ cancel_work_sync(&port->output->dma->work); -+#else -+ if (port->input[0] && port->input[0]->dma) -+ tasklet_kill(&port->input[0]->dma->tasklet); -+ if (port->input[1] && port->input[1]->dma) -+ tasklet_kill(&port->input[1]->dma->tasklet); -+ if (port->output && port->output->dma) -+ tasklet_kill(&port->output->dma->tasklet); -+#endif -+ } -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+#define IRQ_HANDLE(_nr) \ -+ do { if ((s & (1UL << _nr)) && dev->handler[_nr]) \ -+ dev->handler[_nr](dev->handler_data[_nr]); } \ -+ while (0) -+ -+static void irq_handle_msg(struct ddb *dev, u32 s) -+{ -+ dev->i2c_irq++; -+ IRQ_HANDLE(0); -+ IRQ_HANDLE(1); -+ IRQ_HANDLE(2); -+ IRQ_HANDLE(3); -+} -+ -+static void irq_handle_io(struct ddb *dev, u32 s) -+{ -+ dev->ts_irq++; -+ if ((s & 0x000000f0)) { -+ IRQ_HANDLE(4); -+ IRQ_HANDLE(5); -+ IRQ_HANDLE(6); -+ IRQ_HANDLE(7); -+ } -+ if ((s & 0x0000ff00)) { -+ IRQ_HANDLE(8); -+ IRQ_HANDLE(9); -+ IRQ_HANDLE(10); -+ IRQ_HANDLE(11); -+ IRQ_HANDLE(12); -+ IRQ_HANDLE(13); -+ IRQ_HANDLE(14); -+ IRQ_HANDLE(15); -+ } -+ if ((s & 0x00ff0000)) { -+ IRQ_HANDLE(16); -+ IRQ_HANDLE(17); -+ IRQ_HANDLE(18); -+ IRQ_HANDLE(19); -+ IRQ_HANDLE(20); -+ IRQ_HANDLE(21); -+ IRQ_HANDLE(22); -+ IRQ_HANDLE(23); -+ } -+ if ((s & 0xff000000)) { -+ IRQ_HANDLE(24); -+ IRQ_HANDLE(25); -+ IRQ_HANDLE(26); -+ IRQ_HANDLE(27); -+ IRQ_HANDLE(28); -+ IRQ_HANDLE(29); -+ IRQ_HANDLE(30); -+ IRQ_HANDLE(31); -+ } -+} -+ -+#ifdef DDB_USE_MSI_IRQHANDLERS -+static irqreturn_t irq_handler0(int irq, void *dev_id) -+{ -+ struct ddb *dev = (struct ddb *) dev_id; -+ u32 s = ddbreadl(dev, INTERRUPT_STATUS); -+ -+ do { -+ if (s == 0xffffffff) -+ return IRQ_NONE; -+ if (!(s & 0xfff00)) -+ return IRQ_NONE; -+ ddbwritel(dev, s, INTERRUPT_ACK); -+ irq_handle_io(dev, s); -+ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t irq_handler1(int irq, void *dev_id) -+{ -+ struct ddb *dev = (struct ddb *) dev_id; -+ u32 s = ddbreadl(dev, INTERRUPT_STATUS); -+ -+ do { -+ if (s & 0x80000000) -+ return IRQ_NONE; -+ if (!(s & 0x0000f)) -+ return IRQ_NONE; -+ ddbwritel(dev, s, INTERRUPT_ACK); -+ irq_handle_msg(dev, s); -+ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+static irqreturn_t irq_handler(int irq, void *dev_id) -+{ -+ struct ddb *dev = (struct ddb *) dev_id; -+ u32 s = ddbreadl(dev, INTERRUPT_STATUS); -+ int ret = IRQ_HANDLED; -+ -+ if (!s) -+ return IRQ_NONE; -+ do { -+ if (s & 0x80000000) -+ return IRQ_NONE; -+ ddbwritel(dev, s, INTERRUPT_ACK); -+ -+ if (s & 0x0000000f) -+ irq_handle_msg(dev, s); -+ if (s & 0x0fffff00) { -+ irq_handle_io(dev, s); -+#ifdef DDB_TEST_THREADED -+ ret = IRQ_WAKE_THREAD; -+#endif -+ } -+ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); -+ -+ return ret; -+} -+ -+#ifdef DDB_TEST_THREADED -+static irqreturn_t irq_thread(int irq, void *dev_id) -+{ -+ /* struct ddb *dev = (struct ddb *) dev_id; */ -+ -+ /*pr_info("%s\n", __func__);*/ -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static ssize_t nsd_read(struct file *file, char *buf, -+ size_t count, loff_t *ppos) -+{ -+ return 0; -+} -+ -+static unsigned int nsd_poll(struct file *file, poll_table *wait) -+{ -+ return 0; -+} -+ -+static int nsd_release(struct inode *inode, struct file *file) -+{ -+ return dvb_generic_release(inode, file); -+} -+ -+static int nsd_open(struct inode *inode, struct file *file) -+{ -+ return dvb_generic_open(inode, file); -+} -+ -+static struct ddb_input *plugtoinput(struct ddb *dev, u8 plug) -+{ -+ int i, j; -+ -+ for (i = j = 0; i < dev->port_num; i++) { -+ if (dev->port[i].class == DDB_PORT_TUNER) { -+ if (j == plug) -+ return dev->port[i].input[0]; -+ if (j + 1 == plug) -+ return dev->port[i].input[1]; -+ j += 2; -+ } -+ } -+ return 0; -+} -+ -+static int nsd_do_ioctl(struct file *file, unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb *dev = dvbdev->priv; -+ -+ /* unsigned long arg = (unsigned long) parg; */ -+ int ret = 0; -+ -+ switch (cmd) { -+ case NSD_START_GET_TS: -+ { -+ struct dvb_nsd_ts *ts = parg; -+ struct ddb_input *input = plugtoinput(dev, ts->input); -+ u32 ctrl; -+ u32 to; -+ -+ if (!input) -+ return -EINVAL; -+ ctrl = (input->port->lnr << 16) | ((input->nr & 7) << 8) | -+ ((ts->filter_mask & 3) << 2); -+ if (ddbreadl(dev, TS_CAPTURE_CONTROL) & 1) { -+ pr_info("ts capture busy\n"); -+ return -EBUSY; -+ } -+ ddb_dvb_ns_input_start(input); -+ -+ ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL); -+ ddbwritel(dev, ts->pid, TS_CAPTURE_PID); -+ ddbwritel(dev, (ts->section_id << 16) | -+ (ts->table << 8) | ts->section, -+ TS_CAPTURE_TABLESECTION); -+ /* 1024 ms default timeout if timeout set to 0 */ -+ if (ts->timeout) -+ to = ts->timeout; -+ else -+ to = 1024; -+ /* 21 packets default if num set to 0 */ -+ if (ts->num) -+ to |= ((u32) ts->num << 16); -+ else -+ to |= (21 << 16); -+ ddbwritel(dev, to, TS_CAPTURE_TIMEOUT); -+ if (ts->mode) -+ ctrl |= 2; -+ ddbwritel(dev, ctrl | 1, TS_CAPTURE_CONTROL); -+ break; -+ } -+ case NSD_POLL_GET_TS: -+ { -+ struct dvb_nsd_ts *ts = parg; -+ u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); -+ -+ if (ctrl & 1) -+ return -EBUSY; -+ if (ctrl & (1 << 14)) { -+ /*pr_info("ts capture timeout\n");*/ -+ return -EAGAIN; -+ } -+ ddbcpyfrom(dev, dev->tsbuf, TS_CAPTURE_MEMORY, -+ TS_CAPTURE_LEN); -+ ts->len = ddbreadl(dev, TS_CAPTURE_RECEIVED) & 0x1fff; -+ if (copy_to_user(ts->ts, dev->tsbuf, ts->len)) -+ return -EIO; -+ break; -+ } -+ case NSD_CANCEL_GET_TS: -+ { -+ u32 ctrl = 0; -+ -+ /*pr_info("cancel ts capture: 0x%x\n", ctrl);*/ -+ ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL); -+ ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); -+ /*pr_info("control register is 0x%x\n", ctrl);*/ -+ break; -+ } -+ case NSD_STOP_GET_TS: -+ { -+ struct dvb_nsd_ts *ts = parg; -+ struct ddb_input *input = plugtoinput(dev, ts->input); -+ u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); -+ -+ if (!input) -+ return -EINVAL; -+ if (ctrl & 1) { -+ pr_info("cannot stop ts capture, while it was neither finished not canceled\n"); -+ return -EBUSY; -+ } -+ /*pr_info("ts capture stopped\n");*/ -+ ddb_dvb_ns_input_stop(input); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+static long nsd_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy(file, cmd, arg, nsd_do_ioctl); -+} -+ -+static const struct file_operations nsd_fops = { -+ .owner = THIS_MODULE, -+ .read = nsd_read, -+ .open = nsd_open, -+ .release = nsd_release, -+ .poll = nsd_poll, -+ .unlocked_ioctl = nsd_ioctl, -+}; -+ -+static struct dvb_device dvbdev_nsd = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 1, -+ .fops = &nsd_fops, -+}; -+ -+static int ddb_nsd_attach(struct ddb *dev) -+{ -+ int ret; -+ -+ if (!dev->link[0].info->ns_num) -+ return 0; -+ ret = dvb_register_device(&dev->adap[0], -+ &dev->nsd_dev, -+ &dvbdev_nsd, (void *) dev, -+ DVB_DEVICE_NSD, 0); -+ return ret; -+} -+ -+static void ddb_nsd_detach(struct ddb *dev) -+{ -+ if (!dev->link[0].info->ns_num) -+ return; -+ -+ if (dev->nsd_dev->users > 2) { -+ wait_event(dev->nsd_dev->wait_queue, -+ dev->nsd_dev->users == 2); -+ } -+ dvb_unregister_device(dev->nsd_dev); -+} -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static int reg_wait(struct ddb *dev, u32 reg, u32 bit) -+{ -+ u32 count = 0; -+ -+ while (ddbreadl(dev, reg) & bit) { -+ ndelay(10); -+ if (++count == 100) -+ return -1; -+ } -+ return 0; -+} -+ -+static int flashio(struct ddb *dev, u32 lnr, u8 *wbuf, u32 wlen, u8 *rbuf, -+ u32 rlen) -+{ -+ u32 data, shift; -+ u32 tag = DDB_LINK_TAG(lnr); -+ struct ddb_link *link = &dev->link[lnr]; -+ -+ mutex_lock(&link->flash_mutex); -+ if (wlen > 4) -+ ddbwritel(dev, 1, tag | SPI_CONTROL); -+ while (wlen > 4) { -+ /* FIXME: check for big-endian */ -+ data = swab32(*(u32 *) wbuf); -+ wbuf += 4; -+ wlen -= 4; -+ ddbwritel(dev, data, tag | SPI_DATA); -+ if (reg_wait(dev, tag | SPI_CONTROL, 4)) -+ goto fail; -+ } -+ if (rlen) -+ ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), -+ tag | SPI_CONTROL); -+ else -+ ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), -+ tag | SPI_CONTROL); -+ -+ data = 0; -+ shift = ((4 - wlen) * 8); -+ while (wlen) { -+ data <<= 8; -+ data |= *wbuf; -+ wlen--; -+ wbuf++; -+ } -+ if (shift) -+ data <<= shift; -+ ddbwritel(dev, data, tag | SPI_DATA); -+ if (reg_wait(dev, tag | SPI_CONTROL, 4)) -+ goto fail; -+ -+ if (!rlen) { -+ ddbwritel(dev, 0, tag | SPI_CONTROL); -+ goto exit; -+ } -+ if (rlen > 4) -+ ddbwritel(dev, 1, tag | SPI_CONTROL); -+ -+ while (rlen > 4) { -+ ddbwritel(dev, 0xffffffff, tag | SPI_DATA); -+ if (reg_wait(dev, tag | SPI_CONTROL, 4)) -+ goto fail; -+ data = ddbreadl(dev, tag | SPI_DATA); -+ *(u32 *) rbuf = swab32(data); -+ rbuf += 4; -+ rlen -= 4; -+ } -+ ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), -+ tag | SPI_CONTROL); -+ ddbwritel(dev, 0xffffffff, tag | SPI_DATA); -+ if (reg_wait(dev, tag | SPI_CONTROL, 4)) -+ goto fail; -+ -+ data = ddbreadl(dev, tag | SPI_DATA); -+ ddbwritel(dev, 0, tag | SPI_CONTROL); -+ -+ if (rlen < 4) -+ data <<= ((4 - rlen) * 8); -+ -+ while (rlen > 0) { -+ *rbuf = ((data >> 24) & 0xff); -+ data <<= 8; -+ rbuf++; -+ rlen--; -+ } -+exit: -+ mutex_unlock(&link->flash_mutex); -+ return 0; -+fail: -+ mutex_unlock(&link->flash_mutex); -+ return -1; -+} -+ -+int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len) -+{ -+ u8 cmd[4] = {0x03, (addr >> 16) & 0xff, -+ (addr >> 8) & 0xff, addr & 0xff}; -+ -+ return flashio(dev, link, cmd, 4, buf, len); -+} -+ -+static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val) -+{ -+ ddbwritel(dev, adr, MDIO_ADR); -+ ddbwritel(dev, reg, MDIO_REG); -+ ddbwritel(dev, val, MDIO_VAL); -+ ddbwritel(dev, 0x03, MDIO_CTRL); -+ while (ddbreadl(dev, MDIO_CTRL) & 0x02) -+ ndelay(500); -+ return 0; -+} -+ -+static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg) -+{ -+ ddbwritel(dev, adr, MDIO_ADR); -+ ddbwritel(dev, reg, MDIO_REG); -+ ddbwritel(dev, 0x07, MDIO_CTRL); -+ while (ddbreadl(dev, MDIO_CTRL) & 0x02) -+ ndelay(500); -+ return ddbreadl(dev, MDIO_VAL); -+} -+ -+#define DDB_MAGIC 'd' -+ -+struct ddb_flashio { -+ __u8 *write_buf; -+ __u32 write_len; -+ __u8 *read_buf; -+ __u32 read_len; -+ __u32 link; -+}; -+ -+struct ddb_gpio { -+ __u32 mask; -+ __u32 data; -+}; -+ -+struct ddb_id { -+ __u16 vendor; -+ __u16 device; -+ __u16 subvendor; -+ __u16 subdevice; -+ __u32 hw; -+ __u32 regmap; -+}; -+ -+struct ddb_reg { -+ __u32 reg; -+ __u32 val; -+}; -+ -+struct ddb_mem { -+ __u32 off; -+ __u8 *buf; -+ __u32 len; -+}; -+ -+struct ddb_mdio { -+ __u8 adr; -+ __u8 reg; -+ __u16 val; -+}; -+ -+struct ddb_i2c_msg { -+ __u8 bus; -+ __u8 adr; -+ __u8 *hdr; -+ __u32 hlen; -+ __u8 *msg; -+ __u32 mlen; -+}; -+ -+#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) -+#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) -+#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) -+#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id) -+#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) -+#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg) -+#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) -+#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem) -+#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) -+#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) -+#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) -+#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) -+ -+#define DDB_NAME "ddbridge" -+ -+static u32 ddb_num; -+static int ddb_major; -+static DEFINE_MUTEX(ddb_mutex); -+ -+static int ddb_release(struct inode *inode, struct file *file) -+{ -+ struct ddb *dev = file->private_data; -+ -+ dev->ddb_dev_users--; -+ return 0; -+} -+ -+static int ddb_open(struct inode *inode, struct file *file) -+{ -+ struct ddb *dev = ddbs[iminor(inode)]; -+ -+ if (dev->ddb_dev_users) -+ return -EBUSY; -+ dev->ddb_dev_users++; -+ file->private_data = dev; -+ return 0; -+} -+ -+static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct ddb *dev = file->private_data; -+ void *parg = (void *)arg; -+ int res; -+ -+ switch (cmd) { -+ case IOCTL_DDB_FLASHIO: -+ { -+ struct ddb_flashio fio; -+ u8 *rbuf, *wbuf; -+ -+ if (copy_from_user(&fio, parg, sizeof(fio))) -+ return -EFAULT; -+ if (fio.write_len > 1028 || fio.read_len > 1028) -+ return -EINVAL; -+ if (fio.write_len + fio.read_len > 1028) -+ return -EINVAL; -+ if (fio.link > 3) -+ return -EINVAL; -+ -+ wbuf = &dev->iobuf[0]; -+ rbuf = wbuf + fio.write_len; -+ -+ if (copy_from_user(wbuf, fio.write_buf, fio.write_len)) -+ return -EFAULT; -+ res = flashio(dev, fio.link, wbuf, fio.write_len, rbuf, -+ fio.read_len); -+ if (res) -+ return res; -+ if (copy_to_user(fio.read_buf, rbuf, fio.read_len)) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_GPIO_OUT: -+ { -+ struct ddb_gpio gpio; -+ -+ if (copy_from_user(&gpio, parg, sizeof(gpio))) -+ return -EFAULT; -+ ddbwritel(dev, gpio.mask, GPIO_DIRECTION); -+ ddbwritel(dev, gpio.data, GPIO_OUTPUT); -+ break; -+ } -+ case IOCTL_DDB_ID: -+ { -+ struct ddb_id ddbid; -+ -+ ddbid.vendor = dev->link[0].ids.vendor; -+ ddbid.device = dev->link[0].ids.device; -+ ddbid.subvendor = dev->link[0].ids.subvendor; -+ ddbid.subdevice = dev->link[0].ids.subdevice; -+ ddbid.hw = ddbreadl(dev, 0); -+ ddbid.regmap = ddbreadl(dev, 4); -+ if (copy_to_user(parg, &ddbid, sizeof(ddbid))) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_READ_REG: -+ { -+ struct ddb_reg reg; -+ -+ if (copy_from_user(®, parg, sizeof(reg))) -+ return -EFAULT; -+ if ((reg.reg & 0xfffffff) >= dev->regs_len) -+ return -EINVAL; -+ reg.val = ddbreadl(dev, reg.reg); -+ if (copy_to_user(parg, ®, sizeof(reg))) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_WRITE_REG: -+ { -+ struct ddb_reg reg; -+ -+ if (copy_from_user(®, parg, sizeof(reg))) -+ return -EFAULT; -+ if ((reg.reg & 0xfffffff) >= dev->regs_len) -+ return -EINVAL; -+ ddbwritel(dev, reg.val, reg.reg); -+ break; -+ } -+ case IOCTL_DDB_READ_MDIO: -+ { -+ struct ddb_mdio mdio; -+ -+ if (!dev->link[0].info->mdio_num) -+ return -EIO; -+ if (copy_from_user(&mdio, parg, sizeof(mdio))) -+ return -EFAULT; -+ mdio.val = mdio_read(dev, mdio.adr, mdio.reg); -+ if (copy_to_user(parg, &mdio, sizeof(mdio))) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_WRITE_MDIO: -+ { -+ struct ddb_mdio mdio; -+ -+ if (!dev->link[0].info->mdio_num) -+ return -EIO; -+ if (copy_from_user(&mdio, parg, sizeof(mdio))) -+ return -EFAULT; -+ mdio_write(dev, mdio.adr, mdio.reg, mdio.val); -+ break; -+ } -+ case IOCTL_DDB_READ_MEM: -+ { -+ struct ddb_mem mem; -+ u8 *buf = &dev->iobuf[0]; -+ -+ if (copy_from_user(&mem, parg, sizeof(mem))) -+ return -EFAULT; -+ if ((((mem.len + mem.off) & 0xfffffff) > dev->regs_len) || -+ mem.len > 1024) -+ return -EINVAL; -+ ddbcpyfrom(dev, buf, mem.off, mem.len); -+ if (copy_to_user(mem.buf, buf, mem.len)) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_WRITE_MEM: -+ { -+ struct ddb_mem mem; -+ u8 *buf = &dev->iobuf[0]; -+ -+ if (copy_from_user(&mem, parg, sizeof(mem))) -+ return -EFAULT; -+ if ((((mem.len + mem.off) & 0xfffffff) > dev->regs_len) || -+ mem.len > 1024) -+ return -EINVAL; -+ if (copy_from_user(buf, mem.buf, mem.len)) -+ return -EFAULT; -+ ddbcpyto(dev, mem.off, buf, mem.len); - break; - } -- input->attached = 5; -- return 0; --} -+ case IOCTL_DDB_READ_I2C: -+ { -+ struct ddb_i2c_msg i2c; -+ struct i2c_adapter *adap; -+ u8 *mbuf, *hbuf = &dev->iobuf[0]; - --/****************************************************************************/ --/****************************************************************************/ -+ if (copy_from_user(&i2c, parg, sizeof(i2c))) -+ return -EFAULT; -+ if (i2c.bus > dev->link[0].info->regmap->i2c->num) -+ return -EINVAL; -+ if (i2c.mlen + i2c.hlen > 512) -+ return -EINVAL; - --static ssize_t ts_write(struct file *file, const __user char *buf, -- size_t count, loff_t *ppos) --{ -- struct dvb_device *dvbdev = file->private_data; -- struct ddb_output *output = dvbdev->priv; -- size_t left = count; -- int stat; -+ adap = &dev->i2c[i2c.bus].adap; -+ mbuf = hbuf + i2c.hlen; - -- while (left) { -- if (ddb_output_free(output) < 188) { -- if (file->f_flags & O_NONBLOCK) -- break; -- if (wait_event_interruptible( -- output->wq, ddb_output_free(output) >= 188) < 0) -- break; -- } -- stat = ddb_output_write(output, buf, left); -- if (stat < 0) -- break; -- buf += stat; -- left -= stat; -+ -+ if (copy_from_user(hbuf, i2c.hdr, i2c.hlen)) -+ return -EFAULT; -+ if (i2c_io(adap, i2c.adr, hbuf, i2c.hlen, mbuf, i2c.mlen) < 0) -+ return -EIO; -+ if (copy_to_user(i2c.msg, mbuf, i2c.mlen)) -+ return -EFAULT; -+ break; - } -- return (left == count) ? -EAGAIN : (count - left); --} -+ case IOCTL_DDB_WRITE_I2C: -+ { -+ struct ddb_i2c_msg i2c; -+ struct i2c_adapter *adap; -+ u8 *buf = &dev->iobuf[0]; - --static ssize_t ts_read(struct file *file, __user char *buf, -- size_t count, loff_t *ppos) --{ -- struct dvb_device *dvbdev = file->private_data; -- struct ddb_output *output = dvbdev->priv; -- struct ddb_input *input = output->port->input[0]; -- int left, read; -+ if (copy_from_user(&i2c, parg, sizeof(i2c))) -+ return -EFAULT; -+ if (i2c.bus > dev->link[0].info->regmap->i2c->num) -+ return -EINVAL; -+ if (i2c.mlen + i2c.hlen > 250) -+ return -EINVAL; - -- count -= count % 188; -- left = count; -- while (left) { -- if (ddb_input_avail(input) < 188) { -- if (file->f_flags & O_NONBLOCK) -- break; -- if (wait_event_interruptible( -- input->wq, ddb_input_avail(input) >= 188) < 0) -- break; -- } -- read = ddb_input_read(input, buf, left); -- if (read < 0) -- return read; -- left -= read; -- buf += read; -+ adap = &dev->i2c[i2c.bus].adap; -+ if (copy_from_user(buf, i2c.hdr, i2c.hlen)) -+ return -EFAULT; -+ if (copy_from_user(buf + i2c.hlen, i2c.msg, i2c.mlen)) -+ return -EFAULT; -+ if (i2c_write(adap, i2c.adr, buf, i2c.hlen + i2c.mlen) < 0) -+ return -EIO; -+ break; - } -- return (left == count) ? -EAGAIN : (count - left); -+ default: -+ return -ENOTTY; -+ } -+ return 0; - } - --static unsigned int ts_poll(struct file *file, poll_table *wait) --{ -- /* -- struct dvb_device *dvbdev = file->private_data; -- struct ddb_output *output = dvbdev->priv; -- struct ddb_input *input = output->port->input[0]; -- */ -- unsigned int mask = 0; -+static const struct file_operations ddb_fops = { -+ .unlocked_ioctl = ddb_ioctl, -+ .open = ddb_open, -+ .release = ddb_release, -+}; - --#if 0 -- if (data_avail_to_read) -- mask |= POLLIN | POLLRDNORM; -- if (data_avail_to_write) -- mask |= POLLOUT | POLLWRNORM; -+static char *ddb_devnode(struct device *device, umode_t *mode) -+{ -+ struct ddb *dev = dev_get_drvdata(device); - -- poll_wait(file, &read_queue, wait); -- poll_wait(file, &write_queue, wait); --#endif -- return mask; -+ return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr); - } - --static const struct file_operations ci_fops = { -- .owner = THIS_MODULE, -- .read = ts_read, -- .write = ts_write, -- .open = dvb_generic_open, -- .release = dvb_generic_release, -- .poll = ts_poll, --}; -- --static struct dvb_device dvbdev_ci = { -- .readers = -1, -- .writers = -1, -- .users = -1, -- .fops = &ci_fops, --}; -+#define __ATTR_MRO(_name, _show) { \ -+ .attr = { .name = __stringify(_name), .mode = 0444 }, \ -+ .show = _show, \ -+} - --/****************************************************************************/ --/****************************************************************************/ --/****************************************************************************/ -+#define __ATTR_MWO(_name, _store) { \ -+ .attr = { .name = __stringify(_name), .mode = 0222 }, \ -+ .store = _store, \ -+} - --static void input_tasklet(unsigned long data) -+static ssize_t ports_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb_input *input = (struct ddb_input *) data; -- struct ddb *dev = input->port->dev; -+ struct ddb *dev = dev_get_drvdata(device); - -- spin_lock(&input->lock); -- if (!input->running) { -- spin_unlock(&input->lock); -- return; -- } -- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); -+ return sprintf(buf, "%d\n", dev->link[0].info->port_num); -+} - -- if (input->port->class == DDB_PORT_TUNER) { -- if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr))) -- printk(KERN_ERR "Overflow input %d\n", input->nr); -- while (input->cbuf != ((input->stat >> 11) & 0x1f) -- || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) { -- dvb_dmx_swfilter_packets(&input->demux, -- input->vbuf[input->cbuf], -- input->dma_buf_size / 188); -+static ssize_t ts_irq_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); - -- input->cbuf = (input->cbuf + 1) % input->dma_buf_num; -- ddbwritel((input->cbuf << 11), -- DMA_BUFFER_ACK(input->nr)); -- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); -- } -- } -- if (input->port->class == DDB_PORT_CI) -- wake_up(&input->wq); -- spin_unlock(&input->lock); -+ return sprintf(buf, "%d\n", dev->ts_irq); - } - --static void output_tasklet(unsigned long data) -+static ssize_t i2c_irq_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb_output *output = (struct ddb_output *) data; -- struct ddb *dev = output->port->dev; -+ struct ddb *dev = dev_get_drvdata(device); - -- spin_lock(&output->lock); -- if (!output->running) { -- spin_unlock(&output->lock); -- return; -- } -- output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8)); -- wake_up(&output->wq); -- spin_unlock(&output->lock); -+ return sprintf(buf, "%d\n", dev->i2c_irq); - } - -- --static struct cxd2099_cfg cxd_cfg = { -- .bitrate = 62000, -- .adr = 0x40, -- .polarity = 1, -- .clock_mode = 1, -+static char *class_name[] = { -+ "NONE", "CI", "TUNER", "LOOP", "MOD" - }; - --static int ddb_ci_attach(struct ddb_port *port) -+static ssize_t fan_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- int ret; -+ struct ddb *dev = dev_get_drvdata(device); -+ u32 val; - -- ret = dvb_register_adapter(&port->output->adap, -- "DDBridge", -- THIS_MODULE, -- &port->dev->pdev->dev, -- adapter_nr); -- if (ret < 0) -- return ret; -- port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); -- if (!port->en) { -- dvb_unregister_adapter(&port->output->adap); -- return -ENODEV; -- } -- ddb_input_start(port->input[0]); -- ddb_output_start(port->output); -- dvb_ca_en50221_init(&port->output->adap, -- port->en, 0, 1); -- ret = dvb_register_device(&port->output->adap, &port->output->dev, -- &dvbdev_ci, (void *) port->output, -- DVB_DEVICE_SEC, 0); -- return ret; -+ val = ddbreadl(dev, GPIO_OUTPUT) & 1; -+ return sprintf(buf, "%d\n", val); - } - --static int ddb_port_attach(struct ddb_port *port) -+static ssize_t fan_store(struct device *device, struct device_attribute *d, -+ const char *buf, size_t count) - { -- int ret = 0; -+ struct ddb *dev = dev_get_drvdata(device); -+ unsigned val; - -- switch (port->class) { -- case DDB_PORT_TUNER: -- ret = dvb_input_attach(port->input[0]); -- if (ret < 0) -- break; -- ret = dvb_input_attach(port->input[1]); -- break; -- case DDB_PORT_CI: -- ret = ddb_ci_attach(port); -- break; -- default: -- break; -- } -- if (ret < 0) -- printk(KERN_ERR "port_attach on port %d failed\n", port->nr); -- return ret; -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ ddbwritel(dev, 1, GPIO_DIRECTION); -+ ddbwritel(dev, val & 1, GPIO_OUTPUT); -+ return count; - } - --static int ddb_ports_attach(struct ddb *dev) -+static ssize_t temp_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- int i, ret = 0; -- struct ddb_port *port; -+ struct ddb *dev = dev_get_drvdata(device); -+ struct i2c_adapter *adap; -+ int temp, temp2, temp3, i; -+ u8 tmp[2]; - -- for (i = 0; i < dev->info->port_num; i++) { -- port = &dev->port[i]; -- ret = ddb_port_attach(port); -- if (ret < 0) -- break; -+ if (dev->link[0].info->type == DDB_MOD) { -+ ddbwritel(dev, 1, TEMPMON_CONTROL); -+ for (i = 0; i < 10; i++) { -+ if (0 == (1 & ddbreadl(dev, TEMPMON_CONTROL))) -+ break; -+ usleep_range(1000, 2000); -+ } -+ temp = ddbreadl(dev, TEMPMON_SENSOR1); -+ temp2 = ddbreadl(dev, TEMPMON_SENSOR2); -+ temp = (temp * 1000) >> 8; -+ temp2 = (temp2 * 1000) >> 8; -+ if (ddbreadl(dev, TEMPMON_CONTROL) & 0x8000) { -+ temp3 = ddbreadl(dev, TEMPMON_CORE); -+ temp3 = (temp3 * 1000) >> 8; -+ return sprintf(buf, "%d %d %d\n", temp, temp2, temp3); -+ } -+ return sprintf(buf, "%d %d\n", temp, temp2); - } -- return ret; -+ if (!dev->link[0].info->temp_num) -+ return sprintf(buf, "no sensor\n"); -+ adap = &dev->i2c[dev->link[0].info->temp_bus].adap; -+ if (i2c_read_regs(adap, 0x48, 0, tmp, 2) < 0) -+ return sprintf(buf, "read_error\n"); -+ temp = (tmp[0] << 3) | (tmp[1] >> 5); -+ temp *= 125; -+ if (dev->link[0].info->temp_num == 2) { -+ if (i2c_read_regs(adap, 0x49, 0, tmp, 2) < 0) -+ return sprintf(buf, "read_error\n"); -+ temp2 = (tmp[0] << 3) | (tmp[1] >> 5); -+ temp2 *= 125; -+ return sprintf(buf, "%d %d\n", temp, temp2); -+ } -+ return sprintf(buf, "%d\n", temp); - } - --static void ddb_ports_detach(struct ddb *dev) -+static ssize_t ctemp_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- int i; -- struct ddb_port *port; -+ struct ddb *dev = dev_get_drvdata(device); -+ struct i2c_adapter *adap; -+ int temp; -+ u8 tmp[2]; -+ int num = attr->attr.name[4] - 0x30; - -- for (i = 0; i < dev->info->port_num; i++) { -- port = &dev->port[i]; -- switch (port->class) { -- case DDB_PORT_TUNER: -- dvb_input_detach(port->input[0]); -- dvb_input_detach(port->input[1]); -- break; -- case DDB_PORT_CI: -- dvb_unregister_device(port->output->dev); -- if (port->en) { -- ddb_input_stop(port->input[0]); -- ddb_output_stop(port->output); -- dvb_ca_en50221_release(port->en); -- kfree(port->en); -- port->en = NULL; -- dvb_unregister_adapter(&port->output->adap); -- } -- break; -- } -- } -+ adap = &dev->i2c[num].adap; -+ if (!adap) -+ return 0; -+ if (i2c_read_regs(adap, 0x49, 0, tmp, 2) < 0) -+ if (i2c_read_regs(adap, 0x4d, 0, tmp, 2) < 0) -+ return sprintf(buf, "no sensor\n"); -+ temp = tmp[0] * 1000; -+ return sprintf(buf, "%d\n", temp); - } - --/****************************************************************************/ --/****************************************************************************/ -- --static int port_has_ci(struct ddb_port *port) -+static ssize_t mod_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- u8 val; -- return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1; -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ -+ return sprintf(buf, "%s:%s\n", -+ class_name[dev->port[num].class], -+ dev->port[num].type_name); - } - --static int port_has_stv0900(struct ddb_port *port) -+static ssize_t led_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- u8 val; -- if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0) -- return 0; -- return 1; -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ -+ return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0); - } - --static int port_has_stv0900_aa(struct ddb_port *port) -+ -+static void ddb_set_led(struct ddb *dev, int num, int val) - { -- u8 val; -- if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0) -- return 0; -- return 1; -+ if (!dev->link[0].info->led_num) -+ return; -+ switch (dev->port[num].class) { -+ case DDB_PORT_TUNER: -+ switch (dev->port[num].type) { -+ case DDB_TUNER_DVBS_ST: -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x69, 0xf14c, val ? 2 : 0); -+ break; -+ case DDB_TUNER_DVBCT_ST: -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x1f, 0xf00e, 0); -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x1f, 0xf00f, val ? 1 : 0); -+ break; -+ case DDB_TUNER_XO2 ... DDB_TUNER_DVBC2T2_ST: -+ { -+ u8 v; -+ -+ i2c_read_reg(&dev->i2c[num].adap, 0x10, 0x08, &v); -+ v = (v & ~0x10) | (val ? 0x10 : 0); -+ i2c_write_reg(&dev->i2c[num].adap, 0x10, 0x08, v); -+ break; -+ } -+ default: -+ break; -+ } -+ break; -+ } - } - --static int port_has_drxks(struct ddb_port *port) -+static ssize_t led_store(struct device *device, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- u8 val; -- if (i2c_read(&port->i2c->adap, 0x29, &val) < 0) -- return 0; -- if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0) -- return 0; -- return 1; -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ unsigned val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ if (val) -+ dev->leds |= (1 << num); -+ else -+ dev->leds &= ~(1 << num); -+ ddb_set_led(dev, num, val); -+ return count; - } - --static void ddb_port_probe(struct ddb_port *port) -+static ssize_t snr_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb *dev = port->dev; -- char *modname = "NO MODULE"; -- -- port->class = DDB_PORT_NONE; -+ struct ddb *dev = dev_get_drvdata(device); -+ char snr[32]; -+ int num = attr->attr.name[3] - 0x30; - -- if (port_has_ci(port)) { -- modname = "CI"; -- port->class = DDB_PORT_CI; -- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -- } else if (port_has_stv0900(port)) { -- modname = "DUAL DVB-S2"; -- port->class = DDB_PORT_TUNER; -- port->type = DDB_TUNER_DVBS_ST; -- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -- } else if (port_has_stv0900_aa(port)) { -- modname = "DUAL DVB-S2"; -- port->class = DDB_PORT_TUNER; -- port->type = DDB_TUNER_DVBS_ST_AA; -- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -- } else if (port_has_drxks(port)) { -- modname = "DUAL DVB-C/T"; -- port->class = DDB_PORT_TUNER; -- port->type = DDB_TUNER_DVBCT_TR; -- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ if (dev->port[num].type >= DDB_TUNER_XO2) { -+ if (i2c_read_regs(&dev->i2c[num].adap, 0x10, 0x10, snr, 16) < 0) -+ return sprintf(buf, "NO SNR\n"); -+ snr[16] = 0; -+ } else { -+ /* serial number at 0x100-0x11f */ -+ if (i2c_read_regs16(&dev->i2c[num].adap, -+ 0x57, 0x100, snr, 32) < 0) -+ if (i2c_read_regs16(&dev->i2c[num].adap, -+ 0x50, 0x100, snr, 32) < 0) -+ return sprintf(buf, "NO SNR\n"); -+ snr[31] = 0; /* in case it is not terminated on EEPROM */ - } -- printk(KERN_INFO "Port %d (TAB %d): %s\n", -- port->nr, port->nr+1, modname); -+ return sprintf(buf, "%s\n", snr); - } - --static void ddb_input_init(struct ddb_port *port, int nr) --{ -- struct ddb *dev = port->dev; -- struct ddb_input *input = &dev->input[nr]; - -- input->nr = nr; -- input->port = port; -- input->dma_buf_num = INPUT_DMA_BUFS; -- input->dma_buf_size = INPUT_DMA_SIZE; -- ddbwritel(0, TS_INPUT_CONTROL(nr)); -- ddbwritel(2, TS_INPUT_CONTROL(nr)); -- ddbwritel(0, TS_INPUT_CONTROL(nr)); -- ddbwritel(0, DMA_BUFFER_ACK(nr)); -- tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input); -- spin_lock_init(&input->lock); -- init_waitqueue_head(&input->wq); -+static ssize_t snr_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ u8 snr[34] = { 0x01, 0x00 }; -+ -+ return 0; /* NOE: remove completely? */ -+ if (count > 31) -+ return -EINVAL; -+ if (dev->port[num].type >= DDB_TUNER_XO2) -+ return -EINVAL; -+ memcpy(snr + 2, buf, count); -+ i2c_write(&dev->i2c[num].adap, 0x57, snr, 34); -+ i2c_write(&dev->i2c[num].adap, 0x50, snr, 34); -+ return count; - } - --static void ddb_output_init(struct ddb_port *port, int nr) -+static ssize_t bsnr_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb *dev = port->dev; -- struct ddb_output *output = &dev->output[nr]; -- output->nr = nr; -- output->port = port; -- output->dma_buf_num = OUTPUT_DMA_BUFS; -- output->dma_buf_size = OUTPUT_DMA_SIZE; -+ struct ddb *dev = dev_get_drvdata(device); -+ char snr[16]; - -- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); -- ddbwritel(2, TS_OUTPUT_CONTROL(nr)); -- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); -- tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output); -- init_waitqueue_head(&output->wq); -+ ddbridge_flashread(dev, 0, snr, 0x10, 15); -+ snr[15] = 0; /* in case it is not terminated on EEPROM */ -+ return sprintf(buf, "%s\n", snr); - } - --static void ddb_ports_init(struct ddb *dev) -+static ssize_t bpsnr_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- int i; -- struct ddb_port *port; -+ struct ddb *dev = dev_get_drvdata(device); -+ char snr[32]; - -- for (i = 0; i < dev->info->port_num; i++) { -- port = &dev->port[i]; -- port->dev = dev; -- port->nr = i; -- port->i2c = &dev->i2c[i]; -- port->input[0] = &dev->input[2 * i]; -- port->input[1] = &dev->input[2 * i + 1]; -- port->output = &dev->output[i]; -+ if (!dev->i2c_num) -+ return 0; - -- mutex_init(&port->i2c_gate_lock); -- ddb_port_probe(port); -- ddb_input_init(port, 2 * i); -- ddb_input_init(port, 2 * i + 1); -- ddb_output_init(port, i); -- } -+ if (i2c_read_regs16(&dev->i2c[0].adap, -+ 0x50, 0x0000, snr, 32) < 0 || -+ snr[0] == 0xff) -+ return sprintf(buf, "NO SNR\n"); -+ snr[31] = 0; /* in case it is not terminated on EEPROM */ -+ return sprintf(buf, "%s\n", snr); - } - --static void ddb_ports_release(struct ddb *dev) -+static ssize_t redirect_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- int i; -- struct ddb_port *port; -- -- for (i = 0; i < dev->info->port_num; i++) { -- port = &dev->port[i]; -- port->dev = dev; -- tasklet_kill(&port->input[0]->tasklet); -- tasklet_kill(&port->input[1]->tasklet); -- tasklet_kill(&port->output->tasklet); -- } -+ return 0; - } - --/****************************************************************************/ --/****************************************************************************/ --/****************************************************************************/ -- --static void irq_handle_i2c(struct ddb *dev, int n) -+static ssize_t redirect_store(struct device *device, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct ddb_i2c *i2c = &dev->i2c[n]; -+ unsigned int i, p; -+ int res; - -- i2c->done = 1; -- wake_up(&i2c->wq); -+ if (sscanf(buf, "%x %x\n", &i, &p) != 2) -+ return -EINVAL; -+ res = ddb_redirect(i, p); -+ if (res < 0) -+ return res; -+ pr_info("redirect: %02x, %02x\n", i, p); -+ return count; - } - --static irqreturn_t irq_handler(int irq, void *dev_id) -+static ssize_t gap_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb *dev = (struct ddb *) dev_id; -- u32 s = ddbreadl(INTERRUPT_STATUS); -- -- if (!s) -- return IRQ_NONE; -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; - -- do { -- ddbwritel(s, INTERRUPT_ACK); -- -- if (s & 0x00000001) -- irq_handle_i2c(dev, 0); -- if (s & 0x00000002) -- irq_handle_i2c(dev, 1); -- if (s & 0x00000004) -- irq_handle_i2c(dev, 2); -- if (s & 0x00000008) -- irq_handle_i2c(dev, 3); -- -- if (s & 0x00000100) -- tasklet_schedule(&dev->input[0].tasklet); -- if (s & 0x00000200) -- tasklet_schedule(&dev->input[1].tasklet); -- if (s & 0x00000400) -- tasklet_schedule(&dev->input[2].tasklet); -- if (s & 0x00000800) -- tasklet_schedule(&dev->input[3].tasklet); -- if (s & 0x00001000) -- tasklet_schedule(&dev->input[4].tasklet); -- if (s & 0x00002000) -- tasklet_schedule(&dev->input[5].tasklet); -- if (s & 0x00004000) -- tasklet_schedule(&dev->input[6].tasklet); -- if (s & 0x00008000) -- tasklet_schedule(&dev->input[7].tasklet); -- -- if (s & 0x00010000) -- tasklet_schedule(&dev->output[0].tasklet); -- if (s & 0x00020000) -- tasklet_schedule(&dev->output[1].tasklet); -- if (s & 0x00040000) -- tasklet_schedule(&dev->output[2].tasklet); -- if (s & 0x00080000) -- tasklet_schedule(&dev->output[3].tasklet); -- -- /* if (s & 0x000f0000) printk(KERN_DEBUG "%08x\n", istat); */ -- } while ((s = ddbreadl(INTERRUPT_STATUS))); -+ return sprintf(buf, "%d\n", dev->port[num].gap); - -- return IRQ_HANDLED; - } - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -- --static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) -+static ssize_t gap_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) - { -- u32 data, shift; -- -- if (wlen > 4) -- ddbwritel(1, SPI_CONTROL); -- while (wlen > 4) { -- /* FIXME: check for big-endian */ -- data = swab32(*(u32 *)wbuf); -- wbuf += 4; -- wlen -= 4; -- ddbwritel(data, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -- ; -- } -- -- if (rlen) -- ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); -- else -- ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ unsigned int val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ if (val > 20) -+ return -EINVAL; -+ dev->port[num].gap = val; -+ return count; -+} - -- data = 0; -- shift = ((4 - wlen) * 8); -- while (wlen) { -- data <<= 8; -- data |= *wbuf; -- wlen--; -- wbuf++; -- } -- if (shift) -- data <<= shift; -- ddbwritel(data, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -- ; -+static ssize_t version_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); - -- if (!rlen) { -- ddbwritel(0, SPI_CONTROL); -- return 0; -- } -- if (rlen > 4) -- ddbwritel(1, SPI_CONTROL); -+ return sprintf(buf, "%08x %08x\n", -+ dev->link[0].ids.hwid, dev->link[0].ids.regmapid); -+} - -- while (rlen > 4) { -- ddbwritel(0xffffffff, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -- ; -- data = ddbreadl(SPI_DATA); -- *(u32 *) rbuf = swab32(data); -- rbuf += 4; -- rlen -= 4; -- } -- ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); -- ddbwritel(0xffffffff, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -- ; -+static ssize_t hwid_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); - -- data = ddbreadl(SPI_DATA); -- ddbwritel(0, SPI_CONTROL); -+ return sprintf(buf, "0x%08X\n", dev->link[0].ids.hwid); -+} - -- if (rlen < 4) -- data <<= ((4 - rlen) * 8); -+static ssize_t regmap_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); - -- while (rlen > 0) { -- *rbuf = ((data >> 24) & 0xff); -- data <<= 8; -- rbuf++; -- rlen--; -- } -- return 0; -+ return sprintf(buf, "0x%08X\n", dev->link[0].ids.regmapid); - } - --#define DDB_MAGIC 'd' -+static ssize_t vlan_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); - --struct ddb_flashio { -- __user __u8 *write_buf; -- __u32 write_len; -- __user __u8 *read_buf; -- __u32 read_len; --}; -+ return sprintf(buf, "%u\n", dev->vlan); -+} - --#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) -+static ssize_t vlan_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ unsigned int val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ if (val > 1) -+ return -EINVAL; -+ if (!dev->link[0].info->ns_num) -+ return -EINVAL; -+ ddbwritel(dev, 14 + (val ? 4 : 0), ETHER_LENGTH); -+ dev->vlan = val; -+ return count; -+} - --#define DDB_NAME "ddbridge" -+static ssize_t fmode_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ int num = attr->attr.name[5] - 0x30; -+ struct ddb *dev = dev_get_drvdata(device); - --static u32 ddb_num; --static struct ddb *ddbs[32]; --static struct class *ddb_class; --static int ddb_major; -+ return sprintf(buf, "%u\n", dev->link[num].lnb.fmode); -+} - --static int ddb_open(struct inode *inode, struct file *file) -+static ssize_t devid_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb *dev = ddbs[iminor(inode)]; -+ int num = attr->attr.name[5] - 0x30; -+ struct ddb *dev = dev_get_drvdata(device); - -- file->private_data = dev; -- return 0; -+ return sprintf(buf, "%08x\n", dev->link[num].ids.devid); - } - --static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+static ssize_t fmode_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct ddb *dev = file->private_data; -- __user void *parg = (__user void *)arg; -- int res; -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[5] - 0x30; -+ unsigned int val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ if (val > 3) -+ return -EINVAL; -+ lnb_init_fmode(dev, &dev->link[num], val); -+ return count; -+} - -- switch (cmd) { -- case IOCTL_DDB_FLASHIO: -- { -- struct ddb_flashio fio; -- u8 *rbuf, *wbuf; -+static struct device_attribute ddb_attrs[] = { -+ __ATTR_RO(version), -+ __ATTR_RO(ports), -+ __ATTR_RO(ts_irq), -+ __ATTR_RO(i2c_irq), -+ __ATTR(gap0, 0664, gap_show, gap_store), -+ __ATTR(gap1, 0664, gap_show, gap_store), -+ __ATTR(gap2, 0664, gap_show, gap_store), -+ __ATTR(gap3, 0664, gap_show, gap_store), -+ __ATTR(vlan, 0664, vlan_show, vlan_store), -+ __ATTR(fmode0, 0664, fmode_show, fmode_store), -+ __ATTR(fmode1, 0664, fmode_show, fmode_store), -+ __ATTR(fmode2, 0664, fmode_show, fmode_store), -+ __ATTR(fmode3, 0664, fmode_show, fmode_store), -+ __ATTR_MRO(devid0, devid_show), -+ __ATTR_MRO(devid1, devid_show), -+ __ATTR_MRO(devid2, devid_show), -+ __ATTR_MRO(devid3, devid_show), -+ __ATTR_RO(hwid), -+ __ATTR_RO(regmap), -+ __ATTR(redirect, 0664, redirect_show, redirect_store), -+ __ATTR_MRO(snr, bsnr_show), -+ __ATTR_RO(bpsnr), -+ __ATTR_NULL, -+}; - -- if (copy_from_user(&fio, parg, sizeof(fio))) -- return -EFAULT; -+static struct device_attribute ddb_attrs_temp[] = { -+ __ATTR_RO(temp), -+}; - -- if (fio.write_len > 1028 || fio.read_len > 1028) -- return -EINVAL; -- if (fio.write_len + fio.read_len > 1028) -- return -EINVAL; -+static struct device_attribute ddb_attrs_mod[] = { -+ __ATTR_MRO(mod0, mod_show), -+ __ATTR_MRO(mod1, mod_show), -+ __ATTR_MRO(mod2, mod_show), -+ __ATTR_MRO(mod3, mod_show), -+ __ATTR_MRO(mod4, mod_show), -+ __ATTR_MRO(mod5, mod_show), -+ __ATTR_MRO(mod6, mod_show), -+ __ATTR_MRO(mod7, mod_show), -+ __ATTR_MRO(mod8, mod_show), -+ __ATTR_MRO(mod9, mod_show), -+}; - -- wbuf = &dev->iobuf[0]; -- rbuf = wbuf + fio.write_len; -+static struct device_attribute ddb_attrs_fan[] = { -+ __ATTR(fan, 0664, fan_show, fan_store), -+}; - -- if (copy_from_user(wbuf, fio.write_buf, fio.write_len)) -- return -EFAULT; -- res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len); -- if (res) -- return res; -- if (copy_to_user(fio.read_buf, rbuf, fio.read_len)) -- return -EFAULT; -- break; -- } -- default: -- return -ENOTTY; -- } -- return 0; --} -+static struct device_attribute ddb_attrs_snr[] = { -+ __ATTR(snr0, 0664, snr_show, snr_store), -+ __ATTR(snr1, 0664, snr_show, snr_store), -+ __ATTR(snr2, 0664, snr_show, snr_store), -+ __ATTR(snr3, 0664, snr_show, snr_store), -+}; - --static const struct file_operations ddb_fops = { -- .unlocked_ioctl = ddb_ioctl, -- .open = ddb_open, -+static struct device_attribute ddb_attrs_ctemp[] = { -+ __ATTR_MRO(temp0, ctemp_show), -+ __ATTR_MRO(temp1, ctemp_show), -+ __ATTR_MRO(temp2, ctemp_show), -+ __ATTR_MRO(temp3, ctemp_show), - }; - --static char *ddb_devnode(struct device *device, umode_t *mode) --{ -- struct ddb *dev = dev_get_drvdata(device); -+static struct device_attribute ddb_attrs_led[] = { -+ __ATTR(led0, 0664, led_show, led_store), -+ __ATTR(led1, 0664, led_show, led_store), -+ __ATTR(led2, 0664, led_show, led_store), -+ __ATTR(led3, 0664, led_show, led_store), -+}; - -- return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr); --} -+static struct class ddb_class = { -+ .name = "ddbridge", -+ .owner = THIS_MODULE, -+ .devnode = ddb_devnode, -+}; - - static int ddb_class_create(void) - { - ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops); - if (ddb_major < 0) - return ddb_major; -- -- ddb_class = class_create(THIS_MODULE, DDB_NAME); -- if (IS_ERR(ddb_class)) { -- unregister_chrdev(ddb_major, DDB_NAME); -- return PTR_ERR(ddb_class); -- } -- ddb_class->devnode = ddb_devnode; -+ if (class_register(&ddb_class) < 0) -+ return -1; - return 0; - } - - static void ddb_class_destroy(void) - { -- class_destroy(ddb_class); -+ class_unregister(&ddb_class); - unregister_chrdev(ddb_major, DDB_NAME); - } - -+static void ddb_device_attrs_del(struct ddb *dev) -+{ -+ int i; -+ -+ for (i = 0; i < dev->link[0].info->temp_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]); -+ for (i = 0; i < dev->link[0].info->port_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]); -+ for (i = 0; i < dev->link[0].info->fan_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_fan[i]); -+ for (i = 0; i < dev->i2c_num && i < 4; i++) { -+ if (dev->link[0].info->led_num) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_led[i]); -+ device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]); -+ device_remove_file(dev->ddb_dev, &ddb_attrs_ctemp[i]); -+ } -+ for (i = 0; ddb_attrs[i].attr.name; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs[i]); -+} -+ -+static int ddb_device_attrs_add(struct ddb *dev) -+{ -+ int i; -+ -+ for (i = 0; ddb_attrs[i].attr.name; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs[i])) -+ goto fail; -+ for (i = 0; i < dev->link[0].info->temp_num; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_temp[i])) -+ goto fail; -+ for (i = 0; i < dev->link[0].info->port_num; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_mod[i])) -+ goto fail; -+ for (i = 0; i < dev->link[0].info->fan_num; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_fan[i])) -+ goto fail; -+ for (i = 0; i < dev->i2c_num && i < 4; i++) { -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_snr[i])) -+ goto fail; -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_ctemp[i])) -+ goto fail; -+ if (dev->link[0].info->led_num) -+ if (device_create_file(dev->ddb_dev, -+ &ddb_attrs_led[i])) -+ goto fail; -+ } -+ return 0; -+fail: -+ return -1; -+} -+ - static int ddb_device_create(struct ddb *dev) - { -- dev->nr = ddb_num++; -- dev->ddb_dev = device_create(ddb_class, NULL, -+ int res = 0; -+ -+ if (ddb_num == DDB_MAX_ADAPTER) -+ return -ENOMEM; -+ mutex_lock(&ddb_mutex); -+ dev->nr = ddb_num; -+ ddbs[dev->nr] = dev; -+ dev->ddb_dev = device_create(&ddb_class, dev->dev, - MKDEV(ddb_major, dev->nr), - dev, "ddbridge%d", dev->nr); -- ddbs[dev->nr] = dev; -- if (IS_ERR(dev->ddb_dev)) -- return -1; -- return 0; -+ if (IS_ERR(dev->ddb_dev)) { -+ res = PTR_ERR(dev->ddb_dev); -+ pr_info("Could not create ddbridge%d\n", dev->nr); -+ goto fail; -+ } -+ res = ddb_device_attrs_add(dev); -+ if (res) { -+ ddb_device_attrs_del(dev); -+ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); -+ ddbs[dev->nr] = 0; -+ dev->ddb_dev = ERR_PTR(-ENODEV); -+ } else -+ ddb_num++; -+fail: -+ mutex_unlock(&ddb_mutex); -+ return res; - } - - static void ddb_device_destroy(struct ddb *dev) - { -- ddb_num--; - if (IS_ERR(dev->ddb_dev)) - return; -- device_destroy(ddb_class, MKDEV(ddb_major, 0)); -+ ddb_device_attrs_del(dev); -+ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); - } - -+#define LINK_IRQ_HANDLE(_nr) \ -+ do { if ((s & (1UL << _nr)) && dev->handler[_nr + off]) \ -+ dev->handler[_nr + off](dev->handler_data[_nr + off]); } \ -+ while (0) - --/****************************************************************************/ --/****************************************************************************/ --/****************************************************************************/ -- --static void ddb_unmap(struct ddb *dev) -+static void gtl_link_handler(unsigned long priv) - { -- if (dev->regs) -- iounmap(dev->regs); -- vfree(dev); --} -+ struct ddb *dev = (struct ddb *) priv; -+ u32 regs = dev->link[0].info->regmap->gtl->base; - -+ pr_info("GT link change: %u\n", -+ (1 & ddbreadl(dev, regs))); -+} - --static void ddb_remove(struct pci_dev *pdev) -+static void link_tasklet(unsigned long data) - { -- struct ddb *dev = pci_get_drvdata(pdev); -- -- ddb_ports_detach(dev); -- ddb_i2c_release(dev); -+ struct ddb_link *link = (struct ddb_link *) data; -+ struct ddb *dev = link->dev; -+ u32 s, off = 32 * link->nr, tag = DDB_LINK_TAG(link->nr); - -- ddbwritel(0, INTERRUPT_ENABLE); -- free_irq(dev->pdev->irq, dev); --#ifdef CONFIG_PCI_MSI -- if (dev->msi) -- pci_disable_msi(dev->pdev); --#endif -- ddb_ports_release(dev); -- ddb_buffers_free(dev); -- ddb_device_destroy(dev); -+ s = ddbreadl(dev, tag | INTERRUPT_STATUS); -+ pr_info("gtl_irq %08x = %08x\n", tag | INTERRUPT_STATUS, s); - -- ddb_unmap(dev); -- pci_set_drvdata(pdev, NULL); -- pci_disable_device(pdev); -+ if (!s) -+ return; -+ ddbwritel(dev, s, tag | INTERRUPT_ACK); -+ LINK_IRQ_HANDLE(0); -+ LINK_IRQ_HANDLE(1); -+ LINK_IRQ_HANDLE(2); -+ LINK_IRQ_HANDLE(3); - } - -- --static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) -+static void gtl_irq_handler(unsigned long priv) - { -- struct ddb *dev; -- int stat = 0; -- int irq_flag = IRQF_SHARED; -- -- if (pci_enable_device(pdev) < 0) -- return -ENODEV; -- -- dev = vzalloc(sizeof(struct ddb)); -- if (dev == NULL) -- return -ENOMEM; -- -- dev->pdev = pdev; -- pci_set_drvdata(pdev, dev); -- dev->info = (struct ddb_info *) id->driver_data; -- printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name); -- -- dev->regs = ioremap(pci_resource_start(dev->pdev, 0), -- pci_resource_len(dev->pdev, 0)); -- if (!dev->regs) { -- stat = -ENOMEM; -- goto fail; -- } -- printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4)); -- --#ifdef CONFIG_PCI_MSI -- if (pci_msi_enabled()) -- stat = pci_enable_msi(dev->pdev); -- if (stat) { -- printk(KERN_INFO ": MSI not available.\n"); -- } else { -- irq_flag = 0; -- dev->msi = 1; -- } --#endif -- stat = request_irq(dev->pdev->irq, irq_handler, -- irq_flag, "DDBridge", (void *) dev); -- if (stat < 0) -- goto fail1; -- ddbwritel(0, DMA_BASE_WRITE); -- ddbwritel(0, DMA_BASE_READ); -- ddbwritel(0xffffffff, INTERRUPT_ACK); -- ddbwritel(0xfff0f, INTERRUPT_ENABLE); -- ddbwritel(0, MSI1_ENABLE); -- -- if (ddb_i2c_init(dev) < 0) -- goto fail1; -- ddb_ports_init(dev); -- if (ddb_buffers_alloc(dev) < 0) { -- printk(KERN_INFO ": Could not allocate buffer memory\n"); -- goto fail2; -+ struct ddb_link *link = (struct ddb_link *) priv; -+ struct ddb *dev = link->dev; -+ u32 s, off = 32 * link->nr, tag = DDB_LINK_TAG(link->nr); -+ -+ while ((s = ddbreadl(dev, tag | INTERRUPT_STATUS))) { -+ ddbwritel(dev, s, tag | INTERRUPT_ACK); -+ LINK_IRQ_HANDLE(0); -+ LINK_IRQ_HANDLE(1); -+ LINK_IRQ_HANDLE(2); -+ LINK_IRQ_HANDLE(3); - } -- if (ddb_ports_attach(dev) < 0) -- goto fail3; -- ddb_device_create(dev); -- return 0; -- --fail3: -- ddb_ports_detach(dev); -- printk(KERN_ERR "fail3\n"); -- ddb_ports_release(dev); --fail2: -- printk(KERN_ERR "fail2\n"); -- ddb_buffers_free(dev); --fail1: -- printk(KERN_ERR "fail1\n"); -- if (dev->msi) -- pci_disable_msi(dev->pdev); -- if (stat == 0) -- free_irq(dev->pdev->irq, dev); --fail: -- printk(KERN_ERR "fail\n"); -- ddb_unmap(dev); -- pci_set_drvdata(pdev, NULL); -- pci_disable_device(pdev); -- return -1; - } - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -- --static struct ddb_info ddb_none = { -- .type = DDB_NONE, -- .name = "Digital Devices PCIe bridge", -+static struct ddb_regset octopus_max_gtl_i2c = { -+ .base = 0x80, -+ .num = 0x01, -+ .size = 0x20, - }; - --static struct ddb_info ddb_octopus = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus DVB adapter", -- .port_num = 4, -+static struct ddb_regset octopus_max_gtl_i2c_buf = { -+ .base = 0x1000, -+ .num = 0x01, -+ .size = 0x200, - }; - --static struct ddb_info ddb_octopus_le = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus LE DVB adapter", -- .port_num = 2, -+static struct ddb_regmap octopus_max_gtl_map = { -+ .i2c = &octopus_max_gtl_i2c, -+ .i2c_buf = &octopus_max_gtl_i2c_buf, - }; - --static struct ddb_info ddb_octopus_mini = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus Mini", -+static struct ddb_info octopus_max_gtl = { -+ .type = DDB_OCTOPUS_MAX, -+ .name = "Digital Devices Octopus MAX GTL", -+ .regmap = &octopus_max_gtl_map, - .port_num = 4, -+ .i2c_mask = 0x01, -+ .board_control = 1, - }; - --static struct ddb_info ddb_v6 = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Cine S2 V6 DVB adapter", -- .port_num = 3, --}; --static struct ddb_info ddb_v6_5 = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Cine S2 V6.5 DVB adapter", -- .port_num = 4, -+ -+static struct ddb_regset octopus_maxct_gtl_i2c = { -+ .base = 0x80, -+ .num = 0x04, -+ .size = 0x20, - }; - --static struct ddb_info ddb_dvbct = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices DVBCT V6.1 DVB adapter", -- .port_num = 3, -+static struct ddb_regset octopus_maxct_gtl_i2c_buf = { -+ .base = 0x1000, -+ .num = 0x04, -+ .size = 0x200, - }; - --static struct ddb_info ddb_satixS2v3 = { -- .type = DDB_OCTOPUS, -- .name = "Mystique SaTiX-S2 V3 DVB adapter", -- .port_num = 3, -+static struct ddb_regmap octopus_maxct_gtl_map = { -+ .i2c = &octopus_maxct_gtl_i2c, -+ .i2c_buf = &octopus_maxct_gtl_i2c_buf, - }; - --static struct ddb_info ddb_octopusv3 = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus V3 DVB adapter", -+static struct ddb_info octopus_ct_gtl = { -+ .type = DDB_OCTOPUS_MAX_CT, -+ .name = "Digital Devices Octopus MAX CT GTL", -+ .regmap = &octopus_maxct_gtl_map, - .port_num = 4, -+ .i2c_mask = 0x0f, -+ .board_control = 0xff, -+ .board_control_2 = 0xf00, -+ .ts_quirks = TS_QUIRK_SERIAL, - }; - --#define DDVID 0xdd01 /* Digital Devices Vendor ID */ -- --#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ -- .vendor = _vend, .device = _dev, \ -- .subvendor = _subvend, .subdevice = _subdev, \ -- .driver_data = (unsigned long)&_driverdata } -- --static const struct pci_device_id ddb_id_tbl[] = { -- DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), -- DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), -- DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3), -- /* in case sub-ids got deleted in flash */ -- DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -- {0} --}; --MODULE_DEVICE_TABLE(pci, ddb_id_tbl); - -+static int ddb_gtl_init_link(struct ddb *dev, u32 l) -+{ -+ struct ddb_link *link = &dev->link[l]; -+ u32 regs = dev->link[0].info->regmap->gtl->base + -+ (l - 1) * dev->link[0].info->regmap->gtl->size; -+ u32 id; -+ -+ pr_info("Checking GT link %u: regs = %08x\n", l, regs); -+ -+ spin_lock_init(&link->lock); -+ mutex_init(&link->lnb.lock); -+ link->lnb.fmode = 0xffffffff; -+ mutex_init(&link->flash_mutex); -+ -+ if (!(1 & ddbreadl(dev, regs))) { -+ u32 c; -+ -+ for (c = 0; c < 5; c++) { -+ ddbwritel(dev, 2, regs); -+ msleep(20); -+ ddbwritel(dev, 0, regs); -+ msleep(200); -+ if (1 & ddbreadl(dev, regs)) -+ break; -+ } -+ if (c == 5) -+ return -1; -+ } -+ link->nr = l; -+ link->dev = dev; -+ link->regs = regs; -+ -+ id = ddbreadl(dev, DDB_LINK_TAG(l) | 8); -+ switch (id) { -+ case 0x0007dd01: -+ link->info = &octopus_max_gtl; -+ break; -+ case 0x0008dd01: -+ link->info = &octopus_ct_gtl; -+ break; -+ default: -+ pr_info("DDBridge: Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.", -+ id); -+ return -1; -+ } -+ link->ids.devid = id; -+ -+ ddbwritel(dev, 1, 0x1a0); - --static struct pci_driver ddb_pci_driver = { -- .name = "DDBridge", -- .id_table = ddb_id_tbl, -- .probe = ddb_probe, -- .remove = ddb_remove, --}; -+ dev->handler_data[11] = (unsigned long) link; -+ dev->handler[11] = gtl_irq_handler; -+ -+ pr_info("GTL %s\n", dev->link[l].info->name); -+ pr_info("GTL HW %08x REGMAP %08x\n", -+ ddbreadl(dev, DDB_LINK_TAG(l) | 0), -+ ddbreadl(dev, DDB_LINK_TAG(l) | 4)); -+ pr_info("GTL ID %08x\n", -+ ddbreadl(dev, DDB_LINK_TAG(l) | 8)); -+ -+ tasklet_init(&link->tasklet, link_tasklet, (unsigned long) link); -+ ddbwritel(dev, 0xffffffff, DDB_LINK_TAG(l) | INTERRUPT_ACK); -+ ddbwritel(dev, 0xf, DDB_LINK_TAG(l) | INTERRUPT_ENABLE); - --static __init int module_init_ddbridge(void) -+ return 0; -+} -+ -+static int ddb_gtl_init(struct ddb *dev) - { -- int ret; -+ u32 l; - -- printk(KERN_INFO "Digital Devices PCIE bridge driver, " -- "Copyright (C) 2010-11 Digital Devices GmbH\n"); -+ dev->handler_data[10] = (unsigned long) dev; -+ dev->handler[10] = gtl_link_handler; - -- ret = ddb_class_create(); -- if (ret < 0) -- return ret; -- ret = pci_register_driver(&ddb_pci_driver); -- if (ret < 0) -- ddb_class_destroy(); -- return ret; -+ for (l = 1; l < dev->link[0].info->regmap->gtl->num + 1; l++) -+ ddb_gtl_init_link(dev, l); -+ return 0; - } - --static __exit void module_exit_ddbridge(void) -+static int ddb_init_boards(struct ddb *dev) - { -- pci_unregister_driver(&ddb_pci_driver); -- ddb_class_destroy(); -+ struct ddb_info *info; -+ u32 l; -+ -+ for (l = 0; l < DDB_MAX_LINK; l++) { -+ info = dev->link[l].info; -+ if (!info) -+ continue; -+ if (info->board_control) { -+ ddbwritel(dev, 0, DDB_LINK_TAG(l) | BOARD_CONTROL); -+ msleep(100); -+ ddbwritel(dev, info->board_control_2, -+ DDB_LINK_TAG(l) | BOARD_CONTROL); -+ usleep_range(2000, 3000); -+ ddbwritel(dev, -+ info->board_control_2 | info->board_control, -+ DDB_LINK_TAG(l) | BOARD_CONTROL); -+ usleep_range(2000, 3000); -+ } -+ } -+ return 0; - } - --module_init(module_init_ddbridge); --module_exit(module_exit_ddbridge); -+static int ddb_init(struct ddb *dev) -+{ -+ if (dev->link[0].info->ns_num) { -+ ddbwritel(dev, 1, ETHER_CONTROL); -+ dev->vlan = vlan; -+ ddbwritel(dev, 14 + (dev->vlan ? 4 : 0), ETHER_LENGTH); -+ } -+ -+ mutex_init(&dev->link[0].lnb.lock); -+ mutex_init(&dev->link[0].flash_mutex); -+ -+ if (dev->link[0].info->regmap->gtl) -+ ddb_gtl_init(dev); -+ -+ ddb_init_boards(dev); -+ -+ if (ddb_i2c_init(dev) < 0) -+ goto fail; -+ ddb_ports_init(dev); -+ if (ddb_buffers_alloc(dev) < 0) { -+ pr_info(": Could not allocate buffer memory\n"); -+ goto fail2; -+ } -+ ddb_ports_attach(dev); -+ -+ ddb_nsd_attach(dev); -+ -+ ddb_device_create(dev); -+ -+ if (dev->link[0].info->fan_num) { -+ ddbwritel(dev, 1, GPIO_DIRECTION); -+ ddbwritel(dev, 1, GPIO_OUTPUT); -+ } -+ if (dev->link[0].info->type == DDB_MOD) -+ ddbridge_mod_init(dev); -+ return 0; - --MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); --MODULE_AUTHOR("Ralph Metzler"); --MODULE_LICENSE("GPL"); --MODULE_VERSION("0.5"); -+fail2: -+ pr_err("fail2\n"); -+ ddb_buffers_free(dev); -+ ddb_i2c_release(dev); -+fail: -+ pr_err("fail1\n"); -+ return -1; -+} -diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c -new file mode 100644 -index 0000000..1e2e1da ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c -@@ -0,0 +1,290 @@ -+/* -+ * ddbridge-i2c.c: Digital Devices bridge i2c driver -+ * -+ * Copyright (C) 2010-2015 Digital Devices GmbH -+ * Ralph Metzler -+ * Marcus Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+static int i2c_io(struct i2c_adapter *adapter, u8 adr, -+ u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = wbuf, .len = wlen }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = rbuf, .len = rlen } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) -+{ -+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_read_regs(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 *val, u8 len) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_regs16(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 *val, u8 len) -+{ -+ u8 reg16[2] = { reg >> 8, reg }; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = reg16, .len = 2 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, -+ u16 reg, u8 *val) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, -+ u16 reg, u8 val) -+{ -+ u8 msg[3] = {reg >> 8, reg & 0xff, val}; -+ -+ return i2c_write(adap, adr, msg, 3); -+} -+ -+static int i2c_write_reg(struct i2c_adapter *adap, u8 adr, -+ u8 reg, u8 val) -+{ -+ u8 msg[2] = {reg, val}; -+ -+ return i2c_write(adap, adr, msg, 2); -+} -+ -+static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) -+{ -+ struct ddb *dev = i2c->dev; -+ unsigned long stat; -+ u32 val; -+ -+ ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND); -+ stat = wait_for_completion_timeout(&i2c->completion, HZ); -+ val = ddbreadl(dev, i2c->regs + I2C_COMMAND); -+ if (stat == 0) { -+ pr_err("DDBridge I2C timeout, card %d, port %d, link %u\n", -+ dev->nr, i2c->nr, i2c->link); -+ { -+ u32 istat = ddbreadl(dev, INTERRUPT_STATUS); -+ -+ dev_err(dev->dev, "DDBridge IRS %08x\n", istat); -+ if (i2c->link) { -+ u32 listat = ddbreadl(dev, -+ DDB_LINK_TAG(i2c->link) | -+ INTERRUPT_STATUS); -+ -+ dev_err(dev->dev, "DDBridge link %u IRS %08x\n", -+ i2c->link, listat); -+ } -+ if (istat & 1) { -+ ddbwritel(dev, istat & 1, INTERRUPT_ACK); -+ } else { -+ u32 mon = ddbreadl(dev, -+ i2c->regs + I2C_MONITOR); -+ -+ dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n", -+ val, mon); -+ } -+ } -+ return -EIO; -+ } -+ if (val & 0x70000) -+ return -EIO; -+ return 0; -+} -+ -+static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, -+ struct i2c_msg msg[], int num) -+{ -+ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); -+ struct ddb *dev = i2c->dev; -+ u8 addr = 0; -+ -+ if (num != 1 && num != 2) -+ return -EIO; -+ addr = msg[0].addr; -+ if (msg[0].len > i2c->bsize) -+ return -EIO; -+ if (num == 2 && msg[1].flags & I2C_M_RD && -+ !(msg[0].flags & I2C_M_RD)) { -+ if (msg[1].len > i2c->bsize) -+ return -EIO; -+ ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len); -+ ddbwritel(dev, msg[0].len | (msg[1].len << 16), -+ i2c->regs + I2C_TASKLENGTH); -+ if (!ddb_i2c_cmd(i2c, addr, 1)) { -+ ddbcpyfrom(dev, msg[1].buf, -+ i2c->rbuf, -+ msg[1].len); -+ return num; -+ } -+ } -+ if (num == 1 && !(msg[0].flags & I2C_M_RD)) { -+ ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len); -+ ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH); -+ if (!ddb_i2c_cmd(i2c, addr, 2)) -+ return num; -+ } -+ if (num == 1 && (msg[0].flags & I2C_M_RD)) { -+ ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); -+ if (!ddb_i2c_cmd(i2c, addr, 3)) { -+ ddbcpyfrom(dev, msg[0].buf, -+ i2c->rbuf, msg[0].len); -+ return num; -+ } -+ } -+ return -EIO; -+} -+ -+static u32 ddb_i2c_functionality(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -+} -+ -+struct i2c_algorithm ddb_i2c_algo = { -+ .master_xfer = ddb_i2c_master_xfer, -+ .functionality = ddb_i2c_functionality, -+}; -+ -+static void ddb_i2c_release(struct ddb *dev) -+{ -+ int i; -+ struct ddb_i2c *i2c; -+ -+ for (i = 0; i < dev->i2c_num; i++) { -+ i2c = &dev->i2c[i]; -+ i2c_del_adapter(&i2c->adap); -+ } -+} -+ -+static void i2c_handler(unsigned long priv) -+{ -+ struct ddb_i2c *i2c = (struct ddb_i2c *) priv; -+ -+ complete(&i2c->completion); -+} -+ -+static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c, -+ struct ddb_regmap *regmap, int link, int i, int num) -+{ -+ struct i2c_adapter *adap; -+ -+ i2c->nr = i; -+ i2c->dev = dev; -+ i2c->link = link; -+ i2c->bsize = regmap->i2c_buf->size; -+ i2c->wbuf = DDB_LINK_TAG(link) | -+ (regmap->i2c_buf->base + i2c->bsize * i); -+ i2c->rbuf = i2c->wbuf; /* + i2c->bsize / 2 */ -+ i2c->regs = DDB_LINK_TAG(link) | -+ (regmap->i2c->base + regmap->i2c->size * i); -+ ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING); -+ ddbwritel(dev, ((i2c->rbuf & 0xffff) << 16) | (i2c->wbuf & 0xffff), -+ i2c->regs + I2C_TASKADDRESS); -+ init_completion(&i2c->completion); -+ -+ adap = &i2c->adap; -+ i2c_set_adapdata(adap, i2c); -+#ifdef I2C_ADAP_CLASS_TV_DIGITAL -+ adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG; -+#else -+#ifdef I2C_CLASS_TV_ANALOG -+ adap->class = I2C_CLASS_TV_ANALOG; -+#endif -+#endif -+ strcpy(adap->name, "ddbridge"); -+ adap->algo = &ddb_i2c_algo; -+ adap->algo_data = (void *)i2c; -+ adap->dev.parent = dev->dev; -+ return i2c_add_adapter(adap); -+} -+ -+static int ddb_i2c_init(struct ddb *dev) -+{ -+ int stat = 0; -+ u32 i, j, num = 0, l; -+ struct ddb_i2c *i2c; -+ struct i2c_adapter *adap; -+ struct ddb_regmap *regmap; -+ -+ for (l = 0; l < DDB_MAX_LINK; l++) { -+ if (!dev->link[l].info) -+ continue; -+ regmap = dev->link[l].info->regmap; -+ if (!regmap || !regmap->i2c) -+ continue; -+ for (i = 0; i < regmap->i2c->num; i++) { -+ if (!(dev->link[l].info->i2c_mask & (1 << i))) -+ continue; -+ i2c = &dev->i2c[num]; -+ dev->handler_data[i + l * 32] = (unsigned long) i2c; -+ dev->handler[i + l * 32] = i2c_handler; -+ stat = ddb_i2c_add(dev, i2c, regmap, l, i, num); -+ if (stat) -+ break; -+ num++; -+ } -+ } -+ if (stat) { -+ for (j = 0; j < num; j++) { -+ i2c = &dev->i2c[j]; -+ adap = &i2c->adap; -+ i2c_del_adapter(adap); -+ } -+ } else -+ dev->i2c_num = num; -+ return stat; -+} -diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.h b/drivers/media/pci/ddbridge/ddbridge-i2c.h -new file mode 100644 -index 0000000..c20a2ba ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.h -@@ -0,0 +1,116 @@ -+/* -+ * ddbridge-i2c.h: Digital Devices bridge i2c driver -+ * -+ * Copyright (C) 2010-2015 Digital Devices GmbH -+ * Marcus Metzler -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#ifndef _DDBRIDGE_I2C_H_ -+#define _DDBRIDGE_I2C_H_ -+ -+#include -+#include -+ -+static inline int i2c_io(struct i2c_adapter *adapter, u8 adr, -+ u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = wbuf, .len = wlen }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = rbuf, .len = rlen } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_write(struct i2c_adapter *adap, u8 adr, -+ u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ -+static inline int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) -+{ -+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; -+} -+ -+static inline int i2c_read_regs(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 *val, u8 len) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_read_regs16(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 *val, u8 len) -+{ -+ u8 reg16[2] = { reg >> 8, reg }; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = reg16, .len = 2 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, -+ u8 reg, u8 *val) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, -+ u16 reg, u8 *val) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, -+ u16 reg, u8 val) -+{ -+ u8 msg[3] = {reg >> 8, reg & 0xff, val}; -+ -+ return i2c_write(adap, adr, msg, 3); -+} -+ -+static inline int i2c_write_reg(struct i2c_adapter *adap, u8 adr, -+ u8 reg, u8 val) -+{ -+ u8 msg[2] = {reg, val}; -+ -+ return i2c_write(adap, adr, msg, 2); -+} -+ -+#endif -diff --git a/drivers/media/pci/ddbridge/ddbridge-mod.c b/drivers/media/pci/ddbridge/ddbridge-mod.c -new file mode 100644 -index 0000000..fa1e92f ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-mod.c -@@ -0,0 +1,1118 @@ -+/* -+ * ddbridge.c: Digital Devices PCIe bridge driver -+ * -+ * Copyright (C) 2010-2015 Digital Devices GmbH -+ * Marcus Metzler -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include "ddbridge.h" -+#include "ddbridge-regs.h" -+ -+#include -+ -+inline s64 ConvertPCR(s64 a) -+{ -+ s32 ext; -+ s64 b; -+ -+ b = div_s64_rem(a, 300 << 22, &ext); -+ -+ return (b << 31) | ext; -+ -+} -+ -+inline s64 NegConvertPCR(s64 a) -+{ -+ s32 ext; -+ s64 b; -+ -+ b = -div_s64_rem(a, 300 << 22, &ext); -+ -+ if (ext != 0) { -+ ext = (300 << 22) - ext; -+ b -= 1; -+ } -+ return (b << 31) | ext; -+} -+ -+inline s64 RoundPCR(s64 a) -+{ -+ s64 b = a + (HW_LSB_MASK>>1); -+ -+ return b & ~(HW_LSB_MASK - 1); -+} -+ -+inline s64 RoundPCRUp(s64 a) -+{ -+ s64 b = a + (HW_LSB_MASK - 1); -+ -+ return b & ~(HW_LSB_MASK - 1); -+} -+ -+inline s64 RoundPCRDown(s64 a) -+{ -+ return a & ~(HW_LSB_MASK - 1); -+} -+ -+static int mod_busy(struct ddb *dev, int chan) -+{ -+ u32 creg; -+ -+ while (1) { -+ creg = ddbreadl(dev, CHANNEL_CONTROL(chan)); -+ if (creg == 0xffffffff) -+ return -EFAULT; -+ if ((creg & CHANNEL_CONTROL_BUSY) == 0) -+ break; -+ } -+ return 0; -+} -+ -+void ddbridge_mod_output_stop(struct ddb_output *output) -+{ -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ mod->State = CM_IDLE; -+ mod->Control = 0; -+ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); -+ mod_busy(dev, output->nr); -+ pr_info("mod_output_stop %d.%d\n", dev->nr, output->nr); -+} -+ -+static void mod_set_incs(struct ddb_output *output) -+{ -+ s64 pcr; -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ pcr = ConvertPCR(mod->PCRIncrement); -+ ddbwritel(dev, pcr & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTL(output->nr)); -+ ddbwritel(dev, (pcr >> 32) & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTH(output->nr)); -+ mod_busy(dev, output->nr); -+ -+ pcr = NegConvertPCR(mod->PCRDecrement); -+ ddbwritel(dev, pcr & 0xffffffff, -+ CHANNEL_PCR_ADJUST_INL(output->nr)); -+ ddbwritel(dev, (pcr >> 32) & 0xffffffff, -+ CHANNEL_PCR_ADJUST_INH(output->nr)); -+ mod_busy(dev, output->nr); -+ -+} -+ -+static void mod_set_rateinc(struct ddb *dev, u32 chan) -+{ -+ ddbwritel(dev, dev->mod[chan].rate_inc, CHANNEL_RATE_INCR(chan)); -+ mod_busy(dev, chan); -+} -+ -+static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 }; -+ -+void ddbridge_mod_output_start(struct ddb_output *output) -+{ -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ /*PCRIncrement = RoundPCR(PCRIncrement);*/ -+ /*PCRDecrement = RoundPCR(PCRDecrement);*/ -+ -+ mod->LastInPacketCount = 0; -+ mod->LastOutPacketCount = 0; -+ mod->InOverflowPacketCount = 0; -+ mod->OutOverflowPacketCount = 0; -+ mod->LastInPackets = 0; -+ mod->LastOutPackets = 0; -+ mod->LastPCRAdjust = 0; -+ mod->PCRRunningCorr = 0; -+ /* we interrupt every 0x80000=524288 packets */ -+ mod->MinInputPackets = 524288 / 2; -+ mod->PCRIncrement = 0; -+ mod->PCRDecrement = 0; -+ -+ mod->State = CM_STARTUP; -+ mod->StateCounter = CM_STARTUP_DELAY; -+ -+ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); -+ udelay(10); -+ ddbwritel(dev, CHANNEL_CONTROL_RESET, CHANNEL_CONTROL(output->nr)); -+ udelay(10); -+ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); -+ -+ /* QAM: 600 601 602 903 604 = 16 32 64 128 256 */ -+ /* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */ -+ ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr)); -+ -+ mod_set_rateinc(dev, output->nr); -+ mod_set_incs(output); -+ -+ mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | -+ CHANNEL_CONTROL_ENABLE_DVB | -+ CHANNEL_CONTROL_ENABLE_SOURCE); -+ -+ ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr)); -+ pr_info("mod_output_start %d.%d\n", dev->nr, output->nr); -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static void mod_write_dac_register(struct ddb *dev, u8 Index, u8 Value) -+{ -+ u32 RegValue = 0; -+ -+ ddbwritel(dev, Value, DAC_WRITE_DATA); -+ ddbwritel(dev, DAC_CONTROL_STARTIO | Index, DAC_CONTROL); -+ do { -+ RegValue = ddbreadl(dev, DAC_CONTROL); -+ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); -+} -+ -+static void mod_write_dac_register2(struct ddb *dev, u8 Index, u16 Value) -+{ -+ u32 RegValue = 0; -+ -+ ddbwritel(dev, Value, DAC_WRITE_DATA); -+ ddbwritel(dev, DAC_CONTROL_STARTIO | 0x20 | Index, DAC_CONTROL); -+ do { -+ RegValue = ddbreadl(dev, DAC_CONTROL); -+ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); -+} -+ -+static int mod_read_dac_register(struct ddb *dev, u8 Index, u8 *pValue) -+{ -+ u32 RegValue = 0; -+ -+ ddbwritel(dev, DAC_CONTROL_STARTIO | 0x80 | Index, DAC_CONTROL); -+ do { -+ RegValue = ddbreadl(dev, DAC_CONTROL); -+ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); -+ -+ RegValue = ddbreadl(dev, DAC_READ_DATA); -+ *pValue = (u8) RegValue; -+ return 0; -+} -+ -+static void mod_set_up_converter_vco1(struct ddb *dev, u32 Value) -+{ -+ u32 RegValue = 0; -+ -+ /* Extra delay before writing N divider */ -+ if ((Value & 0x03) == 0x02) -+ msleep(50); -+ do { -+ RegValue = ddbreadl(dev, VCO1_CONTROL); -+ } while ((RegValue & VCO1_CONTROL_WRITE) != 0); -+ -+ if ((RegValue & VCO1_CONTROL_CE) == 0) { -+ RegValue |= VCO1_CONTROL_CE; -+ ddbwritel(dev, RegValue, VCO1_CONTROL); -+ msleep(20); -+ } -+ -+ ddbwritel(dev, Value, VCO1_DATA); -+ ddbwritel(dev, RegValue | VCO1_CONTROL_WRITE, VCO1_CONTROL); -+} -+ -+static void mod_set_up_converter_vco2(struct ddb *dev, u32 Value) -+{ -+ u32 RegValue = 0; -+ -+ /* Extra delay before writing N divider */ -+ if ((Value & 0x03) == 0x02) -+ msleep(50); -+ do { -+ RegValue = ddbreadl(dev, VCO2_CONTROL); -+ } while ((RegValue & VCO2_CONTROL_WRITE) != 0); -+ -+ if ((RegValue & VCO2_CONTROL_CE) == 0) { -+ RegValue |= VCO2_CONTROL_CE; -+ ddbwritel(dev, RegValue, VCO2_CONTROL); -+ msleep(20); -+ } -+ -+ ddbwritel(dev, Value, VCO2_DATA); -+ ddbwritel(dev, RegValue | VCO2_CONTROL_WRITE, VCO2_CONTROL); -+} -+ -+static void mod_set_down_converter_vco(struct ddb *dev, u32 Value) -+{ -+ u32 RegValue = 0; -+ -+ do { -+ RegValue = ddbreadl(dev, VCO3_CONTROL); -+ } while ((RegValue & VCO3_CONTROL_WRITE) != 0); -+ -+ if ((RegValue & VCO3_CONTROL_CE) == 0) { -+ RegValue |= VCO3_CONTROL_CE; -+ ddbwritel(dev, RegValue, VCO3_CONTROL); -+ msleep(20); -+ } -+ ddbwritel(dev, Value, VCO3_DATA); -+ ddbwritel(dev, RegValue | VCO3_CONTROL_WRITE, VCO3_CONTROL); -+} -+ -+static int mod_set_attenuator(struct ddb *dev, u32 Value) -+{ -+ if (Value > 31) -+ return -EINVAL; -+ ddbwritel(dev, Value, RF_ATTENUATOR); -+ return 0; -+} -+ -+static void mod_si598_readreg(struct ddb *dev, u8 index, u8 *val) -+{ -+ ddbwritel(dev, index, CLOCKGEN_INDEX); -+ ddbwritel(dev, 1, CLOCKGEN_CONTROL); -+ usleep_range(5000, 6000); -+ *val = ddbreadl(dev, CLOCKGEN_READDATA); -+} -+ -+static void mod_si598_writereg(struct ddb *dev, u8 index, u8 val) -+{ -+ ddbwritel(dev, index, CLOCKGEN_INDEX); -+ ddbwritel(dev, val, CLOCKGEN_WRITEDATA); -+ ddbwritel(dev, 3, CLOCKGEN_CONTROL); -+ usleep_range(5000, 6000); -+} -+ -+static int mod_set_si598(struct ddb *dev, u32 freq) -+{ -+ u8 Data[6]; -+ u64 fDCO = 0; -+ u64 RFreq = 0; -+ u32 fOut = 10000000; -+ u64 m_fXtal = 0; -+ u32 N = 0; -+ u64 HSDiv = 0; -+ -+ u32 fxtal; -+ u64 MinDiv, MaxDiv, Div; -+ u64 RF; -+ -+ if (freq < 10000000 || freq > 525000000) -+ return -EINVAL; -+ mod_si598_writereg(dev, 137, 0x10); -+ -+ if (m_fXtal == 0) { -+ mod_si598_writereg(dev, 135, 0x01); -+ mod_si598_readreg(dev, 7, &Data[0]); -+ mod_si598_readreg(dev, 8, &Data[1]); -+ mod_si598_readreg(dev, 9, &Data[2]); -+ mod_si598_readreg(dev, 10, &Data[3]); -+ mod_si598_readreg(dev, 11, &Data[4]); -+ mod_si598_readreg(dev, 12, &Data[5]); -+ -+ pr_info(" Data = %02x %02x %02x %02x %02x %02x\n", -+ Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]); -+ RFreq = (((u64)Data[1] & 0x3F) << 32) | ((u64)Data[2] << 24) | -+ ((u64)Data[3] << 16) | ((u64)Data[4] << 8) | -+ ((u64)Data[5]); -+ if (RFreq == 0) -+ return -EINVAL; -+ HSDiv = ((Data[0] & 0xE0) >> 5) + 4; -+ if (HSDiv == 8 || HSDiv == 10) -+ return -EINVAL; -+ N = (((u32)(Data[0] & 0x1F) << 2) | -+ ((u32)(Data[1] & 0xE0) >> 6)) + 1; -+ fDCO = fOut * (u64)(HSDiv * N); -+ m_fXtal = fDCO << 28; -+ pr_info("fxtal %016llx rfreq %016llx\n", m_fXtal, RFreq); -+ -+ m_fXtal += RFreq >> 1; -+ m_fXtal = div64_u64(m_fXtal, RFreq); -+ -+ pr_info("fOut = %d fXtal = %d fDCO = %d HDIV = %2d, N = %3d\n", -+ (u32) fOut, (u32) m_fXtal, (u32) fDCO, (u32) HSDiv, N); -+ } -+ -+ fOut = freq; -+ MinDiv = 4850000000ULL; do_div(MinDiv, freq); MinDiv += 1; -+ MaxDiv = 5670000000ULL; do_div(MaxDiv, freq); -+ Div = 5260000000ULL; do_div(Div, freq); -+ -+ if (Div < MinDiv) -+ Div = Div + 1; -+ pr_info(" fOut = %u MinDiv = %llu MaxDiv = %llu StartDiv = %llu\n", -+ fOut, MinDiv, MaxDiv, Div); -+ -+ if (Div <= 11) { -+ N = 1; -+ HSDiv = Div; -+ } else { -+ int retry = 100; -+ -+ while (retry > 0) { -+ N = 0; -+ HSDiv = Div; -+ while ((HSDiv > 11) /*|| ((HSDiv * N) != Div)*/) { -+ N = N + 2; -+ HSDiv = Div; -+ do_div(HSDiv, N); -+ if (N > 128) -+ break; -+ } -+ pr_info(" %3d: %llu %llu %llu %u\n", -+ retry, Div, HSDiv * N, HSDiv, N); -+ if (HSDiv * N < MinDiv) -+ Div = Div + 2; -+ else if (HSDiv * N > MaxDiv) -+ Div = Div - 2; -+ else -+ break; -+ retry = retry - 1; -+ } -+ if (retry == 0) { -+ pr_err(" FAIL\n"); -+ return -EINVAL; -+ } -+ } -+ -+ if (HSDiv == 8 || HSDiv == 10) { -+ HSDiv = HSDiv >> 1; -+ N = N * 2; -+ } -+ -+ if (HSDiv < 4) -+ return -EINVAL; -+ -+ -+ fDCO = (u64)fOut * (u64)N * (u64)HSDiv; -+ pr_info("fdco %16llx\n", fDCO); -+ RFreq = fDCO<<28; -+ pr_info("%16llx %16llx\n", fDCO, RFreq); -+ -+ fxtal = m_fXtal; -+ do_div(RFreq, fxtal); -+ pr_info("%16llx %d\n", RFreq, fxtal); -+ RF = RFreq; -+ -+ pr_info("fOut = %u fXtal = %llu fDCO = %llu HSDIV = %llu, N = %u, RFreq = %llu\n", -+ fOut, m_fXtal, fDCO, HSDiv, N, RFreq); -+ -+ Data[0] = (u8)(((HSDiv - 4) << 5) | ((N - 1) >> 2)); -+ Data[1] = (u8)((((N - 1) & 0x03) << 6) | ((RF >> 32) & 0x3F)); -+ Data[2] = (u8)((RF >> 24) & 0xFF); -+ Data[3] = (u8)((RF >> 16) & 0xFF); -+ Data[4] = (u8)((RF >> 8) & 0xFF); -+ Data[5] = (u8)((RF) & 0xFF); -+ -+ pr_info(" Data = %02x %02x %02x %02x %02x %02x\n", -+ Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]); -+ mod_si598_writereg(dev, 7, Data[0]); -+ mod_si598_writereg(dev, 8, Data[1]); -+ mod_si598_writereg(dev, 9, Data[2]); -+ mod_si598_writereg(dev, 10, Data[3]); -+ mod_si598_writereg(dev, 11, Data[4]); -+ mod_si598_writereg(dev, 12, Data[5]); -+ -+ mod_si598_writereg(dev, 137, 0x00); -+ mod_si598_writereg(dev, 135, 0x40); -+ return 0; -+} -+ -+ -+static void mod_bypass_equalizer(struct ddb *dev, int bypass) -+{ -+ u32 RegValue; -+ -+ RegValue = ddbreadl(dev, IQOUTPUT_CONTROL); -+ RegValue &= ~IQOUTPUT_CONTROL_BYPASS_EQUALIZER; -+ RegValue |= (bypass ? IQOUTPUT_CONTROL_BYPASS_EQUALIZER : 0x00); -+ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); -+} -+ -+static int mod_set_equalizer(struct ddb *dev, u32 Num, s16 *cTable) -+{ -+ u32 i, adr = IQOUTPUT_EQUALIZER_0; -+ -+ if (Num > 11) -+ return -EINVAL; -+ -+ for (i = 0; i < 11 - Num; i += 1) { -+ ddbwritel(dev, 0, adr); -+ adr += 4; -+ } -+ for (i = 0; i < Num; i += 1) { -+ ddbwritel(dev, (u32) cTable[i], adr); -+ adr += 4; -+ } -+ return 0; -+} -+ -+static int mod_init_dac_input(struct ddb *dev) -+{ -+ u8 Set = 0; -+ u8 Hld = 0; -+ u8 Sample = 0; -+ -+ u8 Seek = 0; -+ u8 ReadSeek = 0; -+ -+ u8 SetTable[32]; -+ u8 HldTable[32]; -+ u8 SeekTable[32]; -+ -+ u8 Sample1 = 0xFF; -+ u8 Sample2 = 0xFF; -+ -+ u8 SelectSample = 0xFF; -+ u8 DiffMin = 0xFF; -+ -+ for (Sample = 0; Sample < 32; Sample++) { -+ Set = 0; -+ Hld = 0; -+ -+ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); -+ mod_write_dac_register(dev, 0x05, Sample); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ Seek = ReadSeek & 0x01; -+ SeekTable[Sample] = Seek; -+ -+ HldTable[Sample] = 15; -+ -+ for (Hld = 1; Hld < 16; Hld += 1) { -+ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ -+ if ((ReadSeek & 0x01) != Seek) { -+ HldTable[Sample] = Hld; -+ break; -+ } -+ } -+ -+ Hld = 0; -+ SetTable[Sample] = 15; -+ for (Set = 1; Set < 16; Set += 1) { -+ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ -+ if ((ReadSeek & 0x01) != Seek) { -+ SetTable[Sample] = Set; -+ break; -+ } -+ } -+ } -+ -+ Seek = 1; -+ for (Sample = 0; Sample < 32; Sample += 1) { -+ if (Sample1 == 0xFF && SeekTable[Sample] == 1 && Seek == 0) -+ Sample1 = Sample; -+ if (Sample1 != 0xFF && Sample2 == 0xFF && -+ SeekTable[Sample] == 0 && Seek == 1) -+ Sample2 = Sample; -+ Seek = SeekTable[Sample]; -+ } -+ -+ if (Sample1 == 0xFF || Sample2 == 0xFF) { -+ pr_err(" No valid window found\n"); -+ return -EINVAL; -+ } -+ -+ pr_err(" Window = %d - %d\n", Sample1, Sample2); -+ -+ for (Sample = Sample1; Sample < Sample2; Sample += 1) { -+ if (SetTable[Sample] < HldTable[Sample]) { -+ if (HldTable[Sample] - SetTable[Sample] < DiffMin) { -+ DiffMin = HldTable[Sample] - SetTable[Sample]; -+ SelectSample = Sample; -+ } -+ } -+ } -+ -+ pr_info("Select Sample %d\n", SelectSample); -+ -+ if (SelectSample == 0xFF) { -+ pr_err("No valid sample found\n"); -+ return -EINVAL; -+ } -+ -+ if (HldTable[SelectSample] + SetTable[SelectSample] < 8) { -+ pr_err("Too high jitter\n"); -+ return -EINVAL; -+ } -+ -+ mod_write_dac_register(dev, 0x04, 0x00); -+ mod_write_dac_register(dev, 0x05, (SelectSample - 1) & 0x1F); -+ mod_read_dac_register(dev, 0x06, &Seek); -+ mod_write_dac_register(dev, 0x05, (SelectSample + 1) & 0x1F); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ Seek &= ReadSeek; -+ -+ mod_write_dac_register(dev, 0x05, SelectSample); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ Seek &= ReadSeek; -+ if ((Seek & 0x01) == 0) { -+ pr_err("Insufficient timing margin\n"); -+ return -EINVAL; -+ } -+ pr_info("Done\n"); -+ return 0; -+} -+ -+static void mod_set_up1(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) -+{ -+ u32 RDiv = Ext / Ref; -+ -+ Frequency = Frequency / Ref; -+ mod_set_up_converter_vco1(dev, 0x360001 | (RDiv << 2)); -+ mod_set_up_converter_vco1(dev, 0x0ff128); -+ mod_set_up_converter_vco1(dev, 0x02 | (Frequency << 8)); -+} -+ -+static void mod_set_up2(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) -+{ -+ u32 Rdiv = Ext / Ref; -+ u32 PreScale = 8; -+ -+ Frequency = Frequency / Ref; -+ mod_set_up_converter_vco2(dev, 0x360001 | (Rdiv << 2)); -+ mod_set_up_converter_vco2(dev, 0x0fc128 | -+ (((PreScale - 8) / 8) << 22)); -+ mod_set_up_converter_vco2(dev, 0x02 | ((Frequency / PreScale) << 8) -+ | (Frequency & (PreScale - 1)) << 2); -+} -+ -+static int mod_set_down(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) -+{ -+ u32 BandSelect = Ref * 8; -+ u32 RefMul = 1; -+ u32 RefDiv2 = 1; -+ u32 RefDiv = Ext * RefMul / (Ref * RefDiv2); -+ -+ if (Frequency < 2200 || Frequency > 4000) -+ return -EINVAL; -+ -+ Frequency = Frequency / Ref; -+ -+ mod_set_down_converter_vco(dev, 0x0080003C | -+ ((BandSelect & 0xFF) << 12)); -+ mod_set_down_converter_vco(dev, 0x00000003); -+ mod_set_down_converter_vco(dev, 0x18001E42 | ((RefMul-1) << 25) | -+ ((RefDiv2-1) << 24) | (RefDiv << 14)); -+ mod_set_down_converter_vco(dev, 0x08008021); -+ mod_set_down_converter_vco(dev, Frequency << 15); -+ return 0; -+} -+ -+static int mod_set_dac_clock(struct ddb *dev, u32 Frequency) -+{ -+ int hr, i; -+ -+ if (Frequency) { -+ ddbwritel(dev, DAC_CONTROL_RESET, DAC_CONTROL); -+ msleep(20); -+ if (mod_set_si598(dev, Frequency)) { -+ pr_err("mod_set_si598 failed\n"); -+ return -1; -+ } -+ msleep(50); -+ ddbwritel(dev, 0x000, DAC_CONTROL); -+ msleep(20); -+ mod_write_dac_register(dev, 0, 0x02); -+ } -+ -+ for (i = 0; i < 10; i++) { -+ hr = mod_init_dac_input(dev); -+ if (hr == 0) -+ break; -+ msleep(100); -+ } -+ pr_info("mod_set_dac_clock OK\n"); -+ return hr; -+} -+ -+static void mod_set_dac_current(struct ddb *dev, u32 Current1, u32 Current2) -+{ -+ mod_write_dac_register2(dev, 0x0b, Current1 & 0x3ff); -+ mod_write_dac_register2(dev, 0x0f, Current2 & 0x3ff); -+} -+ -+static void mod_output_enable(struct ddb *dev, int enable) -+{ -+ -+ u32 RegValue; -+ -+ RegValue = ddbreadl(dev, IQOUTPUT_CONTROL); -+ RegValue &= ~(IQOUTPUT_CONTROL_ENABLE | IQOUTPUT_CONTROL_RESET); -+ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); -+ -+ if (enable) { -+ ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_RESET, -+ IQOUTPUT_CONTROL); -+ msleep(20); -+ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); -+ ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_ENABLE, -+ IQOUTPUT_CONTROL); -+ } -+} -+ -+static int mod_set_iq(struct ddb *dev, u32 steps, u32 chan, u32 freq) -+{ -+ u32 i, j, k, fac = 8; -+ u32 s1 = 22, s2 = 33; -+ u64 amp = (1ULL << 17) - 1ULL; -+ u64 s = 0, c = (amp << s1), ss; -+ u64 frq = 0xC90FDAA22168C235ULL; /* PI << 62 */ -+ u32 *iqtab; -+ u32 iqtabadr; -+ u32 regval; -+ -+ iqtab = kmalloc((steps + 1) * 4, GFP_KERNEL); -+ if (!iqtab) -+ return -ENOMEM; -+ frq = div64_u64(frq, steps * fac) >> (61 - s2); -+ -+ /* create sine table */ -+ for (i = 0; i <= steps * fac / 4; i++) { -+ if (!(i & (fac - 1))) { -+ j = i / fac; -+ ss = s >> s1; -+ /* round? ss = ((s >> (s1 - 1)) + 1) >> 1; */ -+ iqtab[j] = iqtab[steps / 2 - j] = ss; -+ iqtab[steps / 2 + j] = iqtab[steps - j] = -ss; -+ } -+ c -= ((s * frq) >> s2); -+ s += ((c * frq) >> s2); -+ } -+ iqtabadr = chan << 16; -+ ddbwritel(dev, chan & 0x0f, MODULATOR_IQTABLE_INDEX); -+ for (i = j = 0, k = steps / 4; i < steps; i++) { -+ ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_I, -+ MODULATOR_IQTABLE_INDEX); -+ ddbwritel(dev, iqtab[j], MODULATOR_IQTABLE_DATA); -+ regval = ddbreadl(dev, MODULATOR_CONTROL); -+ ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_Q, -+ MODULATOR_IQTABLE_INDEX); -+ ddbwritel(dev, iqtab[k], MODULATOR_IQTABLE_DATA); -+ regval = ddbreadl(dev, MODULATOR_CONTROL); -+ j += freq; -+ j %= steps; -+ k += freq; -+ k %= steps; -+ } -+ ddbwritel(dev, steps - 1, MODULATOR_IQTABLE_END); -+ kfree(iqtab); -+ return 0; -+} -+ -+u32 eqtab[] = { -+ 0x0000FFDB, 0x00000121, 0x0000FF0A, 0x000003D7, -+ 0x000001C4, 0x000005A5, 0x000009CC, 0x0000F50D, -+ 0x00001B23, 0x0000EEB7, 0x00006A28 -+}; -+ -+static int mod_set_modulation(struct ddb *dev, int chan, enum fe_modulation mod) -+{ -+ if (mod > QAM_256 || mod < QAM_16) -+ return -EINVAL; -+ dev->mod[chan].modulation = mod; -+ dev->mod[chan].obitrate = 0x0061072787900000ULL * (mod + 3); -+ dev->mod[chan].ibitrate = dev->mod[chan].obitrate; -+ ddbwritel(dev, qamtab[mod], CHANNEL_SETTINGS(chan)); -+ return 0; -+} -+ -+static void mod_set_channelsumshift(struct ddb *dev, u32 shift) -+{ -+ ddbwritel(dev, (shift & 3) << 2, MODULATOR_CONTROL); -+} -+ -+static void mod_pre_eq_gain(struct ddb *dev, u16 gain) -+{ -+ ddbwritel(dev, gain, IQOUTPUT_PRESCALER); -+} -+ -+static void mod_post_eq_gain(struct ddb *dev, u16 igain, u16 qgain) -+{ -+ ddbwritel(dev, ((u32)qgain << 16) | igain, IQOUTPUT_POSTSCALER); -+} -+ -+static int set_base_frequency(struct ddb *dev, u32 freq) -+{ -+ u32 Ext = 40; -+ u32 UP1Frequency = 290; -+ u32 UP2Frequency = 1896; -+ u32 down, freq10; -+ -+ pr_info("set base to %u\n", freq); -+ dev->mod_base.frequency = freq; -+ freq /= 1000000; -+ freq10 = dev->mod_base.flat_start + 4; -+ down = freq + 9 * 8 + freq10 + UP1Frequency + UP2Frequency; -+ -+ if ((freq10 + 9 * 8) > (dev->mod_base.flat_end - 4)) { -+ pr_err("Frequency out of range %d\n", freq10); -+ return -EINVAL; -+ } -+ if (down % 8) { -+ pr_err(" Invalid Frequency %d\n", down); -+ return -EINVAL; -+ } -+ return mod_set_down(dev, down, 8, Ext); -+} -+ -+static int mod_init(struct ddb *dev, u32 Frequency) -+{ -+ int stat = 0; -+ u8 *buffer; -+ struct DDMOD_FLASH *flash; -+ u32 Ext = 40; -+ u32 UP1Frequency = 290; -+ u32 UP2Frequency = 1896; -+ u32 DownFrequency; -+ u32 FrequencyCH10; -+ u32 iqfreq, iqsteps, i; -+ -+ buffer = kmalloc(4096, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ flash = (struct DDMOD_FLASH *) buffer; -+ -+ ddbridge_flashread(dev, 0, buffer, DDMOD_FLASH_START, 4096); -+ -+ if (flash->Magic != DDMOD_FLASH_MAGIC && flash->Magic != 1) { -+ stat = -EINVAL; -+ goto fail; -+ } -+ pr_info("srate = %d\n", flash->DataSet[0].Symbolrate * 1000); -+ -+ mod_output_enable(dev, 0); -+ stat = mod_set_dac_clock(dev, flash->DataSet[0].DACFrequency * 1000); -+ if (stat < 0) { -+ pr_err("setting DAC clock failed\n"); -+ goto fail; -+ } -+ mod_set_dac_current(dev, 512, 512); -+ -+ ddbwritel(dev, flash->DataSet[0].Control2, IQOUTPUT_CONTROL2); -+ -+ mod_set_up1(dev, UP1Frequency, 5, Ext); -+ mod_set_up2(dev, UP2Frequency, 8, Ext); -+ -+ dev->mod_base.flat_start = flash->DataSet[0].FlatStart; -+ dev->mod_base.flat_end = flash->DataSet[0].FlatEnd; -+ -+ Frequency /= 1000000; -+ FrequencyCH10 = flash->DataSet[0].FlatStart + 4; -+ DownFrequency = Frequency + 9 * 8 + FrequencyCH10 + -+ UP1Frequency + UP2Frequency; -+ pr_info("CH10 = %d, Down = %d\n", FrequencyCH10, DownFrequency); -+ -+ if ((FrequencyCH10 + 9 * 8) > (flash->DataSet[0].FlatEnd - 4)) { -+ pr_err("Frequency out of range %d\n", FrequencyCH10); -+ stat = -EINVAL; -+ goto fail; -+ } -+ -+ if (DownFrequency % 8 != 0) { -+ pr_err(" Invalid Frequency %d\n", DownFrequency); -+ stat = -EINVAL; -+ goto fail; -+ } -+ -+ mod_set_down(dev, DownFrequency, 8, Ext); -+ -+ for (i = 0; i < 10; i++) { -+ ddbwritel(dev, 0, CHANNEL_CONTROL(i)); -+ -+ iqfreq = flash->DataSet[0].FrequencyFactor * -+ (FrequencyCH10 + (9 - i) * 8); -+ iqsteps = flash->DataSet[0].IQTableLength; -+ mod_set_iq(dev, iqsteps, i, iqfreq); -+ mod_set_modulation(dev, i, QAM_256); -+ } -+ -+ mod_bypass_equalizer(dev, 1); -+ mod_set_equalizer(dev, 11, flash->DataSet[0].EQTap); -+ mod_bypass_equalizer(dev, 0); -+ mod_post_eq_gain(dev, flash->DataSet[0].PostScaleI, -+ flash->DataSet[0].PostScaleQ); -+ mod_pre_eq_gain(dev, flash->DataSet[0].PreScale); -+ /*mod_pre_eq_gain(dev, 0x0680);*/ -+ pr_info("prescaler %04x\n", flash->DataSet[0].PreScale); -+ mod_set_channelsumshift(dev, 2); -+ mod_output_enable(dev, 1); -+ -+ /*mod_set_attenuator(dev, 10);*/ -+fail: -+ kfree(buffer); -+ return stat; -+} -+ -+#define PACKET_CLOCKS (27000000ULL*1504) -+#define FACTOR (1ULL << 22) -+ -+/* -+ * double Increment = FACTOR*PACKET_CLOCKS/double(m_OutputBitrate); -+ * double Decrement = FACTOR*PACKET_CLOCKS/double(m_InputBitrate); -+ * 27000000 * 1504 * 2^22 / (6900000 * 188 / 204) = 26785190066.1 -+ */ -+ -+void ddbridge_mod_rate_handler(unsigned long data) -+{ -+ struct ddb_output *output = (struct ddb_output *) data; -+ struct ddb_dma *dma = output->dma; -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ u32 chan = output->nr; -+ u32 OutPacketCount; -+ u32 InPacketCount; -+ u64 OutPackets, InPackets; -+ s64 PCRAdjust; -+ u32 PCRAdjustExt, PCRAdjustExtFrac, InPacketDiff, OutPacketDiff; -+ s32 PCRCorr; -+ -+ s64 pcr; -+ s64 PCRIncrementDiff; -+ s64 PCRIncrement; -+ u64 mul; -+ -+ if (!mod->pcr_correction) -+ return; -+ spin_lock(&dma->lock); -+ ddbwritel(dev, mod->Control | CHANNEL_CONTROL_FREEZE_STATUS, -+ CHANNEL_CONTROL(output->nr)); -+ -+ OutPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_OUT(chan)); -+ if (OutPacketCount < mod->LastOutPacketCount) -+ mod->OutOverflowPacketCount += 1; -+ mod->LastOutPacketCount = OutPacketCount; -+ -+ InPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_IN(chan)); -+ if (InPacketCount < mod->LastInPacketCount) -+ mod->InOverflowPacketCount += 1; -+ mod->LastInPacketCount = InPacketCount; -+ -+ OutPackets = ((u64) (mod->OutOverflowPacketCount) << 20) | -+ OutPacketCount; -+ InPackets = ((u64) (mod->InOverflowPacketCount) << 20) | -+ InPacketCount; -+ -+ PCRAdjust = (s64) ((u64) ddbreadl(dev, -+ CHANNEL_PCR_ADJUST_ACCUL(chan)) | -+ (((u64) ddbreadl(dev, -+ CHANNEL_PCR_ADJUST_ACCUH(chan)) -+ << 32))); -+ PCRAdjustExt = (u32)((PCRAdjust & 0x7FFFFFFF) >> 22); -+ PCRAdjustExtFrac = (u32)((PCRAdjust & 0x003FFFFF) >> 12); -+ PCRAdjust >>= 31; -+ InPacketDiff = (u32) (InPackets - mod->LastInPackets); -+ OutPacketDiff = (u32) (OutPackets - mod->LastOutPackets); -+ PCRCorr = 0; -+ -+ switch (mod->State) { -+ case CM_STARTUP: -+ if (mod->StateCounter) { -+ if (mod->StateCounter == 1) { -+ if (mod->ibitrate == 0) { -+ mul = (0x1000000 * -+ (u64) (OutPacketDiff - -+ InPacketDiff - -+ InPacketDiff/1000)); -+ if (OutPacketDiff) -+ mod->rate_inc = div_u64(mul, -+ OutPacketDiff); -+ else -+ mod->rate_inc = 0; -+ mod_set_rateinc(dev, output->nr); -+ mod->PCRIncrement = -+ div_u64(26785190066ULL, -+ mod->modulation + 3); -+ if (InPacketDiff) -+ mod->PCRDecrement = div_u64( -+ mod->PCRIncrement * -+ (u64) OutPacketDiff, -+ InPacketDiff); -+ else -+ mod->PCRDecrement = 0; -+ mod_set_incs(output); -+ } else { -+ mod->PCRIncrement = -+ div_u64(26785190066ULL, -+ mod->modulation + 3); -+ mod->PCRDecrement = -+ div_u64(FACTOR*PACKET_CLOCKS, -+ mod->ibitrate >> 32); -+ mod_set_incs(output); -+ } -+ } -+ mod->StateCounter--; -+ break; -+ } else if (InPacketDiff >= mod->MinInputPackets) { -+ mod->State = CM_ADJUST; -+ mod->Control |= CHANNEL_CONTROL_ENABLE_PCRADJUST; -+ mod->InPacketsSum = 0; -+ mod->OutPacketsSum = 0; -+ mod->PCRAdjustSum = 0; -+ mod->StateCounter = CM_AVERAGE; -+ } -+ break; -+ -+ case CM_ADJUST: -+ if (InPacketDiff < mod->MinInputPackets) { -+ pr_info("PCR Adjust reset IN: %u Min: %u\n", -+ InPacketDiff, mod->MinInputPackets); -+ mod->InPacketsSum = 0; -+ mod->OutPacketsSum = 0; -+ mod->PCRAdjustSum = 0; -+ mod->StateCounter = CM_AVERAGE; -+ ddbwritel(dev, -+ (mod->Control | -+ CHANNEL_CONTROL_FREEZE_STATUS) & -+ ~CHANNEL_CONTROL_ENABLE_PCRADJUST, -+ CHANNEL_CONTROL(chan)); -+ break; -+ } -+ -+ mod->PCRAdjustSum += (s32) PCRAdjust; -+ mod->InPacketsSum += InPacketDiff; -+ mod->OutPacketsSum += OutPacketDiff; -+ if (mod->StateCounter--) -+ break; -+ -+ if (mod->OutPacketsSum) -+ PCRIncrement = div_s64((s64)mod->InPacketsSum * -+ (s64)mod->PCRDecrement + -+ (s64)(mod->OutPacketsSum >> 1), -+ mod->OutPacketsSum); -+ else -+ PCRIncrement = 0; -+ -+ if (mod->PCRAdjustSum > 0) -+ PCRIncrement = RoundPCRDown(PCRIncrement); -+ else -+ PCRIncrement = RoundPCRUp(PCRIncrement); -+ -+ PCRIncrementDiff = PCRIncrement - mod->PCRIncrement; -+ if (PCRIncrementDiff > HW_LSB_MASK) -+ PCRIncrementDiff = HW_LSB_MASK; -+ if (PCRIncrementDiff < -HW_LSB_MASK) -+ PCRIncrementDiff = -HW_LSB_MASK; -+ -+ mod->PCRIncrement += PCRIncrementDiff; -+ pcr = ConvertPCR(mod->PCRIncrement); -+ pr_info("outl %016llx\n", pcr); -+ ddbwritel(dev, pcr & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTL(output->nr)); -+ ddbwritel(dev, (pcr >> 32) & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTH(output->nr)); -+ mod_busy(dev, chan); -+ -+ PCRCorr = (s32) (PCRIncrementDiff >> HW_LSB_SHIFT); -+ mod->PCRRunningCorr += PCRCorr; -+ -+ mod->InPacketsSum = 0; -+ mod->OutPacketsSum = 0; -+ mod->PCRAdjustSum = 0; -+ mod->StateCounter = CM_AVERAGE; -+ break; -+ -+ default: -+ break; -+ } -+ ddbwritel(dev, mod->Control, CHANNEL_CONTROL(chan)); -+ -+ mod->LastInPackets = InPackets; -+ mod->LastOutPackets = OutPackets; -+ mod->LastPCRAdjust = (s32) PCRAdjust; -+ -+ spin_unlock(&dma->lock); -+ -+ pr_info("chan %d out %016llx in %016llx indiff %08x\n", -+ chan, OutPackets, InPackets, InPacketDiff); -+ pr_info("cnt %d pcra %016llx pcraext %08x pcraextfrac %08x pcrcorr %08x pcri %016llx\n", -+ mod->StateCounter, PCRAdjust, PCRAdjustExt, -+ PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement); -+} -+ -+int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb *dev = output->port->dev; -+ -+ /* unsigned long arg = (unsigned long) parg; */ -+ int ret = 0; -+ -+ switch (cmd) { -+ case DVB_MOD_SET: -+ { -+ struct dvb_mod_params *mp = parg; -+ -+ pr_info("set base freq\n"); -+ if (mp->base_frequency != dev->mod_base.frequency) -+ if (set_base_frequency(dev, mp->base_frequency)) -+ return -EINVAL; -+ pr_info("set attenuator\n"); -+ mod_set_attenuator(dev, mp->attenuator); -+ break; -+ } -+ case DVB_MOD_CHANNEL_SET: -+ { -+ struct dvb_mod_channel_params *cp = parg; -+ int res; -+ u32 ri; -+ -+ pr_info("set modulation\n"); -+ res = mod_set_modulation(dev, output->nr, cp->modulation); -+ if (res) -+ return res; -+ -+ if (cp->input_bitrate > dev->mod[output->nr].obitrate) -+ return -EINVAL; -+ dev->mod[output->nr].ibitrate = cp->input_bitrate; -+ dev->mod[output->nr].pcr_correction = cp->pcr_correction; -+ -+ pr_info("ibitrate %llu\n", dev->mod[output->nr].ibitrate); -+ pr_info("obitrate %llu\n", dev->mod[output->nr].obitrate); -+ if (cp->input_bitrate != 0) { -+ u64 d = dev->mod[output->nr].obitrate - -+ dev->mod[output->nr].ibitrate; -+ -+ d = div64_u64(d, dev->mod[output->nr].obitrate >> 24); -+ if (d > 0xfffffe) -+ ri = 0xfffffe; -+ else -+ ri = d; -+ } else -+ ri = 0; -+ dev->mod[output->nr].rate_inc = ri; -+ pr_info("ibr=%llu, obr=%llu, ri=0x%06x\n", -+ dev->mod[output->nr].ibitrate >> 32, -+ dev->mod[output->nr].obitrate >> 32, -+ ri); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+int ddbridge_mod_init(struct ddb *dev) -+{ -+ return mod_init(dev, 722000000); -+} -diff --git a/drivers/media/pci/ddbridge/ddbridge-ns.c b/drivers/media/pci/ddbridge/ddbridge-ns.c -new file mode 100644 -index 0000000..7b6d659 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-ns.c -@@ -0,0 +1,491 @@ -+/* -+ * ddbridge-ns.c: Digital Devices PCIe bridge driver net streaming -+ * -+ * Copyright (C) 2010-2015 Marcus Metzler -+ * Ralph Metzler -+ * Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+static int ddb_dvb_ns_input_start(struct ddb_input *input); -+static int ddb_dvb_ns_input_stop(struct ddb_input *input); -+ -+static u16 calc_pcs(struct dvb_ns_params *p) -+{ -+ u32 sum = 0; -+ u16 pcs; -+ -+ sum += (p->sip[0] << 8) | p->sip[1]; -+ sum += (p->sip[2] << 8) | p->sip[3]; -+ sum += (p->dip[0] << 8) | p->dip[1]; -+ sum += (p->dip[2] << 8) | p->dip[3]; -+ sum += 0x11; /* UDP proto */ -+ sum = (sum >> 16) + (sum & 0xffff); -+ pcs = sum; -+ return pcs; -+} -+ -+static u16 calc_pcs16(struct dvb_ns_params *p, int ipv) -+{ -+ u32 sum = 0, i; -+ u16 pcs; -+ -+ for (i = 0; i < ipv ? 16 : 4; i += 2) { -+ sum += (p->sip[i] << 8) | p->sip[i + 1]; -+ sum += (p->dip[i] << 8) | p->dip[i + 1]; -+ } -+ sum += 0x11; /* UDP proto */ -+ sum = (sum >> 16) + (sum & 0xffff); -+ pcs = sum; -+ return pcs; -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static void ns_free(struct dvbnss *nss) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ -+ mutex_lock(&dev->mutex); -+ dns->input = 0; -+ mutex_unlock(&dev->mutex); -+} -+ -+static int ns_alloc(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ int i, ret = -EBUSY; -+ -+ mutex_lock(&dev->mutex); -+ for (i = 0; i < dev->ns_num; i++) { -+ if (dev->ns[i].input) -+ continue; -+ dev->ns[i].input = input; -+ dev->ns[i].fe = input; -+ nss->priv = &dev->ns[i]; -+ ret = 0; -+ /*pr_info("%s i=%d fe=%d\n", __func__, i, input->nr); */ -+ break; -+ } -+ ddbwritel(dev, 0x03, RTP_MASTER_CONTROL); -+ mutex_unlock(&dev->mutex); -+ return ret; -+} -+ -+static int ns_set_pids(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ -+ if (dev->link[0].ids.devid == 0x0301dd01) { -+ u32 sys = 0; -+ int pid, j = 1; -+ -+ sys |= nss->pids[0] & 3; -+ sys |= (nss->pids[2] & 0x1f) << 4; -+ ddbwritel(dev, sys, PID_FILTER_SYSTEM_PIDS(dns->nr)); -+ for (pid = 20; j < 5 && pid < 8192; pid++) -+ if (nss->pids[pid >> 3] & (1 << (pid & 7))) { -+ ddbwritel(dev, 0x8000 | pid, -+ PID_FILTER_PID(dns->nr, j)); -+ j++; -+ } -+ /* disable unused pids */ -+ for (; j < 5; j++) -+ ddbwritel(dev, 0, PID_FILTER_PID(dns->nr, j)); -+ } else -+ ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400); -+ return 0; -+} -+ -+static int ns_set_pid(struct dvbnss *nss, u16 pid) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ u16 byte = (pid & 0x1fff) >> 3; -+ u8 bit = 1 << (pid & 7); -+ u32 off = STREAM_PIDS(dns->nr); -+ -+ if (dev->link[0].ids.devid == 0x0301dd01) { -+ if (pid & 0x2000) { -+ if (pid & 0x8000) -+ memset(nss->pids, 0xff, 0x400); -+ else -+ memset(nss->pids, 0x00, 0x400); -+ } else { -+ if (pid & 0x8000) -+ nss->pids[byte] |= bit; -+ else -+ nss->pids[byte] &= ~bit; -+ } -+ ns_set_pids(nss); -+ } else { -+ if (pid & 0x2000) { -+ if (pid & 0x8000) -+ ddbmemset(dev, off, 0xff, 0x400); -+ else -+ ddbmemset(dev, off, 0x00, 0x400); -+ } else { -+ u8 val = ddbreadb(dev, off + byte); -+ -+ if (pid & 0x8000) -+ ddbwriteb(dev, val | bit, off + byte); -+ else -+ ddbwriteb(dev, val & ~bit, off + byte); -+ } -+ } -+ return 0; -+} -+ -+static int citoport(struct ddb *dev, u8 ci) -+{ -+ int i, j; -+ -+ for (i = j = 0; i < dev->link[0].info->port_num; i++) { -+ if (dev->port[i].class == DDB_PORT_CI) { -+ if (j == ci) -+ return i; -+ j++; -+ } -+ } -+ return -1; -+} -+ -+static int ns_set_ci(struct dvbnss *nss, u8 ci) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ int ciport; -+ -+ if (ci == 255) { -+ dns->fe = input; -+ return 0; -+ } -+ ciport = citoport(dev, ci); -+ if (ciport < 0) -+ return -EINVAL; -+ -+ pr_info("input %d.%d to ci %d at port %d\n", input->port->lnr, -+ input->nr, ci, ciport); -+ ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1c, -+ TS_OUTPUT_CONTROL(ciport)); -+ usleep_range(1, 5); -+ ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d, -+ TS_OUTPUT_CONTROL(ciport)); -+ dns->fe = dev->port[ciport].input[0]; -+ return 0; -+} -+ -+static u8 rtp_head[] = { -+ 0x80, 0x21, -+ 0x00, 0x00, /* seq number */ -+ 0x00, 0x00, 0x00, 0x00, /* time stamp*/ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+}; -+ -+static u8 rtcp_head[] = { -+ /* SR off 42:8 len 28*/ -+ 0x80, 0xc8, /* SR type */ -+ 0x00, 0x06, /* len */ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* NTP */ -+ 0x73, 0x64, 0x00, 0x00, /* RTP TS */ -+ 0x00, 0x00, 0x00, 0x00, /* packet count */ -+ 0x00, 0x00, 0x00, 0x00, /* octet count */ -+ /* SDES off 70:36 len 20 */ -+ 0x81, 0xca, /* SDES */ -+ 0x00, 0x03, /* len */ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+ 0x01, 0x05, /* CNAME item */ -+ 0x53, 0x41, 0x54, 0x49, 0x50, /* "SATIP" */ -+ 0x00, /* item type 0 */ -+ /* APP off 86:52 len 16+string length */ -+ 0x80, 0xcc, /* APP */ -+ 0x00, 0x04, /* len */ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+ 0x53, 0x45, 0x53, 0x31, /* "SES1" */ -+ 0x00, 0x00, /* identifier */ -+ 0x00, 0x00, /* string length */ -+ /* string off 102:68 */ -+}; -+ -+static int ns_set_rtcp_msg(struct dvbnss *nss, u8 *msg, u32 len) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ u32 off = STREAM_PACKET_ADR(dns->nr); -+ u32 coff = 96; -+ u16 wlen; -+ -+ if (!len) { -+ ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) & -+ ~0x10, -+ STREAM_CONTROL(dns->nr)); -+ return 0; -+ } -+ if (copy_from_user(dns->p + coff + dns->rtcp_len, msg, len)) -+ return -EFAULT; -+ dns->p[coff + dns->rtcp_len - 2] = (len >> 8); -+ dns->p[coff + dns->rtcp_len - 1] = (len & 0xff); -+ if (len & 3) { -+ u32 pad = 4 - (len & 3); -+ -+ memset(dns->p + coff + dns->rtcp_len + len, 0, pad); -+ len += pad; -+ } -+ wlen = len / 4; -+ wlen += 3; -+ dns->p[coff + dns->rtcp_len - 14] = (wlen >> 8); -+ dns->p[coff + dns->rtcp_len - 13] = (wlen & 0xff); -+ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); -+ ddbwritel(dev, (dns->rtcp_udplen + len) | -+ ((STREAM_PACKET_OFF(dns->nr) + coff) << 16), -+ STREAM_RTCP_PACKET(dns->nr)); -+ ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) | 0x10, -+ STREAM_CONTROL(dns->nr)); -+ return 0; -+} -+ -+static u32 set_nsbuf(struct dvb_ns_params *p, u8 *buf, -+ u32 *udplen, int rtcp, int vlan) -+{ -+ u32 c = 0; -+ u16 pcs; -+ u16 sport, dport; -+ -+ sport = rtcp ? p->sport2 : p->sport; -+ dport = rtcp ? p->dport2 : p->dport; -+ -+ /* MAC header */ -+ memcpy(buf + c, p->dmac, 6); -+ memcpy(buf + c + 6, p->smac, 6); -+ c += 12; -+ if (vlan) { -+ buf[c + 0] = 0x81; -+ buf[c + 1] = 0x00; -+ buf[c + 2] = ((p->qos & 7) << 5) | ((p->vlan & 0xf00) >> 8); -+ buf[c + 3] = p->vlan & 0xff; -+ c += 4; -+ } -+ buf[c + 0] = 0x08; -+ buf[c + 1] = 0x00; -+ c += 2; -+ -+ /* IP header */ -+ if (p->flags & DVB_NS_IPV6) { -+ u8 ip6head[8] = { 0x65, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x11, 0x00, }; -+ memcpy(buf + c, ip6head, sizeof(ip6head)); -+ buf[c + 7] = p->ttl; -+ memcpy(buf + c + 8, p->sip, 16); -+ memcpy(buf + c + 24, p->dip, 16); -+ c += 40; -+ -+ /* UDP */ -+ buf[c + 0] = sport >> 8; -+ buf[c + 1] = sport & 0xff; -+ buf[c + 2] = dport >> 8; -+ buf[c + 3] = dport & 0xff; -+ buf[c + 4] = 0; /* length */ -+ buf[c + 5] = 0; -+ pcs = calc_pcs16(p, p->flags & DVB_NS_IPV6); -+ buf[c + 6] = pcs >> 8; -+ buf[c + 7] = pcs & 0xff; -+ c += 8; -+ *udplen = 8; -+ -+ } else { -+ u8 ip4head[12] = { 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x40, 0x00, 0x40, 0x11, 0x00, 0x00 }; -+ -+ memcpy(buf + c, ip4head, sizeof(ip4head)); -+ buf[c + 8] = p->ttl; -+ memcpy(buf + c + 12, p->sip, 4); -+ memcpy(buf + c + 16, p->dip, 4); -+ c += 20; -+ -+ /* UDP */ -+ buf[c + 0] = sport >> 8; -+ buf[c + 1] = sport & 0xff; -+ buf[c + 2] = dport >> 8; -+ buf[c + 3] = dport & 0xff; -+ buf[c + 4] = 0; /* length */ -+ buf[c + 5] = 0; -+ pcs = calc_pcs(p); -+ buf[c + 6] = pcs >> 8; -+ buf[c + 7] = pcs & 0xff; -+ c += 8; -+ *udplen = 8; -+ } -+ -+ if (rtcp) { -+ memcpy(buf + c, rtcp_head, sizeof(rtcp_head)); -+ memcpy(buf + c + 4, p->ssrc, 4); -+ memcpy(buf + c + 32, p->ssrc, 4); -+ memcpy(buf + c + 48, p->ssrc, 4); -+ c += sizeof(rtcp_head); -+ *udplen += sizeof(rtcp_head); -+ } else if (p->flags & DVB_NS_RTP) { -+ memcpy(buf + c, rtp_head, sizeof(rtp_head)); -+ memcpy(buf + c + 8, p->ssrc, 4); -+ c += sizeof(rtp_head); -+ *udplen += sizeof(rtp_head); -+ } -+ return c; -+} -+ -+static int ns_set_ts_packets(struct dvbnss *nss, u8 *buf, u32 len) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ u32 off = STREAM_PACKET_ADR(dns->nr); -+ -+ if (nss->params.flags & DVB_NS_RTCP) -+ return -EINVAL; -+ -+ if (copy_from_user(dns->p + dns->ts_offset, buf, len)) -+ return -EFAULT; -+ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); -+ return 0; -+} -+ -+static int ns_insert_ts_packets(struct dvbnss *nss, u8 count) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ u32 value = count; -+ -+ if (nss->params.flags & DVB_NS_RTCP) -+ return -EINVAL; -+ -+ if (count < 1 || count > 2) -+ return -EINVAL; -+ -+ ddbwritel(dev, value, STREAM_INSERT_PACKET(dns->nr)); -+ return 0; -+} -+ -+static int ns_set_net(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct dvb_ns_params *p = &nss->params; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ u32 off = STREAM_PACKET_ADR(dns->nr); -+ u32 coff = 96; -+ -+ dns->ts_offset = set_nsbuf(p, dns->p, &dns->udplen, 0, dev->vlan); -+ if (nss->params.flags & DVB_NS_RTCP) -+ dns->rtcp_len = set_nsbuf(p, dns->p + coff, -+ &dns->rtcp_udplen, 1, dev->vlan); -+ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); -+ ddbwritel(dev, dns->udplen | (STREAM_PACKET_OFF(dns->nr) << 16), -+ STREAM_RTP_PACKET(dns->nr)); -+ ddbwritel(dev, dns->rtcp_udplen | -+ ((STREAM_PACKET_OFF(dns->nr) + coff) << 16), -+ STREAM_RTCP_PACKET(dns->nr)); -+ return 0; -+} -+ -+static int ns_start(struct dvbnss *nss) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ u32 reg = 0x8003; -+ -+ if (nss->params.flags & DVB_NS_RTCP) -+ reg |= 0x10; -+ if (nss->params.flags & DVB_NS_RTP_TO) -+ reg |= 0x20; -+ if (nss->params.flags & DVB_NS_RTP) -+ reg |= 0x40; -+ if (nss->params.flags & DVB_NS_IPV6) -+ reg |= 0x80; -+ if (dns->fe != input) -+ ddb_dvb_ns_input_start(dns->fe); -+ ddb_dvb_ns_input_start(input); -+ pr_info("ns start ns %u, fe %u link %u\n", -+ dns->nr, dns->fe->nr, dns->fe->port->lnr); -+ ddbwritel(dev, reg | (dns->fe->nr << 8) | (dns->fe->port->lnr << 16), -+ STREAM_CONTROL(dns->nr)); -+ return 0; -+} -+ -+static int ns_stop(struct dvbnss *nss) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ -+ ddbwritel(dev, 0x00, STREAM_CONTROL(dns->nr)); -+ ddb_dvb_ns_input_stop(input); -+ if (dns->fe != input) -+ ddb_dvb_ns_input_stop(dns->fe); -+ return 0; -+} -+ -+static int netstream_init(struct ddb_input *input) -+{ -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_adapter *adap = dvb->adap; -+ struct dvb_netstream *ns = &dvb->dvbns; -+ struct ddb *dev = input->port->dev; -+ int i, res; -+ -+ ddbmemset(dev, STREAM_PIDS(input->nr), 0x00, 0x400); -+ for (i = 0; i < dev->ns_num; i++) -+ dev->ns[i].nr = i; -+ ns->priv = input; -+ ns->set_net = ns_set_net; -+ ns->set_rtcp_msg = ns_set_rtcp_msg; -+ ns->set_ts_packets = ns_set_ts_packets; -+ ns->insert_ts_packets = ns_insert_ts_packets; -+ ns->set_pid = ns_set_pid; -+ ns->set_pids = ns_set_pids; -+ ns->set_ci = ns_set_ci; -+ ns->start = ns_start; -+ ns->stop = ns_stop; -+ ns->alloc = ns_alloc; -+ ns->free = ns_free; -+ res = dvb_netstream_init(adap, ns); -+ return res; -+} -diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h -index a3ccb31..596f322 100644 ---- a/drivers/media/pci/ddbridge/ddbridge-regs.h -+++ b/drivers/media/pci/ddbridge/ddbridge-regs.h -@@ -1,7 +1,7 @@ - /* - * ddbridge-regs.h: Digital Devices PCIe bridge driver - * -- * Copyright (C) 2010-2011 Digital Devices GmbH -+ * Copyright (C) 2010-2015 Digital Devices GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -21,11 +21,11 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - --/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */ -- - /* Register Definitions */ - --#define CUR_REGISTERMAP_VERSION 0x10000 -+#define CUR_REGISTERMAP_VERSION 0x10003 -+#define CUR_REGISTERMAP_VERSION_CI 0x10000 -+#define CUR_REGISTERMAP_VERSION_MOD 0x10000 - - #define HARDWARE_VERSION 0x00 - #define REGISTERMAP_VERSION 0x04 -@@ -37,10 +37,30 @@ - #define SPI_DATA 0x14 - - /* ------------------------------------------------------------------------- */ -+/* GPIO */ -+ -+#define GPIO_OUTPUT 0x20 -+#define GPIO_INPUT 0x24 -+#define GPIO_DIRECTION 0x28 -+ -+/* ------------------------------------------------------------------------- */ -+/* MDIO */ -+ -+#define MDIO_CTRL 0x20 -+#define MDIO_ADR 0x24 -+#define MDIO_REG 0x28 -+#define MDIO_VAL 0x2C -+ -+/* ------------------------------------------------------------------------- */ -+ -+#define BOARD_CONTROL 0x30 -+ -+/* ------------------------------------------------------------------------- */ - --/* Interrupt controller */ --/* How many MSI's are available depends on HW (Min 2 max 8) */ --/* How many are usable also depends on Host platform */ -+/* Interrupt controller -+ * How many MSI's are available depends on HW (Min 2 max 8) -+ * How many are usable also depends on Host platform -+ */ - - #define INTERRUPT_BASE (0x40) - -@@ -57,6 +77,9 @@ - #define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20) - #define INTERRUPT_ACK (INTERRUPT_BASE + 0x20) - -+#define INTMASK_CLOCKGEN (0x00000001) -+#define INTMASK_TEMPMON (0x00000002) -+ - #define INTMASK_I2C1 (0x00000001) - #define INTMASK_I2C2 (0x00000002) - #define INTMASK_I2C3 (0x00000004) -@@ -81,6 +104,35 @@ - #define INTMASK_TSOUTPUT3 (0x00040000) - #define INTMASK_TSOUTPUT4 (0x00080000) - -+ -+ -+/* Modulator registers */ -+ -+/* Clock Generator ( Sil598 @ 0xAA I2c ) */ -+#define CLOCKGEN_BASE (0x80) -+#define CLOCKGEN_CONTROL (CLOCKGEN_BASE + 0x00) -+#define CLOCKGEN_INDEX (CLOCKGEN_BASE + 0x04) -+#define CLOCKGEN_WRITEDATA (CLOCKGEN_BASE + 0x08) -+#define CLOCKGEN_READDATA (CLOCKGEN_BASE + 0x0C) -+ -+/* DAC ( AD9781/AD9783 SPI ) */ -+#define DAC_BASE (0x090) -+#define DAC_CONTROL (DAC_BASE) -+#define DAC_WRITE_DATA (DAC_BASE+4) -+#define DAC_READ_DATA (DAC_BASE+8) -+ -+#define DAC_CONTROL_INSTRUCTION_REG (0xFF) -+#define DAC_CONTROL_STARTIO (0x100) -+#define DAC_CONTROL_RESET (0x200) -+ -+/* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */ -+#define TEMPMON_BASE (0xA0) -+#define TEMPMON_CONTROL (TEMPMON_BASE + 0x00) -+/* SHORT Temperature in °C x 256 */ -+#define TEMPMON_CORE (TEMPMON_BASE + 0x04) -+#define TEMPMON_SENSOR1 (TEMPMON_BASE + 0x08) -+#define TEMPMON_SENSOR2 (TEMPMON_BASE + 0x0C) -+ - /* ------------------------------------------------------------------------- */ - /* I2C Master Controller */ - -@@ -90,19 +142,10 @@ - #define I2C_TIMING (0x04) - #define I2C_TASKLENGTH (0x08) /* High read, low write */ - #define I2C_TASKADDRESS (0x0C) /* High read, low write */ -- - #define I2C_MONITOR (0x1C) - --#define I2C_BASE_1 (I2C_BASE + 0x00) --#define I2C_BASE_2 (I2C_BASE + 0x20) --#define I2C_BASE_3 (I2C_BASE + 0x40) --#define I2C_BASE_4 (I2C_BASE + 0x60) -- --#define I2C_BASE_N(i) (I2C_BASE + (i) * 0x20) -- --#define I2C_TASKMEM_BASE (0x1000) /* Byte offset */ --#define I2C_TASKMEM_SIZE (0x1000) - -+#define I2C_SPEED_666 (0x02010202) - #define I2C_SPEED_400 (0x04030404) - #define I2C_SPEED_200 (0x09080909) - #define I2C_SPEED_154 (0x0C0B0C0C) -@@ -117,35 +160,273 @@ - #define DMA_BASE_WRITE (0x100) - #define DMA_BASE_READ (0x140) - --#define DMA_CONTROL (0x00) /* 64 */ --#define DMA_ERROR (0x04) /* 65 ( only read instance ) */ -- --#define DMA_DIAG_CONTROL (0x1C) /* 71 */ --#define DMA_DIAG_PACKETCOUNTER_LOW (0x20) /* 72 */ --#define DMA_DIAG_PACKETCOUNTER_HIGH (0x24) /* 73 */ --#define DMA_DIAG_TIMECOUNTER_LOW (0x28) /* 74 */ --#define DMA_DIAG_TIMECOUNTER_HIGH (0x2C) /* 75 */ --#define DMA_DIAG_RECHECKCOUNTER (0x30) /* 76 ( Split completions on read ) */ --#define DMA_DIAG_WAITTIMEOUTINIT (0x34) /* 77 */ --#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38) /* 78 */ --#define DMA_DIAG_WAITCOUNTER (0x3C) /* 79 */ -+#define DMA_CONTROL (0x00) -+#define DMA_ERROR (0x04) - --/* ------------------------------------------------------------------------- */ --/* DMA Buffer */ -+#define DMA_DIAG_CONTROL (0x1C) -+#define DMA_DIAG_PACKETCOUNTER_LOW (0x20) -+#define DMA_DIAG_PACKETCOUNTER_HIGH (0x24) -+#define DMA_DIAG_TIMECOUNTER_LOW (0x28) -+#define DMA_DIAG_TIMECOUNTER_HIGH (0x2C) -+#define DMA_DIAG_RECHECKCOUNTER (0x30) -+#define DMA_DIAG_WAITTIMEOUTINIT (0x34) -+#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38) -+#define DMA_DIAG_WAITCOUNTER (0x3C) - - #define TS_INPUT_BASE (0x200) --#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 16 + 0x00) -+#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 0x10 + 0x00) -+#define TS_INPUT_CONTROL2(i) (TS_INPUT_BASE + (i) * 0x10 + 0x04) - - #define TS_OUTPUT_BASE (0x280) --#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 16 + 0x00) -+#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x00) -+#define TS_OUTPUT_CONTROL2(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x04) -+ -+/* ------------------------------------------------------------------------- */ -+/* DMA Buffer */ - - #define DMA_BUFFER_BASE (0x300) - --#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 16 + 0x00) --#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 16 + 0x04) --#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 16 + 0x08) --#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 16 + 0x0c) -+#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x00) -+#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x04) -+#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x08) -+#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c) - - #define DMA_BASE_ADDRESS_TABLE (0x2000) - #define DMA_BASE_ADDRESS_TABLE_ENTRIES (512) - -+ -+/* ------------------------------------------------------------------------- */ -+ -+#define LNB_BASE (0x400) -+#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00) -+#define LNB_CMD (7ULL << 0) -+#define LNB_CMD_NOP 0 -+#define LNB_CMD_INIT 1 -+#define LNB_CMD_STATUS 2 -+#define LNB_CMD_LOW 3 -+#define LNB_CMD_HIGH 4 -+#define LNB_CMD_OFF 5 -+#define LNB_CMD_DISEQC 6 -+#define LNB_CMD_UNI 7 -+ -+#define LNB_BUSY (1ULL << 4) -+#define LNB_TONE (1ULL << 15) -+ -+#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04) -+#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08) -+#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c) -+#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10) -+#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14) -+ -+/* ------------------------------------------------------------------------- */ -+/* CI Interface (only CI-Bridge) */ -+ -+#define CI_BASE (0x400) -+#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) -+ -+#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) -+#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) -+#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) -+#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) -+ -+#define CI_RESET_CAM (0x00000001) -+#define CI_POWER_ON (0x00000002) -+#define CI_ENABLE (0x00000004) -+#define CI_BLOCKIO_ENABLE (0x00000008) -+#define CI_BYPASS_DISABLE (0x00000010) -+#define CI_DISABLE_AUTO_OFF (0x00000020) -+ -+#define CI_CAM_READY (0x00010000) -+#define CI_CAM_DETECT (0x00020000) -+#define CI_READY (0x80000000) -+#define CI_BLOCKIO_ACTIVE (0x40000000) -+#define CI_BLOCKIO_RCVDATA (0x20000000) -+#define CI_BLOCKIO_SEND_PENDING (0x10000000) -+#define CI_BLOCKIO_SEND_COMPLETE (0x08000000) -+ -+#define CI_READ_CMD (0x40000000) -+#define CI_WRITE_CMD (0x80000000) -+ -+#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14) -+#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18) -+ -+#define CI_BLOCKIO_SEND_COMMAND (0x80000000) -+#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000) -+#define CI_BLOCKIO_RCVDATA_ACK (0x40000000) -+ -+#define CI_BUFFER_BASE (0x3000) -+#define CI_BUFFER_SIZE (0x0800) -+#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE/2) -+ -+#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) -+#define CI_BLOCKIO_RECEIVE_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) -+#define CI_BLOCKIO_SEND_BUFFER(i) \ -+ (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE) -+ -+#define VCO1_BASE (0xC0) -+#define VCO1_CONTROL (VCO1_BASE + 0x00) -+#define VCO1_DATA (VCO1_BASE + 0x04) /* 24 Bit */ -+/* 1 = Trigger write, resets when done */ -+#define VCO1_CONTROL_WRITE (0x00000001) -+/* 0 = Put VCO into power down */ -+#define VCO1_CONTROL_CE (0x00000002) -+/* Muxout from VCO (usually = Lock) */ -+#define VCO1_CONTROL_MUXOUT (0x00000004) -+ -+#define VCO2_BASE (0xC8) -+#define VCO2_CONTROL (VCO2_BASE + 0x00) -+#define VCO2_DATA (VCO2_BASE + 0x04) /* 24 Bit */ -+/* 1 = Trigger write, resets when done */ -+#define VCO2_CONTROL_WRITE (0x00000001) -+/* 0 = Put VCO into power down */ -+#define VCO2_CONTROL_CE (0x00000002) -+/* Muxout from VCO (usually = Lock) */ -+#define VCO2_CONTROL_MUXOUT (0x00000004) -+ -+#define VCO3_BASE (0xD0) -+#define VCO3_CONTROL (VCO3_BASE + 0x00) -+#define VCO3_DATA (VCO3_BASE + 0x04) /* 32 Bit */ -+/* 1 = Trigger write, resets when done */ -+#define VCO3_CONTROL_WRITE (0x00000001) -+/* 0 = Put VCO into power down */ -+#define VCO3_CONTROL_CE (0x00000002) -+/* Muxout from VCO (usually = Lock) */ -+#define VCO3_CONTROL_MUXOUT (0x00000004) -+ -+#define RF_ATTENUATOR (0xD8) -+/* 0x00 = 0 dB -+ * 0x01 = 1 dB -+ * ... -+ * 0x1F = 31 dB -+ */ -+ -+#define RF_POWER (0xE0) -+#define RF_POWER_BASE (0xE0) -+#define RF_POWER_CONTROL (RF_POWER_BASE + 0x00) -+#define RF_POWER_DATA (RF_POWER_BASE + 0x04) -+ -+#define RF_POWER_CONTROL_START (0x00000001) -+#define RF_POWER_CONTROL_DONE (0x00000002) -+#define RF_POWER_CONTROL_VALIDMASK (0x00000700) -+#define RF_POWER_CONTROL_VALID (0x00000500) -+ -+ -+/* -------------------------------------------------------------------------- -+ * Output control -+ */ -+ -+#define IQOUTPUT_BASE (0x240) -+#define IQOUTPUT_CONTROL (IQOUTPUT_BASE + 0x00) -+#define IQOUTPUT_CONTROL2 (IQOUTPUT_BASE + 0x04) -+#define IQOUTPUT_PEAK_DETECTOR (IQOUTPUT_BASE + 0x08) -+#define IQOUTPUT_POSTSCALER (IQOUTPUT_BASE + 0x0C) -+#define IQOUTPUT_PRESCALER (IQOUTPUT_BASE + 0x10) -+ -+#define IQOUTPUT_EQUALIZER_0 (IQOUTPUT_BASE + 0x14) -+#define IQOUTPUT_EQUALIZER_1 (IQOUTPUT_BASE + 0x18) -+#define IQOUTPUT_EQUALIZER_2 (IQOUTPUT_BASE + 0x1C) -+#define IQOUTPUT_EQUALIZER_3 (IQOUTPUT_BASE + 0x20) -+#define IQOUTPUT_EQUALIZER_4 (IQOUTPUT_BASE + 0x24) -+#define IQOUTPUT_EQUALIZER_5 (IQOUTPUT_BASE + 0x28) -+#define IQOUTPUT_EQUALIZER_6 (IQOUTPUT_BASE + 0x2C) -+#define IQOUTPUT_EQUALIZER_7 (IQOUTPUT_BASE + 0x30) -+#define IQOUTPUT_EQUALIZER_8 (IQOUTPUT_BASE + 0x34) -+#define IQOUTPUT_EQUALIZER_9 (IQOUTPUT_BASE + 0x38) -+#define IQOUTPUT_EQUALIZER_10 (IQOUTPUT_BASE + 0x3C) -+ -+#define IQOUTPUT_EQUALIZER(i) (IQOUTPUT_EQUALIZER_0 + (i) * 4) -+ -+#define IQOUTPUT_CONTROL_RESET (0x00000001) -+#define IQOUTPUT_CONTROL_ENABLE (0x00000002) -+#define IQOUTPUT_CONTROL_RESET_PEAK (0x00000004) -+#define IQOUTPUT_CONTROL_ENABLE_PEAK (0x00000008) -+#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER (0x00000010) -+ -+ -+/* Modulator Base */ -+ -+#define MODULATOR_BASE (0x200) -+#define MODULATOR_CONTROL (MODULATOR_BASE) -+#define MODULATOR_IQTABLE_END (MODULATOR_BASE+4) -+#define MODULATOR_IQTABLE_INDEX (MODULATOR_BASE+8) -+#define MODULATOR_IQTABLE_DATA (MODULATOR_BASE+12) -+ -+#define MODULATOR_IQTABLE_INDEX_CHANNEL_MASK (0x000F0000) -+#define MODULATOR_IQTABLE_INDEX_IQ_MASK (0x00008000) -+#define MODULATOR_IQTABLE_INDEX_ADDRESS_MASK (0x000007FF) -+#define MODULATOR_IQTABLE_INDEX_SEL_I (0x00000000) -+#define MODULATOR_IQTABLE_INDEX_SEL_Q (MODULATOR_IQTABLE_INDEX_IQ_MASK) -+#define MODULATOR_IQTABLE_SIZE (2048) -+ -+ -+/* Modulator Channels */ -+ -+#define CHANNEL_BASE (0x400) -+#define CHANNEL_CONTROL(i) (CHANNEL_BASE + (i) * 64 + 0x00) -+#define CHANNEL_SETTINGS(i) (CHANNEL_BASE + (i) * 64 + 0x04) -+#define CHANNEL_RATE_INCR(i) (CHANNEL_BASE + (i) * 64 + 0x0C) -+#define CHANNEL_PCR_ADJUST_OUTL(i) (CHANNEL_BASE + (i) * 64 + 0x10) -+#define CHANNEL_PCR_ADJUST_OUTH(i) (CHANNEL_BASE + (i) * 64 + 0x14) -+#define CHANNEL_PCR_ADJUST_INL(i) (CHANNEL_BASE + (i) * 64 + 0x18) -+#define CHANNEL_PCR_ADJUST_INH(i) (CHANNEL_BASE + (i) * 64 + 0x1C) -+#define CHANNEL_PCR_ADJUST_ACCUL(i) (CHANNEL_BASE + (i) * 64 + 0x20) -+#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24) -+#define CHANNEL_PKT_COUNT_OUT(i) (CHANNEL_BASE + (i) * 64 + 0x28) -+#define CHANNEL_PKT_COUNT_IN(i) (CHANNEL_BASE + (i) * 64 + 0x2C) -+ -+#define CHANNEL_CONTROL_RESET (0x00000001) -+#define CHANNEL_CONTROL_ENABLE_DVB (0x00000002) -+#define CHANNEL_CONTROL_ENABLE_IQ (0x00000004) -+#define CHANNEL_CONTROL_ENABLE_SOURCE (0x00000008) -+#define CHANNEL_CONTROL_ENABLE_PCRADJUST (0x00000010) -+#define CHANNEL_CONTROL_FREEZE_STATUS (0x00000100) -+ -+#define CHANNEL_CONTROL_RESET_ERROR (0x00010000) -+#define CHANNEL_CONTROL_BUSY (0x01000000) -+#define CHANNEL_CONTROL_ERROR_SYNC (0x20000000) -+#define CHANNEL_CONTROL_ERROR_UNDERRUN (0x40000000) -+#define CHANNEL_CONTROL_ERROR_FATAL (0x80000000) -+ -+#define CHANNEL_SETTINGS_QAM_MASK (0x00000007) -+#define CHANNEL_SETTINGS_QAM16 (0x00000000) -+#define CHANNEL_SETTINGS_QAM32 (0x00000001) -+#define CHANNEL_SETTINGS_QAM64 (0x00000002) -+#define CHANNEL_SETTINGS_QAM128 (0x00000003) -+#define CHANNEL_SETTINGS_QAM256 (0x00000004) -+ -+ -+/* OCTONET */ -+ -+#define ETHER_BASE (0x100) -+#define ETHER_CONTROL (ETHER_BASE + 0x00) -+#define ETHER_LENGTH (ETHER_BASE + 0x04) -+ -+#define RTP_MASTER_BASE (0x120) -+#define RTP_MASTER_CONTROL (RTP_MASTER_BASE + 0x00) -+#define RTP_RTCP_INTERRUPT (RTP_MASTER_BASE + 0x04) -+#define RTP_MASTER_RTCP_SETTINGS (RTP_MASTER_BASE + 0x0c) -+ -+#define STREAM_BASE (0x400) -+#define STREAM_CONTROL(i) (STREAM_BASE + (i) * 0x20 + 0x00) -+#define STREAM_RTP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x04) -+#define STREAM_RTCP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x08) -+#define STREAM_RTP_SETTINGS(i) (STREAM_BASE + (i) * 0x20 + 0x0c) -+#define STREAM_INSERT_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x10) -+ -+#define STREAM_PACKET_OFF(i) ((i) * 0x200) -+#define STREAM_PACKET_ADR(i) (0x2000 + (STREAM_PACKET_OFF(i))) -+ -+#define STREAM_PIDS(i) (0x4000 + (i) * 0x400) -+ -+#define TS_CAPTURE_BASE (0x0140) -+#define TS_CAPTURE_CONTROL (TS_CAPTURE_BASE + 0x00) -+#define TS_CAPTURE_PID (TS_CAPTURE_BASE + 0x04) -+#define TS_CAPTURE_RECEIVED (TS_CAPTURE_BASE + 0x08) -+#define TS_CAPTURE_TIMEOUT (TS_CAPTURE_BASE + 0x0c) -+#define TS_CAPTURE_TABLESECTION (TS_CAPTURE_BASE + 0x10) -+ -+#define TS_CAPTURE_MEMORY (0x7000) -+ -+#define PID_FILTER_BASE (0x800) -+#define PID_FILTER_SYSTEM_PIDS(i) (PID_FILTER_BASE + (i) * 0x20) -+#define PID_FILTER_PID(i, j) (PID_FILTER_BASE + (i) * 0x20 + (j) * 4) -diff --git a/drivers/media/pci/ddbridge/ddbridge.c b/drivers/media/pci/ddbridge/ddbridge.c -new file mode 100644 -index 0000000..b9d93f2 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge.c -@@ -0,0 +1,541 @@ -+/* -+ * ddbridge.c: Digital Devices PCIe bridge driver -+ * -+ * Copyright (C) 2010-2015 Digital Devices GmbH -+ * Ralph Metzler -+ * Marcus Metzler -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*#define DDB_ALT_DMA*/ -+#define DDB_USE_WORK -+/*#define DDB_TEST_THREADED*/ -+ -+#include "ddbridge.h" -+#include "ddbridge-regs.h" -+ -+static struct workqueue_struct *ddb_wq; -+ -+static int adapter_alloc; -+module_param(adapter_alloc, int, 0444); -+MODULE_PARM_DESC(adapter_alloc, -+ "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); -+ -+#ifdef CONFIG_PCI_MSI -+#define DDB_USE_MSI_IRQHANDLERS -+#ifdef CONFIG_DVB_DDBRIDGE_MSIENABLE -+static int msi = 1; -+#else -+static int msi = 0; -+#endif -+module_param(msi, int, 0444); -+MODULE_PARM_DESC(msi, -+#ifdef CONFIG_DVB_DDBRIDGE_MSIENABLE -+ " Control MSI interrupts: 0-disable, 1-enable (default)"); -+#else -+ " Control MSI interrupts: 0-disable (default), 1-enable"); -+#endif -+#endif -+ -+#include "ddbridge-core.c" -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static void ddb_unmap(struct ddb *dev) -+{ -+ if (dev->regs) -+ iounmap(dev->regs); -+ vfree(dev); -+} -+ -+ -+static void ddb_remove(struct pci_dev *pdev) -+{ -+ struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev); -+ -+ ddb_device_destroy(dev); -+ ddb_nsd_detach(dev); -+ ddb_ports_detach(dev); -+ ddb_i2c_release(dev); -+ -+ if (dev->link[0].info->ns_num) -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ -+ ddbwritel(dev, 0, MSI1_ENABLE); -+ if (dev->msi == 2) -+ free_irq(dev->pdev->irq + 1, dev); -+ free_irq(dev->pdev->irq, dev); -+#ifdef CONFIG_PCI_MSI -+ if (dev->msi) -+ pci_disable_msi(dev->pdev); -+#endif -+ ddb_ports_release(dev); -+ ddb_buffers_free(dev); -+ -+ ddb_unmap(dev); -+ pci_set_drvdata(pdev, NULL); -+ pci_disable_device(pdev); -+} -+ -+static int ddb_probe(struct pci_dev *pdev, -+ const struct pci_device_id *id) -+{ -+ struct ddb *dev; -+ int stat = 0; -+ int irq_flag = IRQF_SHARED; -+ -+ if (pci_enable_device(pdev) < 0) -+ return -ENODEV; -+ -+ dev = vzalloc(sizeof(struct ddb)); -+ if (dev == NULL) -+ return -ENOMEM; -+ -+ mutex_init(&dev->mutex); -+ dev->has_dma = 1; -+ dev->pdev = pdev; -+ dev->dev = &pdev->dev; -+ pci_set_drvdata(pdev, dev); -+ -+ dev->link[0].ids.vendor = id->vendor; -+ dev->link[0].ids.device = id->device; -+ dev->link[0].ids.subvendor = id->subvendor; -+ dev->link[0].ids.subdevice = id->subdevice; -+ -+ dev->link[0].dev = dev; -+ dev->link[0].info = (struct ddb_info *) id->driver_data; -+ pr_info("DDBridge driver detected: %s\n", dev->link[0].info->name); -+ -+ dev->regs_len = pci_resource_len(dev->pdev, 0); -+ dev->regs = ioremap(pci_resource_start(dev->pdev, 0), -+ pci_resource_len(dev->pdev, 0)); -+ -+ if (!dev->regs) { -+ pr_err("DDBridge: not enough memory for register map\n"); -+ stat = -ENOMEM; -+ goto fail; -+ } -+ if (ddbreadl(dev, 0) == 0xffffffff) { -+ pr_err("DDBridge: cannot read registers\n"); -+ stat = -ENODEV; -+ goto fail; -+ } -+ -+ dev->link[0].ids.hwid = ddbreadl(dev, 0); -+ dev->link[0].ids.regmapid = ddbreadl(dev, 4); -+ -+ pr_info("DDBridge: HW %08x REGMAP %08x\n", -+ dev->link[0].ids.hwid, dev->link[0].ids.regmapid); -+ -+ if (dev->link[0].info->ns_num) { -+ int i; -+ -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ for (i = 0; i < 16; i++) -+ ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i)); -+ usleep_range(5000, 6000); -+ } -+ ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI1_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI2_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI3_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI4_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI5_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI6_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI7_ENABLE); -+ -+#ifdef CONFIG_PCI_MSI -+ if (msi && pci_msi_enabled()) { -+ stat = pci_enable_msi_range(dev->pdev, 1, 2); -+ if (stat >= 1) { -+ dev->msi = stat; -+ pr_info("DDBridge: using %d MSI interrupt(s)\n", -+ dev->msi); -+ irq_flag = 0; -+ } else -+ pr_info("DDBridge: MSI not available.\n"); -+ } -+ if (dev->msi == 2) { -+ stat = request_irq(dev->pdev->irq, irq_handler0, -+ irq_flag, "ddbridge", (void *) dev); -+ if (stat < 0) -+ goto fail0; -+ stat = request_irq(dev->pdev->irq + 1, irq_handler1, -+ irq_flag, "ddbridge", (void *) dev); -+ if (stat < 0) { -+ free_irq(dev->pdev->irq, dev); -+ goto fail0; -+ } -+ } else -+#endif -+ { -+#ifdef DDB_TEST_THREADED -+ stat = request_threaded_irq(dev->pdev->irq, irq_handler, -+ irq_thread, -+ irq_flag, -+ "ddbridge", (void *) dev); -+#else -+ stat = request_irq(dev->pdev->irq, irq_handler, -+ irq_flag, "ddbridge", (void *) dev); -+#endif -+ if (stat < 0) -+ goto fail0; -+ } -+ ddbwritel(dev, 0, DMA_BASE_READ); -+ if (dev->link[0].info->type != DDB_MOD) -+ ddbwritel(dev, 0, DMA_BASE_WRITE); -+ -+ if (dev->link[0].info->type == DDB_MOD) { -+ if (ddbreadl(dev, 0x1c) == 4) -+ dev->link[0].info->port_num = 4; -+ } -+ -+ /*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/ -+ if (dev->msi == 2) { -+ ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0x0000000f, MSI1_ENABLE); -+ } else { -+ ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI1_ENABLE); -+ } -+ if (ddb_init(dev) == 0) -+ return 0; -+ -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0, MSI1_ENABLE); -+ free_irq(dev->pdev->irq, dev); -+ if (dev->msi == 2) -+ free_irq(dev->pdev->irq + 1, dev); -+fail0: -+ pr_err("fail0\n"); -+ if (dev->msi) -+ pci_disable_msi(dev->pdev); -+fail: -+ pr_err("fail\n"); -+ -+ ddb_unmap(dev); -+ pci_set_drvdata(pdev, NULL); -+ pci_disable_device(pdev); -+ return -1; -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static struct ddb_regset octopus_i2c = { -+ .base = 0x80, -+ .num = 0x04, -+ .size = 0x20, -+}; -+ -+static struct ddb_regset octopus_i2c_buf = { -+ .base = 0x1000, -+ .num = 0x04, -+ .size = 0x200, -+}; -+ -+/****************************************************************************/ -+ -+ -+static struct ddb_regmap octopus_map = { -+ .i2c = &octopus_i2c, -+ .i2c_buf = &octopus_i2c_buf, -+}; -+ -+static struct ddb_regmap octopus_net_map = { -+ .i2c = &octopus_i2c, -+ .i2c_buf = &octopus_i2c_buf, -+}; -+ -+static struct ddb_regmap octopus_mod_map = { -+}; -+ -+ -+/****************************************************************************/ -+ -+static struct ddb_info ddb_none = { -+ .type = DDB_NONE, -+ .name = "unknown Digital Devices PCIe card, install newer driver", -+ .regmap = &octopus_map, -+}; -+ -+static struct ddb_info ddb_octopus = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+}; -+ -+static struct ddb_info ddb_octopusv3 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus V3 DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+}; -+ -+static struct ddb_info ddb_octopus_le = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus LE DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 2, -+ .i2c_mask = 0x03, -+}; -+ -+static struct ddb_info ddb_octopus_oem = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus OEM", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+ .led_num = 1, -+ .fan_num = 1, -+ .temp_num = 1, -+ .temp_bus = 0, -+}; -+ -+static struct ddb_info ddb_octopus_mini = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus Mini", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+}; -+ -+static struct ddb_info ddb_v6 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine S2 V6 DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 3, -+ .i2c_mask = 0x07, -+}; -+ -+static struct ddb_info ddb_v6_5 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine S2 V6.5 DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+}; -+ -+static struct ddb_info ddb_v7 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine S2 V7 DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+ .board_control = 2, -+ .board_control_2 = 4, -+ .ts_quirks = TS_QUIRK_REVERSED, -+}; -+ -+static struct ddb_info ddb_ctv7 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine CT V7 DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+ .board_control = 3, -+ .board_control_2 = 4, -+}; -+ -+static struct ddb_info ddb_satixS2v3 = { -+ .type = DDB_OCTOPUS, -+ .name = "Mystique SaTiX-S2 V3 DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 3, -+ .i2c_mask = 0x07, -+}; -+ -+static struct ddb_info ddb_ci = { -+ .type = DDB_OCTOPUS_CI, -+ .name = "Digital Devices Octopus CI", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x03, -+}; -+ -+static struct ddb_info ddb_cis = { -+ .type = DDB_OCTOPUS_CI, -+ .name = "Digital Devices Octopus CI single", -+ .regmap = &octopus_map, -+ .port_num = 3, -+ .i2c_mask = 0x03, -+}; -+ -+static struct ddb_info ddb_ci_s2_pro = { -+ .type = DDB_OCTOPUS_CI, -+ .name = "Digital Devices Octopus CI S2 Pro", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x01, -+ .board_control = 2, -+ .board_control_2 = 4, -+}; -+ -+static struct ddb_info ddb_dvbct = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices DVBCT V6.1 DVB adapter", -+ .regmap = &octopus_map, -+ .port_num = 3, -+ .i2c_mask = 0x07, -+}; -+ -+/****************************************************************************/ -+ -+static struct ddb_info ddb_s2_48 = { -+ .type = DDB_OCTOPUS_MAX, -+ .name = "Digital Devices MAX S8 4/8", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x01, -+ .board_control = 1, -+}; -+ -+static struct ddb_info ddb_ct_8 = { -+ .type = DDB_OCTOPUS_MAX_CT, -+ .name = "Digital Devices MAX CT8", -+ .regmap = &octopus_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+ .board_control = 0x0ff, -+ .board_control_2 = 0xf00, -+ .ts_quirks = TS_QUIRK_SERIAL, -+}; -+ -+static struct ddb_info ddb_mod = { -+ .type = DDB_MOD, -+ .name = "Digital Devices DVB-C modulator", -+ .regmap = &octopus_mod_map, -+ .port_num = 10, -+ .temp_num = 1, -+}; -+ -+static struct ddb_info ddb_octopus_net = { -+ .type = DDB_OCTONET, -+ .name = "Digital Devices OctopusNet network DVB adapter", -+ .regmap = &octopus_net_map, -+ .port_num = 10, -+ .i2c_mask = 0x3ff, -+ .ns_num = 12, -+ .mdio_num = 1, -+}; -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+#define DDVID 0xdd01 /* Digital Devices Vendor ID */ -+ -+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ -+ .vendor = _vend, .device = _dev, \ -+ .subvendor = _subvend, .subdevice = _subdev, \ -+ .driver_data = (unsigned long)&_driverdata } -+ -+static const struct pci_device_id ddb_id_tbl[] = { -+ DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), -+ DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), -+ DDB_ID(DDVID, 0x0005, DDVID, 0x0011, ddb_octopus_mini), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0022, ddb_v7), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), -+ DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0031, ddb_ctv7), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0032, ddb_ctv7), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0033, ddb_ctv7), -+ DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48), -+ DDB_ID(DDVID, 0x0008, DDVID, 0x0034, ddb_ct_8), -+ DDB_ID(DDVID, 0x0008, DDVID, 0x0035, ddb_ct_8), -+ DDB_ID(DDVID, 0x0008, DDVID, 0x0036, ddb_ct_8), -+ DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci), -+ DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis), -+ DDB_ID(DDVID, 0x0012, DDVID, 0x0042, ddb_ci), -+ DDB_ID(DDVID, 0x0013, DDVID, 0x0043, ddb_ci_s2_pro), -+ DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod), -+ DDB_ID(DDVID, 0x0201, DDVID, 0x0002, ddb_mod), -+ DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_octopus_net), -+ /* in case sub-ids got deleted in flash */ -+ DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0005, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0006, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0007, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0008, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0013, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ {0} -+}; -+MODULE_DEVICE_TABLE(pci, ddb_id_tbl); -+ -+static struct pci_driver ddb_pci_driver = { -+ .name = "ddbridge", -+ .id_table = ddb_id_tbl, -+ .probe = ddb_probe, -+ .remove = ddb_remove, -+}; -+ -+static __init int module_init_ddbridge(void) -+{ -+ int stat = -1; -+ -+ pr_info("Digital Devices PCIE bridge driver " -+ DDBRIDGE_VERSION -+ ", Copyright (C) 2010-15 Digital Devices GmbH\n"); -+ if (ddb_class_create() < 0) -+ return -1; -+ ddb_wq = create_workqueue("ddbridge"); -+ if (ddb_wq == NULL) -+ goto exit1; -+ stat = pci_register_driver(&ddb_pci_driver); -+ if (stat < 0) -+ goto exit2; -+ return stat; -+exit2: -+ destroy_workqueue(ddb_wq); -+exit1: -+ ddb_class_destroy(); -+ return stat; -+} -+ -+static __exit void module_exit_ddbridge(void) -+{ -+ pci_unregister_driver(&ddb_pci_driver); -+ destroy_workqueue(ddb_wq); -+ ddb_class_destroy(); -+} -+ -+module_init(module_init_ddbridge); -+module_exit(module_exit_ddbridge); -+ -+MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); -+MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DDBRIDGE_VERSION); -diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h -index be87fbd..edc42de 100644 ---- a/drivers/media/pci/ddbridge/ddbridge.h -+++ b/drivers/media/pci/ddbridge/ddbridge.h -@@ -1,7 +1,8 @@ - /* - * ddbridge.h: Digital Devices PCIe bridge driver - * -- * Copyright (C) 2010-2011 Digital Devices GmbH -+ * Copyright (C) 2010-2015 Digital Devices GmbH -+ * Ralph Metzler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -24,16 +25,41 @@ - #ifndef _DDBRIDGE_H_ - #define _DDBRIDGE_H_ - -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ - #include - #include - #include --#include - #include - #include --#include -+#include -+#include -+#include -+ - #include - #include -+#include -+#include - -+#include "dvb_netstream.h" - #include "dmxdev.h" - #include "dvbdev.h" - #include "dvb_demux.h" -@@ -41,143 +67,582 @@ - #include "dvb_ringbuffer.h" - #include "dvb_ca_en50221.h" - #include "dvb_net.h" -+ -+#include "tda18271c2dd.h" -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "lnbh24.h" -+#include "drxk.h" -+#include "stv0367dd.h" -+#include "tda18212.h" -+#include "cxd2843.h" - #include "cxd2099.h" -+#include "stv0910.h" -+#include "stv6111.h" -+#include "lnbh25.h" -+#include "mxl5xx.h" -+ -+#define DDB_MAX_I2C 16 -+#define DDB_MAX_PORT 16 -+#define DDB_MAX_INPUT 44 -+#define DDB_MAX_OUTPUT 10 -+#define DDB_MAX_LINK 4 -+#define DDB_LINK_SHIFT 28 -+ -+#define DDB_LINK_TAG(_x) (_x << DDB_LINK_SHIFT) -+ -+struct ddb_regset { -+ u32 base; -+ u32 num; -+ u32 size; -+}; -+ -+struct ddb_ports { -+ u32 base; -+ u32 num; -+ u32 size; -+}; -+ -+struct ddb_regmap { -+ struct ddb_ports *bc; -+ struct ddb_regset *i2c; -+ struct ddb_regset *i2c_buf; -+ struct ddb_regset *dma; -+ struct ddb_regset *dma_buf; -+ struct ddb_regset *input; -+ struct ddb_regset *output; -+ struct ddb_regset *channel; -+ struct ddb_regset *ci; -+ struct ddb_regset *pid_filter; -+ struct ddb_regset *ns; -+ struct ddb_regset *gtl; -+}; - --#define DDB_MAX_I2C 4 --#define DDB_MAX_PORT 4 --#define DDB_MAX_INPUT 8 --#define DDB_MAX_OUTPUT 4 -+struct ddb_ids { -+ u16 vendor; -+ u16 device; -+ u16 subvendor; -+ u16 subdevice; -+ -+ u32 hwid; -+ u32 regmapid; -+ u32 devid; -+ u32 mac; -+}; - - struct ddb_info { - int type; - #define DDB_NONE 0 - #define DDB_OCTOPUS 1 -+#define DDB_OCTOPUS_CI 2 -+#define DDB_MOD 3 -+#define DDB_OCTONET 4 -+#define DDB_OCTOPUS_MAX 5 -+#define DDB_OCTOPUS_MAX_CT 6 - char *name; -- int port_num; -- u32 port_type[DDB_MAX_PORT]; -+ u32 i2c_mask; -+ u8 port_num; -+ u8 led_num; -+ u8 fan_num; -+ u8 temp_num; -+ u8 temp_bus; -+ u32 board_control; -+ u32 board_control_2; -+ u8 ns_num; -+ u8 mdio_num; -+ u8 con_clock; /* use a continuous clock */ -+ u8 ts_quirks; -+#define TS_QUIRK_SERIAL 1 -+#define TS_QUIRK_REVERSED 2 -+ struct ddb_regmap *regmap; - }; - --/* DMA_SIZE MUST be divisible by 188 and 128 !!! */ -+/* DMA_SIZE MUST be smaller than 256k and -+ * MUST be divisible by 188 and 128 !!! -+ */ -+ -+#define DMA_MAX_BUFS 32 /* hardware table limit */ - --#define INPUT_DMA_MAX_BUFS 32 /* hardware table limit */ - #define INPUT_DMA_BUFS 8 - #define INPUT_DMA_SIZE (128*47*21) -+#define INPUT_DMA_IRQ_DIV 1 - --#define OUTPUT_DMA_MAX_BUFS 32 - #define OUTPUT_DMA_BUFS 8 - #define OUTPUT_DMA_SIZE (128*47*21) -+#define OUTPUT_DMA_IRQ_DIV 1 - - struct ddb; - struct ddb_port; - --struct ddb_input { -- struct ddb_port *port; -+struct ddb_dma { -+ void *io; - u32 nr; -- int attached; -- -- dma_addr_t pbuf[INPUT_DMA_MAX_BUFS]; -- u8 *vbuf[INPUT_DMA_MAX_BUFS]; -- u32 dma_buf_num; -- u32 dma_buf_size; -+ dma_addr_t pbuf[DMA_MAX_BUFS]; -+ u8 *vbuf[DMA_MAX_BUFS]; -+ u32 num; -+ u32 size; -+ u32 div; -+ u32 bufreg; - -+#ifdef DDB_USE_WORK -+ struct work_struct work; -+#else - struct tasklet_struct tasklet; -+#endif - spinlock_t lock; - wait_queue_head_t wq; - int running; - u32 stat; -+ u32 ctrl; - u32 cbuf; - u32 coff; -+}; - -- struct dvb_adapter adap; -+struct ddb_dvb { -+ struct dvb_adapter *adap; -+ int adap_registered; - struct dvb_device *dev; -+ struct i2c_client *i2c_client[1]; - struct dvb_frontend *fe; - struct dvb_frontend *fe2; - struct dmxdev dmxdev; - struct dvb_demux demux; - struct dvb_net dvbnet; -+ struct dvb_netstream dvbns; - struct dmx_frontend hw_frontend; - struct dmx_frontend mem_frontend; - int users; -- int (*gate_ctrl)(struct dvb_frontend *, int); -+ u32 attached; -+ u8 input; -+ -+ enum fe_sec_tone_mode tone; -+ enum fe_sec_voltage voltage; -+ -+ int (*i2c_gate_ctrl)(struct dvb_frontend *, int); -+ int (*set_voltage)(struct dvb_frontend *fe, -+ enum fe_sec_voltage voltage); -+ int (*set_input)(struct dvb_frontend *fe, int input); -+ int (*diseqc_send_master_cmd)(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *cmd); - }; - --struct ddb_output { -+struct ddb_ci { -+ struct dvb_ca_en50221 en; - struct ddb_port *port; - u32 nr; -- dma_addr_t pbuf[OUTPUT_DMA_MAX_BUFS]; -- u8 *vbuf[OUTPUT_DMA_MAX_BUFS]; -- u32 dma_buf_num; -- u32 dma_buf_size; -- struct tasklet_struct tasklet; -- spinlock_t lock; -- wait_queue_head_t wq; -- int running; -- u32 stat; -- u32 cbuf; -- u32 coff; -+ struct mutex lock; -+}; - -- struct dvb_adapter adap; -- struct dvb_device *dev; -+struct ddb_io { -+ struct ddb_port *port; -+ u32 nr; -+ struct ddb_dma *dma; -+ struct ddb_io *redo; -+ struct ddb_io *redi; - }; - -+#define ddb_output ddb_io -+#define ddb_input ddb_io -+ - struct ddb_i2c { - struct ddb *dev; - u32 nr; -- struct i2c_adapter adap; -- struct i2c_adapter adap2; - u32 regs; -+ u32 link; -+ struct i2c_adapter adap; - u32 rbuf; - u32 wbuf; -- int done; -- wait_queue_head_t wq; -+ u32 bsize; -+ struct completion completion; - }; - - struct ddb_port { - struct ddb *dev; - u32 nr; -+ u32 pnr; -+ u32 regs; -+ u32 lnr; - struct ddb_i2c *i2c; - struct mutex i2c_gate_lock; - u32 class; - #define DDB_PORT_NONE 0 - #define DDB_PORT_CI 1 - #define DDB_PORT_TUNER 2 -- u32 type; --#define DDB_TUNER_NONE 0 --#define DDB_TUNER_DVBS_ST 1 --#define DDB_TUNER_DVBS_ST_AA 2 --#define DDB_TUNER_DVBCT_TR 16 --#define DDB_TUNER_DVBCT_ST 17 -- u32 adr; -+#define DDB_PORT_LOOP 3 -+#define DDB_PORT_MOD 4 -+ char *name; -+ char *type_name; -+ u32 type; -+#define DDB_TUNER_NONE 0 -+#define DDB_TUNER_DVBS_ST 1 -+#define DDB_TUNER_DVBS_ST_AA 2 -+#define DDB_TUNER_DVBCT_TR 3 -+#define DDB_TUNER_DVBCT_ST 4 -+#define DDB_CI_INTERNAL 5 -+#define DDB_CI_EXTERNAL_SONY 6 -+#define DDB_TUNER_DVBCT2_SONY_P 7 -+#define DDB_TUNER_DVBC2T2_SONY_P 8 -+#define DDB_TUNER_ISDBT_SONY_P 9 -+#define DDB_TUNER_DVBS_STV0910_P 10 -+#define DDB_TUNER_MXL5XX 11 -+#define DDB_CI_EXTERNAL_XO2 12 -+#define DDB_CI_EXTERNAL_XO2_B 13 -+#define DDB_TUNER_DVBS_STV0910_PR 14 -+ -+#define DDB_TUNER_XO2 32 -+#define DDB_TUNER_DVBS_STV0910 (DDB_TUNER_XO2 + 0) -+#define DDB_TUNER_DVBCT2_SONY (DDB_TUNER_XO2 + 1) -+#define DDB_TUNER_ISDBT_SONY (DDB_TUNER_XO2 + 2) -+#define DDB_TUNER_DVBC2T2_SONY (DDB_TUNER_XO2 + 3) -+#define DDB_TUNER_ATSC_ST (DDB_TUNER_XO2 + 4) -+#define DDB_TUNER_DVBC2T2_ST (DDB_TUNER_XO2 + 5) - - struct ddb_input *input[2]; - struct ddb_output *output; - struct dvb_ca_en50221 *en; -+ struct ddb_dvb dvb[2]; -+ u32 gap; -+ u32 obr; -+ u8 creg; -+}; -+ -+struct mod_base { -+ u32 frequency; -+ u32 flat_start; -+ u32 flat_end; -+}; -+ -+struct mod_state { -+ u32 modulation; -+ u64 obitrate; -+ u64 ibitrate; -+ u32 pcr_correction; -+ -+ u32 rate_inc; -+ u32 Control; -+ u32 State; -+ u32 StateCounter; -+ s32 LastPCRAdjust; -+ s32 PCRAdjustSum; -+ s32 InPacketsSum; -+ s32 OutPacketsSum; -+ s64 PCRIncrement; -+ s64 PCRDecrement; -+ s32 PCRRunningCorr; -+ u32 OutOverflowPacketCount; -+ u32 InOverflowPacketCount; -+ u32 LastOutPacketCount; -+ u32 LastInPacketCount; -+ u64 LastOutPackets; -+ u64 LastInPackets; -+ u32 MinInputPackets; -+}; -+ -+#define CM_STARTUP_DELAY 2 -+#define CM_AVERAGE 20 -+#define CM_GAIN 10 -+ -+#define HW_LSB_SHIFT 12 -+#define HW_LSB_MASK 0x1000 -+ -+#define CM_IDLE 0 -+#define CM_STARTUP 1 -+#define CM_ADJUST 2 -+ -+#define TS_CAPTURE_LEN (4096) -+ -+/* net streaming hardware block */ -+ -+#define DDB_NS_MAX 15 -+ -+struct ddb_ns { -+ struct ddb_input *input; -+ int nr; -+ struct ddb_input *fe; -+ u32 rtcp_udplen; -+ u32 rtcp_len; -+ u32 ts_offset; -+ u32 udplen; -+ u8 p[512]; -+}; -+ -+struct ddb_lnb { -+ struct mutex lock; -+ u32 tone; -+ enum fe_sec_voltage oldvoltage[4]; -+ u32 voltage[4]; -+ u32 voltages; -+ u32 fmode; -+}; -+ -+struct ddb_link { -+ struct ddb *dev; -+ struct ddb_info *info; -+ u32 nr; -+ u32 regs; -+ spinlock_t lock; -+ struct mutex flash_mutex; -+ struct ddb_lnb lnb; -+ struct tasklet_struct tasklet; -+ struct ddb_ids ids; - }; - - struct ddb { - struct pci_dev *pdev; -- unsigned char __iomem *regs; -+ struct platform_device *pfdev; -+ struct device *dev; -+ -+ int msi; -+ struct workqueue_struct *wq; -+ u32 has_dma; -+ u32 has_ns; -+ struct ddb_link link[DDB_MAX_LINK]; -+ unsigned char *regs; -+ u32 regs_len; -+ u32 port_num; - struct ddb_port port[DDB_MAX_PORT]; -+ u32 i2c_num; - struct ddb_i2c i2c[DDB_MAX_I2C]; - struct ddb_input input[DDB_MAX_INPUT]; - struct ddb_output output[DDB_MAX_OUTPUT]; -+ struct dvb_adapter adap[DDB_MAX_INPUT]; -+ struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT]; -+ -+ void (*handler[128])(unsigned long); -+ unsigned long handler_data[128]; - - struct device *ddb_dev; -- int nr; -+ u32 ddb_dev_users; -+ u32 nr; - u8 iobuf[1028]; - -- struct ddb_info *info; -- int msi; -+ u8 leds; -+ u32 ts_irq; -+ u32 i2c_irq; -+ int ns_num; -+ -+ struct ddb_ns ns[DDB_NS_MAX]; -+ int vlan; -+ struct mutex mutex; -+ -+ struct dvb_device *nsd_dev; -+ u8 tsbuf[TS_CAPTURE_LEN]; -+ -+ struct mod_base mod_base; -+ struct mod_state mod[10]; - }; - --/****************************************************************************/ -+static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr) -+{ -+ writeb(val, (char *) (dev->regs + (adr))); -+} -+ -+static inline u32 ddbreadb(struct ddb *dev, u32 adr) -+{ -+ return readb((char *) (dev->regs + (adr))); -+} -+ -+static inline void ddbwritel0(struct ddb_link *link, u32 val, u32 adr) -+{ -+ writel(val, (char *) (link->dev->regs + (adr))); -+} -+ -+static inline u32 ddbreadl0(struct ddb_link *link, u32 adr) -+{ -+ return readl((char *) (link->dev->regs + (adr))); -+} -+ -+static inline void gtlw(struct ddb_link *link) -+{ -+ while (1 & ddbreadl0(link, link->regs + 0x10)) -+ ; -+} -+ -+static u32 ddbreadl(struct ddb *dev, u32 adr) -+{ -+ if (unlikely(adr & 0xf0000000)) { -+ unsigned long flags; -+ u32 val, l = (adr >> DDB_LINK_SHIFT); -+ struct ddb_link *link = &dev->link[l]; -+ -+ spin_lock_irqsave(&link->lock, flags); -+ gtlw(link); -+ ddbwritel0(link, adr & 0xfffc, link->regs + 0x14); -+ ddbwritel0(link, 3, link->regs + 0x10); -+ gtlw(link); -+ val = ddbreadl0(link, link->regs + 0x1c); -+ spin_unlock_irqrestore(&link->lock, flags); -+ return val; -+ } -+ return readl((char *) (dev->regs + (adr))); -+} -+ -+static void ddbwritel(struct ddb *dev, u32 val, u32 adr) -+{ -+ if (unlikely(adr & 0xf0000000)) { -+ unsigned long flags; -+ u32 l = (adr >> DDB_LINK_SHIFT); -+ struct ddb_link *link = &dev->link[l]; - --#define ddbwritel(_val, _adr) writel((_val), \ -- dev->regs+(_adr)) --#define ddbreadl(_adr) readl(dev->regs+(_adr)) --#define ddbcpyto(_adr, _src, _count) memcpy_toio(dev->regs+(_adr), (_src), (_count)) --#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), dev->regs+(_adr), (_count)) -+ spin_lock_irqsave(&link->lock, flags); -+ gtlw(link); -+ ddbwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14); -+ ddbwritel0(link, val, link->regs + 0x18); -+ ddbwritel0(link, 1, link->regs + 0x10); -+ spin_unlock_irqrestore(&link->lock, flags); -+ return; -+ } -+ writel(val, (char *) (dev->regs + (adr))); -+} - -+static void gtlcpyto(struct ddb *dev, u32 adr, const u8 *buf, -+ unsigned int count) -+{ -+ u32 val = 0, p = adr; -+ u32 aa = p & 3; -+ -+ if (aa) { -+ while (p & 3 && count) { -+ val >>= 8; -+ val |= *buf << 24; -+ p++; -+ buf++; -+ count--; -+ } -+ ddbwritel(dev, val, adr); -+ } -+ while (count >= 4) { -+ val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); -+ ddbwritel(dev, val, p); -+ p += 4; -+ buf += 4; -+ count -= 4; -+ } -+ if (count) { -+ val = buf[0]; -+ if (count > 1) -+ val |= buf[1] << 8; -+ if (count > 2) -+ val |= buf[2] << 16; -+ ddbwritel(dev, val, p); -+ } -+} -+ -+static void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count) -+{ -+ u32 val = 0, p = adr; -+ u32 a = p & 3; -+ -+ if (a) { -+ val = ddbreadl(dev, p) >> (8 * a); -+ while (p & 3 && count) { -+ *buf = val & 0xff; -+ val >>= 8; -+ p++; -+ buf++; -+ count--; -+ } -+ } -+ while (count >= 4) { -+ val = ddbreadl(dev, p); -+ buf[0] = val & 0xff; -+ buf[1] = (val >> 8) & 0xff; -+ buf[2] = (val >> 16) & 0xff; -+ buf[3] = (val >> 24) & 0xff; -+ p += 4; -+ buf += 4; -+ count -= 4; -+ } -+ if (count) { -+ val = ddbreadl(dev, p); -+ buf[0] = val & 0xff; -+ if (count > 1) -+ buf[1] = (val >> 8) & 0xff; -+ if (count > 2) -+ buf[2] = (val >> 16) & 0xff; -+ } -+} -+ -+static void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count) -+{ -+ if (unlikely(adr & 0xf0000000)) -+ return gtlcpyto(dev, adr, src, count); -+ return memcpy_toio((char *) (dev->regs + adr), src, count); -+} -+ -+static void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count) -+{ -+ if (unlikely(adr & 0xf0000000)) -+ return gtlcpyfrom(dev, dst, adr, count); -+ return memcpy_fromio(dst, (char *) (dev->regs + adr), count); -+} -+ -+#define ddbmemset(_dev, _adr, _val, _count) \ -+ memset_io((char *) (_dev->regs + (_adr)), (_val), (_count)) -+ -+ -+/****************************************************************************/ - /****************************************************************************/ -+/****************************************************************************/ -+ -+#define dd_uint8 u8 -+#define dd_uint16 u16 -+#define dd_int16 s16 -+#define dd_uint32 u32 -+#define dd_int32 s32 -+#define dd_uint64 u64 -+#define dd_int64 s64 -+ -+#define DDMOD_FLASH_START 0x1000 -+ -+struct DDMOD_FLASH_DS { -+ dd_uint32 Symbolrate; /* kSymbols/s */ -+ dd_uint32 DACFrequency; /* kHz */ -+ dd_uint16 FrequencyResolution; /* kHz */ -+ dd_uint16 IQTableLength; -+ dd_uint16 FrequencyFactor; -+ dd_int16 PhaseCorr; /* TBD */ -+ dd_uint32 Control2; -+ dd_uint16 PostScaleI; -+ dd_uint16 PostScaleQ; -+ dd_uint16 PreScale; -+ dd_int16 EQTap[11]; -+ dd_uint16 FlatStart; -+ dd_uint16 FlatEnd; -+ dd_uint32 FlashOffsetPrecalculatedIQTables; /* 0 = none */ -+ dd_uint8 Reserved[28]; -+ -+}; -+ -+struct DDMOD_FLASH { -+ dd_uint32 Magic; -+ dd_uint16 Version; -+ dd_uint16 DataSets; -+ -+ dd_uint16 VCORefFrequency; /* MHz */ -+ dd_uint16 VCO1Frequency; /* MHz */ -+ dd_uint16 VCO2Frequency; /* MHz */ -+ -+ dd_uint16 DACAux1; /* TBD */ -+ dd_uint16 DACAux2; /* TBD */ -+ -+ dd_uint8 Reserved1[238]; -+ -+ struct DDMOD_FLASH_DS DataSet[1]; -+}; -+ -+#define DDMOD_FLASH_MAGIC 0x5F564d5F -+ -+ -+int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg); -+int ddbridge_mod_init(struct ddb *dev); -+void ddbridge_mod_output_stop(struct ddb_output *output); -+void ddbridge_mod_output_start(struct ddb_output *output); -+void ddbridge_mod_rate_handler(unsigned long data); -+ -+ -+int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len); -+ -+#define DDBRIDGE_VERSION "0.9.23" - - #endif -diff --git a/drivers/media/pci/ddbridge/octonet.c b/drivers/media/pci/ddbridge/octonet.c -new file mode 100644 -index 0000000..3546f96 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/octonet.c -@@ -0,0 +1,262 @@ -+/* -+ * octonet.c: Digital Devices network tuner driver -+ * -+ * Copyright (C) 2012-15 Digital Devices GmbH -+ * Marcus Metzler -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include "ddbridge.h" -+#include "ddbridge-regs.h" -+ -+static int adapter_alloc = 3; -+module_param(adapter_alloc, int, 0444); -+MODULE_PARM_DESC(adapter_alloc, -+"0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); -+ -+#include "ddbridge-core.c" -+ -+static struct ddb_regset octopus_i2c = { -+ .base = 0x80, -+ .num = 0x04, -+ .size = 0x20, -+}; -+ -+static struct ddb_regset octopus_i2c_buf = { -+ .base = 0x1000, -+ .num = 0x04, -+ .size = 0x200, -+}; -+ -+static struct ddb_regmap octopus_net_map = { -+ .i2c = &octopus_i2c, -+ .i2c_buf = &octopus_i2c_buf, -+}; -+ -+static struct ddb_regset octopus_gtl = { -+ .base = 0x180, -+ .num = 0x01, -+ .size = 0x20, -+}; -+ -+static struct ddb_regmap octopus_net_gtl = { -+ .i2c = &octopus_i2c, -+ .i2c_buf = &octopus_i2c_buf, -+ .gtl = &octopus_gtl, -+}; -+ -+static struct ddb_info ddb_octonet = { -+ .type = DDB_OCTONET, -+ .name = "Digital Devices OctopusNet network DVB adapter", -+ .regmap = &octopus_net_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+ .ns_num = 12, -+ .mdio_num = 1, -+}; -+ -+static struct ddb_info ddb_octonet_jse = { -+ .type = DDB_OCTONET, -+ .name = "Digital Devices OctopusNet network DVB adapter JSE", -+ .regmap = &octopus_net_map, -+ .port_num = 4, -+ .i2c_mask = 0x0f, -+ .ns_num = 15, -+ .mdio_num = 1, -+}; -+ -+static struct ddb_info ddb_octonet_gtl = { -+ .type = DDB_OCTONET, -+ .name = "Digital Devices OctopusNet GTL", -+ .regmap = &octopus_net_gtl, -+ .port_num = 4, -+ .i2c_mask = 0x05, -+ .ns_num = 12, -+ .mdio_num = 1, -+ .con_clock = 1, -+}; -+ -+static struct ddb_info ddb_octonet_tbd = { -+ .type = DDB_OCTONET, -+ .name = "Digital Devices OctopusNet", -+ .regmap = &octopus_net_map, -+}; -+ -+static void octonet_unmap(struct ddb *dev) -+{ -+ if (dev->regs) -+ iounmap(dev->regs); -+ vfree(dev); -+} -+ -+static int octonet_remove(struct platform_device *pdev) -+{ -+ struct ddb *dev; -+ -+ dev = platform_get_drvdata(pdev); -+ -+ ddb_device_destroy(dev); -+ ddb_nsd_detach(dev); -+ ddb_ports_detach(dev); -+ ddb_i2c_release(dev); -+ -+ if (dev->link[0].info->ns_num) -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ -+ free_irq(platform_get_irq(dev->pfdev, 0), dev); -+ ddb_ports_release(dev); -+ octonet_unmap(dev); -+ platform_set_drvdata(pdev, 0); -+ return 0; -+} -+ -+static int octonet_probe(struct platform_device *pdev) -+{ -+ struct ddb *dev; -+ struct resource *regs; -+ int irq; -+ int i; -+ -+ dev = vzalloc(sizeof(struct ddb)); -+ if (!dev) -+ return -ENOMEM; -+ platform_set_drvdata(pdev, dev); -+ dev->dev = &pdev->dev; -+ dev->pfdev = pdev; -+ -+ mutex_init(&dev->mutex); -+ regs = platform_get_resource(dev->pfdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ dev->regs_len = (regs->end - regs->start) + 1; -+ dev_info(dev->dev, "regs_start=%08x regs_len=%08x\n", -+ (u32) regs->start, (u32) dev->regs_len); -+ dev->regs = ioremap(regs->start, dev->regs_len); -+ -+ if (!dev->regs) { -+ dev_err(dev->dev, "ioremap failed\n"); -+ return -ENOMEM; -+ } -+ -+ dev->link[0].ids.hwid = ddbreadl(dev, 0); -+ dev->link[0].ids.regmapid = ddbreadl(dev, 4); -+ dev->link[0].ids.devid = ddbreadl(dev, 8); -+ dev->link[0].ids.mac = ddbreadl(dev, 12); -+ -+ dev->link[0].ids.vendor = dev->link[0].ids.devid & 0xffff; -+ dev->link[0].ids.device = dev->link[0].ids.devid >> 16; -+ dev->link[0].ids.subvendor = dev->link[0].ids.devid & 0xffff; -+ dev->link[0].ids.subdevice = dev->link[0].ids.devid >> 16; -+ -+ dev->link[0].dev = dev; -+ if (dev->link[0].ids.devid == 0x0300dd01) -+ dev->link[0].info = &ddb_octonet; -+ else if (dev->link[0].ids.devid == 0x0301dd01) -+ dev->link[0].info = &ddb_octonet_jse; -+ else if (dev->link[0].ids.devid == 0x0307dd01) -+ dev->link[0].info = &ddb_octonet_gtl; -+ else -+ dev->link[0].info = &ddb_octonet_tbd; -+ -+ pr_info("HW %08x REGMAP %08x\n", dev->link[0].ids.hwid, -+ dev->link[0].ids.regmapid); -+ pr_info("MAC %08x DEVID %08x\n", dev->link[0].ids.mac, -+ dev->link[0].ids.devid); -+ -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS); -+ for (i = 0; i < 16; i++) -+ ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i)); -+ usleep_range(5000, 6000); -+ -+ irq = platform_get_irq(dev->pfdev, 0); -+ if (irq < 0) -+ goto fail; -+ if (request_irq(irq, irq_handler, -+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, -+ "octonet-dvb", (void *) dev) < 0) -+ goto fail; -+ ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE); -+ -+ if (ddb_init(dev) == 0) -+ return 0; -+ -+fail: -+ dev_err(dev->dev, "fail\n"); -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ octonet_unmap(dev); -+ platform_set_drvdata(pdev, 0); -+ return -1; -+} -+ -+#ifdef CONFIG_OF -+static const struct of_device_id octonet_dt_ids[] = { -+ { .compatible = "digitaldevices,octonet-dvb" }, -+ { /* sentinel */ } -+}; -+ -+MODULE_DEVICE_TABLE(of, octonet_dt_ids); -+#endif -+ -+static struct platform_driver octonet_driver = { -+ .remove = __exit_p(octonet_remove), -+ .probe = octonet_probe, -+ .driver = { -+ .name = "octonet-dvb", -+ .owner = THIS_MODULE, -+#ifdef CONFIG_OF -+ .of_match_table = of_match_ptr(octonet_dt_ids), -+#endif -+ }, -+}; -+ -+static int init_octonet(void) -+{ -+ int res; -+ -+ pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION -+ ", Copyright (C) 2010-15 Digital Devices GmbH\n"); -+ res = ddb_class_create(); -+ if (res) -+ return res; -+ res = platform_driver_probe(&octonet_driver, octonet_probe); -+ if (res) { -+ ddb_class_destroy(); -+ return res; -+ } -+ return 0; -+} -+ -+static void exit_octonet(void) -+{ -+ platform_driver_unregister(&octonet_driver); -+ ddb_class_destroy(); -+} -+ -+module_init(init_octonet); -+module_exit(exit_octonet); -+ -+MODULE_DESCRIPTION("GPL"); -+MODULE_AUTHOR("Marcus and Ralph Metzler, Metzler Brothers Systementwicklung GbR"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("0.6"); -diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c -index 2c0015b..03688ee 100644 ---- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c -+++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c -@@ -111,6 +111,7 @@ static struct tda18212_config tda18212_conf = { - .if_dvbt_7 = 4150, - .if_dvbt_8 = 4500, - .if_dvbc = 5000, -+ .init_flags = 0, - }; - - int c8sectpfe_frontend_attach(struct dvb_frontend **fe, -diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c -index 7b80683..2488537 100644 ---- a/drivers/media/tuners/tda18212.c -+++ b/drivers/media/tuners/tda18212.c -@@ -220,6 +220,11 @@ static int tda18212_probe(struct i2c_client *client, - fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ - - ret = regmap_read(dev->regmap, 0x00, &chip_id); -+ -+ /* retry probe if desired */ -+ if (ret && (cfg->init_flags & TDA18212_INIT_RETRY)) -+ ret = regmap_read(dev->regmap, 0x00, &chip_id); -+ - dev_dbg(&dev->client->dev, "chip_id=%02x\n", chip_id); - - if (fe->ops.i2c_gate_ctrl) -diff --git a/drivers/media/tuners/tda18212.h b/drivers/media/tuners/tda18212.h -index e58c909..457ae72 100644 ---- a/drivers/media/tuners/tda18212.h -+++ b/drivers/media/tuners/tda18212.h -@@ -24,6 +24,8 @@ - #include - #include "dvb_frontend.h" - -+#define TDA18212_INIT_RETRY (1 << 0) -+ - struct tda18212_config { - u16 if_dvbt_6; - u16 if_dvbt_7; -@@ -37,6 +39,11 @@ struct tda18212_config { - u16 if_atsc_qam; - - /* -+ * flags for tuner init control -+ */ -+ u32 init_flags; -+ -+ /* - * pointer to DVB frontend - */ - struct dvb_frontend *fe; -diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c -index ae917c0..02d22eb 100644 ---- a/drivers/media/usb/dvb-usb-v2/anysee.c -+++ b/drivers/media/usb/dvb-usb-v2/anysee.c -@@ -336,6 +336,7 @@ static struct tda18212_config anysee_tda18212_config = { - .if_dvbt_7 = 4150, - .if_dvbt_8 = 4150, - .if_dvbc = 5000, -+ .init_flags = 0, - }; - - static struct tda18212_config anysee_tda18212_config2 = { -@@ -346,6 +347,7 @@ static struct tda18212_config anysee_tda18212_config2 = { - .if_dvbt2_7 = 4000, - .if_dvbt2_8 = 4000, - .if_dvbc = 5000, -+ .init_flags = 0, - }; - - static struct cx24116_config anysee_cx24116_config = { -diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c -index 8cedef0..7bc7778 100644 ---- a/drivers/media/usb/em28xx/em28xx-dvb.c -+++ b/drivers/media/usb/em28xx/em28xx-dvb.c -@@ -376,6 +376,7 @@ static struct tda18271_config kworld_ub435q_v2_config = { - static struct tda18212_config kworld_ub435q_v3_config = { - .if_atsc_vsb = 3600, - .if_atsc_qam = 3600, -+ .init_flags = 0, - }; - - static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { -diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c -index 692ba3e..a965edc 100644 ---- a/drivers/staging/media/cxd2099/cxd2099.c -+++ b/drivers/staging/media/cxd2099/cxd2099.c -@@ -1,7 +1,7 @@ - /* - * cxd2099.c: Driver for the CXD2099AR Common Interface Controller - * -- * Copyright (C) 2010-2011 Digital Devices GmbH -+ * Copyright (C) 2010-2013 Digital Devices GmbH - * - * - * This program is free software; you can redistribute it and/or -@@ -22,6 +22,7 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -+#include - #include - #include - #include -@@ -33,7 +34,9 @@ - - #include "cxd2099.h" - --#define MAX_BUFFER_SIZE 248 -+/* #define BUFFER_MODE 1 */ -+ -+static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount); - - struct cxd { - struct dvb_ca_en50221 en; -@@ -48,6 +51,7 @@ struct cxd { - int mode; - int ready; - int dr; -+ int write_busy; - int slot_stat; - - u8 amem[1024]; -@@ -55,6 +59,9 @@ struct cxd { - - int cammode; - struct mutex lock; -+ -+ u8 rbuf[1028]; -+ u8 wbuf[1028]; - }; - - static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, -@@ -73,7 +80,7 @@ static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, - } - - static int i2c_write(struct i2c_adapter *adapter, u8 adr, -- u8 *data, u8 len) -+ u8 *data, u16 len) - { - struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len}; - -@@ -100,7 +107,7 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, - } - - static int i2c_read(struct i2c_adapter *adapter, u8 adr, -- u8 reg, u8 *data, u8 n) -+ u8 reg, u8 *data, u16 n) - { - struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, - .buf = ®, .len = 1}, -@@ -114,14 +121,27 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, - return 0; - } - --static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n) -+static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n) - { -- int status; -+ int status = 0; - -- status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); -+ if (ci->lastaddress != adr) -+ status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); - if (!status) { - ci->lastaddress = adr; -- status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n); -+ -+ while (n) { -+ int len = n; -+ -+ if (ci->cfg.max_i2c && -+ len > ci->cfg.max_i2c) -+ len = ci->cfg.max_i2c; -+ status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, len); -+ if (status) -+ return status; -+ data += len; -+ n -= len; -+ } - } - return status; - } -@@ -181,46 +201,18 @@ static int write_io(struct cxd *ci, u16 address, u8 val) - return status; - } - --#if 0 --static int read_io_data(struct cxd *ci, u8 *data, u8 n) --{ -- int status; -- u8 addr[3] = { 2, 0, 0 }; -- -- status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3); -- if (!status) -- status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n); -- return 0; --} -- --static int write_io_data(struct cxd *ci, u8 *data, u8 n) --{ -- int status; -- u8 addr[3] = {2, 0, 0}; -- -- status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3); -- if (!status) { -- u8 buf[256] = {3}; -- -- memcpy(buf+1, data, n); -- status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1); -- } -- return 0; --} --#endif -- - static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask) - { -- int status; -+ int status = 0; - -- status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg); -+ if (ci->lastaddress != reg) -+ status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg); - if (!status && reg >= 6 && reg <= 8 && mask != 0xff) - status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]); -+ ci->lastaddress = reg; - ci->regs[reg] = (ci->regs[reg] & (~mask)) | val; -- if (!status) { -- ci->lastaddress = reg; -+ if (!status) - status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]); -- } - if (reg == 0x20) - ci->regs[reg] &= 0x7f; - return status; -@@ -232,16 +224,32 @@ static int write_reg(struct cxd *ci, u8 reg, u8 val) - } - - #ifdef BUFFER_MODE --static int write_block(struct cxd *ci, u8 adr, u8 *data, int n) -+static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n) - { -- int status; -- u8 buf[256] = {1}; -- -- status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); -- if (!status) { -- ci->lastaddress = adr; -- memcpy(buf + 1, data, n); -- status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1); -+ int status = 0; -+ u8 *buf = ci->wbuf; -+ -+ if (ci->lastaddress != adr) -+ status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); -+ if (status) -+ return status; -+ dev_info(&ci->i2c->dev, "write_block %d\n", n); -+ -+ ci->lastaddress = adr; -+ buf[0] = 1; -+ while (n) { -+ int len = n; -+ -+ if (ci->cfg.max_i2c && -+ len + 1 > ci->cfg.max_i2c) -+ len = ci->cfg.max_i2c - 1; -+ dev_info(&ci->i2c->dev, "write %d\n", len); -+ memcpy(buf + 1, data, len); -+ status = i2c_write(ci->i2c, ci->cfg.adr, buf, len + 1); -+ if (status) -+ return status; -+ n -= len; -+ data += len; - } - return status; - } -@@ -267,6 +275,8 @@ static void set_mode(struct cxd *ci, int mode) - - static void cam_mode(struct cxd *ci, int mode) - { -+ u8 dummy; -+ - if (mode == ci->cammode) - return; - -@@ -275,16 +285,15 @@ static void cam_mode(struct cxd *ci, int mode) - write_regm(ci, 0x20, 0x80, 0x80); - break; - case 0x01: --#ifdef BUFFER_MODE - if (!ci->en.read_data) - return; -+ ci->write_busy = 0; - dev_info(&ci->i2c->dev, "enable cam buffer mode\n"); -- /* write_reg(ci, 0x0d, 0x00); */ -- /* write_reg(ci, 0x0e, 0x01); */ -+ write_reg(ci, 0x0d, 0x00); -+ write_reg(ci, 0x0e, 0x01); - write_regm(ci, 0x08, 0x40, 0x40); -- /* read_reg(ci, 0x12, &dummy); */ -+ read_reg(ci, 0x12, &dummy); - write_regm(ci, 0x08, 0x80, 0x80); --#endif - break; - default: - break; -@@ -292,8 +301,6 @@ static void cam_mode(struct cxd *ci, int mode) - ci->cammode = mode; - } - -- -- - static int init(struct cxd *ci) - { - int status; -@@ -329,12 +336,6 @@ static int init(struct cxd *ci) - if (status < 0) - break; - --#if 0 -- /* Input Mode C, BYPass Serial, TIVAL = low, MSB */ -- status = write_reg(ci, 0x09, 0x4D); -- if (status < 0) -- break; --#endif - /* TOSTRT = 8, Mode B (gated clock), falling Edge, - * Serial, POL=HIGH, MSB */ - status = write_reg(ci, 0x0A, 0xA7); -@@ -361,7 +362,10 @@ static int init(struct cxd *ci) - if (status < 0) - break; - -- if (ci->cfg.clock_mode) { -+ if (ci->cfg.clock_mode == 2) { -+ /* bitrate*2^13/ 72000 */ -+ u32 reg = ((ci->cfg.bitrate << 13) + 71999) / 72000; -+ - if (ci->cfg.polarity) { - status = write_reg(ci, 0x09, 0x6f); - if (status < 0) -@@ -371,6 +375,25 @@ static int init(struct cxd *ci) - if (status < 0) - break; - } -+ status = write_reg(ci, 0x20, 0x08); -+ if (status < 0) -+ break; -+ status = write_reg(ci, 0x21, (reg >> 8) & 0xff); -+ if (status < 0) -+ break; -+ status = write_reg(ci, 0x22, reg & 0xff); -+ if (status < 0) -+ break; -+ } else if (ci->cfg.clock_mode == 1) { -+ if (ci->cfg.polarity) { -+ status = write_reg(ci, 0x09, 0x6f); /* D */ -+ if (status < 0) -+ break; -+ } else { -+ status = write_reg(ci, 0x09, 0x6d); -+ if (status < 0) -+ break; -+ } - status = write_reg(ci, 0x20, 0x68); - if (status < 0) - break; -@@ -382,7 +405,7 @@ static int init(struct cxd *ci) - break; - } else { - if (ci->cfg.polarity) { -- status = write_reg(ci, 0x09, 0x4f); -+ status = write_reg(ci, 0x09, 0x4f); /* C */ - if (status < 0) - break; - } else { -@@ -390,7 +413,6 @@ static int init(struct cxd *ci) - if (status < 0) - break; - } -- - status = write_reg(ci, 0x20, 0x28); - if (status < 0) - break; -@@ -431,23 +453,6 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca, - int slot, int address) - { - struct cxd *ci = ca->data; --#if 0 -- if (ci->amem_read) { -- if (address <= 0 || address > 1024) -- return -EIO; -- return ci->amem[address]; -- } -- -- mutex_lock(&ci->lock); -- write_regm(ci, 0x06, 0x00, 0x05); -- read_pccard(ci, 0, &ci->amem[0], 128); -- read_pccard(ci, 128, &ci->amem[0], 128); -- read_pccard(ci, 256, &ci->amem[0], 128); -- read_pccard(ci, 384, &ci->amem[0], 128); -- write_regm(ci, 0x06, 0x05, 0x05); -- mutex_unlock(&ci->lock); -- return ci->amem[address]; --#else - u8 val; - - mutex_lock(&ci->lock); -@@ -456,7 +461,6 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca, - mutex_unlock(&ci->lock); - /* printk(KERN_INFO "%02x:%02x\n", address,val); */ - return val; --#endif - } - - static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, -@@ -500,16 +504,10 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) - { - struct cxd *ci = ca->data; - -+ if (ci->cammode) -+ read_data(ca, slot, ci->rbuf, 0); -+ - mutex_lock(&ci->lock); --#if 0 -- write_reg(ci, 0x00, 0x21); -- write_reg(ci, 0x06, 0x1F); -- write_reg(ci, 0x00, 0x31); --#else --#if 0 -- write_reg(ci, 0x06, 0x1F); -- write_reg(ci, 0x06, 0x2F); --#else - cam_mode(ci, 0); - write_reg(ci, 0x00, 0x21); - write_reg(ci, 0x06, 0x1F); -@@ -517,25 +515,14 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) - write_regm(ci, 0x20, 0x80, 0x80); - write_reg(ci, 0x03, 0x02); - ci->ready = 0; --#endif --#endif - ci->mode = -1; - { - int i; --#if 0 -- u8 val; --#endif -+ - for (i = 0; i < 100; i++) { - usleep_range(10000, 11000); --#if 0 -- read_reg(ci, 0x06, &val); -- dev_info(&ci->i2c->dev, "%d:%02x\n", i, val); -- if (!(val&0x10)) -- break; --#else - if (ci->ready) - break; --#endif - } - } - mutex_unlock(&ci->lock); -@@ -548,11 +535,19 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) - struct cxd *ci = ca->data; - - dev_info(&ci->i2c->dev, "slot_shutdown\n"); -+ if (ci->cammode) -+ read_data(ca, slot, ci->rbuf, 0); - mutex_lock(&ci->lock); -+ write_reg(ci, 0x00, 0x21); -+ write_reg(ci, 0x06, 0x1F); -+ msleep(300); -+ - write_regm(ci, 0x09, 0x08, 0x08); - write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */ - write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */ -+ - ci->mode = -1; -+ ci->write_busy = 0; - mutex_unlock(&ci->lock); - return 0; - } -@@ -564,9 +559,7 @@ static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) - mutex_lock(&ci->lock); - write_regm(ci, 0x09, 0x00, 0x08); - set_mode(ci, 0); --#ifdef BUFFER_MODE - cam_mode(ci, 1); --#endif - mutex_unlock(&ci->lock); - return 0; - } -@@ -585,8 +578,10 @@ static int campoll(struct cxd *ci) - ci->dr = 1; - dev_info(&ci->i2c->dev, "DR\n"); - } -- if (istat&0x20) -+ if (istat&0x20) { -+ ci->write_busy = 0; - dev_info(&ci->i2c->dev, "WC\n"); -+ } - - if (istat&2) { - u8 slotstat; -@@ -594,7 +589,7 @@ static int campoll(struct cxd *ci) - read_reg(ci, 0x01, &slotstat); - if (!(2&slotstat)) { - if (!ci->slot_stat) { -- ci->slot_stat = DVB_CA_EN50221_POLL_CAM_PRESENT; -+ ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; - write_regm(ci, 0x03, 0x08, 0x08); - } - -@@ -606,8 +601,8 @@ static int campoll(struct cxd *ci) - ci->ready = 0; - } - } -- if (istat&8 && -- ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT) { -+ if ((istat&8) && -+ (ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT)) { - ci->ready = 1; - ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY; - } -@@ -629,7 +624,6 @@ static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) - return ci->slot_stat; - } - --#ifdef BUFFER_MODE - static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) - { - struct cxd *ci = ca->data; -@@ -647,23 +641,33 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) - mutex_lock(&ci->lock); - read_reg(ci, 0x0f, &msb); - read_reg(ci, 0x10, &lsb); -- len = (msb<<8)|lsb; -+ len = ((u16) msb << 8) | lsb; -+ if (len > ecount || len < 2) { -+ /* read it anyway or cxd may hang */ -+ read_block(ci, 0x12, ci->rbuf, len); -+ mutex_unlock(&ci->lock); -+ return -EIO; -+ } - read_block(ci, 0x12, ebuf, len); - ci->dr = 0; - mutex_unlock(&ci->lock); -- - return len; - } - -+#ifdef BUFFER_MODE -+ - static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) - { - struct cxd *ci = ca->data; - -+ if (ci->write_busy) -+ return -EAGAIN; - mutex_lock(&ci->lock); -- printk(kern_INFO "write_data %d\n", ecount); -+ dev_info(&ci->i2c->dev, "write_data %d\n", ecount); - write_reg(ci, 0x0d, ecount>>8); - write_reg(ci, 0x0e, ecount&0xff); - write_block(ci, 0x11, ebuf, ecount); -+ ci->write_busy = 1; - mutex_unlock(&ci->lock); - return ecount; - } -diff --git a/drivers/staging/media/cxd2099/cxd2099.h b/drivers/staging/media/cxd2099/cxd2099.h -index 0eb607c..f4b29b1 100644 ---- a/drivers/staging/media/cxd2099/cxd2099.h -+++ b/drivers/staging/media/cxd2099/cxd2099.h -@@ -30,8 +30,10 @@ - struct cxd2099_cfg { - u32 bitrate; - u8 adr; -- u8 polarity:1; -- u8 clock_mode:1; -+ u8 polarity; -+ u8 clock_mode; -+ -+ u32 max_i2c; - }; - - #if defined(CONFIG_DVB_CXD2099) || \ -diff --git a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h -index 00a20cd..bf9d16b 100644 ---- a/include/uapi/linux/dvb/frontend.h -+++ b/include/uapi/linux/dvb/frontend.h -@@ -156,6 +156,8 @@ enum fe_code_rate { - FEC_3_5, - FEC_9_10, - FEC_2_5, -+ FEC_1_4, -+ FEC_1_3, - }; - - enum fe_modulation { -@@ -307,7 +309,9 @@ enum fe_interleaving { - #define DTV_STAT_ERROR_BLOCK_COUNT 68 - #define DTV_STAT_TOTAL_BLOCK_COUNT 69 - --#define DTV_MAX_COMMAND DTV_STAT_TOTAL_BLOCK_COUNT -+#define DTV_INPUT 70 -+ -+#define DTV_MAX_COMMAND DTV_INPUT - - enum fe_pilot { - PILOT_ON, -@@ -342,6 +346,7 @@ enum fe_delivery_system { - SYS_DVBT2, - SYS_TURBO, - SYS_DVBC_ANNEX_C, -+ SYS_DVBC2, - }; - - /* backward compatibility */ -diff --git a/include/uapi/linux/dvb/mod.h b/include/uapi/linux/dvb/mod.h -new file mode 100644 -index 0000000..f595a2c ---- /dev/null -+++ b/include/uapi/linux/dvb/mod.h -@@ -0,0 +1,22 @@ -+#ifndef _UAPI_DVBMOD_H_ -+#define _UAPI_DVBMOD_H_ -+ -+#include -+#include "frontend.h" -+ -+struct dvb_mod_params { -+ __u32 base_frequency; -+ __u32 attenuator; -+}; -+ -+struct dvb_mod_channel_params { -+ enum fe_modulation modulation; -+ __u64 input_bitrate; /* 2^-32 Hz */ -+ int pcr_correction; -+}; -+ -+ -+#define DVB_MOD_SET _IOW('o', 208, struct dvb_mod_params) -+#define DVB_MOD_CHANNEL_SET _IOW('o', 209, struct dvb_mod_channel_params) -+ -+#endif /*_UAPI_DVBMOD_H_*/ -diff --git a/include/uapi/linux/dvb/ns.h b/include/uapi/linux/dvb/ns.h -new file mode 100644 -index 0000000..4cfd9f0 ---- /dev/null -+++ b/include/uapi/linux/dvb/ns.h -@@ -0,0 +1,69 @@ -+#ifndef _UAPI_DVBNS_H_ -+#define _UAPI_DVBNS_H_ -+ -+#include -+ -+struct dvb_ns_params { -+ __u8 smac[6]; -+ __u8 dmac[6]; -+ __u8 sip[16]; -+ __u8 dip[16]; -+ __u16 sport; -+ __u16 dport; -+ __u16 sport2; -+ __u16 dport2; -+ __u8 ssrc[8]; -+ __u8 flags; -+ __u8 qos; -+ __u16 vlan; -+ __u8 ttl; -+}; -+ -+#define DVB_NS_IPV6 0x01 -+#define DVB_NS_RTP 0x02 -+#define DVB_NS_RTCP 0x04 -+#define DVB_NS_RTP_TO 0x08 -+#define DVB_NS_VLAN 0x10 -+ -+struct dvb_ns_rtcp { -+ __u8 *msg; -+ __u16 len; -+}; -+ -+struct dvb_ns_packet { -+ __u8 *buf; -+ __u8 count; -+}; -+ -+struct dvb_nsd_ts { -+ __u16 pid; -+ __u16 num; -+ __u16 input; -+ __u16 timeout; -+ __u16 len; -+ __u8 *ts; -+ __u8 mode; -+ __u8 table; -+ -+ __u8 filter_mask; -+ __u8 section; -+ __u16 section_id; -+}; -+ -+#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params) -+#define NS_START _IO('o', 193) -+#define NS_STOP _IO('o', 194) -+#define NS_SET_PID _IOW('o', 195, __u16) -+#define NS_SET_PIDS _IOW('o', 196, __u8 *) -+#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp) -+ -+#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts) -+#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts) -+#define NSD_CANCEL_GET_TS _IO('o', 200) -+#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts) -+ -+#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet) -+#define NS_INSERT_PACKETS _IOW('o', 203, __u8) -+#define NS_SET_CI _IOW('o', 204, __u8) -+ -+#endif /*_UAPI_DVBNS_H_*/ diff --git a/packages/linux/patches/default/linux-950-saa716x_PCIe_interface_chipset.patch.todo b/packages/linux/patches/default/linux-950-saa716x_PCIe_interface_chipset.patch.todo deleted file mode 100644 index 1acb96c92c..0000000000 --- a/packages/linux/patches/default/linux-950-saa716x_PCIe_interface_chipset.patch.todo +++ /dev/null @@ -1,13026 +0,0 @@ -diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig -index b85f88c..238b2ed 100644 ---- a/drivers/media/common/Kconfig -+++ b/drivers/media/common/Kconfig -@@ -18,4 +18,5 @@ config CYPRESS_FIRMWARE - - source "drivers/media/common/b2c2/Kconfig" - source "drivers/media/common/saa7146/Kconfig" -+source "drivers/media/common/saa716x/Kconfig" - source "drivers/media/common/siano/Kconfig" -diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile -index d208de3..b3c373d 100644 ---- a/drivers/media/common/Makefile -+++ b/drivers/media/common/Makefile -@@ -1,4 +1,4 @@ --obj-y += b2c2/ saa7146/ siano/ -+obj-y += b2c2/ saa7146/ saa716x/ siano/ - obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o - obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o - obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o -diff --git a/drivers/media/common/saa716x/Kconfig b/drivers/media/common/saa716x/Kconfig -new file mode 100644 -index 0000000..e667a58 ---- /dev/null -+++ b/drivers/media/common/saa716x/Kconfig -@@ -0,0 +1,67 @@ -+menuconfig SAA716X_SUPPORT -+ bool "Support for SAA716x family from NXP/Philips" -+ depends on PCI && I2C -+ help -+ support for saa716x -+ -+if SAA716X_SUPPORT -+config SAA716X_CORE -+ tristate "SAA7160/1/2 PCI Express bridge based devices" -+ depends on PCI && I2C -+ -+ help -+ Support for PCI cards based on the SAA7160/1/2 PCI Express bridge. -+ -+ Say Y if you own such a device and want to use it. -+ -+config DVB_SAA716X_BUDGET -+ tristate "SAA7160/1/2 based Budget PCIe cards (DVB only)" -+ depends on SAA716X_CORE && DVB_CORE -+ select DVB_DS3000 if !DVB_FE_CUSTOMISE -+ select DVB_DS3103 if !DVB_FE_CUSTOMISE -+ select DVB_TS2022 if !DVB_FE_CUSTOMISE -+ -+ help -+ Support for the SAA7160/1/2 based Budget PCIe DVB cards -+ Currently supported devices are: -+ -+ * KNC1 Dual S2 (DVB-S, DVB-S/S2) -+ * Twinhan/Azurewave VP-1028 (DVB-S) -+ * Twinhan/Azurewave VP-3071 (DVB-T x2) -+ * Twinhan/Azurewave VP-6002 (DVB-S) -+ -+ Say Y if you own such a device and want to use it. -+ -+config DVB_SAA716X_HYBRID -+ tristate "SAA7160/1/2 based Hybrid PCIe cards (DVB + Analog)" -+ depends on SAA716X_CORE && DVB_CORE -+ -+ help -+ Support for the SAA7160/1/2 based Hybrid PCIe DVB cards -+ Currently supported devices are: -+ -+ * Avermedia H-788 (DVB-T) -+ * Avermedia HC-82 (DVB-T) -+ * NXP Reference (Atlantis) (DVB-T x2) -+ * NXP Reference (Nemo) (DVB-T) -+ * Twinhan/Azurewave VP-6090 (DVB-S x2, DVB-T x2) -+ -+ Say Y if you own such a device and want to use it. -+ -+#config DVB_SAA716X_FF -+# tristate "SAA7160/1/2 based Full Fledged PCIe cards" -+# depends on SAA716X_CORE && DVB_CORE -+# depends on INPUT # IR -+# default n -+ -+# help -+# Support for the SAA7160/1/2 based Full fledged PCIe DVB cards -+# These cards do feature a hardware MPEG decoder and other -+# peripherals. Also known as Premium cards. -+# Currently supported devices are: -+ -+# * Technotrend S2 6400 Dual S2 HD (DVB-S/S2 x2) -+ -+# Say Y if you own such a device and want to use it. -+ -+endif # SAA716X_SUPPORT -diff --git a/drivers/media/common/saa716x/Makefile b/drivers/media/common/saa716x/Makefile -new file mode 100644 -index 0000000..c86f224 ---- /dev/null -+++ b/drivers/media/common/saa716x/Makefile -@@ -0,0 +1,26 @@ -+saa716x_core-objs := saa716x_pci.o \ -+ saa716x_i2c.o \ -+ saa716x_cgu.o \ -+ saa716x_msi.o \ -+ saa716x_dma.o \ -+ saa716x_vip.o \ -+ saa716x_aip.o \ -+ saa716x_phi.o \ -+ saa716x_boot.o \ -+ saa716x_fgpi.o \ -+ saa716x_adap.o \ -+ saa716x_gpio.o \ -+ saa716x_greg.o \ -+ saa716x_rom.o \ -+ saa716x_spi.o -+ -+#saa716x_ff-objs := saa716x_ff_main.o \ -+# saa716x_ff_cmd.o \ -+# saa716x_ff_ir.o -+ -+obj-$(CONFIG_SAA716X_CORE) += saa716x_core.o -+obj-$(CONFIG_DVB_SAA716X_BUDGET) += saa716x_budget.o -+obj-$(CONFIG_DVB_SAA716X_HYBRID) += saa716x_hybrid.o -+#obj-$(CONFIG_DVB_SAA716X_FF) += saa716x_ff.o -+ -+EXTRA_CFLAGS = -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/ -diff --git a/drivers/media/common/saa716x/saa716x_adap.c b/drivers/media/common/saa716x/saa716x_adap.c -new file mode 100644 -index 0000000..6d7346c ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_adap.c -@@ -0,0 +1,274 @@ -+#include -+ -+#include "dmxdev.h" -+#include "dvbdev.h" -+#include "dvb_demux.h" -+#include "dvb_frontend.h" -+ -+#include "saa716x_mod.h" -+#include "saa716x_spi.h" -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_gpio.h" -+#include "saa716x_priv.h" -+#include "saa716x_budget.h" -+ -+ -+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -+ -+ -+void saa716x_dma_start(struct saa716x_dev *saa716x, u8 adapter) -+{ -+ struct fgpi_stream_params params; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Start DMA engine for Adapter:%d", adapter); -+ -+ params.bits = 8; -+ params.samples = 188; -+ params.lines = 348; -+ params.pitch = 188; -+ params.offset = 0; -+ params.page_tables = 0; -+ params.stream_type = FGPI_TRANSPORT_STREAM; -+ params.stream_flags = 0; -+ -+ saa716x_fgpi_start(saa716x, saa716x->config->adap_config[adapter].ts_port, ¶ms); -+} -+ -+void saa716x_dma_stop(struct saa716x_dev *saa716x, u8 adapter) -+{ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Stop DMA engine for Adapter:%d", adapter); -+ -+ saa716x_fgpi_stop(saa716x, saa716x->config->adap_config[adapter].ts_port); -+} -+ -+static int saa716x_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; -+ struct saa716x_dev *saa716x = saa716x_adap->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Start feed"); -+ if (!dvbdmx->dmx.frontend) { -+ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); -+ return -EINVAL; -+ } -+ saa716x_adap->feeds++; -+ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed, feeds=%d", -+ saa716x_adap->feeds); -+ -+ if (saa716x_adap->feeds == 1) { -+ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed & dma"); -+ saa716x_dma_start(saa716x, saa716x_adap->count); -+ } -+ -+ return saa716x_adap->feeds; -+} -+ -+static int saa716x_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; -+ struct saa716x_dev *saa716x = saa716x_adap->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Stop feed"); -+ if (!dvbdmx->dmx.frontend) { -+ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); -+ return -EINVAL; -+ } -+ saa716x_adap->feeds--; -+ if (saa716x_adap->feeds == 0) { -+ dprintk(SAA716x_DEBUG, 1, "saa716x stop feed and dma"); -+ saa716x_dma_stop(saa716x, saa716x_adap->count); -+ } -+ -+ return 0; -+} -+ -+int saa716x_dvb_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct saa716x_config *config = saa716x->config; -+ int result, i; -+ -+ mutex_init(&saa716x->adap_lock); -+ -+ for (i = 0; i < config->adapters; i++) { -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_register_adapter"); -+ if (dvb_register_adapter(&saa716x_adap->dvb_adapter, -+ "SAA716x dvb adapter", -+ THIS_MODULE, -+ &saa716x->pdev->dev, -+ adapter_nr) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "Error registering adapter"); -+ return -ENODEV; -+ } -+ -+ saa716x_adap->count = i; -+ -+ saa716x_adap->dvb_adapter.priv = saa716x_adap; -+ saa716x_adap->demux.dmx.capabilities = DMX_TS_FILTERING | -+ DMX_SECTION_FILTERING | -+ DMX_MEMORY_BASED_FILTERING; -+ -+ saa716x_adap->demux.priv = saa716x_adap; -+ saa716x_adap->demux.filternum = 256; -+ saa716x_adap->demux.feednum = 256; -+ saa716x_adap->demux.start_feed = saa716x_dvb_start_feed; -+ saa716x_adap->demux.stop_feed = saa716x_dvb_stop_feed; -+ saa716x_adap->demux.write_to_decoder = NULL; -+ switch (saa716x->pdev->subsystem_device) { -+ case TEVII_S472: { -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ u8 mac[6]; -+ u8 b0[] = { 0, 9 }; -+ struct i2c_msg msg[] = { -+ { -+ .addr = 0x50, -+ .flags = 0, -+ .buf = b0, -+ .len = 2 -+ }, { -+ .addr = 0x50, -+ .flags = I2C_M_RD, -+ .buf = mac, -+ .len = 6 -+ } -+ }; -+ -+ i2c_transfer(adapter, msg, 2); -+ dprintk(SAA716x_INFO, 1, "TeVii S472 MAC= %pM\n", mac); -+ memcpy(saa716x_adap->dvb_adapter.proposed_mac, mac, 6); -+ } -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_dmx_init"); -+ if ((result = dvb_dmx_init(&saa716x_adap->demux)) < 0) { -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err0; -+ } -+ -+ saa716x_adap->dmxdev.filternum = 256; -+ saa716x_adap->dmxdev.demux = &saa716x_adap->demux.dmx; -+ saa716x_adap->dmxdev.capabilities = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_dmxdev_init"); -+ if ((result = dvb_dmxdev_init(&saa716x_adap->dmxdev, -+ &saa716x_adap->dvb_adapter)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); -+ goto err1; -+ } -+ -+ saa716x_adap->fe_hw.source = DMX_FRONTEND_0; -+ -+ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_hw)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err2; -+ } -+ -+ saa716x_adap->fe_mem.source = DMX_MEMORY_FE; -+ -+ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_mem)) < 0) { -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err3; -+ } -+ -+ if ((result = saa716x_adap->demux.dmx.connect_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_hw)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err4; -+ } -+ -+ dvb_net_init(&saa716x_adap->dvb_adapter, &saa716x_adap->dvb_net, &saa716x_adap->demux.dmx); -+// tasklet_init(&saa716x_adap->tasklet, saa716x_dma_xfer, (unsigned long) saa716x); -+ dprintk(SAA716x_DEBUG, 1, "Frontend Init"); -+ saa716x_adap->saa716x = saa716x; -+ -+ if (config->frontend_attach) { -+ result = config->frontend_attach(saa716x_adap, i); -+ if (result < 0) -+ dprintk(SAA716x_ERROR, 1, "SAA716x frontend attach failed"); -+ -+ if (saa716x_adap->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "A frontend driver was not found for [%04x:%04x] subsystem [%04x:%04x]\n", -+ saa716x->pdev->vendor, -+ saa716x->pdev->device, -+ saa716x->pdev->subsystem_vendor, -+ saa716x->pdev->subsystem_device); -+ } else { -+ result = dvb_register_frontend(&saa716x_adap->dvb_adapter, saa716x_adap->fe); -+ if (result < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x register frontend failed"); -+ goto err6; -+ } -+ } -+ -+ } else { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach = NULL"); -+ } -+ -+ saa716x_fgpi_init(saa716x, config->adap_config[i].ts_port, -+ config->adap_config[i].worker); -+ -+ saa716x_adap++; -+ } -+ -+ -+ return 0; -+ -+ /* Error conditions */ -+err6: -+ dvb_frontend_detach(saa716x_adap->fe); -+err4: -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); -+err3: -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); -+err2: -+ dvb_dmxdev_release(&saa716x_adap->dmxdev); -+err1: -+ dvb_dmx_release(&saa716x_adap->demux); -+err0: -+ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); -+ -+ return result; -+} -+EXPORT_SYMBOL(saa716x_dvb_init); -+ -+void saa716x_dvb_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ int i; -+ -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ -+ saa716x_fgpi_exit(saa716x, saa716x->config->adap_config[i].ts_port); -+ -+ if (saa716x_adap->fe) { -+ dvb_unregister_frontend(saa716x_adap->fe); -+ dvb_frontend_detach(saa716x_adap->fe); -+ } -+ -+// tasklet_kill(&saa716x->tasklet); -+ dvb_net_release(&saa716x_adap->dvb_net); -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); -+ dvb_dmxdev_release(&saa716x_adap->dmxdev); -+ dvb_dmx_release(&saa716x_adap->demux); -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_unregister_adapter"); -+ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); -+ -+ saa716x_adap++; -+ } -+ -+ return; -+} -+EXPORT_SYMBOL(saa716x_dvb_exit); -diff --git a/drivers/media/common/saa716x/saa716x_adap.h b/drivers/media/common/saa716x/saa716x_adap.h -new file mode 100644 -index 0000000..7822e36 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_adap.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_ADAP_H -+#define __SAA716x_ADAP_H -+ -+struct saa716x_dev; -+ -+extern int saa716x_dvb_init(struct saa716x_dev *saa716x); -+extern void saa716x_dvb_exit(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_ADAP_H */ -diff --git a/drivers/media/common/saa716x/saa716x_aip.c b/drivers/media/common/saa716x/saa716x_aip.c -new file mode 100644 -index 0000000..3bdb265 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_aip.c -@@ -0,0 +1,20 @@ -+#include -+ -+#include "saa716x_mod.h" -+#include "saa716x_aip_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_aip.h" -+#include "saa716x_priv.h" -+ -+int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev) -+{ -+ return SAA716x_EPRD(dev, AI_CTL) == 0 ? 0 : -1; -+} -+EXPORT_SYMBOL_GPL(saa716x_aip_status); -+ -+void saa716x_aip_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(AI0, AI_CTL, 0x00); -+ SAA716x_EPWR(AI1, AI_CTL, 0x00); -+} -+EXPORT_SYMBOL_GPL(saa716x_aip_disable); -diff --git a/drivers/media/common/saa716x/saa716x_aip.h b/drivers/media/common/saa716x/saa716x_aip.h -new file mode 100644 -index 0000000..36277b7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_aip.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_AIP_H -+#define __SAA716x_AIP_H -+ -+struct saa716x_dev; -+ -+extern int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev); -+extern void saa716x_aip_disable(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_AIP_H */ -diff --git a/drivers/media/common/saa716x/saa716x_aip_reg.h b/drivers/media/common/saa716x/saa716x_aip_reg.h -new file mode 100644 -index 0000000..3e0893a ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_aip_reg.h -@@ -0,0 +1,62 @@ -+#ifndef __SAA716x_AIP_REG_H -+#define __SAA716x_AIP_REG_H -+ -+/* -------------- AI Registers ---------------- */ -+ -+#define AI_STATUS 0x000 -+#define AI_BUF1_ACTIVE (0x00000001 << 4) -+#define AI_OVERRUN (0x00000001 << 3) -+#define AI_HBE (0x00000001 << 2) -+#define AI_BUF2_FULL (0x00000001 << 1) -+#define AI_BUF1_FULL (0x00000001 << 0) -+ -+#define AI_CTL 0x004 -+#define AI_RESET (0x00000001 << 31) -+#define AI_CAP_ENABLE (0x00000001 << 30) -+#define AI_CAP_MODE (0x00000003 << 28) -+#define AI_SIGN_CONVERT (0x00000001 << 27) -+#define AI_EARLYMODE (0x00000001 << 26) -+#define AI_DIAGMODE (0x00000001 << 25) -+#define AI_RAWMODE (0x00000001 << 24) -+#define AI_OVR_INTEN (0x00000001 << 7) -+#define AI_HBE_INTEN (0x00000001 << 6) -+#define AI_BUF2_INTEN (0x00000001 << 5) -+#define AI_BUF1_INTEN (0x00000001 << 4) -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_SERIAL 0x008 -+#define AI_SER_MASTER (0x00000001 << 31) -+#define AI_DATAMODE (0x00000001 << 30) -+#define AI_FRAMEMODE (0x00000003 << 28) -+#define AI_CLOCK_EDGE (0x00000001 << 27) -+#define AI_SSPOS4 (0x00000001 << 19) -+#define AI_NR_CHAN (0x00000003 << 17) -+#define AI_WSDIV (0x000001ff << 8) -+#define AI_SCKDIV (0x000000ff << 0) -+ -+#define AI_FRAMING 0x00c -+#define AI_VALIDPOS (0x000001ff << 22) -+#define AI_LEFTPOS (0x000001ff << 13) -+#define AI_RIGHTPOS (0x000001ff << 4) -+#define AI_SSPOS_3_0 (0x0000000f << 0) -+ -+#define AI_BASE1 0x014 -+#define AI_BASE2 0x018 -+#define AI_BASE (0x03ffffff << 6) -+ -+#define AI_SIZE 0x01c -+#define AI_SAMPLE_SIZE (0x03ffffff << 6) -+ -+#define AI_INT_ACK 0x020 -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_PWR_DOWN 0xff4 -+#define AI_PWR_DWN (0x00000001 << 0) -+ -+#endif /* __SAA716x_AIP_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_boot.c b/drivers/media/common/saa716x/saa716x_boot.c -new file mode 100644 -index 0000000..21e59d0 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_boot.c -@@ -0,0 +1,319 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_greg_reg.h" -+#include "saa716x_cgu_reg.h" -+#include "saa716x_vip_reg.h" -+#include "saa716x_aip_reg.h" -+#include "saa716x_msi_reg.h" -+#include "saa716x_dma_reg.h" -+#include "saa716x_gpio_reg.h" -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_dcs_reg.h" -+ -+#include "saa716x_boot.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static int saa716x_ext_boot(struct saa716x_dev *saa716x) -+{ -+ /* Write GREG boot_ready to 0 -+ * DW_0 = 0x0001_2018 -+ * DW_1 = 0x0000_0000 -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000000); -+ -+ /* Clear VI0 interrupt -+ * DW_2 = 0x0000_0fe8 -+ * DW_3 = 0x0000_03ff -+ */ -+ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x000003ff); -+ -+ /* Clear VI1 interrupt -+ * DW_4 = 0x0000_1fe8 -+ * DW_5 = 0x0000_03ff -+ */ -+ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x000003ff); -+ -+ /* CLear FGPI0 interrupt -+ * DW_6 = 0x0000_2fe8 -+ * DW_7 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI0, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI1 interrupt -+ * DW_8 = 0x0000_3fe8 -+ * DW_9 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI1, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI2 interrupt -+ * DW_10 = 0x0000_4fe8 -+ * DW_11 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI2, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI3 interrupt -+ * DW_12 = 0x0000_5fe8 -+ * DW_13 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI3, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear AI0 interrupt -+ * DW_14 = 0x0000_6020 -+ * DW_15 = 0x0000_000f -+ */ -+ SAA716x_EPWR(AI0, AI_INT_ACK, 0x0000000f); -+ -+ /* Clear AI1 interrupt -+ * DW_16 = 0x0000_7020 -+ * DW_17 = 0x0000_200f -+ */ -+ SAA716x_EPWR(AI1, AI_INT_ACK, 0x0000000f); -+ -+ /* Set GREG boot_ready bit to 1 -+ * DW_18 = 0x0001_2018 -+ * DW_19 = 0x0000_2000 -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); -+#if 0 -+ /* End of Boot script command -+ * DW_20 = 0x0000_0006 -+ * Where to write this value ?? -+ * This seems very odd an address to trigger the -+ * Boot Control State Machine ! -+ */ -+ SAA716x_EPWR(VI0, 0x00000006, 0xffffffff); -+#endif -+ return 0; -+} -+ -+/* Internal Bootscript configuration */ -+static void saa716x_int_boot(struct saa716x_dev *saa716x) -+{ -+ /* #1 Configure PCI COnfig space -+ * GREG_JETSTR_CONFIG_0 -+ */ -+ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, saa716x->pdev->subsystem_vendor); -+ -+ /* GREG_JETSTR_CONFIG_1 -+ * pmcsr_scale:7 = 0x00 -+ * pmcsr_scale:6 = 0x00 -+ * pmcsr_scale:5 = 0x00 -+ * pmcsr_scale:4 = 0x00 -+ * pmcsr_scale:3 = 0x00 -+ * pmcsr_scale:2 = 0x00 -+ * pmcsr_scale:1 = 0x00 -+ * pmcsr_scale:0 = 0x00 -+ * BAR mask = 20 bit -+ * BAR prefetch = no -+ * MSI capable = 32 messages -+ */ -+ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, 0x00001005); -+ -+ /* GREG_JETSTR_CONFIG_2 -+ * pmcsr_data:3 = 0x0 -+ * pmcsr_data:2 = 0x0 -+ * pmcsr_data:1 = 0x0 -+ * pmcsr_data:0 = 0x0 -+ */ -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, 0x00000000); -+ -+ /* GREG_JETSTR_CONFIG_3 -+ * pmcsr_data:7 = 0x0 -+ * pmcsr_data:6 = 0x0 -+ * pmcsr_data:5 = 0x0 -+ * pmcsr_data:4 = 0x0 -+ */ -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, 0x00000000); -+ -+ /* #2 Release GREG resets -+ * ip_rst_an -+ * dpa1_rst_an -+ * jetsream_reset_an -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000e00); -+ -+ /* #3 GPIO Setup -+ * GPIO 25:24 = Output -+ * GPIO Output "0" after Reset -+ */ -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); -+ -+ /* #4 Custom stuff goes in here */ -+ -+ /* #5 Disable CGU Clocks -+ * except for PHY, Jetstream, DPA1, DCS, Boot, GREG -+ * CGU_PCR_0_3: pss_mmu_clk:0 = 0x0 -+ */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_3, 0x00000006); -+ -+ /* CGU_PCR_0_4: pss_dtl2mtl_mmu_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_4, 0x00000006); -+ -+ /* CGU_PCR_0_5: pss_msi_ck:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_5, 0x00000006); -+ -+ /* CGU_PCR_0_7: pss_gpio_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_7, 0x00000006); -+ -+ /* CGU_PCR_2_1: spi_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_2_1, 0x00000006); -+ -+ /* CGU_PCR_3_2: i2c_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_2, 0x00000006); -+ -+ /* CGU_PCR_4_1: phi_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_4_1, 0x00000006); -+ -+ /* CGU_PCR_5: vip0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_5, 0x00000006); -+ -+ /* CGU_PCR_6: vip1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_6, 0x00000006); -+ -+ /* CGU_PCR_7: fgpi0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_7, 0x00000006); -+ -+ /* CGU_PCR_8: fgpi1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_8, 0x00000006); -+ -+ /* CGU_PCR_9: fgpi2_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_9, 0x00000006); -+ -+ /* CGU_PCR_10: fgpi3_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_10, 0x00000006); -+ -+ /* CGU_PCR_11: ai0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_11, 0x00000006); -+ -+ /* CGU_PCR_12: ai1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_12, 0x00000006); -+ -+ /* #6 Set GREG boot_ready = 0x1 */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); -+ -+ /* #7 Disable GREG CGU Clock */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_6, 0x00000006); -+ -+ /* End of Bootscript command ?? */ -+} -+ -+int saa716x_core_boot(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_config *config = saa716x->config; -+ -+ switch (config->boot_mode) { -+ case SAA716x_EXT_BOOT: -+ dprintk(SAA716x_DEBUG, 1, "Using External Boot from config"); -+ saa716x_ext_boot(saa716x); -+ break; -+ case SAA716x_INT_BOOT: -+ dprintk(SAA716x_DEBUG, 1, "Using Internal Boot from config"); -+ saa716x_int_boot(saa716x); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown configuration %d", config->boot_mode); -+ break; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_core_boot); -+ -+static void saa716x_bus_report(struct pci_dev *pdev, int enable) -+{ -+ u32 reg; -+ -+ pci_read_config_dword(pdev, 0x04, ®); -+ if (enable) -+ reg |= 0x00000100; /* enable SERR */ -+ else -+ reg &= 0xfffffeff; /* disable SERR */ -+ pci_write_config_dword(pdev, 0x04, reg); -+ -+ pci_read_config_dword(pdev, 0x58, ®); -+ reg &= 0xfffffffd; -+ pci_write_config_dword(pdev, 0x58, reg); -+} -+ -+int saa716x_jetpack_init(struct saa716x_dev *saa716x) -+{ -+ /* -+ * configure PHY through config space not to report -+ * non-fatal error messages to avoid problems with -+ * quirky BIOS'es -+ */ -+ saa716x_bus_report(saa716x->pdev, 0); -+ -+ /* -+ * create time out for blocks that have no clock -+ * helps with lower bitrates on FGPI -+ */ -+ SAA716x_EPWR(DCS, DCSC_CTRL, ENABLE_TIMEOUT); -+ -+ /* Reset all blocks */ -+ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); -+ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); -+ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); -+ -+ switch (saa716x->pdev->device) { -+ case SAA7162: -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ -+ msleep(10); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x03000000); /* Enable decoders */ -+ break; -+ case SAA7161: -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfeffffff); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ -+ msleep(10); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x01000000); /* Enable decoder */ -+ break; -+ case SAA7160: -+ saa716x->i2c_rate = SAA716x_I2C_RATE_100; -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown device (0x%02x)", saa716x->pdev->device); -+ return -ENODEV; -+ } -+ -+ /* General setup for MMU */ -+ SAA716x_EPWR(MMU, MMU_MODE, 0x14); -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Jetpack Successfully initialized", saa716x->pdev->device); -+ -+ return 0; -+} -+EXPORT_SYMBOL(saa716x_jetpack_init); -+ -+void saa716x_core_reset(struct saa716x_dev *saa716x) -+{ -+ dprintk(SAA716x_DEBUG, 1, "RESET Modules"); -+ -+ /* VIP */ -+ SAA716x_EPWR(VI0, VI_MODE, SOFT_RESET); -+ SAA716x_EPWR(VI1, VI_MODE, SOFT_RESET); -+ -+ /* FGPI */ -+ SAA716x_EPWR(FGPI0, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI1, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI2, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI3, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ -+ /* AIP */ -+ SAA716x_EPWR(AI0, AI_CTL, AI_RESET); -+ SAA716x_EPWR(AI1, AI_CTL, AI_RESET); -+ -+ /* BAM */ -+ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); -+ -+ /* MMU */ -+ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); -+ -+ /* MSI */ -+ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); -+} -+EXPORT_SYMBOL_GPL(saa716x_core_reset); -diff --git a/drivers/media/common/saa716x/saa716x_boot.h b/drivers/media/common/saa716x/saa716x_boot.h -new file mode 100644 -index 0000000..8102853 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_boot.h -@@ -0,0 +1,18 @@ -+#ifndef __SAA716x_BOOT_H -+#define __SAA716x_BOOT_H -+ -+#define DISABLE_TIMEOUT 0x17 -+#define ENABLE_TIMEOUT 0x16 -+ -+enum saa716x_boot_mode { -+ SAA716x_EXT_BOOT = 1, -+ SAA716x_INT_BOOT, /* GPIO[31:30] = 0x01 */ -+}; -+ -+struct saa716x_dev; -+ -+extern int saa716x_core_boot(struct saa716x_dev *saa716x); -+extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); -+extern void saa716x_core_reset(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_BOOT_H */ -diff --git a/drivers/media/common/saa716x/saa716x_budget.c b/drivers/media/common/saa716x/saa716x_budget.c -new file mode 100644 -index 0000000..6b52fc1 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_budget.c -@@ -0,0 +1,717 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_budget.h" -+#include "saa716x_gpio.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "mb86a16.h" -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "ds3103.h" -+#include "ts2022.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+#define DRIVER_NAME "SAA716x Budget" -+ -+static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ int err = 0; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed"); -+ } -+ -+ /* set default port mapping */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x04080FA9); -+ /* enable FGPI3 and FGPI1 for TS input from Port 2 and 6 */ -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x321); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail4; -+ } -+ -+ return 0; -+ -+fail4: -+ saa716x_dvb_exit(saa716x); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_budget_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ -+ saa716x_dvb_exit(saa716x); -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ u32 stat_h, stat_l, mask_h, mask_l; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ -+ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ stat_l, stat_h, mask_l, mask_h); -+ -+ if (!((stat_l & mask_l) || (stat_h & mask_h))) -+ return IRQ_NONE; -+ -+ if (stat_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); -+ -+ if (stat_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); -+ -+ saa716x_msi_event(saa716x, stat_l, stat_h); -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ -+ if (stat_l) { -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) { -+ tasklet_schedule(&saa716x->fgpi[0].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) { -+ tasklet_schedule(&saa716x->fgpi[1].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) { -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) { -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071" -+#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T" -+ -+static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp3071_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP3071, -+ .dev_type = SAA716x_DEV_TWINHAN_VP3071, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_vp3071_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028" -+#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S" -+ -+static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) -+{ -+ struct saa716x_dev *saa716x = fe->dvb->priv; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); -+ break; -+ case SEC_VOLTAGE_18: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); -+ break; -+ case SEC_VOLTAGE_OFF: -+ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+struct mb86a16_config vp1028_mb86a16_config = { -+ .demod_address = 0x08, -+ .set_voltage = vp1028_dvbs_set_voltage, -+}; -+ -+static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[1]; -+ -+ if (count == 0) { -+ -+ mutex_lock(&saa716x->adap_lock); -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count); -+ saa716x_gpio_set_output(saa716x, 10); -+ msleep(1); -+ -+ /* VP-1028 has inverted power supply control */ -+ saa716x_gpio_write(saa716x, 10, 1); /* set to standby */ -+ saa716x_gpio_write(saa716x, 10, 0); /* switch it on */ -+ msleep(100); -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count); -+ saa716x_gpio_set_output(saa716x, 12); -+ msleep(1); -+ -+ /* reset demodulator (Active LOW) */ -+ saa716x_gpio_write(saa716x, 12, 1); -+ msleep(100); -+ saa716x_gpio_write(saa716x, 12, 0); -+ msleep(100); -+ saa716x_gpio_write(saa716x, 12, 1); -+ msleep(100); -+ -+ mutex_unlock(&saa716x->adap_lock); -+ -+ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); -+ adapter->fe = mb86a16_attach(&vp1028_mb86a16_config, &i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", -+ vp1028_mb86a16_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ } -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp1028_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP1028, -+ .dev_type = SAA716x_DEV_TWINHAN_VP1028, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp1028_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002" -+#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S" -+ -+static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp6002_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP6002, -+ .dev_type = SAA716x_DEV_TWINHAN_VP6002, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp6002_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2" -+#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2" -+ -+static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_knc1_duals2_config = { -+ .model_name = SAA716x_MODEL_KNC1_DUALS2, -+ .dev_type = SAA716x_DEV_KNC1_DUALS2, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_knc1_duals2_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD" -+#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2" -+ -+static struct stv090x_config skystar2_stv090x_config = { -+ .device = STV0903, -+ .demod_mode = STV090x_SINGLE, -+ .clk_mode = STV090x_CLK_EXT, -+ -+ .xtal = 8000000, -+ .address = 0x68, -+ -+ .ts1_mode = STV090x_TSMODE_DVBCI, -+ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ -+ .repeater_level = STV090x_RPTLEVEL_16, -+ -+ .tuner_init = NULL, -+ .tuner_sleep = NULL, -+ .tuner_set_mode = NULL, -+ .tuner_set_frequency = NULL, -+ .tuner_get_frequency = NULL, -+ .tuner_set_bandwidth = NULL, -+ .tuner_get_bandwidth = NULL, -+ .tuner_set_bbgain = NULL, -+ .tuner_get_bbgain = NULL, -+ .tuner_set_refclk = NULL, -+ .tuner_get_status = NULL, -+}; -+ -+static int skystar2_set_voltage(struct dvb_frontend *fe, -+ enum fe_sec_voltage voltage) -+{ -+ int err; -+ u8 en = 0; -+ u8 sel = 0; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_OFF: -+ en = 0; -+ break; -+ -+ case SEC_VOLTAGE_13: -+ en = 1; -+ sel = 0; -+ break; -+ -+ case SEC_VOLTAGE_18: -+ en = 1; -+ sel = 1; -+ break; -+ -+ default: -+ break; -+ } -+ -+ err = skystar2_stv090x_config.set_gpio(fe, 2, 0, en, 0); -+ if (err < 0) -+ goto exit; -+ err = skystar2_stv090x_config.set_gpio(fe, 3, 0, sel, 0); -+ if (err < 0) -+ goto exit; -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg) -+{ -+ int err; -+ u8 value; -+ -+ if (arg) -+ value = 1; -+ else -+ value = 0; -+ -+ err = skystar2_stv090x_config.set_gpio(fe, 4, 0, value, 0); -+ if (err < 0) -+ goto exit; -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static struct stv6110x_config skystar2_stv6110x_config = { -+ .addr = 0x60, -+ .refclk = 16000000, -+ .clk_div = 2, -+}; -+ -+static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter, -+ int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ struct stv6110x_devctl *ctl; -+ -+ if (count < saa716x->config->adapters) { -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", -+ count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, -+ saa716x->pdev->subsystem_device); -+ -+ saa716x_gpio_set_output(saa716x, 26); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, 26, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 26, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 26, 1); -+ msleep(10); -+ -+ adapter->fe = dvb_attach(stv090x_attach, -+ &skystar2_stv090x_config, -+ &i2c->i2c_adapter, -+ STV090x_DEMODULATOR_0); -+ -+ if (adapter->fe) { -+ dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x", -+ skystar2_stv090x_config.address); -+ } else { -+ goto exit; -+ } -+ -+ adapter->fe->ops.set_voltage = skystar2_set_voltage; -+ adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost; -+ -+ ctl = dvb_attach(stv6110x_attach, -+ adapter->fe, -+ &skystar2_stv6110x_config, -+ &i2c->i2c_adapter); -+ -+ if (ctl) { -+ dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x", -+ skystar2_stv6110x_config.addr); -+ -+ skystar2_stv090x_config.tuner_init = ctl->tuner_init; -+ skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep; -+ skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; -+ skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; -+ skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; -+ skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; -+ skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; -+ skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; -+ skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; -+ skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; -+ skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status; -+ -+ /* call the init function once to initialize -+ tuner's clock output divider and demod's -+ master clock */ -+ if (adapter->fe->ops.init) -+ adapter->fe->ops.init(adapter->fe); -+ } else { -+ goto exit; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config skystar2_express_hd_config = { -+ .model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD, -+ .dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = skystar2_express_hd_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 1, /* using FGPI 1 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+static struct ds3103_config s472_ds3103_config = { -+ .demod_address = 0x68, -+ .ci_mode = 1, -+}; -+ -+static int saa716x_s472_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[1]; -+ -+ if (count != 0) -+ return 0; -+ -+ dprintk(SAA716x_ERROR, 1, "Probing for DS3103 (DVB-S/S2)"); -+ adapter->fe = dvb_attach(ds3103_attach, &s472_ds3103_config, -+ &i2c->i2c_adapter); -+ -+ if (adapter->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "found DS3103 DVB-S/S2 frontend @0x%02x", -+ s472_ds3103_config.demod_address); -+ if (NULL == dvb_attach(ts2022_attach, adapter->fe, 0x60, &i2c->i2c_adapter)) -+ dprintk(SAA716x_ERROR, 1, "ts2022 attach failed"); -+ else -+ dprintk(SAA716x_ERROR, 1, "ts2022 attached!"); -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ -+} -+ -+static struct saa716x_config tevii_s472_config = { -+ .model_name = "TeVii S472 DVB-S2", -+ .dev_type = "DVB-S/S2", -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_s472_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 1, /* using FGPI 1 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+static struct pci_device_id saa716x_budget_pci_table[] = { -+ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */ -+ MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config), -+ MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config), -+ MAKE_ENTRY(TEVII, TEVII_S472, SAA7160, &tevii_s472_config), -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table); -+ -+static struct pci_driver saa716x_budget_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_budget_pci_table, -+ .probe = saa716x_budget_pci_probe, -+ .remove = saa716x_budget_pci_remove, -+}; -+ -+static int saa716x_budget_init(void) -+{ -+ return pci_register_driver(&saa716x_budget_pci_driver); -+} -+ -+static void saa716x_budget_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_budget_pci_driver); -+} -+ -+module_init(saa716x_budget_init); -+module_exit(saa716x_budget_exit); -+ -+MODULE_DESCRIPTION("SAA716x Budget driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_budget.h b/drivers/media/common/saa716x/saa716x_budget.h -new file mode 100644 -index 0000000..d6b8c46 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_budget.h -@@ -0,0 +1,17 @@ -+#ifndef __SAA716x_BUDGET_H -+#define __SAA716x_BUDGET_H -+ -+#define TWINHAN_TECHNOLOGIES 0x1822 -+#define TWINHAN_VP_3071 0x0039 -+#define TWINHAN_VP_1028 0x0044 -+#define TWINHAN_VP_6002 0x0047 -+ -+#define KNC_One 0x1894 -+#define KNC_Dual_S2 0x0110 -+ -+#define TECHNISAT 0x1AE4 -+#define SKYSTAR2_EXPRESS_HD 0x0700 -+#define TEVII 0x9022 -+#define TEVII_S472 0xd472 -+ -+#endif /* __SAA716x_BUDGET_H */ -diff --git a/drivers/media/common/saa716x/saa716x_cgu.c b/drivers/media/common/saa716x/saa716x_cgu.c -new file mode 100644 -index 0000000..a0ffb04 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_cgu.c -@@ -0,0 +1,539 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_cgu_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+u32 cgu_clk[14] = { -+ CGU_FDC_0, -+ CGU_FDC_1, -+ CGU_FDC_2, -+ CGU_FDC_3, -+ CGU_FDC_4, -+ CGU_FDC_5, -+ CGU_FDC_6, -+ CGU_FDC_7, -+ CGU_FDC_8, -+ CGU_FDC_9, -+ CGU_FDC_10, -+ CGU_FDC_11, -+ CGU_FDC_12, -+ CGU_FDC_13 -+}; -+ -+char *clk_desc[14] = { -+ "Clk PSS", -+ "Clk DCS", -+ "Clk SPI", -+ "Clk I2C/Boot", -+ "Clk PHI", -+ "Clk VI0", -+ "Clk VI1", -+ "Clk FGPI0", -+ "Clk FGPI1", -+ "Clk FGPI2", -+ "Clk FGPI3", -+ "Clk AI0", -+ "Clk AI1", -+ "Clk Phy" -+}; -+ -+int saa716x_getbootscript_setup(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 i; -+ s8 N = 0; -+ s16 M = 0; -+ -+ SAA716x_EPWR(CGU, CGU_PCR_0_6, CGU_PCR_RUN); /* GREG */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_3, CGU_PCR_RUN); /* PSS_MMU */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_4, CGU_PCR_RUN); /* PSS_DTL2MTL */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_5, CGU_PCR_RUN); /* MSI */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_2, CGU_PCR_RUN); /* I2C */ -+ SAA716x_EPWR(CGU, CGU_PCR_4_1, CGU_PCR_RUN); /* PHI */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_7, CGU_PCR_RUN); /* GPIO */ -+ SAA716x_EPWR(CGU, CGU_PCR_2_1, CGU_PCR_RUN); /* SPI */ -+ SAA716x_EPWR(CGU, CGU_PCR_1_1, CGU_PCR_RUN); /* DCS */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_1, CGU_PCR_RUN); /* BOOT */ -+ -+ /* get all dividers */ -+ for (i = 0; i < CGU_CLKS; i++) { -+ cgu->clk_boot_div[i] = SAA716x_EPRD(CGU, cgu_clk[i]); -+ cgu->clk_curr_div[i] = cgu->clk_boot_div[i]; -+ -+ N = (cgu->clk_boot_div[i] >> 11) & 0xff; -+ N *= -1; -+ M = ((cgu->clk_boot_div[i] >> 3) & 0xff) + N; -+ -+ if (M) -+ cgu->clk_freq[i] = (u32 ) N * PLL_FREQ / (u32 ) M; -+ else -+ cgu->clk_freq[i] = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Domain %d: %s <0x%02x> Divider: 0x%x --> N=%d, M=%d, freq=%d", -+ i, clk_desc[i], cgu_clk[i], cgu->clk_boot_div[i], N, M, cgu->clk_freq[i]); -+ } -+ /* store clock settings */ -+ cgu->clk_vi_0[0] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_0[1] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_0[2] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_1[0] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ cgu->clk_vi_1[1] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ cgu->clk_vi_1[2] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ -+ return 0; -+} -+ -+int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 delay = 1; -+ -+ switch (port) { -+ case PORT_VI0_VIDEO: -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(5); -+ break; -+ -+ case PORT_VI0_VBI: -+ cgu->clk_int_port[PORT_VI0_VBI] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(5); -+ break; -+ -+ case PORT_VI1_VIDEO: -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(6); -+ break; -+ -+ case PORT_VI1_VBI: -+ cgu->clk_int_port[PORT_VI1_VBI] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(6); -+ break; -+ -+ case PORT_FGPI0: -+ cgu->clk_int_port[PORT_FGPI0] = 1; -+ SAA716x_CGU_CLKRUN(7); -+ break; -+ -+ case PORT_FGPI1: -+ cgu->clk_int_port[PORT_FGPI1] = 1; -+ SAA716x_CGU_CLKRUN(8); -+ break; -+ -+ case PORT_FGPI2: -+ cgu->clk_int_port[PORT_FGPI2] = 1; -+ SAA716x_CGU_CLKRUN(9); -+ break; -+ -+ case PORT_FGPI3: -+ cgu->clk_int_port[PORT_FGPI3] = 1; -+ SAA716x_CGU_CLKRUN(10); -+ break; -+ -+ case PORT_AI0: -+ cgu->clk_int_port[PORT_AI0] = 1; -+ SAA716x_CGU_CLKRUN(11); -+ break; -+ -+ case PORT_AI1: -+ cgu->clk_int_port[PORT_AI1] = 1; -+ SAA716x_CGU_CLKRUN(12); -+ break; -+ -+ case PORT_ALL: -+ SAA716x_CGU_CLKRUN(5); -+ SAA716x_CGU_CLKRUN(6); -+ SAA716x_CGU_CLKRUN(7); -+ SAA716x_CGU_CLKRUN(8); -+ SAA716x_CGU_CLKRUN(9); -+ SAA716x_CGU_CLKRUN(10); -+ SAA716x_CGU_CLKRUN(11); -+ SAA716x_CGU_CLKRUN(12); -+ -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; -+ cgu->clk_int_port[PORT_VI0_VBI] = 1; -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; -+ cgu->clk_int_port[PORT_VI1_VBI] = 1; -+ cgu->clk_int_port[PORT_FGPI0] = 1; -+ cgu->clk_int_port[PORT_FGPI1] = 1; -+ cgu->clk_int_port[PORT_FGPI2] = 1; -+ cgu->clk_int_port[PORT_FGPI3] = 1; -+ cgu->clk_int_port[PORT_AI0] = 1; -+ cgu->clk_int_port[PORT_AI1] = 1; -+ break; -+ -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); -+ delay = 0; -+ break; -+ } -+ -+ /* wait for PLL */ -+ if (delay) -+ msleep(1); -+ -+ return 0; -+} -+ -+int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 delay = 1; -+ -+ switch (port) { -+ case PORT_VI0_VIDEO: -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI0_VBI: -+ cgu->clk_int_port[PORT_VI0_VBI] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI1_VIDEO: -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI1_VBI: -+ cgu->clk_int_port[PORT_VI1_VBI] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI0: -+ cgu->clk_int_port[PORT_FGPI0] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_7, 0x4); /* FGPI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_7, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI1: -+ cgu->clk_int_port[PORT_FGPI1] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_8, 0x5); /* FGPI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_8, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI2: -+ cgu->clk_int_port[PORT_FGPI2] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_9, 0x6); /* FGPI 2 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_9, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI3: -+ cgu->clk_int_port[PORT_FGPI3] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_10, 0x7); /* FGPI 3 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_10, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_AI0: -+ cgu->clk_int_port[PORT_AI0] = 1; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_11, 0x8); /* AI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_11, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_AI1: -+ cgu->clk_int_port[PORT_AI1] = 1; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_12, 0x9); /* AI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_12, 0x0); /* disable divider */ -+ break; -+ -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); -+ delay = 0; -+ break; -+ -+ } -+ -+ if (delay) -+ msleep(1); -+ -+ return 0; -+} -+ -+int saa716x_get_clk(struct saa716x_dev *saa716x, -+ enum saa716x_clk_domain domain, -+ u32 *frequency) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ switch (domain) { -+ case CLK_DOMAIN_PSS: -+ case CLK_DOMAIN_DCS: -+ case CLK_DOMAIN_SPI: -+ case CLK_DOMAIN_I2C: -+ case CLK_DOMAIN_PHI: -+ case CLK_DOMAIN_VI0: -+ case CLK_DOMAIN_VI1: -+ case CLK_DOMAIN_FGPI0: -+ case CLK_DOMAIN_FGPI1: -+ case CLK_DOMAIN_FGPI2: -+ case CLK_DOMAIN_FGPI3: -+ case CLK_DOMAIN_AI0: -+ case CLK_DOMAIN_AI1: -+ case CLK_DOMAIN_PHY: -+ *frequency = cgu->clk_freq[domain]; -+ break; -+ -+ case CLK_DOMAIN_VI0VBI: -+ *frequency = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ break; -+ -+ case CLK_DOMAIN_VI1VBI: -+ *frequency =cgu->clk_freq[CLK_DOMAIN_VI1]; -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Error Clock domain <%02x>", domain); -+ break; -+ } -+ -+ return 0; -+} -+ -+int saa716x_set_clk(struct saa716x_dev *saa716x, -+ enum saa716x_clk_domain domain, -+ u32 frequency) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u32 M = 1, N = 1, reset, i; -+ s8 N_tmp, M_tmp, sub, add, lsb; -+ -+ -+ if (cgu->clk_freq_min > frequency) -+ frequency = cgu->clk_freq_min; -+ -+ if (cgu->clk_freq_max < frequency) -+ frequency = cgu->clk_freq_max; -+ -+ switch (domain) { -+ case CLK_DOMAIN_PSS: -+ case CLK_DOMAIN_DCS: -+ case CLK_DOMAIN_SPI: -+ case CLK_DOMAIN_I2C: -+ case CLK_DOMAIN_PHI: -+ case CLK_DOMAIN_FGPI0: -+ case CLK_DOMAIN_FGPI1: -+ case CLK_DOMAIN_FGPI2: -+ case CLK_DOMAIN_FGPI3: -+ case CLK_DOMAIN_AI0: -+ case CLK_DOMAIN_AI1: -+ case CLK_DOMAIN_PHY: -+ -+ if (frequency == cgu->clk_freq[domain]) -+ return 0; /* same frequency */ -+ break; -+ -+ case CLK_DOMAIN_VI0: -+ -+ if (frequency == cgu->clk_vi_0[1]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_0[0]) { -+ cgu->clk_vi_0[1] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_0[2]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_0[1] = frequency; -+ -+ if (frequency != cgu->clk_vi_0[2]) -+ return 0; -+ -+ } -+ break; -+ -+ case CLK_DOMAIN_VI1: -+ if (frequency == cgu->clk_vi_1[1]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_1[0]) { -+ cgu->clk_vi_1[1] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_1[2]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_1[1] = frequency; -+ -+ if (frequency != cgu->clk_vi_1[2]) -+ return 0; -+ -+ } -+ break; -+ -+ case CLK_DOMAIN_VI0VBI: -+ if (frequency == cgu->clk_vi_0[2]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_0[0]) { -+ cgu->clk_vi_0[2] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_0[1]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_0[2] = frequency; /* store */ -+ -+ if (frequency != cgu->clk_vi_0[1]) -+ return 0; -+ -+ } -+ domain = CLK_DOMAIN_VI0; /* change domain */ -+ break; -+ -+ case CLK_DOMAIN_VI1VBI: -+ if (frequency == cgu->clk_vi_1[2]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_1[0]) { -+ cgu->clk_vi_1[2] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_1[1]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_1[2] = frequency; /* store */ -+ -+ if (frequency != cgu->clk_vi_1[1]) -+ return 0; -+ -+ } -+ domain = CLK_DOMAIN_VI1; /* change domain */ -+ break; -+ } -+ -+ /* calculate divider */ -+ do { -+ M = (N * PLL_FREQ) / frequency; -+ if (M == 0) -+ N++; -+ -+ } while (M == 0); -+ -+ /* calculate frequency */ -+ cgu->clk_freq[domain] = (N * PLL_FREQ) / M; -+ -+ N_tmp = N & 0xff; -+ M_tmp = M & 0xff; -+ sub = -N_tmp; -+ add = M_tmp - N_tmp; -+ lsb = 4; /* run */ -+ -+ if (((10 * N) / M) < 5) -+ lsb |= 1; /* stretch */ -+ -+ /* store new divider */ -+ cgu->clk_curr_div[domain] = sub & 0xff; -+ cgu->clk_curr_div[domain] <<= 8; -+ cgu->clk_curr_div[domain] = add & 0xff; -+ cgu->clk_curr_div[domain] <<= 3; -+ cgu->clk_curr_div[domain] |= lsb; -+ -+ dprintk(SAA716x_DEBUG, 1, "Domain <0x%02x> Frequency <%d> Set Freq <%d> N=%d M=%d Divider <0x%02x>", -+ domain, -+ frequency, -+ cgu->clk_freq[domain], -+ N, -+ M, -+ cgu->clk_curr_div[domain]); -+ -+ reset = 0; -+ -+ /* Reset */ -+ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain] | 0x2); -+ -+ /* Reset disable */ -+ for (i = 0; i < 1000; i++) { -+ msleep(10); -+ reset = SAA716x_EPRD(CGU, cgu_clk[domain]); -+ -+ if (cgu->clk_curr_div[domain == reset]) -+ break; -+ } -+ -+ if (cgu->clk_curr_div[domain] != reset) -+ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain]); -+ -+ return 0; -+} -+ -+int saa716x_cgu_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ cgu->clk_freq_min = PLL_FREQ / 255; -+ if (PLL_FREQ > (cgu->clk_freq_min * 255)) -+ cgu->clk_freq_min++; -+ -+ cgu->clk_freq_max = PLL_FREQ; -+ -+ saa716x_getbootscript_setup(saa716x); -+ saa716x_set_clk_internal(saa716x, PORT_ALL); -+ -+ return 0; -+} -+EXPORT_SYMBOL(saa716x_cgu_init); -diff --git a/drivers/media/common/saa716x/saa716x_cgu.h b/drivers/media/common/saa716x/saa716x_cgu.h -new file mode 100644 -index 0000000..5353cf2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_cgu.h -@@ -0,0 +1,61 @@ -+#ifndef __SAA716x_CGU_H -+#define __SAA716x_CGU_H -+ -+#define PLL_FREQ 2500 -+ -+#define SAA716x_CGU_CLKRUN(__reg) do { \ -+ SAA716x_EPWR(CGU, CGU_PCR_##__reg, CGU_PCR_RUN); /* Run */ \ -+ SAA716x_EPWR(CGU, CGU_SCR_##__reg, CGU_SCR_ENF1); /* Switch */ \ -+ SAA716x_EPWR(CGU, CGU_FS1_##__reg, 0x00000000); /* PLL Clk */ \ -+ SAA716x_EPWR(CGU, CGU_ESR_##__reg, CGU_ESR_FD_EN); /* Frac div */ \ -+} while (0) -+ -+enum saa716x_clk_domain { -+ CLK_DOMAIN_PSS = 0, -+ CLK_DOMAIN_DCS = 1, -+ CLK_DOMAIN_SPI = 2, -+ CLK_DOMAIN_I2C = 3, -+ CLK_DOMAIN_PHI = 4, -+ CLK_DOMAIN_VI0 = 5, -+ CLK_DOMAIN_VI1 = 6, -+ CLK_DOMAIN_FGPI0 = 7, -+ CLK_DOMAIN_FGPI1 = 8, -+ CLK_DOMAIN_FGPI2 = 9, -+ CLK_DOMAIN_FGPI3 = 10, -+ CLK_DOMAIN_AI0 = 11, -+ CLK_DOMAIN_AI1 = 12, -+ CLK_DOMAIN_PHY = 13, -+ CLK_DOMAIN_VI0VBI = 14, -+ CLK_DOMAIN_VI1VBI = 15 -+}; -+ -+#define PORT_VI0_VIDEO 0 -+#define PORT_VI0_VBI 2 -+#define PORT_VI1_VIDEO 3 -+#define PORT_VI1_VBI 5 -+#define PORT_FGPI0 6 -+#define PORT_FGPI1 7 -+#define PORT_FGPI2 8 -+#define PORT_FGPI3 9 -+#define PORT_AI0 10 -+#define PORT_AI1 11 -+#define PORT_ALL 12 -+ -+#define CGU_CLKS 14 -+ -+struct saa716x_cgu { -+ u8 clk_int_port[12]; -+ u32 clk_vi_0[3]; -+ u32 clk_vi_1[3]; -+ u32 clk_boot_div[CGU_CLKS]; -+ u32 clk_curr_div[CGU_CLKS]; -+ u32 clk_freq[CGU_CLKS]; -+ u32 clk_freq_min; -+ u32 clk_freq_max; -+}; -+ -+extern int saa716x_cgu_init(struct saa716x_dev *saa716x); -+extern int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port); -+extern int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port); -+ -+#endif /* __SAA716x_CGU_H */ -diff --git a/drivers/media/common/saa716x/saa716x_cgu_reg.h b/drivers/media/common/saa716x/saa716x_cgu_reg.h -new file mode 100644 -index 0000000..f7d82ae ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_cgu_reg.h -@@ -0,0 +1,178 @@ -+#ifndef __SAA716x_CGU_REG_H -+#define __SAA716x_CGU_REG_H -+ -+/* -------------- CGU Registers -------------- */ -+ -+#define CGU_SCR_0 0x000 -+#define CGU_SCR_1 0x004 -+#define CGU_SCR_2 0x008 -+#define CGU_SCR_3 0x00c -+#define CGU_SCR_4 0x010 -+#define CGU_SCR_5 0x014 -+#define CGU_SCR_6 0x018 -+#define CGU_SCR_7 0x01c -+#define CGU_SCR_8 0x020 -+#define CGU_SCR_9 0x024 -+#define CGU_SCR_10 0x028 -+#define CGU_SCR_11 0x02c -+#define CGU_SCR_12 0x030 -+#define CGU_SCR_13 0x034 -+#define CGU_SCR_STOP (0x00000001 << 3) -+#define CGU_SCR_RESET (0x00000001 << 2) -+#define CGU_SCR_ENF2 (0x00000001 << 1) -+#define CGU_SCR_ENF1 (0x00000001 << 0) -+ -+#define CGU_FS1_0 0x038 -+#define CGU_FS1_1 0x03c -+#define CGU_FS1_2 0x040 -+#define CGU_FS1_3 0x044 -+#define CGU_FS1_4 0x048 -+#define CGU_FS1_5 0x04c -+#define CGU_FS1_6 0x050 -+#define CGU_FS1_7 0x054 -+#define CGU_FS1_8 0x058 -+#define CGU_FS1_9 0x05c -+#define CGU_FS1_10 0x060 -+#define CGU_FS1_11 0x064 -+#define CGU_FS1_12 0x068 -+#define CGU_FS1_13 0x06c -+#define CGU_FS1_PLL (0x00000000 << 0) -+ -+ -+#define CGU_FS2_0 0x070 -+#define CGU_FS2_1 0x074 -+#define CGU_FS2_2 0x078 -+#define CGU_FS2_3 0x07c -+#define CGU_FS2_4 0x080 -+#define CGU_FS2_5 0x084 -+#define CGU_FS2_6 0x088 -+#define CGU_FS2_7 0x08c -+#define CGU_FS2_8 0x090 -+#define CGU_FS2_9 0x094 -+#define CGU_FS2_10 0x098 -+#define CGU_FS2_11 0x09c -+#define CGU_FS2_12 0x0a0 -+#define CGU_FS2_13 0x0a4 -+ -+#define CGU_SSR_0 0x0a8 -+#define CGU_SSR_1 0x0ac -+#define CGU_SSR_2 0x0b0 -+#define CGU_SSR_3 0x0b4 -+#define CGU_SSR_4 0x0b8 -+#define CGU_SSR_5 0x0bc -+#define CGU_SSR_6 0x0c0 -+#define CGU_SSR_7 0x0c4 -+#define CGU_SSR_8 0x0c8 -+#define CGU_SSR_9 0x0cc -+#define CGU_SSR_10 0x0d0 -+#define CGU_SSR_11 0x0d4 -+#define CGU_SSR_12 0x0d8 -+#define CGU_SSR_13 0x0dc -+ -+#define CGU_PCR_0_0 0x0e0 -+#define CGU_PCR_0_1 0x0e4 -+#define CGU_PCR_0_2 0x0e8 -+#define CGU_PCR_0_3 0x0ec -+#define CGU_PCR_0_4 0x0f0 -+#define CGU_PCR_0_5 0x0f4 -+#define CGU_PCR_0_6 0x0f8 -+#define CGU_PCR_0_7 0x0fc -+#define CGU_PCR_1_0 0x100 -+#define CGU_PCR_1_1 0x104 -+#define CGU_PCR_2_0 0x108 -+#define CGU_PCR_2_1 0x10c -+#define CGU_PCR_3_0 0x110 -+#define CGU_PCR_3_1 0x114 -+#define CGU_PCR_3_2 0x118 -+#define CGU_PCR_4_0 0x11c -+#define CGU_PCR_4_1 0x120 -+#define CGU_PCR_5 0x124 -+#define CGU_PCR_6 0x128 -+#define CGU_PCR_7 0x12c -+#define CGU_PCR_8 0x130 -+#define CGU_PCR_9 0x134 -+#define CGU_PCR_10 0x138 -+#define CGU_PCR_11 0x13c -+#define CGU_PCR_12 0x140 -+#define CGU_PCR_13 0x144 -+#define CGU_PCR_WAKE_EN (0x00000001 << 2) -+#define CGU_PCR_AUTO (0x00000001 << 1) -+#define CGU_PCR_RUN (0x00000001 << 0) -+ -+ -+#define CGU_PSR_0_0 0x148 -+#define CGU_PSR_0_1 0x14c -+#define CGU_PSR_0_2 0x150 -+#define CGU_PSR_0_3 0x154 -+#define CGU_PSR_0_4 0x158 -+#define CGU_PSR_0_5 0x15c -+#define CGU_PSR_0_6 0x160 -+#define CGU_PSR_0_7 0x164 -+#define CGU_PSR_1_0 0x168 -+#define CGU_PSR_1_1 0x16c -+#define CGU_PSR_2_0 0x170 -+#define CGU_PSR_2_1 0x174 -+#define CGU_PSR_3_0 0x178 -+#define CGU_PSR_3_1 0x17c -+#define CGU_PSR_3_2 0x180 -+#define CGU_PSR_4_0 0x184 -+#define CGU_PSR_4_1 0x188 -+#define CGU_PSR_5 0x18c -+#define CGU_PSR_6 0x190 -+#define CGU_PSR_7 0x194 -+#define CGU_PSR_8 0x198 -+#define CGU_PSR_9 0x19c -+#define CGU_PSR_10 0x1a0 -+#define CGU_PSR_11 0x1a4 -+#define CGU_PSR_12 0x1a8 -+#define CGU_PSR_13 0x1ac -+ -+#define CGU_ESR_0_0 0x1b0 -+#define CGU_ESR_0_1 0x1b4 -+#define CGU_ESR_0_2 0x1b8 -+#define CGU_ESR_0_3 0x1bc -+#define CGU_ESR_0_4 0x1c0 -+#define CGU_ESR_0_5 0x1c4 -+#define CGU_ESR_0_6 0x1c8 -+#define CGU_ESR_0_7 0x1cc -+#define CGU_ESR_1_0 0x1d0 -+#define CGU_ESR_1_1 0x1d4 -+#define CGU_ESR_2_0 0x1d8 -+#define CGU_ESR_2_1 0x1dc -+#define CGU_ESR_3_0 0x1e0 -+#define CGU_ESR_3_1 0x1e4 -+#define CGU_ESR_3_2 0x1e8 -+#define CGU_ESR_4_0 0x1ec -+#define CGU_ESR_4_1 0x1f0 -+#define CGU_ESR_5 0x1f4 -+#define CGU_ESR_6 0x1f8 -+#define CGU_ESR_7 0x1fc -+#define CGU_ESR_8 0x200 -+#define CGU_ESR_9 0x204 -+#define CGU_ESR_10 0x208 -+#define CGU_ESR_11 0x20c -+#define CGU_ESR_12 0x210 -+#define CGU_ESR_13 0x214 -+#define CGU_ESR_FD_EN (0x00000001 << 0) -+ -+#define CGU_FDC_0 0x218 -+#define CGU_FDC_1 0x21c -+#define CGU_FDC_2 0x220 -+#define CGU_FDC_3 0x224 -+#define CGU_FDC_4 0x228 -+#define CGU_FDC_5 0x22c -+#define CGU_FDC_6 0x230 -+#define CGU_FDC_7 0x234 -+#define CGU_FDC_8 0x238 -+#define CGU_FDC_9 0x23c -+#define CGU_FDC_10 0x240 -+#define CGU_FDC_11 0x244 -+#define CGU_FDC_12 0x248 -+#define CGU_FDC_13 0x24c -+#define CGU_FDC_STRETCH (0x00000001 << 0) -+#define CGU_FDC_RESET (0x00000001 << 1) -+#define CGU_FDC_RUN1 (0x00000001 << 2) -+#define CGU_FDC_MADD (0x000000ff << 3) -+#define CGU_FDC_MSUB (0x000000ff << 11) -+ -+#endif /* __SAA716x_CGU_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_dcs_reg.h b/drivers/media/common/saa716x/saa716x_dcs_reg.h -new file mode 100644 -index 0000000..26dba68 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dcs_reg.h -@@ -0,0 +1,56 @@ -+#ifndef __SAA716x_DCS_REG_H -+#define __SAA716x_DCS_REG_H -+ -+/* -------------- DCS Registers -------------- */ -+ -+#define DCSC_CTRL 0x000 -+#define DCSC_SEL_PLLDI (0x03ffffff << 5) -+#define DCSC_TOUT_SEL (0x0000000f << 1) -+#define DCSC_TOUT_OFF (0x00000001 << 0) -+ -+#define DCSC_ADDR 0x00c -+#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) -+ -+#define DCSC_STAT 0x010 -+#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) -+#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) -+#define DCSC_ERR_TOUT_READ (0x00000001 << 8) -+#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) -+#define DCSC_ERR_ACK (0x00000001 << 1) -+ -+#define DCSC_FEATURES 0x040 -+#define DCSC_UNIQUE_ID (0x00000007 << 16) -+#define DCSC_SECURITY (0x00000001 << 14) -+#define DCSC_NUM_BASE_REGS (0x00000003 << 11) -+#define DCSC_NUM_TARGETS (0x0000001f << 5) -+#define DCSC_NUM_INITIATORS (0x0000001f << 0) -+ -+#define DCSC_BASE_REG0 0x100 -+#define DCSC_BASE_N_REG (0x00000fff << 20) -+ -+#define DCSC_INT_CLR_ENABLE 0xfd8 -+#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_ENABLE 0xfdc -+#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_STATUS 0xfe0 -+#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) -+#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_ENABLE 0xfe4 -+#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_CLR_STATUS 0xfe8 -+#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_STATUS 0xfec -+#define DCSC_INT_SET_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ERROR (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_DCS_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_dma.c b/drivers/media/common/saa716x/saa716x_dma.c -new file mode 100644 -index 0000000..21d1dd8 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dma.c -@@ -0,0 +1,307 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "saa716x_dma.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+/* Allocates one page of memory, which is stores the data of one -+ * 716x page table. The result gets stored in the passed DMA buffer -+ * structure. -+ */ -+static int saa716x_allocate_ptable(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "SG Page table allocate"); -+ dmabuf->mem_ptab_virt = (void *) __get_free_page(GFP_KERNEL); -+ -+ if (dmabuf->mem_ptab_virt == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Out of pages !"); -+ return -ENOMEM; -+ } -+ -+ dmabuf->mem_ptab_phys = dma_map_single(&pdev->dev, -+ dmabuf->mem_ptab_virt, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+ if (dmabuf->mem_ptab_phys == 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: map memory failed !"); -+ return -ENOMEM; -+ } -+ -+ BUG_ON(!(((unsigned long) dmabuf->mem_ptab_phys % SAA716x_PAGE_SIZE) == 0)); -+ -+ return 0; -+} -+ -+static void saa716x_free_ptable(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG Page table free"); -+ -+ /* free physical PCI memory */ -+ if (dmabuf->mem_ptab_phys != 0) { -+ dma_unmap_single(&pdev->dev, -+ dmabuf->mem_ptab_phys, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+ dmabuf->mem_ptab_phys = 0; -+ } -+ -+ /* free kernel memory */ -+ if (dmabuf->mem_ptab_virt != NULL) { -+ free_page((unsigned long) dmabuf->mem_ptab_virt); -+ dmabuf->mem_ptab_virt = NULL; -+ } -+} -+ -+static void saa716x_dmabuf_sgfree(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG free"); -+ -+ dmabuf->mem_virt = NULL; -+ if (dmabuf->mem_virt_noalign != NULL) { -+ if (dmabuf->dma_type == SAA716x_DMABUF_INT) -+ vfree(dmabuf->mem_virt_noalign); -+ -+ dmabuf->mem_virt_noalign = NULL; -+ } -+ -+ if (dmabuf->sg_list != NULL) { -+ kfree(dmabuf->sg_list); -+ dmabuf->sg_list = NULL; -+ } -+} -+ -+/* -+ * Create a SG, when an allocated buffer is passed to it, -+ * otherwise the needed memory gets allocated by itself -+ */ -+static int saa716x_dmabuf_sgalloc(struct saa716x_dmabuf *dmabuf, void *buf, int size) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct scatterlist *list; -+ struct page *pg; -+ -+ int i, pages; -+ -+ BUG_ON(!(size > 0)); -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG allocate"); -+ -+ if ((size % SAA716x_PAGE_SIZE) != 0) /* calculate required pages */ -+ pages = size / SAA716x_PAGE_SIZE + 1; -+ else -+ pages = size / SAA716x_PAGE_SIZE; -+ -+ /* Allocate memory for SG list */ -+ dmabuf->sg_list = kzalloc(sizeof (struct scatterlist) * pages, GFP_KERNEL); -+ if (dmabuf->sg_list == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for scatterlist."); -+ return -ENOMEM; -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SG table"); -+ sg_init_table(dmabuf->sg_list, pages); -+ -+ if (buf == NULL) { -+ -+ /* allocate memory, unaligned */ -+ dmabuf->mem_virt_noalign = vmalloc((pages + 1) * SAA716x_PAGE_SIZE); -+ if (dmabuf->mem_virt_noalign == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for buffer"); -+ return -ENOMEM; -+ } -+ -+ /* align memory to page */ -+ dmabuf->mem_virt = (void *) PAGE_ALIGN (((unsigned long) dmabuf->mem_virt_noalign)); -+ -+ BUG_ON(!((((unsigned long) dmabuf->mem_virt) % SAA716x_PAGE_SIZE) == 0)); -+ } else { -+ dmabuf->mem_virt = buf; -+ } -+ -+ dmabuf->list_len = pages; /* scatterlist length */ -+ list = dmabuf->sg_list; -+ -+ dprintk(SAA716x_DEBUG, 1, "Allocating SG pages"); -+ for (i = 0; i < pages; i++) { -+ if (buf == NULL) -+ pg = vmalloc_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); -+ else -+ pg = virt_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); -+ -+ BUG_ON(pg == NULL); -+ sg_set_page(&list[i], pg, SAA716x_PAGE_SIZE, 0); -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "Done!"); -+ return 0; -+} -+ -+/* Fill the "page table" page with the pointers to the specified SG buffer */ -+static void saa716x_dmabuf_sgpagefill(struct saa716x_dmabuf *dmabuf, struct scatterlist *sg_list, int pages, int offset) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ struct scatterlist *sg_cur; -+ -+ u32 *page; -+ int i, j, k = 0; -+ dma_addr_t addr = 0; -+ -+ BUG_ON(dmabuf == NULL); -+ BUG_ON(sg_list == NULL); -+ BUG_ON(pages == 0); -+ dprintk(SAA716x_DEBUG, 1, "SG page fill"); -+ -+ /* make page writable for the PC */ -+ dma_sync_single_for_cpu(&pdev->dev, dmabuf->mem_ptab_phys, SAA716x_PAGE_SIZE, DMA_TO_DEVICE); -+ page = dmabuf->mem_ptab_virt; -+ -+ /* create page table */ -+ for (i = 0; i < pages; i++) { -+ sg_cur = &sg_list[i]; -+ BUG_ON(!(((sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE) == 0)); -+ -+ if (i == 0) -+ dmabuf->offset = (sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE; -+ else -+ BUG_ON(sg_cur->offset != 0); -+ -+ for (j = 0; (j * SAA716x_PAGE_SIZE) < sg_dma_len(sg_cur); j++) { -+ -+ if ((offset + sg_cur->offset) >= SAA716x_PAGE_SIZE) { -+ offset -= SAA716x_PAGE_SIZE; -+ continue; -+ } -+ -+ addr = ((u64)sg_dma_address(sg_cur)) + (j * SAA716x_PAGE_SIZE) - sg_cur->offset; -+ -+ BUG_ON(addr == 0); -+ page[k * 2] = (u32 )addr; /* Low */ -+ page[k * 2 + 1] = (u32 )(((u64) addr) >> 32); /* High */ -+ BUG_ON(page[k * 2] % SAA716x_PAGE_SIZE); -+ k++; -+ } -+ } -+ -+ for (; k < (SAA716x_PAGE_SIZE / 8); k++) { -+ page[k * 2] = (u32 ) addr; -+ page[k * 2 + 1] = (u32 ) (((u64 ) addr) >> 32); -+ } -+ -+ /* make "page table" page writable for the PC */ -+ dma_sync_single_for_device(&pdev->dev, -+ dmabuf->mem_ptab_phys, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+} -+ -+void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "DMABUF sync DEVICE"); -+ BUG_ON(dmabuf->sg_list == NULL); -+ -+ dma_sync_sg_for_device(&pdev->dev, -+ dmabuf->sg_list, -+ dmabuf->list_len, -+ DMA_FROM_DEVICE); -+ -+} -+ -+void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "DMABUF sync CPU"); -+ BUG_ON(dmabuf->sg_list == NULL); -+ -+ dma_sync_sg_for_cpu(&pdev->dev, -+ dmabuf->sg_list, -+ dmabuf->list_len, -+ DMA_FROM_DEVICE); -+} -+ -+/* Allocates a DMA buffer for the specified external linear buffer. */ -+int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf, int size) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ int ret; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(dmabuf == NULL); -+ BUG_ON(! (size > 0)); -+ -+ dmabuf->dma_type = SAA716x_DMABUF_INT; -+ -+ dmabuf->mem_virt_noalign = NULL; -+ dmabuf->mem_virt = NULL; -+ dmabuf->mem_ptab_phys = 0; -+ dmabuf->mem_ptab_virt = NULL; -+ -+ dmabuf->list_len = 0; -+ dmabuf->saa716x = saa716x; -+ -+ /* Allocate page table */ -+ ret = saa716x_allocate_ptable(dmabuf); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "PT alloc failed, Out of memory"); -+ goto err1; -+ } -+ -+ /* Allocate buffer as SG */ -+ ret = saa716x_dmabuf_sgalloc(dmabuf, NULL, size); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SG alloc failed"); -+ goto err2; -+ } -+ -+ ret = dma_map_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SG map failed"); -+ goto err3; -+ } -+ -+ saa716x_dmabuf_sgpagefill(dmabuf, dmabuf->sg_list, ret, 0); -+ -+ return 0; -+err3: -+ saa716x_dmabuf_sgfree(dmabuf); -+err2: -+ saa716x_free_ptable(dmabuf); -+err1: -+ return ret; -+} -+ -+void saa716x_dmabuf_free(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(dmabuf == NULL); -+ -+ dma_unmap_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); -+ saa716x_dmabuf_sgfree(dmabuf); -+ saa716x_free_ptable(dmabuf); -+} -diff --git a/drivers/media/common/saa716x/saa716x_dma.h b/drivers/media/common/saa716x/saa716x_dma.h -new file mode 100644 -index 0000000..f92d667 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dma.h -@@ -0,0 +1,38 @@ -+#ifndef __SAA716x_DMA_H -+#define __SAA716x_DMA_H -+ -+#define SAA716x_PAGE_SIZE 4096 -+ -+enum saa716x_dma_type { -+ SAA716x_DMABUF_EXT_LIN, /* Linear external */ -+ SAA716x_DMABUF_EXT_SG, /* SG external */ -+ SAA716x_DMABUF_INT /* Linear internal */ -+}; -+ -+struct saa716x_dev; -+ -+struct saa716x_dmabuf { -+ enum saa716x_dma_type dma_type; -+ -+ void *mem_virt_noalign; -+ void *mem_virt; /* page aligned */ -+ dma_addr_t mem_ptab_phys; -+ void *mem_ptab_virt; -+ void *sg_list; /* SG list */ -+ -+ struct saa716x_dev *saa716x; -+ -+ int list_len; /* buffer len */ -+ int offset; /* page offset */ -+}; -+ -+extern int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, -+ struct saa716x_dmabuf *dmabuf, -+ int size); -+extern void saa716x_dmabuf_free(struct saa716x_dev *saa716x, -+ struct saa716x_dmabuf *dmabuf); -+ -+extern void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf); -+extern void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf); -+ -+#endif /* __SAA716x_DMA_H */ -diff --git a/drivers/media/common/saa716x/saa716x_dma_reg.h b/drivers/media/common/saa716x/saa716x_dma_reg.h -new file mode 100644 -index 0000000..6037ca9 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dma_reg.h -@@ -0,0 +1,200 @@ -+#ifndef __SAA716x_DMA_REG_H -+#define __SAA716x_DMA_REG_H -+ -+/* -------------- BAM Registers -------------- */ -+ -+#define BAM_VI0_0_DMA_BUF_MODE 0x000 -+ -+#define BAM_VI0_0_ADDR_OFFST_0 0x004 -+#define BAM_VI0_0_ADDR_OFFST_1 0x008 -+#define BAM_VI0_0_ADDR_OFFST_2 0x00c -+#define BAM_VI0_0_ADDR_OFFST_3 0x010 -+#define BAM_VI0_0_ADDR_OFFST_4 0x014 -+#define BAM_VI0_0_ADDR_OFFST_5 0x018 -+#define BAM_VI0_0_ADDR_OFFST_6 0x01c -+#define BAM_VI0_0_ADDR_OFFST_7 0x020 -+ -+#define BAM_VI0_1_DMA_BUF_MODE 0x024 -+#define BAM_VI0_1_ADDR_OFFST_0 0x028 -+#define BAM_VI0_1_ADDR_OFFST_1 0x02c -+#define BAM_VI0_1_ADDR_OFFST_2 0x030 -+#define BAM_VI0_1_ADDR_OFFST_3 0x034 -+#define BAM_VI0_1_ADDR_OFFST_4 0x038 -+#define BAM_VI0_1_ADDR_OFFST_5 0x03c -+#define BAM_VI0_1_ADDR_OFFST_6 0x040 -+#define BAM_VI0_1_ADDR_OFFST_7 0x044 -+ -+#define BAM_VI0_2_DMA_BUF_MODE 0x048 -+#define BAM_VI0_2_ADDR_OFFST_0 0x04c -+#define BAM_VI0_2_ADDR_OFFST_1 0x050 -+#define BAM_VI0_2_ADDR_OFFST_2 0x054 -+#define BAM_VI0_2_ADDR_OFFST_3 0x058 -+#define BAM_VI0_2_ADDR_OFFST_4 0x05c -+#define BAM_VI0_2_ADDR_OFFST_5 0x060 -+#define BAM_VI0_2_ADDR_OFFST_6 0x064 -+#define BAM_VI0_2_ADDR_OFFST_7 0x068 -+ -+ -+#define BAM_VI1_0_DMA_BUF_MODE 0x06c -+#define BAM_VI1_0_ADDR_OFFST_0 0x070 -+#define BAM_VI1_0_ADDR_OFFST_1 0x074 -+#define BAM_VI1_0_ADDR_OFFST_2 0x078 -+#define BAM_VI1_0_ADDR_OFFST_3 0x07c -+#define BAM_VI1_0_ADDR_OFFST_4 0x080 -+#define BAM_VI1_0_ADDR_OFFST_5 0x084 -+#define BAM_VI1_0_ADDR_OFFST_6 0x088 -+#define BAM_VI1_0_ADDR_OFFST_7 0x08c -+ -+#define BAM_VI1_1_DMA_BUF_MODE 0x090 -+#define BAM_VI1_1_ADDR_OFFST_0 0x094 -+#define BAM_VI1_1_ADDR_OFFST_1 0x098 -+#define BAM_VI1_1_ADDR_OFFST_2 0x09c -+#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 -+#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 -+#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 -+#define BAM_VI1_1_ADDR_OFFST_6 0x0ac -+#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 -+ -+#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 -+#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 -+#define BAM_VI1_2_ADDR_OFFST_1 0x0bc -+#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 -+#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 -+#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 -+#define BAM_VI1_2_ADDR_OFFST_5 0x0cc -+#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 -+#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 -+ -+ -+#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 -+#define BAM_FGPI0_ADDR_OFFST_0 0x0dc -+#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 -+#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 -+#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 -+#define BAM_FGPI0_ADDR_OFFST_4 0x0ec -+#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 -+#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 -+#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 -+ -+#define BAM_FGPI1_DMA_BUF_MODE 0x0fc -+#define BAM_FGPI1_ADDR_OFFST_0 0x100 -+#define BAM_FGPI1_ADDR_OFFST_1 0x104 -+#define BAM_FGPI1_ADDR_OFFST_2 0x108 -+#define BAM_FGPI1_ADDR_OFFST_3 0x10c -+#define BAM_FGPI1_ADDR_OFFST_4 0x110 -+#define BAM_FGPI1_ADDR_OFFST_5 0x114 -+#define BAM_FGPI1_ADDR_OFFST_6 0x118 -+#define BAM_FGPI1_ADDR_OFFST_7 0x11c -+ -+#define BAM_FGPI2_DMA_BUF_MODE 0x120 -+#define BAM_FGPI2_ADDR_OFFST_0 0x124 -+#define BAM_FGPI2_ADDR_OFFST_1 0x128 -+#define BAM_FGPI2_ADDR_OFFST_2 0x12c -+#define BAM_FGPI2_ADDR_OFFST_3 0x130 -+#define BAM_FGPI2_ADDR_OFFST_4 0x134 -+#define BAM_FGPI2_ADDR_OFFST_5 0x138 -+#define BAM_FGPI2_ADDR_OFFST_6 0x13c -+#define BAM_FGPI2_ADDR_OFFST_7 0x140 -+ -+#define BAM_FGPI3_DMA_BUF_MODE 0x144 -+#define BAM_FGPI3_ADDR_OFFST_0 0x148 -+#define BAM_FGPI3_ADDR_OFFST_1 0x14c -+#define BAM_FGPI3_ADDR_OFFST_2 0x150 -+#define BAM_FGPI3_ADDR_OFFST_3 0x154 -+#define BAM_FGPI3_ADDR_OFFST_4 0x158 -+#define BAM_FGPI3_ADDR_OFFST_5 0x15c -+#define BAM_FGPI3_ADDR_OFFST_6 0x160 -+#define BAM_FGPI3_ADDR_OFFST_7 0x164 -+ -+ -+#define BAM_AI0_DMA_BUF_MODE 0x168 -+#define BAM_AI0_ADDR_OFFST_0 0x16c -+#define BAM_AI0_ADDR_OFFST_1 0x170 -+#define BAM_AI0_ADDR_OFFST_2 0x174 -+#define BAM_AI0_ADDR_OFFST_3 0x178 -+#define BAM_AI0_ADDR_OFFST_4 0x17c -+#define BAM_AIO_ADDR_OFFST_5 0x180 -+#define BAM_AI0_ADDR_OFFST_6 0x184 -+#define BAM_AIO_ADDR_OFFST_7 0x188 -+ -+#define BAM_AI1_DMA_BUF_MODE 0x18c -+#define BAM_AI1_ADDR_OFFST_0 0x190 -+#define BAM_AI1_ADDR_OFFST_1 0x194 -+#define BAM_AI1_ADDR_OFFST_2 0x198 -+#define BAM_AI1_ADDR_OFFST_3 0x19c -+#define BAM_AI1_ADDR_OFFST_4 0x1a0 -+#define BAM_AI1_ADDR_OFFST_5 0x1a4 -+#define BAM_AI1_ADDR_OFFST_6 0x1a8 -+#define BAM_AI1_ADDR_OFFST_7 0x1ac -+ -+#define BAM_SW_RST 0xff0 -+#define BAM_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+ -+/* -------------- MMU Registers -------------- */ -+ -+#define MMU_MODE 0x000 -+ -+#define MMU_DMA_CONFIG0 0x004 -+#define MMU_DMA_CONFIG1 0x008 -+#define MMU_DMA_CONFIG2 0x00c -+#define MMU_DMA_CONFIG3 0x010 -+#define MMU_DMA_CONFIG4 0x014 -+#define MMU_DMA_CONFIG5 0x018 -+#define MMU_DMA_CONFIG6 0x01c -+#define MMU_DMA_CONFIG7 0x020 -+#define MMU_DMA_CONFIG8 0x024 -+#define MMU_DMA_CONFIG9 0x028 -+#define MMU_DMA_CONFIG10 0x02c -+#define MMU_DMA_CONFIG11 0x030 -+#define MMU_DMA_CONFIG12 0x034 -+#define MMU_DMA_CONFIG13 0x038 -+#define MMU_DMA_CONFIG14 0x03c -+#define MMU_DMA_CONFIG15 0x040 -+ -+#define MMU_SW_RST 0xff0 -+#define MMU_SW_RESET (0x0001 << 0) -+ -+#define MMU_PTA_BASE0 0x044 /* DMA 0 */ -+#define MMU_PTA_BASE1 0x084 /* DMA 1 */ -+#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ -+#define MMU_PTA_BASE3 0x104 /* DMA 3 */ -+#define MMU_PTA_BASE4 0x144 /* DMA 4 */ -+#define MMU_PTA_BASE5 0x184 /* DMA 5 */ -+#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ -+#define MMU_PTA_BASE7 0x204 /* DMA 7 */ -+#define MMU_PTA_BASE8 0x244 /* DMA 8 */ -+#define MMU_PTA_BASE9 0x284 /* DMA 9 */ -+#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ -+#define MMU_PTA_BASE11 0x304 /* DMA 11 */ -+#define MMU_PTA_BASE12 0x344 /* DMA 12 */ -+#define MMU_PTA_BASE13 0x384 /* DMA 13 */ -+#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ -+#define MMU_PTA_BASE15 0x404 /* DMA 15 */ -+ -+#define MMU_PTA_BASE 0x044 /* DMA 0 */ -+#define MMU_PTA_OFFSET 0x40 -+ -+#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) -+ -+#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 -+#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 -+#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 -+#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c -+#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 -+#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 -+#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 -+#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c -+#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 -+#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 -+#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 -+#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c -+#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 -+#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 -+#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 -+#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c -+ -+#endif /* __SAA716x_DMA_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_ff.h b/drivers/media/common/saa716x/saa716x_ff.h -new file mode 100644 -index 0000000..cb65929 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff.h -@@ -0,0 +1,158 @@ -+#ifndef __SAA716x_FF_H -+#define __SAA716x_FF_H -+ -+#include "dvb_filter.h" -+#include "dvb_ringbuffer.h" -+ -+#define TECHNOTREND 0x13c2 -+#define S2_6400_DUAL_S2_PREMIUM_DEVEL 0x3009 -+#define S2_6400_DUAL_S2_PREMIUM_PROD 0x300A -+ -+#define TT_PREMIUM_GPIO_POWER_ENABLE 27 -+#define TT_PREMIUM_GPIO_RESET_BACKEND 26 -+#define TT_PREMIUM_GPIO_FPGA_CS1 17 -+#define TT_PREMIUM_GPIO_FPGA_CS0 16 -+#define TT_PREMIUM_GPIO_FPGA_PROGRAMN 15 -+#define TT_PREMIUM_GPIO_FPGA_DONE 14 -+#define TT_PREMIUM_GPIO_FPGA_INITN 13 -+ -+/* fpga interrupt register addresses */ -+#define FPGA_ADDR_PHI_ICTRL 0x8000 /* PHI General control of the PC => STB interrupt controller */ -+#define FPGA_ADDR_PHI_ISR 0x8010 /* PHI Interrupt Status Register */ -+#define FPGA_ADDR_PHI_ISET 0x8020 /* PHI Interrupt Set Register */ -+#define FPGA_ADDR_PHI_ICLR 0x8030 /* PHI Interrupt Clear Register */ -+#define FPGA_ADDR_EMI_ICTRL 0x8100 /* EMI General control of the STB => PC interrupt controller */ -+#define FPGA_ADDR_EMI_ISR 0x8110 /* EMI Interrupt Status Register */ -+#define FPGA_ADDR_EMI_ISET 0x8120 /* EMI Interrupt Set Register */ -+#define FPGA_ADDR_EMI_ICLR 0x8130 /* EMI Interrupt Clear Register */ -+ -+/* fpga TS router register addresses */ -+#define FPGA_ADDR_TSR_CTRL 0x8200 /* TS router control register */ -+#define FPGA_ADDR_TSR_MUX1 0x8210 /* TS multiplexer 1 selection register */ -+#define FPGA_ADDR_TSR_MUX2 0x8220 /* TS multiplexer 2 selection register */ -+#define FPGA_ADDR_TSR_MUX3 0x8230 /* TS multiplexer 3 selection register */ -+#define FPGA_ADDR_TSR_MUXCI1 0x8240 /* TS multiplexer CI 1 selection register */ -+#define FPGA_ADDR_TSR_MUXCI2 0x8250 /* TS multiplexer CI 2 selection register */ -+ -+#define FPGA_ADDR_TSR_BRFE1 0x8280 /* bit rate for TS coming from frontend 1 */ -+#define FPGA_ADDR_TSR_BRFE2 0x8284 /* bit rate for TS coming from frontend 2 */ -+#define FPGA_ADDR_TSR_BRFF1 0x828C /* bit rate for TS coming from FIFO 1 */ -+#define FPGA_ADDR_TSR_BRO1 0x8294 /* bit rate for TS going to output 1 */ -+#define FPGA_ADDR_TSR_BRO2 0x8298 /* bit rate for TS going to output 2 */ -+#define FPGA_ADDR_TSR_BRO3 0x829C /* bit rate for TS going to output 3 */ -+ -+/* fpga TS FIFO register addresses */ -+#define FPGA_ADDR_FIFO_CTRL 0x8300 /* FIFO control register */ -+#define FPGA_ADDR_FIFO_STAT 0x8310 /* FIFO status register */ -+ -+#define FPGA_ADDR_VERSION 0x80F0 /* FPGA bitstream version register */ -+ -+#define FPGA_ADDR_PIO_CTRL 0x8500 /* FPGA GPIO control register */ -+ -+#define ISR_CMD_MASK 0x0001 /* interrupt source for normal cmds (osd, fre, av, ...) */ -+#define ISR_READY_MASK 0x0002 /* interrupt source for command acknowledge */ -+#define ISR_BLOCK_MASK 0x0004 /* interrupt source for single block transfers and acknowledge */ -+#define ISR_DATA_MASK 0x0008 /* interrupt source for data transfer acknowledge */ -+#define ISR_BOOT_FINISH_MASK 0x0010 /* interrupt source for boot finish indication */ -+#define ISR_AUDIO_PTS_MASK 0x0020 /* interrupt source for audio PTS */ -+#define ISR_VIDEO_PTS_MASK 0x0040 /* interrupt source for video PTS */ -+#define ISR_CURRENT_STC_MASK 0x0080 /* interrupt source for current system clock */ -+#define ISR_REMOTE_EVENT_MASK 0x0100 /* interrupt source for remote events */ -+#define ISR_DVO_FORMAT_MASK 0x0200 /* interrupt source for DVO format change */ -+#define ISR_OSD_CMD_MASK 0x0400 /* interrupt source for OSD cmds */ -+#define ISR_OSD_READY_MASK 0x0800 /* interrupt source for OSD command acknowledge */ -+#define ISR_FE_CMD_MASK 0x1000 /* interrupt source for frontend cmds */ -+#define ISR_FE_READY_MASK 0x2000 /* interrupt source for frontend command acknowledge */ -+#define ISR_LOG_MESSAGE_MASK 0x4000 /* interrupt source for log messages */ -+#define ISR_FIFO1_EMPTY_MASK 0x8000 /* interrupt source for FIFO1 empty */ -+ -+#define ADDR_CMD_DATA 0x0000 /* address for cmd data in fpga dpram */ -+#define ADDR_OSD_CMD_DATA 0x01A0 /* address for OSD cmd data */ -+#define ADDR_FE_CMD_DATA 0x05C0 /* address for frontend cmd data */ -+#define ADDR_BLOCK_DATA 0x0600 /* address for block data */ -+#define ADDR_AUDIO_PTS 0x3E00 /* address for audio PTS (64 Bits) */ -+#define ADDR_VIDEO_PTS 0x3E08 /* address for video PTS (64 Bits) */ -+#define ADDR_CURRENT_STC 0x3E10 /* address for system clock (64 Bits) */ -+#define ADDR_DVO_FORMAT 0x3E18 /* address for DVO format 32 Bits) */ -+#define ADDR_REMOTE_EVENT 0x3F00 /* address for remote events (32 Bits) */ -+#define ADDR_LOG_MESSAGE 0x3F80 /* address for log messages */ -+ -+#define SIZE_CMD_DATA 0x01A0 /* maximum size for command data (416 Bytes) */ -+#define SIZE_OSD_CMD_DATA 0x0420 /* maximum size for OSD command data (1056 Bytes) */ -+#define SIZE_FE_CMD_DATA 0x0040 /* maximum size for frontend command data (64 Bytes) */ -+#define SIZE_BLOCK_DATA 0x3800 /* maximum size for block data (14 kB) */ -+#define SIZE_LOG_MESSAGE_DATA 0x0080 /* maximum size for log message data (128 Bytes) */ -+ -+#define SIZE_BLOCK_HEADER 8 /* block header size */ -+ -+#define MAX_RESULT_LEN 256 -+#define MAX_DATA_LEN (1024 * 1024) -+ -+#define TSOUT_LEN (1024 * TS_SIZE) -+#define TSBUF_LEN (8 * 1024) -+ -+/* place to store all the necessary device information */ -+struct sti7109_dev { -+ struct saa716x_dev *dev; -+ struct dvb_device *osd_dev; -+ struct dvb_device *video_dev; -+ struct dvb_device *audio_dev; -+ -+ void *iobuf; /* memory for all buffers */ -+ struct dvb_ringbuffer tsout; /* buffer for TS output */ -+ u8 *tsbuf; /* temp ts buffer */ -+ -+ struct tasklet_struct fifo_tasklet; -+ -+ wait_queue_head_t boot_finish_wq; -+ int boot_finished; -+ -+ wait_queue_head_t cmd_ready_wq; -+ int cmd_ready; -+ u8 cmd_data[SIZE_CMD_DATA]; -+ u32 cmd_len; -+ -+ wait_queue_head_t result_avail_wq; -+ int result_avail; -+ u8 result_data[MAX_RESULT_LEN]; -+ u32 result_len; -+ u32 result_max_len; -+ -+ wait_queue_head_t osd_cmd_ready_wq; -+ int osd_cmd_ready; -+ u8 osd_cmd_data[SIZE_OSD_CMD_DATA]; -+ u32 osd_cmd_len; -+ -+ wait_queue_head_t osd_result_avail_wq; -+ int osd_result_avail; -+ u8 osd_result_data[MAX_RESULT_LEN]; -+ u32 osd_result_len; -+ u32 osd_result_max_len; -+ -+ u16 data_handle; -+ u8 *data_buffer; /* raw data transfer buffer */ -+ wait_queue_head_t data_ready_wq; -+ int data_ready; -+ wait_queue_head_t block_done_wq; -+ int block_done; -+ -+ struct mutex cmd_lock; -+ struct mutex osd_cmd_lock; -+ struct mutex data_lock; -+ -+ u64 audio_pts; -+ u64 video_pts; -+ u64 current_stc; -+ -+ u32 int_count_enable; -+ u32 total_int_count; -+ u32 fgpi_int_count[2]; -+ u32 i2c_int_count[2]; -+ u32 ext_int_total_count; -+ u32 ext_int_source_count[16]; -+ u32 last_int_ticks; -+ -+ u16 fpga_version; -+}; -+ -+#endif /* __SAA716x_FF_H */ -diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.c b/drivers/media/common/saa716x/saa716x_ff_cmd.c -new file mode 100644 -index 0000000..81c1078 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_cmd.c -@@ -0,0 +1,412 @@ -+#include -+ -+#include -+#include -+ -+#include "saa716x_phi_reg.h" -+ -+#include "saa716x_phi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+#include "saa716x_ff.h" -+#include "saa716x_ff_cmd.h" -+ -+ -+int sti7109_cmd_init(struct sti7109_dev *sti7109) -+{ -+ mutex_init(&sti7109->cmd_lock); -+ mutex_init(&sti7109->osd_cmd_lock); -+ mutex_init(&sti7109->data_lock); -+ -+ init_waitqueue_head(&sti7109->boot_finish_wq); -+ sti7109->boot_finished = 0; -+ -+ init_waitqueue_head(&sti7109->cmd_ready_wq); -+ sti7109->cmd_ready = 0; -+ -+ init_waitqueue_head(&sti7109->result_avail_wq); -+ sti7109->result_avail = 0; -+ -+ init_waitqueue_head(&sti7109->osd_cmd_ready_wq); -+ sti7109->osd_cmd_ready = 0; -+ init_waitqueue_head(&sti7109->osd_result_avail_wq); -+ sti7109->osd_result_avail = 0; -+ -+ sti7109->data_handle = 0; -+ sti7109->data_buffer = (u8 *) (sti7109->iobuf + TSOUT_LEN + TSBUF_LEN); -+ init_waitqueue_head(&sti7109->data_ready_wq); -+ sti7109->data_ready = 0; -+ init_waitqueue_head(&sti7109->block_done_wq); -+ sti7109->block_done = 0; -+ return 0; -+} -+ -+static int sti7109_do_raw_cmd(struct sti7109_dev * sti7109) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->cmd_ready_wq, -+ sti7109->cmd_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->cmd_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "cmd ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for command ready"); -+ return -EIO; -+ } -+ -+ sti7109->cmd_ready = 0; -+ sti7109->result_avail = 0; -+ saa716x_phi_write(saa716x, ADDR_CMD_DATA, sti7109->cmd_data, -+ sti7109->cmd_len); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_CMD_MASK); -+ -+ if (sti7109->result_max_len > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout( -+ sti7109->result_avail_wq, -+ sti7109->result_avail == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->result_avail == 0) { -+ sti7109->result_len = 0; -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "result ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for command result"); -+ return -EIO; -+ } -+ -+ if (sti7109->result_len > sti7109->result_max_len) { -+ sti7109->result_len = sti7109->result_max_len; -+ dprintk(SAA716x_NOTICE, 1, -+ "not enough space in result buffer"); -+ } -+ } -+ -+ return 0; -+} -+ -+int sti7109_raw_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (cmd->cmd_len > SIZE_CMD_DATA) { -+ dprintk(SAA716x_ERROR, 1, "command too long"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->cmd_data, (void __user *)cmd->cmd_data, -+ cmd->cmd_len)) -+ goto out; -+ -+ sti7109->cmd_len = cmd->cmd_len; -+ sti7109->result_max_len = cmd->result_len; -+ -+ err = sti7109_do_raw_cmd(sti7109); -+ if (err) -+ goto out; -+ -+ cmd->result_len = sti7109->result_len; -+ if (sti7109->result_len > 0) { -+ if (copy_to_user((void __user *)cmd->result_data, -+ sti7109->result_data, -+ sti7109->result_len)) -+ err = -EFAULT; -+ } -+ -+out: -+ mutex_unlock(&sti7109->cmd_lock); -+ return err; -+} -+ -+static int sti7109_do_raw_osd_cmd(struct sti7109_dev * sti7109) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->osd_cmd_ready_wq, -+ sti7109->osd_cmd_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->osd_cmd_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "osd cmd ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for osd command ready"); -+ return -EIO; -+ } -+ -+ sti7109->osd_cmd_ready = 0; -+ sti7109->osd_result_avail = 0; -+ saa716x_phi_write(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_cmd_data, -+ sti7109->osd_cmd_len); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_OSD_CMD_MASK); -+ -+ if (sti7109->osd_result_max_len > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout( -+ sti7109->osd_result_avail_wq, -+ sti7109->osd_result_avail == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->osd_result_avail == 0) { -+ sti7109->osd_result_len = 0; -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, -+ "osd result ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for osd command result"); -+ return -EIO; -+ } -+ -+ if (sti7109->osd_result_len > sti7109->osd_result_max_len) { -+ sti7109->osd_result_len = sti7109->osd_result_max_len; -+ dprintk(SAA716x_NOTICE, 1, -+ "not enough space in result buffer"); -+ } -+ } -+ -+ return 0; -+} -+ -+int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (cmd->cmd_len > SIZE_OSD_CMD_DATA) { -+ dprintk(SAA716x_ERROR, 1, "command too long"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->osd_cmd_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->osd_cmd_data, (void __user *)cmd->cmd_data, -+ cmd->cmd_len)) -+ goto out; -+ -+ sti7109->osd_cmd_len = cmd->cmd_len; -+ sti7109->osd_result_max_len = cmd->result_len; -+ -+ err = sti7109_do_raw_osd_cmd(sti7109); -+ if (err) -+ goto out; -+ -+ cmd->result_len = sti7109->osd_result_len; -+ if (sti7109->osd_result_len > 0) { -+ if (copy_to_user((void __user *)cmd->result_data, -+ sti7109->osd_result_data, -+ sti7109->osd_result_len)) -+ err = -EFAULT; -+ } -+ -+out: -+ mutex_unlock(&sti7109->osd_cmd_lock); -+ return err; -+} -+ -+static int sti7109_do_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ u16 blockSize; -+ u16 lastBlockSize; -+ u16 numBlocks; -+ u16 blockIndex; -+ u8 blockHeader[SIZE_BLOCK_HEADER]; -+ u8 * blockPtr; -+ int activeBlock; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->data_ready_wq, -+ sti7109->data_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->data_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "data ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for data ready"); -+ return -EIO; -+ } -+ -+ sti7109->data_ready = 0; -+ -+ /* -+ * 8 bytes is the size of the block header. Block header structure is: -+ * 16 bit - block index -+ * 16 bit - number of blocks -+ * 16 bit - current block data size -+ * 16 bit - block handle. This is used to reference the data in the -+ * command that uses it. -+ */ -+ blockSize = (SIZE_BLOCK_DATA / 2) - SIZE_BLOCK_HEADER; -+ numBlocks = data->data_length / blockSize; -+ lastBlockSize = data->data_length % blockSize; -+ if (lastBlockSize > 0) -+ numBlocks++; -+ -+ blockHeader[2] = (u8) (numBlocks >> 8); -+ blockHeader[3] = (u8) numBlocks; -+ blockHeader[6] = (u8) (sti7109->data_handle >> 8); -+ blockHeader[7] = (u8) sti7109->data_handle; -+ blockPtr = sti7109->data_buffer; -+ activeBlock = 0; -+ for (blockIndex = 0; blockIndex < numBlocks; blockIndex++) { -+ u32 addr; -+ -+ if (lastBlockSize && (blockIndex == (numBlocks - 1))) -+ blockSize = lastBlockSize; -+ -+ blockHeader[0] = (uint8_t) (blockIndex >> 8); -+ blockHeader[1] = (uint8_t) blockIndex; -+ blockHeader[4] = (uint8_t) (blockSize >> 8); -+ blockHeader[5] = (uint8_t) blockSize; -+ -+ addr = ADDR_BLOCK_DATA + activeBlock * (SIZE_BLOCK_DATA / 2); -+ saa716x_phi_write(saa716x, addr, blockHeader, -+ SIZE_BLOCK_HEADER); -+ saa716x_phi_write(saa716x, addr + SIZE_BLOCK_HEADER, blockPtr, -+ blockSize); -+ activeBlock = (activeBlock + 1) & 1; -+ if (blockIndex > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_timeout(sti7109->block_done_wq, -+ sti7109->block_done == 1, -+ timeout); -+ -+ if (sti7109->block_done == 0) { -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for block done"); -+ return -EIO; -+ } -+ } -+ sti7109->block_done = 0; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_BLOCK_MASK); -+ blockPtr += blockSize; -+ } -+ timeout = 1 * HZ; -+ timeout = wait_event_timeout(sti7109->block_done_wq, -+ sti7109->block_done == 1, -+ timeout); -+ -+ if (sti7109->block_done == 0) { -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for block done"); -+ return -EIO; -+ } -+ sti7109->block_done = 0; -+ -+ data->data_handle = sti7109->data_handle; -+ sti7109->data_handle++; -+ return 0; -+} -+ -+int sti7109_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (data->data_length > MAX_DATA_LEN) { -+ dprintk(SAA716x_ERROR, 1, "data too big"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->data_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->data_buffer, -+ (void __user *)data->data_buffer, -+ data->data_length)) -+ goto out; -+ -+ err = sti7109_do_raw_data(sti7109, data); -+ if (err) -+ goto out; -+ -+out: -+ mutex_unlock(&sti7109->data_lock); -+ return err; -+} -+ -+int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, u32 *fw_version) -+{ -+ int ret_val = -EINVAL; -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ sti7109->cmd_data[0] = 0x00; -+ sti7109->cmd_data[1] = 0x04; -+ sti7109->cmd_data[2] = 0x00; -+ sti7109->cmd_data[3] = 0x00; -+ sti7109->cmd_data[4] = 0x00; -+ sti7109->cmd_data[5] = 0x00; -+ sti7109->cmd_len = 6; -+ sti7109->result_max_len = MAX_RESULT_LEN; -+ -+ ret_val = sti7109_do_raw_cmd(sti7109); -+ if (ret_val == 0) { -+ *fw_version = (sti7109->result_data[6] << 16) -+ | (sti7109->result_data[7] << 8) -+ | sti7109->result_data[8]; -+ } -+ -+ mutex_unlock(&sti7109->cmd_lock); -+ -+ return ret_val; -+} -+ -+int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, video_size_t *vs) -+{ -+ int ret_val = -EINVAL; -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ sti7109->cmd_data[0] = 0x00; -+ sti7109->cmd_data[1] = 0x05; /* command length */ -+ sti7109->cmd_data[2] = 0x00; -+ sti7109->cmd_data[3] = 0x01; /* A/V decoder command group */ -+ sti7109->cmd_data[4] = 0x00; -+ sti7109->cmd_data[5] = 0x10; /* get video format info command */ -+ sti7109->cmd_data[6] = 0x00; /* decoder index 0 */ -+ sti7109->cmd_len = 7; -+ sti7109->result_max_len = MAX_RESULT_LEN; -+ -+ ret_val = sti7109_do_raw_cmd(sti7109); -+ if (ret_val == 0) { -+ vs->w = (sti7109->result_data[7] << 8) -+ | sti7109->result_data[8]; -+ vs->h = (sti7109->result_data[9] << 8) -+ | sti7109->result_data[10]; -+ vs->aspect_ratio = sti7109->result_data[11] >> 4; -+ } -+ -+ mutex_unlock(&sti7109->cmd_lock); -+ -+ return ret_val; -+} -+ -diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.h b/drivers/media/common/saa716x/saa716x_ff_cmd.h -new file mode 100644 -index 0000000..fc79f08 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_cmd.h -@@ -0,0 +1,16 @@ -+#ifndef __SAA716x_FF_CMD_H -+#define __SAA716x_FF_CMD_H -+ -+extern int sti7109_cmd_init(struct sti7109_dev *sti7109); -+extern int sti7109_raw_cmd(struct sti7109_dev * sti7109, -+ osd_raw_cmd_t * cmd); -+extern int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, -+ osd_raw_cmd_t * cmd); -+extern int sti7109_raw_data(struct sti7109_dev * sti7109, -+ osd_raw_data_t * data); -+extern int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, -+ u32 *fw_version); -+extern int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, -+ video_size_t *vs); -+ -+#endif /* __SAA716x_FF_CMD_H */ -diff --git a/drivers/media/common/saa716x/saa716x_ff_ir.c b/drivers/media/common/saa716x/saa716x_ff_ir.c -new file mode 100644 -index 0000000..3562478 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_ir.c -@@ -0,0 +1,265 @@ -+/* -+ * Driver for the remote control of the TT6400 DVB-S2 card -+ * -+ * Copyright (C) 2010 Oliver Endriss -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ * -+ */ -+ -+#include -+#include -+ -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+#include "saa716x_ff.h" -+ -+ -+/* infrared remote control */ -+struct infrared { -+ u16 key_map[128]; -+ struct input_dev *input_dev; -+ char input_phys[32]; -+ struct timer_list keyup_timer; -+ struct tasklet_struct tasklet; -+ u32 command; -+ u32 device_mask; -+ u8 protocol; -+ u16 last_key; -+ u16 last_toggle; -+ bool delay_timer_finished; -+}; -+ -+#define IR_RC5 0 -+#define UP_TIMEOUT (HZ*7/25) -+ -+ -+/* key-up timer */ -+static void ir_emit_keyup(unsigned long parm) -+{ -+ struct infrared *ir = (struct infrared *) parm; -+ -+ if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) -+ return; -+ -+ input_report_key(ir->input_dev, ir->last_key, 0); -+ input_sync(ir->input_dev); -+} -+ -+ -+/* tasklet */ -+static void ir_emit_key(unsigned long parm) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) parm; -+ struct infrared *ir = saa716x->ir_priv; -+ u32 ircom = ir->command; -+ u8 data; -+ u8 addr; -+ u16 toggle; -+ u16 keycode; -+ -+ /* extract device address and data */ -+ if (ircom & 0x80000000) { /* CEC remote command */ -+ addr = 0; -+ data = ircom & 0x7F; -+ toggle = 0; -+ } else { -+ switch (ir->protocol) { -+ case IR_RC5: /* extended RC5: 5 bits device address, 7 bits data */ -+ addr = (ircom >> 6) & 0x1f; -+ /* data bits 1..6 */ -+ data = ircom & 0x3f; -+ /* data bit 7 (inverted) */ -+ if (!(ircom & 0x1000)) -+ data |= 0x40; -+ toggle = ircom & 0x0800; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s: invalid protocol %x\n", -+ __func__, ir->protocol); -+ return; -+ } -+ } -+ -+ input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data); -+ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); -+ -+ keycode = ir->key_map[data]; -+ -+ dprintk(SAA716x_DEBUG, 0, -+ "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", -+ __func__, ircom, addr, data, keycode); -+ -+ /* check device address */ -+ if (!(ir->device_mask & (1 << addr))) -+ return; -+ -+ if (!keycode) { -+ printk(KERN_WARNING "%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", -+ __func__, ircom, addr, data); -+ return; -+ } -+ -+ if (timer_pending(&ir->keyup_timer)) { -+ del_timer(&ir->keyup_timer); -+ if (ir->last_key != keycode || toggle != ir->last_toggle) { -+ ir->delay_timer_finished = false; -+ input_event(ir->input_dev, EV_KEY, ir->last_key, 0); -+ input_event(ir->input_dev, EV_KEY, keycode, 1); -+ input_sync(ir->input_dev); -+ } else if (ir->delay_timer_finished) { -+ input_event(ir->input_dev, EV_KEY, keycode, 2); -+ input_sync(ir->input_dev); -+ } -+ } else { -+ ir->delay_timer_finished = false; -+ input_event(ir->input_dev, EV_KEY, keycode, 1); -+ input_sync(ir->input_dev); -+ } -+ -+ ir->last_key = keycode; -+ ir->last_toggle = toggle; -+ -+ ir->keyup_timer.expires = jiffies + UP_TIMEOUT; -+ add_timer(&ir->keyup_timer); -+ -+} -+ -+ -+/* register with input layer */ -+static void ir_register_keys(struct infrared *ir) -+{ -+ int i; -+ -+ set_bit(EV_KEY, ir->input_dev->evbit); -+ set_bit(EV_REP, ir->input_dev->evbit); -+ set_bit(EV_MSC, ir->input_dev->evbit); -+ -+ set_bit(MSC_RAW, ir->input_dev->mscbit); -+ set_bit(MSC_SCAN, ir->input_dev->mscbit); -+ -+ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); -+ -+ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) { -+ if (ir->key_map[i] > KEY_MAX) -+ ir->key_map[i] = 0; -+ else if (ir->key_map[i] > KEY_RESERVED) -+ set_bit(ir->key_map[i], ir->input_dev->keybit); -+ } -+ -+ ir->input_dev->keycode = ir->key_map; -+ ir->input_dev->keycodesize = sizeof(ir->key_map[0]); -+ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); -+} -+ -+ -+/* called by the input driver after rep[REP_DELAY] ms */ -+static void ir_repeat_key(unsigned long parm) -+{ -+ struct infrared *ir = (struct infrared *) parm; -+ -+ ir->delay_timer_finished = true; -+} -+ -+ -+/* interrupt handler */ -+void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd) -+{ -+ struct infrared *ir = saa716x->ir_priv; -+ -+ if (!ir) -+ return; -+ -+ ir->command = ir_cmd; -+ tasklet_schedule(&ir->tasklet); -+} -+ -+ -+int saa716x_ir_init(struct saa716x_dev *saa716x) -+{ -+ struct input_dev *input_dev; -+ struct infrared *ir; -+ int rc; -+ int i; -+ -+ if (!saa716x) -+ return -ENOMEM; -+ -+ ir = kzalloc(sizeof(struct infrared), GFP_KERNEL); -+ if (!ir) -+ return -ENOMEM; -+ -+ init_timer(&ir->keyup_timer); -+ ir->keyup_timer.function = ir_emit_keyup; -+ ir->keyup_timer.data = (unsigned long) ir; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ goto err; -+ -+ ir->input_dev = input_dev; -+ input_dev->name = "TT6400 DVB IR receiver"; -+ snprintf(ir->input_phys, sizeof(ir->input_phys), -+ "pci-%s/ir0", pci_name(saa716x->pdev)); -+ input_dev->phys = ir->input_phys; -+ input_dev->id.bustype = BUS_PCI; -+ input_dev->id.version = 1; -+ input_dev->id.vendor = saa716x->pdev->subsystem_vendor; -+ input_dev->id.product = saa716x->pdev->subsystem_device; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -+ input_dev->dev.parent = &saa716x->pdev->dev; -+#else -+ input_dev->cdev.dev = &saa716x->pdev->dev; -+#endif -+ rc = input_register_device(input_dev); -+ if (rc) -+ goto err; -+ -+ /* TODO: fix setup/keymap */ -+ ir->protocol = IR_RC5; -+ ir->device_mask = 0xffffffff; -+ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) -+ ir->key_map[i] = i+1; -+ ir_register_keys(ir); -+ -+ /* override repeat timer */ -+ input_dev->timer.function = ir_repeat_key; -+ input_dev->timer.data = (unsigned long) ir; -+ -+ tasklet_init(&ir->tasklet, ir_emit_key, (unsigned long) saa716x); -+ saa716x->ir_priv = ir; -+ -+ return 0; -+ -+err: -+ if (ir->input_dev) -+ input_free_device(ir->input_dev); -+ kfree(ir); -+ return -ENOMEM; -+} -+ -+ -+void saa716x_ir_exit(struct saa716x_dev *saa716x) -+{ -+ struct infrared *ir = saa716x->ir_priv; -+ -+ saa716x->ir_priv = NULL; -+ tasklet_kill(&ir->tasklet); -+ del_timer_sync(&ir->keyup_timer); -+ input_unregister_device(ir->input_dev); -+ kfree(ir); -+} -diff --git a/drivers/media/common/saa716x/saa716x_ff_main.c b/drivers/media/common/saa716x/saa716x_ff_main.c -new file mode 100644 -index 0000000..34093c2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_main.c -@@ -0,0 +1,1535 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_dma_reg.h" -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_phi_reg.h" -+#include "saa716x_spi_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_vip.h" -+#include "saa716x_aip.h" -+#include "saa716x_msi.h" -+#include "saa716x_adap.h" -+#include "saa716x_gpio.h" -+#include "saa716x_phi.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "saa716x_ff.h" -+#include "saa716x_ff_cmd.h" -+ -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "isl6423.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+unsigned int int_count_enable; -+module_param(int_count_enable, int, 0644); -+MODULE_PARM_DESC(int_count_enable, "enable counting of interrupts"); -+ -+#define DRIVER_NAME "SAA716x FF" -+ -+static int saa716x_ff_fpga_init(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ int fpgaInit; -+ int fpgaDone; -+ int rounds; -+ int ret; -+ const struct firmware *fw; -+ -+ /* request the FPGA firmware, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-fpga-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load FPGA firmware," -+ " file not found: dvb-ttpremium-fpga-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ -+ /* set FPGA PROGRAMN high */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); -+ msleep(10); -+ -+ /* set FPGA PROGRAMN low to set it into configuration mode */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 0); -+ msleep(10); -+ -+ /* set FPGA PROGRAMN high to start configuration process */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); -+ -+ rounds = 0; -+ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ while (fpgaInit == 0 && rounds < 5000) { -+ //msleep(1); -+ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ rounds++; -+ } -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA INITN=%d, rounds=%d", -+ fpgaInit, rounds); -+ -+ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, 0x08); -+ SAA716x_EPWR(SPI, SPI_CONTROL_REG, SPI_MODE_SELECT); -+ -+ msleep(10); -+ -+ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream"); -+ saa716x_spi_write(saa716x, fw->data, fw->size); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream done"); -+ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); -+ -+ msleep(10); -+ -+ release_firmware(fw); -+ -+ if (!fpgaDone) { -+ printk(KERN_ERR "SAA716x FF FPGA is not responding, did you " -+ "connect the power supply?\n"); -+ return -EINVAL; -+ } -+ -+ sti7109->fpga_version = SAA716x_EPRD(PHI_1, FPGA_ADDR_VERSION); -+ printk(KERN_INFO "SAA716x FF FPGA version %X.%02X\n", -+ sti7109->fpga_version >> 8, sti7109->fpga_version & 0xFF); -+ -+ return 0; -+} -+ -+static int saa716x_ff_st7109_init(struct saa716x_dev *saa716x) -+{ -+ int i; -+ int length; -+ u32 requestedBlock; -+ u32 writtenBlock; -+ u32 numBlocks; -+ u32 blockSize; -+ u32 lastBlockSize; -+ u64 startTime; -+ u64 currentTime; -+ u64 waitTime; -+ int ret; -+ const struct firmware *fw; -+ u32 loaderVersion; -+ -+ /* request the st7109 loader, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-loader-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 loader," -+ " file not found: dvb-ttpremium-loader-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ loaderVersion = (fw->data[0x1385] << 8) | fw->data[0x1384]; -+ printk(KERN_INFO "SAA716x FF loader version %X.%02X\n", -+ loaderVersion >> 8, loaderVersion & 0xFF); -+ -+ saa716x_phi_write(saa716x, 0, fw->data, fw->size); -+ msleep(10); -+ -+ release_firmware(fw); -+ -+ /* take ST out of reset */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 1); -+ -+ startTime = jiffies; -+ waitTime = 0; -+ do { -+ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); -+ if (requestedBlock == 1) -+ break; -+ -+ currentTime = jiffies; -+ waitTime = currentTime - startTime; -+ } while (waitTime < (1 * HZ)); -+ -+ if (waitTime >= 1 * HZ) { -+ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); -+ return -1; -+ } -+ dprintk(SAA716x_INFO, 1, "STi7109 ready after %llu ticks", waitTime); -+ -+ /* request the st7109 firmware, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-st7109-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 firmware," -+ " file not found: dvb-ttpremium-st7109-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ -+ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware"); -+ writtenBlock = 0; -+ blockSize = 0x3c00; -+ length = fw->size; -+ numBlocks = length / blockSize; -+ lastBlockSize = length % blockSize; -+ for (i = 0; i < length; i += blockSize) { -+ writtenBlock++; -+ /* write one block (last may differ from blockSize) */ -+ if (lastBlockSize && writtenBlock == (numBlocks + 1)) -+ saa716x_phi_write(saa716x, 0, &fw->data[i], lastBlockSize); -+ else -+ saa716x_phi_write(saa716x, 0, &fw->data[i], blockSize); -+ -+ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); -+ startTime = jiffies; -+ waitTime = 0; -+ do { -+ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); -+ if (requestedBlock == (writtenBlock + 1)) -+ break; -+ -+ currentTime = jiffies; -+ waitTime = currentTime - startTime; -+ } while (waitTime < (1 * HZ)); -+ -+ if (waitTime >= 1 * HZ) { -+ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); -+ release_firmware(fw); -+ return -1; -+ } -+ } -+ -+ /* disable frontend support through ST firmware */ -+ SAA716x_EPWR(PHI_1, 0x3ff4, 1); -+ -+ /* indicate end of transfer */ -+ writtenBlock++; -+ writtenBlock |= 0x80000000; -+ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); -+ -+ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware done"); -+ -+ release_firmware(fw); -+ -+ return 0; -+} -+ -+static int saa716x_usercopy(struct dvb_device *dvbdev, -+ unsigned int cmd, unsigned long arg, -+ int (*func)(struct dvb_device *dvbdev, -+ unsigned int cmd, void *arg)) -+{ -+ char sbuf[128]; -+ void *mbuf = NULL; -+ void *parg = NULL; -+ int err = -EINVAL; -+ -+ /* Copy arguments into temp kernel buffer */ -+ switch (_IOC_DIR(cmd)) { -+ case _IOC_NONE: -+ /* -+ * For this command, the pointer is actually an integer -+ * argument. -+ */ -+ parg = (void *) arg; -+ break; -+ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ -+ case _IOC_WRITE: -+ case (_IOC_WRITE | _IOC_READ): -+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { -+ parg = sbuf; -+ } else { -+ /* too big to allocate from stack */ -+ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); -+ if (NULL == mbuf) -+ return -ENOMEM; -+ parg = mbuf; -+ } -+ -+ err = -EFAULT; -+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -+ goto out; -+ break; -+ } -+ -+ /* call driver */ -+ if ((err = func(dvbdev, cmd, parg)) == -ENOIOCTLCMD) -+ err = -EINVAL; -+ -+ if (err < 0) -+ goto out; -+ -+ /* Copy results into user buffer */ -+ switch (_IOC_DIR(cmd)) -+ { -+ case _IOC_READ: -+ case (_IOC_WRITE | _IOC_READ): -+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ break; -+ } -+ -+out: -+ kfree(mbuf); -+ return err; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_osd_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_osd_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ int err = -EINVAL; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ if (cmd == OSD_RAW_CMD) { -+ osd_raw_cmd_t raw_cmd; -+ u8 hdr[4]; -+ -+ err = -EFAULT; -+ if (copy_from_user(&raw_cmd, (void __user *)arg, -+ _IOC_SIZE(cmd))) -+ goto out; -+ -+ if (copy_from_user(hdr, (void __user *)raw_cmd.cmd_data, 4)) -+ goto out; -+ -+ if (hdr[3] == 4) -+ err = sti7109_raw_osd_cmd(sti7109, &raw_cmd); -+ else -+ err = sti7109_raw_cmd(sti7109, &raw_cmd); -+ -+ if (err) -+ goto out; -+ -+ if (copy_to_user((void __user *)arg, &raw_cmd, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ } -+ else if (cmd == OSD_RAW_DATA) { -+ osd_raw_data_t raw_data; -+ -+ err = -EFAULT; -+ if (copy_from_user(&raw_data, (void __user *)arg, -+ _IOC_SIZE(cmd))) -+ goto out; -+ -+ err = sti7109_raw_data(sti7109, &raw_data); -+ if (err) -+ goto out; -+ -+ if (copy_to_user((void __user *)arg, &raw_data, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ } -+ -+out: -+ return err; -+} -+ -+static struct file_operations dvb_osd_fops = { -+ .owner = THIS_MODULE, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_osd_ioctl, -+#else -+ .unlocked_ioctl = dvb_osd_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+}; -+ -+static struct dvb_device dvbdev_osd = { -+ .priv = NULL, -+ .users = 2, -+ .writers = 2, -+ .fops = &dvb_osd_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_osd_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_unregister_device(sti7109->osd_dev); -+ return 0; -+} -+ -+static int saa716x_ff_osd_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->osd_dev, -+ &dvbdev_osd, -+ sti7109, -+ DVB_DEVICE_OSD); -+ -+ return 0; -+} -+ -+static int do_dvb_audio_ioctl(struct dvb_device *dvbdev, -+ unsigned int cmd, void *parg) -+{ -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ //struct saa716x_dev *saa716x = sti7109->dev; -+ int ret = 0; -+ -+ switch (cmd) { -+ case AUDIO_GET_PTS: -+ { -+ *(u64 *)parg = sti7109->audio_pts; -+ break; -+ } -+ default: -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return ret; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_audio_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_audio_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_audio_ioctl); -+} -+ -+static struct file_operations dvb_audio_fops = { -+ .owner = THIS_MODULE, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_audio_ioctl, -+#else -+ .unlocked_ioctl = dvb_audio_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+}; -+ -+static struct dvb_device dvbdev_audio = { -+ .priv = NULL, -+ .users = 1, -+ .writers = 1, -+ .fops = &dvb_audio_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_audio_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_unregister_device(sti7109->audio_dev); -+ return 0; -+} -+ -+static int saa716x_ff_audio_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->audio_dev, -+ &dvbdev_audio, -+ sti7109, -+ DVB_DEVICE_AUDIO); -+ -+ return 0; -+} -+ -+static void fifo_worker(unsigned long data) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) data; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ u32 fifoCtrl; -+ u32 fifoStat; -+ u16 fifoSize; -+ u16 fifoUsage; -+ u16 fifoFree; -+ int len; -+ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoStat = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_STAT); -+ fifoSize = (u16) (fifoStat >> 16); -+ fifoUsage = (u16) fifoStat; -+ fifoFree = fifoSize - fifoUsage; -+ spin_lock(&sti7109->tsout.lock); -+ len = dvb_ringbuffer_avail(&sti7109->tsout); -+ if (len > fifoFree) -+ len = fifoFree; -+ if (len >= TS_SIZE) -+ { -+ while (len >= TS_SIZE) -+ { -+ dvb_ringbuffer_read(&sti7109->tsout, sti7109->tsbuf, (size_t) TS_SIZE); -+ saa716x_phi_write_fifo(saa716x, sti7109->tsbuf, TS_SIZE); -+ len -= TS_SIZE; -+ } -+ wake_up(&sti7109->tsout.queue); -+ fifoCtrl |= 0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ } -+ spin_unlock(&sti7109->tsout.lock); -+} -+ -+#define FREE_COND_TS (dvb_ringbuffer_free(&sti7109->tsout) >= TS_SIZE) -+ -+static ssize_t dvb_video_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ struct saa716x_dev *saa716x = sti7109->dev; -+ unsigned long todo = count; -+ -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ return -EPERM; -+/* -+ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) -+ return -EPERM; -+*/ -+ if ((file->f_flags & O_NONBLOCK) && !FREE_COND_TS) -+ return -EWOULDBLOCK; -+ -+ while (todo >= TS_SIZE) { -+ if (!FREE_COND_TS) { -+ if (file->f_flags & O_NONBLOCK) -+ break; -+ if (wait_event_interruptible(sti7109->tsout.queue, FREE_COND_TS)) -+ break; -+ } -+ dvb_ringbuffer_write(&sti7109->tsout, buf, TS_SIZE); -+ todo -= TS_SIZE; -+ buf += TS_SIZE; -+ } -+ -+ if (count > todo) { -+ u32 fifoCtrl; -+ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoCtrl |= 0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ } -+ -+ return count - todo; -+} -+ -+static unsigned int dvb_video_poll(struct file *file, poll_table *wait) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ unsigned int mask = 0; -+ -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) -+ poll_wait(file, &sti7109->tsout.queue, wait); -+ -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { -+ if (1/*sti7109->playing*/) { -+ if (FREE_COND_TS) -+ mask |= (POLLOUT | POLLWRNORM); -+ } else /* if not playing: may play if asked for */ -+ mask |= (POLLOUT | POLLWRNORM); -+ } -+ -+ return mask; -+} -+ -+static int do_dvb_video_ioctl(struct dvb_device *dvbdev, -+ unsigned int cmd, void *parg) -+{ -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ struct saa716x_dev *saa716x = sti7109->dev; -+ int ret = 0; -+ -+ switch (cmd) { -+ case VIDEO_SELECT_SOURCE: -+ { -+ video_stream_source_t stream_source; -+ -+ stream_source = (video_stream_source_t) parg; -+ if (stream_source == VIDEO_SOURCE_DEMUX) { -+ /* stop and reset FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); -+ } -+ else { -+ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); -+ /* reset FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); -+ /* start FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 2); -+ } -+ break; -+ } -+ case VIDEO_CLEAR_BUFFER: -+ { -+ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); -+ break; -+ } -+ case VIDEO_GET_PTS: -+ { -+ *(u64 *)parg = sti7109->video_pts; -+ break; -+ } -+ case VIDEO_GET_SIZE: -+ { -+ ret = sti7109_cmd_get_video_format(sti7109, (video_size_t *) parg); -+ break; -+ } -+ default: -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return ret; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_video_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_video_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_video_ioctl); -+} -+ -+static struct file_operations dvb_video_fops = { -+ .owner = THIS_MODULE, -+ .write = dvb_video_write, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_video_ioctl, -+#else -+ .unlocked_ioctl = dvb_video_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+ .poll = dvb_video_poll, -+}; -+ -+static struct dvb_device dvbdev_video = { -+ .priv = NULL, -+ .users = 1, -+ .writers = 1, -+ .fops = &dvb_video_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_video_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ tasklet_kill(&sti7109->fifo_tasklet); -+ dvb_unregister_device(sti7109->video_dev); -+ return 0; -+} -+ -+static int saa716x_ff_video_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_ringbuffer_init(&sti7109->tsout, sti7109->iobuf, TSOUT_LEN); -+ sti7109->tsbuf = (u8 *) (sti7109->iobuf + TSOUT_LEN); -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->video_dev, -+ &dvbdev_video, -+ sti7109, -+ DVB_DEVICE_VIDEO); -+ -+ tasklet_init(&sti7109->fifo_tasklet, fifo_worker, -+ (unsigned long)saa716x); -+ -+ return 0; -+} -+ -+static int saa716x_ff_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ struct sti7109_dev *sti7109; -+ int err = 0; -+ u32 value; -+ unsigned long timeout; -+ u32 fw_version; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ err = saa716x_phi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PHI Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ /* prepare the sti7109 device struct */ -+ sti7109 = kzalloc(sizeof(struct sti7109_dev), GFP_KERNEL); -+ if (!sti7109) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x: out of memory"); -+ goto fail3; -+ } -+ -+ sti7109->dev = saa716x; -+ -+ sti7109->iobuf = vmalloc(TSOUT_LEN + TSBUF_LEN + MAX_DATA_LEN); -+ if (!sti7109->iobuf) -+ goto fail4; -+ -+ sti7109_cmd_init(sti7109); -+ -+ sti7109->int_count_enable = int_count_enable; -+ sti7109->total_int_count = 0; -+ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); -+ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); -+ sti7109->ext_int_total_count = 0; -+ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); -+ sti7109->last_int_ticks = jiffies; -+ -+ saa716x->priv = sti7109; -+ -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS0); -+ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS0, 1); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS1); -+ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS1, 1); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN); -+ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ -+ /* hold ST in reset */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 0); -+ -+ /* enable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 1); -+ msleep(100); -+ -+ err = saa716x_ff_fpga_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF FPGA Initialization failed"); -+ goto fail5; -+ } -+ -+ /* configure TS muxer */ -+ if (sti7109->fpga_version < 0x110) { -+ /* select FIFO 1 for TS mux 3 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 4); -+ } else { -+ /* select FIFO 1 for TS mux 3 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 1); -+ } -+ -+ /* enable interrupts from ST7109 -> PC */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICTRL, 0x3); -+ -+ value = SAA716x_EPRD(MSI, MSI_CONFIG33); -+ value &= 0xFCFFFFFF; -+ value |= MSI_INT_POL_EDGE_FALL; -+ SAA716x_EPWR(MSI, MSI_CONFIG33, value); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_EXTINT_0); -+ -+ /* enable tuner reset */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 0); -+ msleep(50); -+ /* disable tuner reset */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 1); -+ -+ err = saa716x_ff_st7109_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF STi7109 initialization failed"); -+ goto fail5; -+ } -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ /* enable FGPI2 and FGPI3 for TS inputs */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x0689F04); -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x280); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail6; -+ } -+ -+ /* wait a maximum of 10 seconds for the STi7109 to boot */ -+ timeout = 10 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->boot_finish_wq, -+ sti7109->boot_finished == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->boot_finished == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ goto fail6; -+ } -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for boot finish"); -+ err = -1; -+ goto fail6; -+ } -+ dprintk(SAA716x_INFO, 1, "STi7109 finished booting"); -+ -+ err = saa716x_ff_video_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF VIDEO initialization failed"); -+ goto fail7; -+ } -+ -+ err = saa716x_ff_audio_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF AUDIO initialization failed"); -+ goto fail8; -+ } -+ -+ err = saa716x_ff_osd_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF OSD initialization failed"); -+ goto fail9; -+ } -+ -+ err = sti7109_cmd_get_fw_version(sti7109, &fw_version); -+ if (!err) { -+ printk(KERN_INFO "SAA716x FF firmware version %X.%X.%X\n", -+ (fw_version >> 16) & 0xFF, (fw_version >> 8) & 0xFF, -+ fw_version & 0xFF); -+ } -+ -+ err = saa716x_ir_init(saa716x); -+ if (err) -+ goto fail9; -+ -+ return 0; -+ -+fail9: -+ saa716x_ff_osd_exit(saa716x); -+fail8: -+ saa716x_ff_audio_exit(saa716x); -+fail7: -+ saa716x_ff_video_exit(saa716x); -+fail6: -+ saa716x_dvb_exit(saa716x); -+fail5: -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); -+ -+ /* disable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); -+ -+ vfree(sti7109->iobuf); -+fail4: -+ kfree(sti7109); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_ff_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ saa716x_ir_exit(saa716x); -+ -+ saa716x_ff_osd_exit(saa716x); -+ -+ saa716x_ff_audio_exit(saa716x); -+ -+ saa716x_ff_video_exit(saa716x); -+ -+ saa716x_dvb_exit(saa716x); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); -+ -+ /* disable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); -+ -+ vfree(sti7109->iobuf); -+ -+ saa716x->priv = NULL; -+ kfree(sti7109); -+ -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+static irqreturn_t saa716x_ff_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ struct sti7109_dev *sti7109; -+ u32 msiStatusL; -+ u32 msiStatusH; -+ u32 phiISR; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ sti7109 = saa716x->priv; -+ if (unlikely(sti7109 == NULL)) { -+ printk("%s: sti7109=NULL", __func__); -+ return IRQ_NONE; -+ } -+ if (sti7109->int_count_enable) -+ sti7109->total_int_count++; -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_L), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ msiStatusL = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, msiStatusL); -+ msiStatusH = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, msiStatusH); -+ -+ if (msiStatusL) { -+ if (msiStatusL & MSI_INT_TAGACK_FGPI_2) { -+ if (sti7109->int_count_enable) -+ sti7109->fgpi_int_count[0]++; -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (msiStatusL & MSI_INT_TAGACK_FGPI_3) { -+ if (sti7109->int_count_enable) -+ sti7109->fgpi_int_count[1]++; -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ if (msiStatusH) { -+ //dprintk(SAA716x_INFO, 1, "msiStatusH: %08X", msiStatusH); -+ } -+ -+ if (msiStatusH & MSI_INT_I2CINT_0) { -+ if (sti7109->int_count_enable) -+ sti7109->i2c_int_count[0]++; -+ saa716x->i2c[0].i2c_op = 0; -+ wake_up(&saa716x->i2c[0].i2c_wq); -+ } -+ if (msiStatusH & MSI_INT_I2CINT_1) { -+ if (sti7109->int_count_enable) -+ sti7109->i2c_int_count[1]++; -+ saa716x->i2c[1].i2c_op = 0; -+ wake_up(&saa716x->i2c[1].i2c_wq); -+ } -+ -+ if (msiStatusH & MSI_INT_EXTINT_0) { -+ -+ phiISR = SAA716x_EPRD(PHI_1, FPGA_ADDR_EMI_ISR); -+ //dprintk(SAA716x_INFO, 1, "interrupt status register: %08X", phiISR); -+ -+ if (sti7109->int_count_enable) { -+ int i; -+ sti7109->ext_int_total_count++; -+ for (i = 0; i < 16; i++) -+ if (phiISR & (1 << i)) -+ sti7109->ext_int_source_count[i]++; -+ } -+ -+ if (phiISR & ISR_CMD_MASK) { -+ -+ u32 value; -+ u32 length; -+ /*dprintk(SAA716x_INFO, 1, "CMD interrupt source");*/ -+ -+ value = SAA716x_EPRD(PHI_1, ADDR_CMD_DATA); -+ value = __cpu_to_be32(value); -+ length = (value >> 16) + 2; -+ -+ /*dprintk(SAA716x_INFO, 1, "CMD length: %d", length);*/ -+ -+ if (length > MAX_RESULT_LEN) { -+ dprintk(SAA716x_ERROR, 1, "CMD length %d > %d", length, MAX_RESULT_LEN); -+ length = MAX_RESULT_LEN; -+ } -+ -+ saa716x_phi_read(saa716x, ADDR_CMD_DATA, sti7109->result_data, length); -+ sti7109->result_len = length; -+ sti7109->result_avail = 1; -+ wake_up(&sti7109->result_avail_wq); -+ -+ phiISR &= ~ISR_CMD_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CMD_MASK); -+ } -+ -+ if (phiISR & ISR_READY_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "READY interrupt source");*/ -+ sti7109->cmd_ready = 1; -+ wake_up(&sti7109->cmd_ready_wq); -+ phiISR &= ~ISR_READY_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_READY_MASK); -+ } -+ -+ if (phiISR & ISR_OSD_CMD_MASK) { -+ -+ u32 value; -+ u32 length; -+ /*dprintk(SAA716x_INFO, 1, "OSD CMD interrupt source");*/ -+ -+ value = SAA716x_EPRD(PHI_1, ADDR_OSD_CMD_DATA); -+ value = __cpu_to_be32(value); -+ length = (value >> 16) + 2; -+ -+ /*dprintk(SAA716x_INFO, 1, "OSD CMD length: %d", length);*/ -+ -+ if (length > MAX_RESULT_LEN) { -+ dprintk(SAA716x_ERROR, 1, "OSD CMD length %d > %d", length, MAX_RESULT_LEN); -+ length = MAX_RESULT_LEN; -+ } -+ -+ saa716x_phi_read(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_result_data, length); -+ sti7109->osd_result_len = length; -+ sti7109->osd_result_avail = 1; -+ wake_up(&sti7109->osd_result_avail_wq); -+ -+ phiISR &= ~ISR_OSD_CMD_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_CMD_MASK); -+ } -+ -+ if (phiISR & ISR_OSD_READY_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "OSD_READY interrupt source");*/ -+ sti7109->osd_cmd_ready = 1; -+ wake_up(&sti7109->osd_cmd_ready_wq); -+ phiISR &= ~ISR_OSD_READY_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_READY_MASK); -+ } -+ -+ if (phiISR & ISR_BLOCK_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "BLOCK interrupt source");*/ -+ sti7109->block_done = 1; -+ wake_up(&sti7109->block_done_wq); -+ phiISR &= ~ISR_BLOCK_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BLOCK_MASK); -+ } -+ -+ if (phiISR & ISR_DATA_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "DATA interrupt source");*/ -+ sti7109->data_ready = 1; -+ wake_up(&sti7109->data_ready_wq); -+ phiISR &= ~ISR_DATA_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DATA_MASK); -+ } -+ -+ if (phiISR & ISR_BOOT_FINISH_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "BOOT FINISH interrupt source");*/ -+ sti7109->boot_finished = 1; -+ wake_up(&sti7109->boot_finish_wq); -+ phiISR &= ~ISR_BOOT_FINISH_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BOOT_FINISH_MASK); -+ } -+ -+ if (phiISR & ISR_AUDIO_PTS_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_AUDIO_PTS, data, 8); -+ sti7109->audio_pts = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_AUDIO_PTS_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_AUDIO_PTS_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "AUDIO PTS: %llX", sti7109->audio_pts);*/ -+ } -+ -+ if (phiISR & ISR_VIDEO_PTS_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_VIDEO_PTS, data, 8); -+ sti7109->video_pts = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_VIDEO_PTS_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_VIDEO_PTS_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "VIDEO PTS: %llX", sti7109->video_pts);*/ -+ } -+ -+ if (phiISR & ISR_CURRENT_STC_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_CURRENT_STC, data, 8); -+ sti7109->current_stc = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_CURRENT_STC_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CURRENT_STC_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "CURRENT STC: %llu", sti7109->current_stc);*/ -+ } -+ -+ if (phiISR & ISR_REMOTE_EVENT_MASK) { -+ u8 data[4]; -+ u32 remote_event; -+ -+ saa716x_phi_read(saa716x, ADDR_REMOTE_EVENT, data, 4); -+ remote_event = (data[3] << 24) -+ | (data[2] << 16) -+ | (data[1] << 8) -+ | (data[0]); -+ memset(data, 0, sizeof(data)); -+ saa716x_phi_write(saa716x, ADDR_REMOTE_EVENT, data, 4); -+ -+ phiISR &= ~ISR_REMOTE_EVENT_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_REMOTE_EVENT_MASK); -+ -+ if (remote_event == 0) { -+ dprintk(SAA716x_ERROR, 1, "REMOTE EVENT: %X ignored", remote_event); -+ } else { -+ dprintk(SAA716x_INFO, 1, "REMOTE EVENT: %X", remote_event); -+ saa716x_ir_handler(saa716x, remote_event); -+ } -+ } -+ -+ if (phiISR & ISR_DVO_FORMAT_MASK) { -+ u8 data[4]; -+ u32 format; -+ -+ saa716x_phi_read(saa716x, ADDR_DVO_FORMAT, data, 4); -+ format = (data[0] << 24) -+ | (data[1] << 16) -+ | (data[2] << 8) -+ | (data[3]); -+ -+ phiISR &= ~ISR_DVO_FORMAT_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DVO_FORMAT_MASK); -+ -+ dprintk(SAA716x_INFO, 1, "DVO FORMAT CHANGE: %u", format); -+ } -+ -+ if (phiISR & ISR_LOG_MESSAGE_MASK) { -+ char message[SIZE_LOG_MESSAGE_DATA]; -+ -+ saa716x_phi_read(saa716x, ADDR_LOG_MESSAGE, message, -+ SIZE_LOG_MESSAGE_DATA); -+ -+ phiISR &= ~ISR_LOG_MESSAGE_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_LOG_MESSAGE_MASK); -+ -+ dprintk(SAA716x_INFO, 1, "LOG MESSAGE: %.*s", -+ SIZE_LOG_MESSAGE_DATA, message); -+ } -+ -+ if (phiISR & ISR_FIFO1_EMPTY_MASK) { -+ u32 fifoCtrl; -+ -+ /*dprintk(SAA716x_INFO, 1, "FIFO EMPTY interrupt source");*/ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoCtrl &= ~0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ tasklet_schedule(&sti7109->fifo_tasklet); -+ phiISR &= ~ISR_FIFO1_EMPTY_MASK; -+ } -+ -+ if (phiISR) { -+ dprintk(SAA716x_INFO, 1, "unknown interrupt source"); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, phiISR); -+ } -+ } -+ -+ if (sti7109->int_count_enable) { -+ if (jiffies - sti7109->last_int_ticks >= HZ) { -+ dprintk(SAA716x_INFO, 1, "int count: t: %d, f:%d %d, i:%d %d," -+ "e: %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)", -+ sti7109->total_int_count, -+ sti7109->fgpi_int_count[0], -+ sti7109->fgpi_int_count[1], -+ sti7109->i2c_int_count[0], -+ sti7109->i2c_int_count[1], -+ sti7109->ext_int_total_count, -+ sti7109->ext_int_source_count[0], -+ sti7109->ext_int_source_count[1], -+ sti7109->ext_int_source_count[2], -+ sti7109->ext_int_source_count[3], -+ sti7109->ext_int_source_count[4], -+ sti7109->ext_int_source_count[5], -+ sti7109->ext_int_source_count[6], -+ sti7109->ext_int_source_count[7], -+ sti7109->ext_int_source_count[8], -+ sti7109->ext_int_source_count[9], -+ sti7109->ext_int_source_count[10], -+ sti7109->ext_int_source_count[11], -+ sti7109->ext_int_source_count[12], -+ sti7109->ext_int_source_count[13], -+ sti7109->ext_int_source_count[14], -+ sti7109->ext_int_source_count[15]); -+ sti7109->total_int_count = 0; -+ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); -+ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); -+ sti7109->ext_int_total_count = 0; -+ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); -+ sti7109->last_int_ticks = jiffies; -+ } -+ } -+ return IRQ_HANDLED; -+} -+ -+#define SAA716x_MODEL_S2_6400_DUAL "Technotrend S2 6400 Dual S2 Premium" -+#define SAA716x_DEV_S2_6400_DUAL "2x DVB-S/S2 + Hardware decode" -+ -+static struct stv090x_config tt6400_stv090x_config = { -+ .device = STV0900, -+ .demod_mode = STV090x_DUAL, -+ .clk_mode = STV090x_CLK_EXT, -+ -+ .xtal = 13500000, -+ .address = 0x68, -+ -+ .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ .ts1_clk = 135000000, -+ .ts2_clk = 135000000, -+ -+ .repeater_level = STV090x_RPTLEVEL_16, -+ -+ .tuner_init = NULL, -+ .tuner_set_mode = NULL, -+ .tuner_set_frequency = NULL, -+ .tuner_get_frequency = NULL, -+ .tuner_set_bandwidth = NULL, -+ .tuner_get_bandwidth = NULL, -+ .tuner_set_bbgain = NULL, -+ .tuner_get_bbgain = NULL, -+ .tuner_set_refclk = NULL, -+ .tuner_get_status = NULL, -+}; -+ -+static struct stv6110x_config tt6400_stv6110x_config = { -+ .addr = 0x60, -+ .refclk = 27000000, -+ .clk_div = 2, -+}; -+ -+static struct isl6423_config tt6400_isl6423_config[2] = { -+ { -+ .current_max = SEC_CURRENT_515m, -+ .curlim = SEC_CURRENT_LIM_ON, -+ .mod_extern = 1, -+ .addr = 0x09, -+ }, -+ { -+ .current_max = SEC_CURRENT_515m, -+ .curlim = SEC_CURRENT_LIM_ON, -+ .mod_extern = 1, -+ .addr = 0x08, -+ } -+}; -+ -+ -+static int saa716x_s26400_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *i2c_adapter = &i2c[SAA716x_I2C_BUS_A].i2c_adapter; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ if (count == 0 || count == 1) { -+ adapter->fe = dvb_attach(stv090x_attach, -+ &tt6400_stv090x_config, -+ i2c_adapter, -+ STV090x_DEMODULATOR_0 + count); -+ -+ if (adapter->fe) { -+ struct stv6110x_devctl *ctl; -+ ctl = dvb_attach(stv6110x_attach, -+ adapter->fe, -+ &tt6400_stv6110x_config, -+ i2c_adapter); -+ -+ tt6400_stv090x_config.tuner_init = ctl->tuner_init; -+ tt6400_stv090x_config.tuner_sleep = ctl->tuner_sleep; -+ tt6400_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; -+ tt6400_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; -+ tt6400_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; -+ tt6400_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; -+ tt6400_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; -+ tt6400_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; -+ tt6400_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; -+ tt6400_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; -+ tt6400_stv090x_config.tuner_get_status = ctl->tuner_get_status; -+ -+ if (count == 1) { -+ /* call the init function once to initialize -+ tuner's clock output divider and demod's -+ master clock */ -+ /* The second tuner drives the STV0900 so -+ call it only for adapter 1 */ -+ if (adapter->fe->ops.init) -+ adapter->fe->ops.init(adapter->fe); -+ } -+ -+ dvb_attach(isl6423_attach, -+ adapter->fe, -+ i2c_adapter, -+ &tt6400_isl6423_config[count]); -+ -+ } -+ } -+ return 0; -+} -+ -+static struct saa716x_config saa716x_s26400_config = { -+ .model_name = SAA716x_MODEL_S2_6400_DUAL, -+ .dev_type = SAA716x_DEV_S2_6400_DUAL, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_s26400_frontend_attach, -+ .irq_handler = saa716x_ff_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .i2c_mode = SAA716x_I2C_MODE_IRQ_BUFFERED, -+ -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 2, -+ .worker = demux_worker -+ },{ -+ /* Adapter 1 */ -+ .ts_port = 3, -+ .worker = demux_worker -+ } -+ } -+}; -+ -+ -+static struct pci_device_id saa716x_ff_pci_table[] = { -+ -+ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_DEVEL, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual development version */ -+ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_PROD, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual production version */ -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_ff_pci_table); -+ -+static struct pci_driver saa716x_ff_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_ff_pci_table, -+ .probe = saa716x_ff_pci_probe, -+ .remove = saa716x_ff_pci_remove, -+}; -+ -+static int saa716x_ff_init(void) -+{ -+ return pci_register_driver(&saa716x_ff_pci_driver); -+} -+ -+static void saa716x_ff_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_ff_pci_driver); -+} -+ -+module_init(saa716x_ff_init); -+module_exit(saa716x_ff_exit); -+ -+MODULE_DESCRIPTION("SAA716x FF driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_fgpi.c b/drivers/media/common/saa716x/saa716x_fgpi.c -new file mode 100644 -index 0000000..8bdb13d ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_fgpi.c -@@ -0,0 +1,389 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_dma_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_dma.h" -+#include "saa716x_fgpi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static const u32 mmu_pta_base[] = { -+ MMU_PTA_BASE0, -+ MMU_PTA_BASE1, -+ MMU_PTA_BASE2, -+ MMU_PTA_BASE3, -+ MMU_PTA_BASE4, -+ MMU_PTA_BASE5, -+ MMU_PTA_BASE6, -+ MMU_PTA_BASE7, -+ MMU_PTA_BASE8, -+ MMU_PTA_BASE9, -+ MMU_PTA_BASE10, -+ MMU_PTA_BASE11, -+ MMU_PTA_BASE12, -+ MMU_PTA_BASE13, -+ MMU_PTA_BASE14, -+ MMU_PTA_BASE15, -+}; -+ -+static const u32 mmu_dma_cfg[] = { -+ MMU_DMA_CONFIG0, -+ MMU_DMA_CONFIG1, -+ MMU_DMA_CONFIG2, -+ MMU_DMA_CONFIG3, -+ MMU_DMA_CONFIG4, -+ MMU_DMA_CONFIG5, -+ MMU_DMA_CONFIG6, -+ MMU_DMA_CONFIG7, -+ MMU_DMA_CONFIG8, -+ MMU_DMA_CONFIG9, -+ MMU_DMA_CONFIG10, -+ MMU_DMA_CONFIG11, -+ MMU_DMA_CONFIG12, -+ MMU_DMA_CONFIG13, -+ MMU_DMA_CONFIG14, -+ MMU_DMA_CONFIG15, -+}; -+ -+static const u32 fgpi_ch[] = { -+ FGPI0, -+ FGPI1, -+ FGPI2, -+ FGPI3 -+}; -+ -+static const u32 bamdma_bufmode[] = { -+ BAM_FGPI0_DMA_BUF_MODE, -+ BAM_FGPI1_DMA_BUF_MODE, -+ BAM_FGPI2_DMA_BUF_MODE, -+ BAM_FGPI3_DMA_BUF_MODE -+}; -+ -+static const u32 msi_int_tagack[] = { -+ MSI_INT_TAGACK_FGPI_0, -+ MSI_INT_TAGACK_FGPI_1, -+ MSI_INT_TAGACK_FGPI_2, -+ MSI_INT_TAGACK_FGPI_3 -+}; -+ -+static const u32 msi_int_ovrflw[] = { -+ MSI_INT_OVRFLW_FGPI_0, -+ MSI_INT_OVRFLW_FGPI_1, -+ MSI_INT_OVRFLW_FGPI_2, -+ MSI_INT_OVRFLW_FGPI_3 -+}; -+ -+static const u32 msi_int_avint[] = { -+ MSI_INT_AVINT_FGPI_0, -+ MSI_INT_AVINT_FGPI_1, -+ MSI_INT_AVINT_FGPI_2, -+ MSI_INT_AVINT_FGPI_3 -+}; -+ -+void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 fgpi_port; -+ -+ fgpi_port = fgpi_ch[channel]; -+ -+ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0); /* disable FGPI IRQ */ -+ SAA716x_EPWR(fgpi_port, INT_CLR_STATUS, 0x7f); /* clear status */ -+} -+EXPORT_SYMBOL_GPL(saa716x_fgpiint_disable); -+ -+int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, u32 fgpi_index) -+{ -+ u32 fgpi_base; -+ u32 buf_mode_reg; -+ u32 buf_mode; -+ -+ switch (fgpi_index) { -+ case 0: /* FGPI_0 */ -+ fgpi_base = FGPI0; -+ buf_mode_reg = BAM_FGPI0_DMA_BUF_MODE; -+ break; -+ -+ case 1: /* FGPI_1 */ -+ fgpi_base = FGPI1; -+ buf_mode_reg = BAM_FGPI1_DMA_BUF_MODE; -+ break; -+ -+ case 2: /* FGPI_2 */ -+ fgpi_base = FGPI2; -+ buf_mode_reg = BAM_FGPI2_DMA_BUF_MODE; -+ break; -+ -+ case 3: /* FGPI_3 */ -+ fgpi_base = FGPI3; -+ buf_mode_reg = BAM_FGPI3_DMA_BUF_MODE; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s: unexpected fgpi %u\n", -+ __func__, fgpi_index); -+ return -1; -+ } -+ -+ buf_mode = SAA716x_EPRD(BAM, buf_mode_reg); -+ if (saa716x->revision < 2) { -+ /* workaround for revision 1: restore buffer numbers on BAM */ -+ SAA716x_EPWR(fgpi_base, INT_CLR_STATUS, 0x7F); -+ SAA716x_EPWR(BAM, buf_mode_reg, buf_mode | 7); -+ } -+ return (buf_mode >> 3) & 0x7; -+} -+EXPORT_SYMBOL_GPL(saa716x_fgpi_get_write_index); -+ -+static u32 saa716x_init_ptables(struct saa716x_dmabuf *dmabuf, int channel) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 config, i; -+ -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); -+ -+ config = mmu_dma_cfg[channel]; /* DMACONFIGx */ -+ -+ SAA716x_EPWR(MMU, config, (FGPI_BUFFERS - 1)); -+ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ -+ -+ return 0; -+} -+ -+int saa716x_fgpi_setparams(struct saa716x_dmabuf *dmabuf, -+ struct fgpi_stream_params *stream_params, -+ int port) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 fgpi_port, buf_mode, val, mid; -+ u32 D1_XY_END, offst_1, offst_2; -+ int i = 0; -+ -+ fgpi_port = fgpi_ch[port]; -+ buf_mode = bamdma_bufmode[port]; -+ -+ /* Reset FGPI block */ -+ SAA716x_EPWR(fgpi_port, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ -+ /* Reset DMA channel */ -+ SAA716x_EPWR(BAM, buf_mode, 0x00000040); -+ saa716x_init_ptables(dmabuf, saa716x->fgpi[port].dma_channel); -+ -+ -+ /* monitor BAM reset */ -+ val = SAA716x_EPRD(BAM, buf_mode); -+ while (val && (i < 100)) { -+ msleep(30); -+ val = SAA716x_EPRD(BAM, buf_mode); -+ i++; -+ } -+ -+ if (val) { -+ dprintk(SAA716x_ERROR, 1, "Error: BAM FGPI Reset failed!"); -+ return -EIO; -+ } -+ -+ /* set buffer count */ -+ SAA716x_EPWR(BAM, buf_mode, FGPI_BUFFERS - 1); -+ -+ /* initialize all available address offsets */ -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_0(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_1(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_2(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_3(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_4(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_5(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_6(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_7(port), 0x0); -+ -+ /* get module ID */ -+ mid = SAA716x_EPRD(fgpi_port, FGPI_MODULE_ID); -+ if (mid != 0x14b0100) -+ dprintk(SAA716x_ERROR, 1, "FGPI Id<%04x> is not supported", mid); -+ -+ /* Initialize FGPI block */ -+ SAA716x_EPWR(fgpi_port, FGPI_REC_SIZE, stream_params->samples * (stream_params->bits / 8)); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); -+ -+ offst_1 = 0; -+ offst_2 = 0; -+ switch (stream_params->stream_type) { -+ case FGPI_TRANSPORT_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ break; -+ -+ case FGPI_PROGRAM_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ break; -+ -+ case FGPI_VIDEO_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); -+ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_START, 0x00000002); -+ -+ if ((stream_params->stream_flags & FGPI_INTERLACED) && -+ (stream_params->stream_flags & FGPI_ODD_FIELD) && -+ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { -+ -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines / 2); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 4); /* interlaced stride of 2 lines */ -+ -+ D1_XY_END = (stream_params->samples << 16); -+ D1_XY_END |= (stream_params->lines / 2) + 2; -+ -+ if (stream_params->stream_flags & FGPI_PAL) -+ offst_1 = 768 * 2; -+ else -+ offst_2 = 768 * 2; -+ -+ } else { -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 2); /* stride of 1 line */ -+ -+ D1_XY_END = stream_params->samples << 16; -+ D1_XY_END |= stream_params->lines + 2; -+ } -+ -+ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_END, D1_XY_END); -+ break; -+ -+ default: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); -+ break; -+ } -+ -+ SAA716x_EPWR(fgpi_port, FGPI_BASE_1, ((saa716x->fgpi[port].dma_channel) << 21) + offst_1); -+ SAA716x_EPWR(fgpi_port, FGPI_BASE_2, ((saa716x->fgpi[port].dma_channel) << 21) + offst_2); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, -+ struct fgpi_stream_params *stream_params) -+{ -+ u32 fgpi_port; -+ u32 config; -+ u32 val; -+ u32 i; -+ -+ fgpi_port = fgpi_ch[port]; -+ -+ SAA716x_EPWR(fgpi_port, FGPI_INTERFACE, 0); -+ msleep(10); -+ -+ if (saa716x_fgpi_setparams(saa716x->fgpi[port].dma_buf, stream_params, port) != 0) { -+ return -EIO; -+ } -+ -+ config = mmu_dma_cfg[saa716x->fgpi[port].dma_channel]; /* DMACONFIGx */ -+ -+ val = SAA716x_EPRD(MMU, config); -+ SAA716x_EPWR(MMU, config, val & ~0x40); -+ SAA716x_EPWR(MMU, config, val | 0x40); -+ -+ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0x7F); -+ -+ val = SAA716x_EPRD(MMU, config); -+ i = 0; -+ while (i < 500) { -+ if (val & 0x80) -+ break; -+ msleep(10); -+ val = SAA716x_EPRD(MMU, config); -+ i++; -+ } -+ -+ if (!(val & 0x80)) { -+ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); -+ return -EIO; -+ } -+ -+ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); -+ val |= 0x3000; -+ -+ saa716x_set_clk_external(saa716x, saa716x->fgpi[port].dma_channel); -+ -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port) -+{ -+ u32 fgpi_port; -+ u32 val; -+ -+ fgpi_port = fgpi_ch[port]; -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); -+ -+ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); -+ val &= ~0x3000; -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); -+ -+ saa716x_set_clk_internal(saa716x, saa716x->fgpi[port].dma_channel); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, -+ void (*worker)(unsigned long)) -+{ -+ int i; -+ int ret; -+ -+ saa716x->fgpi[port].dma_channel = port + 6; -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ { -+ /* TODO: what is a good size for TS DMA buffer? */ -+ ret = saa716x_dmabuf_alloc(saa716x, &saa716x->fgpi[port].dma_buf[i], 16 * SAA716x_PAGE_SIZE); -+ if (ret < 0) { -+ return ret; -+ } -+ } -+ saa716x->fgpi[port].saa716x = saa716x; -+ tasklet_init(&saa716x->fgpi[port].tasklet, worker, -+ (unsigned long)&saa716x->fgpi[port]); -+ saa716x->fgpi[port].read_index = 0; -+ -+ return 0; -+} -+ -+int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port) -+{ -+ int i; -+ -+ tasklet_kill(&saa716x->fgpi[port].tasklet); -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ { -+ saa716x_dmabuf_free(saa716x, &saa716x->fgpi[port].dma_buf[i]); -+ } -+ -+ return 0; -+} -diff --git a/drivers/media/common/saa716x/saa716x_fgpi.h b/drivers/media/common/saa716x/saa716x_fgpi.h -new file mode 100644 -index 0000000..225aff0 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_fgpi.h -@@ -0,0 +1,112 @@ -+#ifndef __SAA716x_FGPI_H -+#define __SAA716x_FGPI_H -+ -+#include -+ -+#define FGPI_BUFFERS 8 -+#define PTA_LSB(__mem) ((u32 ) (__mem)) -+#define PTA_MSB(__mem) ((u32 ) ((u64)(__mem) >> 32)) -+ -+#define BAM_DMA_BUF_MODE_BASE 0x0d8 -+#define BAM_DMA_BUF_MODE_OFFSET 0x24 -+ -+#define BAM_DMA_BUF_MODE(__ch) (BAM_DMA_BUF_MODE_BASE + (BAM_DMA_BUF_MODE_OFFSET * __ch)) -+ -+#define BAM_FGPI_ADDR_OFFST_BASE 0x0dc -+#define BAM_FGPI_ADDR_OFFST_OFFSET 0x24 -+ -+#define BAM_FGPI_ADDR_OFFSET(__ch) (BAM_FGPI_ADDR_OFFST_BASE + (BAM_FGPI_ADDR_OFFST_OFFSET * __ch)) -+ -+#define BAM_FGPI_ADDR_OFFST_0(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x00 -+#define BAM_FGPI_ADDR_OFFST_1(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x04 -+#define BAM_FGPI_ADDR_OFFST_2(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x08 -+#define BAM_FGPI_ADDR_OFFST_3(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x0c -+#define BAM_FGPI_ADDR_OFFST_4(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x10 -+#define BAM_FGPI_ADDR_OFFST_5(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x14 -+#define BAM_FGPI_ADDR_OFFST_6(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x18 -+#define BAM_FGPI_ADDR_OFFST_7(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x1c -+ -+struct saa716x_dmabuf; -+ -+/* -+ * Port supported streams -+ * -+ * FGPI_AUDIO_STREAM -+ * FGPI_VIDEO_STREAM -+ * FGPI_VBI_STREAM -+ * FGPI_TRANSPORT_STREAM -+ * FGPI_PROGRAM_STREAM -+ */ -+enum fgpi_stream_type { -+ FGPI_AUDIO_STREAM = 0x01, -+ FGPI_VIDEO_STREAM = 0x02, -+ FGPI_VBI_STREAM = 0x04, -+ FGPI_TRANSPORT_STREAM = 0x08, -+ FGPI_PROGRAM_STREAM = 0x10 -+}; -+ -+/* -+ * Stream port flags -+ * -+ * FGPI_ODD_FIELD -+ * FGPI_EVEN_FIELD -+ * FGPI_HD_0 -+ * FGPI_HD_1 -+ * FGPI_PAL -+ * FGPI_NTSC -+ */ -+enum fgpi_stream_flags { -+ FGPI_ODD_FIELD = 0x0001, -+ FGPI_EVEN_FIELD = 0x0002, -+ FGPI_INTERLACED = 0x0004, -+ FGPI_HD0 = 0x0010, -+ FGPI_HD1 = 0x0020, -+ FGPI_PAL = 0x0040, -+ FGPI_NTSC = 0x0080, -+ FGPI_NO_SCALER = 0x0100, -+}; -+ -+/* -+ * Stream port parameters -+ * bits: Bits per sample -+ * samples: samples perline -+ * lines: number of lines -+ * pitch: stream pitch in bytes -+ * offset: offset to first valid line -+ */ -+struct fgpi_stream_params { -+ u32 bits; -+ u32 samples; -+ u32 lines; -+ -+ s32 pitch; -+ -+ u32 offset; -+ u32 page_tables; -+ -+ enum fgpi_stream_flags stream_flags; -+ enum fgpi_stream_type stream_type; -+}; -+ -+struct saa716x_dmabuf; -+ -+struct saa716x_fgpi_stream_port { -+ u8 dma_channel; -+ struct saa716x_dmabuf dma_buf[FGPI_BUFFERS]; -+ struct saa716x_dev *saa716x; -+ struct tasklet_struct tasklet; -+ u8 read_index; -+}; -+ -+extern void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel); -+extern int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, -+ u32 fgpi_index); -+extern int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, -+ struct fgpi_stream_params *stream_params); -+extern int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port); -+ -+extern int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, -+ void (*worker)(unsigned long)); -+extern int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port); -+ -+#endif /* __SAA716x_FGPI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_fgpi_reg.h b/drivers/media/common/saa716x/saa716x_fgpi_reg.h -new file mode 100644 -index 0000000..1193016 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_fgpi_reg.h -@@ -0,0 +1,74 @@ -+#ifndef __SAA716x_FGPI_REG_H -+#define __SAA716x_FGPI_REG_H -+ -+/* -------------- FGPI Registers -------------- */ -+ -+#define FGPI_CONTROL 0x000 -+#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) -+#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) -+#define FGPI_MODE (0x00000001 << 11) -+#define FGPI_SAMPLE_SIZE (0x00000003 << 8) -+#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) -+#define FGPI_REC_START_MSG_START (0x00000003 << 2) -+#define FGPI_TSTAMP_SELECT (0x00000001 << 1) -+#define FGPI_VAR_LENGTH (0x00000001 << 0) -+ -+#define FGPI_BASE_1 0x004 -+#define FGPI_BASE_2 0x008 -+#define FGPI_SIZE 0x00c -+#define FGPI_REC_SIZE 0x010 -+#define FGPI_STRIDE 0x014 -+#define FGPI_NUM_RECORD_1 0x018 -+#define FGPI_NUM_RECORD_2 0x01c -+#define FGPI_THRESHOLD_1 0x020 -+#define FGPI_THRESHOLD_2 0x024 -+#define FGPI_D1_XY_START 0x028 -+#define FGPI_D1_XY_END 0x02c -+ -+#define INT_STATUS 0xfe0 -+#define FGPI_BUF1_ACTIVE (0x00000001 << 7) -+#define FGPI_OVERFLOW (0x00000001 << 6) -+#define FGPI_MBE (0x00000001 << 5) -+#define FGPI_UNDERRUN (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED (0x00000001 << 2) -+#define FGPI_BUF2_FULL (0x00000001 << 1) -+#define FGPI_BUF1_FULL (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define FGPI_OVERFLOW_ENA (0x00000001 << 6) -+#define FGPI_MBE_ENA (0x00000001 << 5) -+#define FGPI_UNDERRUN_ENA (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) -+#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) -+#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define FGPI_OVERFLOW_ACK (0x00000001 << 6) -+#define FGPI_MBE_ACK (0x00000001 << 5) -+#define FGPI_UNDERRUN_ACK (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) -+#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) -+#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define FGPI_OVERFLOW_SET (0x00000001 << 6) -+#define FGPI_MBE_SET (0x00000001 << 5) -+#define FGPI_UNDERRUN_SET (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) -+#define FGPI_BUF2_DONE_SET (0x00000001 << 1) -+#define FGPI_BUF1_DONE_SET (0x00000001 << 0) -+ -+#define FGPI_SOFT_RESET 0xff0 -+#define FGPI_SOFTWARE_RESET (0x00000001 << 0) -+ -+#define FGPI_INTERFACE 0xff4 -+#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) -+ -+#define FGPI_MOD_ID_EXT 0xff8 -+#define FGPI_MODULE_ID 0xffc -+ -+#endif /* __SAA716x_FGPI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_gpio.c b/drivers/media/common/saa716x/saa716x_gpio.c -new file mode 100644 -index 0000000..62b6112 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_gpio.c -@@ -0,0 +1,140 @@ -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+ -+#include "saa716x_gpio.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+void saa716x_gpio_init(struct saa716x_dev *saa716x) -+{ -+ spin_lock_init(&saa716x->gpio_lock); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_init); -+ -+int saa716x_get_gpio_mode(struct saa716x_dev *saa716x, u32 *config) -+{ -+ *config = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ -+ return 0; -+} -+ -+int saa716x_set_gpio_mode(struct saa716x_dev *saa716x, u32 mask, u32 config) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ reg = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ reg &= ~mask; -+ reg |= (config & mask); -+ SAA716x_EPWR(GPIO, GPIO_WR_MODE, reg); -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+ -+ return 0; -+} -+ -+u32 saa716x_gpio_rd(struct saa716x_dev *saa716x) -+{ -+ return SAA716x_EPRD(GPIO, GPIO_RD); -+} -+ -+void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data) -+{ -+ SAA716x_EPWR(GPIO, GPIO_WR, data); -+} -+ -+void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ -+ reg = SAA716x_EPRD(GPIO, GPIO_OEN); -+ reg &= mask; -+ reg |= bits; -+ SAA716x_EPWR(GPIO, GPIO_OEN, reg); -+ -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+ -+void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ -+ reg = SAA716x_EPRD(GPIO, GPIO_WR); -+ reg &= ~bits; -+ /* TODO ! add maskable config bits in here */ -+ /* reg |= (config->mask & bits) */ -+ reg |= bits; -+ SAA716x_EPWR(GPIO, GPIO_WR, reg); -+ -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+ -+void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_OEN); -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_OEN, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_output); -+ -+void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_OEN); -+ value |= 1 << gpio; -+ SAA716x_EPWR(GPIO, GPIO_OEN, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_input); -+ -+void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ if (mode) -+ value |= 1 << gpio; -+ else -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_WR_MODE, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_mode); -+ -+void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set) -+{ -+ uint32_t value; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ value = SAA716x_EPRD(GPIO, GPIO_WR); -+ if (set) -+ value |= 1 << gpio; -+ else -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_WR, value); -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_write); -+ -+int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_RD); -+ if (value & (1 << gpio)) -+ return 1; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_read); -diff --git a/drivers/media/common/saa716x/saa716x_gpio.h b/drivers/media/common/saa716x/saa716x_gpio.h -new file mode 100644 -index 0000000..a82580b ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_gpio.h -@@ -0,0 +1,26 @@ -+#ifndef __SAA716x_GPIO_H -+#define __SAA716x_GPIO_H -+ -+#define BOOT_MODE GPIO_31 | GPIO_30 -+#define AV_UNIT_B GPIO_25 -+#define AV_UNIT_A GPIO_24 -+#define AV_INTR_B GPIO_01 -+#define AV_INTR_A GPIO_00 -+ -+struct saa716x_dev; -+ -+extern void saa716x_gpio_init(struct saa716x_dev *saa716x); -+ -+extern u32 saa716x_gpio_rd(struct saa716x_dev *saa716x); -+extern void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data); -+extern void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits); -+ -+extern void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits); -+ -+extern void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio); -+extern void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio); -+extern void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode); -+extern void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set); -+extern int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio); -+ -+#endif /* __SAA716x_GPIO_H */ -diff --git a/drivers/media/common/saa716x/saa716x_gpio_reg.h b/drivers/media/common/saa716x/saa716x_gpio_reg.h -new file mode 100644 -index 0000000..f36184a ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_gpio_reg.h -@@ -0,0 +1,47 @@ -+#ifndef __SAA716x_GPIO_REG_H -+#define __SAA716x_GPIO_REG_H -+ -+/* -------------- GPIO Registers -------------- */ -+ -+#define GPIO_RD 0x000 -+#define GPIO_WR 0x004 -+#define GPIO_WR_MODE 0x008 -+#define GPIO_OEN 0x00c -+ -+#define GPIO_SW_RST 0xff0 -+#define GPIO_SW_RESET (0x00000001 << 0) -+ -+#define GPIO_31 (1 << 31) -+#define GPIO_30 (1 << 30) -+#define GPIO_29 (1 << 29) -+#define GPIO_28 (1 << 28) -+#define GPIO_27 (1 << 27) -+#define GPIO_26 (1 << 26) -+#define GPIO_25 (1 << 25) -+#define GPIO_24 (1 << 24) -+#define GPIO_23 (1 << 23) -+#define GPIO_22 (1 << 22) -+#define GPIO_21 (1 << 21) -+#define GPIO_20 (1 << 20) -+#define GPIO_19 (1 << 19) -+#define GPIO_18 (1 << 18) -+#define GPIO_17 (1 << 17) -+#define GPIO_16 (1 << 16) -+#define GPIO_15 (1 << 15) -+#define GPIO_14 (1 << 14) -+#define GPIO_13 (1 << 13) -+#define GPIO_12 (1 << 12) -+#define GPIO_11 (1 << 11) -+#define GPIO_10 (1 << 10) -+#define GPIO_09 (1 << 9) -+#define GPIO_08 (1 << 8) -+#define GPIO_07 (1 << 7) -+#define GPIO_06 (1 << 6) -+#define GPIO_05 (1 << 5) -+#define GPIO_04 (1 << 4) -+#define GPIO_03 (1 << 3) -+#define GPIO_02 (1 << 2) -+#define GPIO_01 (1 << 1) -+#define GPIO_00 (1 << 0) -+ -+#endif /* __SAA716x_GPIO_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_greg.c b/drivers/media/common/saa716x/saa716x_greg.c -new file mode 100644 -index 0000000..d93a3b8 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_greg.c -@@ -0,0 +1,42 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_greg_reg.h" -+#include "saa716x_greg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static u32 g_save[12]; -+ -+void saa716x_greg_save(struct saa716x_dev *saa716x) -+{ -+ g_save[0] = SAA716x_EPRD(GREG, GREG_SUBSYS_CONFIG); -+ g_save[1] = SAA716x_EPRD(GREG, GREG_MSI_BAR_PMCSR); -+ g_save[2] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_1); -+ g_save[3] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_2); -+ g_save[4] = SAA716x_EPRD(GREG, GREG_VI_CTRL); -+ g_save[5] = SAA716x_EPRD(GREG, GREG_FGPI_CTRL); -+ g_save[6] = SAA716x_EPRD(GREG, GREG_RSTU_CTRL); -+ g_save[7] = SAA716x_EPRD(GREG, GREG_I2C_CTRL); -+ g_save[8] = SAA716x_EPRD(GREG, GREG_OVFLW_CTRL); -+ g_save[9] = SAA716x_EPRD(GREG, GREG_TAG_ACK_FLEN); -+ -+ g_save[10] = SAA716x_EPRD(GREG, GREG_VIDEO_IN_CTRL); -+} -+ -+void saa716x_greg_restore(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, g_save[0]); -+ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, g_save[1]); -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, g_save[2]); -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, g_save[3]); -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, g_save[4]); -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, g_save[5]); -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, g_save[6]); -+ SAA716x_EPWR(GREG, GREG_I2C_CTRL, g_save[7]); -+ SAA716x_EPWR(GREG, GREG_OVFLW_CTRL, g_save[8]); -+ SAA716x_EPWR(GREG, GREG_TAG_ACK_FLEN, g_save[9]); -+ -+ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, g_save[10]); -+} -diff --git a/drivers/media/common/saa716x/saa716x_greg.h b/drivers/media/common/saa716x/saa716x_greg.h -new file mode 100644 -index 0000000..487595e ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_greg.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_GREG_H -+#define __SAA716x_GREG_H -+ -+struct saa716x_dev; -+ -+extern void saa716x_greg_save(struct saa716x_dev *saa716x); -+extern void saa716x_greg_restore(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_GREG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_greg_reg.h b/drivers/media/common/saa716x/saa716x_greg_reg.h -new file mode 100644 -index 0000000..052e8cd ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_greg_reg.h -@@ -0,0 +1,91 @@ -+#ifndef __SAA716x_GREG_REG_H -+#define __SAA716x_GREG_REG_H -+ -+/* -------------- GREG Registers -------------- */ -+ -+#define GREG_SUBSYS_CONFIG 0x000 -+#define GREG_SUBSYS_ID (0x0000ffff << 16) -+#define GREG_SUBSYS_VID (0x0000ffff << 0) -+ -+#define GREG_MSI_BAR_PMCSR 0x004 -+#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) -+#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) -+#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) -+#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) -+#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) -+#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) -+#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) -+#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) -+ -+#define GREG_BAR_WIDTH_17 (0x0000001e << 8) -+#define GREG_BAR_WIDTH_18 (0x0000001c << 8) -+#define GREG_BAR_WIDTH_19 (0x00000018 << 8) -+#define GREG_BAR_WIDTH_20 (0x00000010 << 8) -+ -+#define GREG_BAR_PREFETCH (0x00000001 << 3) -+#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! -+#define GREG_MSI_MM_CAP2 (0x00000001 << 0) -+#define GREG_MSI_MM_CAP4 (0x00000002 << 0) -+#define GREG_MSI_MM_CAP8 (0x00000003 << 0) -+#define GREG_MSI_MM_CAP16 (0x00000004 << 0) -+#define GREG_MSI_MM_CAP32 (0x00000005 << 0) -+ -+#define GREG_PMCSR_DATA_1 0x008 -+#define GREG_PMCSR_DATA_2 0x00c -+#define GREG_VI_CTRL 0x010 -+#define GREG_FGPI_CTRL 0x014 -+ -+#define GREG_RSTU_CTRL 0x018 -+#define GREG_BOOT_READY (0x00000001 << 13) -+#define GREG_RESET_REQ (0x00000001 << 12) -+#define GREG_IP_RST_RELEASE (0x00000001 << 11) -+#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) -+#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) -+#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) -+#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) -+#define GREG_CGU_RST_RELEASE (0x00000001 << 6) -+#define GREG_IP_RST_ASSERT (0x00000001 << 5) -+#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) -+#define GREG_RST_ASSERT (0x00000001 << 3) -+#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) -+#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) -+#define GREG_CGU_RST_ASSERT (0x00000001 << 0) -+ -+#define GREG_I2C_CTRL 0x01c -+#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) -+ -+#define GREG_OVFLW_CTRL 0x020 -+#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) -+ -+#define GREG_TAG_ACK_FLEN 0x024 -+#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) -+#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) -+#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) -+#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) -+ -+#define GREG_VIDEO_IN_CTRL 0x028 -+ -+#define GREG_SPARE_1 0x02c -+#define GREG_SPARE_2 0x030 -+#define GREG_SPARE_3 0x034 -+#define GREG_SPARE_4 0x038 -+#define GREG_SPARE_5 0x03c -+#define GREG_SPARE_6 0x040 -+#define GREG_SPARE_7 0x044 -+#define GREG_SPARE_8 0x048 -+#define GREG_SPARE_9 0x04c -+#define GREG_SPARE_10 0x050 -+#define GREG_SPARE_11 0x054 -+#define GREG_SPARE_12 0x058 -+#define GREG_SPARE_13 0x05c -+#define GREG_SPARE_14 0x060 -+#define GREG_SPARE_15 0x064 -+ -+#define GREG_FAIL_DISABLE 0x068 -+#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) -+ -+#define GREG_SW_RST 0xff0 -+#define GREG_SW_RESET (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_GREG_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_hybrid.c b/drivers/media/common/saa716x/saa716x_hybrid.c -new file mode 100644 -index 0000000..27e5e71 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_hybrid.c -@@ -0,0 +1,726 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_hybrid.h" -+#include "saa716x_gpio.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "zl10353.h" -+#include "mb86a16.h" -+#include "tda1004x.h" -+#include "tda827x.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+#define DRIVER_NAME "SAA716x Hybrid" -+ -+static int saa716x_hybrid_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ int err = 0; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_hybrid_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ /* enable decoders on 7162 */ -+ if (pdev->device == SAA7162) { -+ saa716x_gpio_set_output(saa716x, 24); -+ saa716x_gpio_set_output(saa716x, 25); -+ -+ saa716x_gpio_write(saa716x, 24, 0); -+ saa716x_gpio_write(saa716x, 25, 0); -+ -+ msleep(10); -+ -+ saa716x_gpio_write(saa716x, 24, 1); -+ saa716x_gpio_write(saa716x, 25, 1); -+ } -+ -+ /* set default port mapping */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F44); -+ /* enable FGPI3 and FGPI0 for TS input from Port 3 and 6 */ -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x894); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail4; -+ } -+ -+ return 0; -+ -+fail4: -+ saa716x_dvb_exit(saa716x); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_hybrid_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ -+ saa716x_dvb_exit(saa716x); -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static irqreturn_t saa716x_hybrid_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ u32 stat_h, stat_l, mask_h, mask_l; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ -+ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ stat_l, stat_h, mask_l, mask_h); -+ -+ if (!((stat_l & mask_l) || (stat_h & mask_h))) -+ return IRQ_NONE; -+ -+ if (stat_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); -+ -+ if (stat_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); -+ -+ saa716x_msi_event(saa716x, stat_l, stat_h); -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ -+ if (stat_l) { -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) { -+ tasklet_schedule(&saa716x->fgpi[0].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) { -+ tasklet_schedule(&saa716x->fgpi[1].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) { -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) { -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+/* -+ * Twinhan/Azurewave VP-6090 -+ * DVB-S Frontend: 2x MB86A16 -+ * DVB-T Frontend: 2x TDA10046 + TDA8275 -+ */ -+#define SAA716x_MODEL_TWINHAN_VP6090 "Twinhan/Azurewave VP-6090" -+#define SAA716x_DEV_TWINHAN_VP6090 "2xDVB-S + 2xDVB-T + 2xAnalog" -+ -+static int tda1004x_vp6090_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_vp6090_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_4M, -+ .agc_config = TDA10046_AGC_DEFAULT, -+ .if_freq = TDA10046_FREQ_3617, -+ .request_firmware = tda1004x_vp6090_request_firmware, -+}; -+ -+static int vp6090_dvbs_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) -+{ -+ struct saa716x_dev *saa716x = fe->dvb->priv; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); -+ break; -+ case SEC_VOLTAGE_18: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); -+ break; -+ case SEC_VOLTAGE_OFF: -+ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+struct mb86a16_config vp6090_mb86a16_config = { -+ .demod_address = 0x08, -+ .set_voltage = vp6090_dvbs_set_voltage, -+}; -+ -+static int saa716x_vp6090_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[count]; -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); -+ -+ saa716x_gpio_set_output(saa716x, 11); -+ saa716x_gpio_set_output(saa716x, 10); -+ saa716x_gpio_write(saa716x, 11, 1); -+ saa716x_gpio_write(saa716x, 10, 1); -+ msleep(100); -+#if 0 -+ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); -+ adapter->fe = mb86a16_attach(&vp6090_mb86a16_config, &i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", -+ vp6090_mb86a16_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+#endif -+ adapter->fe = tda10046_attach(&tda1004x_vp6090_config, &i2c->i2c_adapter); -+ if (adapter->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+ } else { -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+ -+ return 0; -+} -+ -+static struct saa716x_config saa716x_vp6090_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP6090, -+ .dev_type = SAA716x_DEV_TWINHAN_VP6090, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp6090_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+/* -+ * NXP Reference design (Atlantis) -+ * 2x DVB-T Frontend: 2x TDA10046 -+ * Analog Decoder: 2x Internal -+ */ -+#define SAA716x_MODEL_NXP_ATLANTIS "Atlantis reference board" -+#define SAA716x_DEV_NXP_ATLANTIS "2x DVB-T + 2x Analog" -+ -+static int tda1004x_atlantis_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_atlantis_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_16M, -+ .agc_config = TDA10046_AGC_TDA827X, -+ .if_freq = TDA10046_FREQ_045, -+ .request_firmware = tda1004x_atlantis_request_firmware, -+ .tuner_address = 0x60, -+}; -+ -+static struct tda827x_config tda827x_atlantis_config = { -+ .init = NULL, -+ .sleep = NULL, -+ .config = 0, -+ .switch_addr = 0, -+ .agcf = NULL, -+}; -+ -+static int saa716x_atlantis_frontend_attach(struct saa716x_adapter *adapter, -+ int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c; -+ u8 i2c_buf[3] = { 0x05, 0x23, 0x01 }; /* activate the silent I2C bus */ -+ struct i2c_msg msg = { -+ .addr = 0x42 >> 1, -+ .flags = 0, -+ .buf = i2c_buf, -+ .len = sizeof(i2c_buf) -+ }; -+ -+ if (count < saa716x->config->adapters) { -+ u32 reset_gpio; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", -+ count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, -+ saa716x->pdev->subsystem_device); -+ -+ if (count == 0) { -+ reset_gpio = 14; -+ i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; -+ } else { -+ reset_gpio = 15; -+ i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ } -+ -+ /* activate the silent I2C bus */ -+ i2c_transfer(&i2c->i2c_adapter, &msg, 1); -+ -+ saa716x_gpio_set_output(saa716x, reset_gpio); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, reset_gpio, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, reset_gpio, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, reset_gpio, 1); -+ msleep(10); -+ -+ adapter->fe = tda10046_attach(&tda1004x_atlantis_config, -+ &i2c->i2c_adapter); -+ if (adapter->fe == NULL) -+ goto exit; -+ -+ dprintk(SAA716x_ERROR, 1, -+ "found TDA10046 DVB-T frontend @0x%02x", -+ tda1004x_atlantis_config.demod_address); -+ -+ if (dvb_attach(tda827x_attach, adapter->fe, -+ tda1004x_atlantis_config.tuner_address, -+ &i2c->i2c_adapter, &tda827x_atlantis_config)) { -+ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", -+ tda1004x_atlantis_config.tuner_address); -+ } else { -+ goto exit; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_atlantis_config = { -+ .model_name = SAA716x_MODEL_NXP_ATLANTIS, -+ .dev_type = SAA716x_DEV_NXP_ATLANTIS, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_atlantis_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 3, /* using FGPI 3 */ -+ .worker = demux_worker -+ }, -+ { -+ /* Adapter 1 */ -+ .ts_port = 0, /* using FGPI 0 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+/* -+ * NXP Reference design (NEMO) -+ * DVB-T Frontend: 1x TDA10046 + TDA8275 -+ * Analog Decoder: External SAA7136 -+ */ -+#define SAA716x_MODEL_NXP_NEMO "NEMO reference board" -+#define SAA716x_DEV_NXP_NEMO "DVB-T + Analog" -+ -+static int tda1004x_nemo_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_nemo_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_16M, -+ .agc_config = TDA10046_AGC_TDA827X, -+ .if_freq = TDA10046_FREQ_045, -+ .request_firmware = tda1004x_nemo_request_firmware, -+ .tuner_address = 0x60, -+}; -+ -+static struct tda827x_config tda827x_nemo_config = { -+ .init = NULL, -+ .sleep = NULL, -+ .config = 0, -+ .switch_addr = 0, -+ .agcf = NULL, -+}; -+ -+static int saa716x_nemo_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *demod_i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ struct saa716x_i2c *tuner_i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; -+ -+ -+ if (count == 0) { -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); -+ -+ /* GPIO 26 controls a +15dB gain */ -+ saa716x_gpio_set_output(saa716x, 26); -+ saa716x_gpio_write(saa716x, 26, 0); -+ -+ saa716x_gpio_set_output(saa716x, 14); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, 14, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 14, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 14, 1); -+ msleep(10); -+ -+ adapter->fe = tda10046_attach(&tda1004x_nemo_config, -+ &demod_i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found TDA10046 DVB-T frontend @0x%02x", -+ tda1004x_nemo_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+ if (dvb_attach(tda827x_attach, adapter->fe, -+ tda1004x_nemo_config.tuner_address, -+ &tuner_i2c->i2c_adapter, &tda827x_nemo_config)) { -+ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", -+ tda1004x_nemo_config.tuner_address); -+ } else { -+ goto exit; -+ } -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ } -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_nemo_config = { -+ .model_name = SAA716x_MODEL_NXP_NEMO, -+ .dev_type = SAA716x_DEV_NXP_NEMO, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_nemo_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 3, /* using FGPI 3 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+ -+#define SAA716x_MODEL_AVERMEDIA_HC82 "Avermedia HC82 Express-54" -+#define SAA716x_DEV_AVERMEDIA_HC82 "DVB-T + Analog" -+ -+#if 0 -+static struct zl10353_config saa716x_averhc82_zl10353_config = { -+ .demod_address = 0x1f, -+ .adc_clock = 450560, -+ .if2 = 361667, -+ .no_tuner = 1, -+ .parallel_ts = 1, -+}; -+#endif -+ -+static int saa716x_averhc82_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+// adapter->fe = zl10353_attach(&saa716x_averhc82_zl10353_config, &i2c->i2c_adapter); -+ -+ -+ return 0; -+} -+ -+static struct saa716x_config saa716x_averhc82_config = { -+ .model_name = SAA716x_MODEL_AVERMEDIA_HC82, -+ .dev_type = SAA716x_DEV_AVERMEDIA_HC82, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_averhc82_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+#define SAA716x_MODEL_AVERMEDIA_H788 "Avermedia H788" -+#define SAA716x_DEV_AVERMEDIA_H788 "DVB-T + Analaog" -+ -+static int saa716x_averh88_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_averh788_config = { -+ .model_name = SAA716x_MODEL_AVERMEDIA_H788, -+ .dev_type = SAA716x_DEV_AVERMEDIA_H788, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_averh88_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+static struct pci_device_id saa716x_hybrid_pci_table[] = { -+ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6090, SAA7162, &saa716x_vp6090_config), -+ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_HC82, SAA7160, &saa716x_averhc82_config), -+ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_H788, SAA7160, &saa716x_averh788_config), -+ MAKE_ENTRY(KWORLD, KWORLD_DVB_T_PE310, SAA7162, &saa716x_atlantis_config), -+ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7162, &saa716x_atlantis_config), -+ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7160, &saa716x_nemo_config), -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_hybrid_pci_table); -+ -+static struct pci_driver saa716x_hybrid_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_hybrid_pci_table, -+ .probe = saa716x_hybrid_pci_probe, -+ .remove = saa716x_hybrid_pci_remove, -+}; -+ -+static int saa716x_hybrid_init(void) -+{ -+ return pci_register_driver(&saa716x_hybrid_pci_driver); -+} -+ -+static void saa716x_hybrid_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_hybrid_pci_driver); -+} -+ -+module_init(saa716x_hybrid_init); -+module_exit(saa716x_hybrid_exit); -+ -+MODULE_DESCRIPTION("SAA716x Hybrid driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_hybrid.h b/drivers/media/common/saa716x/saa716x_hybrid.h -new file mode 100644 -index 0000000..df34a59 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_hybrid.h -@@ -0,0 +1,13 @@ -+#ifndef __SAA716x_HYBRID_H -+#define __SAA716x_HYBRID_H -+ -+#define TWINHAN_TECHNOLOGIES 0x1822 -+#define AVERMEDIA 0x1461 -+#define KWORLD 0x17DE -+ -+#define TWINHAN_VP_6090 0x0027 -+#define AVERMEDIA_HC82 0x2355 -+#define AVERMEDIA_H788 0x1455 -+#define KWORLD_DVB_T_PE310 0x7521 -+ -+#endif /* __SAA716x_HYBRID_H */ -diff --git a/drivers/media/common/saa716x/saa716x_i2c.c b/drivers/media/common/saa716x/saa716x_i2c.c -new file mode 100644 -index 0000000..91a091d ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_i2c.c -@@ -0,0 +1,731 @@ -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_i2c_reg.h" -+#include "saa716x_msi_reg.h" -+#include "saa716x_cgu_reg.h" -+ -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#define SAA716x_I2C_TXFAIL (I2C_ERROR_IBE | \ -+ I2C_ACK_INTER_MTNA | \ -+ I2C_FAILURE_INTER_MAF) -+ -+#define SAA716x_I2C_TXBUSY (I2C_TRANSMIT | \ -+ I2C_TRANSMIT_PROG) -+ -+#define SAA716x_I2C_RXBUSY (I2C_RECEIVE | \ -+ I2C_RECEIVE_CLEAR) -+ -+static const char* state[] = { -+ "Idle", -+ "DoneStop", -+ "Busy", -+ "TOscl", -+ "TOarb", -+ "DoneWrite", -+ "DoneRead", -+ "DoneWriteTO", -+ "DoneReadTO", -+ "NoDevice", -+ "NoACK", -+ "BUSErr", -+ "ArbLost", -+ "SEQErr", -+ "STErr" -+}; -+ -+int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus) -+{ -+ u32 stat, mask; -+ u32 *I2C_DEV; -+ -+ BUG_ON(saa716x == NULL); -+ I2C_DEV = saa716x->I2C_DEV; -+ -+ stat = SAA716x_EPRD(I2C_DEV[bus], INT_STATUS); -+ mask = SAA716x_EPRD(I2C_DEV[bus], INT_ENABLE); -+ saa716x->i2c[bus].i2c_stat = stat; -+ dprintk(SAA716x_DEBUG, 0, "Bus(%d) I2C event: Status=<%s> --> Stat=<%02x> Mask=<%02x>", -+ bus, state[stat], stat, mask); -+ -+ if (!(stat & mask)) -+ return -1; -+ -+ SAA716x_EPWR(I2C_DEV[bus], INT_CLR_STATUS, stat); -+ -+ if (stat & I2C_INTERRUPT_STFNF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPT_MTFNF) { -+ dprintk(SAA716x_DEBUG, 0, " "); -+ } -+ -+ if (stat & I2C_INTERRUPT_RFDA) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPTE_RFF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_INTERRUPT_STDR) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_MASTER_INTERRUPT_MTDR) { -+ dprintk(SAA716x_DEBUG, 0, " "); -+ } -+ -+ if (stat & I2C_ERROR_IBE) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_MODE_CHANGE_INTER_MSMC) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_ACK_INTER_MTNA) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_FAILURE_INTER_MAF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPT_MTD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ return 0; -+} -+ -+static irqreturn_t saa716x_i2c_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_L), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_CLR_STATUS), -+ SAA716x_EPRD(I2C_B, INT_CLR_STATUS)); -+ -+ return IRQ_HANDLED; -+} -+ -+static void saa716x_term_xfer(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); /* Start: SCL/SDA High */ -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x00); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); -+ -+ return; -+} -+ -+static void saa716x_i2c_hwdeinit(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+} -+ -+static int saa716x_i2c_hwinit(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ struct i2c_adapter *adapter = &i2c->i2c_adapter; -+ -+ int i, err = 0; -+ u32 reg; -+ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & 0xd)) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed, Exiting !", -+ I2C_DEV, adapter->name); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* Flush queue */ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xcc); -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ -+ /* Reset I2C Core and generate a delay */ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc1); -+ -+ for (i = 0; i < 100; i++) { -+ reg = SAA716x_EPRD(I2C_DEV, I2C_CONTROL); -+ if (reg == 0xc0) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET", -+ I2C_DEV, adapter->name); -+ break; -+ } -+ msleep(1); -+ -+ if (i == 99) -+ err = -EIO; -+ } -+ -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed", -+ I2C_DEV, adapter->name); -+ -+ saa716x_term_xfer(i2c, I2C_DEV); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* I2C Rate Setup */ -+ switch (i2c->i2c_rate) { -+ case SAA716x_I2C_RATE_400: -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 400k", adapter->name); -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x1a); /* 0.5 * 27MHz/400kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x21); /* 0.5 * 27MHz/400kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x19); -+ break; -+ -+ case SAA716x_I2C_RATE_100: -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 100k", adapter->name); -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x68); /* 0.5 * 27MHz/100kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x87); /* 0.5 * 27MHz/100kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x60); -+ break; -+ -+ default: -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter %s Unknown Rate (Rate=0x%02x)", -+ adapter->name, -+ i2c->i2c_rate); -+ -+ break; -+ } -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ -+ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ /* Enabled interrupts: -+ * Master Transaction Done, -+ * Master Transaction Data Request -+ * (0x81) -+ */ -+ msleep(5); -+ -+ SAA716x_EPWR(I2C_DEV, INT_SET_ENABLE, -+ I2C_SET_ENABLE_MTDR | I2C_SET_ENABLE_MTD); -+ -+ /* Check interrupt enable status */ -+ reg = SAA716x_EPRD(I2C_DEV, INT_ENABLE); -+ if (reg != 0x81) { -+ -+ dprintk(SAA716x_ERROR, 1, -+ "Adapter (%d) %s Interrupt enable failed, Exiting !", -+ i, -+ adapter->name); -+ -+ err = -EIO; -+ goto exit; -+ } -+ } -+ -+ /* Check status */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & 0xd)) { -+ -+ dprintk(SAA716x_ERROR, 1, -+ "Adapter (%02x) %s has bad state, Exiting !", -+ I2C_DEV, -+ adapter->name); -+ -+ err = -EIO; -+ goto exit; -+ } -+#if 0 -+ saa716x_add_irqvector(saa716x, -+ i2c_vec[i].vector, -+ i2c_vec[i].edge, -+ i2c_vec[i].handler, -+ SAA716x_I2C_ADAPTER(i)); -+#endif -+ reg = SAA716x_EPRD(CGU, CGU_SCR_3); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%02x) Autowake <%d> Active <%d>", -+ I2C_DEV, -+ (reg >> 1) & 0x01, -+ reg & 0x01); -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ int i, err = 0; -+ u32 reg; -+ -+ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ /* Write to FIFO */ -+ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); -+ return 0; -+ } -+ -+ /* Check FIFO status before TX */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ i2c->stat_tx_prior = reg; -+ if (reg & SAA716x_I2C_TXBUSY) { -+ for (i = 0; i < 100; i++) { -+ /* TODO! check for hotplug devices */ -+ msleep(10); -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ -+ if (reg & SAA716x_I2C_TXBUSY) { -+ dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); -+ -+ err = saa716x_i2c_hwinit(i2c, I2C_DEV); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Error Reinit"); -+ err = -EIO; -+ goto exit; -+ } -+ } else { -+ break; -+ } -+ } -+ } -+ -+ /* Write to FIFO */ -+ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); -+ -+ /* Check for data write */ -+ for (i = 0; i < 1000; i++) { -+ /* TODO! check for hotplug devices */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (reg & I2C_TRANSMIT_CLEAR) { -+ break; -+ } -+ } -+ i2c->stat_tx_done = reg; -+ -+ if (!(reg & I2C_TRANSMIT_CLEAR)) { -+ dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); -+ err = -EIO; -+ goto exit; -+ } -+ -+ return err; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); -+ return err; -+} -+ -+static int saa716x_i2c_recv(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 *data) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ int i, err = 0; -+ u32 reg; -+ -+ /* Check FIFO status before RX */ -+ for (i = 0; i < 1000; i++) { -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & SAA716x_I2C_RXBUSY)) { -+ break; -+ } -+ } -+ if (reg & SAA716x_I2C_RXBUSY) { -+ dprintk(SAA716x_INFO, 1, "FIFO empty"); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* Read from FIFO */ -+ *data = SAA716x_EPRD(I2C_DEV, RX_FIFO); -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error Reading data, err=%d", err); -+ return err; -+} -+ -+static void saa716x_i2c_irq_start(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) -+ return; -+ -+ i2c->i2c_op = 1; -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+} -+ -+static int saa716x_i2c_irq_wait(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ unsigned long timeout; -+ int err = 0; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) -+ return 0; -+ -+ timeout = HZ/100 + 1; /* 10ms */ -+ timeout = wait_event_interruptible_timeout(i2c->i2c_wq, i2c->i2c_op == 0, timeout); -+ if (timeout == -ERESTARTSYS || i2c->i2c_op) { -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ err = -ERESTARTSYS; -+ } else { -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for end of xfer!"); -+ err = -EIO; -+ } -+ } -+ return err; -+} -+ -+static int saa716x_i2c_write_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, -+ u16 addr, u8 *buf, u16 len, u8 add_stop) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ u32 data; -+ int err; -+ int i; -+ int bytes; -+ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ -+ /* first write START with I2C address */ -+ data = I2C_START_BIT | (addr << 1); -+ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Address write failed"); -+ goto exit; -+ } -+ -+ bytes = i2c->block_size - 1; -+ -+ /* now write the data */ -+ while (len > 0) { -+ if (bytes == i2c->block_size) { -+ /* this is not the first round, so restart irq */ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ } -+ -+ if (bytes > len) -+ bytes = len; -+ -+ for (i = 0; i < bytes; i++) { -+ data = buf[i]; -+ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n", i, data); -+ if (add_stop && i == (len - 1)) -+ data |= I2C_STOP_BIT; -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data send failed"); -+ goto exit; -+ } -+ } -+ -+ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); -+ if (err < 0) { -+ goto exit; -+ } -+ -+ len -= bytes; -+ buf += bytes; -+ bytes = i2c->block_size; -+ } -+ -+ return 0; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error writing data, err=%d", err); -+ return err; -+} -+ -+static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, -+ u16 addr, u8 *buf, u16 len, u8 add_stop) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ u32 data; -+ int err; -+ int i; -+ int bytes; -+ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ -+ /* first write START with I2C address */ -+ data = I2C_START_BIT | (addr << 1) | 1; -+ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Address write failed"); -+ goto exit; -+ } -+ -+ bytes = i2c->block_size - 1; -+ -+ /* now read the data */ -+ while (len > 0) { -+ if (bytes == i2c->block_size) { -+ /* this is not the first round, so restart irq */ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ } -+ -+ if (bytes > len) -+ bytes = len; -+ -+ for (i = 0; i < bytes; i++) { -+ data = 0x00; /* dummy write for reading */ -+ if (add_stop && i == (len - 1)) -+ data |= I2C_STOP_BIT; -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data send failed"); -+ goto exit; -+ } -+ } -+ -+ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); -+ if (err < 0) { -+ goto exit; -+ } -+ -+ for (i = 0; i < bytes; i++) { -+ err = saa716x_i2c_recv(i2c, I2C_DEV, &data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data receive failed"); -+ goto exit; -+ } -+ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n\n", i, data); -+ buf[i] = data; -+ } -+ -+ len -= bytes; -+ buf += bytes; -+ bytes = i2c->block_size; -+ } -+ -+ return 0; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); -+ return err; -+} -+ -+static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) -+{ -+ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); -+ int i, j, err = 0; -+ int t; -+ -+ dprintk(SAA716x_DEBUG, 0, "\n"); -+ dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); -+ mutex_lock(&i2c->i2c_lock); -+ -+ for (t = 0; t < 3; t++) { -+ for (i = 0; i < num; i++) { -+ if (msgs[i].flags & I2C_M_RD) -+ err = saa716x_i2c_read_msg(i2c, DEV, -+ msgs[i].addr, msgs[i].buf, msgs[i].len, -+ i == (num - 1)); -+ else -+ err = saa716x_i2c_write_msg(i2c, DEV, -+ msgs[i].addr, msgs[i].buf, msgs[i].len, -+ i == (num - 1)); -+ if (err < 0) { -+ err = -EIO; -+ goto retry; -+ } -+ } -+ break; -+retry: -+ dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); -+ for (i = 0; i < num; i++) { -+ dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", -+ i, msgs[i].addr, msgs[i].len, msgs[i].flags); -+ if (!(msgs[i].flags & I2C_M_RD)) { -+ for (j = 0; j < msgs[i].len; j++) { -+ dprintk(SAA716x_INFO, 1, " 0x%02x", -+ j, msgs[i].buf[j]); -+ } -+ } -+ } -+ err = saa716x_i2c_hwinit(i2c, DEV); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Error Reinit"); -+ err = -EIO; -+ goto bail_out; -+ } -+ } -+ -+ mutex_unlock(&i2c->i2c_lock); -+ return num; -+ -+bail_out: -+ dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); -+ mutex_unlock(&i2c->i2c_lock); -+ return err; -+} -+ -+static u32 saa716x_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm saa716x_algo = { -+ .master_xfer = saa716x_i2c_xfer, -+ .functionality = saa716x_i2c_func, -+}; -+ -+struct saa716x_i2cvec { -+ u32 vector; -+ enum saa716x_edge edge; -+ irqreturn_t (*handler)(int irq, void *dev_id); -+}; -+ -+static const struct saa716x_i2cvec i2c_vec[] = { -+ { -+ .vector = I2CINT_0, -+ .edge = SAA716x_EDGE_RISING, -+ .handler = saa716x_i2c_irq -+ }, { -+ .vector = I2CINT_1, -+ .edge = SAA716x_EDGE_RISING, -+ .handler = saa716x_i2c_irq -+ } -+}; -+ -+int saa716x_i2c_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = NULL; -+ -+ int i, err = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", -+ saa716x->pdev->device); -+ -+ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { -+ -+ mutex_init(&i2c->i2c_lock); -+ -+ init_waitqueue_head(&i2c->i2c_wq); -+ i2c->i2c_op = 0; -+ -+ i2c->i2c_dev = i; -+ i2c->i2c_rate = saa716x->config->i2c_rate; -+ i2c->i2c_mode = saa716x->config->i2c_mode; -+ adapter = &i2c->i2c_adapter; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_IRQ_BUFFERED) -+ i2c->block_size = 8; -+ else -+ i2c->block_size = 1; -+ -+ if (adapter != NULL) { -+ -+ i2c_set_adapdata(adapter, i2c); -+ -+ strcpy(adapter->name, SAA716x_I2C_ADAPTER(i)); -+ -+ adapter->owner = THIS_MODULE; -+ adapter->algo = &saa716x_algo; -+ adapter->algo_data = NULL; -+ adapter->timeout = 500; /* FIXME ! */ -+ adapter->retries = 3; /* FIXME ! */ -+ adapter->dev.parent = &pdev->dev; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing adapter (%d) %s", -+ i, -+ adapter->name); -+ -+ err = i2c_add_adapter(adapter); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s init failed", i, adapter->name); -+ goto exit; -+ } -+ -+ i2c->saa716x = saa716x; -+ saa716x_i2c_hwinit(i2c, SAA716x_I2C_BUS(i)); -+ } -+ i2c++; -+ } -+ -+ if (saa716x->config->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_0); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_1); -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully initialized", -+ saa716x->pdev->device); -+ -+ return 0; -+exit: -+ return err; -+} -+EXPORT_SYMBOL_GPL(saa716x_i2c_init); -+ -+int saa716x_i2c_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = NULL; -+ int i; -+ -+ dprintk(SAA716x_DEBUG, 1, "Removing SAA%02x I2C Core", saa716x->pdev->device); -+ -+ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { -+ -+ adapter = &i2c->i2c_adapter; -+#if 0 -+ saa716x_remove_irqvector(saa716x, i2c_vec[i].vector); -+#endif -+ saa716x_i2c_hwdeinit(i2c, SAA716x_I2C_BUS(i)); -+ dprintk(SAA716x_DEBUG, 1, "Removing adapter (%d) %s", i, adapter->name); -+ -+ i2c_del_adapter(adapter); -+ i2c++; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully removed", saa716x->pdev->device); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_i2c_exit); -diff --git a/drivers/media/common/saa716x/saa716x_i2c.h b/drivers/media/common/saa716x/saa716x_i2c.h -new file mode 100644 -index 0000000..da767ac ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_i2c.h -@@ -0,0 +1,52 @@ -+#ifndef __SAA716x_I2C_H -+#define __SAA716x_I2C_H -+ -+#define SAA716x_I2C_ADAPTERS 2 -+ -+#define SAA716x_I2C_ADAPTER(__dev) (( \ -+ (__dev == 1) ? \ -+ "SAA716x I2C Core 1" : \ -+ "SAA716x I2C Core 0")) -+ -+#define SAA716x_I2C_BUS(__x) ((__x == 1) ? 0x0000c000 : 0x0000b000) -+ -+#define SAA716x_I2C_BUS_A 0x01 -+#define SAA716x_I2C_BUS_B 0x00 -+ -+struct saa716x_dev; -+ -+enum saa716x_i2c_rate { -+ SAA716x_I2C_RATE_400 = 1, -+ SAA716x_I2C_RATE_100, -+}; -+ -+enum saa716x_i2c_mode { -+ SAA716x_I2C_MODE_POLLING = 0, -+ SAA716x_I2C_MODE_IRQ, -+ SAA716x_I2C_MODE_IRQ_BUFFERED -+}; -+ -+struct saa716x_i2c { -+ struct i2c_adapter i2c_adapter; -+ struct mutex i2c_lock; -+ struct saa716x_dev *saa716x; -+ u8 i2c_dev; -+ -+ enum saa716x_i2c_rate i2c_rate; /* run time */ -+ enum saa716x_i2c_mode i2c_mode; -+ u32 block_size; /* block size for buffered -+ mode, 1 otherwise */ -+ u32 i2c_stat; -+ -+ u32 stat_tx_prior; -+ u32 stat_tx_done; -+ wait_queue_head_t i2c_wq; -+ int i2c_op; -+}; -+ -+extern int saa716x_i2c_init(struct saa716x_dev *saa716x); -+extern int saa716x_i2c_exit(struct saa716x_dev *saa716x); -+extern void saa716x_i2cint_disable(struct saa716x_dev *saa716x); -+extern int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus); -+ -+#endif /* __SAA716x_I2C_H */ -diff --git a/drivers/media/common/saa716x/saa716x_i2c_reg.h b/drivers/media/common/saa716x/saa716x_i2c_reg.h -new file mode 100644 -index 0000000..8fa992c ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_i2c_reg.h -@@ -0,0 +1,145 @@ -+#ifndef __SAA716x_I2C_REG_H -+#define __SAA716x_I2C_REG_H -+ -+/* -------------- I2C Registers -------------- */ -+ -+#define RX_FIFO 0x000 -+#define I2C_RX_BYTE (0x000000ff << 0) -+ -+#define TX_FIFO 0x000 -+#define I2C_STOP_BIT (0x00000001 << 9) -+#define I2C_START_BIT (0x00000001 << 8) -+#define I2C_TX_BYTE (0x000000ff << 0) -+ -+#define I2C_STATUS 0x008 -+#define I2C_TRANSMIT (0x00000001 << 11) -+#define I2C_RECEIVE (0x00000001 << 10) -+#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) -+#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) -+#define I2C_TRANSMIT_PROG (0x00000001 << 7) -+#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) -+#define I2C_RECEIVE_PROG (0x00000001 << 5) -+#define I2C_RECEIVE_CLEAR (0x00000001 << 4) -+#define I2C_SDA_LINE (0x00000001 << 3) -+#define I2C_SCL_LINE (0x00000001 << 2) -+#define I2C_START_STOP_FLAG (0x00000001 << 1) -+#define I2C_MODE_STATUS (0x00000001 << 0) -+ -+#define I2C_CONTROL 0x00c -+#define I2C_SCL_CONTROL (0x00000001 << 7) -+#define I2C_SDA_CONTROL (0x00000001 << 6) -+#define I2C_RECEIVE_PROTECT (0x00000001 << 5) -+#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) -+#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) -+#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) -+#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) -+#define I2C_RESET (0x00000001 << 0) -+ -+#define I2C_CLOCK_DIVISOR_HIGH 0x010 -+#define I2C_CLOCK_HIGH (0x0000ffff << 0) -+ -+#define I2C_CLOCK_DIVISOR_LOW 0x014 -+#define I2C_CLOCK_LOW (0x0000ffff << 0) -+ -+#define I2C_RX_LEVEL 0x01c -+#define I2C_RECEIVE_RANGE (0x0000007f << 0) -+ -+#define I2C_TX_LEVEL 0x020 -+#define I2C_TRANSMIT_RANGE (0x0000007f << 0) -+ -+#define I2C_SDA_HOLD 0x028 -+#define I2C_HOLD_TIME (0x0000007f << 0) -+ -+#define MODULE_CONF 0xfd4 -+#define INT_CLR_ENABLE 0xfd8 -+#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) -+#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) -+#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) -+#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) -+#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) -+#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_SET_ENABLE 0xfdc -+#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_SET_ENABLE_RFF (0x00000001 << 9) -+#define I2C_SET_ENABLE_STDR (0x00000001 << 8) -+#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_SET_ENABLE_IBE (0x00000001 << 6) -+#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_SET_ENABLE_STSD (0x00000001 << 3) -+#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_SET_ENABLE_MAF (0x00000001 << 1) -+#define I2C_SET_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_STATUS 0xfe0 -+#define I2C_INTERRUPT_STFNF (0x00000001 << 12) -+#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) -+#define I2C_INTERRUPT_RFDA (0x00000001 << 10) -+#define I2C_INTERRUPTE_RFF (0x00000001 << 9) -+#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) -+#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) -+#define I2C_ERROR_IBE (0x00000001 << 6) -+#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) -+#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) -+#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) -+#define I2C_ACK_INTER_MTNA (0x00000001 << 2) -+#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) -+#define I2C_INTERRUPT_MTD (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define I2C_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_ENABLE_RFF (0x00000001 << 9) -+#define I2C_ENABLE_STDR (0x00000001 << 8) -+#define I2C_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_ENABLE_IBE (0x00000001 << 6) -+#define I2C_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_ENABLE_STSD (0x00000001 << 3) -+#define I2C_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_ENABLE_MAF (0x00000001 << 1) -+#define I2C_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) -+#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) -+#define I2C_CLR_STATUS_RFF (0x00000001 << 9) -+#define I2C_CLR_STATUS_STDR (0x00000001 << 8) -+#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) -+#define I2C_CLR_STATUS_IBE (0x00000001 << 6) -+#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) -+#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) -+#define I2C_CLR_STATUS_STSD (0x00000001 << 3) -+#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) -+#define I2C_CLR_STATUS_MAF (0x00000001 << 1) -+#define I2C_CLR_STATIS_MTD (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define I2C_SET_STATUS_STFNF (0x00000001 << 12) -+#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_SET_STATUS_RFDA (0x00000001 << 10) -+#define I2C_SET_STATUS_RFF (0x00000001 << 9) -+#define I2C_SET_STATUS_STDR (0x00000001 << 8) -+#define I2C_SET_STATUS_MTDR (0x00000001 << 7) -+#define I2C_SET_STATUS_IBE (0x00000001 << 6) -+#define I2C_SET_STATUS_MSMC (0x00000001 << 5) -+#define I2C_SET_STATUS_SRSD (0x00000001 << 4) -+#define I2C_SET_STATUS_STSD (0x00000001 << 3) -+#define I2C_SET_STATUS_MTNA (0x00000001 << 2) -+#define I2C_SET_STATUS_MAF (0x00000001 << 1) -+#define I2C_SET_STATIS_MTD (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_I2C_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_mod.h b/drivers/media/common/saa716x/saa716x_mod.h -new file mode 100644 -index 0000000..273efdd ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_mod.h -@@ -0,0 +1,50 @@ -+#ifndef __SAA716x_MOD_H -+#define __SAA716x_MOD_H -+ -+/* BAR = 17 bits */ -+/* -+ VI0 0x00000000 -+ VI1 0x00001000 -+ FGPI0 0x00002000 -+ FGPI1 0x00003000 -+ FGPI2 0x00004000 -+ FGPI3 0x00005000 -+ AI0 0x00006000 -+ AI1 0x00007000 -+ BAM 0x00008000 -+ MMU 0x00009000 -+ MSI 0x0000a000 -+ I2C_B 0x0000b000 -+ I2C_A 0x0000c000 -+ SPI 0x0000d000 -+ GPIO 0x0000e000 -+ PHI_0 0x0000f000 -+ CGU 0x00013000 -+ DCS 0x00014000 -+ GREG 0x00012000 -+ -+ PHI_1 0x00020000 -+*/ -+ -+#define VI0 0x00000000 -+#define VI1 0x00001000 -+#define FGPI0 0x00002000 -+#define FGPI1 0x00003000 -+#define FGPI2 0x00004000 -+#define FGPI3 0x00005000 -+#define AI0 0x00006000 -+#define AI1 0x00007000 -+#define BAM 0x00008000 -+#define MMU 0x00009000 -+#define MSI 0x0000a000 -+#define I2C_B 0x0000b000 -+#define I2C_A 0x0000c000 -+#define SPI 0x0000d000 -+#define GPIO 0x0000e000 -+#define PHI_0 0x0000f000 -+#define GREG 0x00012000 -+#define CGU 0x00013000 -+#define DCS 0x00014000 -+#define PHI_1 0x00020000 -+ -+#endif /* __SAA716x_MOD_H */ -diff --git a/drivers/media/common/saa716x/saa716x_msi.c b/drivers/media/common/saa716x/saa716x_msi.c -new file mode 100644 -index 0000000..b0f05a2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_msi.c -@@ -0,0 +1,479 @@ -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_msi_reg.h" -+#include "saa716x_msi.h" -+#include "saa716x_spi.h" -+ -+#include "saa716x_priv.h" -+ -+#define SAA716x_MSI_VECTORS 50 -+ -+static const char *vector_name[] = { -+ "TAGACK_VI0_0", -+ "TAGACK_VI0_1", -+ "TAGACK_VI0_2", -+ "TAGACK_VI1_0", -+ "TAGACK_VI1_1", -+ "TAGACK_VI1_2", -+ "TAGACK_FGPI_0", -+ "TAGACK_FGPI_1", -+ "TAGACK_FGPI_2", -+ "TAGACK_FGPI_3", -+ "TAGACK_AI_0", -+ "TAGACK_AI_1", -+ "OVRFLW_VI0_0", -+ "OVRFLW_VI0_1", -+ "OVRFLW_VI0_2", -+ "OVRFLW_VI1_0", -+ "OVRFLW_VI1_1", -+ "OVRFLW_VI1_2", -+ "OVRFLW_FGPI_O", -+ "OVRFLW_FGPI_1", -+ "OVRFLW_FGPI_2", -+ "OVRFLW_FGPI_3", -+ "OVRFLW_AI_0", -+ "OVRFLW_AI_1", -+ "AVINT_VI0", -+ "AVINT_VI1", -+ "AVINT_FGPI_0", -+ "AVINT_FGPI_1", -+ "AVINT_FGPI_2", -+ "AVINT_FGPI_3", -+ "AVINT_AI_0", -+ "AVINT_AI_1", -+ "UNMAPD_TC_INT", -+ "EXTINT_0", -+ "EXTINT_1", -+ "EXTINT_2", -+ "EXTINT_3", -+ "EXTINT_4", -+ "EXTINT_5", -+ "EXTINT_6", -+ "EXTINT_7", -+ "EXTINT_8", -+ "EXTINT_9", -+ "EXTINT_10", -+ "EXTINT_11", -+ "EXTINT_12", -+ "EXTINT_13", -+ "EXTINT_14", -+ "EXTINT_15", -+ "I2CINT_0", -+ "I2CINT_1" -+}; -+ -+static u32 MSI_CONFIG_REG[51] = { -+ MSI_CONFIG0, -+ MSI_CONFIG1, -+ MSI_CONFIG2, -+ MSI_CONFIG3, -+ MSI_CONFIG4, -+ MSI_CONFIG5, -+ MSI_CONFIG6, -+ MSI_CONFIG7, -+ MSI_CONFIG8, -+ MSI_CONFIG9, -+ MSI_CONFIG10, -+ MSI_CONFIG11, -+ MSI_CONFIG12, -+ MSI_CONFIG13, -+ MSI_CONFIG14, -+ MSI_CONFIG15, -+ MSI_CONFIG16, -+ MSI_CONFIG17, -+ MSI_CONFIG18, -+ MSI_CONFIG19, -+ MSI_CONFIG20, -+ MSI_CONFIG21, -+ MSI_CONFIG22, -+ MSI_CONFIG23, -+ MSI_CONFIG24, -+ MSI_CONFIG25, -+ MSI_CONFIG26, -+ MSI_CONFIG27, -+ MSI_CONFIG28, -+ MSI_CONFIG29, -+ MSI_CONFIG30, -+ MSI_CONFIG31, -+ MSI_CONFIG32, -+ MSI_CONFIG33, -+ MSI_CONFIG34, -+ MSI_CONFIG35, -+ MSI_CONFIG36, -+ MSI_CONFIG37, -+ MSI_CONFIG38, -+ MSI_CONFIG39, -+ MSI_CONFIG40, -+ MSI_CONFIG41, -+ MSI_CONFIG42, -+ MSI_CONFIG43, -+ MSI_CONFIG44, -+ MSI_CONFIG45, -+ MSI_CONFIG46, -+ MSI_CONFIG47, -+ MSI_CONFIG48, -+ MSI_CONFIG49, -+ MSI_CONFIG50 -+}; -+ -+int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h) -+{ -+ dprintk(SAA716x_DEBUG, 0, "%s: MSI event ", __func__); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[0]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[1]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[2]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[3]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[4]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[5]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[6]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[7]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[8]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[9]); -+ -+ if (stat_l & MSI_INT_TAGACK_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[10]); -+ -+ if (stat_l & MSI_INT_TAGACK_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[11]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[12]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[13]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[14]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[15]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[16]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[17]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[18]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[19]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[20]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[21]); -+ -+ if (stat_l & MSI_INT_OVRFLW_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[22]); -+ -+ if (stat_l & MSI_INT_OVRFLW_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[23]); -+ -+ if (stat_l & MSI_INT_AVINT_VI0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[24]); -+ -+ if (stat_l & MSI_INT_AVINT_VI1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[25]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[26]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[27]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[28]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[29]); -+ -+ if (stat_l & MSI_INT_AVINT_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[30]); -+ -+ if (stat_l & MSI_INT_AVINT_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[31]); -+ -+ if (stat_h & MSI_INT_UNMAPD_TC_INT) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[32]); -+ -+ if (stat_h & MSI_INT_EXTINT_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[33]); -+ -+ if (stat_h & MSI_INT_EXTINT_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[34]); -+ -+ if (stat_h & MSI_INT_EXTINT_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[35]); -+ -+ if (stat_h & MSI_INT_EXTINT_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[36]); -+ -+ if (stat_h & MSI_INT_EXTINT_4) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[37]); -+ -+ if (stat_h & MSI_INT_EXTINT_5) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[38]); -+ -+ if (stat_h & MSI_INT_EXTINT_6) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[39]); -+ -+ if (stat_h & MSI_INT_EXTINT_7) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[40]); -+ -+ if (stat_h & MSI_INT_EXTINT_8) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[41]); -+ -+ if (stat_h & MSI_INT_EXTINT_9) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[42]); -+ -+ if (stat_h & MSI_INT_EXTINT_10) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[43]); -+ -+ if (stat_h & MSI_INT_EXTINT_11) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[44]); -+ -+ if (stat_h & MSI_INT_EXTINT_12) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[45]); -+ -+ if (stat_h & MSI_INT_EXTINT_13) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[46]); -+ -+ if (stat_h & MSI_INT_EXTINT_14) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[47]); -+ -+ if (stat_h & MSI_INT_EXTINT_15) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[48]); -+ -+ if (stat_h & MSI_INT_I2CINT_0) { -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[49]); -+ saa716x_i2c_irqevent(saa716x, 0); -+ } -+ -+ if (stat_h & MSI_INT_I2CINT_1) { -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[50]); -+ saa716x_i2c_irqevent(saa716x, 1); -+ } -+ -+ dprintk(SAA716x_DEBUG, 0, "\n"); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_msi_event); -+ -+int saa716x_msi_init(struct saa716x_dev *saa716x) -+{ -+ u32 ena_l, ena_h, sta_l, sta_h, mid; -+ int i; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing MSI .."); -+ saa716x->handlers = 0; -+ -+ /* get module id & version */ -+ mid = SAA716x_EPRD(MSI, MSI_MODULE_ID); -+ if (mid != 0x30100) -+ dprintk(SAA716x_ERROR, 1, "MSI Id<%04x> is not supported", mid); -+ -+ /* let HW take care of MSI race */ -+ SAA716x_EPWR(MSI, MSI_DELAY_TIMER, 0x0); -+ -+ /* INTA Polarity: Active High */ -+ SAA716x_EPWR(MSI, MSI_INTA_POLARITY, MSI_INTA_POLARITY_HIGH); -+ -+ /* -+ * IRQ Edge Rising: 25:24 = 0x01 -+ * Traffic Class: 18:16 = 0x00 -+ * MSI ID: 4:0 = 0x00 -+ */ -+ for (i = 0; i < SAA716x_MSI_VECTORS; i++) -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[i], MSI_INT_POL_EDGE_RISE); -+ -+ /* get Status */ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ -+ /* disable and clear enabled and asserted IRQ's */ -+ if (sta_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, sta_l); -+ -+ if (sta_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, sta_h); -+ -+ if (ena_l) -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, ena_l); -+ -+ if (ena_h) -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, ena_h); -+ -+ msleep(5); -+ -+ /* Check IRQ's really disabled */ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ -+ if ((ena_l == 0) && (ena_h == 0) && (sta_l == 0) && (sta_h == 0)) { -+ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x> sta_l <%02x> sta_h <%02x>", -+ ena_l, ena_h, sta_l, sta_h); -+ -+ return 0; -+ } else { -+ dprintk(SAA716x_DEBUG, 1, "I/O error"); -+ return -EIO; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_msi_init); -+ -+void saa716x_msiint_disable(struct saa716x_dev *saa716x) -+{ -+ dprintk(SAA716x_DEBUG, 1, "Disabling Interrupts ..."); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_L, 0x0); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_H, 0x0); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0xffffffff); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0x0000ffff); -+} -+EXPORT_SYMBOL_GPL(saa716x_msiint_disable); -+ -+ -+/* Map the given vector Id to the hardware bitmask. */ -+static void saa716x_map_vector(struct saa716x_dev *saa716x, int vector, u32 *mask_l, u32 *mask_h) -+{ -+ u32 tmp = 1; -+ -+ if (vector < 32) { -+ /* Bits 0 - 31 */ -+ tmp <<= vector; -+ *mask_l = tmp; -+ *mask_h = 0; -+ } else { -+ /* Bits 32 - 48 */ -+ tmp <<= vector - 32; -+ *mask_l = 0; -+ *mask_h = tmp; -+ } -+} -+ -+int saa716x_add_irqvector(struct saa716x_dev *saa716x, -+ int vector, -+ enum saa716x_edge edge, -+ irqreturn_t (*handler)(int irq, void *dev_id), -+ char *desc) -+{ -+ struct saa716x_msix_entry *msix_handler = NULL; -+ -+ u32 config, mask_l, mask_h, ena_l, ena_h; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(vector > SAA716x_MSI_VECTORS); -+ dprintk(SAA716x_DEBUG, 1, "Adding Vector %d <%s>", vector, vector_name[vector]); -+ -+ if ((vector > 32) && (vector < 49)) { -+ config = SAA716x_EPRD(MSI, MSI_CONFIG_REG[vector]); -+ config &= 0xfcffffff; /* clear polarity */ -+ -+ switch (edge) { -+ default: -+ case SAA716x_EDGE_RISING: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x01000000); -+ break; -+ -+ case SAA716x_EDGE_FALLING: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x02000000); -+ break; -+ -+ case SAA716x_EDGE_ANY: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x03000000); -+ break; -+ } -+ } -+ -+ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); -+ -+ /* add callback */ -+ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; -+ strcpy(msix_handler->desc, desc); -+ msix_handler->vector = vector; -+ msix_handler->handler = handler; -+ saa716x->handlers++; -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, mask_l); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, mask_h); -+ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x>", ena_l, ena_h); -+ -+ return 0; -+} -+ -+int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector) -+{ -+ struct saa716x_msix_entry *msix_handler; -+ int i; -+ u32 mask_l, mask_h; -+ -+ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; -+ BUG_ON(msix_handler == NULL); -+ dprintk(SAA716x_DEBUG, 1, "Removing Vector %d <%s>", vector, vector_name[vector]); -+ -+ /* loop through the registered handlers */ -+ for (i = 0; i < saa716x->handlers; i++) { -+ -+ /* we found our vector */ -+ if (msix_handler->vector == vector) { -+ BUG_ON(msix_handler->handler == NULL); /* no handler yet */ -+ dprintk(SAA716x_DEBUG, 1, "Vector %d <%s> removed", -+ msix_handler->vector, -+ msix_handler->desc); -+ -+ /* check whether it is already released */ -+ if (msix_handler->handler) { -+ msix_handler->vector = 0; -+ msix_handler->handler = NULL; -+ saa716x->handlers--; -+ } -+ } -+ } -+ -+ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); -+ -+ /* disable vector */ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, mask_l); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, mask_h); -+ -+ return 0; -+} -diff --git a/drivers/media/common/saa716x/saa716x_msi.h b/drivers/media/common/saa716x/saa716x_msi.h -new file mode 100644 -index 0000000..8eb72d7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_msi.h -@@ -0,0 +1,87 @@ -+#ifndef __SAA716x_MSI_H -+#define __SAA716x_MSI_H -+ -+#define TAGACK_VI0_0 0x000 -+#define TAGACK_VI0_1 0x001 -+#define TAGACK_VI0_2 0x002 -+#define TAGACK_VI1_0 0x003 -+#define TAGACK_VI1_1 0x004 -+#define TAGACK_VI1_2 0x005 -+#define TAGACK_FGPI_0 0x006 -+#define TAGACK_FGPI_1 0x007 -+#define TAGACK_FGPI_2 0x008 -+#define TAGACK_FGPI_3 0x009 -+#define TAGACK_AI_0 0x00a -+#define TAGACK_AI_1 0x00b -+#define OVRFLW_VI0_0 0x00c -+#define OVRFLW_VI0_1 0x00d -+#define OVRFLW_VI0_2 0x00e -+#define OVRFLW_VI1_0 0x00f -+#define OVRFLW_VI1_1 0x010 -+#define OVRFLW_VI1_2 0x011 -+#define OVRFLW_FGPI_O 0x012 -+#define OVRFLW_FGPI_1 0x013 -+#define OVRFLW_FGPI_2 0x014 -+#define OVRFLW_FGPI_3 0x015 -+#define OVRFLW_AI_0 0x016 -+#define OVRFLW_AI_1 0x017 -+#define AVINT_VI0 0x018 -+#define AVINT_VI1 0x019 -+#define AVINT_FGPI_0 0x01a -+#define AVINT_FGPI_1 0x01b -+#define AVINT_FGPI_2 0x01c -+#define AVINT_FGPI_3 0x01d -+#define AVINT_AI_0 0x01e -+#define AVINT_AI_1 0x01f -+#define UNMAPD_TC_INT 0x020 -+#define EXTINT_0 0x021 -+#define EXTINT_1 0x022 -+#define EXTINT_2 0x023 -+#define EXTINT_3 0x024 -+#define EXTINT_4 0x025 -+#define EXTINT_5 0x026 -+#define EXTINT_6 0x027 -+#define EXTINT_7 0x028 -+#define EXTINT_8 0x029 -+#define EXTINT_9 0x02a -+#define EXTINT_10 0x02b -+#define EXTINT_11 0x02c -+#define EXTINT_12 0x02d -+#define EXTINT_13 0x02e -+#define EXTINT_14 0x02f -+#define EXTINT_15 0x030 -+#define I2CINT_0 0x031 -+#define I2CINT_1 0x032 -+ -+#define SAA716x_TC0 0x000 -+#define SAA716x_TC1 0x001 -+#define SAA716x_TC2 0x002 -+#define SAA716x_TC3 0x003 -+#define SAA716x_TC4 0x004 -+#define SAA716x_TC5 0x005 -+#define SAA716x_TC6 0x006 -+#define SAA716x_TC7 0x007 -+ -+ -+enum saa716x_edge { -+ SAA716x_EDGE_RISING = 1, -+ SAA716x_EDGE_FALLING = 2, -+ SAA716x_EDGE_ANY = 3 -+}; -+ -+struct saa716x_dev; -+ -+extern int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h); -+ -+extern int saa716x_msi_init(struct saa716x_dev *saa716x); -+extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); -+ -+extern int saa716x_add_irqvector(struct saa716x_dev *saa716x, -+ int vector, -+ enum saa716x_edge edge, -+ irqreturn_t (*handler)(int irq, void *dev_id), -+ char *desc); -+ -+extern int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector); -+ -+#endif /* __SAA716x_MSI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_msi_reg.h b/drivers/media/common/saa716x/saa716x_msi_reg.h -new file mode 100644 -index 0000000..d9a12c7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_msi_reg.h -@@ -0,0 +1,143 @@ -+#ifndef __SAA716x_MSI_REG_H -+#define __SAA716x_MSI_REG_H -+ -+/* -------------- MSI Registers -------------- */ -+ -+#define MSI_DELAY_TIMER 0x000 -+#define MSI_DELAY_1CLK (0x00000001 << 0) -+#define MSI_DELAY_2CLK (0x00000002 << 0) -+ -+#define MSI_INTA_POLARITY 0x004 -+#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) -+ -+#define MSI_CONFIG0 0x008 -+#define MSI_CONFIG1 0x00c -+#define MSI_CONFIG2 0x010 -+#define MSI_CONFIG3 0x014 -+#define MSI_CONFIG4 0x018 -+#define MSI_CONFIG5 0x01c -+#define MSI_CONFIG6 0x020 -+#define MSI_CONFIG7 0x024 -+#define MSI_CONFIG8 0x028 -+#define MSI_CONFIG9 0x02c -+#define MSI_CONFIG10 0x030 -+#define MSI_CONFIG11 0x034 -+#define MSI_CONFIG12 0x038 -+#define MSI_CONFIG13 0x03c -+#define MSI_CONFIG14 0x040 -+#define MSI_CONFIG15 0x044 -+#define MSI_CONFIG16 0x048 -+#define MSI_CONFIG17 0x04c -+#define MSI_CONFIG18 0x050 -+#define MSI_CONFIG19 0x054 -+#define MSI_CONFIG20 0x058 -+#define MSI_CONFIG21 0x05c -+#define MSI_CONFIG22 0x060 -+#define MSI_CONFIG23 0x064 -+#define MSI_CONFIG24 0x068 -+#define MSI_CONFIG25 0x06c -+#define MSI_CONFIG26 0x070 -+#define MSI_CONFIG27 0x074 -+#define MSI_CONFIG28 0x078 -+#define MSI_CONFIG29 0x07c -+#define MSI_CONFIG30 0x080 -+#define MSI_CONFIG31 0x084 -+#define MSI_CONFIG32 0x088 -+#define MSI_CONFIG33 0x08c -+#define MSI_CONFIG34 0x090 -+#define MSI_CONFIG35 0x094 -+#define MSI_CONFIG36 0x098 -+#define MSI_CONFIG37 0x09c -+#define MSI_CONFIG38 0x0a0 -+#define MSI_CONFIG39 0x0a4 -+#define MSI_CONFIG40 0x0a8 -+#define MSI_CONFIG41 0x0ac -+#define MSI_CONFIG42 0x0b0 -+#define MSI_CONFIG43 0x0b4 -+#define MSI_CONFIG44 0x0b8 -+#define MSI_CONFIG45 0x0bc -+#define MSI_CONFIG46 0x0c0 -+#define MSI_CONFIG47 0x0c4 -+#define MSI_CONFIG48 0x0c8 -+#define MSI_CONFIG49 0x0cc -+#define MSI_CONFIG50 0x0d0 -+ -+#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) -+#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) -+#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) -+#define MSI_TC (0x00000007 << 16) -+#define MSI_ID (0x0000000f << 0) -+ -+#define MSI_INT_STATUS_L 0xfc0 -+#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) -+#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) -+#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) -+#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) -+#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) -+#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) -+#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) -+#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) -+#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) -+#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) -+#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) -+#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) -+#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) -+#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) -+#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) -+#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) -+#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) -+#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) -+#define MSI_INT_OVRFLW_FGPI_0 (0x00000001 << 18) -+#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) -+#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) -+#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) -+#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) -+#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) -+#define MSI_INT_AVINT_VI0 (0x00000001 << 24) -+#define MSI_INT_AVINT_VI1 (0x00000001 << 25) -+#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) -+#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) -+#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) -+#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) -+#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) -+#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) -+ -+#define MSI_INT_STATUS_H 0xfc4 -+#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) -+#define MSI_INT_EXTINT_0 (0x00000001 << 1) -+#define MSI_INT_EXTINT_1 (0x00000001 << 2) -+#define MSI_INT_EXTINT_2 (0x00000001 << 3) -+#define MSI_INT_EXTINT_3 (0x00000001 << 4) -+#define MSI_INT_EXTINT_4 (0x00000001 << 5) -+#define MSI_INT_EXTINT_5 (0x00000001 << 6) -+#define MSI_INT_EXTINT_6 (0x00000001 << 7) -+#define MSI_INT_EXTINT_7 (0x00000001 << 8) -+#define MSI_INT_EXTINT_8 (0x00000001 << 9) -+#define MSI_INT_EXTINT_9 (0x00000001 << 10) -+#define MSI_INT_EXTINT_10 (0x00000001 << 11) -+#define MSI_INT_EXTINT_11 (0x00000001 << 12) -+#define MSI_INT_EXTINT_12 (0x00000001 << 13) -+#define MSI_INT_EXTINT_13 (0x00000001 << 14) -+#define MSI_INT_EXTINT_14 (0x00000001 << 15) -+#define MSI_INT_EXTINT_15 (0x00000001 << 16) -+#define MSI_INT_I2CINT_0 (0x00000001 << 17) -+#define MSI_INT_I2CINT_1 (0x00000001 << 18) -+ -+#define MSI_INT_STATUS_CLR_L 0xfc8 -+#define MSI_INT_STATUS_CLR_H 0xfcc -+#define MSI_INT_STATUS_SET_L 0xfd0 -+#define MSI_INT_STATUS_SET_H 0xfd4 -+#define MSI_INT_ENA_L 0xfd8 -+#define MSI_INT_ENA_H 0xfdc -+#define MSI_INT_ENA_CLR_L 0xfe0 -+#define MSI_INT_ENA_CLR_H 0xfe4 -+#define MSI_INT_ENA_SET_L 0xfe8 -+#define MSI_INT_ENA_SET_H 0xfec -+ -+#define MSI_SW_RST 0xff0 -+#define MSI_SW_RESET (0x0001 << 0) -+ -+#define MSI_MODULE_ID 0xffc -+ -+ -+#endif /* __SAA716x_MSI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_pci.c b/drivers/media/common/saa716x/saa716x_pci.c -new file mode 100644 -index 0000000..7fa6bad ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_pci.c -@@ -0,0 +1,272 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_spi.h" -+#include "saa716x_msi.h" -+#include "saa716x_priv.h" -+ -+#define DRIVER_NAME "SAA716x Core" -+ -+static int saa716x_enable_msi(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int err; -+ -+ err = pci_enable_msi(pdev); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "MSI enable failed <%d>", err); -+ return err; -+ } -+ -+ return err; -+} -+ -+static int saa716x_enable_msix(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int i, ret = 0; -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) -+ saa716x->msix_entries[i].entry = i; -+ -+ ret = pci_enable_msix(pdev, saa716x->msix_entries, SAA716x_MSI_MAX_VECTORS); -+ if (ret < 0) -+ dprintk(SAA716x_ERROR, 1, "MSI-X request failed <%d>", ret); -+ if (ret > 0) -+ dprintk(SAA716x_ERROR, 1, "Request exceeds available IRQ's <%d>", ret); -+ -+ return ret; -+} -+ -+static int saa716x_request_irq(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct saa716x_config *config = saa716x->config; -+ int i, ret = 0; -+ -+ if (saa716x->int_type == MODE_MSI) { -+ dprintk(SAA716x_DEBUG, 1, "Using MSI mode"); -+ ret = saa716x_enable_msi(saa716x); -+ } else if (saa716x->int_type == MODE_MSI_X) { -+ dprintk(SAA716x_DEBUG, 1, "Using MSI-X mode"); -+ ret = saa716x_enable_msix(saa716x); -+ } -+ -+ if (ret) { -+ dprintk(SAA716x_ERROR, 1, "INT-A Mode"); -+ saa716x->int_type = MODE_INTA; -+ } -+ -+ if (saa716x->int_type == MODE_MSI) { -+ ret = request_irq(pdev->irq, -+ config->irq_handler, -+ 0, -+ DRIVER_NAME, -+ saa716x); -+ -+ if (ret) { -+ pci_disable_msi(pdev); -+ dprintk(SAA716x_ERROR, 1, "MSI registration failed"); -+ ret = -EIO; -+ } -+ } -+ -+ if (saa716x->int_type == MODE_MSI_X) { -+ for (i = 0; SAA716x_MSI_MAX_VECTORS; i++) { -+ ret = request_irq(saa716x->msix_entries[i].vector, -+ saa716x->saa716x_msix_handler[i].handler, -+ IRQF_SHARED, -+ saa716x->saa716x_msix_handler[i].desc, -+ saa716x); -+ -+ dprintk(SAA716x_ERROR, 1, "%s @ 0x%p", saa716x->saa716x_msix_handler[i].desc, saa716x->saa716x_msix_handler[i].handler); -+ if (ret) { -+ dprintk(SAA716x_ERROR, 1, "%s MSI-X-%d registration failed <%d>", saa716x->saa716x_msix_handler[i].desc, i, ret); -+ return -1; -+ } -+ } -+ } -+ -+ if (saa716x->int_type == MODE_INTA) { -+ ret = request_irq(pdev->irq, -+ config->irq_handler, -+ IRQF_SHARED, -+ DRIVER_NAME, -+ saa716x); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed <%d>", ret); -+ ret = -ENODEV; -+ } -+ } -+ -+ return ret; -+} -+ -+static void saa716x_free_irq(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int i, vector; -+ -+ if (saa716x->int_type == MODE_MSI_X) { -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { -+ vector = saa716x->msix_entries[i].vector; -+ free_irq(vector, saa716x); -+ } -+ -+ pci_disable_msix(pdev); -+ -+ } else { -+ free_irq(pdev->irq, saa716x); -+ if (saa716x->int_type == MODE_MSI) -+ pci_disable_msi(pdev); -+ } -+} -+ -+int saa716x_pci_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int err = 0, ret = -ENODEV, i, use_dac, pm_cap; -+ u32 msi_cap; -+ u8 revision; -+ -+ dprintk(SAA716x_ERROR, 1, "found a %s PCIe card", saa716x->config->model_name); -+ -+ err = pci_enable_device(pdev); -+ if (err != 0) { -+ ret = -ENODEV; -+ dprintk(SAA716x_ERROR, 1, "ERROR: PCI enable failed (%i)", err); -+ goto fail0; -+ } -+ -+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { -+ use_dac = 1; -+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "Unable to obtain 64bit DMA"); -+ goto fail1; -+ } -+ } else if ((err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { -+ dprintk(SAA716x_ERROR, 1, "Unable to obtain 32bit DMA"); -+ goto fail1; -+ } -+ -+ pci_set_master(pdev); -+ -+ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); -+ if (pm_cap == 0) { -+ dprintk(SAA716x_ERROR, 1, "Cannot find Power Management Capability"); -+ err = -EIO; -+ goto fail1; -+ } -+ -+ if (!request_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0), -+ DRIVER_NAME)) { -+ -+ dprintk(SAA716x_ERROR, 1, "BAR0 Request failed"); -+ ret = -ENODEV; -+ goto fail1; -+ } -+ saa716x->mmio = ioremap(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ -+ if (!saa716x->mmio) { -+ dprintk(SAA716x_ERROR, 1, "Mem 0 remap failed"); -+ ret = -ENODEV; -+ goto fail2; -+ } -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) -+ saa716x->msix_entries[i].entry = i; -+ -+ err = saa716x_request_irq(saa716x); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed, err=%d", err); -+ ret = -ENODEV; -+ goto fail3; -+ } -+ -+ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); -+ pci_read_config_dword(pdev, 0x40, &msi_cap); -+ -+ saa716x->revision = revision; -+ -+ dprintk(SAA716x_ERROR, 0, " SAA%02x Rev %d [%04x:%04x], ", -+ saa716x->pdev->device, -+ revision, -+ saa716x->pdev->subsystem_vendor, -+ saa716x->pdev->subsystem_device); -+ -+ dprintk(SAA716x_ERROR, 0, -+ "irq: %d,\n mmio: 0x%p\n", -+ saa716x->pdev->irq, -+ saa716x->mmio); -+ -+ dprintk(SAA716x_ERROR, 0, " SAA%02x %sBit, MSI %s, MSI-X=%d msgs", -+ saa716x->pdev->device, -+ (((msi_cap >> 23) & 0x01) == 1 ? "64":"32"), -+ (((msi_cap >> 16) & 0x01) == 1 ? "Enabled" : "Disabled"), -+ (1 << ((msi_cap >> 17) & 0x07))); -+ -+ dprintk(SAA716x_ERROR, 0, "\n"); -+ -+ pci_set_drvdata(pdev, saa716x); -+ -+ return 0; -+ -+fail3: -+ dprintk(SAA716x_ERROR, 1, "Err: IO Unmap"); -+ if (saa716x->mmio) -+ iounmap(saa716x->mmio); -+fail2: -+ dprintk(SAA716x_ERROR, 1, "Err: Release regions"); -+ release_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ -+fail1: -+ dprintk(SAA716x_ERROR, 1, "Err: Disabling device"); -+ pci_disable_device(pdev); -+ -+fail0: -+ pci_set_drvdata(pdev, NULL); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(saa716x_pci_init); -+ -+void saa716x_pci_exit(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ saa716x_free_irq(saa716x); -+ -+ dprintk(SAA716x_NOTICE, 1, "SAA%02x mem0: 0x%p", -+ saa716x->pdev->device, -+ saa716x->mmio); -+ -+ if (saa716x->mmio) { -+ iounmap(saa716x->mmio); -+ release_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ } -+ -+ pci_disable_device(pdev); -+ pci_set_drvdata(pdev, NULL); -+} -+EXPORT_SYMBOL_GPL(saa716x_pci_exit); -+ -+MODULE_DESCRIPTION("SAA716x bridge driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_phi.c b/drivers/media/common/saa716x/saa716x_phi.c -new file mode 100644 -index 0000000..7df9a98 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_phi.c -@@ -0,0 +1,152 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_phi_reg.h" -+ -+#include "saa716x_spi.h" -+#include "saa716x_phi.h" -+#include "saa716x_priv.h" -+ -+u32 PHI_0_REGS[] = { -+ PHI_0_MODE, -+ PHI_0_0_CONFIG, -+ PHI_0_1_CONFIG, -+ PHI_0_2_CONFIG, -+ PHI_0_3_CONFIG -+}; -+ -+u32 PHI_1_REGS[] = { -+ PHI_1_MODE, -+ PHI_1_0_CONFIG, -+ PHI_1_1_CONFIG, -+ PHI_1_2_CONFIG, -+ PHI_1_3_CONFIG, -+ PHI_1_4_CONFIG, -+ PHI_1_5_CONFIG, -+ PHI_1_6_CONFIG, -+ PHI_1_7_CONFIG -+}; -+ -+#define PHI_BASE(__port) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_BASE : \ -+ PHI_0_BASE \ -+)) -+ -+#define PHI_APERTURE(_port) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_APERTURE: \ -+ PHI_0_APERTURE \ -+)) -+ -+#define PHI_REG(__port, __reg) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_REGS[__reg] : \ -+ PHI_0_REGS[__reg] \ -+)) -+ -+#define PHI_SLAVE(__port, __slave) (( \ -+ PHI_BASE(__port) + (__slave * (PHI_APERTURE(__port))) \ -+)) -+ -+/* // Read SAA716x registers -+ * SAA716x_EPRD(PHI_0, PHI_REG(__port, __reg)) -+ * SAA716x_EPWR(PHI_1, PHI_REG(__port, __reg), __data) -+ * -+ * // Read slave registers -+ * SAA716x_EPRD(PHI_0, PHI_SLAVE(__port, __slave, __offset)) -+ * SAA716x_EPWR(PHI_1, PHI_SLAVE(__port, __slave, _offset), __data) -+ */ -+ -+int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave) -+{ -+ int i; -+ -+ /* Reset */ -+ SAA716x_EPWR(PHI_0, PHI_SW_RST, 0x1); -+ -+ for (i = 0; i < 20; i++) { -+ msleep(1); -+ if (!(SAA716x_EPRD(PHI_0, PHI_SW_RST))) -+ break; -+ } -+ -+ return 0; -+} -+ -+int saa716x_phi_init(struct saa716x_dev *saa716x) -+{ -+ uint32_t value; -+ -+ /* init PHI 0 to FIFO mode */ -+ value = 0; -+ value |= PHI_FIFO_MODE; -+ SAA716x_EPWR(PHI_0, PHI_0_MODE, value); -+ -+ value = 0; -+ value |= 0x02; /* chip select 1 */ -+ value |= 0x00 << 8; /* ready mask */ -+ value |= 0x03 << 12; /* strobe time */ -+ value |= 0x06 << 20; /* cycle time */ -+ SAA716x_EPWR(PHI_0, PHI_0_0_CONFIG, value); -+ -+ /* init PHI 1 to SRAM mode, auto increment on */ -+ value = 0; -+ value |= PHI_AUTO_INCREMENT; -+ SAA716x_EPWR(PHI_0, PHI_1_MODE, value); -+ -+ value = 0; -+ value |= 0x01; /* chip select 0 */ -+ value |= 0x00 << 8; /* ready mask */ -+ value |= 0x03 << 12; /* strobe time */ -+ value |= 0x05 << 20; /* cycle time */ -+ SAA716x_EPWR(PHI_0, PHI_1_0_CONFIG, value); -+ -+ value = 0; -+ value |= PHI_ALE_POL; /* ALE is active high */ -+ SAA716x_EPWR(PHI_0, PHI_POLARITY, value); -+ -+ SAA716x_EPWR(PHI_0, PHI_TIMEOUT, 0x2a); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_init); -+ -+int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ SAA716x_EPWR(PHI_1, address, *((u32 *) &data[i])); -+ address += 4; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_write); -+ -+int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ *((u32 *) &data[i]) = SAA716x_EPRD(PHI_1, address); -+ address += 4; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_read); -+ -+int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ SAA716x_EPWR(PHI_0, PHI_0_0_RW_0, *((u32 *) &data[i])); -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_write_fifo); -diff --git a/drivers/media/common/saa716x/saa716x_phi.h b/drivers/media/common/saa716x/saa716x_phi.h -new file mode 100644 -index 0000000..ff5cda2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_phi.h -@@ -0,0 +1,39 @@ -+#ifndef __SAA716x_PHI_H -+#define __SAA716x_PHI_H -+ -+/* PHI SLAVE */ -+#define PHI_SLAVE_0 0 -+#define PHI_SLAVE_1 1 -+#define PHI_SLAVE_2 2 -+#define PHI_SLAVE_3 3 -+#define PHI_SLAVE_4 4 -+#define PHI_SLAVE_5 5 -+#define PHI_SLAVE_6 6 -+#define PHI_SLAVE_7 7 -+ -+/* PHI_REG */ -+#define PHI_MODE 0 -+#define PHI_CONFIG_0 1 -+#define PHI_CONFIG_1 2 -+#define PHI_CONFIG_2 3 -+#define PHI_CONFIG_3 4 -+#define PHI_CONFIG_4 5 -+#define PHI_CONFIG_5 6 -+#define PHI_CONFIG_6 7 -+#define PHI_CONFIG_7 8 -+ -+#define PHI_0_BASE 0x1000 -+#define PHI_0_APERTURE 0x0800 -+ -+#define PHI_1_BASE 0x0000 -+#define PHI_1_APERTURE 0xfffc -+ -+struct saa716x_dev; -+ -+extern int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave); -+extern int saa716x_phi_init(struct saa716x_dev *saa716x); -+extern int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 *data, int length); -+extern int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 *data, int length); -+extern int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length); -+ -+#endif /* __SAA716x_PHI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_phi_reg.h b/drivers/media/common/saa716x/saa716x_phi_reg.h -new file mode 100644 -index 0000000..08f0aa7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_phi_reg.h -@@ -0,0 +1,100 @@ -+#ifndef __SAA716x_PHI_REG_H -+#define __SAA716x_PHI_REG_H -+ -+/* -------------- PHI_0 Registers -------------- */ -+ -+#define PHI_0_MODE 0x0000 -+#define PHI_0_0_CONFIG 0x0008 -+#define PHI_0_1_CONFIG 0x000c -+#define PHI_0_2_CONFIG 0x0010 -+#define PHI_0_3_CONFIG 0x0014 -+ -+#define PHI_POLARITY 0x0038 -+#define PHI_TIMEOUT 0x003c -+#define PHI_SW_RST 0x0ff0 -+ -+#define PHI_0_0_RW_0 0x1000 -+#define PHI_0_0_RW_511 0x17fc -+ -+#define PHI_0_1_RW_0 0x1800 -+#define PHI_0_1_RW_511 0x1ffc -+ -+#define PHI_0_2_RW_0 0x2000 -+#define PHI_0_2_RW_511 0x27fc -+ -+#define PHI_0_3_RW_0 0x2800 -+#define PHI_0_3_RW_511 0x2ffc -+ -+#define PHI_CSN_DEASSERT (0x00000001 << 2) -+#define PHI_AUTO_INCREMENT (0x00000001 << 1) -+#define PHI_FIFO_MODE (0x00000001 << 0) -+ -+#define PHI_DELAY_RD_WR (0x0000001f << 27) -+#define PHI_EXTEND_RDY3 (0x00000003 << 25) -+#define PHI_EXTEND_RDY2 (0x00000003 << 23) -+#define PHI_EXTEND_RDY1 (0x00000003 << 21) -+#define PHI_EXTEND_RDY0 (0x00000003 << 19) -+#define PHI_RDY3_OD (0x00000001 << 18) -+#define PHI_RDY2_OD (0x00000001 << 17) -+#define PHI_RDY1_OD (0x00000001 << 16) -+#define PHI_RDY0_OD (0x00000001 << 15) -+#define PHI_ALE_POL (0x00000001 << 14) -+#define PHI_WRN_POL (0x00000001 << 13) -+#define PHI_RDN_POL (0x00000001 << 12) -+#define PHI_RDY3_POL (0x00000001 << 11) -+#define PHI_RDY2_POL (0x00000001 << 10) -+#define PHI_RDY1_POL (0x00000001 << 9) -+#define PHI_RDY0_POL (0x00000001 << 8) -+#define PHI_CSN7_POL (0x00000001 << 7) -+#define PHI_CSN6_POL (0x00000001 << 6) -+#define PHI_CSN5_POL (0x00000001 << 5) -+#define PHI_CSN4_POL (0x00000001 << 4) -+#define PHI_CSN3_POL (0x00000001 << 3) -+#define PHI_CSN2_POL (0x00000001 << 2) -+#define PHI_CSN1_POL (0x00000001 << 1) -+#define PHI_CSN0_POL (0x00000001 << 0) -+ -+/* -------------- PHI_1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+#define PHI_1_MODE 0x00004 -+#define PHI_1_0_CONFIG 0x00018 -+#define PHI_1_1_CONFIG 0x0001c -+#define PHI_1_2_CONFIG 0x00020 -+#define PHI_1_3_CONFIG 0x00024 -+#define PHI_1_4_CONFIG 0x00028 -+#define PHI_1_5_CONFIG 0x0002c -+#define PHI_1_6_CONFIG 0x00030 -+#define PHI_1_7_CONFIG 0x00034 -+ -+#define PHI_1_0_RW_0 0x00000 -+#define PHI_1_0_RW_16383 0x0fffc -+ -+#define PHI_1_1_RW_0 0x1000 -+#define PHI_1_1_RW_16383 0x1ffc -+ -+#define PHI_1_2_RW_0 0x2000 -+#define PHI_1_2_RW_16383 0x2ffc -+ -+#define PHI_1_3_RW_0 0x3000 -+#define PHI_1_3_RW_16383 0x3ffc -+ -+#define PHI_1_4_RW_0 0x4000 -+#define PHI_1_4_RW_16383 0x4ffc -+ -+#define PHI_1_5_RW_0 0x5000 -+#define PHI_1_5_RW_16383 0x5ffc -+ -+#define PHI_1_6_RW_0 0x6000 -+#define PHI_1_6_RW_16383 0x6ffc -+ -+#define PHI_1_7_RW_0 0x7000 -+#define PHI_1_7_RW_16383 0x7ffc -+ -+ -+/* BAR = 20 bits */ -+/* -------------- PHI1 Registers -------------- */ -+ -+ -+#endif /* __SAA716x_PHI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_priv.h b/drivers/media/common/saa716x/saa716x_priv.h -new file mode 100644 -index 0000000..1ad1d9c ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_priv.h -@@ -0,0 +1,194 @@ -+#ifndef __SAA716x_PRIV_H -+#define __SAA716x_PRIV_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "saa716x_i2c.h" -+#include "saa716x_boot.h" -+#include "saa716x_cgu.h" -+#include "saa716x_dma.h" -+#include "saa716x_fgpi.h" -+ -+#include "dvbdev.h" -+#include "dvb_demux.h" -+#include "dmxdev.h" -+#include "dvb_frontend.h" -+#include "dvb_net.h" -+ -+#define SAA716x_ERROR 0 -+#define SAA716x_NOTICE 1 -+#define SAA716x_INFO 2 -+#define SAA716x_DEBUG 3 -+ -+#define SAA716x_DEV (saa716x)->num -+#define SAA716x_VERBOSE (saa716x)->verbose -+#define SAA716x_MAX_ADAPTERS 4 -+ -+#define dprintk(__x, __y, __fmt, __arg...) do { \ -+ if (__y) { \ -+ if ((SAA716x_VERBOSE > SAA716x_ERROR) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_ERR "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_NOTICE) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_NOTICE "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_INFO) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_INFO "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_DEBUG) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_DEBUG "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ } else { \ -+ if (SAA716x_VERBOSE > __x) \ -+ printk(__fmt , ##__arg); \ -+ } \ -+} while(0) -+ -+ -+#define NXP_SEMICONDUCTOR 0x1131 -+#define SAA7160 0x7160 -+#define SAA7161 0x7161 -+#define SAA7162 0x7162 -+ -+#define NXP_REFERENCE_BOARD 0x1131 -+ -+#define MAKE_ENTRY(__subven, __subdev, __chip, __configptr) { \ -+ .vendor = NXP_SEMICONDUCTOR, \ -+ .device = (__chip), \ -+ .subvendor = (__subven), \ -+ .subdevice = (__subdev), \ -+ .driver_data = (unsigned long) (__configptr) \ -+} -+ -+#define SAA716x_EPWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) -+#define SAA716x_EPRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) -+ -+#define SAA716x_RCWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) -+#define SAA716x_RCRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) -+ -+ -+#define SAA716x_MSI_MAX_VECTORS 16 -+ -+struct saa716x_msix_entry { -+ int vector; -+ u8 desc[32]; -+ irqreturn_t (*handler)(int irq, void *dev_id); -+}; -+ -+struct saa716x_dev; -+struct saa716x_adapter; -+struct saa716x_spi_config; -+ -+struct saa716x_adap_config { -+ u32 ts_port; -+ void (*worker)(unsigned long); -+}; -+ -+struct saa716x_config { -+ char *model_name; -+ char *dev_type; -+ -+ enum saa716x_boot_mode boot_mode; -+ -+ int adapters; -+ int frontends; -+ -+ int (*frontend_attach)(struct saa716x_adapter *adapter, int count); -+ irqreturn_t (*irq_handler)(int irq, void *dev_id); -+ -+ struct saa716x_adap_config adap_config[SAA716x_MAX_ADAPTERS]; -+ enum saa716x_i2c_rate i2c_rate; -+ enum saa716x_i2c_mode i2c_mode; -+}; -+ -+struct saa716x_adapter { -+ struct dvb_adapter dvb_adapter; -+ struct dvb_frontend *fe; -+ struct dvb_demux demux; -+ struct dmxdev dmxdev; -+ struct dmx_frontend fe_hw; -+ struct dmx_frontend fe_mem; -+ struct dvb_net dvb_net; -+ -+ struct saa716x_dev *saa716x; -+ -+ u8 feeds; -+ u8 count; -+}; -+ -+struct saa716x_dev { -+ struct saa716x_config *config; -+ struct pci_dev *pdev; -+ -+ int num; /* device count */ -+ int verbose; -+ -+ u8 revision; -+ -+ /* PCI */ -+ void __iomem *mmio; -+ -+#define MODE_INTA 0 -+#define MODE_MSI 1 -+#define MODE_MSI_X 2 -+ u8 int_type; -+ -+ struct msix_entry msix_entries[SAA716x_MSI_MAX_VECTORS]; -+ struct saa716x_msix_entry saa716x_msix_handler[56]; -+ u8 handlers; /* no. of active handlers */ -+ -+ /* I2C */ -+ struct saa716x_i2c i2c[2]; -+ u32 i2c_rate; /* init time */ -+ u32 I2C_DEV[2]; -+ -+ struct saa716x_spi_state *saa716x_spi; -+ struct saa716x_spi_config spi_config; -+ -+ struct saa716x_adapter saa716x_adap[SAA716x_MAX_ADAPTERS]; -+ struct mutex adap_lock; -+ struct saa716x_cgu cgu; -+ -+ spinlock_t gpio_lock; -+ /* DMA */ -+ -+ struct saa716x_fgpi_stream_port fgpi[4]; -+ -+ u32 id_offst; -+ u32 id_len; -+ void *priv; -+ -+ /* remote control */ -+ void *ir_priv; -+}; -+ -+/* PCI */ -+extern int saa716x_pci_init(struct saa716x_dev *saa716x); -+extern void saa716x_pci_exit(struct saa716x_dev *saa716x); -+ -+/* MSI */ -+extern int saa716x_msi_init(struct saa716x_dev *saa716x); -+extern void saa716x_msi_exit(struct saa716x_dev *saa716x); -+extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); -+ -+/* DMA */ -+extern int saa716x_dma_init(struct saa716x_dev *saa716x); -+extern void saa716x_dma_exit(struct saa716x_dev *saa716x); -+ -+/* AUDIO */ -+extern int saa716x_audio_init(struct saa716x_dev *saa716x); -+extern void saa716x_audio_exit(struct saa716x_dev *saa716x); -+ -+/* Boot */ -+extern int saa716x_core_boot(struct saa716x_dev *saa716x); -+extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); -+ -+/* Remote control */ -+extern int saa716x_ir_init(struct saa716x_dev *saa716x); -+extern void saa716x_ir_exit(struct saa716x_dev *saa716x); -+extern void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd); -+ -+#endif /* __SAA716x_PRIV_H */ -diff --git a/drivers/media/common/saa716x/saa716x_reg.h b/drivers/media/common/saa716x/saa716x_reg.h -new file mode 100644 -index 0000000..effd966 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_reg.h -@@ -0,0 +1,1279 @@ -+#ifndef __SAA716x_REG_H -+#define __SAA716x_REG_H -+ -+/* BAR = 17 bits */ -+/* -+ VI0 0x00000000 -+ VI1 0x00001000 -+ FGPI0 0x00002000 -+ FGPI1 0x00003000 -+ FGPI2 0x00004000 -+ FGPI3 0x00005000 -+ AI0 0x00006000 -+ AI1 0x00007000 -+ BAM 0x00008000 -+ MMU 0x00009000 -+ MSI 0x0000a000 -+ I2C_B 0x0000b000 -+ I2C_A 0x0000c000 -+ SPI 0x0000d000 -+ GPIO 0x0000e000 -+ PHI_0 0x0000f000 -+ CGU 0x00013000 -+ DCS 0x00014000 -+ GREG 0x00012000 -+ -+ PHI_1 0x00020000 -+*/ -+ -+/* -------------- VIP Registers -------------- */ -+ -+#define VI0 0x00000000 -+#define VI1 0x00001000 -+ -+#define VI_MODE 0x000 -+#define VID_CFEN (0x00000003 << 30) -+#define VID_OSM (0x00000001 << 29) -+#define VID_FSEQ (0x00000001 << 28) -+#define AUX_CFEN (0x00000003 << 26) -+#define AUX_OSM (0x00000001 << 25) -+#define AUX_FSEQ (0x00000001 << 24) -+#define AUX_ANC_DATA (0x00000003 << 22) -+#define AUX_ANC_RAW (0x00000001 << 21) -+#define RST_ON_ERR (0x00000001 << 17) -+#define SOFT_RESET (0x00000001 << 16) -+#define IFF_CLAMP (0x00000001 << 14) -+#define IFF_MODE (0x00000003 << 12) -+#define DFF_CLAMP (0x00000001 << 10) -+#define DFF_MODE (0x00000003 << 8) -+#define HSP_CLAMP (0x00000001 << 3) -+#define HSP_RGB (0x00000001 << 2) -+#define HSP_MODE (0x00000003 << 0) -+ -+#define RCRB_CTRL 0x004 -+#define RCRB_CFG_ADDR 0x008 -+#define RCRB_CFG_EXT_ADDR 0x00c -+#define RCRB_IO_ADDR 0x010 -+#define RCRB_MEM_LADDR 0x014 -+#define RCRB_MEM_UADDR 0x018 -+#define RCRB_DATA 0x01c -+#define RCRB_MASK 0x020 -+#define RCRB_MSG_HDR 0x040 -+#define RCRB_MSG_PL0 0x044 -+#define RCRB_MSG_PL1 0x048 -+ -+#define ID_MASK0 0x020 -+#define VI_ID_MASK_0 (0x000000ff << 8) -+#define VI_DATA_ID_0 (0x000000ff << 0) -+ -+#define ID_MASK1 0x024 -+#define VI_ID_MASK_1 (0x000000ff << 8) -+#define VI_DATA_ID_1 (0x000000ff << 0) -+ -+#define VIP_LINE_THRESH 0x040 -+#define VI_LCTHR (0x000007ff << 0) -+ -+#define VIN_FORMAT 0x100 -+#define VI_VSRA (0x00000003 << 30) -+#define VI_SYNCHD (0x00000001 << 25) -+#define VI_DUAL_STREAM (0x00000001 << 24) -+#define VI_NHDAUX (0x00000001 << 20) -+#define VI_NPAR (0x00000001 << 19) -+#define VI_VSEL (0x00000003 << 14) -+#define VI_TWOS (0x00000001 << 13) -+#define VI_TPG (0x00000001 << 12) -+#define VI_FREF (0x00000001 << 10) -+#define VI_FTGL (0x00000001 << 9) -+#define VI_SF (0x00000001 << 3) -+#define VI_FZERO (0x00000001 << 2) -+#define VI_REVS (0x00000001 << 1) -+#define VI_REHS (0x00000001 << 0) -+ -+#define TC76543210 0x800 -+#define TCFEDCBA98 0x804 -+#define PHYCFG 0x900 -+#define CONFIG 0xfd4 -+#define INT_ENABLE_CLR 0xfd8 -+#define INT_ENABLE_SET 0xfdc -+ -+ -+#define INT_STATUS 0xfe0 -+#define VI_STAT_FID_AUX (0x00000001 << 31) -+#define VI_STAT_FID_VID (0x00000001 << 30) -+#define VI_STAT_FID_VPI (0x00000001 << 29) -+#define VI_STAT_LINE_COUNT (0x00000fff << 16) -+#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) -+#define VI_STAT_VID_OVRFLW (0x00000001 << 8) -+#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) -+#define VI_STAT_FID_SEQBRK (0x00000001 << 6) -+#define VI_STAT_LINE_THRESH (0x00000001 << 5) -+#define VI_STAT_AUX_WRAP (0x00000001 << 4) -+#define VI_STAT_AUX_START_IN (0x00000001 << 3) -+#define VI_STAT_AUX_END_OUT (0x00000001 << 2) -+#define VI_STAT_VID_START_IN (0x00000001 << 1) -+#define VI_STAT_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) -+#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) -+#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) -+#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) -+#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) -+#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) -+#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) -+#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) -+#define VI_ENABLE_VID_START_IN (0x00000001 << 1) -+#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define VIP_POWER_DOWN 0xff4 -+#define VI_PWR_DWN (0x00000001 << 31) -+ -+ -+ -+ -+/* -------------- FGPI Registers -------------- */ -+ -+#define FGPI0 0x00002000 -+#define FGPI1 0x00003000 -+#define FGPI2 0x00004000 -+#define FGPI3 0x00005000 -+ -+#define FGPI_CONTROL 0x000 -+#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) -+#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) -+#define FGPI_MODE (0x00000001 << 11) -+#define FGPI_SAMPLE_SIZE (0x00000003 << 8) -+#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) -+#define FGPI_REC_START_MSG_START (0x00000003 << 2) -+#define FGPI_TSTAMP_SELECT (0x00000001 << 1) -+#define FGPI_VAR_LENGTH (0x00000001 << 0) -+ -+#define FGPI_BASE_1 0x004 -+#define FGPI_BASE_2 0x008 -+#define FGPI_SIZE 0x00c -+#define FGPI_REC_SIZE 0x010 -+#define FGPI_STRIDE 0x014 -+#define FGPI_NUM_RECORD_1 0x018 -+#define FGPI_NUM_RECORD_2 0x01c -+#define FGPI_THRESHOLD_1 0x020 -+#define FGPI_THRESHOLD_2 0x024 -+#define FGPI_D1_XY_START 0x028 -+#define FGPI_D1_XY_END 0x02c -+ -+#define INT_STATUS 0xfe0 -+#define FGPI_BUF1_ACTIVE (0x00000001 << 7) -+#define FGPI_OVERFLOW (0x00000001 << 6) -+#define FGPI_MBE (0x00000001 << 5) -+#define FGPI_UNDERRUN (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED (0x00000001 << 2) -+#define FGPI_BUF2_FULL (0x00000001 << 1) -+#define FGPI_BUF1_FULL (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define FGPI_OVERFLOW_ENA (0x00000001 << 6) -+#define FGPI_MBE_ENA (0x00000001 << 5) -+#define FGPI_UNDERRUN_ENA (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) -+#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) -+#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define FGPI_OVERFLOW_ACK (0x00000001 << 6) -+#define FGPI_MBE_ACK (0x00000001 << 5) -+#define FGPI_UNDERRUN_ACK (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) -+#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) -+#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define FGPI_OVERFLOW_SET (0x00000001 << 6) -+#define FGPI_MBE_SET (0x00000001 << 5) -+#define FGPI_UNDERRUN_SET (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) -+#define FGPI_BUF2_DONE_SET (0x00000001 << 1) -+#define FGPI_BUF1_DONE_SET (0x00000001 << 0) -+ -+#define FGPI_SOFT_RESET 0xff0 -+#define FGPI_SOFTWARE_RESET (0x00000001 << 0) -+ -+#define FGPI_INTERFACE 0xff4 -+#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) -+ -+#define FGPI_MOD_ID_EXT 0xff8 -+#define FGPI_MODULE_ID 0xffc -+ -+ -+/* -------------- AI Registers ---------------- */ -+ -+#define AI0 0x00006000 -+#define AI1 0x00007000 -+ -+#define AI_STATUS 0x000 -+#define AI_BUF1_ACTIVE (0x00000001 << 4) -+#define AI_OVERRUN (0x00000001 << 3) -+#define AI_HBE (0x00000001 << 2) -+#define AI_BUF2_FULL (0x00000001 << 1) -+#define AI_BUF1_FULL (0x00000001 << 0) -+ -+#define AI_CTL 0x004 -+#define AI_RESET (0x00000001 << 31) -+#define AI_CAP_ENABLE (0x00000001 << 30) -+#define AI_CAP_MODE (0x00000003 << 28) -+#define AI_SIGN_CONVERT (0x00000001 << 27) -+#define AI_EARLYMODE (0x00000001 << 26) -+#define AI_DIAGMODE (0x00000001 << 25) -+#define AI_RAWMODE (0x00000001 << 24) -+#define AI_OVR_INTEN (0x00000001 << 7) -+#define AI_HBE_INTEN (0x00000001 << 6) -+#define AI_BUF2_INTEN (0x00000001 << 5) -+#define AI_BUF1_INTEN (0x00000001 << 4) -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_SERIAL 0x008 -+#define AI_SER_MASTER (0x00000001 << 31) -+#define AI_DATAMODE (0x00000001 << 30) -+#define AI_FRAMEMODE (0x00000003 << 28) -+#define AI_CLOCK_EDGE (0x00000001 << 27) -+#define AI_SSPOS4 (0x00000001 << 19) -+#define AI_NR_CHAN (0x00000003 << 17) -+#define AI_WSDIV (0x000001ff << 8) -+#define AI_SCKDIV (0x000000ff << 0) -+ -+#define AI_FRAMING 0x00c -+#define AI_VALIDPOS (0x000001ff << 22) -+#define AI_LEFTPOS (0x000001ff << 13) -+#define AI_RIGHTPOS (0x000001ff << 4) -+#define AI_SSPOS_3_0 (0x0000000f << 0) -+ -+#define AI_BASE1 0x014 -+#define AI_BASE2 0x018 -+#define AI_BASE (0x03ffffff << 6) -+ -+#define AI_SIZE 0x01c -+#define AI_SAMPLE_SIZE (0x03ffffff << 6) -+ -+#define AI_INT_ACK 0x020 -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_PWR_DOWN 0xff4 -+#define AI_PWR_DWN (0x00000001 << 0) -+ -+/* -------------- BAM Registers -------------- */ -+ -+#define BAM 0x00008000 -+ -+#define BAM_VI0_0_DMA_BUF_MODE 0x000 -+ -+#define BAM_VI0_0_ADDR_OFFST_0 0x004 -+#define BAM_VI0_0_ADDR_OFFST_1 0x008 -+#define BAM_VI0_0_ADDR_OFFST_2 0x00c -+#define BAM_VI0_0_ADDR_OFFST_3 0x010 -+#define BAM_VI0_0_ADDR_OFFST_4 0x014 -+#define BAM_VI0_0_ADDR_OFFST_5 0x018 -+#define BAM_VI0_0_ADDR_OFFST_6 0x01c -+#define BAM_VI0_0_ADDR_OFFST_7 0x020 -+ -+#define BAM_VI0_1_DMA_BUF_MODE 0x024 -+#define BAM_VI0_1_ADDR_OFFST_0 0x028 -+#define BAM_VI0_1_ADDR_OFFST_1 0x02c -+#define BAM_VI0_1_ADDR_OFFST_2 0x030 -+#define BAM_VI0_1_ADDR_OFFST_3 0x034 -+#define BAM_VI0_1_ADDR_OFFST_4 0x038 -+#define BAM_VI0_1_ADDR_OFFST_5 0x03c -+#define BAM_VI0_1_ADDR_OFFST_6 0x040 -+#define BAM_VI0_1_ADDR_OFFST_7 0x044 -+ -+#define BAM_VI0_2_DMA_BUF_MODE 0x048 -+#define BAM_VI0_2_ADDR_OFFST_0 0x04c -+#define BAM_VI0_2_ADDR_OFFST_1 0x050 -+#define BAM_VI0_2_ADDR_OFFST_2 0x054 -+#define BAM_VI0_2_ADDR_OFFST_3 0x058 -+#define BAM_VI0_2_ADDR_OFFST_4 0x05c -+#define BAM_VI0_2_ADDR_OFFST_5 0x060 -+#define BAM_VI0_2_ADDR_OFFST_6 0x064 -+#define BAM_VI0_2_ADDR_OFFST_7 0x068 -+ -+ -+#define BAM_VI1_0_DMA_BUF_MODE 0x06c -+#define BAM_VI1_0_ADDR_OFFST_0 0x070 -+#define BAM_VI1_0_ADDR_OFFST_1 0x074 -+#define BAM_VI1_0_ADDR_OFFST_2 0x078 -+#define BAM_VI1_0_ADDR_OFFST_3 0x07c -+#define BAM_VI1_0_ADDR_OFFST_4 0x080 -+#define BAM_VI1_0_ADDR_OFFST_5 0x084 -+#define BAM_VI1_0_ADDR_OFFST_6 0x088 -+#define BAM_VI1_0_ADDR_OFFST_7 0x08c -+ -+#define BAM_VI1_1_DMA_BUF_MODE 0x090 -+#define BAM_VI1_1_ADDR_OFFST_0 0x094 -+#define BAM_VI1_1_ADDR_OFFST_1 0x098 -+#define BAM_VI1_1_ADDR_OFFST_2 0x09c -+#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 -+#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 -+#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 -+#define BAM_VI1_1_ADDR_OFFST_6 0x0ac -+#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 -+ -+#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 -+#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 -+#define BAM_VI1_2_ADDR_OFFST_1 0x0bc -+#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 -+#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 -+#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 -+#define BAM_VI1_2_ADDR_OFFST_5 0x0cc -+#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 -+#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 -+ -+ -+#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 -+#define BAM_FGPI0_ADDR_OFFST_0 0x0dc -+#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 -+#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 -+#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 -+#define BAM_FGPI0_ADDR_OFFST_4 0x0ec -+#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 -+#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 -+#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 -+ -+#define BAM_FGPI1_DMA_BUF_MODE 0x0fc -+#define BAM_FGPI1_ADDR_OFFST_0 0x100 -+#define BAM_FGPI1_ADDR_OFFST_1 0x104 -+#define BAM_FGPI1_ADDR_OFFST_2 0x108 -+#define BAM_FGPI1_ADDR_OFFST_3 0x10c -+#define BAM_FGPI1_ADDR_OFFST_4 0x110 -+#define BAM_FGPI1_ADDR_OFFST_5 0x114 -+#define BAM_FGPI1_ADDR_OFFST_6 0x118 -+#define BAM_FGPI1_ADDR_OFFST_7 0x11c -+ -+#define BAM_FGPI2_DMA_BUF_MODE 0x120 -+#define BAM_FGPI2_ADDR_OFFST_0 0x124 -+#define BAM_FGPI2_ADDR_OFFST_1 0x128 -+#define BAM_FGPI2_ADDR_OFFST_2 0x12c -+#define BAM_FGPI2_ADDR_OFFST_3 0x130 -+#define BAM_FGPI2_ADDR_OFFST_4 0x134 -+#define BAM_FGPI2_ADDR_OFFST_5 0x138 -+#define BAM_FGPI2_ADDR_OFFST_6 0x13c -+#define BAM_FGPI2_ADDR_OFFST_7 0x140 -+ -+#define BAM_FGPI3_DMA_BUF_MODE 0x144 -+#define BAM_FGPI3_ADDR_OFFST_0 0x148 -+#define BAM_FGPI3_ADDR_OFFST_1 0x14c -+#define BAM_FGPI3_ADDR_OFFST_2 0x150 -+#define BAM_FGPI3_ADDR_OFFST_3 0x154 -+#define BAM_FGPI3_ADDR_OFFST_4 0x158 -+#define BAM_FGPI3_ADDR_OFFST_5 0x15c -+#define BAM_FGPI3_ADDR_OFFST_6 0x160 -+#define BAM_FGPI3_ADDR_OFFST_7 0x164 -+ -+ -+#define BAM_AI0_DMA_BUF_MODE 0x168 -+#define BAM_AI0_ADDR_OFFST_0 0x16c -+#define BAM_AI0_ADDR_OFFST_1 0x170 -+#define BAM_AI0_ADDR_OFFST_2 0x174 -+#define BAM_AI0_ADDR_OFFST_3 0x178 -+#define BAM_AI0_ADDR_OFFST_4 0x17c -+#define BAM_AIO_ADDR_OFFST_5 0x180 -+#define BAM_AI0_ADDR_OFFST_6 0x184 -+#define BAM_AIO_ADDR_OFFST_7 0x188 -+ -+#define BAM_AI1_DMA_BUF_MODE 0x18c -+#define BAM_AI1_ADDR_OFFST_0 0x190 -+#define BAM_AI1_ADDR_OFFST_1 0x194 -+#define BAM_AI1_ADDR_OFFST_2 0x198 -+#define BAM_AI1_ADDR_OFFST_3 0x19c -+#define BAM_AI1_ADDR_OFFST_4 0x1a0 -+#define BAM_AI1_ADDR_OFFST_5 0x1a4 -+#define BAM_AI1_ADDR_OFFST_6 0x1a8 -+#define BAM_AI1_ADDR_OFFST_7 0x1ac -+ -+#define BAM_SW_RST 0xff0 -+#define BAM_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+ -+/* -------------- MMU Registers -------------- */ -+ -+#define MMU 0x00009000 -+ -+#define MMU_MODE 0x000 -+ -+#define MMU_DMA_CONFIG0 0x004 -+#define MMU_DMA_CONFIG1 0x008 -+#define MMU_DMA_CONFIG2 0x00c -+#define MMU_DMA_CONFIG3 0x010 -+#define MMU_DMA_CONFIG4 0x014 -+#define MMU_DMA_CONFIG5 0x018 -+#define MMU_DMA_CONFIG6 0x01c -+#define MMU_DMA_CONFIG7 0x020 -+#define MMU_DMA_CONFIG8 0x024 -+#define MMU_DMA_CONFIG9 0x028 -+#define MMU_DMA_CONFIG10 0x02c -+#define MMU_DMA_CONFIG11 0x030 -+#define MMU_DMA_CONFIG12 0x034 -+#define MMU_DMA_CONFIG13 0x038 -+#define MMU_DMA_CONFIG14 0x03c -+#define MMU_DMA_CONFIG15 0x040 -+ -+#define MMU_SW_RST 0xff0 -+#define MMU_SW_RESET (0x0001 << 0) -+ -+#define MMU_PTA_BASE0 0x044 /* DMA 0 */ -+#define MMU_PTA_BASE1 0x084 /* DMA 1 */ -+#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ -+#define MMU_PTA_BASE3 0x104 /* DMA 3 */ -+#define MMU_PTA_BASE4 0x144 /* DMA 4 */ -+#define MMU_PTA_BASE5 0x184 /* DMA 5 */ -+#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ -+#define MMU_PTA_BASE7 0x204 /* DMA 7 */ -+#define MMU_PTA_BASE8 0x244 /* DMA 8 */ -+#define MMU_PTA_BASE9 0x284 /* DMA 9 */ -+#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ -+#define MMU_PTA_BASE11 0x304 /* DMA 11 */ -+#define MMU_PTA_BASE12 0x344 /* DMA 12 */ -+#define MMU_PTA_BASE13 0x384 /* DMA 13 */ -+#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ -+#define MMU_PTA_BASE15 0x404 /* DMA 15 */ -+ -+#define MMU_PTA_BASE 0x044 /* DMA 0 */ -+#define MMU_PTA_OFFSET 0x40 -+ -+#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) -+ -+#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 -+#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 -+#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 -+#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c -+#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 -+#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 -+#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 -+#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c -+#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 -+#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 -+#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 -+#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c -+#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 -+#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 -+#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 -+#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c -+ -+ -+/* -------------- MSI Registers -------------- */ -+ -+#define MSI 0x0000a000 -+ -+#define MSI_DELAY_TIMER 0x000 -+#define MSI_DELAY_1CLK (0x00000001 << 0) -+#define MSI_DELAY_2CLK (0x00000002 << 0) -+ -+#define MSI_INTA_POLARITY 0x004 -+#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) -+ -+#define MSI_CONFIG0 0x008 -+#define MSI_CONFIG1 0x00c -+#define MSI_CONFIG2 0x010 -+#define MSI_CONFIG3 0x014 -+#define MSI_CONFIG4 0x018 -+#define MSI_CONFIG5 0x01c -+#define MSI_CONFIG6 0x020 -+#define MSI_CONFIG7 0x024 -+#define MSI_CONFIG8 0x028 -+#define MSI_CONFIG9 0x02c -+#define MSI_CONFIG10 0x030 -+#define MSI_CONFIG11 0x034 -+#define MSI_CONFIG12 0x038 -+#define MSI_CONFIG13 0x03c -+#define MSI_CONFIG14 0x040 -+#define MSI_CONFIG15 0x044 -+#define MSI_CONFIG16 0x048 -+#define MSI_CONFIG17 0x04c -+#define MSI_CONFIG18 0x050 -+#define MSI_CONFIG19 0x054 -+#define MSI_CONFIG20 0x058 -+#define MSI_CONFIG21 0x05c -+#define MSI_CONFIG22 0x060 -+#define MSI_CONFIG23 0x064 -+#define MSI_CONFIG24 0x068 -+#define MSI_CONFIG25 0x06c -+#define MSI_CONFIG26 0x070 -+#define MSI_CONFIG27 0x074 -+#define MSI_CONFIG28 0x078 -+#define MSI_CONFIG29 0x07c -+#define MSI_CONFIG30 0x080 -+#define MSI_CONFIG31 0x084 -+#define MSI_CONFIG32 0x088 -+#define MSI_CONFIG33 0x08c -+#define MSI_CONFIG34 0x090 -+#define MSI_CONFIG35 0x094 -+#define MSI_CONFIG36 0x098 -+#define MSI_CONFIG37 0x09c -+#define MSI_CONFIG38 0x0a0 -+#define MSI_CONFIG39 0x0a4 -+#define MSI_CONFIG40 0x0a8 -+#define MSI_CONFIG41 0x0ac -+#define MSI_CONFIG42 0x0b0 -+#define MSI_CONFIG43 0x0b4 -+#define MSI_CONFIG44 0x0b8 -+#define MSI_CONFIG45 0x0bc -+#define MSI_CONFIG46 0x0c0 -+#define MSI_CONFIG47 0x0c4 -+#define MSI_CONFIG48 0x0c8 -+#define MSI_CONFIG49 0x0cc -+#define MSI_CONFIG50 0x0d0 -+ -+#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) -+#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) -+#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) -+#define MSI_TC (0x00000007 << 16) -+#define MSI_ID (0x0000000f << 0) -+ -+#define MSI_INT_STATUS_L 0xfc0 -+#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) -+#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) -+#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) -+#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) -+#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) -+#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) -+#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) -+#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) -+#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) -+#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) -+#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) -+#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) -+#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) -+#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) -+#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) -+#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) -+#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) -+#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) -+#define MSI_INT_OVRFLW_FGPI_O (0x00000001 << 18) -+#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) -+#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) -+#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) -+#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) -+#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) -+#define MSI_INT_AVINT_VI0 (0x00000001 << 24) -+#define MSI_INT_AVINT_VI1 (0x00000001 << 25) -+#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) -+#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) -+#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) -+#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) -+#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) -+#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) -+ -+#define MSI_INT_STATUS_H 0xfc4 -+#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) -+#define MSI_INT_EXTINT_0 (0x00000001 << 1) -+#define MSI_INT_EXTINT_1 (0x00000001 << 2) -+#define MSI_INT_EXTINT_2 (0x00000001 << 3) -+#define MSI_INT_EXTINT_3 (0x00000001 << 4) -+#define MSI_INT_EXTINT_4 (0x00000001 << 5) -+#define MSI_INT_EXTINT_5 (0x00000001 << 6) -+#define MSI_INT_EXTINT_6 (0x00000001 << 7) -+#define MSI_INT_EXTINT_7 (0x00000001 << 8) -+#define MSI_INT_EXTINT_8 (0x00000001 << 9) -+#define MSI_INT_EXTINT_9 (0x00000001 << 10) -+#define MSI_INT_EXTINT_10 (0x00000001 << 11) -+#define MSI_INT_EXTINT_11 (0x00000001 << 12) -+#define MSI_INT_EXTINT_12 (0x00000001 << 13) -+#define MSI_INT_EXTINT_13 (0x00000001 << 14) -+#define MSI_INT_EXTINT_14 (0x00000001 << 15) -+#define MSI_INT_EXTINT_15 (0x00000001 << 16) -+#define MSI_INT_I2CINT_0 (0x00000001 << 17) -+#define MSI_INT_I2CINT_1 (0x00000001 << 18) -+ -+#define MSI_INT_STATUS_CLR_L 0xfc8 -+#define MSI_INT_STATUS_CLR_H 0xfcc -+#define MSI_INT_STATUS_SET_L 0xfd0 -+#define MSI_INT_STATUS_SET_H 0xfd4 -+#define MSI_INT_ENA_L 0xfd8 -+#define MSI_INT_ENA_H 0xfdc -+#define MSI_INT_ENA_CLR_L 0xfe0 -+#define MSI_INT_ENA_CLR_H 0xfe4 -+#define MSI_INT_ENA_SET_L 0xfe8 -+#define MSI_INT_ENA_SET_H 0xfec -+ -+#define MSI_SW_RST 0xff0 -+#define MSI_SW_RESET (0x0001 << 0) -+ -+#define MSI_MODULE_ID 0xffc -+ -+ -+/* -------------- I2C Registers -------------- */ -+ -+#define I2C_B 0x0000b000 -+#define I2C_A 0x0000c000 -+ -+#define RX_FIFO 0x000 -+#define I2C_RX_BYTE (0x000000ff << 0) -+ -+#define TX_FIFO 0x000 -+#define I2C_STOP_BIT (0x00000001 << 9) -+#define I2C_START_BIT (0x00000001 << 8) -+#define I2C_TX_BYTE (0x000000ff << 0) -+ -+#define I2C_STATUS 0x008 -+#define I2C_TRANSMIT (0x00000001 << 11) -+#define I2C_RECEIVE (0x00000001 << 10) -+#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) -+#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) -+#define I2C_TRANSMIT_PROG (0x00000001 << 7) -+#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) -+#define I2C_RECEIVE_PROG (0x00000001 << 5) -+#define I2C_RECEIVE_CLEAR (0x00000001 << 4) -+#define I2C_SDA_LINE (0x00000001 << 3) -+#define I2C_SCL_LINE (0x00000001 << 2) -+#define I2C_START_STOP_FLAG (0x00000001 << 1) -+#define I2C_MODE_STATUS (0x00000001 << 0) -+ -+#define I2C_CONTROL 0x00c -+#define I2C_SCL_CONTROL (0x00000001 << 7) -+#define I2C_SDA_CONTROL (0x00000001 << 6) -+#define I2C_RECEIVE_PROTECT (0x00000001 << 5) -+#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) -+#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) -+#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) -+#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) -+#define I2C_RESET (0x00000001 << 0) -+ -+#define I2C_CLOCK_DIVISOR_HIGH 0x010 -+#define I2C_CLOCK_HIGH (0x0000ffff << 0) -+ -+#define I2C_CLOCK_DIVISOR_LOW 0x014 -+#define I2C_CLOCK_LOW (0x0000ffff << 0) -+ -+#define I2C_RX_LEVEL 0x01c -+#define I2C_RECEIVE_RANGE (0x0000007f << 0) -+ -+#define I2C_TX_LEVEL 0x020 -+#define I2C_TRANSMIT_RANGE (0x0000007f << 0) -+ -+#define I2C_SDA_HOLD 0x028 -+#define I2C_HOLD_TIME (0x0000007f << 0) -+ -+#define MODULE_CONF 0xfd4 -+#define INT_CLR_ENABLE 0xfd8 -+#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) -+#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) -+#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) -+#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) -+#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) -+#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_SET_ENABLE 0xfdc -+#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_SET_ENABLE_RFF (0x00000001 << 9) -+#define I2C_SET_ENABLE_STDR (0x00000001 << 8) -+#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_SET_ENABLE_IBE (0x00000001 << 6) -+#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_SET_ENABLE_STSD (0x00000001 << 3) -+#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_SET_ENABLE_MAF (0x00000001 << 1) -+#define I2C_SET_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_STATUS 0xfe0 -+#define I2C_INTERRUPT_STFNF (0x00000001 << 12) -+#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) -+#define I2C_INTERRUPT_RFDA (0x00000001 << 10) -+#define I2C_INTERRUPTE_RFF (0x00000001 << 9) -+#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) -+#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) -+#define I2C_ERROR_IBE (0x00000001 << 6) -+#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) -+#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) -+#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) -+#define I2C_ACK_INTER_MTNA (0x00000001 << 2) -+#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) -+#define I2C_INTERRUPT_MTD (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define I2C_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_ENABLE_RFF (0x00000001 << 9) -+#define I2C_ENABLE_STDR (0x00000001 << 8) -+#define I2C_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_ENABLE_IBE (0x00000001 << 6) -+#define I2C_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_ENABLE_STSD (0x00000001 << 3) -+#define I2C_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_ENABLE_MAF (0x00000001 << 1) -+#define I2C_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) -+#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) -+#define I2C_CLR_STATUS_RFF (0x00000001 << 9) -+#define I2C_CLR_STATUS_STDR (0x00000001 << 8) -+#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) -+#define I2C_CLR_STATUS_IBE (0x00000001 << 6) -+#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) -+#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) -+#define I2C_CLR_STATUS_STSD (0x00000001 << 3) -+#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) -+#define I2C_CLR_STATUS_MAF (0x00000001 << 1) -+#define I2C_CLR_STATIS_MTD (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define I2C_SET_STATUS_STFNF (0x00000001 << 12) -+#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_SET_STATUS_RFDA (0x00000001 << 10) -+#define I2C_SET_STATUS_RFF (0x00000001 << 9) -+#define I2C_SET_STATUS_STDR (0x00000001 << 8) -+#define I2C_SET_STATUS_MTDR (0x00000001 << 7) -+#define I2C_SET_STATUS_IBE (0x00000001 << 6) -+#define I2C_SET_STATUS_MSMC (0x00000001 << 5) -+#define I2C_SET_STATUS_SRSD (0x00000001 << 4) -+#define I2C_SET_STATUS_STSD (0x00000001 << 3) -+#define I2C_SET_STATUS_MTNA (0x00000001 << 2) -+#define I2C_SET_STATUS_MAF (0x00000001 << 1) -+#define I2C_SET_STATIS_MTD (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- SPI Registers -------------- */ -+ -+#define SPI 0x0000d000 -+ -+#define SPI_CONTROL_REG 0x000 -+#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) -+#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) -+#define SPI_MODE_SELECT (0x00000001 << 5) -+#define SPI_CLOCK_POLARITY (0x00000001 << 4) -+#define SPI_CLOCK_PHASE (0x00000001 << 3) -+ -+#define SPI_STATUS 0x004 -+#define SPI_TRANSFER_FLAG (0x00000001 << 7) -+#define SPI_WRITE_COLLISSION (0x00000001 << 6) -+#define SPI_READ_OVERRUN (0x00000001 << 5) -+#define SPI_MODE_FAULT (0x00000001 << 4) -+#define SPI_SLAVE_ABORT (0x00000001 << 3) -+ -+#define SPI_DATA 0x008 -+#define SPI_BIDI_DATA (0x000000ff << 0) -+ -+#define SPI_CLOCK_COUNTER 0x00c -+#define SPI_CLOCK (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- GPIO Registers -------------- */ -+ -+#define GPIO 0x0000e000 -+ -+#define GPIO_RD 0x000 -+#define GPIO_WR 0x004 -+#define GPIO_WR_MODE 0x008 -+#define GPIO_OEN 0x00c -+ -+#define GPIO_SW_RST 0xff0 -+#define GPIO_SW_RESET (0x00000001 << 0) -+ -+#define GPIO_31 (1 << 31) -+#define GPIO_30 (1 << 30) -+#define GPIO_29 (1 << 29) -+#define GPIO_28 (1 << 28) -+#define GPIO_27 (1 << 27) -+#define GPIO_26 (1 << 26) -+#define GPIO_25 (1 << 25) -+#define GPIO_24 (1 << 24) -+#define GPIO_23 (1 << 23) -+#define GPIO_22 (1 << 22) -+#define GPIO_21 (1 << 21) -+#define GPIO_20 (1 << 20) -+#define GPIO_19 (1 << 19) -+#define GPIO_18 (1 << 18) -+#define GPIO_17 (1 << 17) -+#define GPIO_16 (1 << 16) -+#define GPIO_15 (1 << 15) -+#define GPIO_14 (1 << 14) -+#define GPIO_13 (1 << 13) -+#define GPIO_12 (1 << 12) -+#define GPIO_11 (1 << 11) -+#define GPIO_10 (1 << 10) -+#define GPIO_09 (1 << 9) -+#define GPIO_08 (1 << 8) -+#define GPIO_07 (1 << 7) -+#define GPIO_06 (1 << 6) -+#define GPIO_05 (1 << 5) -+#define GPIO_04 (1 << 4) -+#define GPIO_03 (1 << 3) -+#define GPIO_02 (1 << 2) -+#define GPIO_01 (1 << 1) -+#define GPIO_00 (1 << 0) -+ -+/* -------------- PHI_0 Registers -------------- */ -+ -+#define PHI_0 0x0000f000 -+ -+#define PHI_0_MODE 0x0000 -+#define PHI_0_0_CONFIG 0x0008 -+#define PHI_0_1_CONFIG 0x000c -+#define PHI_0_2_CONFIG 0x0010 -+#define PHI_0_3_CONFIG 0x0014 -+ -+#define PHI_POLARITY 0x0038 -+#define PHI_TIMEOUT 0x003c -+#define PHI_SW_RST 0x0ff0 -+ -+#define PHI_0_0_RW_0 0x1000 -+#define PHI_0_0_RW_511 0x17fc -+ -+#define PHI_0_1_RW_0 0x1800 -+#define PHI_0_1_RW_511 0x1ffc -+ -+#define PHI_0_2_RW_0 0x2000 -+#define PHI_0_2_RW_511 0x27fc -+ -+#define PHI_0_3_RW_0 0x2800 -+#define PHI_0_3_RW_511 0x2ffc -+ -+#define PHI_CSN_DEASSERT (0x00000001 << 2) -+#define PHI_AUTO_INCREMENT (0x00000001 << 1) -+#define PHI_FIFO_MODE (0x00000001 << 0) -+ -+#define PHI_DELAY_RD_WR (0x0000001f << 27) -+#define PHI_EXTEND_RDY3 (0x00000003 << 25) -+#define PHI_EXTEND_RDY2 (0x00000003 << 23) -+#define PHI_EXTEND_RDY1 (0x00000003 << 21) -+#define PHI_EXTEND_RDY0 (0x00000003 << 19) -+#define PHI_RDY3_OD (0x00000001 << 18) -+#define PHI_RDY2_OD (0x00000001 << 17) -+#define PHI_RDY1_OD (0x00000001 << 16) -+#define PHI_RDY0_OD (0x00000001 << 15) -+#define PHI_ALE_POL (0x00000001 << 14) -+#define PHI_WRN_POL (0x00000001 << 13) -+#define PHI_RDN_POL (0x00000001 << 12) -+#define PHI_RDY3_POL (0x00000001 << 11) -+#define PHI_RDY2_POL (0x00000001 << 10) -+#define PHI_RDY1_POL (0x00000001 << 9) -+#define PHI_RDY0_POL (0x00000001 << 8) -+#define PHI_CSN7_POL (0x00000001 << 7) -+#define PHI_CSN6_POL (0x00000001 << 6) -+#define PHI_CSN5_POL (0x00000001 << 5) -+#define PHI_CSN4_POL (0x00000001 << 4) -+#define PHI_CSN3_POL (0x00000001 << 3) -+#define PHI_CSN2_POL (0x00000001 << 2) -+#define PHI_CSN1_POL (0x00000001 << 1) -+#define PHI_CSN0_POL (0x00000001 << 0) -+ -+/* -------------- PHI_1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+#define PHI_1_MODE 0x00004 -+#define PHI_1_0_CONFIG 0x00018 -+#define PHI_1_1_CONFIG 0x0001c -+#define PHI_1_2_CONFIG 0x00020 -+#define PHI_1_3_CONFIG 0x00024 -+#define PHI_1_4_CONFIG 0x00028 -+#define PHI_1_5_CONFIG 0x0002c -+#define PHI_1_6_CONFIG 0x00030 -+#define PHI_1_7_CONFIG 0x00034 -+ -+#define PHI_1_0_RW_0 0x00000 -+#define PHI_1_0_RW_16383 0x0fffc -+ -+#define PHI_1_1_RW_0 0x1000 -+#define PHI_1_1_RW_16383 0x1ffc -+ -+#define PHI_1_2_RW_0 0x2000 -+#define PHI_1_2_RW_16383 0x2ffc -+ -+#define PHI_1_3_RW_0 0x3000 -+#define PHI_1_3_RW_16383 0x3ffc -+ -+#define PHI_1_4_RW_0 0x4000 -+#define PHI_1_4_RW_16383 0x4ffc -+ -+#define PHI_1_5_RW_0 0x5000 -+#define PHI_1_5_RW_16383 0x5ffc -+ -+#define PHI_1_6_RW_0 0x6000 -+#define PHI_1_6_RW_16383 0x6ffc -+ -+#define PHI_1_7_RW_0 0x7000 -+#define PHI_1_7_RW_16383 0x7ffc -+ -+/* -------------- CGU Registers -------------- */ -+ -+#define CGU 0x00013000 -+ -+#define CGU_SCR_0 0x000 -+#define CGU_SCR_1 0x004 -+#define CGU_SCR_2 0x008 -+#define CGU_SCR_3 0x00c -+#define CGU_SCR_4 0x010 -+#define CGU_SCR_5 0x014 -+#define CGU_SCR_6 0x018 -+#define CGU_SCR_7 0x01c -+#define CGU_SCR_8 0x020 -+#define CGU_SCR_9 0x024 -+#define CGU_SCR_10 0x028 -+#define CGU_SCR_11 0x02c -+#define CGU_SCR_12 0x030 -+#define CGU_SCR_13 0x034 -+#define CGU_SCR_STOP (0x00000001 << 3) -+#define CGU_SCR_RESET (0x00000001 << 2) -+#define CGU_SCR_ENF2 (0x00000001 << 1) -+#define CGU_SCR_ENF1 (0x00000001 << 0) -+ -+#define CGU_FS1_0 0x038 -+#define CGU_FS1_1 0x03c -+#define CGU_FS1_2 0x040 -+#define CGU_FS1_3 0x044 -+#define CGU_FS1_4 0x048 -+#define CGU_FS1_5 0x04c -+#define CGU_FS1_6 0x050 -+#define CGU_FS1_7 0x054 -+#define CGU_FS1_8 0x058 -+#define CGU_FS1_9 0x05c -+#define CGU_FS1_10 0x060 -+#define CGU_FS1_11 0x064 -+#define CGU_FS1_12 0x068 -+#define CGU_FS1_13 0x06c -+#define CGU_FS1_PLL (0x00000000 << 0) -+ -+ -+#define CGU_FS2_0 0x070 -+#define CGU_FS2_1 0x074 -+#define CGU_FS2_2 0x078 -+#define CGU_FS2_3 0x07c -+#define CGU_FS2_4 0x080 -+#define CGU_FS2_5 0x084 -+#define CGU_FS2_6 0x088 -+#define CGU_FS2_7 0x08c -+#define CGU_FS2_8 0x090 -+#define CGU_FS2_9 0x094 -+#define CGU_FS2_10 0x098 -+#define CGU_FS2_11 0x09c -+#define CGU_FS2_12 0x0a0 -+#define CGU_FS2_13 0x0a4 -+ -+#define CGU_SSR_0 0x0a8 -+#define CGU_SSR_1 0x0ac -+#define CGU_SSR_2 0x0b0 -+#define CGU_SSR_3 0x0b4 -+#define CGU_SSR_4 0x0b8 -+#define CGU_SSR_5 0x0bc -+#define CGU_SSR_6 0x0c0 -+#define CGU_SSR_7 0x0c4 -+#define CGU_SSR_8 0x0c8 -+#define CGU_SSR_9 0x0cc -+#define CGU_SSR_10 0x0d0 -+#define CGU_SSR_11 0x0d4 -+#define CGU_SSR_12 0x0d8 -+#define CGU_SSR_13 0x0dc -+ -+#define CGU_PCR_0_0 0x0e0 -+#define CGU_PCR_0_1 0x0e4 -+#define CGU_PCR_0_2 0x0e8 -+#define CGU_PCR_0_3 0x0ec -+#define CGU_PCR_0_4 0x0f0 -+#define CGU_PCR_0_5 0x0f4 -+#define CGU_PCR_0_6 0x0f8 -+#define CGU_PCR_0_7 0x0fc -+#define CGU_PCR_1_0 0x100 -+#define CGU_PCR_1_1 0x104 -+#define CGU_PCR_2_0 0x108 -+#define CGU_PCR_2_1 0x10c -+#define CGU_PCR_3_0 0x110 -+#define CGU_PCR_3_1 0x114 -+#define CGU_PCR_3_2 0x118 -+#define CGU_PCR_4_0 0x11c -+#define CGU_PCR_4_1 0x120 -+#define CGU_PCR_5 0x124 -+#define CGU_PCR_6 0x128 -+#define CGU_PCR_7 0x12c -+#define CGU_PCR_8 0x130 -+#define CGU_PCR_9 0x134 -+#define CGU_PCR_10 0x138 -+#define CGU_PCR_11 0x13c -+#define CGU_PCR_12 0x140 -+#define CGU_PCR_13 0x144 -+#define CGU_PCR_WAKE_EN (0x00000001 << 2) -+#define CGU_PCR_AUTO (0x00000001 << 1) -+#define CGU_PCR_RUN (0x00000001 << 0) -+ -+ -+#define CGU_PSR_0_0 0x148 -+#define CGU_PSR_0_1 0x14c -+#define CGU_PSR_0_2 0x150 -+#define CGU_PSR_0_3 0x154 -+#define CGU_PSR_0_4 0x158 -+#define CGU_PSR_0_5 0x15c -+#define CGU_PSR_0_6 0x160 -+#define CGU_PSR_0_7 0x164 -+#define CGU_PSR_1_0 0x168 -+#define CGU_PSR_1_1 0x16c -+#define CGU_PSR_2_0 0x170 -+#define CGU_PSR_2_1 0x174 -+#define CGU_PSR_3_0 0x178 -+#define CGU_PSR_3_1 0x17c -+#define CGU_PSR_3_2 0x180 -+#define CGU_PSR_4_0 0x184 -+#define CGU_PSR_4_1 0x188 -+#define CGU_PSR_5 0x18c -+#define CGU_PSR_6 0x190 -+#define CGU_PSR_7 0x194 -+#define CGU_PSR_8 0x198 -+#define CGU_PSR_9 0x19c -+#define CGU_PSR_10 0x1a0 -+#define CGU_PSR_11 0x1a4 -+#define CGU_PSR_12 0x1a8 -+#define CGU_PSR_13 0x1ac -+ -+#define CGU_ESR_0_0 0x1b0 -+#define CGU_ESR_0_1 0x1b4 -+#define CGU_ESR_0_2 0x1b8 -+#define CGU_ESR_0_3 0x1bc -+#define CGU_ESR_0_4 0x1c0 -+#define CGU_ESR_0_5 0x1c4 -+#define CGU_ESR_0_6 0x1c8 -+#define CGU_ESR_0_7 0x1cc -+#define CGU_ESR_1_0 0x1d0 -+#define CGU_ESR_1_1 0x1d4 -+#define CGU_ESR_2_0 0x1d8 -+#define CGU_ESR_2_1 0x1dc -+#define CGU_ESR_3_0 0x1e0 -+#define CGU_ESR_3_1 0x1e4 -+#define CGU_ESR_3_2 0x1e8 -+#define CGU_ESR_4_0 0x1ec -+#define CGU_ESR_4_1 0x1f0 -+#define CGU_ESR_5 0x1f4 -+#define CGU_ESR_6 0x1f8 -+#define CGU_ESR_7 0x1fc -+#define CGU_ESR_8 0x200 -+#define CGU_ESR_9 0x204 -+#define CGU_ESR_10 0x208 -+#define CGU_ESR_11 0x20c -+#define CGU_ESR_12 0x210 -+#define CGU_ESR_13 0x214 -+#define CGU_ESR_FD_EN (0x00000001 << 0) -+ -+#define CGU_FDC_0 0x218 -+#define CGU_FDC_1 0x21c -+#define CGU_FDC_2 0x220 -+#define CGU_FDC_3 0x224 -+#define CGU_FDC_4 0x228 -+#define CGU_FDC_5 0x22c -+#define CGU_FDC_6 0x230 -+#define CGU_FDC_7 0x234 -+#define CGU_FDC_8 0x238 -+#define CGU_FDC_9 0x23c -+#define CGU_FDC_10 0x240 -+#define CGU_FDC_11 0x244 -+#define CGU_FDC_12 0x248 -+#define CGU_FDC_13 0x24c -+#define CGU_FDC_STRETCH (0x00000001 << 0) -+#define CGU_FDC_RESET (0x00000001 << 1) -+#define CGU_FDC_RUN1 (0x00000001 << 2) -+#define CGU_FDC_MADD (0x000000ff << 3) -+#define CGU_FDC_MSUB (0x000000ff << 11) -+ -+/* -------------- DCS Registers -------------- */ -+ -+#define DCS 0x00014000 -+ -+#define DCSC_CTRL 0x000 -+#define DCSC_SEL_PLLDI (0x03ffffff << 5) -+#define DCSC_TOUT_SEL (0x0000000f << 1) -+#define DCSC_TOUT_OFF (0x00000001 << 0) -+ -+#define DCSC_ADDR 0x00c -+#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) -+ -+#define DCSC_STAT 0x010 -+#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) -+#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) -+#define DCSC_ERR_TOUT_READ (0x00000001 << 8) -+#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) -+#define DCSC_ERR_ACK (0x00000001 << 1) -+ -+#define DCSC_FEATURES 0x040 -+#define DCSC_UNIQUE_ID (0x00000007 << 16) -+#define DCSC_SECURITY (0x00000001 << 14) -+#define DCSC_NUM_BASE_REGS (0x00000003 << 11) -+#define DCSC_NUM_TARGETS (0x0000001f << 5) -+#define DCSC_NUM_INITIATORS (0x0000001f << 0) -+ -+#define DCSC_BASE_REG0 0x100 -+#define DCSC_BASE_N_REG (0x00000fff << 20) -+ -+#define DCSC_INT_CLR_ENABLE 0xfd8 -+#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_ENABLE 0xfdc -+#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_STATUS 0xfe0 -+#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) -+#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_ENABLE 0xfe4 -+#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_CLR_STATUS 0xfe8 -+#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_STATUS 0xfec -+#define DCSC_INT_SET_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ERROR (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- GREG Registers -------------- */ -+ -+#define GREG 0x00012000 -+ -+#define GREG_SUBSYS_CONFIG 0x000 -+#define GREG_SUBSYS_ID (0x0000ffff << 16) -+#define GREG_SUBSYS_VID (0x0000ffff << 0) -+ -+#define GREG_MSI_BAR_PMCSR 0x004 -+#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) -+#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) -+#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) -+#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) -+#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) -+#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) -+#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) -+#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) -+ -+#define GREG_BAR_WIDTH_17 (0x0000001e << 8) -+#define GREG_BAR_WIDTH_18 (0x0000001c << 8) -+#define GREG_BAR_WIDTH_19 (0x00000018 << 8) -+#define GREG_BAR_WIDTH_20 (0x00000010 << 8) -+ -+#define GREG_BAR_PREFETCH (0x00000001 << 3) -+#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! -+#define GREG_MSI_MM_CAP2 (0x00000001 << 0) -+#define GREG_MSI_MM_CAP4 (0x00000002 << 0) -+#define GREG_MSI_MM_CAP8 (0x00000003 << 0) -+#define GREG_MSI_MM_CAP16 (0x00000004 << 0) -+#define GREG_MSI_MM_CAP32 (0x00000005 << 0) -+ -+#define GREG_PMCSR_DATA_1 0x008 -+#define GREG_PMCSR_DATA_2 0x00c -+#define GREG_VI_CTRL 0x010 -+#define GREG_FGPI_CTRL 0x014 -+ -+#define GREG_RSTU_CTRL 0x018 -+#define GREG_BOOT_READY (0x00000001 << 13) -+#define GREG_RESET_REQ (0x00000001 << 12) -+#define GREG_IP_RST_RELEASE (0x00000001 << 11) -+#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) -+#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) -+#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) -+#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) -+#define GREG_CGU_RST_RELEASE (0x00000001 << 6) -+#define GREG_IP_RST_ASSERT (0x00000001 << 5) -+#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) -+#define GREG_RST_ASSERT (0x00000001 << 3) -+#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) -+#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) -+#define GREG_CGU_RST_ASSERT (0x00000001 << 0) -+ -+#define GREG_I2C_CTRL 0x01c -+#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) -+ -+#define GREG_OVFLW_CTRL 0x020 -+#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) -+ -+#define GREG_TAG_ACK_FLEN 0x024 -+#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) -+#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) -+#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) -+#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) -+ -+#define GREG_VIDEO_IN_CTRL 0x028 -+ -+#define GREG_SPARE_1 0x02c -+#define GREG_SPARE_2 0x030 -+#define GREG_SPARE_3 0x034 -+#define GREG_SPARE_4 0x038 -+#define GREG_SPARE_5 0x03c -+#define GREG_SPARE_6 0x040 -+#define GREG_SPARE_7 0x044 -+#define GREG_SPARE_8 0x048 -+#define GREG_SPARE_9 0x04c -+#define GREG_SPARE_10 0x050 -+#define GREG_SPARE_11 0x054 -+#define GREG_SPARE_12 0x058 -+#define GREG_SPARE_13 0x05c -+#define GREG_SPARE_14 0x060 -+#define GREG_SPARE_15 0x064 -+ -+#define GREG_FAIL_DISABLE 0x068 -+#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) -+ -+#define GREG_SW_RST 0xff0 -+#define GREG_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+/* BAR = 20 bits */ -+ -+/* -------------- PHI1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+ -+ -+#endif /* __SAA716x_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_rom.c b/drivers/media/common/saa716x/saa716x_rom.c -new file mode 100644 -index 0000000..7f8dbe1 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_rom.c -@@ -0,0 +1,1071 @@ -+#include -+#include -+ -+#include "saa716x_rom.h" -+#include "saa716x_adap.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+int i; -+ -+static int eeprom_read_bytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ -+ u8 b0[] = { MSB(reg), LSB(reg) }; -+ int ret; -+ -+ struct i2c_msg msg[] = { -+ { .addr = 0x50, .flags = 0, .buf = b0, .len = sizeof (b0) }, -+ { .addr = 0x50, .flags = I2C_M_RD, .buf = val, .len = len } -+ }; -+ -+ ret = i2c_transfer(adapter, msg, 2); -+ if (ret != 2) { -+ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); -+ return -EREMOTEIO; -+ } -+ -+ return ret; -+} -+ -+static int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ struct i2c_msg msg[2]; -+ -+ u8 b0[2]; -+ int ret, count; -+ -+ count = len / DUMP_BYTES; -+ if (len % DUMP_BYTES) -+ count++; -+ -+ count *= 2; -+ -+ for (i = 0; i < count; i += 2) { -+ dprintk(SAA716x_DEBUG, 1, "Length=%d, Count=%d, Reg=0x%02x", -+ len, -+ count, -+ reg); -+ -+ b0[0] = MSB(reg); -+ b0[1] = LSB(reg); -+ -+ /* Write */ -+ msg[0].addr = 0x50; -+ msg[0].flags = 0; -+ msg[0].buf = b0; -+ msg[0].len = 2; -+ -+ /* Read */ -+ msg[1].addr = 0x50; -+ msg[1].flags = I2C_M_RD; -+ msg[1].buf = val; -+ -+ if (i == (count - 2)) { -+ /* last message */ -+ if (len % DUMP_BYTES) { -+ msg[1].len = len % DUMP_BYTES; -+ dprintk(SAA716x_DEBUG, 1, "Last Message length=%d", len % DUMP_BYTES); -+ } else { -+ msg[1].len = DUMP_BYTES; -+ } -+ } else { -+ msg[1].len = DUMP_BYTES; -+ } -+ -+ ret = i2c_transfer(adapter, msg, 2); -+ if (ret != 2) { -+ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); -+ return -EREMOTEIO; -+ } -+ -+ reg += DUMP_BYTES; -+ val += DUMP_BYTES; -+ } -+ -+ return 0; -+} -+ -+static int saa716x_get_offset(struct saa716x_dev *saa716x, u8 *buf, u32 *offset) -+{ -+ int i; -+ -+ *offset = 0; -+ for (i = 0; i < 256; i++) { -+ if (!(strncmp("START", buf + i, 5))) -+ break; -+ } -+ dprintk(SAA716x_INFO, 1, "Offset @ %d", i); -+ *offset = i; -+ -+ return 0; -+} -+ -+static int saa716x_eeprom_header(struct saa716x_dev *saa716x, -+ struct saa716x_romhdr *rom_header, -+ u8 *buf, -+ u32 *offset) -+{ -+ memcpy(rom_header, &buf[*offset], sizeof (struct saa716x_romhdr)); -+ if (rom_header->header_size != sizeof (struct saa716x_romhdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ (int)sizeof (struct saa716x_romhdr), -+ rom_header->header_size); -+ -+ return -1; -+ } -+ *offset += sizeof (struct saa716x_romhdr); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Data=%d bytes\n", -+ saa716x->pdev->device, -+ rom_header->data_size); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Version=%d\n", -+ saa716x->pdev->device, -+ rom_header->version); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Devices=%d\n", -+ saa716x->pdev->device, -+ rom_header->devices); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Compressed=%d\n\n", -+ saa716x->pdev->device, -+ rom_header->compression); -+ -+ return 0; -+} -+ -+int saa716x_dump_eeprom(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_romhdr rom_header; -+ u8 buf[DUMP_BYTES]; -+ int i, err = 0; -+ u32 offset = 0; -+ -+ err = eeprom_read_bytes(saa716x, DUMP_OFFST, DUMP_BYTES, buf); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "EEPROM Read error"); -+ return err; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, " Card: %s\n", -+ saa716x->config->model_name); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " ---------------- SAA%02x ROM @ Offset 0x%02x ----------------", -+ saa716x->pdev->device, -+ DUMP_OFFST); -+ -+ for (i = 0; i < DUMP_BYTES; i++) { -+ if ((i % 16) == 0) { -+ dprintk(SAA716x_NOTICE, 0, "\n "); -+ dprintk(SAA716x_NOTICE, 0, "%04x: ", i); -+ } -+ -+ if ((i % 8) == 0) -+ dprintk(SAA716x_NOTICE, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_NOTICE, 0, " "); -+ dprintk(SAA716x_NOTICE, 0, "%02x ", buf[i]); -+ } -+ dprintk(SAA716x_NOTICE, 0, "\n"); -+ dprintk(SAA716x_NOTICE, 0, -+ " ---------------- SAA%02x ROM Dump end ---------------------\n\n", -+ saa716x->pdev->device); -+ -+ err = saa716x_get_offset(saa716x, buf, &offset); -+ if (err != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Descriptor not found <%d>", err); -+ return err; -+ } -+ offset += 5; -+ saa716x->id_offst = offset; -+ /* Get header */ -+ err = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); -+ if (err != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", err); -+ return -1; -+ } -+ saa716x->id_len = rom_header.data_size; -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_dump_eeprom); -+ -+static void saa716x_descriptor_dbg(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset, -+ u8 size, -+ u8 ext_size) -+{ -+ int i; -+ -+ dprintk(SAA716x_INFO, 0, " "); -+ for (i = 0; i < 49; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ -+ for (i = 0; i < size + ext_size; i++) { -+ if ((i % 16) == 0) -+ dprintk(SAA716x_INFO, 0, "\n "); -+ if ((i % 8) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ -+ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); -+ } -+ -+ dprintk(SAA716x_INFO, 0, "\n "); -+ for (i = 0; i < 49; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ dprintk(SAA716x_INFO, 0, "\n"); -+ -+} -+ -+static int saa716x_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext Data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_gpio_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_gpio_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_gpio_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_gpio_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_gpio_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Pins=%d\n", -+ saa716x->pdev->device, -+ header.pins); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ -+ return 0; -+} -+ -+static int saa716x_video_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_video_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_video_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_video_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_video_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 0=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port0); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 1=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port1); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 2=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port2); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI PORT ID=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_port_id); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Video PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Encoder PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.encoder_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Video Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Encoder Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.encoder_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_audio_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_audio_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_audio_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_audio_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_audio_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_event_source_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_evsrc_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_evsrc_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_evsrc_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_evsrc_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_crossbar_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_xbar_hdr header; -+ struct saa716x_xbar_pair_info pair_info; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_xbar_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_xbar_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_xbar_hdr)); -+ -+ return -1; -+ } -+ -+ memcpy(&pair_info, &buf[*offset], sizeof (struct saa716x_xbar_pair_info)); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Pairs=%d\n", -+ saa716x->pdev->device, -+ header.pair_inputs); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data + (sizeof (struct saa716x_xbar_pair_info) * header.pair_inputs); -+ return 0; -+} -+ -+static int saa716x_tuner_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_tuner_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_tuner_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_tuner_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_tuner_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_pll_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_pll_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_pll_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_pll_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_pll_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_channel_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_channel_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_channel_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_channel_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_channel_decoder_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_encoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_encoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_encoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_encoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_encoder_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_ir_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_ir_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_ir_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_ir_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_ir_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_eeprom_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_eeprom_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_eeprom_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_eeprom_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_eeprom_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_filter_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_filter_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_filter_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_filter_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof(struct saa716x_filter_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_streamdev_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_streamdev_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_streamdev_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_streamdev_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof(struct saa716x_streamdev_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_unknown_device_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ u8 size; -+ u8 ext_size = 0; -+ -+ size = buf[*offset]; -+ if (size > 1) -+ ext_size = buf[*offset + size -1]; -+ -+ saa716x_descriptor_dbg(saa716x, buf, offset, size, ext_size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ ext_size); -+ -+ *offset += size + ext_size; -+ return 0; -+} -+ -+ -+static void saa716x_device_dbg(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset, -+ u8 size, -+ u8 ext_size, -+ u8 addr_size) -+{ -+ int i; -+ -+ dprintk(SAA716x_INFO, 0, " "); -+ for (i = 0; i < 53; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ -+ for (i = 0; i < size + ext_size + addr_size; i++) { -+ if ((i % 16) == 0) -+ dprintk(SAA716x_INFO, 0, "\n "); -+ if ((i % 8) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ -+ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); -+ } -+ -+ dprintk(SAA716x_INFO, 0, "\n "); -+ for (i = 0; i < 53; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ dprintk(SAA716x_INFO, 0, "\n"); -+ -+} -+ -+ -+static int saa716x_device_info(struct saa716x_dev *saa716x, -+ struct saa716x_devinfo *device, -+ u8 *buf, -+ u32 *offset) -+{ -+ u8 address = 0; -+ -+ memcpy(device, &buf[*offset], sizeof(struct saa716x_devinfo)); -+ if (device->struct_size != sizeof(struct saa716x_devinfo)) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Device size mismatch! Read=%d bytes, expected=%d bytes", -+ device->struct_size, -+ (int)sizeof(struct saa716x_devinfo)); -+ -+ return -1; -+ } -+ -+ saa716x_device_dbg(saa716x, -+ buf, -+ offset, -+ device->struct_size, -+ device->extd_data_size, -+ device->addr_size); -+ -+ *offset += device->struct_size; -+ -+ if (device->addr_size) { -+ address = buf[*offset]; -+ address >>= 1; -+ *offset += device->addr_size; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device @ 0x%02x\n", -+ saa716x->pdev->device, -+ address); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ device->struct_size); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->device_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Master ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->master_devid); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Bus ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->master_busid); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device type=0x%02x\n", -+ saa716x->pdev->device, -+ device->device_type); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Implementation ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->implem_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Path ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->path_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: GPIO ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->gpio_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Address=%d bytes\n", -+ saa716x->pdev->device, -+ device->addr_size); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Extended data=%d bytes\n\n", -+ saa716x->pdev->device, -+ device->extd_data_size); -+ -+ if (device->extd_data_size) { -+ u32 mask; -+ -+ mask = 0x00000001; -+ while (mask) { -+ if (device->device_type & mask) { -+ switch (mask) { -+ case DECODER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case GPIO_SOURCE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found GPIO device\n", -+ saa716x->pdev->device); -+ -+ saa716x_gpio_info(saa716x, buf, offset); -+ break; -+ -+ case VIDEO_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Video Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_video_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case AUDIO_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Audio Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_audio_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case EVENT_SOURCE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Event source\n", -+ saa716x->pdev->device); -+ -+ saa716x_event_source_info(saa716x, buf, offset); -+ break; -+ -+ case CROSSBAR: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Crossbar device\n", -+ saa716x->pdev->device); -+ -+ saa716x_crossbar_info(saa716x, buf, offset); -+ break; -+ -+ case TUNER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Tuner device\n", -+ saa716x->pdev->device); -+ -+ saa716x_tuner_info(saa716x, buf, offset); -+ break; -+ -+ case PLL_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found PLL device\n", -+ saa716x->pdev->device); -+ -+ saa716x_pll_info(saa716x, buf, offset); -+ break; -+ -+ case CHANNEL_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Channel Demodulator device\n", -+ saa716x->pdev->device); -+ -+ saa716x_channel_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case RDS_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found RDS Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ case ENCODER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Encoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_encoder_info(saa716x, buf, offset); -+ break; -+ -+ case IR_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found IR device\n", -+ saa716x->pdev->device); -+ -+ saa716x_ir_info(saa716x, buf, offset); -+ break; -+ -+ case EEPROM_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found EEPROM device\n", -+ saa716x->pdev->device); -+ -+ saa716x_eeprom_info(saa716x, buf, offset); -+ break; -+ -+ case NOISE_FILTER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Noise filter device\n", -+ saa716x->pdev->device); -+ -+ saa716x_filter_info(saa716x, buf, offset); -+ break; -+ -+ case LNx_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found LNx device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ case STREAM_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found streaming device\n", -+ saa716x->pdev->device); -+ -+ saa716x_streamdev_info(saa716x, buf, offset); -+ break; -+ -+ case CONFIGSPACE_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Configspace device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ default: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found unknown device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ } -+ } -+ mask <<= 1; -+ } -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, "\n"); -+ -+ return 0; -+} -+ -+int saa716x_eeprom_data(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_romhdr rom_header; -+ struct saa716x_devinfo *device; -+ -+ u8 buf[1024]; -+ int i, ret = 0; -+ u32 offset = 0; -+ -+ /* dump */ -+ ret = saa716x_read_rombytes(saa716x, saa716x->id_offst, saa716x->id_len + 8, buf); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "EEPROM Read error <%d>", ret); -+ goto err0; -+ } -+ -+ /* Get header */ -+ ret = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", ret); -+ goto err0; -+ } -+ -+ /* allocate for device info */ -+ device = kzalloc(sizeof (struct saa716x_devinfo) * rom_header.devices, GFP_KERNEL); -+ if (device == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: out of memory"); -+ goto err0; -+ } -+ -+ for (i = 0; i < rom_header.devices; i++) { -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: ===== Device %d =====\n", -+ saa716x->pdev->device, -+ i); -+ -+ ret = saa716x_device_info(saa716x, &device[i], buf, &offset); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Device info read failed <%d>", ret); -+ goto err1; -+ } -+ } -+ -+ kfree(device); -+ -+ return 0; -+ -+err1: -+ kfree(device); -+ -+err0: -+ return ret; -+} -+EXPORT_SYMBOL_GPL(saa716x_eeprom_data); -diff --git a/drivers/media/common/saa716x/saa716x_rom.h b/drivers/media/common/saa716x/saa716x_rom.h -new file mode 100644 -index 0000000..6bb317f ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_rom.h -@@ -0,0 +1,253 @@ -+#ifndef __SAA716x_ROM_H -+#define __SAA716x_ROM_H -+ -+ -+#define MSB(__x) ((__x >> 8) & 0xff) -+#define LSB(__x) (__x & 0xff) -+ -+#define DUMP_BYTES 0xf0 -+#define DUMP_OFFST 0x000 -+ -+struct saa716x_dev; -+ -+struct saa716x_romhdr { -+ u16 header_size; -+ u8 compression; -+ u8 version; -+ u16 data_size; -+ u8 devices; -+ u8 checksum; -+} __attribute__((packed)); -+ -+struct saa716x_devinfo { -+ u8 struct_size; -+ u8 device_id; -+ u8 master_devid; -+ u8 master_busid; -+ u32 device_type; -+ u16 implem_id; -+ u8 path_id; -+ u8 gpio_id; -+ u16 addr_size; -+ u16 extd_data_size; -+} __attribute__((packed)); -+ -+enum saa716x_device_types { -+ DECODER_DEVICE = 0x00000001, -+ GPIO_SOURCE = 0x00000002, -+ VIDEO_DECODER = 0x00000004, -+ AUDIO_DECODER = 0x00000008, -+ EVENT_SOURCE = 0x00000010, -+ CROSSBAR = 0x00000020, -+ TUNER_DEVICE = 0x00000040, -+ PLL_DEVICE = 0x00000080, -+ CHANNEL_DECODER = 0x00000100, -+ RDS_DECODER = 0x00000200, -+ ENCODER_DEVICE = 0x00000400, -+ IR_DEVICE = 0x00000800, -+ EEPROM_DEVICE = 0x00001000, -+ NOISE_FILTER = 0x00002000, -+ LNx_DEVICE = 0x00004000, -+ STREAM_DEVICE = 0x00010000, -+ CONFIGSPACE_DEVICE = 0x80000000 -+}; -+ -+struct saa716x_decoder_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_decoder_info { -+ struct saa716x_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_gpio_hdr { -+ u8 size; -+ u8 pins; -+ u8 rsvd; -+ u8 ext_data; -+}; -+ -+struct saa716x_gpio_info { -+ struct saa716x_gpio_hdr gpio_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_video_decoder_hdr { -+ u8 size; -+ u8 video_port0; -+ u8 video_port1; -+ u8 video_port2; -+ u8 vbi_port_id; -+ u8 video_port_type; -+ u8 vbi_port_type; -+ u8 encoder_port_type; -+ u8 video_output; -+ u8 vbi_output; -+ u8 encoder_output; -+ u8 ext_data; -+}; -+ -+struct saa716x_video_decoder_info { -+ struct saa716x_video_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_audio_decoder_hdr { -+ u8 size; -+ u8 port; -+ u8 output; -+ u8 ext_data; -+}; -+ -+struct saa716x_audio_decoder_info { -+ struct saa716x_audio_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_evsrc_hdr { -+ u8 size; -+ u8 master_devid; -+ u16 condition_id; -+ u8 rsvd; -+ u8 ext_data; -+}; -+ -+struct saa716x_evsrc_info { -+ struct saa716x_evsrc_hdr evsrc_hdr; -+ u8 *ext_data; -+}; -+ -+enum saa716x_input_pair_type { -+ TUNER_SIF = 0x00, -+ TUNER_LINE = 0x01, -+ TUNER_SPDIF = 0x02, -+ TUNER_NONE = 0x03, -+ CVBS_LINE = 0x04, -+ CVBS_SPDIF = 0x05, -+ CVBS_NONE = 0x06, -+ YC_LINE = 0x07, -+ YC_SPDIF = 0x08, -+ YC_NONE = 0x09, -+ YPbPr_LINE = 0x0a, -+ YPbPr_SPDIF = 0x0b, -+ YPbPr_NONE = 0x0c, -+ NO_LINE = 0x0d, -+ NO_SPDIF = 0x0e, -+ RGB_LINE = 0x0f, -+ RGB_SPDIF = 0x10, -+ RGB_NONE = 0x11 -+}; -+ -+struct saa716x_xbar_pair_info { -+ u8 pair_input_type; -+ u8 video_input_id; -+ u8 audio_input_id; -+}; -+ -+struct saa716x_xbar_hdr { -+ u8 size; -+ u8 pair_inputs; -+ u8 pair_route_default; -+ u8 ext_data; -+}; -+ -+struct saa716x_xbar_info { -+ struct saa716x_xbar_hdr xbar_hdr; -+ struct saa716x_xbar_pair_info *pair_info; -+ u8 *ext_data; -+}; -+ -+struct saa716x_tuner_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_tuner_info { -+ struct saa716x_tuner_hdr tuner_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_pll_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_pll_info { -+ struct saa716x_pll_hdr pll_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_channel_decoder_hdr { -+ u8 size; -+ u8 port; -+ u8 ext_data; -+}; -+ -+struct saa716x_channel_decoder_info { -+ struct saa716x_channel_decoder_hdr channel_dec_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_encoder_hdr { -+ u8 size; -+ u8 stream_port0; -+ u8 stream_port1; -+ u8 ext_data; -+}; -+ -+struct saa716x_encoder_info { -+ struct saa716x_encoder_hdr encoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_ir_hdr { -+ u8 size; -+ u8 ir_caps; -+ u8 ext_data; -+}; -+ -+struct saa716x_ir_info { -+ struct saa716x_ir_hdr ir_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_eeprom_hdr { -+ u8 size; -+ u8 rel_device; -+ u8 ext_data; -+}; -+ -+struct saa716x_eeprom_info { -+ struct saa716x_eeprom_hdr eeprom_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_filter_hdr { -+ u8 size; -+ u8 video_decoder; -+ u8 audio_decoder; -+ u8 event_source; -+ u8 ext_data; -+}; -+ -+struct saa716x_filter_info { -+ struct saa716x_filter_hdr filter_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_streamdev_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_streamdev_info { -+ struct saa716x_streamdev_hdr streamdev_hdr; -+ u8 *ext_data; -+}; -+ -+extern int saa716x_dump_eeprom(struct saa716x_dev *saa716x); -+extern int saa716x_eeprom_data(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_ROM_H */ -diff --git a/drivers/media/common/saa716x/saa716x_spi.c b/drivers/media/common/saa716x/saa716x_spi.c -new file mode 100644 -index 0000000..8859454 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_spi.c -@@ -0,0 +1,313 @@ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_spi_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#if 0 // not needed atm -+int saa716x_spi_irqevent(struct saa716x_dev *saa716x) -+{ -+ u32 stat, mask; -+ -+ BUG_ON(saa716x == NULL); -+ -+ stat = SAA716x_EPRD(SPI, SPI_STATUS); -+ mask = SAA716x_EPRD(SPI, SPI_CONTROL_REG) & SPI_SERIAL_INTER_ENABLE; -+ if ((!stat && !mask)) -+ return -1; -+ -+ dprintk(SAA716x_DEBUG, 0, "SPI event: Stat=<%02x>", stat); -+ -+ if (stat & SPI_TRANSFER_FLAG) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_WRITE_COLLISSION) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_READ_OVERRUN) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_MODE_FAULT) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_SLAVE_ABORT) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ return 0; -+} -+#endif -+ -+void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length) -+{ -+ int i; -+ u32 value; -+ int rounds; -+ -+ for (i = 0; i < length; i++) { -+ SAA716x_EPWR(SPI, SPI_DATA, data[i]); -+ rounds = 0; -+ value = SAA716x_EPRD(SPI, SPI_STATUS); -+ -+ while ((value & SPI_TRANSFER_FLAG) == 0 && rounds < 5000) { -+ value = SAA716x_EPRD(SPI, SPI_STATUS); -+ rounds++; -+ } -+ } -+} -+EXPORT_SYMBOL_GPL(saa716x_spi_write); -+ -+#if 0 // not needed atm -+static int saa716x_spi_status(struct saa716x_dev *saa716x, u32 *status) -+{ -+ u32 stat; -+ -+ stat = SAA716x_EPRD(SPI, SPI_STATUS); -+ -+ if (stat & SPI_TRANSFER_FLAG) -+ dprintk(SAA716x_DEBUG, 1, "Transfer complete <%02x>", stat); -+ -+ if (stat & SPI_WRITE_COLLISSION) -+ dprintk(SAA716x_DEBUG, 1, "Write collission <%02x>", stat); -+ -+ if (stat & SPI_READ_OVERRUN) -+ dprintk(SAA716x_DEBUG, 1, "Read Overrun <%02x>", stat); -+ -+ if (stat & SPI_MODE_FAULT) -+ dprintk(SAA716x_DEBUG, 1, "MODE fault <%02x>", stat); -+ -+ if (stat & SPI_SLAVE_ABORT) -+ dprintk(SAA716x_DEBUG, 1, "SLAVE abort <%02x>", stat); -+ -+ *status = stat; -+ -+ return 0; -+} -+ -+#define SPI_CYCLE_TIMEOUT 100 -+ -+static int saa716x_spi_xfer(struct saa716x_dev *saa716x, u32 *data) -+{ -+ u32 i, status = 0; -+ -+ /* write data and wait for completion */ -+ SAA716x_EPWR(SPI, SPI_DATA, data[i]); -+ for (i = 0; i < SPI_CYCLE_TIMEOUT; i++) { -+ msleep(10); -+ saa716x_spi_status(saa716x, &status); -+#if 0 -+ if (status & SPI_TRANSFER_FLAG) { -+ data = SAA716x_EPRD(SPI, SPI_DATA); -+ return 0; -+ } -+#endif -+ if (status & (SPI_WRITE_COLLISSION | -+ SPI_READ_OVERRUN | -+ SPI_MODE_FAULT | -+ SPI_SLAVE_ABORT)) -+ -+ return -EIO; -+ } -+ -+ return -EIO; -+} -+ -+#if 0 -+static int saa716x_spi_wr(struct saa716x_dev *saa716x, const u8 *data, int length) -+{ -+ struct saa716x_spi_config *config = saa716x->spi_config; -+ u32 gpio_mask; -+ int ret = 0; -+ -+ // protect against multiple access -+ spin_lock(&saa716x->gpio_lock); -+ -+ // configure the module -+ saa716x_spi_config(saa716x); -+ -+ // check input -+ -+ // change polarity of GPIO if active high -+ if (config->active_hi) { -+ select = 1; -+ release = 0; -+ } -+ -+ // configure GPIO, first set output register to low selected level -+ saa716x_gpio_write(saa716x, gpio, select); -+ -+ // set mode register to register controlled (0) -+ gpio_mask = (1 << gpio); -+ saa716x_set_gpio_mode(saa716x, gpio_mask, 0); -+ -+ // configure bit as output (0) -+ saa716x_gpio_ctl(saa716x, gpio_mask, 0); -+ -+ // wait at least 500ns before sending a byte -+ msleep(1); -+ -+ // send command -+ for (i = 0; i < dwCommandSize; i++) { -+ ucData = 0; -+// dwStatus = TransferData(pucCommand[i], &ucData); -+ ret = saa716x_spi_xfer(saa716x); -+ //tmDBGPRINTEx(4,("Info: Command 0x%x ", pucCommand[i] )); -+ -+ /* If command length > 1, disable CS at the end of each command. -+ * But after the last command byte CS must be left active! -+ */ -+ if ((dwCommandSize > 1) && (i < dwCommandSize - 1)) { -+ -+ saa716x_gpio_write(saa716x, gpio, release); -+ msleep(1); /* 500 nS minimum */ -+ saa716x_gpio_write(saa716x, gpio, select); -+ } -+ -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Command transfer failed"); -+ msleep(1); /* 500 nS minimum */ -+ saa716x_gpio_write(saa716x, gpio, release); /* release GPIO */ -+ spin_unlock(&saa716x->spi_lock); -+ return ret; -+ } -+ -+ if (config->LSB_first) -+ dwTransferByte++; -+ else -+ dwTransferByte--; -+ } -+ -+// assume that the byte order is the same as the bit order -+ -+// send read address -+ -+// send data -+ -+// wait at least 500ns before releasing slave -+ -+// release GPIO pin -+ -+ // release spinlock -+ spin_unlock(&saa716x->gpio_lock); -+} -+#endif -+ -+#define MODEBITS (SPI_CPOL | SPI_CPHA) -+ -+static int saa716x_spi_setup(struct spi_device *spi) -+{ -+ struct spi_master *master = spi->master; -+ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); -+ struct saa716x_dev *saa716x = saa716x_spi->saa716x; -+ struct saa716x_spi_config *config = &saa716x->spi_config; -+ -+ u8 control = 0; -+ -+ if (spi->mode & ~MODEBITS) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Unsupported MODE bits <%x>", -+ spi->mode & ~MODEBITS); -+ -+ return -EINVAL; -+ } -+ -+ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, config->clk_count); -+ -+ control |= SPI_MODE_SELECT; /* SPI Master */ -+ -+ if (config->LSB_first) -+ control |= SPI_LSB_FIRST_ENABLE; -+ -+ if (config->clk_pol) -+ control |= SPI_CLOCK_POLARITY; -+ -+ if (config->clk_pha) -+ control |= SPI_CLOCK_PHASE; -+ -+ SAA716x_EPWR(SPI, SPI_CONTROL_REG, control); -+ -+ return 0; -+} -+ -+static void saa716x_spi_cleanup(struct spi_device *spi) -+{ -+ -+} -+ -+static int saa716x_spi_transfer(struct spi_device *spi, struct spi_message *msg) -+{ -+ struct spi_master *master = spi->master; -+ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); -+ struct saa716x_dev *saa716x = saa716x_spi->saa716x; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+#if 0 -+ if (saa716x_spi->run == QUEUE_STOPPED) { -+ spin_unlock_irqrestore(&saa716x_spi->lock, flags); -+ return -ESHUTDOWN; -+ } -+ -+ msg->actual_length = 0; -+ msg->status = -EINPROGRESS; -+ msg->state = START_STATE; -+ -+ list_add_tail(&msg->queue, &saa716x_spi->queue); -+ -+ if (saa716x_spi->run == QUEUE_RUNNING && !saa716x_spi->busy) -+ queue_work(saa716x_spi->workqueue, &saa716x_spi->pump_messages); -+#endif -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+ -+ return 0; -+} -+ -+int saa716x_spi_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct spi_master *master; -+ struct saa716x_spi_state *saa716x_spi; -+ int ret; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", -+ saa716x->pdev->device); -+ -+ master = spi_alloc_master(&pdev->dev, sizeof (struct saa716x_spi_state)); -+ if (master == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Cannot allocate SPI Master!"); -+ return -ENOMEM; -+ } -+ -+ saa716x_spi = spi_master_get_devdata(master); -+ saa716x_spi->master = master; -+ saa716x_spi->saa716x = saa716x; -+ saa716x->saa716x_spi = saa716x_spi; -+ -+ master->bus_num = pdev->bus->number; -+ master->num_chipselect = 1; /* TODO! use config */ -+ master->cleanup = saa716x_spi_cleanup; -+ master->setup = saa716x_spi_setup; -+ master->transfer = saa716x_spi_transfer; -+ -+ ret = spi_register_master(master); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: registering SPI Master!"); -+ goto err; -+ } -+err: -+ spi_master_put(master); -+ return ret; -+} -+EXPORT_SYMBOL(saa716x_spi_init); -+ -+void saa716x_spi_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_spi_state *saa716x_spi = saa716x->saa716x_spi; -+ -+ spi_unregister_master(saa716x_spi->master); -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x SPI succesfully removed", saa716x->pdev->device); -+} -+EXPORT_SYMBOL(saa716x_spi_exit); -+#endif -+ -diff --git a/drivers/media/common/saa716x/saa716x_spi.h b/drivers/media/common/saa716x/saa716x_spi.h -new file mode 100644 -index 0000000..0060c22 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_spi.h -@@ -0,0 +1,23 @@ -+#ifndef __SAA716x_SPI_H -+#define __SAA716x_SPI_H -+ -+struct saa716x_dev; -+ -+struct saa716x_spi_config { -+ u8 clk_count; -+ u8 clk_pol:1; -+ u8 clk_pha:1; -+ u8 LSB_first:1; -+}; -+ -+struct saa716x_spi_state { -+ struct spi_master *master; -+ struct saa716x_dev *saa716x; -+}; -+ -+extern void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length); -+ -+extern int saa716x_spi_init(struct saa716x_dev *saa716x); -+extern void saa716x_spi_exit(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_SPI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_spi_reg.h b/drivers/media/common/saa716x/saa716x_spi_reg.h -new file mode 100644 -index 0000000..c51abce ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_spi_reg.h -@@ -0,0 +1,27 @@ -+#ifndef __SAA716x_SPI_REG_H -+#define __SAA716x_SPI_REG_H -+ -+/* -------------- SPI Registers -------------- */ -+ -+#define SPI_CONTROL_REG 0x000 -+#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) -+#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) -+#define SPI_MODE_SELECT (0x00000001 << 5) -+#define SPI_CLOCK_POLARITY (0x00000001 << 4) -+#define SPI_CLOCK_PHASE (0x00000001 << 3) -+ -+#define SPI_STATUS 0x004 -+#define SPI_TRANSFER_FLAG (0x00000001 << 7) -+#define SPI_WRITE_COLLISSION (0x00000001 << 6) -+#define SPI_READ_OVERRUN (0x00000001 << 5) -+#define SPI_MODE_FAULT (0x00000001 << 4) -+#define SPI_SLAVE_ABORT (0x00000001 << 3) -+ -+#define SPI_DATA 0x008 -+#define SPI_BIDI_DATA (0x000000ff << 0) -+ -+#define SPI_CLOCK_COUNTER 0x00c -+#define SPI_CLOCK (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_SPI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_vip.c b/drivers/media/common/saa716x/saa716x_vip.c -new file mode 100644 -index 0000000..4cd4c81 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_vip.c -@@ -0,0 +1,23 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_vip_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+void saa716x_vipint_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(VI0, INT_ENABLE, 0); /* disable VI 0 IRQ */ -+ SAA716x_EPWR(VI1, INT_ENABLE, 0); /* disable VI 1 IRQ */ -+ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ -+ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ -+} -+EXPORT_SYMBOL_GPL(saa716x_vipint_disable); -+ -+void saa716x_vip_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(VI0, VIP_POWER_DOWN, VI_PWR_DWN); -+ SAA716x_EPWR(VI1, VIP_POWER_DOWN, VI_PWR_DWN); -+} -+EXPORT_SYMBOL_GPL(saa716x_vip_disable); -diff --git a/drivers/media/common/saa716x/saa716x_vip.h b/drivers/media/common/saa716x/saa716x_vip.h -new file mode 100644 -index 0000000..55c6a1a ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_vip.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_VIP_H -+#define __SAA716x_VIP_H -+ -+struct saa716x_dev; -+ -+extern void saa716x_vipint_disable(struct saa716x_dev *saa716x); -+extern void saa716x_vip_disable(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_VIP_H */ -diff --git a/drivers/media/common/saa716x/saa716x_vip_reg.h b/drivers/media/common/saa716x/saa716x_vip_reg.h -new file mode 100644 -index 0000000..2d773bd ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_vip_reg.h -@@ -0,0 +1,127 @@ -+#ifndef __SAA716x_VIP_REG_H -+#define __SAA716x_VIP_REG_H -+ -+/* -------------- VIP Registers -------------- */ -+ -+#define VI_MODE 0x000 -+#define VID_CFEN (0x00000003 << 30) -+#define VID_OSM (0x00000001 << 29) -+#define VID_FSEQ (0x00000001 << 28) -+#define AUX_CFEN (0x00000003 << 26) -+#define AUX_OSM (0x00000001 << 25) -+#define AUX_FSEQ (0x00000001 << 24) -+#define AUX_ANC_DATA (0x00000003 << 22) -+#define AUX_ANC_RAW (0x00000001 << 21) -+#define RST_ON_ERR (0x00000001 << 17) -+#define SOFT_RESET (0x00000001 << 16) -+#define IFF_CLAMP (0x00000001 << 14) -+#define IFF_MODE (0x00000003 << 12) -+#define DFF_CLAMP (0x00000001 << 10) -+#define DFF_MODE (0x00000003 << 8) -+#define HSP_CLAMP (0x00000001 << 3) -+#define HSP_RGB (0x00000001 << 2) -+#define HSP_MODE (0x00000003 << 0) -+ -+#define RCRB_CTRL 0x004 -+#define RCRB_CFG_ADDR 0x008 -+#define RCRB_CFG_EXT_ADDR 0x00c -+#define RCRB_IO_ADDR 0x010 -+#define RCRB_MEM_LADDR 0x014 -+#define RCRB_MEM_UADDR 0x018 -+#define RCRB_DATA 0x01c -+#define RCRB_MASK 0x020 -+#define RCRB_MSG_HDR 0x040 -+#define RCRB_MSG_PL0 0x044 -+#define RCRB_MSG_PL1 0x048 -+ -+#define ID_MASK0 0x020 -+#define VI_ID_MASK_0 (0x000000ff << 8) -+#define VI_DATA_ID_0 (0x000000ff << 0) -+ -+#define ID_MASK1 0x024 -+#define VI_ID_MASK_1 (0x000000ff << 8) -+#define VI_DATA_ID_1 (0x000000ff << 0) -+ -+#define VIP_LINE_THRESH 0x040 -+#define VI_LCTHR (0x000007ff << 0) -+ -+#define VIN_FORMAT 0x100 -+#define VI_VSRA (0x00000003 << 30) -+#define VI_SYNCHD (0x00000001 << 25) -+#define VI_DUAL_STREAM (0x00000001 << 24) -+#define VI_NHDAUX (0x00000001 << 20) -+#define VI_NPAR (0x00000001 << 19) -+#define VI_VSEL (0x00000003 << 14) -+#define VI_TWOS (0x00000001 << 13) -+#define VI_TPG (0x00000001 << 12) -+#define VI_FREF (0x00000001 << 10) -+#define VI_FTGL (0x00000001 << 9) -+#define VI_SF (0x00000001 << 3) -+#define VI_FZERO (0x00000001 << 2) -+#define VI_REVS (0x00000001 << 1) -+#define VI_REHS (0x00000001 << 0) -+ -+#define TC76543210 0x800 -+#define TCFEDCBA98 0x804 -+#define PHYCFG 0x900 -+#define CONFIG 0xfd4 -+#define INT_ENABLE_CLR 0xfd8 -+#define INT_ENABLE_SET 0xfdc -+ -+ -+#define INT_STATUS 0xfe0 -+#define VI_STAT_FID_AUX (0x00000001 << 31) -+#define VI_STAT_FID_VID (0x00000001 << 30) -+#define VI_STAT_FID_VPI (0x00000001 << 29) -+#define VI_STAT_LINE_COUNT (0x00000fff << 16) -+#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) -+#define VI_STAT_VID_OVRFLW (0x00000001 << 8) -+#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) -+#define VI_STAT_FID_SEQBRK (0x00000001 << 6) -+#define VI_STAT_LINE_THRESH (0x00000001 << 5) -+#define VI_STAT_AUX_WRAP (0x00000001 << 4) -+#define VI_STAT_AUX_START_IN (0x00000001 << 3) -+#define VI_STAT_AUX_END_OUT (0x00000001 << 2) -+#define VI_STAT_VID_START_IN (0x00000001 << 1) -+#define VI_STAT_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) -+#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) -+#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) -+#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) -+#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) -+#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) -+#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) -+#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) -+#define VI_ENABLE_VID_START_IN (0x00000001 << 1) -+#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define VIP_POWER_DOWN 0xff4 -+#define VI_PWR_DWN (0x00000001 << 31) -+ -+#endif /* __SAA716x_VIP_REG_H */ -diff --git a/drivers/media/dvb-frontends/ds3103.h b/drivers/media/dvb-frontends/ds3103.h -new file mode 100644 -index 0000000..e52740c ---- /dev/null -+++ b/drivers/media/dvb-frontends/ds3103.h -@@ -0,0 +1,47 @@ -+/* -+ Montage Technology DS3103 - DVBS/S2 Demodulator driver -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#ifndef DS3103_H -+#define DS3103_H -+ -+#include -+ -+struct ds3103_config { -+ /* the demodulator's i2c address */ -+ u8 demod_address; -+ u8 ci_mode; -+ /* Set device param to start dma */ -+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); -+ /* Hook for Lock LED */ -+ void (*set_lock_led)(struct dvb_frontend *fe, int offon); -+}; -+ -+#if defined(CONFIG_DVB_DS3103) || \ -+ (defined(CONFIG_DVB_DS3103_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, -+ struct i2c_adapter *i2c); -+#else -+static inline -+struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_DS3103 */ -+#endif /* DS3103_H */ -diff --git a/drivers/media/dvb-frontends/ts2022.h b/drivers/media/dvb-frontends/ts2022.h -new file mode 100644 -index 0000000..c894edb ---- /dev/null -+++ b/drivers/media/dvb-frontends/ts2022.h -@@ -0,0 +1,51 @@ -+ /* -+ Driver for Montage TS2022 DVBS/S2 Silicon tuner -+ -+ Copyright (C) 2012 Tomazzo Muzumici -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ -+ */ -+ -+#ifndef __DVB_TS2022_H__ -+#define __DVB_TS2022_H__ -+ -+#include -+#include "dvb_frontend.h" -+ -+/** -+ * Attach a ts2022 tuner to the supplied frontend structure. -+ * -+ * @param fe Frontend to attach to. -+ * @param addr i2c address of the tuner. -+ * @param i2c i2c adapter to use. -+ * @return FE pointer on success, NULL on failure. -+ */ -+#if defined(CONFIG_DVB_TS2022) || (defined(CONFIG_DVB_TS2022_MODULE) \ -+ && defined(MODULE)) -+extern struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, int addr, -+ struct i2c_adapter *i2c); -+#else -+static inline struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, -+ int addr, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_TS2022 */ -+ -+#endif /* __DVB_TS2022_H__ */ -diff --git a/include/uapi/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h -index 880e684..edd728c 100644 ---- a/include/uapi/linux/dvb/osd.h -+++ b/include/uapi/linux/dvb/osd.h -@@ -141,4 +141,20 @@ typedef struct osd_cap_s { - #define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t) - #define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t) - -+typedef struct osd_raw_cmd_s { -+ const void __user *cmd_data; -+ int cmd_len; -+ void __user *result_data; -+ int result_len; -+} osd_raw_cmd_t; -+ -+typedef struct osd_raw_data_s { -+ const void __user *data_buffer; -+ int data_length; -+ int data_handle; -+} osd_raw_data_t; -+ -+#define OSD_RAW_CMD _IOWR('o', 162, osd_raw_cmd_t) -+#define OSD_RAW_DATA _IOWR('o', 163, osd_raw_data_t) -+ - #endif diff --git a/packages/linux/patches/default/linux-999-partly-revert-media-rc-core.patch b/packages/linux/patches/default/linux-999-partly-revert-media-rc-core.patch deleted file mode 100644 index f56c27fe14..0000000000 --- a/packages/linux/patches/default/linux-999-partly-revert-media-rc-core.patch +++ /dev/null @@ -1,42 +0,0 @@ -From patchwork Sat Jul 30 13:19:27 2016 -From: Ole Ernst -Date: Sat, 30 Jul 2016 15:19:27 +0200 -Subject: Partly revert "[media] rc-core: allow calling rc_open with device not initialized" - -This partly reverts commit 078600f514a12fd763ac84c86af68ef5b5267563. - -Due to the relocation of input_register_device() call, holding down a -button on an IR remote no longer resulted in repeated key down events. - -Signed-off-by: Ole Ernst ---- - drivers/media/rc/rc-main.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index 8e7f292..26fd63b 100644 ---- a/drivers/media/rc/rc-main.c -+++ b/drivers/media/rc/rc-main.c -@@ -1460,6 +1460,10 @@ int rc_register_device(struct rc_dev *dev) - dev->input_dev->phys = dev->input_phys; - dev->input_dev->name = dev->input_name; - -+ rc = input_register_device(dev->input_dev); -+ if (rc) -+ goto out_table; -+ - /* - * Default delay of 250ms is too short for some protocols, especially - * since the timeout is currently set to 250ms. Increase it to 500ms, -@@ -1475,11 +1479,6 @@ int rc_register_device(struct rc_dev *dev) - */ - dev->input_dev->rep[REP_PERIOD] = 125; - -- /* rc_open will be called here */ -- rc = input_register_device(dev->input_dev); -- if (rc) -- goto out_table; -- - path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); - dev_info(&dev->dev, "%s as %s\n", - dev->input_name ?: "Unspecified device", path ?: "N/A"); diff --git a/projects/Generic/linux/linux.x86_64.conf b/projects/Generic/linux/linux.x86_64.conf index cab54c945d..2f472b7a0f 100644 --- a/projects/Generic/linux/linux.x86_64.conf +++ b/projects/Generic/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.8.11 Kernel Configuration +# Linux/x86_64 4.9.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -45,6 +45,7 @@ CONFIG_PGTABLE_LEVELS=4 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y # # General setup @@ -303,6 +304,8 @@ CONFIG_HAVE_STACK_VALIDATION=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_COMPAT_OLD_SIGACTION=y # CONFIG_CPU_NO_EFFICIENT_FFS is not set +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y # # GCOV-based kernel profiling @@ -355,6 +358,7 @@ CONFIG_EFI_PARTITION=y # CONFIG_SYSV68_PARTITION is not set # CONFIG_CMDLINE_PARTITION is not set CONFIG_BLOCK_COMPAT=y +CONFIG_BLK_MQ_PCI=y # # IO Schedulers @@ -636,7 +640,8 @@ CONFIG_HAVE_ACPI_APEI_NMI=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_ATTR_SET=y CONFIG_CPU_FREQ_GOV_COMMON=y -# CONFIG_CPU_FREQ_STAT is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set @@ -700,6 +705,7 @@ CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_PERFORMANCE is not set CONFIG_PCIE_PME=y # CONFIG_PCIE_DPC is not set +# CONFIG_PCIE_PTM is not set CONFIG_PCI_BUS_ADDR_T_64BIT=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_IRQ_DOMAIN=y @@ -717,6 +723,7 @@ CONFIG_PCI_LABEL=y # PCI host controller drivers # # CONFIG_PCIE_DW_PLAT is not set +# CONFIG_VMD is not set # CONFIG_ISA_BUS is not set CONFIG_ISA_DMA_API=y CONFIG_AMD_NB=y @@ -744,7 +751,6 @@ CONFIG_SYSVIPC_COMPAT=y CONFIG_KEYS_COMPAT=y CONFIG_X86_DEV_DMA_OPS=y CONFIG_PMC_ATOM=y -# CONFIG_VMD is not set CONFIG_NET=y CONFIG_COMPAT_NETLINK_MESSAGES=y @@ -1087,6 +1093,7 @@ CONFIG_BT_HCIBTUSB_RTL=y CONFIG_BT_ATH3K=m # CONFIG_AF_RXRPC is not set # CONFIG_AF_KCM is not set +# CONFIG_STREAM_PARSER is not set CONFIG_WIRELESS=y CONFIG_WIRELESS_EXT=y CONFIG_WEXT_CORE=y @@ -1154,6 +1161,7 @@ CONFIG_WANT_DEV_COREDUMP=y # CONFIG_ALLOW_DEV_COREDUMP is not set # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set CONFIG_GENERIC_CPU_AUTOPROBE=y @@ -1227,7 +1235,6 @@ CONFIG_BLK_DEV_NVME=y # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_BMP085_I2C is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_SRAM is not set # CONFIG_C2PORT is not set @@ -1362,6 +1369,7 @@ CONFIG_SCSI_MVSAS=y CONFIG_MEGARAID_SAS=y # CONFIG_SCSI_MPT3SAS is not set # CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_SMARTPQI is not set # CONFIG_SCSI_UFSHCD is not set # CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_BUSLOGIC is not set @@ -1505,7 +1513,6 @@ CONFIG_NET_CORE=y # CONFIG_NET_TEAM is not set CONFIG_MACVLAN=m # CONFIG_MACVTAP is not set -# CONFIG_IPVLAN is not set # CONFIG_VXLAN is not set # CONFIG_MACSEC is not set CONFIG_NETCONSOLE=y @@ -1534,6 +1541,8 @@ CONFIG_VORTEX=y # CONFIG_NET_VENDOR_AGERE is not set # CONFIG_NET_VENDOR_ALTEON is not set # CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMAZON=y +# CONFIG_ENA_ETHERNET is not set CONFIG_NET_VENDOR_AMD=y # CONFIG_AMD8111_ETH is not set CONFIG_PCNET32=y @@ -1562,6 +1571,7 @@ CONFIG_NET_VENDOR_CAVIUM=y # CONFIG_THUNDER_NIC_PF is not set # CONFIG_THUNDER_NIC_VF is not set # CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_RGX is not set # CONFIG_LIQUIDIO is not set # CONFIG_NET_VENDOR_CHELSIO is not set # CONFIG_NET_VENDOR_CISCO is not set @@ -1659,38 +1669,44 @@ CONFIG_VIA_VELOCITY=y CONFIG_PHYLIB=y # -# MII PHY device drivers +# MDIO bus device drivers # -# CONFIG_AQUANTIA_PHY is not set -CONFIG_AT803X_PHY=y -CONFIG_AMD_PHY=y -CONFIG_MARVELL_PHY=y -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_TERANETICS_PHY is not set -# CONFIG_SMSC_PHY is not set -CONFIG_BCM_NET_PHYLIB=y -CONFIG_BROADCOM_PHY=y -# CONFIG_BCM7XXX_PHY is not set -# CONFIG_BCM87XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -CONFIG_REALTEK_PHY=y -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_DP83848_PHY is not set -# CONFIG_DP83867_PHY is not set -# CONFIG_MICROCHIP_PHY is not set -# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BCM_UNIMAC is not set # CONFIG_MDIO_BITBANG is not set # CONFIG_MDIO_OCTEON is not set # CONFIG_MDIO_THUNDER is not set -# CONFIG_MDIO_BCM_UNIMAC is not set + +# +# MII PHY device drivers +# +CONFIG_AMD_PHY=y +# CONFIG_AQUANTIA_PHY is not set +CONFIG_AT803X_PHY=y +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BROADCOM_PHY=y +# CONFIG_CICADA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_ICPLUS_PHY is not set # CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +CONFIG_MARVELL_PHY=y +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +CONFIG_REALTEK_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set CONFIG_PPP=m CONFIG_PPP_BSDCOMP=m CONFIG_PPP_DEFLATE=m @@ -2034,11 +2050,11 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set # CONFIG_TOUCHSCREEN_EETI is not set # CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set -# CONFIG_TOUCHSCREEN_FT6236 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GOODIX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set CONFIG_TOUCHSCREEN_ELAN=y # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set @@ -2099,6 +2115,7 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_BEEPER is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_GPIO_DECODER is not set # CONFIG_INPUT_ATLAS_BTNS is not set CONFIG_INPUT_ATI_REMOTE2=m # CONFIG_INPUT_KEYSPAN_REMOTE is not set @@ -2169,6 +2186,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # CONFIG_SERIAL_8250_DW is not set # CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_LPSS is not set # CONFIG_SERIAL_8250_MID is not set # CONFIG_SERIAL_8250_MOXA is not set @@ -2335,7 +2353,6 @@ CONFIG_PINCTRL_CHERRYVIEW=y # CONFIG_PINCTRL_BROXTON is not set # CONFIG_PINCTRL_SUNRISEPOINT is not set CONFIG_GPIOLIB=y -CONFIG_GPIO_DEVRES=y CONFIG_GPIO_ACPI=y CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_DEBUG_GPIO is not set @@ -2349,6 +2366,7 @@ CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_ICH is not set # CONFIG_GPIO_LYNXPOINT is not set +# CONFIG_GPIO_MOCKUP is not set # CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_ZX is not set @@ -2370,6 +2388,7 @@ CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set # CONFIG_GPIO_TPIC2810 is not set +# CONFIG_GPIO_TS4900 is not set # # MFD GPIO expanders @@ -2391,6 +2410,8 @@ CONFIG_GPIOLIB_IRQCHIP=y # USB GPIO expanders # # CONFIG_W1 is not set +# CONFIG_POWER_AVS is not set +# CONFIG_POWER_RESET is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set @@ -2413,8 +2434,6 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set # CONFIG_CHARGER_RT9455 is not set -# CONFIG_POWER_RESET is not set -# CONFIG_POWER_AVS is not set CONFIG_HWMON=y CONFIG_HWMON_VID=y # CONFIG_HWMON_DEBUG_CHIP is not set @@ -2623,6 +2642,7 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_DA9063 is not set # CONFIG_MFD_DA9150 is not set # CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_EXYNOS_LPASS is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set @@ -2672,6 +2692,7 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_MFD_TPS65086 is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set # CONFIG_MFD_TPS65218 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set @@ -2802,6 +2823,7 @@ CONFIG_VIDEO_TM6000_DVB=m # CONFIG_DVB_USB=m # CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB3000MC=m # CONFIG_DVB_USB_A800 is not set CONFIG_DVB_USB_DIBUSB_MB=m CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y @@ -2827,6 +2849,18 @@ CONFIG_DVB_USB_DTV5100=m # CONFIG_DVB_USB_FRIIO is not set CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_TBSQBOX=m +CONFIG_DVB_USB_TBSQBOX2=m +CONFIG_DVB_USB_TBSQBOX22=m +CONFIG_DVB_USB_TBS5922SE=m +CONFIG_DVB_USB_TBSQBOXS2=m +CONFIG_DVB_USB_TBSQBOX2CI=m +CONFIG_DVB_USB_TBS5925=m +CONFIG_DVB_USB_TBS5880=m +CONFIG_DVB_USB_TBS5220=m +CONFIG_DVB_USB_TBS5881=m +CONFIG_DVB_USB_TBS5520=m +CONFIG_DVB_USB_TBS5927=m CONFIG_DVB_USB_V2=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m @@ -2861,6 +2895,7 @@ CONFIG_MEDIA_PCI_SUPPORT=y # Media capture support # # CONFIG_VIDEO_SOLO6X10 is not set +# CONFIG_VIDEO_TW5864 is not set # CONFIG_VIDEO_TW68 is not set # CONFIG_VIDEO_TW686X is not set # CONFIG_VIDEO_ZORAN is not set @@ -2894,6 +2929,7 @@ CONFIG_VIDEO_SAA7134=m CONFIG_VIDEO_SAA7134_RC=y CONFIG_VIDEO_SAA7134_DVB=m CONFIG_VIDEO_SAA7164=m +# CONFIG_SAA716X_SUPPORT is not set # # Media digital TV PCI Adapters @@ -2917,8 +2953,8 @@ CONFIG_DVB_MANTIS=m # CONFIG_DVB_HOPPER is not set CONFIG_DVB_NGENE=m CONFIG_DVB_DDBRIDGE=m -# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set CONFIG_DVB_SMIPCIE=m +CONFIG_DVB_TBSECP3=m # CONFIG_V4L_PLATFORM_DRIVERS is not set # CONFIG_V4L_MEM2MEM_DRIVERS is not set # CONFIG_V4L_TEST_DRIVERS is not set @@ -2950,7 +2986,7 @@ CONFIG_SMS_SIANO_RC=y # CONFIG_SMS_SIANO_DEBUGFS is not set # -# Media ancillary drivers (tuners, sensors, i2c, frontends) +# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_MEDIA_ATTACH=y @@ -3040,6 +3076,9 @@ CONFIG_MEDIA_TUNER_SI2157=m CONFIG_MEDIA_TUNER_IT913X=m CONFIG_MEDIA_TUNER_R820T=m CONFIG_MEDIA_TUNER_QM1D1C0042=m +CONFIG_MEDIA_TUNER_AV201X=m +CONFIG_MEDIA_TUNER_STV6120=m +CONFIG_MEDIA_TUNER_R848=m # # Multistandard (satellite) frontends @@ -3047,10 +3086,7 @@ CONFIG_MEDIA_TUNER_QM1D1C0042=m CONFIG_DVB_STB0899=m CONFIG_DVB_STB6100=m CONFIG_DVB_STV090x=m -CONFIG_DVB_STV0910=m CONFIG_DVB_STV6110x=m -CONFIG_DVB_STV6111=m -CONFIG_DVB_MXL5XX=m CONFIG_DVB_M88DS3103=m # @@ -3061,8 +3097,6 @@ CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_SI2165=m CONFIG_DVB_MN88472=m CONFIG_DVB_MN88473=m -CONFIG_DVB_STV0367DD=m -CONFIG_DVB_CXD2843=m # # DVB-S (satellite) frontends @@ -3117,6 +3151,7 @@ CONFIG_DVB_RTL2830=m CONFIG_DVB_RTL2832=m CONFIG_DVB_SI2168=m CONFIG_DVB_AS102_FE=m +# CONFIG_DVB_GP8PSK_FE is not set # # DVB-C (cable) frontends @@ -3164,7 +3199,6 @@ CONFIG_DVB_TUNER_DIB0090=m # SEC control devices for DVB-S # CONFIG_DVB_DRX39XYJ=m -CONFIG_DVB_LNBH25=m CONFIG_DVB_LNBP21=m CONFIG_DVB_LNBP22=m CONFIG_DVB_ISL6405=m @@ -3178,10 +3212,13 @@ CONFIG_DVB_TDA665x=m CONFIG_DVB_IX2505V=m CONFIG_DVB_M88RS2000=m CONFIG_DVB_AF9033=m +CONFIG_DVB_TAS2101=m # # Tools to develop new frontends # +CONFIG_DVB_STV0910=m +CONFIG_DVB_AVL6882=m # CONFIG_DVB_DUMMY_FE is not set # @@ -3211,22 +3248,19 @@ CONFIG_DRM_TTM=y # CONFIG_DRM_I2C_CH7006 is not set # CONFIG_DRM_I2C_SIL164 is not set # CONFIG_DRM_I2C_NXP_TDA998X is not set -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=y # CONFIG_DRM_RADEON_USERPTR is not set CONFIG_DRM_AMDGPU=y +CONFIG_DRM_AMDGPU_SI=y CONFIG_DRM_AMDGPU_CIK=y # CONFIG_DRM_AMDGPU_USERPTR is not set # CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set -CONFIG_DRM_AMD_POWERPLAY=y # # ACP (Audio CoProcessor) Configuration # CONFIG_DRM_AMD_ACP=y # CONFIG_DRM_NOUVEAU is not set -# CONFIG_DRM_I810 is not set CONFIG_DRM_I915=y # CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set CONFIG_DRM_I915_USERPTR=y @@ -3237,10 +3271,6 @@ CONFIG_DRM_I915_USERPTR=y # # CONFIG_DRM_I915_WERROR is not set # CONFIG_DRM_I915_DEBUG is not set -# CONFIG_DRM_MGA is not set -# CONFIG_DRM_SIS is not set -# CONFIG_DRM_VIA is not set -# CONFIG_DRM_SAVAGE is not set # CONFIG_DRM_VGEM is not set # CONFIG_DRM_VMWGFX is not set # CONFIG_DRM_GMA500 is not set @@ -3262,6 +3292,7 @@ CONFIG_DRM_BRIDGE=y # Display Interface Bridges # # CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_LEGACY is not set # # Frame buffer Devices @@ -3554,12 +3585,6 @@ CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m # CONFIG_SND_SOC_INTEL_SKL_RT286_MACH is not set # CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH is not set # CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH is not set - -# -# Allwinner SoC Audio support -# -# CONFIG_SND_SUN4I_CODEC is not set -# CONFIG_SND_SUN4I_I2S is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=y @@ -3639,6 +3664,7 @@ CONFIG_SND_SOC_TS3A227E=m # CONFIG_SND_SOC_WM8974 is not set # CONFIG_SND_SOC_WM8978 is not set # CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_NAU8810 is not set # CONFIG_SND_SOC_TPA6130A2 is not set CONFIG_SND_SIMPLE_CARD_UTILS=m CONFIG_SND_SIMPLE_CARD=m @@ -3750,6 +3776,11 @@ CONFIG_USB_HIDDEV=y # I2C HID support # # CONFIG_I2C_HID is not set + +# +# Intel ISH HID support +# +# CONFIG_INTEL_ISH_HID is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y @@ -3765,7 +3796,7 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set CONFIG_USB_MON=m # CONFIG_USB_WUSB_CBAF is not set @@ -3920,6 +3951,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_UCSI is not set @@ -3933,6 +3965,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_ISP1301 is not set # CONFIG_USB_GADGET is not set # CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_ULPI_BUS is not set # CONFIG_UWB is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set @@ -4015,6 +4048,7 @@ CONFIG_LEDS_CLASS_FLASH=y # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_MLXCPLD is not set # # LED Triggers @@ -4070,7 +4104,6 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_ISL12057 is not set # CONFIG_RTC_DRV_X1205 is not set # CONFIG_RTC_DRV_PCF8523 is not set # CONFIG_RTC_DRV_PCF85063 is not set @@ -4203,7 +4236,6 @@ CONFIG_VT6656=m CONFIG_STAGING_MEDIA=y # CONFIG_MEDIA_CEC is not set CONFIG_DVB_CXD2099=m -# CONFIG_VIDEO_TW686X_KH is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set # CONFIG_LIRC_IMON is not set @@ -4227,6 +4259,7 @@ CONFIG_LIRC_XBOX=m # CONFIG_WILC1000_SDIO is not set # CONFIG_MOST is not set # CONFIG_KS7010 is not set +# CONFIG_GREYBUS is not set # CONFIG_X86_PLATFORM_DEVICES is not set # CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y @@ -4242,7 +4275,6 @@ CONFIG_COMMON_CLK=y # CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_PIC32 is not set -# CONFIG_SUNXI_CCU is not set # # Hardware Spinlock drivers @@ -4347,6 +4379,7 @@ CONFIG_EFI_ESRT=y CONFIG_EFI_RUNTIME_WRAPPERS=y # CONFIG_EFI_BOOTLOADER_CONTROL is not set # CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_TEST is not set # # File systems @@ -4450,6 +4483,7 @@ CONFIG_TMPFS_POSIX_ACL=y CONFIG_TMPFS_XATTR=y # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y # CONFIG_CONFIGFS_FS is not set CONFIG_EFIVAR_FS=y CONFIG_MISC_FILESYSTEMS=y @@ -4709,7 +4743,6 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y @@ -4750,6 +4783,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set # CONFIG_UBSAN is not set CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y CONFIG_STRICT_DEVMEM=y @@ -5025,7 +5059,6 @@ CONFIG_DQL=y CONFIG_GLOB=y # CONFIG_GLOB_SELFTEST is not set CONFIG_NLATTR=y -CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set # CONFIG_IRQ_POLL is not set @@ -5040,3 +5073,4 @@ CONFIG_SG_POOL=y CONFIG_ARCH_HAS_SG_CHAIN=y CONFIG_ARCH_HAS_PMEM_API=y CONFIG_ARCH_HAS_MMIO_FLUSH=y +CONFIG_SBITMAP=y diff --git a/projects/RPi/linux/linux.arm.conf b/projects/RPi/linux/linux.arm.conf index 50e5281791..5b26ebd48c 100644 --- a/projects/RPi/linux/linux.arm.conf +++ b/projects/RPi/linux/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.8.11 Kernel Configuration +# Linux/arm 4.9.0 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -68,6 +68,7 @@ CONFIG_HANDLE_DOMAIN_IRQ=y # CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_GENERIC_CLOCKEVENTS=y # @@ -239,6 +240,7 @@ CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y # CONFIG_CPU_NO_EFFICIENT_FFS is not set +# CONFIG_HAVE_ARCH_VMAP_STACK is not set # # GCOV-based kernel profiling @@ -360,7 +362,7 @@ CONFIG_ARCH_BCM=y # Other Architectures # CONFIG_ARCH_BCM2835=y -CONFIG_MACH_BCM2708=y +CONFIG_BCM2835_FAST_MEMCPY=y # CONFIG_ARCH_CNS3XXX is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_ASPEED is not set @@ -509,7 +511,8 @@ CONFIG_AUTO_ZRELADDR=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_ATTR_SET=y CONFIG_CPU_FREQ_GOV_COMMON=y -# CONFIG_CPU_FREQ_STAT is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set @@ -558,6 +561,7 @@ CONFIG_BINFMT_ELF=y CONFIG_ELFCORE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y +# CONFIG_BINFMT_FLAT is not set # CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set CONFIG_COREDUMP=y @@ -915,6 +919,7 @@ CONFIG_BT_HCIUART_3WIRE=y CONFIG_BT_HCIUART_BCM=y # CONFIG_BT_HCIUART_QCA is not set # CONFIG_BT_HCIUART_AG6XX is not set +# CONFIG_BT_HCIUART_MRVL is not set CONFIG_BT_HCIBCM203X=m # CONFIG_BT_HCIBPA10X is not set CONFIG_BT_HCIBFUSB=m @@ -923,6 +928,7 @@ CONFIG_BT_HCIBFUSB=m CONFIG_BT_ATH3K=m # CONFIG_AF_RXRPC is not set # CONFIG_AF_KCM is not set +# CONFIG_STREAM_PARSER is not set CONFIG_WIRELESS=y CONFIG_WIRELESS_EXT=y CONFIG_WEXT_CORE=y @@ -983,6 +989,7 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_ALLOW_DEV_COREDUMP is not set # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set CONFIG_REGMAP=y @@ -1062,8 +1069,6 @@ CONFIG_BCM2835_SMI=m # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085_I2C is not set -# CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set # CONFIG_SRAM is not set @@ -1090,7 +1095,6 @@ CONFIG_EEPROM_93CX6=m # Altera FPGA firmware download module # # CONFIG_ALTERA_STAPL is not set -CONFIG_BCM2708_VCHIQ=y # # Intel MIC Bus Driver @@ -1180,7 +1184,6 @@ CONFIG_NET_CORE=y # CONFIG_NET_TEAM is not set CONFIG_MACVLAN=m # CONFIG_MACVTAP is not set -# CONFIG_IPVLAN is not set # CONFIG_VXLAN is not set # CONFIG_MACSEC is not set CONFIG_NETCONSOLE=y @@ -1204,38 +1207,44 @@ CONFIG_PHYLIB=y CONFIG_SWPHY=y # -# MII PHY device drivers +# MDIO bus device drivers # -# CONFIG_AQUANTIA_PHY is not set -# CONFIG_AT803X_PHY is not set -# CONFIG_AMD_PHY is not set -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_TERANETICS_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_BCM7XXX_PHY is not set -# CONFIG_BCM87XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_DP83848_PHY is not set -# CONFIG_DP83867_PHY is not set -# CONFIG_MICROCHIP_PHY is not set -CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BCM_UNIMAC is not set # CONFIG_MDIO_BITBANG is not set # CONFIG_MDIO_BUS_MUX_GPIO is not set # CONFIG_MDIO_BUS_MUX_MMIOREG is not set -# CONFIG_MDIO_BCM_UNIMAC is not set -# CONFIG_INTEL_XWAY_PHY is not set # CONFIG_MDIO_HISI_FEMAC is not set + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_ICPLUS_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set # CONFIG_MICREL_KS8995MA is not set CONFIG_PPP=m CONFIG_PPP_BSDCOMP=m @@ -1474,11 +1483,11 @@ CONFIG_TOUCHSCREEN_ADS7846=m # CONFIG_TOUCHSCREEN_EETI is not set CONFIG_TOUCHSCREEN_EGALAX=m # CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set -# CONFIG_TOUCHSCREEN_FT6236 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GOODIX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set # CONFIG_TOUCHSCREEN_ELAN is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set @@ -1544,6 +1553,7 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_BEEPER is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_GPIO_DECODER is not set # CONFIG_INPUT_ATI_REMOTE2 is not set # CONFIG_INPUT_KEYSPAN_REMOTE is not set # CONFIG_INPUT_KXTJ9 is not set @@ -1716,6 +1726,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_AXI_SPI_ENGINE is not set CONFIG_SPI_BCM2835=m CONFIG_SPI_BCM2835AUX=m +# CONFIG_SPI_BCM_QSPI is not set # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_CADENCE is not set # CONFIG_SPI_DESIGNWARE is not set @@ -1769,7 +1780,6 @@ CONFIG_PINCONF=y CONFIG_PINCTRL_BCM2835=y CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_GPIOLIB=y -CONFIG_GPIO_DEVRES=y CONFIG_OF_GPIO=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y @@ -1784,6 +1794,7 @@ CONFIG_GPIO_BCM_VIRT=y # CONFIG_GPIO_EM is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_MOCKUP is not set # CONFIG_GPIO_MPC8XXX is not set # CONFIG_GPIO_PL061 is not set # CONFIG_GPIO_XILINX is not set @@ -1801,11 +1812,13 @@ CONFIG_GPIO_BCM_VIRT=y # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set # CONFIG_GPIO_TPIC2810 is not set +# CONFIG_GPIO_TS4900 is not set # # MFD GPIO expanders # CONFIG_GPIO_ARIZONA=m +# CONFIG_HTC_EGPIO is not set # # SPI GPIO expanders @@ -1849,6 +1862,15 @@ CONFIG_W1_SLAVE_THERM=m # CONFIG_W1_SLAVE_DS2781 is not set # CONFIG_W1_SLAVE_DS28E04 is not set # CONFIG_W1_SLAVE_BQ27000 is not set +# CONFIG_POWER_AVS is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMKONA is not set +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_RESTART=y +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set @@ -1871,15 +1893,6 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set # CONFIG_CHARGER_RT9455 is not set -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_BRCMKONA is not set -CONFIG_POWER_RESET_GPIO=y -CONFIG_POWER_RESET_GPIO_RESTART=y -# CONFIG_POWER_RESET_LTC2952 is not set -CONFIG_POWER_RESET_RESTART=y -# CONFIG_POWER_RESET_SYSCON is not set -# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set -# CONFIG_POWER_AVS is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -2020,6 +2033,7 @@ CONFIG_THERMAL_GOV_STEP_WISE=y # CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set # CONFIG_CPU_THERMAL is not set # CONFIG_THERMAL_EMULATION is not set +# CONFIG_QORIQ_THERMAL is not set CONFIG_THERMAL_BCM2835=y # @@ -2048,6 +2062,11 @@ CONFIG_BCM2835_WDT=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set + +# +# Watchdog Pretimeout Governors +# +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set CONFIG_SSB_POSSIBLE=y # @@ -2096,10 +2115,10 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_DA9063 is not set # CONFIG_MFD_DA9150 is not set # CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_EXYNOS_LPASS is not set # CONFIG_MFD_MC13XXX_SPI is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_MFD_HI6421_PMIC is not set -# CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set # CONFIG_INTEL_SOC_PMIC is not set @@ -2147,6 +2166,7 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_MFD_TPS65086 is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set # CONFIG_MFD_TPS65218 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set @@ -2281,6 +2301,7 @@ CONFIG_VIDEO_TM6000_DVB=m # CONFIG_DVB_USB=m # CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB3000MC=m # CONFIG_DVB_USB_A800 is not set CONFIG_DVB_USB_DIBUSB_MB=m CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y @@ -2306,6 +2327,18 @@ CONFIG_DVB_USB_DTV5100=m # CONFIG_DVB_USB_FRIIO is not set CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_TBSQBOX=m +CONFIG_DVB_USB_TBSQBOX2=m +CONFIG_DVB_USB_TBSQBOX22=m +CONFIG_DVB_USB_TBS5922SE=m +CONFIG_DVB_USB_TBSQBOXS2=m +CONFIG_DVB_USB_TBSQBOX2CI=m +CONFIG_DVB_USB_TBS5925=m +CONFIG_DVB_USB_TBS5880=m +CONFIG_DVB_USB_TBS5220=m +CONFIG_DVB_USB_TBS5881=m +CONFIG_DVB_USB_TBS5520=m +CONFIG_DVB_USB_TBS5927=m CONFIG_DVB_USB_V2=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m @@ -2356,7 +2389,7 @@ CONFIG_SMS_SIANO_RC=y # CONFIG_SMS_SIANO_DEBUGFS is not set # -# Media ancillary drivers (tuners, sensors, i2c, frontends) +# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_MEDIA_ATTACH=y @@ -2442,6 +2475,9 @@ CONFIG_MEDIA_TUNER_SI2157=m CONFIG_MEDIA_TUNER_IT913X=m CONFIG_MEDIA_TUNER_R820T=m CONFIG_MEDIA_TUNER_QM1D1C0042=m +CONFIG_MEDIA_TUNER_AV201X=m +CONFIG_MEDIA_TUNER_STV6120=m +CONFIG_MEDIA_TUNER_R848=m # # Multistandard (satellite) frontends @@ -2503,6 +2539,7 @@ CONFIG_DVB_RTL2830=m CONFIG_DVB_RTL2832=m CONFIG_DVB_SI2168=m CONFIG_DVB_AS102_FE=m +# CONFIG_DVB_GP8PSK_FE is not set # # DVB-C (cable) frontends @@ -2558,10 +2595,13 @@ CONFIG_DVB_ATBM8830=m CONFIG_DVB_IX2505V=m CONFIG_DVB_M88RS2000=m CONFIG_DVB_AF9033=m +CONFIG_DVB_TAS2101=m # # Tools to develop new frontends # +CONFIG_DVB_STV0910=m +CONFIG_DVB_AVL6882=m # CONFIG_DVB_DUMMY_FE is not set # @@ -2710,7 +2750,6 @@ CONFIG_SND_BCM2835_SOC_I2S=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m CONFIG_SND_BCM2708_SOC_RPI_DAC=m CONFIG_SND_BCM2708_SOC_RPI_PROTO=m CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m @@ -2740,13 +2779,6 @@ CONFIG_SND_PISOUND=m # CONFIG_SND_SOC_FSL_ESAI is not set # CONFIG_SND_SOC_IMX_AUDMUX is not set # CONFIG_SND_SOC_IMG is not set - -# -# Allwinner SoC Audio support -# -# CONFIG_SND_SUN4I_CODEC is not set -# CONFIG_SND_SUN4I_I2S is not set -# CONFIG_SND_SUN4I_SPDIF is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=m @@ -2810,7 +2842,6 @@ CONFIG_SND_SOC_STA32X=m # CONFIG_SND_SOC_TAS571X is not set # CONFIG_SND_SOC_TAS5720 is not set # CONFIG_SND_SOC_TFA9879 is not set -CONFIG_SND_SOC_TAS5713=m # CONFIG_SND_SOC_TLV320AIC23_I2C is not set # CONFIG_SND_SOC_TLV320AIC23_SPI is not set # CONFIG_SND_SOC_TLV320AIC31XX is not set @@ -2837,8 +2868,10 @@ CONFIG_SND_SOC_WM8804_I2C=m # CONFIG_SND_SOC_WM8974 is not set # CONFIG_SND_SOC_WM8978 is not set # CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_NAU8810 is not set CONFIG_SND_SOC_TPA6130A2=m # CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SND_SIMPLE_SCU_CARD is not set # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=m @@ -2961,7 +2994,7 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set CONFIG_USB_MON=m # CONFIG_USB_WUSB_CBAF is not set @@ -3106,6 +3139,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set @@ -3119,6 +3153,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_ULPI is not set # CONFIG_USB_GADGET is not set # CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_ULPI_BUS is not set # CONFIG_UWB is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set @@ -3185,6 +3220,7 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_TLC591XX is not set # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_KTD2692 is not set +# CONFIG_LEDS_IS31FL319X is not set # CONFIG_LEDS_IS31FL32XX is not set # @@ -3238,6 +3274,7 @@ CONFIG_RTC_INTF_DEV=y CONFIG_RTC_DRV_ABX80X=m CONFIG_RTC_DRV_DS1307=m CONFIG_RTC_DRV_DS1307_HWMON=y +# CONFIG_RTC_DRV_DS1307_CENTURY is not set # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_HYM8563 is not set @@ -3245,7 +3282,6 @@ CONFIG_RTC_DRV_DS1307_HWMON=y # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_ISL12057 is not set # CONFIG_RTC_DRV_X1205 is not set CONFIG_RTC_DRV_PCF8523=m # CONFIG_RTC_DRV_PCF85063 is not set @@ -3397,6 +3433,8 @@ CONFIG_LIRC_RPI=m # CONFIG_WILC1000_SPI is not set # CONFIG_MOST is not set # CONFIG_KS7010 is not set +# CONFIG_GREYBUS is not set +CONFIG_BCM2708_VCHIQ=y # CONFIG_GOLDFISH is not set # CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y @@ -3416,7 +3454,6 @@ CONFIG_COMMON_CLK=y # CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_PIC32 is not set -# CONFIG_SUNXI_CCU is not set # # Hardware Spinlock drivers @@ -3437,6 +3474,7 @@ CONFIG_ARM_TIMER_SP804=y # CONFIG_EM_TIMER_STI is not set CONFIG_MAILBOX=y # CONFIG_ARM_MHU is not set +# CONFIG_PLATFORM_MHU is not set # CONFIG_PL320_MBOX is not set # CONFIG_ALTERA_MBOX is not set CONFIG_BCM2835_MBOX=y @@ -3472,6 +3510,7 @@ CONFIG_EXTCON=m CONFIG_EXTCON_ARIZONA=m # CONFIG_EXTCON_GPIO is not set # CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_QCOM_SPMI_MISC is not set # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set # CONFIG_EXTCON_USB_GPIO is not set @@ -3482,7 +3521,16 @@ CONFIG_IRQCHIP=y CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_IPACK_BUS is not set CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_ATH79 is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_LPC18XX is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_STM32 is not set +# CONFIG_RESET_SUNXI is not set # CONFIG_TI_SYSCON_RESET is not set +# CONFIG_RESET_ZYNQ is not set # CONFIG_FMC is not set # @@ -3894,6 +3942,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set # CONFIG_UBSAN is not set CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y # CONFIG_STRICT_DEVMEM is not set @@ -4115,7 +4164,6 @@ CONFIG_HAS_IOPORT_MAP=y CONFIG_HAS_DMA=y CONFIG_DQL=y CONFIG_NLATTR=y -CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set # CONFIG_IRQ_POLL is not set @@ -4128,4 +4176,5 @@ CONFIG_FONT_8x16=y # CONFIG_SG_SPLIT is not set CONFIG_SG_POOL=y CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y # CONFIG_VIRTUALIZATION is not set diff --git a/projects/RPi/patches/linux/linux-01-RPi_support.patch b/projects/RPi/patches/linux/linux-01-RPi_support.patch index 1c3a98131a..4369261e5c 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support.patch @@ -1,104 +1,7 @@ -From 7d5fc6dc9e80848e3fb1dc99bf93e3fc6251aed4 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 27 Apr 2016 17:43:28 +0100 -Subject: [PATCH 001/208] Revert "SUNRPC: Make NFS swap work with multipath" - -This reverts commit 15001e5a7e1e207b6bd258cd8f187814cd15b6dc. ---- - net/sunrpc/clnt.c | 66 +++++++++++++++++++++++++++++++++++-------------------- - 1 file changed, 42 insertions(+), 24 deletions(-) - -diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c -index 66f23b376fa04a91134eddf6d8ee22a2f5de5808..f55fe2b0137e8fbefcd20c336b28ad48a7a105c1 100644 ---- a/net/sunrpc/clnt.c -+++ b/net/sunrpc/clnt.c -@@ -2743,39 +2743,57 @@ void rpc_show_tasks(struct net *net) - #endif - - #if IS_ENABLED(CONFIG_SUNRPC_SWAP) --static int --rpc_clnt_swap_activate_callback(struct rpc_clnt *clnt, -- struct rpc_xprt *xprt, -- void *dummy) --{ -- return xprt_enable_swap(xprt); --} -- - int - rpc_clnt_swap_activate(struct rpc_clnt *clnt) - { -- if (atomic_inc_return(&clnt->cl_swapper) == 1) -- return rpc_clnt_iterate_for_each_xprt(clnt, -- rpc_clnt_swap_activate_callback, NULL); -- return 0; --} --EXPORT_SYMBOL_GPL(rpc_clnt_swap_activate); -+ int ret = 0; -+ struct rpc_xprt *xprt; - --static int --rpc_clnt_swap_deactivate_callback(struct rpc_clnt *clnt, -- struct rpc_xprt *xprt, -- void *dummy) --{ -- xprt_disable_swap(xprt); -- return 0; -+ if (atomic_inc_return(&clnt->cl_swapper) == 1) { -+retry: -+ rcu_read_lock(); -+ xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); -+ rcu_read_unlock(); -+ if (!xprt) { -+ /* -+ * If we didn't get a reference, then we likely are -+ * racing with a migration event. Wait for a grace -+ * period and try again. -+ */ -+ synchronize_rcu(); -+ goto retry; -+ } -+ -+ ret = xprt_enable_swap(xprt); -+ xprt_put(xprt); -+ } -+ return ret; - } -+EXPORT_SYMBOL_GPL(rpc_clnt_swap_activate); - - void - rpc_clnt_swap_deactivate(struct rpc_clnt *clnt) - { -- if (atomic_dec_if_positive(&clnt->cl_swapper) == 0) -- rpc_clnt_iterate_for_each_xprt(clnt, -- rpc_clnt_swap_deactivate_callback, NULL); -+ struct rpc_xprt *xprt; -+ -+ if (atomic_dec_if_positive(&clnt->cl_swapper) == 0) { -+retry: -+ rcu_read_lock(); -+ xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); -+ rcu_read_unlock(); -+ if (!xprt) { -+ /* -+ * If we didn't get a reference, then we likely are -+ * racing with a migration event. Wait for a grace -+ * period and try again. -+ */ -+ synchronize_rcu(); -+ goto retry; -+ } -+ -+ xprt_disable_swap(xprt); -+ xprt_put(xprt); -+ } - } - EXPORT_SYMBOL_GPL(rpc_clnt_swap_deactivate); - #endif /* CONFIG_SUNRPC_SWAP */ - -From a076f856510da92d7b277dd9ad19b624ce02a559 Mon Sep 17 00:00:00 2001 +From 187d14c75091ecf91914e7273ea75a94649f5715 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 002/208] smsx95xx: fix crimes against truesize +Subject: [PATCH 001/111] smsx95xx: fix crimes against truesize smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings. @@ -110,10 +13,10 @@ Signed-off-by: Steve Glendinning 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62cb78cc1bb 100644 +index 831aa33d078ae7d2dd57fdded5de71d1eb915f99..b77935bded8c0ff7808b00f170ff10e594300ad0 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -80,6 +80,10 @@ static bool turbo_mode = true; +@@ -82,6 +82,10 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); @@ -124,7 +27,7 @@ index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62c static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -1848,7 +1852,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1951,7 +1955,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(skb); skb_trim(skb, skb->len - 4); /* remove fcs */ @@ -134,7 +37,7 @@ index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62c return 1; } -@@ -1866,7 +1871,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1969,7 +1974,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(ax_skb); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ @@ -145,55 +48,33 @@ index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62c usbnet_skb_return(dev, ax_skb); } -From 1a57f996e9d7b4b9698abf85d2665f32c03a2ded Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 003/208] smsc95xx: Disable turbo mode by default - ---- - drivers/net/usb/smsc95xx.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 116680e3089f16e1e3e9113a3b93e62cb78cc1bb..aa4cb43dcd9ba83b042332bc15a4dce68affce28 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -76,7 +76,7 @@ struct smsc95xx_priv { - struct usbnet *dev; - }; - --static bool turbo_mode = true; -+static bool turbo_mode = false; - module_param(turbo_mode, bool, 0644); - MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); - - -From e256c71277d74a1115d9bd9844fcfb5860fec9b2 Mon Sep 17 00:00:00 2001 +From 584529ad0dc510e6e870aa9141ed889edf2dbbbd Mon Sep 17 00:00:00 2001 From: Sam Nazarko Date: Fri, 1 Apr 2016 17:27:21 +0100 -Subject: [PATCH 004/208] add smsc95xx packetsize module_param +Subject: [PATCH 002/111] smsc95xx: Experimental: Enable turbo_mode and + packetsize=2560 by default -Signed-off-by: Sam Nazarko +See: http://forum.kodi.tv/showthread.php?tid=285288 --- drivers/net/usb/smsc95xx.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index aa4cb43dcd9ba83b042332bc15a4dce68affce28..889bdabd9dea6cebccc361aa4ac569d73681396b 100644 +index b77935bded8c0ff7808b00f170ff10e594300ad0..693f163684de921404738e33244881e0aab92ec9 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -84,6 +84,10 @@ static bool truesize_mode = false; +@@ -86,6 +86,10 @@ static bool truesize_mode = false; module_param(truesize_mode, bool, 0644); MODULE_PARM_DESC(truesize_mode, "Report larger truesize value"); -+static int packetsize = 0; ++static int packetsize = 2560; +module_param(packetsize, int, 0644); +MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); + static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -1005,13 +1009,13 @@ static int smsc95xx_reset(struct usbnet *dev) +@@ -1106,13 +1110,13 @@ static int smsc95xx_reset(struct usbnet *dev) if (!turbo_mode) { burst_cap = 0; @@ -213,10 +94,10 @@ index aa4cb43dcd9ba83b042332bc15a4dce68affce28..889bdabd9dea6cebccc361aa4ac569d7 netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", -From 919b66093359eca7e24223ecbba9e788111c841f Mon Sep 17 00:00:00 2001 +From 2bf8ca86c5944a4f05a715a9a6b137bce58e7a59 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 005/208] Allow mac address to be set in smsc95xx +Subject: [PATCH 003/111] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -224,7 +105,7 @@ Signed-off-by: popcornmix 1 file changed, 56 insertions(+) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9f72bebe3 100644 +index 693f163684de921404738e33244881e0aab92ec9..df60c989fc229bf0aab3c27e95ccd45323367840 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -60,6 +60,7 @@ @@ -235,7 +116,7 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 #define CARRIER_CHECK_DELAY (2 * HZ) -@@ -88,6 +89,10 @@ static int packetsize = 0; +@@ -90,6 +91,10 @@ static int packetsize = 2560; module_param(packetsize, int, 0644); MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); @@ -246,7 +127,7 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -817,6 +822,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +@@ -918,6 +923,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } @@ -300,7 +181,7 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 static void smsc95xx_init_mac_address(struct usbnet *dev) { const u8 *mac_addr; -@@ -838,6 +890,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) +@@ -939,6 +991,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) } } @@ -312,75 +193,10 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); -From 6885eab792b8feb8c2329f2981453074fae14527 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 9 Aug 2016 22:19:28 +0100 -Subject: [PATCH 006/208] smsc95xx: Experimental: Enable turbo_mode and - packetsize=2560 by default - -See: http://forum.kodi.tv/showthread.php?tid=285288 ---- - drivers/net/usb/smsc95xx.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index d22a2324085fbf61fbd8920362bfc7b9f72bebe3..c846c55075387398d9bcb0957e31f5c82fd7d58d 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -77,7 +77,7 @@ struct smsc95xx_priv { - struct usbnet *dev; - }; - --static bool turbo_mode = false; -+static bool turbo_mode = true; - module_param(turbo_mode, bool, 0644); - MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); - -@@ -85,7 +85,7 @@ static bool truesize_mode = false; - module_param(truesize_mode, bool, 0644); - MODULE_PARM_DESC(truesize_mode, "Report larger truesize value"); - --static int packetsize = 0; -+static int packetsize = 2560; - module_param(packetsize, int, 0644); - MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); - - -From f0bec5372fdc974676a90c5828dc73ac8df18bb9 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 9 Mar 2016 13:28:24 +0000 -Subject: [PATCH 007/208] serial: Take care starting a hung-up tty's port - -tty_port_hangup sets a port's tty field to NULL (holding the port lock), -but uart_tx_stopped, called from __uart_start (with the port lock), -uses the tty field without checking for NULL. - -Change uart_tx_stopped to treat a NULL tty field as another stopped -indication. - -Signed-off-by: Phil Elwell ---- - include/linux/serial_core.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h -index 2f44e20136545162d15ee9a39c2eae38352580d1..6b0518ce13ad210b888b73dd6c02a5558798b38f 100644 ---- a/include/linux/serial_core.h -+++ b/include/linux/serial_core.h -@@ -412,7 +412,7 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); - static inline int uart_tx_stopped(struct uart_port *port) - { - struct tty_struct *tty = port->state->port.tty; -- if (tty->stopped || port->hw_stopped) -+ if (!tty || tty->stopped || port->hw_stopped) - return 1; - return 0; - } - -From 7a4314314fefb3d4288ba4a245f08abd83334c9d Mon Sep 17 00:00:00 2001 +From 481e18fc6c63b56179f93596c5393e5638fab295 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 12:43:36 +0000 -Subject: [PATCH 008/208] Protect __release_resource against resources without +Subject: [PATCH 004/111] Protect __release_resource against resources without parents Without this patch, removing a device tree overlay can crash here. @@ -408,10 +224,10 @@ index 9b5f04404152c296af3a96132f27cfc80ffa9af9..f8a9af6e6b915812be2ba2c1c2b40106 for (;;) { tmp = *p; -From b67c49a019770ea73d250e046faabd79df373fa9 Mon Sep 17 00:00:00 2001 +From 1b2be2671cee28c79160329883028029c2b0c857 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Dec 2014 16:07:15 -0800 -Subject: [PATCH 009/208] mm: Remove the PFN busy warning +Subject: [PATCH 005/111] mm: Remove the PFN busy warning See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is expected sometimes when using CMA. However, that commit still spams @@ -423,10 +239,10 @@ Signed-off-by: Eric Anholt 1 file changed, 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 7401e996009afa14cb6c3834b62ce8780e6e958a..7f48cd9228cd1c7c4fb9451729f7826d2ca3d6eb 100644 +index 6de9440e3ae2d995b28577dc4a000fc23f4182c0..bea7204c14a5e24e018218b3d3eaef7c1ac5fd4f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -7318,8 +7318,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, +@@ -7289,8 +7289,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, /* Make sure the range is really isolated. */ if (test_pages_isolated(outer_start, end, false)) { @@ -436,51 +252,10 @@ index 7401e996009afa14cb6c3834b62ce8780e6e958a..7f48cd9228cd1c7c4fb9451729f7826d goto done; } -From 606896cbfc13f4e43c502c30e9d07acaa77f80c3 Mon Sep 17 00:00:00 2001 -From: Robert Tiemann -Date: Mon, 20 Jul 2015 11:01:25 +0200 -Subject: [PATCH 010/208] BCM2835_DT: Fix I2S register map - ---- - Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- - Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -index baf9b34d20bfb5b5493e0a69841362530c900a77..11c052acf65e74f032ae77bfd2749db860762b2d 100644 ---- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -+++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -@@ -74,8 +74,8 @@ Example: - - bcm2835_i2s: i2s@7e203000 { - compatible = "brcm,bcm2835-i2s"; -- reg = < 0x7e203000 0x20>, -- < 0x7e101098 0x02>; -+ reg = < 0x7e203000 0x24>, -+ < 0x7e101098 0x08>; - - dmas = <&dma 2>, - <&dma 3>; -diff --git a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt -index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554427118a2 100644 ---- a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt -+++ b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt -@@ -16,8 +16,8 @@ Example: - - bcm2835_i2s: i2s@7e203000 { - compatible = "brcm,bcm2835-i2s"; -- reg = <0x7e203000 0x20>, -- <0x7e101098 0x02>; -+ reg = <0x7e203000 0x24>, -+ <0x7e101098 0x08>; - - dmas = <&dma 2>, - <&dma 3>; - -From 59ffae373ced5b44abaa948286cb2e1b69fe9cf3 Mon Sep 17 00:00:00 2001 +From 5d1f384994be88b18a6dfb189687c32204c5b827 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 4 Dec 2015 17:41:50 +0000 -Subject: [PATCH 011/208] irq-bcm2836: Prevent spurious interrupts, and trap +Subject: [PATCH 006/111] irq-bcm2836: Prevent spurious interrupts, and trap them early The old arch-specific IRQ macros included a dsb to ensure the @@ -507,10 +282,10 @@ index d96b2c947e74e3edab3917551c64fbd1ced0f34c..93e3f7660c4230c9f1dd3b195958cb49 #endif } else if (stat) { -From 64abf4863e38961cfdc3c2b1680e3b7751cd7dee Mon Sep 17 00:00:00 2001 +From 62120b5cc0bcdf3a2d243ae8d32dc6033eb0a616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 12 Jun 2015 19:01:05 +0200 -Subject: [PATCH 012/208] irqchip: bcm2835: Add FIQ support +Subject: [PATCH 007/111] irqchip: bcm2835: Add FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -528,10 +303,10 @@ Acked-by: Stephen Warren 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 34f0fca0b8472720cd107946e8f5a99d4cfa542a..5f6ab16792a93b2dd2e3f9e647f8ac4062d4fa6d 100644 +index a0e66d8200c5cf8f2ea592abf870a32800213fa2..4ff30d5278a7ce093c9629d4c25d37e3bbbda752 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig -@@ -153,6 +153,7 @@ config ARCH_BCM2835 +@@ -152,6 +152,7 @@ config ARCH_BCM2835 select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7 select CLKSRC_OF select BCM2835_TIMER @@ -639,10 +414,10 @@ index 44d7c38dde479d771f3552e914bf8c1c1f5019f7..42ff5e6a8e0d532f5b60a1e7af7cc4d9 } -From 86a5fcd1b51a616ae46047631553503ad2b096c8 Mon Sep 17 00:00:00 2001 +From 2a1701f404bdbf47c8864d62551626d60d022d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 23 Oct 2015 16:26:55 +0200 -Subject: [PATCH 013/208] irqchip: irq-bcm2835: Add 2836 FIQ support +Subject: [PATCH 008/111] irqchip: irq-bcm2835: Add 2836 FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -741,10 +516,10 @@ index 42ff5e6a8e0d532f5b60a1e7af7cc4d941bd5008..eccf6ed025299cb480884f5bcbe77abf for (b = 0; b < NR_BANKS; b++) { for (i = 0; i < bank_irqs[b]; i++) { -From dec587cf518f9b967b7ce5faa5fa2944a6e6c0cd Mon Sep 17 00:00:00 2001 +From 573c26f692a511b5850d94ce07a7ae8d27aeb87b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 10:26:09 +0100 -Subject: [PATCH 014/208] spidev: Add "spidev" compatible string to silence +Subject: [PATCH 009/111] spidev: Add "spidev" compatible string to silence warning See: https://github.com/raspberrypi/linux/issues/1054 @@ -765,17 +540,17 @@ index 2e05046f866bd01bf87edcdeff0d5b76d4d0aea7..d780491b8013a4e97fa843958964454e }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -From c142337d3ab8a9fbceb6d611e32b3a621d577cb5 Mon Sep 17 00:00:00 2001 +From 49007260438ac25b031a5f426336b4a3c2f79164 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 30 Jun 2015 14:12:42 +0100 -Subject: [PATCH 015/208] serial: 8250: Don't crash when nr_uarts is 0 +Subject: [PATCH 010/111] serial: 8250: Don't crash when nr_uarts is 0 --- drivers/tty/serial/8250/8250_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c -index dcf43f66404f12d2bd290a30adfe494dd056162e..0fba189c676ded310b92a09c4e7e8f768d753895 100644 +index 240a361b674fe72ce657067e5303156b7add6a6f..14f6cdfd744209482056d206dc476d9427cba9ba 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -509,6 +509,8 @@ static void __init serial8250_isa_init_ports(void) @@ -788,10 +563,10 @@ index dcf43f66404f12d2bd290a30adfe494dd056162e..0fba189c676ded310b92a09c4e7e8f76 for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; -From 967fd972c6351fed9598396aa68071d3699023d2 Mon Sep 17 00:00:00 2001 +From 8dd1e9defb5253e50db90363693595d980b9f89e Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 016/208] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 011/111] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -813,10 +588,10 @@ index fa77165fab2c1348163979da507df17e7168c49b..d11e2e4ea189466e686d762cb6c6fef9 .can_sleep = false, }; -From c5d54043c247044a8ecdd7451b7a2fbc5650f114 Mon Sep 17 00:00:00 2001 +From 1ea344b8d6146e5ddb11d0b8cef5d9c5f1fc76c9 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 017/208] pinctrl-bcm2835: Fix interrupt handling for GPIOs +Subject: [PATCH 012/111] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -962,10 +737,10 @@ index d11e2e4ea189466e686d762cb6c6fef9111ecf8e..107ad7d58de8f8a7f55e09c9cdcf7d66 }, }; -From f12b7d81a1109e470185f3392099dc89552e1545 Mon Sep 17 00:00:00 2001 +From 1a70bcb135aba08029a4a527d94611eea7b14fbe Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 018/208] pinctrl-bcm2835: Only request the interrupts listed +Subject: [PATCH 013/111] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -992,10 +767,10 @@ index 107ad7d58de8f8a7f55e09c9cdcf7d66fa7ab66b..644bdecbcfcb79d3b84a33769265fca5 pc->irq_data[i].irqgroup = i; -From 28c879d001bb5ab3fd6dbacdf0df76518b41dce1 Mon Sep 17 00:00:00 2001 +From 7198cc8ee9b058e09ea92f672ed183abd622aa9b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 May 2016 12:32:47 +0100 -Subject: [PATCH 019/208] pinctrl-bcm2835: Return pins to inputs when freed +Subject: [PATCH 014/111] pinctrl-bcm2835: Return pins to inputs when freed When dynamically unloading overlays, it is important that freed pins are restored to being inputs to prevent functions from being enabled in @@ -1036,10 +811,10 @@ index 644bdecbcfcb79d3b84a33769265fca5d3d0c9e5..81a66cba2ab0f7e3ae179de7edd10122 .get_function_name = bcm2835_pmx_get_function_name, .get_function_groups = bcm2835_pmx_get_function_groups, -From 34a7ed67a97641610545f768e1fac116fb09f129 Mon Sep 17 00:00:00 2001 +From 2f3c0a3e933104ad100b1c28e957c72d7d083de6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 -Subject: [PATCH 020/208] spi-bcm2835: Support pin groups other than 7-11 +Subject: [PATCH 015/111] spi-bcm2835: Support pin groups other than 7-11 The spi-bcm2835 driver automatically uses GPIO chip-selects due to some unreliability of the native ones. In doing so it chooses the @@ -1120,10 +895,10 @@ index f35cc10772f6670397ea923ad30158270dd68578..5dfe20ffc2866fa6789825016c585175 /* and set up the "mode" and level */ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -From 164780791396998dfdc84cdd11ac0a57acb88c8d Mon Sep 17 00:00:00 2001 +From 2f97bbd1ddafb4209b88897b2f6cc1267bc1f247 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 1 Jul 2016 22:09:24 +0100 -Subject: [PATCH 021/208] spi-bcm2835: Disable forced software CS +Subject: [PATCH 016/111] spi-bcm2835: Disable forced software CS Select software CS in bcm2708_common.dtsi, and disable the automatic conversion in the driver to allow hardware CS to be re-enabled with an @@ -1157,10 +932,101 @@ index 5dfe20ffc2866fa6789825016c585175a29705b6..8493474d286f7a1ac6454a22c61c8c2c return 0; } -From 8f9c99a7bb5105f249f22244ee7c11c9491909d2 Mon Sep 17 00:00:00 2001 +From 4a119ff4ae732e4220dba5262ad4d800d1af7dde Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 8 Nov 2016 21:35:38 +0000 +Subject: [PATCH 017/111] spi-bcm2835: Remove unused code + +--- + drivers/spi/spi-bcm2835.c | 61 ----------------------------------------------- + 1 file changed, 61 deletions(-) + +diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c +index 8493474d286f7a1ac6454a22c61c8c2cef9121bf..33d75ad38a7f77d085321ace9101900a83bebcac 100644 +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -679,17 +679,8 @@ static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) + bcm2835_wr(bs, BCM2835_SPI_CS, cs); + } + +-static int chip_match_name(struct gpio_chip *chip, void *data) +-{ +- return !strcmp(chip->label, data); +-} +- + static int bcm2835_spi_setup(struct spi_device *spi) + { +- int err; +- struct gpio_chip *chip; +- struct device_node *pins; +- u32 pingroup_index; + /* + * sanity checking the native-chipselects + */ +@@ -707,58 +698,6 @@ static int bcm2835_spi_setup(struct spi_device *spi) + return -EINVAL; + } + +-#if 0 +- /* now translate native cs to GPIO */ +- /* first look for chip select pins in the devices pin groups */ +- for (pingroup_index = 0; +- (pins = of_parse_phandle(spi->master->dev.of_node, +- "pinctrl-0", +- pingroup_index)) != 0; +- pingroup_index++) { +- u32 pin; +- u32 pin_index; +- for (pin_index = 0; +- of_property_read_u32_index(pins, +- "brcm,pins", +- pin_index, +- &pin) == 0; +- pin_index++) { +- if (((spi->chip_select == 0) && +- ((pin == 8) || (pin == 36) || (pin == 46))) || +- ((spi->chip_select == 1) && +- ((pin == 7) || (pin == 35)))) { +- spi->cs_gpio = pin; +- break; +- } +- } +- of_node_put(pins); +- } +- /* if that fails, assume GPIOs 7-11 are used */ +- if (!gpio_is_valid(spi->cs_gpio) ) { +- /* get the gpio chip for the base */ +- chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); +- if (!chip) +- return 0; +- +- /* and calculate the real CS */ +- spi->cs_gpio = chip->base + 8 - spi->chip_select; +- } +- +- /* and set up the "mode" and level */ +- dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", +- spi->chip_select, spi->cs_gpio); +- +- /* set up GPIO as output and pull to the correct level */ +- err = gpio_direction_output(spi->cs_gpio, +- (spi->mode & SPI_CS_HIGH) ? 0 : 1); +- if (err) { +- dev_err(&spi->dev, +- "could not set CS%i gpio %i as output: %i", +- spi->chip_select, spi->cs_gpio, err); +- return err; +- } +-#endif +- + return 0; + } + + +From de1125b3a2d6229dc168c35ad82f6ef8a202c459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 3 Jun 2015 12:26:13 +0200 -Subject: [PATCH 022/208] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 018/111] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1213,10 +1079,10 @@ index 0c1edfc98696da0e0bb7f4a18cdfbcdd27a9795d..8f152266ba9b470df2eaaed9ebcf158e static const char * const bcm2835_compat[] = { -From 0dcea622ab242228d2ac5492166f6cc83499596b Mon Sep 17 00:00:00 2001 +From 64d21030cae9fb9718296e2657c9881cd74e18fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 3 Oct 2015 22:22:55 +0200 -Subject: [PATCH 023/208] dmaengine: bcm2835: Load driver early and support +Subject: [PATCH 019/111] dmaengine: bcm2835: Load driver early and support legacy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -1234,7 +1100,7 @@ Signed-off-by: Noralf Trønnes 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 739f797b40d9843b7d75261e955439866c7aaa83..f7b3ac574968b35aeb1fb6b3ba8d4f1bf61599f9 100644 +index 141aefbe37ec93d1f4f38d1be5e2cf8d93266725..9c931d36c6a499a02f4f215f8cd77d3f2254a3b9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -108,7 +108,7 @@ config COH901318 @@ -1319,10 +1185,10 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); -From c4d9aa87d6bf7e07bcaa8559af6ad15ab0d2ed95 Mon Sep 17 00:00:00 2001 +From 9300f525a49182536af3efc15a3a274962504e47 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jan 2016 17:25:12 +0000 -Subject: [PATCH 024/208] firmware: Updated mailbox header +Subject: [PATCH 020/111] firmware: Updated mailbox header --- include/soc/bcm2835/raspberrypi-firmware.h | 11 +++++++++++ @@ -1385,59 +1251,10 @@ index 3fb357193f09914fe21f8555a4b8613f74f22bc3..227a107214a02deadcca3db202da265e RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, -From 13a01898fca61986f9fbb5fb2e55477248b2037f Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 26 Apr 2016 11:44:59 -0700 -Subject: [PATCH 025/208] clk: bcm2835: Mark the VPU clock as critical - -The VPU clock is also the clock for our AXI bus, so we really can't -disable it. This might have happened during boot if, for example, -uart1 (aux_uart clock) probed and was then disabled before the other -consumers of the VPU clock had probed. - -v2: Rewrite to use a .flags in bcm2835_clock_data, since other clocks - will need this too. - -Signed-off-by: Eric Anholt ---- - drivers/clk/bcm/clk-bcm2835.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 0fc71cbaa4404bddc1ca603a28a43425a7e5a341..085e5217d3b9f73c312dc7fd510ef55cddb4a27c 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -443,6 +443,8 @@ struct bcm2835_clock_data { - /* Number of fractional bits in the divider */ - u32 frac_bits; - -+ u32 flags; -+ - bool is_vpu_clock; - bool is_mash_clock; - }; -@@ -1253,7 +1255,7 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, - init.parent_names = parents; - init.num_parents = data->num_mux_parents; - init.name = data->name; -- init.flags = CLK_IGNORE_UNUSED; -+ init.flags = data->flags | CLK_IGNORE_UNUSED; - - if (data->is_vpu_clock) { - init.ops = &bcm2835_vpu_clock_clk_ops; -@@ -1672,6 +1674,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .div_reg = CM_VPUDIV, - .int_bits = 12, - .frac_bits = 8, -+ .flags = CLK_IS_CRITICAL, - .is_vpu_clock = true), - - /* clocks with per parent mux */ - -From a136d9a40644e151876c7aa36e971aad4b0dc799 Mon Sep 17 00:00:00 2001 +From 9de63dc57340cb047969dedcfdfd8b51c3779083 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 May 2016 17:28:18 -0700 -Subject: [PATCH 026/208] clk: bcm2835: Mark GPIO clocks enabled at boot as +Subject: [PATCH 021/111] clk: bcm2835: Mark GPIO clocks enabled at boot as critical. These divide off of PLLD_PER and are used for the ethernet and wifi @@ -1451,14 +1268,14 @@ v2: Skip marking as critical if they aren't on at boot. Signed-off-by: Eric Anholt --- - drivers/clk/bcm/clk-bcm2835.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) + drivers/clk/bcm/clk-bcm2835.c | 9 +++++++++ + 1 file changed, 9 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 085e5217d3b9f73c312dc7fd510ef55cddb4a27c..e527649ee5e32d20cebd762f4badbfca06657a84 100644 +index 8c7763fd9efc52b30f02d9ebcd4fdb10d2876465..a73f0873b7b8f78bc4a70f01e17eb287eec1d9e3 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1257,6 +1257,15 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, +@@ -1260,6 +1260,15 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, init.name = data->name; init.flags = data->flags | CLK_IGNORE_UNUSED; @@ -1474,128 +1291,11 @@ index 085e5217d3b9f73c312dc7fd510ef55cddb4a27c..e527649ee5e32d20cebd762f4badbfca if (data->is_vpu_clock) { init.ops = &bcm2835_vpu_clock_clk_ops; } else { -@@ -1731,13 +1740,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .div_reg = CM_GP1DIV, - .int_bits = 12, - .frac_bits = 12, -+ .flags = CLK_IS_CRITICAL, - .is_mash_clock = true), - [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK( - .name = "gp2", - .ctl_reg = CM_GP2CTL, - .div_reg = CM_GP2DIV, - .int_bits = 12, -- .frac_bits = 12), -+ .frac_bits = 12, -+ .flags = CLK_IS_CRITICAL), - - /* HDMI state machine */ - [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK( -From 8c1cbf01341c3f78a107af5dc9b3190932a6c7b2 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 1 Jun 2016 12:05:35 -0700 -Subject: [PATCH 027/208] clk: bcm2835: Mark the CM SDRAM clock's parent as - critical - -While the SDRAM is being driven by its dedicated PLL most of the time, -there is a little loop running in the firmware that periodically turns -on the CM SDRAM clock (using its pre-initialized parent) and switches -SDRAM to using the CM clock to do PVT recalibration. - -This avoids system hangs if we choose SDRAM's parent for some other -clock, then disable that clock. - -Signed-off-by: Eric Anholt ---- - drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index e527649ee5e32d20cebd762f4badbfca06657a84..fbf616021704178a9d007219a0ea2a9f1704f0a6 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -36,6 +36,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -1827,6 +1828,25 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_PERIICTL), - }; - -+/* -+ * Permanently take a reference on the parent of the SDRAM clock. -+ * -+ * While the SDRAM is being driven by its dedicated PLL most of the -+ * time, there is a little loop running in the firmware that -+ * periodically switches the SDRAM to using our CM clock to do PVT -+ * recalibration, with the assumption that the previously configured -+ * SDRAM parent is still enabled and running. -+ */ -+static int bcm2835_mark_sdc_parent_critical(struct clk *sdc) -+{ -+ struct clk *parent = clk_get_parent(sdc); -+ -+ if (IS_ERR(parent)) -+ return PTR_ERR(parent); -+ -+ return clk_prepare_enable(parent); -+} -+ - static int bcm2835_clk_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -1836,6 +1856,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - const struct bcm2835_clk_desc *desc; - const size_t asize = ARRAY_SIZE(clk_desc_array); - size_t i; -+ int ret; - - cprman = devm_kzalloc(dev, - sizeof(*cprman) + asize * sizeof(*clks), -@@ -1866,6 +1887,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - clks[i] = desc->clk_register(cprman, desc->data); - } - -+ ret = bcm2835_mark_sdc_parent_critical(clks[BCM2835_CLOCK_SDRAM]); -+ if (ret) -+ return ret; -+ - return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, - &cprman->onecell); - } - -From 8fabd4b2587c362117ced1337e5ade069e9a2955 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 3 Oct 2016 13:58:40 +0100 -Subject: [PATCH 028/208] Enable upstream BCM2835 auxiliar mini UART support - ---- - drivers/tty/serial/8250/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig -index 7c6f7afca5ddeed7b25fa6272246fc539bf31b04..748098f900d3474b5d535b24da76ad06e9690335 100644 ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -291,7 +291,7 @@ config SERIAL_8250_ACORN - - config SERIAL_8250_BCM2835AUX - tristate "BCM2835 auxiliar mini UART support" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835 || COMPILE_TEST - depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ - help - Support for the BCM2835 auxiliar mini UART. - -From 9f7ddb4f7342c03f3d921e48515f8c89a08efe27 Mon Sep 17 00:00:00 2001 +From 448de2edc0f549ce252e0a0dc8089100c80184c3 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 15 Jun 2016 16:48:41 +0100 -Subject: [PATCH 029/208] rtc: Add SPI alias for pcf2123 driver +Subject: [PATCH 022/111] rtc: Add SPI alias for pcf2123 driver Without this alias, Device Tree won't cause the driver to be loaded. @@ -1615,2442 +1315,419 @@ index 8895f77726e8da5444afcd602dceff8f25a9b3fd..1833b8853ceb0e6147cceb93a00e558c MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:rtc-pcf2123"); -From ca0a284e86c89410ce033ce4abaa0581465665eb Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 19 Apr 2016 15:55:02 -0700 -Subject: [PATCH 030/208] ARM: bcm2708: Enable building power domain driver. +From 2e36db73f1fa2356e1561d09305294e4cf91e3bd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 7 Oct 2016 16:50:59 +0200 +Subject: [PATCH 023/111] watchdog: bcm2835: Support setting reboot partition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit -Signed-off-by: Eric Anholt +The Raspberry Pi firmware looks at the RSTS register to know which +partition to boot from. The reboot syscall command +LINUX_REBOOT_CMD_RESTART2 supports passing in a string argument. + +Add support for passing in a partition number 0..63 to boot from. +Partition 63 is a special partiton indicating halt. +If the partition doesn't exist, the firmware falls back to partition 0. + +Signed-off-by: Noralf Trønnes --- - drivers/soc/bcm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + drivers/watchdog/bcm2835_wdt.c | 61 +++++++++++++++++++++++++----------------- + 1 file changed, 36 insertions(+), 25 deletions(-) + +diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c +index 4dddd8298a227d64862f2e92954a465f2e44b3f6..1f545e024422f59280932713e6a1b05150b39b22 100644 +--- a/drivers/watchdog/bcm2835_wdt.c ++++ b/drivers/watchdog/bcm2835_wdt.c +@@ -35,13 +35,7 @@ + #define PM_RSTC_WRCFG_SET 0x00000030 + #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 + #define PM_RSTC_RESET 0x00000102 +- +-/* +- * The Raspberry Pi firmware uses the RSTS register to know which partiton +- * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. +- * Partiton 63 is a special partition used by the firmware to indicate halt. +- */ +-#define PM_RSTS_RASPBERRYPI_HALT 0x555 ++#define PM_RSTS_PARTITION_CLR 0xfffffaaa + + #define SECS_TO_WDOG_TICKS(x) ((x) << 16) + #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) +@@ -111,15 +105,28 @@ static struct watchdog_device bcm2835_wdt_wdd = { + .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), + }; + +-static int +-bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) ++/* ++ * The Raspberry Pi firmware uses the RSTS register to know which partiton ++ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. ++ * Partiton 63 is a special partition used by the firmware to indicate halt. ++ */ ++ ++static void bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition) + { +- struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, +- restart_handler); +- u32 val; ++ u32 val, rsts; ++ ++ rsts = (partition & BIT(0)) | ((partition & BIT(1)) << 1) | ++ ((partition & BIT(2)) << 2) | ((partition & BIT(3)) << 3) | ++ ((partition & BIT(4)) << 4) | ((partition & BIT(5)) << 5); ++ ++ val = readl_relaxed(wdt->base + PM_RSTS); ++ val &= PM_RSTS_PARTITION_CLR; ++ val |= PM_PASSWORD | rsts; ++ writel_relaxed(val, wdt->base + PM_RSTS); + + /* use a timeout of 10 ticks (~150us) */ + writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG); ++ + val = readl_relaxed(wdt->base + PM_RSTC); + val &= PM_RSTC_WRCFG_CLR; + val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; +@@ -127,6 +134,20 @@ bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) + + /* No sleeping, possibly atomic. */ + mdelay(1); ++} ++ ++static int bcm2835_restart_notifier_call(struct notifier_block *this, ++ unsigned long mode, void *cmd) ++{ ++ struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, ++ restart_handler); ++ unsigned long long val; ++ u8 partition = 0; ++ ++ if (cmd && !kstrtoull(cmd, 0, &val) && val <= 63) ++ partition = val; ++ ++ bcm2835_restart(wdt, partition); + + return 0; + } +@@ -142,19 +163,9 @@ static void bcm2835_power_off(void) + of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt"); + struct platform_device *pdev = of_find_device_by_node(np); + struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); +- u32 val; +- +- /* +- * We set the watchdog hard reset bit here to distinguish this reset +- * from the normal (full) reset. bootcode.bin will not reboot after a +- * hard reset. +- */ +- val = readl_relaxed(wdt->base + PM_RSTS); +- val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT; +- writel_relaxed(val, wdt->base + PM_RSTS); + +- /* Continue with normal reset mechanism */ +- bcm2835_restart(&wdt->restart_handler, REBOOT_HARD, NULL); ++ /* Partition 63 tells the firmware that this is a halt */ ++ bcm2835_restart(wdt, 63); + } + + static int bcm2835_wdt_probe(struct platform_device *pdev) +@@ -188,7 +199,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) + return err; + } + +- wdt->restart_handler.notifier_call = bcm2835_restart; ++ wdt->restart_handler.notifier_call = bcm2835_restart_notifier_call; + wdt->restart_handler.priority = 128; + register_restart_handler(&wdt->restart_handler); + if (pm_power_off == NULL) + +From 126d1c9c30b84709d3df1c9ee6951925ef86e561 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 5 Apr 2016 19:40:12 +0100 +Subject: [PATCH 024/111] reboot: Use power off rather than busy spinning when + halt is requested + +--- + arch/arm/kernel/reboot.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c +index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e00fb59a19 100644 +--- a/arch/arm/kernel/reboot.c ++++ b/arch/arm/kernel/reboot.c +@@ -102,9 +102,7 @@ void machine_shutdown(void) + */ + void machine_halt(void) + { +- local_irq_disable(); +- smp_send_stop(); +- while (1); ++ machine_power_off(); + } + + /* + +From 369132293cbf3404c2f12567f36c72745442d1a7 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 9 Nov 2016 13:02:52 +0000 +Subject: [PATCH 025/111] bcm: Make RASPBERRYPI_POWER depend on PM + +--- + drivers/soc/bcm/Kconfig | 1 + + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig -index a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226..7d11a44f36d2e6f8697773cd49a72e53bca3a5a0 100644 +index a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226..e037a6dd79d1881a09e3ca911578270917888846 100644 --- a/drivers/soc/bcm/Kconfig +++ b/drivers/soc/bcm/Kconfig -@@ -2,7 +2,7 @@ menu "Broadcom SoC drivers" - - config RASPBERRYPI_POWER +@@ -4,6 +4,7 @@ config RASPBERRYPI_POWER bool "Raspberry Pi power domain driver" -- depends on ARCH_BCM2835 || (COMPILE_TEST && OF) -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || (COMPILE_TEST && OF) + depends on ARCH_BCM2835 || (COMPILE_TEST && OF) depends on RASPBERRYPI_FIRMWARE=y ++ depends on PM select PM_GENERIC_DOMAINS if PM help + This enables support for the RPi power domains which can be enabled -From d2a8c66431d4a830d84aa61337e7cf75f7263e7a Mon Sep 17 00:00:00 2001 +From 4f1f33c99707022e920996b81d2394e8a67d72cc Mon Sep 17 00:00:00 2001 +From: Martin Sperl +Date: Fri, 2 Sep 2016 16:45:27 +0100 +Subject: [PATCH 026/111] Register the clocks early during the boot process, so + that special/critical clocks can get enabled early on in the boot process + avoiding the risk of disabling a clock, pll_divider or pll when a claiming + driver fails to install propperly - maybe it needs to defer. + +Signed-off-by: Martin Sperl +--- + drivers/clk/bcm/clk-bcm2835.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index a73f0873b7b8f78bc4a70f01e17eb287eec1d9e3..56fd47891e50dddcf83e687f1d53aeb46d85a7b2 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1901,8 +1901,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + if (ret) + return ret; + +- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, ++ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + &cprman->onecell); ++ if (ret) ++ return ret; ++ ++ /* note that we have registered all the clocks */ ++ dev_dbg(dev, "registered %d clocks\n", asize); ++ ++ return 0; + } + + static const struct of_device_id bcm2835_clk_of_match[] = { +@@ -1919,7 +1926,11 @@ static struct platform_driver bcm2835_clk_driver = { + .probe = bcm2835_clk_probe, + }; + +-builtin_platform_driver(bcm2835_clk_driver); ++static int __init __bcm2835_clk_driver_init(void) ++{ ++ return platform_driver_register(&bcm2835_clk_driver); ++} ++core_initcall(__bcm2835_clk_driver_init); + + MODULE_AUTHOR("Eric Anholt "); + MODULE_DESCRIPTION("BCM2835 clock driver"); + +From 007bca50057b289594959c0b3a40f697042de092 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 6 Dec 2016 17:05:39 +0000 +Subject: [PATCH 027/111] bcm2835-rng: Avoid initialising if already enabled + +Avoids the 0x40000 cycles of warmup again if firmware has already used it +--- + drivers/char/hw_random/bcm2835-rng.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c +index 574211a495491d9d6021dcaefe4274a63ed02055..e66c0fca8c6090e32f72796c0877a1cf1d499fb6 100644 +--- a/drivers/char/hw_random/bcm2835-rng.c ++++ b/drivers/char/hw_random/bcm2835-rng.c +@@ -102,9 +102,10 @@ static int bcm2835_rng_probe(struct platform_device *pdev) + rng_setup(rng_base); + + /* set warm-up count & enable */ +- __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); +- __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); +- ++ if (!(__raw_readl(rng_base + RNG_CTRL) & RNG_RBGEN)) { ++ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); ++ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); ++ } + /* register driver */ + err = hwrng_register(&bcm2835_rng_ops); + if (err) { + +From ea730ebfa6c5a592f2085c3ed4b5ba73b65344e0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 24 Aug 2016 16:28:44 +0100 +Subject: [PATCH 028/111] kbuild: Ignore dtco targets when filtering symbols + +--- + scripts/Kbuild.include | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include +index 179219845dfcdfbeb586d12c5ec1296095d9fbf4..e0743e44f84188667a0c322e8c3d36f18385dcd3 100644 +--- a/scripts/Kbuild.include ++++ b/scripts/Kbuild.include +@@ -284,7 +284,7 @@ ksym_dep_filter = \ + $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ + as_*_S|cpp_s_S) \ + $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ +- boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ ++ boot*|build*|*cpp_lds_S|dtc*|host*|vdso*) : ;; \ + *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ + esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' + + +From bacce62ef301d1ac7882ecdfeaa3289a597c65cc Mon Sep 17 00:00:00 2001 +From: Robert Tiemann +Date: Mon, 20 Jul 2015 11:01:25 +0200 +Subject: [PATCH 029/111] BCM2835_DT: Fix I2S register map + +--- + Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- + Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +index baf9b34d20bfb5b5493e0a69841362530c900a77..11c052acf65e74f032ae77bfd2749db860762b2d 100644 +--- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt ++++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +@@ -74,8 +74,8 @@ Example: + + bcm2835_i2s: i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; +- reg = < 0x7e203000 0x20>, +- < 0x7e101098 0x02>; ++ reg = < 0x7e203000 0x24>, ++ < 0x7e101098 0x08>; + + dmas = <&dma 2>, + <&dma 3>; +diff --git a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt +index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554427118a2 100644 +--- a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt ++++ b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt +@@ -16,8 +16,8 @@ Example: + + bcm2835_i2s: i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; +- reg = <0x7e203000 0x20>, +- <0x7e101098 0x02>; ++ reg = <0x7e203000 0x24>, ++ <0x7e101098 0x08>; + + dmas = <&dma 2>, + <&dma 3>; + +From 83e431a4170b965b12737d9fd9828b224f0b5dc3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 031/208] Main bcm2708/bcm2709 linux port +Subject: [PATCH 030/111] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 49 +++ - arch/arm/Kconfig.debug | 8 + - arch/arm/Makefile | 2 + - arch/arm/kernel/head.S | 8 + - arch/arm/kernel/process.c | 10 + - arch/arm/mach-bcm2708/Kconfig | 23 ++ - arch/arm/mach-bcm2708/Makefile | 5 + - arch/arm/mach-bcm2708/Makefile.boot | 3 + - arch/arm/mach-bcm2708/bcm2708.c | 231 ++++++++++++ - arch/arm/mach-bcm2708/include/mach/debug-macro.S | 22 ++ - arch/arm/mach-bcm2708/include/mach/io.h | 27 ++ - arch/arm/mach-bcm2708/include/mach/memory.h | 57 +++ - arch/arm/mach-bcm2708/include/mach/platform.h | 112 ++++++ - arch/arm/mach-bcm2708/include/mach/system.h | 37 ++ - arch/arm/mach-bcm2708/include/mach/uncompress.h | 84 +++++ - arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 ++ - arch/arm/mach-bcm2709/Kconfig | 16 + - arch/arm/mach-bcm2709/Makefile | 5 + - arch/arm/mach-bcm2709/Makefile.boot | 3 + - arch/arm/mach-bcm2709/bcm2709.c | 380 ++++++++++++++++++++ - arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 ++ - arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 +++++++ - arch/arm/mach-bcm2709/include/mach/io.h | 27 ++ - arch/arm/mach-bcm2709/include/mach/memory.h | 57 +++ - arch/arm/mach-bcm2709/include/mach/platform.h | 188 ++++++++++ - arch/arm/mach-bcm2709/include/mach/system.h | 37 ++ - arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 +++++ - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 ++ - arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 ++ - arch/arm/mach-bcm2709/vc_mem.c | 431 +++++++++++++++++++++++ - arch/arm/mm/proc-v6.S | 15 +- - arch/arm/tools/mach-types | 2 + - drivers/clocksource/Makefile | 2 +- - drivers/irqchip/Makefile | 3 + - drivers/irqchip/irq-bcm2835.c | 7 +- - include/linux/mmc/host.h | 1 + - 36 files changed, 2151 insertions(+), 5 deletions(-) - create mode 100644 arch/arm/mach-bcm2708/Kconfig - create mode 100644 arch/arm/mach-bcm2708/Makefile - create mode 100644 arch/arm/mach-bcm2708/Makefile.boot - create mode 100644 arch/arm/mach-bcm2708/bcm2708.c - create mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2708/include/mach/io.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/system.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2709/Kconfig - create mode 100644 arch/arm/mach-bcm2709/Makefile - create mode 100644 arch/arm/mach-bcm2709/Makefile.boot - create mode 100644 arch/arm/mach-bcm2709/bcm2709.c - create mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/io.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/system.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2709/vc_mem.c -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index a9c4e48bb7ec997bec394066914d26f337a2fec4..018ee76322d9e013598887c50ebea9628ecb9ee3 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -326,6 +326,52 @@ choice - default ARM_SINGLE_ARMV7M if !MMU - default ARCH_MULTIPLATFORM if MMU +bcm2709: Drop platform smp and timer init code + +irq-bcm2836 handles this through these functions: +bcm2835_init_local_timer_frequency() +bcm2836_arm_irqchip_smp_init() + +Signed-off-by: Noralf Trønnes + +bcm270x: Use watchdog for reboot/poweroff + +The watchdog driver already has support for reboot/poweroff. +Make use of this and remove the code from the platform files. + +Signed-off-by: Noralf Trønnes +--- + arch/arm/mach-bcm/Kconfig | 1 + + arch/arm/mach-bcm/board_bcm2835.c | 17 +++++++++++++++++ + arch/arm/mm/proc-v6.S | 15 ++++++++++++--- + drivers/irqchip/irq-bcm2835.c | 7 ++++++- + drivers/mailbox/bcm2835-mailbox.c | 18 ++++++++++++++++-- + 5 files changed, 52 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig +index 4ff30d5278a7ce093c9629d4c25d37e3bbbda752..333dc3c2e5ffbb2c5ab8fcfb6115b6162643cf20 100644 +--- a/arch/arm/mach-bcm/Kconfig ++++ b/arch/arm/mach-bcm/Kconfig +@@ -155,6 +155,7 @@ config ARCH_BCM2835 + select FIQ + select PINCTRL + select PINCTRL_BCM2835 ++ select MFD_SYSCON if ARCH_MULTI_V7 + help + This enables support for the Broadcom BCM2835 and BCM2836 SoCs. + This SoC is used in the Raspberry Pi and Roku 2 devices. +diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c +index 8f152266ba9b470df2eaaed9ebcf158ed2079834..133338f0a21237fda9b7660d2c57a33b991f08ae 100644 +--- a/arch/arm/mach-bcm/board_bcm2835.c ++++ b/arch/arm/mach-bcm/board_bcm2835.c +@@ -16,17 +16,21 @@ + #include + #include + #include ++#include + #include -+config ARCH_BCM2708 -+ bool "Broadcom BCM2708 family" -+ select CPU_V6 -+ select ARM_AMBA -+ select CLKSRC_MMIO -+ select CLKSRC_OF if OF -+ select HAVE_SCHED_CLOCK -+ select NEED_MACH_GPIO_H -+ select NEED_MACH_MEMORY_H -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select ARM_ERRATA_411920 -+ select MACH_BCM2708 -+ select MULTI_IRQ_HANDLER -+ select SPARSE_IRQ -+ select VC4 -+ select FIQ -+ help -+ This enables support for Broadcom BCM2708 boards. + #include + #include + ++#include + -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ select CPU_V7 -+ select HAVE_SMP -+ select ARM_AMBA -+ select MIGHT_HAVE_CACHE_L2X0 -+ select HAVE_SCHED_CLOCK -+ select NEED_MACH_MEMORY_H -+ select NEED_MACH_IO_H -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select MACH_BCM2709 -+ select MULTI_IRQ_HANDLER -+ select SPARSE_IRQ -+ select MFD_SYSCON -+ select VC4 -+ select FIQ -+ select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - config ARCH_MULTIPLATFORM - bool "Allow multiple platforms to be selected" - depends on MMU -@@ -711,6 +757,9 @@ config ARCH_VIRT - # Kconfigs may be included either alphabetically (according to the - # plat- suffix) or along side the corresponding mach-* source. - # -+source "arch/arm/mach-bcm2708/Kconfig" -+source "arch/arm/mach-bcm2709/Kconfig" -+ - source "arch/arm/mach-mvebu/Kconfig" + static void __init bcm2835_init(void) + { + struct device_node *np = of_find_node_by_path("/system"); + u32 val; + u64 val64; - source "arch/arm/mach-alpine/Kconfig" -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index a9693b6987a6e41c69702f1003d0d8bd2279530e..f47f4e70395635fafeacd680c4392cc51660ea8e 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -1312,6 +1312,14 @@ choice - options; the platform specific options are deprecated - and will be soon removed. ++ vc_cma_early_init(); + bcm2835_init_clocks(); -+ config DEBUG_BCM2708_UART0 -+ bool "Broadcom BCM270X UART0 (PL011)" -+ depends on ARCH_BCM2708 || ARCH_BCM2709 -+ help -+ Say Y here if you want the debug print routines to direct -+ their output to UART 0. The port must have been initialised -+ by the boot-loader before use. -+ - endchoice - - config DEBUG_AT91_UART -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 61f6ccc19cfa94364e777cc68d10ce5a24093c0f..d1e45094ab4338f95dab09e81d358cd723f5eb3d 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -152,6 +152,8 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 - - # Machine directory name. This list is sorted alphanumerically - # by CONFIG_* macro name. -+machine-$(CONFIG_ARCH_BCM2708) += bcm2708 -+machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_ALPINE) += alpine - machine-$(CONFIG_ARCH_ARTPEC) += artpec - machine-$(CONFIG_ARCH_AT91) += at91 -diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S -index 04286fd9e09ce7a27259c4d375a05a965e3be0ea..ed826280e744828ebb1c5ae6b7a62d70f28c1429 100644 ---- a/arch/arm/kernel/head.S -+++ b/arch/arm/kernel/head.S -@@ -700,6 +700,14 @@ ARM_BE8(rev16 ip, ip) - ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 1b - ret lr -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop - #endif - ENDPROC(__fixup_a_pv_table) - -diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 612eb530f33fcd19bc4539facb26fc30a2583979..0a0332cb13a7475ee0c4d75a97685b7de6475c95 100644 ---- a/arch/arm/kernel/process.c -+++ b/arch/arm/kernel/process.c -@@ -91,6 +91,16 @@ void arch_cpu_idle_exit(void) - ledtrig_cpu(CPU_LED_IDLE_END); + if (!of_property_read_u32(np, "linux,revision", &val)) +@@ -35,6 +39,17 @@ static void __init bcm2835_init(void) + system_serial_low = val64; } -+char bcm2708_reboot_mode = 'h'; -+ -+int __init reboot_setup(char *str) ++static void __init bcm2835_init_early(void) +{ -+ bcm2708_reboot_mode = str[0]; -+ return 1; ++ /* dwc_otg needs this for bounce buffers on non-aligned transfers */ ++ init_dma_coherent_pool_size(SZ_1M); +} + -+__setup("reboot=", reboot_setup); -+ - void __show_regs(struct pt_regs *regs) - { - unsigned long flags; -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..6eabe844767f7fa9bdc09a897bab83e5149fc0dd ---- /dev/null -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -0,0 +1,23 @@ -+menu "Broadcom BCM2708 Implementations" -+ depends on ARCH_BCM2708 -+ -+config MACH_BCM2708 -+ bool "Broadcom BCM2708 Development Platform" -+ select NEED_MACH_MEMORY_H -+ select NEED_MACH_IO_H -+ select CPU_V6 -+ select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 -+ help -+ Include support for the Broadcom(R) BCM2708 platform. -+ -+config BCM2708_NOL2CACHE -+ bool "Videocore L2 cache disable" -+ depends on MACH_BCM2708 -+ default n -+ help -+ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -+ -+endmenu -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..3da1a1b4ea1fb04ae0b535b2915ea9f386f5701c ---- /dev/null -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -0,0 +1,5 @@ -+# -+# Makefile for the linux kernel. -+# -+ -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o -diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot -new file mode 100644 -index 0000000000000000000000000000000000000000..67039c3e0c48fa6b94f1147b3316f74afcecba9e ---- /dev/null -+++ b/arch/arm/mach-bcm2708/Makefile.boot -@@ -0,0 +1,3 @@ -+ zreladdr-y := 0x00008000 -+params_phys-y := 0x00000100 -+initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -new file mode 100644 -index 0000000000000000000000000000000000000000..280628ba8907d2a4323fc86dfc6db7fc684aeabc ---- /dev/null -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -0,0 +1,231 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/bcm2708.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -+ * give us IO access only to 64Mbytes of physical memory (26 bits). We could -+ * represent this window by setting our dmamasks to 26 bits but, in fact -+ * we're not going to use addresses outside this range (they're not in real -+ * memory) so we don't bother. -+ * -+ * In the future we might include code to use this IOMMU to remap other -+ * physical addresses onto VideoCore memory then the use of 32-bits would be -+ * more legitimate. -+ */ -+ -+/* command line parameters */ -+static unsigned boardrev, serial; -+static unsigned reboot_part = 0; -+ -+static struct map_desc bcm2708_io_desc[] __initdata = { -+ { -+ .virtual = IO_ADDRESS(ARMCTRL_BASE), -+ .pfn = __phys_to_pfn(ARMCTRL_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART0_BASE), -+ .pfn = __phys_to_pfn(UART0_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART1_BASE), -+ .pfn = __phys_to_pfn(UART1_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(DMA_BASE), -+ .pfn = __phys_to_pfn(DMA_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(MCORE_BASE), -+ .pfn = __phys_to_pfn(MCORE_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(ST_BASE), -+ .pfn = __phys_to_pfn(ST_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(USB_BASE), -+ .pfn = __phys_to_pfn(USB_BASE), -+ .length = SZ_128K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(PM_BASE), -+ .pfn = __phys_to_pfn(PM_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(GPIO_BASE), -+ .pfn = __phys_to_pfn(GPIO_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE} -+}; -+ -+void __init bcm2708_map_io(void) -+{ -+ iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); -+} -+ -+int calc_rsts(int partition) -+{ -+ return PM_PASSWORD | -+ ((partition & (1 << 0)) << 0) | -+ ((partition & (1 << 1)) << 1) | -+ ((partition & (1 << 2)) << 2) | -+ ((partition & (1 << 3)) << 3) | -+ ((partition & (1 << 4)) << 4) | -+ ((partition & (1 << 5)) << 5); -+} -+ -+static void bcm2708_restart(enum reboot_mode mode, const char *cmd) -+{ -+ extern char bcm2708_reboot_mode; -+ uint32_t pm_rstc, pm_wdog; -+ uint32_t timeout = 10; -+ uint32_t pm_rsts = 0; -+ -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < 1.3 booting with reboot=q -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -+ } -+ else if(bcm2708_reboot_mode == 'p') -+ { -+ // NOOBS < 1.3 halting -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -+ } -+ else -+ { -+ pm_rsts = calc_rsts(reboot_part); -+ } -+ -+ writel(pm_rsts, __io_address(PM_RSTS)); -+ -+ /* Setup watchdog for reset */ -+ pm_rstc = readl(__io_address(PM_RSTC)); -+ -+ pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -+ pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -+ -+ writel(pm_wdog, __io_address(PM_WDOG)); -+ writel(pm_rstc, __io_address(PM_RSTC)); -+} -+ -+/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ -+static void bcm2708_power_off(void) -+{ -+ extern char bcm2708_reboot_mode; -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < v1.3 -+ bcm2708_restart('p', ""); -+ } -+ else -+ { -+ /* partition 63 is special code for HALT the bootloader knows not to boot*/ -+ reboot_part = 63; -+ /* continue with normal reset mechanism */ -+ bcm2708_restart(0, ""); -+ } -+} -+ -+static void __init bcm2708_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2708: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ -+void __init bcm2708_init(void) -+{ -+ int ret; -+ -+ vc_cma_early_init(); -+ -+ pm_power_off = bcm2708_power_off; -+ -+ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -+ NULL); -+ if (ret) { -+ pr_err("of_platform_populate failed: %d\n", ret); -+ BUG(); -+ } -+ -+ bcm2708_init_uart1(); -+ -+ system_rev = boardrev; -+ system_serial_low = serial; -+} -+ -+void __init bcm2708_init_early(void) -+{ -+ /* -+ * Some devices allocate their coherent buffers from atomic -+ * context. Increase size of atomic coherent pool to make sure such -+ * the allocations won't fail. -+ */ -+ init_dma_coherent_pool_size(SZ_4M); -+} -+ -+static void __init board_reserve(void) ++static void __init bcm2835_board_reserve(void) +{ + vc_cma_reserve(); +} + -+static const char * const bcm2708_compat[] = { -+ "brcm,bcm2708", -+ NULL -+}; -+ -+MACHINE_START(BCM2708, "BCM2708") -+ /* Maintainer: Broadcom Europe Ltd. */ -+ .map_io = bcm2708_map_io, -+ .init_machine = bcm2708_init, -+ .init_early = bcm2708_init_early, -+ .reserve = board_reserve, -+ .restart = bcm2708_restart, -+ .dt_compat = bcm2708_compat, -+MACHINE_END -+ -+module_param(boardrev, uint, 0644); -+module_param(serial, uint, 0644); -+module_param(reboot_part, uint, 0644); -diff --git a/arch/arm/mach-bcm2708/include/mach/debug-macro.S b/arch/arm/mach-bcm2708/include/mach/debug-macro.S -new file mode 100644 -index 0000000000000000000000000000000000000000..b24304a6755e965b8a28eb048b7f4e2d868820f9 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/debug-macro.S -@@ -0,0 +1,22 @@ -+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -+ * -+ * Debugging macro include header -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 1994-1999 Russell King -+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+*/ -+ -+#include -+ -+ .macro addruart, rp, rv, tmp -+ ldr \rp, =UART0_BASE -+ ldr \rv, =IO_ADDRESS(UART0_BASE) -+ .endm -+ -+#include -diff --git a/arch/arm/mach-bcm2708/include/mach/io.h b/arch/arm/mach-bcm2708/include/mach/io.h -new file mode 100644 -index 0000000000000000000000000000000000000000..e6eb84d71006db417dbd0afc4d08d3b19b09a619 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/io.h -@@ -0,0 +1,27 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/io.h -+ * -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARM_ARCH_IO_H -+#define __ASM_ARM_ARCH_IO_H -+ -+#define IO_SPACE_LIMIT 0xffffffff -+ -+#define __io(a) __typesafe_io(a) -+ -+#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/memory.h b/arch/arm/mach-bcm2708/include/mach/memory.h -new file mode 100644 -index 0000000000000000000000000000000000000000..7548a52dcf84affa4d1b0667e5e2f89f591891b8 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/memory.h -@@ -0,0 +1,57 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/memory.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_MEMORY_H -+#define __ASM_ARCH_MEMORY_H -+ -+/* Memory overview: -+ -+ [ARMcore] <--virtual addr--> -+ [ARMmmu] <--physical addr--> -+ [GERTmap] <--bus add--> -+ [VCperiph] -+ -+*/ -+ -+/* -+ * Physical DRAM offset. -+ */ -+#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) -+#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -+ -+#ifdef CONFIG_BCM2708_NOL2CACHE -+ #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ -+#else -+ #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ -+#endif -+ -+/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -+ * will provide the offset into this area as well as setting the bits that -+ * stop the L1 and L2 cache from being used -+ * -+ * WARNING: this only works because the ARM is given memory at a fixed location -+ * (ARMMEM_OFFSET) -+ */ -+#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) -+#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) -+#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) -+#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+ -+#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4fb43cf391e50e702d0a0588ceff397c79c501d7 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -0,0 +1,112 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/platform.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _BCM2708_PLATFORM_H -+#define _BCM2708_PLATFORM_H -+ -+ -+/* macros to get at IO space when running virtually */ -+#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -+ -+#define __io_address(n) IOMEM(IO_ADDRESS(n)) -+ -+ -+/* -+ * SDRAM -+ */ -+#define BCM2708_SDRAM_BASE 0x00000000 -+ -+/* -+ * Logic expansion modules -+ * -+ */ -+ -+ -+/* ------------------------------------------------------------------------ -+ * BCM2708 ARMCTRL Registers -+ * ------------------------------------------------------------------------ -+ */ -+ -+#define HW_REGISTER_RW(addr) (addr) -+#define HW_REGISTER_RO(addr) (addr) -+ -+/* -+ * Definitions and addresses for the ARM CONTROL logic -+ * This file is manually generated. -+ */ -+ -+#define BCM2708_PERI_BASE 0x20000000 -+#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) -+#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ -+#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ -+#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ -+#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ -+#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ -+#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ -+#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ -+#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ -+#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ -+#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ -+#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ -+#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ -+#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ -+#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ -+#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ -+#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ -+#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ -+#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ -+#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -+ -+#define ARMCTRL_BASE (ARM_BASE + 0x000) -+#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ -+#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ -+#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+ -+/* -+ * Watchdog -+ */ -+#define PM_RSTC (PM_BASE+0x1c) -+#define PM_RSTS (PM_BASE+0x20) -+#define PM_WDOG (PM_BASE+0x24) -+ -+#define PM_WDOG_RESET 0000000000 -+#define PM_PASSWORD 0x5a000000 -+#define PM_WDOG_TIME_SET 0x000fffff -+#define PM_RSTC_WRCFG_CLR 0xffffffcf -+#define PM_RSTC_WRCFG_SET 0x00000030 -+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -+#define PM_RSTC_RESET 0x00000102 -+ -+#define PM_RSTS_HADPOR_SET 0x00001000 -+#define PM_RSTS_HADSRH_SET 0x00000400 -+#define PM_RSTS_HADSRF_SET 0x00000200 -+#define PM_RSTS_HADSRQ_SET 0x00000100 -+#define PM_RSTS_HADWRH_SET 0x00000040 -+#define PM_RSTS_HADWRF_SET 0x00000020 -+#define PM_RSTS_HADWRQ_SET 0x00000010 -+#define PM_RSTS_HADDRH_SET 0x00000004 -+#define PM_RSTS_HADDRF_SET 0x00000002 -+#define PM_RSTS_HADDRQ_SET 0x00000001 -+ -+#define UART0_CLOCK 3000000 -+ -+#endif -+ -+/* END */ -diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h -new file mode 100644 -index 0000000000000000000000000000000000000000..c9a9c9a881102c5354971d15203a746906761a70 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/system.h -@@ -0,0 +1,37 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/system.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * Copyright (C) 2000 Deep Blue Solutions Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_SYSTEM_H -+#define __ASM_ARCH_SYSTEM_H -+ -+#include -+#include -+ -+static inline void arch_idle(void) -+{ -+ /* -+ * This should do all the clock switching -+ * and wait for interrupt tricks -+ */ -+ cpu_do_idle(); -+} -+ -+#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/uncompress.h b/arch/arm/mach-bcm2708/include/mach/uncompress.h -new file mode 100644 -index 0000000000000000000000000000000000000000..de7504bfc20ba24be8707861b8389783860adb77 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/uncompress.h -@@ -0,0 +1,84 @@ -+/* -+ * arch/arm/mach-bcn2708/include/mach/uncompress.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+ -+#define UART_BAUD 115200 -+ -+#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) -+#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) -+#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) -+#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) -+#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) -+#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -+ -+/* -+ * This does not append a newline -+ */ -+static inline void putc(int c) -+{ -+ while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -+ barrier(); -+ -+ __raw_writel(c, BCM2708_UART_DR); -+} -+ -+static inline void flush(void) -+{ -+ int fr; -+ -+ do { -+ fr = __raw_readl(BCM2708_UART_FR); -+ barrier(); -+ } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); -+} -+ -+static inline void arch_decomp_setup(void) -+{ -+ int temp, div, rem, frac; -+ -+ temp = 16 * UART_BAUD; -+ div = UART0_CLOCK / temp; -+ rem = UART0_CLOCK % temp; -+ temp = (8 * rem) / UART_BAUD; -+ frac = (temp >> 1) + (temp & 1); -+ -+ /* Make sure the UART is disabled before we start */ -+ __raw_writel(0, BCM2708_UART_CR); -+ -+ /* Set the baud rate */ -+ __raw_writel(div, BCM2708_UART_IBRD); -+ __raw_writel(frac, BCM2708_UART_FBRD); -+ -+ /* Set the UART to 8n1, FIFO enabled */ -+ __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -+ -+ /* Enable the UART */ -+ __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -+ BCM2708_UART_CR); -+} -+ -+/* -+ * nothing to do -+ */ -+#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h -new file mode 100644 -index 0000000000000000000000000000000000000000..502c6178101be60b10c9eb31afec938b5534c33f ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/vmalloc.h -@@ -0,0 +1,20 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vmalloc.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#define VMALLOC_END (0xe8000000) -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..643b4b984512a5f2ae33cee9beffa70a53e005ff ---- /dev/null -+++ b/arch/arm/mach-bcm2709/Kconfig -@@ -0,0 +1,16 @@ -+menu "Broadcom BCM2709 Implementations" -+ depends on ARCH_BCM2709 -+ -+config MACH_BCM2709 -+ bool "Broadcom BCM2709 Development Platform" -+ help -+ Include support for the Broadcom(R) BCM2709 platform. -+ -+config BCM2708_NOL2CACHE -+ bool "Videocore L2 cache disable" -+ depends on MACH_BCM2709 -+ default y -+ help -+ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -+ -+endmenu -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..26cd67d3dc343dbd250fa97855a82c28bbd95af0 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -0,0 +1,5 @@ -+# -+# Makefile for the linux kernel. -+# -+ -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o -diff --git a/arch/arm/mach-bcm2709/Makefile.boot b/arch/arm/mach-bcm2709/Makefile.boot -new file mode 100644 -index 0000000000000000000000000000000000000000..67039c3e0c48fa6b94f1147b3316f74afcecba9e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/Makefile.boot -@@ -0,0 +1,3 @@ -+ zreladdr-y := 0x00008000 -+params_phys-y := 0x00000100 -+initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -new file mode 100644 -index 0000000000000000000000000000000000000000..90773a30b87abbfda1615326c6faf59b9db6d68e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -0,0 +1,380 @@ -+/* -+ * linux/arch/arm/mach-bcm2709/bcm2709.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+ -+/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -+ * give us IO access only to 64Mbytes of physical memory (26 bits). We could -+ * represent this window by setting our dmamasks to 26 bits but, in fact -+ * we're not going to use addresses outside this range (they're not in real -+ * memory) so we don't bother. -+ * -+ * In the future we might include code to use this IOMMU to remap other -+ * physical addresses onto VideoCore memory then the use of 32-bits would be -+ * more legitimate. -+ */ -+ -+/* command line parameters */ -+static unsigned boardrev, serial; -+static unsigned reboot_part = 0; -+ -+static struct map_desc bcm2709_io_desc[] __initdata = { -+ { -+ .virtual = IO_ADDRESS(ARMCTRL_BASE), -+ .pfn = __phys_to_pfn(ARMCTRL_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART0_BASE), -+ .pfn = __phys_to_pfn(UART0_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART1_BASE), -+ .pfn = __phys_to_pfn(UART1_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(DMA_BASE), -+ .pfn = __phys_to_pfn(DMA_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(MCORE_BASE), -+ .pfn = __phys_to_pfn(MCORE_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(ST_BASE), -+ .pfn = __phys_to_pfn(ST_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(USB_BASE), -+ .pfn = __phys_to_pfn(USB_BASE), -+ .length = SZ_128K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(PM_BASE), -+ .pfn = __phys_to_pfn(PM_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(GPIO_BASE), -+ .pfn = __phys_to_pfn(GPIO_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(ARM_LOCAL_BASE), -+ .pfn = __phys_to_pfn(ARM_LOCAL_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+}; -+ -+void __init bcm2709_map_io(void) -+{ -+ iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); -+} -+ -+int calc_rsts(int partition) -+{ -+ return PM_PASSWORD | -+ ((partition & (1 << 0)) << 0) | -+ ((partition & (1 << 1)) << 1) | -+ ((partition & (1 << 2)) << 2) | -+ ((partition & (1 << 3)) << 3) | -+ ((partition & (1 << 4)) << 4) | -+ ((partition & (1 << 5)) << 5); -+} -+ -+static void bcm2709_restart(enum reboot_mode mode, const char *cmd) -+{ -+ extern char bcm2708_reboot_mode; -+ uint32_t pm_rstc, pm_wdog; -+ uint32_t timeout = 10; -+ uint32_t pm_rsts = 0; -+ -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < 1.3 booting with reboot=q -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -+ } -+ else if(bcm2708_reboot_mode == 'p') -+ { -+ // NOOBS < 1.3 halting -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -+ } -+ else -+ { -+ pm_rsts = calc_rsts(reboot_part); -+ } -+ -+ writel(pm_rsts, __io_address(PM_RSTS)); -+ -+ /* Setup watchdog for reset */ -+ pm_rstc = readl(__io_address(PM_RSTC)); -+ -+ pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -+ pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -+ -+ writel(pm_wdog, __io_address(PM_WDOG)); -+ writel(pm_rstc, __io_address(PM_RSTC)); -+} -+ -+/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ -+static void bcm2709_power_off(void) -+{ -+ extern char bcm2708_reboot_mode; -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < v1.3 -+ bcm2709_restart('p', ""); -+ } -+ else -+ { -+ /* partition 63 is special code for HALT the bootloader knows not to boot*/ -+ reboot_part = 63; -+ /* continue with normal reset mechanism */ -+ bcm2709_restart(0, ""); -+ } -+} -+ -+static void __init bcm2709_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2709: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ -+void __init bcm2709_init(void) -+{ -+ int ret; -+ -+ vc_cma_early_init(); -+ -+ pm_power_off = bcm2709_power_off; -+ -+ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -+ NULL); -+ if (ret) { -+ pr_err("of_platform_populate failed: %d\n", ret); -+ BUG(); -+ } -+ -+ bcm2709_init_uart1(); -+ -+ system_rev = boardrev; -+ system_serial_low = serial; -+} -+ -+static void __init bcm2709_timer_init(void) -+{ -+ // timer control -+ writel(0, __io_address(ARM_LOCAL_CONTROL)); -+ // timer pre_scaler -+ writel(0x80000000, __io_address(ARM_LOCAL_PRESCALER)); // 19.2MHz -+ //writel(0x06AAAAAB, __io_address(ARM_LOCAL_PRESCALER)); // 1MHz -+ -+ of_clk_init(NULL); -+ clocksource_probe(); -+} -+ -+ -+void __init bcm2709_init_early(void) -+{ -+ /* -+ * Some devices allocate their coherent buffers from atomic -+ * context. Increase size of atomic coherent pool to make sure such -+ * the allocations won't fail. -+ */ -+ init_dma_coherent_pool_size(SZ_4M); -+} -+ -+static void __init board_reserve(void) -+{ -+ vc_cma_reserve(); -+} -+ -+ -+#ifdef CONFIG_SMP -+#include -+ -+#include -+#include -+int dc4=0; -+//void dc4_log(unsigned x) { if (dc4) writel((x), __io_address(ST_BASE+10 + raw_smp_processor_id()*4)); } -+void dc4_log_dead(unsigned x) { if (dc4) writel((readl(__io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)) & 0xffff) | ((x)<<16), __io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)); } -+ -+static void bcm2835_send_doorbell(const struct cpumask *mask, unsigned int irq) -+{ -+ int cpu; -+ /* -+ * Ensure that stores to Normal memory are visible to the -+ * other CPUs before issuing the IPI. -+ */ -+ dsb(); -+ -+ /* Convert our logical CPU mask into a physical one. */ -+ for_each_cpu(cpu, mask) -+ { -+ /* submit softirq */ -+ writel(1<%x)\n", __FUNCTION__, (unsigned)virt_to_phys((void *)secondary_startup), (unsigned)__io_address(ST_BASE + 0x10)); -+ printk("[%s] ncores=%d\n", __FUNCTION__, ncores); -+ -+ for (i = 0; i < ncores; i++) { -+ set_cpu_possible(i, true); -+ /* enable IRQ (not FIQ) */ -+ writel(0x1, __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 0x4 * i)); -+ //writel(0xf, __io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 0x4 * i)); -+ } -+ set_smp_cross_call(bcm2835_send_doorbell); -+} -+ -+/* -+ * for arch/arm/kernel/smp.c:smp_prepare_cpus(unsigned int max_cpus) -+ */ -+void __init bcm2709_smp_prepare_cpus(unsigned int max_cpus) -+{ -+ //void __iomem *scu_base; -+ -+ printk("[%s] enter\n", __FUNCTION__); -+ //scu_base = scu_base_addr(); -+ //scu_enable(scu_base); -+} -+ -+/* -+ * for linux/arch/arm/kernel/smp.c:secondary_start_kernel(void) -+ */ -+void __init bcm2709_secondary_init(unsigned int cpu) -+{ -+ printk("[%s] enter cpu:%d\n", __FUNCTION__, cpu); -+ //gic_secondary_init(0); -+} -+ -+/* -+ * for linux/arch/arm/kernel/smp.c:__cpu_up(..) -+ */ -+int __init bcm2709_boot_secondary(unsigned int cpu, struct task_struct *idle) -+{ -+ void secondary_startup(void); -+ void *mbox_set = __io_address(ARM_LOCAL_MAILBOX3_SET0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -+ void *mbox_clr = __io_address(ARM_LOCAL_MAILBOX3_CLR0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -+ unsigned secondary_boot = (unsigned)virt_to_phys((void *)secondary_startup); -+ int timeout=20; -+ unsigned t = -1; -+ //printk("[%s] enter cpu:%d (%x->%p) %x\n", __FUNCTION__, cpu, secondary_boot, wake, readl(wake)); -+ -+ dsb(); -+ BUG_ON(readl(mbox_clr) != 0); -+ writel(secondary_boot, mbox_set); -+ -+ while (--timeout > 0) { -+ t = readl(mbox_clr); -+ if (t == 0) break; -+ cpu_relax(); -+ } -+ if (timeout==0) -+ printk("[%s] cpu:%d failed to start (%x)\n", __FUNCTION__, cpu, t); -+ else -+ printk("[%s] cpu:%d started (%x) %d\n", __FUNCTION__, cpu, t, timeout); -+ -+ return 0; -+} -+ -+ -+struct smp_operations bcm2709_smp_ops __initdata = { -+ .smp_init_cpus = bcm2709_smp_init_cpus, -+ .smp_prepare_cpus = bcm2709_smp_prepare_cpus, -+ .smp_secondary_init = bcm2709_secondary_init, -+ .smp_boot_secondary = bcm2709_boot_secondary, -+}; -+#endif -+ -+static const char * const bcm2709_compat[] = { -+ "brcm,bcm2709", -+ "brcm,bcm2708", /* Could use bcm2708 in a pinch */ -+ NULL -+}; -+ -+MACHINE_START(BCM2709, "BCM2709") -+ /* Maintainer: Broadcom Europe Ltd. */ -+#ifdef CONFIG_SMP -+ .smp = smp_ops(bcm2709_smp_ops), -+#endif -+ .map_io = bcm2709_map_io, -+ .init_time = bcm2709_timer_init, -+ .init_machine = bcm2709_init, -+ .init_early = bcm2709_init_early, -+ .reserve = board_reserve, -+ .restart = bcm2709_restart, -+ .dt_compat = bcm2709_compat, -+MACHINE_END -+ -+MACHINE_START(BCM2708, "BCM2709") -+ /* Maintainer: Broadcom Europe Ltd. */ -+#ifdef CONFIG_SMP -+ .smp = smp_ops(bcm2709_smp_ops), -+#endif -+ .map_io = bcm2709_map_io, -+ .init_time = bcm2709_timer_init, -+ .init_machine = bcm2709_init, -+ .init_early = bcm2709_init_early, -+ .reserve = board_reserve, -+ .restart = bcm2709_restart, -+ .dt_compat = bcm2709_compat, -+MACHINE_END -+ -+module_param(boardrev, uint, 0644); -+module_param(serial, uint, 0644); -+module_param(reboot_part, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/include/mach/debug-macro.S b/arch/arm/mach-bcm2709/include/mach/debug-macro.S -new file mode 100644 -index 0000000000000000000000000000000000000000..b24304a6755e965b8a28eb048b7f4e2d868820f9 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/debug-macro.S -@@ -0,0 +1,22 @@ -+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -+ * -+ * Debugging macro include header -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 1994-1999 Russell King -+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+*/ -+ -+#include -+ -+ .macro addruart, rp, rv, tmp -+ ldr \rp, =UART0_BASE -+ ldr \rv, =IO_ADDRESS(UART0_BASE) -+ .endm -+ -+#include -diff --git a/arch/arm/mach-bcm2709/include/mach/entry-macro.S b/arch/arm/mach-bcm2709/include/mach/entry-macro.S -new file mode 100644 -index 0000000000000000000000000000000000000000..d08591b63c1a1710c40350d343d3eddc97ae74c1 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/entry-macro.S -@@ -0,0 +1,123 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/entry-macro.S -+ * -+ * Low-level IRQ helper macros for BCM2708 platforms -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#include -+#include -+ -+ .macro disable_fiq -+ .endm -+ -+ .macro get_irqnr_preamble, base, tmp -+ ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) -+ .endm -+ -+ .macro arch_ret_to_user, tmp1, tmp2 -+ .endm -+ -+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -+ /* get core number */ -+ mrc p15, 0, \tmp, c0, c0, 5 -+ ubfx \tmp, \tmp, #0, #2 -+ -+ /* get core's local interrupt controller */ -+ ldr \irqstat, = __io_address(ARM_LOCAL_IRQ_PENDING0) @ local interrupt source -+ add \irqstat, \irqstat, \tmp, lsl #2 -+ ldr \tmp, [\irqstat] -+ /* ignore gpu interrupt */ -+ bic \tmp, #0x100 -+ /* ignore mailbox interrupts */ -+ bics \tmp, #0xf0 -+ beq 1005f -+ -+ @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -+ @ N.B. CLZ is an ARM5 instruction. -+ mov \irqnr, #(ARM_IRQ_LOCAL_BASE + 31) -+ sub \irqstat, \tmp, #1 -+ eor \irqstat, \irqstat, \tmp -+ clz \tmp, \irqstat -+ sub \irqnr, \tmp -+ b 1020f -+1005: -+ /* get core number */ -+ mrc p15, 0, \tmp, c0, c0, 5 -+ ubfx \tmp, \tmp, #0, #2 -+ -+ cmp \tmp, #1 -+ beq 1020f -+ cmp \tmp, #2 -+ beq 1020f -+ cmp \tmp, #3 -+ beq 1020f -+ -+ /* get masked status */ -+ ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] -+ mov \irqnr, #(ARM_IRQ0_BASE + 31) -+ and \tmp, \irqstat, #0x300 @ save bits 8 and 9 -+ /* clear bits 8 and 9, and test */ -+ bics \irqstat, \irqstat, #0x300 -+ bne 1010f -+ -+ tst \tmp, #0x100 -+ ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] -+ movne \irqnr, #(ARM_IRQ1_BASE + 31) -+ @ Mask out the interrupts also present in PEND0 - see SW-5809 -+ bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) -+ bicne \irqstat, #((1<<18) | (1<<19)) -+ bne 1010f -+ -+ tst \tmp, #0x200 -+ ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] -+ movne \irqnr, #(ARM_IRQ2_BASE + 31) -+ @ Mask out the interrupts also present in PEND0 - see SW-5809 -+ bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) -+ bicne \irqstat, #((1<<30)) -+ beq 1020f -+ -+1010: -+ @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -+ @ N.B. CLZ is an ARM5 instruction. -+ sub \tmp, \irqstat, #1 -+ eor \irqstat, \irqstat, \tmp -+ clz \tmp, \irqstat -+ sub \irqnr, \tmp -+ -+1020: @ EQ will be set if no irqs pending -+ -+ .endm -+ -+ .macro test_for_ipi, irqnr, irqstat, base, tmp -+ /* get core number */ -+ mrc p15, 0, \tmp, c0, c0, 5 -+ ubfx \tmp, \tmp, #0, #2 -+ /* get core's mailbox interrupt control */ -+ ldr \irqstat, = __io_address(ARM_LOCAL_MAILBOX0_CLR0) @ mbox_clr -+ add \irqstat, \irqstat, \tmp, lsl #4 -+ ldr \tmp, [\irqstat] -+ cmp \tmp, #0 -+ beq 1030f -+ clz \tmp, \tmp -+ rsb \irqnr, \tmp, #31 -+ mov \tmp, #1 -+ lsl \tmp, \irqnr -+ str \tmp, [\irqstat] @ clear interrupt source -+ dsb -+1030: @ EQ will be set if no irqs pending -+ .endm -diff --git a/arch/arm/mach-bcm2709/include/mach/io.h b/arch/arm/mach-bcm2709/include/mach/io.h -new file mode 100644 -index 0000000000000000000000000000000000000000..e6eb84d71006db417dbd0afc4d08d3b19b09a619 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/io.h -@@ -0,0 +1,27 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/io.h -+ * -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARM_ARCH_IO_H -+#define __ASM_ARM_ARCH_IO_H -+ -+#define IO_SPACE_LIMIT 0xffffffff -+ -+#define __io(a) __typesafe_io(a) -+ -+#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/memory.h b/arch/arm/mach-bcm2709/include/mach/memory.h -new file mode 100644 -index 0000000000000000000000000000000000000000..7548a52dcf84affa4d1b0667e5e2f89f591891b8 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/memory.h -@@ -0,0 +1,57 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/memory.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_MEMORY_H -+#define __ASM_ARCH_MEMORY_H -+ -+/* Memory overview: -+ -+ [ARMcore] <--virtual addr--> -+ [ARMmmu] <--physical addr--> -+ [GERTmap] <--bus add--> -+ [VCperiph] -+ -+*/ -+ -+/* -+ * Physical DRAM offset. -+ */ -+#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) -+#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -+ -+#ifdef CONFIG_BCM2708_NOL2CACHE -+ #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ -+#else -+ #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ -+#endif -+ -+/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -+ * will provide the offset into this area as well as setting the bits that -+ * stop the L1 and L2 cache from being used -+ * -+ * WARNING: this only works because the ARM is given memory at a fixed location -+ * (ARMMEM_OFFSET) -+ */ -+#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) -+#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) -+#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) -+#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+ -+#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -new file mode 100644 -index 0000000000000000000000000000000000000000..311b9f26fab7dd770bdcd684c7691442b0872d55 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -0,0 +1,188 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/platform.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _BCM2708_PLATFORM_H -+#define _BCM2708_PLATFORM_H -+ -+ -+/* macros to get at IO space when running virtually */ -+#define IO_ADDRESS(x) (((x) & 0x00ffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -+ -+#define __io_address(n) IOMEM(IO_ADDRESS(n)) -+ -+ -+/* -+ * SDRAM -+ */ -+#define BCM2708_SDRAM_BASE 0x00000000 -+ -+/* -+ * Logic expansion modules -+ * -+ */ -+ -+ -+/* ------------------------------------------------------------------------ -+ * BCM2708 ARMCTRL Registers -+ * ------------------------------------------------------------------------ -+ */ -+ -+#define HW_REGISTER_RW(addr) (addr) -+#define HW_REGISTER_RO(addr) (addr) -+ -+/* -+ * Definitions and addresses for the ARM CONTROL logic -+ * This file is manually generated. -+ */ -+ -+#define BCM2708_PERI_BASE 0x3F000000 -+#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) -+#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ -+#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ -+#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ -+#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ -+#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ -+#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ -+#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ -+#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ -+#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ -+#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ -+#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ -+#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ -+#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ -+#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ -+#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ -+#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ -+#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ -+#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ -+#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -+ -+#define ARMCTRL_BASE (ARM_BASE + 0x000) -+#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ -+#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ -+#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+ -+/* -+ * Watchdog -+ */ -+#define PM_RSTC (PM_BASE+0x1c) -+#define PM_RSTS (PM_BASE+0x20) -+#define PM_WDOG (PM_BASE+0x24) -+ -+#define PM_WDOG_RESET 0000000000 -+#define PM_PASSWORD 0x5a000000 -+#define PM_WDOG_TIME_SET 0x000fffff -+#define PM_RSTC_WRCFG_CLR 0xffffffcf -+#define PM_RSTC_WRCFG_SET 0x00000030 -+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -+#define PM_RSTC_RESET 0x00000102 -+ -+#define PM_RSTS_HADPOR_SET 0x00001000 -+#define PM_RSTS_HADSRH_SET 0x00000400 -+#define PM_RSTS_HADSRF_SET 0x00000200 -+#define PM_RSTS_HADSRQ_SET 0x00000100 -+#define PM_RSTS_HADWRH_SET 0x00000040 -+#define PM_RSTS_HADWRF_SET 0x00000020 -+#define PM_RSTS_HADWRQ_SET 0x00000010 -+#define PM_RSTS_HADDRH_SET 0x00000004 -+#define PM_RSTS_HADDRF_SET 0x00000002 -+#define PM_RSTS_HADDRQ_SET 0x00000001 -+ -+#define UART0_CLOCK 3000000 -+ -+#define ARM_LOCAL_BASE 0x40000000 -+#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) -+ -+#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) -+#define ARM_LOCAL_PRESCALER HW_REGISTER_RW(ARM_LOCAL_BASE+0x008) -+#define ARM_LOCAL_GPU_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x00C) -+#define ARM_LOCAL_PM_ROUTING_SET HW_REGISTER_RW(ARM_LOCAL_BASE+0x010) -+#define ARM_LOCAL_PM_ROUTING_CLR HW_REGISTER_RW(ARM_LOCAL_BASE+0x014) -+#define ARM_LOCAL_TIMER_LS HW_REGISTER_RW(ARM_LOCAL_BASE+0x01C) -+#define ARM_LOCAL_TIMER_MS HW_REGISTER_RW(ARM_LOCAL_BASE+0x020) -+#define ARM_LOCAL_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x024) -+#define ARM_LOCAL_AXI_COUNT HW_REGISTER_RW(ARM_LOCAL_BASE+0x02C) -+#define ARM_LOCAL_AXI_IRQ HW_REGISTER_RW(ARM_LOCAL_BASE+0x030) -+#define ARM_LOCAL_TIMER_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x034) -+#define ARM_LOCAL_TIMER_WRITE HW_REGISTER_RW(ARM_LOCAL_BASE+0x038) -+ -+#define ARM_LOCAL_TIMER_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x040) -+#define ARM_LOCAL_TIMER_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x044) -+#define ARM_LOCAL_TIMER_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x048) -+#define ARM_LOCAL_TIMER_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x04C) -+ -+#define ARM_LOCAL_MAILBOX_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x050) -+#define ARM_LOCAL_MAILBOX_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x054) -+#define ARM_LOCAL_MAILBOX_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x058) -+#define ARM_LOCAL_MAILBOX_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x05C) -+ -+#define ARM_LOCAL_IRQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x060) -+#define ARM_LOCAL_IRQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x064) -+#define ARM_LOCAL_IRQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x068) -+#define ARM_LOCAL_IRQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x06C) -+ -+#define ARM_LOCAL_FIQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x070) -+#define ARM_LOCAL_FIQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x074) -+#define ARM_LOCAL_FIQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x078) -+#define ARM_LOCAL_FIQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x07C) -+ -+#define ARM_LOCAL_MAILBOX0_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x080) -+#define ARM_LOCAL_MAILBOX1_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x084) -+#define ARM_LOCAL_MAILBOX2_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x088) -+#define ARM_LOCAL_MAILBOX3_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x08C) -+ -+#define ARM_LOCAL_MAILBOX0_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x090) -+#define ARM_LOCAL_MAILBOX1_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x094) -+#define ARM_LOCAL_MAILBOX2_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x098) -+#define ARM_LOCAL_MAILBOX3_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x09C) -+ -+#define ARM_LOCAL_MAILBOX0_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A0) -+#define ARM_LOCAL_MAILBOX1_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A4) -+#define ARM_LOCAL_MAILBOX2_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A8) -+#define ARM_LOCAL_MAILBOX3_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0AC) -+ -+#define ARM_LOCAL_MAILBOX0_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B0) -+#define ARM_LOCAL_MAILBOX1_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B4) -+#define ARM_LOCAL_MAILBOX2_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B8) -+#define ARM_LOCAL_MAILBOX3_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0BC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C0) -+#define ARM_LOCAL_MAILBOX1_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C4) -+#define ARM_LOCAL_MAILBOX2_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C8) -+#define ARM_LOCAL_MAILBOX3_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0CC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D0) -+#define ARM_LOCAL_MAILBOX1_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D4) -+#define ARM_LOCAL_MAILBOX2_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D8) -+#define ARM_LOCAL_MAILBOX3_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0DC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E0) -+#define ARM_LOCAL_MAILBOX1_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E4) -+#define ARM_LOCAL_MAILBOX2_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E8) -+#define ARM_LOCAL_MAILBOX3_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0EC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F0) -+#define ARM_LOCAL_MAILBOX1_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F4) -+#define ARM_LOCAL_MAILBOX2_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F8) -+#define ARM_LOCAL_MAILBOX3_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0FC) -+ -+#endif -+ -+/* END */ -diff --git a/arch/arm/mach-bcm2709/include/mach/system.h b/arch/arm/mach-bcm2709/include/mach/system.h -new file mode 100644 -index 0000000000000000000000000000000000000000..c9a9c9a881102c5354971d15203a746906761a70 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/system.h -@@ -0,0 +1,37 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/system.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * Copyright (C) 2000 Deep Blue Solutions Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_SYSTEM_H -+#define __ASM_ARCH_SYSTEM_H -+ -+#include -+#include -+ -+static inline void arch_idle(void) -+{ -+ /* -+ * This should do all the clock switching -+ * and wait for interrupt tricks -+ */ -+ cpu_do_idle(); -+} -+ -+#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/uncompress.h b/arch/arm/mach-bcm2709/include/mach/uncompress.h -new file mode 100644 -index 0000000000000000000000000000000000000000..de7504bfc20ba24be8707861b8389783860adb77 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/uncompress.h -@@ -0,0 +1,84 @@ -+/* -+ * arch/arm/mach-bcn2708/include/mach/uncompress.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+ -+#define UART_BAUD 115200 -+ -+#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) -+#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) -+#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) -+#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) -+#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) -+#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -+ -+/* -+ * This does not append a newline -+ */ -+static inline void putc(int c) -+{ -+ while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -+ barrier(); -+ -+ __raw_writel(c, BCM2708_UART_DR); -+} -+ -+static inline void flush(void) -+{ -+ int fr; -+ -+ do { -+ fr = __raw_readl(BCM2708_UART_FR); -+ barrier(); -+ } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); -+} -+ -+static inline void arch_decomp_setup(void) -+{ -+ int temp, div, rem, frac; -+ -+ temp = 16 * UART_BAUD; -+ div = UART0_CLOCK / temp; -+ rem = UART0_CLOCK % temp; -+ temp = (8 * rem) / UART_BAUD; -+ frac = (temp >> 1) + (temp & 1); -+ -+ /* Make sure the UART is disabled before we start */ -+ __raw_writel(0, BCM2708_UART_CR); -+ -+ /* Set the baud rate */ -+ __raw_writel(div, BCM2708_UART_IBRD); -+ __raw_writel(frac, BCM2708_UART_FBRD); -+ -+ /* Set the UART to 8n1, FIFO enabled */ -+ __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -+ -+ /* Enable the UART */ -+ __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -+ BCM2708_UART_CR); -+} -+ -+/* -+ * nothing to do -+ */ -+#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4a4a33845cbc02f0e0d5368fed3609f6ba9ff92b ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -@@ -0,0 +1,35 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#if !defined( VC_MEM_H ) -+#define VC_MEM_H -+ -+#include -+ -+#define VC_MEM_IOC_MAGIC 'v' -+ -+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) -+#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) -+#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) -+#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -+ -+#if defined( __KERNEL__ ) -+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -+ -+extern unsigned long mm_vc_mem_phys_addr; -+extern unsigned int mm_vc_mem_size; -+extern int vc_mem_get_current_size( void ); -+#endif -+ -+#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2709/include/mach/vmalloc.h b/arch/arm/mach-bcm2709/include/mach/vmalloc.h -new file mode 100644 -index 0000000000000000000000000000000000000000..6aa68260dd866c83527dffece8de483913231fb3 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/vmalloc.h -@@ -0,0 +1,20 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vmalloc.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#define VMALLOC_END (0xff000000) -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -new file mode 100644 -index 0000000000000000000000000000000000000000..d2adfd1db2421984ea8ab8fb809d1adb0765714e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/vc_mem.c -@@ -0,0 +1,431 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_ARCH_KONA -+#include -+#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) -+#else -+#include -+#endif -+ -+#include "mach/vc_mem.h" -+ -+#define DRIVER_NAME "vc-mem" -+ -+// Device (/dev) related variables -+static dev_t vc_mem_devnum = 0; -+static struct class *vc_mem_class = NULL; -+static struct cdev vc_mem_cdev; -+static int vc_mem_inited = 0; -+ -+#ifdef CONFIG_DEBUG_FS -+static struct dentry *vc_mem_debugfs_entry; -+#endif -+ -+/* -+ * Videocore memory addresses and size -+ * -+ * Drivers that wish to know the videocore memory addresses and sizes should -+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -+ * headers. This allows the other drivers to not be tied down to a a certain -+ * address/size at compile time. -+ * -+ * In the future, the goal is to have the videocore memory virtual address and -+ * size be calculated at boot time rather than at compile time. The decision of -+ * where the videocore memory resides and its size would be in the hands of the -+ * bootloader (and/or kernel). When that happens, the values of these variables -+ * would be calculated and assigned in the init function. -+ */ -+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space -+unsigned long mm_vc_mem_phys_addr = 0x00000000; -+unsigned int mm_vc_mem_size = 0; -+unsigned int mm_vc_mem_base = 0; -+ -+EXPORT_SYMBOL(mm_vc_mem_phys_addr); -+EXPORT_SYMBOL(mm_vc_mem_size); -+EXPORT_SYMBOL(mm_vc_mem_base); -+ -+static uint phys_addr = 0; -+static uint mem_size = 0; -+static uint mem_base = 0; -+ -+ -+/**************************************************************************** -+* -+* vc_mem_open -+* -+***************************************************************************/ -+ -+static int -+vc_mem_open(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_release -+* -+***************************************************************************/ -+ -+static int -+vc_mem_release(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_size -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_size(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_base -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_base(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_current_size -+* -+***************************************************************************/ -+ -+int -+vc_mem_get_current_size(void) -+{ -+ return mm_vc_mem_size; -+} -+ -+EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -+ -+/**************************************************************************** -+* -+* vc_mem_ioctl -+* -+***************************************************************************/ -+ -+static long -+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int rc = 0; -+ -+ (void) cmd; -+ (void) arg; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ switch (cmd) { -+ case VC_MEM_IOC_MEM_PHYS_ADDR: -+ { -+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -+ __func__, (void *) mm_vc_mem_phys_addr); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -+ sizeof (mm_vc_mem_phys_addr)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_SIZE: -+ { -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -+ mm_vc_mem_size); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_size, -+ sizeof (mm_vc_mem_size)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_BASE: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_LOAD: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ default: -+ { -+ return -ENOTTY; -+ } -+ } -+ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_mmap -+* -+***************************************************************************/ -+ -+static int -+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ int rc = 0; -+ unsigned long length = vma->vm_end - vma->vm_start; -+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -+ -+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -+ __func__, (long) vma->vm_start, (long) vma->vm_end, -+ (long) vma->vm_pgoff); -+ -+ if (offset + length > mm_vc_mem_size) { -+ pr_err("%s: length %ld is too big\n", __func__, length); -+ return -EINVAL; -+ } -+ // Do not cache the memory map -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ rc = remap_pfn_range(vma, vma->vm_start, -+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -+ vma->vm_pgoff, length, vma->vm_page_prot); -+ if (rc != 0) { -+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -+ } -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for the driver. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_mem_fops = { -+ .owner = THIS_MODULE, -+ .open = vc_mem_open, -+ .release = vc_mem_release, -+ .unlocked_ioctl = vc_mem_ioctl, -+ .mmap = vc_mem_mmap, -+}; -+ -+#ifdef CONFIG_DEBUG_FS -+static void vc_mem_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vc_mem_debugfs_entry); -+ vc_mem_debugfs_entry = NULL; -+} -+ -+ -+static int vc_mem_debugfs_init( -+ struct device *dev) -+{ -+ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -+ if (!vc_mem_debugfs_entry) { -+ dev_warn(dev, "could not create debugfs entry\n"); -+ return -EFAULT; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_phys_addr", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_phys_addr)) { -+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_size", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_size)) { -+ dev_warn(dev, "%s:could not create vc_mem_size entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_base", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_base)) { -+ dev_warn(dev, "%s:could not create vc_mem_base entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ vc_mem_debugfs_deinit(); -+ return -EFAULT; -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -+ -+ -+/**************************************************************************** -+* -+* vc_mem_init -+* -+***************************************************************************/ -+ -+static int __init -+vc_mem_init(void) -+{ -+ int rc = -EFAULT; -+ struct device *dev; -+ -+ pr_debug("%s: called\n", __func__); -+ -+ mm_vc_mem_phys_addr = phys_addr; -+ mm_vc_mem_size = mem_size; -+ mm_vc_mem_base = mem_base; -+ -+ vc_mem_get_size(); -+ -+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -+ -+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -+ __func__, rc); -+ goto out_err; -+ } -+ -+ cdev_init(&vc_mem_cdev, &vc_mem_fops); -+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -+ goto out_unregister; -+ } -+ -+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vc_mem_class)) { -+ rc = PTR_ERR(vc_mem_class); -+ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -+ goto out_cdev_del; -+ } -+ -+ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -+ DRIVER_NAME); -+ if (IS_ERR(dev)) { -+ rc = PTR_ERR(dev); -+ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -+ goto out_class_destroy; -+ } -+ -+#ifdef CONFIG_DEBUG_FS -+ /* don't fail if the debug entries cannot be created */ -+ vc_mem_debugfs_init(dev); -+#endif -+ -+ vc_mem_inited = 1; -+ return 0; -+ -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ -+ out_class_destroy: -+ class_destroy(vc_mem_class); -+ vc_mem_class = NULL; -+ -+ out_cdev_del: -+ cdev_del(&vc_mem_cdev); -+ -+ out_unregister: -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ -+ out_err: -+ return -1; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_exit -+* -+***************************************************************************/ -+ -+static void __exit -+vc_mem_exit(void) -+{ -+ pr_debug("%s: called\n", __func__); -+ -+ if (vc_mem_inited) { -+#if CONFIG_DEBUG_FS -+ vc_mem_debugfs_deinit(); -+#endif -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ class_destroy(vc_mem_class); -+ cdev_del(&vc_mem_cdev); -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ } -+} -+ -+module_init(vc_mem_init); -+module_exit(vc_mem_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -+ -+module_param(phys_addr, uint, 0644); -+module_param(mem_size, uint, 0644); -+module_param(mem_base, uint, 0644); + static const char * const bcm2835_compat[] = { + #ifdef CONFIG_ARCH_MULTI_V6 + "brcm,bcm2835", +@@ -47,5 +62,7 @@ static const char * const bcm2835_compat[] = { + + DT_MACHINE_START(BCM2835, "BCM2835") + .init_machine = bcm2835_init, ++ .reserve = bcm2835_board_reserve, ++ .init_early = bcm2835_init_early, + .dt_compat = bcm2835_compat + MACHINE_END diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 06d890a2342b1600e2eae6e350994ad59f5c3a08..30d96e81c0e052c725bdb00bb3df56194023ab9f 100644 --- a/arch/arm/mm/proc-v6.S @@ -4078,46 +1755,6 @@ index 06d890a2342b1600e2eae6e350994ad59f5c3a08..30d96e81c0e052c725bdb00bb3df5619 ret lr ENTRY(cpu_v6_dcache_clean_area) -diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index 2ed1b8a922ed02b9e3545991873af77b4c1bf871..b52d949ee91d96eb7672fbbb4969bfa1e7afc376 100644 ---- a/arch/arm/tools/mach-types -+++ b/arch/arm/tools/mach-types -@@ -522,6 +522,8 @@ torbreck MACH_TORBRECK TORBRECK 3090 - prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 - paz00 MACH_PAZ00 PAZ00 3128 - acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 -+bcm2708 MACH_BCM2708 BCM2708 3138 -+bcm2709 MACH_BCM2709 BCM2709 3139 - ag5evm MACH_AG5EVM AG5EVM 3189 - ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 - wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 -diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile -index fd9d6df0bbc0993c3b7862a08f89dc3a9725be9d..a60aa840b28f0fa73c496a2e0d5c816eed6f771a 100644 ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -19,7 +19,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o - obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o - obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o - obj-$(CONFIG_ORION_TIMER) += time-orion.o --obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o -+obj-$(CONFIG_BCM2835_TIMER)$(CONFIG_ARCH_BCM2708) += bcm2835_timer.o - obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o - obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o - obj-$(CONFIG_MOXART_TIMER) += moxart_timer.o -diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index 4c203b6b816357dce8d7a768ac81feaba91d431b..75da978fac0e06819d8a9740b95ee3d7035c1059 100644 ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -5,6 +5,9 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o - obj-$(CONFIG_ATH79) += irq-ath79-misc.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o -+obj-$(CONFIG_ARCH_BCM2708) += irq-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o - obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o - obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index eccf6ed025299cb480884f5bcbe77abf55a6bbb1..8ed457fd74bd23bee27b64a2c9e3828ce0e4fb87 100644 --- a/drivers/irqchip/irq-bcm2835.c @@ -4154,102 +1791,6 @@ index eccf6ed025299cb480884f5bcbe77abf55a6bbb1..8ed457fd74bd23bee27b64a2c9e3828c return 0; } -diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index aa4bfbf129e4585ebb89b25fca4b03c928925022..89f7a3a539b5a1b84ddcf0a1548160c000103fbb 100644 ---- a/include/linux/mmc/host.h -+++ b/include/linux/mmc/host.h -@@ -311,6 +311,7 @@ struct mmc_host { - #define MMC_CAP2_HS400_ES (1 << 20) /* Host supports enhanced strobe */ - #define MMC_CAP2_NO_SD (1 << 21) /* Do not send SD commands during initialization */ - #define MMC_CAP2_NO_MMC (1 << 22) /* Do not send (e)MMC commands during initialization */ -+#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31) /* Always use multiblock transfers */ - - mmc_pm_flag_t pm_caps; /* supported pm features */ - - -From 7a75212664e74d790360674f0e9d589f967149cf Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 5 Apr 2016 19:40:12 +0100 -Subject: [PATCH 032/208] reboot: Use power off rather than busy spinning when - halt is requested - ---- - arch/arm/kernel/reboot.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c -index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e00fb59a19 100644 ---- a/arch/arm/kernel/reboot.c -+++ b/arch/arm/kernel/reboot.c -@@ -102,9 +102,7 @@ void machine_shutdown(void) - */ - void machine_halt(void) - { -- local_irq_disable(); -- smp_send_stop(); -- while (1); -+ machine_power_off(); - } - - /* - -From f80a468706132177faffe0708b0cd0976ad6bf80 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 11 Nov 2015 21:01:15 +0000 -Subject: [PATCH 033/208] squash: include ARCH_BCM2708 / ARCH_BCM2709 - ---- - drivers/char/hw_random/Kconfig | 2 +- - drivers/clk/bcm/Makefile | 4 ++-- - drivers/mailbox/Kconfig | 2 +- - drivers/mailbox/bcm2835-mailbox.c | 18 ++++++++++++++++-- - drivers/pwm/Kconfig | 2 +- - drivers/spi/Kconfig | 4 ++-- - drivers/watchdog/Kconfig | 2 +- - sound/soc/bcm/Kconfig | 2 +- - 8 files changed, 25 insertions(+), 11 deletions(-) - -diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 8c0770bf8881351c1d956d310c5d670684090770..205b6b34d32c660d34c885e8391032d682c8870e 100644 ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX - - config HW_RANDOM_BCM2835 - tristate "Broadcom BCM2835 Random Number Generator support" -- depends on ARCH_BCM2835 || ARCH_BCM_NSP || ARCH_BCM_5301X -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM_NSP || ARCH_BCM_5301X - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number -diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile -index 1d79bd2c36f004669d1dcf78fa681025c3f074e2..fcf1bb5d792111a31226c33dec6b1da309a36e0d 100644 ---- a/drivers/clk/bcm/Makefile -+++ b/drivers/clk/bcm/Makefile -@@ -4,8 +4,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o --obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o --obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o - obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o - obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o -diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index 7817d40d81e74ad282b1760b1dc50d090d10670d..dc46b41705af8ea405dc961d9230058c7086db7d 100644 ---- a/drivers/mailbox/Kconfig -+++ b/drivers/mailbox/Kconfig -@@ -74,7 +74,7 @@ config ALTERA_MBOX - - config BCM2835_MBOX - tristate "BCM2835 Mailbox" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - An implementation of the BCM2385 Mailbox. It is used to invoke - the services of the Videocore. Say Y here if you want to use the diff --git a/drivers/mailbox/bcm2835-mailbox.c b/drivers/mailbox/bcm2835-mailbox.c index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f27006f4edd15 100644 --- a/drivers/mailbox/bcm2835-mailbox.c @@ -4299,71 +1840,11 @@ index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f2700 MODULE_AUTHOR("Lubomir Rintel "); MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); -diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig -index 80a566a00d0437dcc8fca7715c1109e7c2d35f67..549cf7a786e27e19863ec0ad53a8b2836afd0c2a 100644 ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -95,7 +95,7 @@ config PWM_BCM_KONA - - config PWM_BCM2835 - tristate "BCM2835 PWM support" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - PWM framework driver for BCM2835 controller (Raspberry Pi) - -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index d6fb8d4b778672fd006446c0eab710d35f6e6e3a..4b09be74af155c2a6e0590a6380242db40e6f914 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -94,7 +94,7 @@ config SPI_AXI_SPI_ENGINE - config SPI_BCM2835 - tristate "BCM2835 SPI controller" - depends on GPIOLIB -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI master. - -@@ -105,7 +105,7 @@ config SPI_BCM2835 - - config SPI_BCM2835AUX - tristate "BCM2835 SPI auxiliary controller" -- depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST -+ depends on ((ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709) && GPIOLIB) || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI aux master. - -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index 1bffe006ca9a843e2e71bc1a461a2d67e97480c0..9a28f1fdf93a79104049c03ed51abc31d34165d5 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1440,7 +1440,7 @@ config BCM63XX_WDT - - config BCM2835_WDT - tristate "Broadcom BCM2835 hardware watchdog" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - select WATCHDOG_CORE - help - Watchdog driver for the built in watchdog hardware in Broadcom -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index d528aaceaad95bc6bae2147ebe66249629d2512e..03a303e52d5fe57bbdd8769d24bca59067c54c65 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -1,6 +1,6 @@ - config SND_BCM2835_SOC_I2S - tristate "SoC Audio support for the Broadcom BCM2835 I2S module" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || MACH_BCM2708 || MACH_BCM2709 || COMPILE_TEST - select SND_SOC_GENERIC_DMAENGINE_PCM - select REGMAP_MMIO - help -From 719e241414d5c0c769e3cec0a36701f43665032e Mon Sep 17 00:00:00 2001 +From 4c8bdb873c0c0b35a8dfbff881bf15d64df34ddc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 034/208] Add dwc_otg driver +Subject: [PATCH 031/111] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -4857,6 +2338,12 @@ See: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=70437 Signed-off-by: popcornmix dwc_otg: Use kzalloc when suitable + +dwc_otg: Pass struct device to dma_alloc*() + +This makes it possible to get the bus address from Device Tree. + +Signed-off-by: Noralf Trønnes --- arch/arm/include/asm/irqflags.h | 16 +- arch/arm/kernel/fiqasm.S | 4 + @@ -4876,7 +2363,7 @@ dwc_otg: Use kzalloc when suitable drivers/usb/host/dwc_common_port/dwc_cc.c | 532 ++ drivers/usb/host/dwc_common_port/dwc_cc.h | 224 + drivers/usb/host/dwc_common_port/dwc_common_fbsd.c | 1308 ++++ - .../usb/host/dwc_common_port/dwc_common_linux.c | 1433 ++++ + .../usb/host/dwc_common_port/dwc_common_linux.c | 1418 ++++ drivers/usb/host/dwc_common_port/dwc_common_nbsd.c | 1275 ++++ drivers/usb/host/dwc_common_port/dwc_crypto.c | 308 + drivers/usb/host/dwc_common_port/dwc_crypto.h | 111 + @@ -4910,25 +2397,25 @@ dwc_otg: Use kzalloc when suitable drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 1355 ++++ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 370 + drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S | 80 + - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4257 ++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 862 +++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1132 ++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4260 ++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 868 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1139 ++++ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 417 ++ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2727 ++++++++ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 1005 +++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 962 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 963 +++ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 188 + - drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2712 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 266 + - drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 360 + - drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 5147 ++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1279 ++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2725 ++++++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 273 + + drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 361 + + drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 5148 ++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1280 ++++ drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2550 +++++++ drivers/usb/host/dwc_otg/test/Makefile | 16 + drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 + drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 + drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + - 70 files changed, 59883 insertions(+), 16 deletions(-) + 70 files changed, 59908 insertions(+), 16 deletions(-) create mode 100644 drivers/usb/gadget/file_storage.c create mode 100644 drivers/usb/host/dwc_common_port/Makefile create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd @@ -5059,10 +2546,10 @@ index 358ca8dd784fe43700ae070764fa783500a792fe..abaac7c7142d8887c1516957fc52162c return i; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 1d5fc32d06d007a6f64526a531da8ae69e8e6950..ce881480114d0f444f4b1099c713c2568b725162 100644 +index cbb146736f577da8a060d49b17052af78881adfa..7b07ce5dbdc5cffa36fb7e8dda07dd2a4102e1c5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -5041,7 +5041,7 @@ static void port_event(struct usb_hub *hub, int port1) +@@ -5039,7 +5039,7 @@ static void port_event(struct usb_hub *hub, int port1) if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0, unused; @@ -5072,10 +2559,10 @@ index 1d5fc32d06d007a6f64526a531da8ae69e8e6950..ce881480114d0f444f4b1099c713c256 USB_PORT_FEAT_C_OVER_CURRENT); msleep(100); /* Cool down */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c -index 0406a59f05510cb1dee98ffbf22b55c0ccd65750..8c3401f7c1ca80e0eedc7aec6cca5d593cf16718 100644 +index 3a47077461578f2af47af8d551353c2c7cb12f0e..85b7ff6f24b8023e1b589aa1a3557885c48d7a13 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c -@@ -1906,6 +1906,85 @@ free_interfaces: +@@ -1908,6 +1908,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); @@ -5162,7 +2649,7 @@ index 0406a59f05510cb1dee98ffbf22b55c0ccd65750..8c3401f7c1ca80e0eedc7aec6cca5d59 /* Now that the interfaces are installed, re-enable LPM. */ usb_unlocked_enable_lpm(dev); diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h -index a95b0c989c216eca774abd0709451096fda19792..17b605f5e1a3219b2c878e2aeeb45cec8e56ff3a 100644 +index 085049d37d7a5b23ff8dbf44b02afc1837fe3b68..63a461a21cc14b9c6f14db7c1d03c7a2ebcdba65 100644 --- a/drivers/usb/core/otg_whitelist.h +++ b/drivers/usb/core/otg_whitelist.h @@ -19,33 +19,82 @@ @@ -5199,7 +2686,7 @@ index a95b0c989c216eca774abd0709451096fda19792..17b605f5e1a3219b2c878e2aeeb45cec +//{ USB_DEVICE(0x0525, 0xa4a2), }, #endif - #if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE) + #if IS_ENABLED(CONFIG_USB_TEST) /* gadget zero, for testing */ -{ USB_DEVICE(0x0525, 0xa4a0), }, +//{ USB_DEVICE(0x0525, 0xa4a0), }, @@ -9001,7 +6488,7 @@ index 0000000000000000000000000000000000000000..a896d73f7a9336f5a34015c44ea5a6b0 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index 2e710a4cca525915991bf2b2a884dd2cec844281..a94354d1c7574c5cf1fdb7c47165459a5378c2c0 100644 +index 0b80cee30da4740e8c28c6ea7a4cc700163a12ee..f17b939c149562527937f49d90e23c7ab8b72328 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -762,6 +762,19 @@ config USB_HWA_HCD @@ -11719,10 +9206,10 @@ index 0000000000000000000000000000000000000000..6dd04b58f8f6c6d5ddad3b0b0148ff5d +} diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c new file mode 100644 -index 0000000000000000000000000000000000000000..46646841dda96fb2bed01152de552ccac5f0e5e4 +index 0000000000000000000000000000000000000000..0d641e6da24beeb07109e23847d1d6e81dc7d4ea --- /dev/null +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -@@ -0,0 +1,1433 @@ +@@ -0,0 +1,1418 @@ +#include +#include +#include @@ -12062,27 +9549,12 @@ index 0000000000000000000000000000000000000000..46646841dda96fb2bed01152de552cca + +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) +{ -+#ifdef xxCOSIM /* Only works for 32-bit cosim */ -+ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); -+#else -+ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); -+#endif -+ if (!buf) { -+ return NULL; -+ } -+ -+ memset(buf, 0, (size_t)size); -+ return buf; ++ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_KERNEL | GFP_DMA32); +} + +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) +{ -+ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); -+ if (!buf) { -+ return NULL; -+ } -+ memset(buf, 0, (size_t)size); -+ return buf; ++ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_ATOMIC); +} + +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) @@ -17265,7 +14737,7 @@ index 0000000000000000000000000000000000000000..4a8cdfe565b1fcefb400706dc7bc13cf +#endif /* __DWC_NOTIFIER_H__ */ diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h new file mode 100644 -index 0000000000000000000000000000000000000000..a2bbe232ffc3b58001d026864c3019792cdf5efa +index 0000000000000000000000000000000000000000..9a86d299403bd1dfdcdb6532fad702b2b65138d7 --- /dev/null +++ b/drivers/usb/host/dwc_common_port/dwc_os.h @@ -0,0 +1,1276 @@ @@ -17946,9 +15418,9 @@ index 0000000000000000000000000000000000000000..a2bbe232ffc3b58001d026864c301979 +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) + +# ifdef DWC_LINUX -+#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) ++#define DWC_DMA_ALLOC(_dev, _size_, _dma_) __DWC_DMA_ALLOC(_dev, _size_, _dma_) ++#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) __DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) ++#define DWC_DMA_FREE(_dev, _size_,_virt_, _dma_) __DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) +# endif + +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) @@ -17979,12 +15451,12 @@ index 0000000000000000000000000000000000000000..a2bbe232ffc3b58001d026864c301979 +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) + +# ifdef DWC_LINUX -+#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ -+ _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ -+ _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ -+ _virt_, _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC(_dev, _size_, _dma_) \ ++ dwc_dma_alloc_debug(_dev, _size_, _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) \ ++ dwc_dma_alloc_atomic_debug(_dev, _size_, _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) \ ++ dwc_dma_free_debug(_dev, _size_, _virt_, _dma_, __func__, __LINE__) +# endif + +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) @@ -38916,7 +36388,7 @@ index 0000000000000000000000000000000000000000..6a8be63a0ab20f4e1c56251b85648aa2 +#endif diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c new file mode 100644 -index 0000000000000000000000000000000000000000..85d82f31cb49631f03b23631882d2b6c063b33db +index 0000000000000000000000000000000000000000..13047c08fb71cc6e44c66096720d4654d3f9e4e1 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c @@ -0,0 +1,1355 @@ @@ -39000,7 +36472,7 @@ index 0000000000000000000000000000000000000000..85d82f31cb49631f03b23631882d2b6c + * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock + * Must be called with local interrupts and FIQ disabled. + */ -+#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) ++#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) +inline void fiq_fsm_spin_lock(fiq_lock_t *lock) +{ + unsigned long tmp; @@ -39033,7 +36505,7 @@ index 0000000000000000000000000000000000000000..85d82f31cb49631f03b23631882d2b6c +/** + * fiq_fsm_spin_unlock() - ARMv6+ bare bones spinunlock + */ -+#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) ++#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) +inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) +{ + smp_mb(); @@ -40739,10 +38211,10 @@ index 0000000000000000000000000000000000000000..ffa8d21bc61e893fee86ba04955587e7 +END(_dwc_otg_fiq_stub) diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c new file mode 100644 -index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6b13113fc +index 0000000000000000000000000000000000000000..027414bb2bf9fc3f3652407724187f3c6dc5ff68 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -0,0 +1,4257 @@ +@@ -0,0 +1,4260 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ @@ -41629,6 +39101,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + */ +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(dwc_otg_hcd); + int i; + + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); @@ -41661,7 +39134,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + + if (dwc_otg_hcd->core_if->dma_enable) { + if (dwc_otg_hcd->status_buf_dma) { -+ DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ DWC_DMA_FREE(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, + dwc_otg_hcd->status_buf, + dwc_otg_hcd->status_buf_dma); + } @@ -41691,6 +39164,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + int retval = 0; + int num_channels; + int i; @@ -41786,7 +39260,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + * for use as transaction bounce buffers in a 2-D array. Our access into this chunk is done by some + * moderately readable array casts. + */ -+ hcd->fiq_dmab = DWC_DMA_ALLOC((sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); ++ hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); + DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d", + (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base, + sizeof(struct fiq_dma_channel) * num_channels); @@ -41837,7 +39311,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + */ + if (hcd->core_if->dma_enable) { + hcd->status_buf = -+ DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ DWC_DMA_ALLOC(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, + &hcd->status_buf_dma); + } else { + hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); @@ -41932,6 +39406,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + uint32_t intr_enable; + unsigned long flags; + gintmsk_data_t gintmsk = { .d32 = 0, }; ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); + @@ -42126,7 +39601,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + buf_size = 4096; + } + if (!qh->dw_align_buf) { -+ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, ++ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(dev, buf_size, + &qh->dw_align_buf_dma); + if (!qh->dw_align_buf) { + DWC_ERROR @@ -42177,7 +39652,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + fiq_fsm_spin_unlock(&hcd->fiq_state->lock); + local_fiq_enable(); + } -+ ++ + local_irq_restore(flags); + hc->qh = qh; +} @@ -45002,10 +42477,10 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h new file mode 100644 -index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99ca8dce7dc +index 0000000000000000000000000000000000000000..4539cd7b802d3e49ac9a6cb3f1d88b475a1ace16 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -0,0 +1,862 @@ +@@ -0,0 +1,868 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ + * $Revision: #58 $ @@ -45049,6 +42524,7 @@ index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99c +#include "dwc_list.h" +#include "dwc_otg_cil.h" +#include "dwc_otg_fiq_fsm.h" ++#include "dwc_otg_driver.h" + + +/** @@ -45621,6 +43097,11 @@ index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99c +#endif +}; + ++static inline struct device *dwc_otg_hcd_to_dev(struct dwc_otg_hcd *hcd) ++{ ++ return &hcd->otg_dev->os_dep.platformdev->dev; ++} ++ +/** @name Transaction Execution Functions */ +/** @{ */ +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t @@ -45870,10 +43351,10 @@ index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99c +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c new file mode 100644 -index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d809fec4e70 +index 0000000000000000000000000000000000000000..126e99ab2fc43f11d89a08ff0476181ead84029f --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -0,0 +1,1132 @@ +@@ -0,0 +1,1139 @@ +/*========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ + * $Revision: #10 $ @@ -45951,12 +43432,12 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + : qh->interval); +} + -+static int desc_list_alloc(dwc_otg_qh_t * qh) ++static int desc_list_alloc(struct device *dev, dwc_otg_qh_t * qh) +{ + int retval = 0; + + qh->desc_list = (dwc_otg_host_dma_desc_t *) -+ DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), ++ DWC_DMA_ALLOC(dev, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), + &qh->desc_list_dma); + + if (!qh->desc_list) { @@ -45982,10 +43463,10 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + +} + -+static void desc_list_free(dwc_otg_qh_t * qh) ++static void desc_list_free(struct device *dev, dwc_otg_qh_t * qh) +{ + if (qh->desc_list) { -+ DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, ++ DWC_DMA_FREE(dev, max_desc_num(qh), qh->desc_list, + qh->desc_list_dma); + qh->desc_list = NULL; + } @@ -45998,11 +43479,13 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + +static int frame_list_alloc(dwc_otg_hcd_t * hcd) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + int retval = 0; ++ + if (hcd->frame_list) + return 0; + -+ hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, ++ hcd->frame_list = DWC_DMA_ALLOC(dev, 4 * MAX_FRLIST_EN_NUM, + &hcd->frame_list_dma); + if (!hcd->frame_list) { + retval = -DWC_E_NO_MEMORY; @@ -46016,10 +43499,12 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + +static void frame_list_free(dwc_otg_hcd_t * hcd) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); ++ + if (!hcd->frame_list) + return; + -+ DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); ++ DWC_DMA_FREE(dev, 4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); + hcd->frame_list = NULL; +} + @@ -46197,6 +43682,7 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + */ +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + int retval = 0; + + if (qh->do_split) { @@ -46204,7 +43690,7 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + return -1; + } + -+ retval = desc_list_alloc(qh); ++ retval = desc_list_alloc(dev, qh); + + if ((retval == 0) + && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { @@ -46231,7 +43717,9 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + */ +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ -+ desc_list_free(qh); ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); ++ ++ desc_list_free(dev, qh); + + /* + * Channel still assigned due to some reasons. @@ -50164,7 +47652,7 @@ index 0000000000000000000000000000000000000000..e6b38ac330b72152204c2a6879c20f0c +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c new file mode 100644 -index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e83aee1443 +index 0000000000000000000000000000000000000000..74cd5fa54aed5241b61371477ef67d706477fd30 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c @@ -0,0 +1,1005 @@ @@ -50687,6 +48175,7 @@ index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e8 + ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = + dwc_otg_hcd; + otg_dev->hcd = dwc_otg_hcd; ++ otg_dev->hcd->otg_dev = otg_dev; + + if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { + goto error2; @@ -50701,7 +48190,6 @@ index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e8 + } + } + -+ otg_dev->hcd->otg_dev = otg_dev; + hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later @@ -51175,10 +48663,10 @@ index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e8 +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c new file mode 100644 -index 0000000000000000000000000000000000000000..3b2a60763b92fb2e9261a8ade3d4b33e3896cd62 +index 0000000000000000000000000000000000000000..c2dff94e8e6edd22e4427aaa1eac7aad972cb6bd --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -0,0 +1,962 @@ +@@ -0,0 +1,963 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ + * $Revision: #44 $ @@ -51240,6 +48728,7 @@ index 0000000000000000000000000000000000000000..3b2a60763b92fb2e9261a8ade3d4b33e + uint32_t buf_size = 0; + uint8_t *align_buf_virt = NULL; + dwc_dma_t align_buf_dma; ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + + /* Free each QTD in the QTD list */ + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); @@ -51263,7 +48752,7 @@ index 0000000000000000000000000000000000000000..3b2a60763b92fb2e9261a8ade3d4b33e + DWC_FREE(qh); + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + if (align_buf_virt) -+ DWC_DMA_FREE(buf_size, align_buf_virt, align_buf_dma); ++ DWC_DMA_FREE(dev, buf_size, align_buf_virt, align_buf_dma); + return; +} + @@ -52337,10 +49826,10 @@ index 0000000000000000000000000000000000000000..6b2c7d0c93f36a63863ff4b0ecc1f3ea +#endif /* _DWC_OS_DEP_H_ */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c new file mode 100644 -index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3d7ef86b8 +index 0000000000000000000000000000000000000000..9dabbe5c9791c5296d1cc7b663afa6ec462173cb --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -@@ -0,0 +1,2712 @@ +@@ -0,0 +1,2725 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ + * $Revision: #101 $ @@ -52580,20 +50069,22 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + * This function allocates a DMA Descriptor chain for the Endpoint + * buffer to be used for a transfer to/from the specified endpoint. + */ -+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, ++dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(struct device *dev, ++ dwc_dma_t * dma_desc_addr, + uint32_t count) +{ -+ return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), ++ return DWC_DMA_ALLOC_ATOMIC(dev, count * sizeof(dwc_otg_dev_dma_desc_t), + dma_desc_addr); +} + +/** + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. + */ -+void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, ++void dwc_otg_ep_free_desc_chain(struct device *dev, ++ dwc_otg_dev_dma_desc_t * desc_addr, + uint32_t dma_desc_addr, uint32_t count) +{ -+ DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, ++ DWC_DMA_FREE(dev, count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, + dma_desc_addr); +} + @@ -53448,8 +50939,10 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + * This function initialized the PCD portion of the driver. + * + */ -+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) ++dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev) +{ ++ struct device *dev = &otg_dev->os_dep.platformdev->dev; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; + dwc_otg_pcd_t *pcd = NULL; + dwc_otg_dev_if_t *dev_if; + int i; @@ -53506,7 +50999,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + */ + if (GET_CORE_IF(pcd)->dma_enable) { + pcd->setup_pkt = -+ DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_ALLOC(dev, sizeof(*pcd->setup_pkt) * 5, + &pcd->setup_pkt_dma_handle); + if (pcd->setup_pkt == NULL) { + DWC_FREE(pcd); @@ -53514,10 +51007,10 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + } + + pcd->status_buf = -+ DWC_DMA_ALLOC(sizeof(uint16_t), ++ DWC_DMA_ALLOC(dev, sizeof(uint16_t), + &pcd->status_buf_dma_handle); + if (pcd->status_buf == NULL) { -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, + pcd->setup_pkt, pcd->setup_pkt_dma_handle); + DWC_FREE(pcd); + return NULL; @@ -53525,17 +51018,17 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + + if (GET_CORE_IF(pcd)->dma_desc_enable) { + dev_if->setup_desc_addr[0] = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_setup_desc_addr[0], 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_setup_desc_addr[0], 1); + dev_if->setup_desc_addr[1] = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_setup_desc_addr[1], 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_setup_desc_addr[1], 1); + dev_if->in_desc_addr = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_in_desc_addr, 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_in_desc_addr, 1); + dev_if->out_desc_addr = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_out_desc_addr, 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_out_desc_addr, 1); + pcd->data_terminated = 0; + + if (dev_if->setup_desc_addr[0] == 0 @@ -53544,26 +51037,26 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + || dev_if->out_desc_addr == 0) { + + if (dev_if->out_desc_addr) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->out_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->out_desc_addr, + dev_if->dma_out_desc_addr, 1); + if (dev_if->in_desc_addr) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->in_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->in_desc_addr, + dev_if->dma_in_desc_addr, 1); + if (dev_if->setup_desc_addr[1]) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->setup_desc_addr[1], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[1], + dev_if->dma_setup_desc_addr[1], 1); + if (dev_if->setup_desc_addr[0]) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->setup_desc_addr[0], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[0], + dev_if->dma_setup_desc_addr[0], 1); + -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, + pcd->setup_pkt, + pcd->setup_pkt_dma_handle); -+ DWC_DMA_FREE(sizeof(*pcd->status_buf), ++ DWC_DMA_FREE(dev, sizeof(*pcd->status_buf), + pcd->status_buf, + pcd->status_buf_dma_handle); + @@ -53645,7 +51138,9 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) +{ + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + int i; ++ + if (pcd->core_if->core_params->dev_out_nak) { + for (i = 0; i < MAX_EPS_CHANNELS; i++) { + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); @@ -53654,20 +51149,24 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + } + + if (GET_CORE_IF(pcd)->dma_enable) { -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, ++ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, + pcd->setup_pkt_dma_handle); -+ DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, ++ DWC_DMA_FREE(dev, sizeof(uint16_t), pcd->status_buf, + pcd->status_buf_dma_handle); + if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[0], + dev_if->dma_setup_desc_addr + [0], 1); -+ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[1], + dev_if->dma_setup_desc_addr + [1], 1); -+ dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->in_desc_addr, + dev_if->dma_in_desc_addr, 1); -+ dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->out_desc_addr, + dev_if->dma_out_desc_addr, + 1); + } @@ -53806,6 +51305,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; + int retval = 0; + int i, epcount; ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + + desc = (const usb_endpoint_descriptor_t *)ep_desc; + @@ -53914,9 +51414,9 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + if (ep->dwc_ep.type != UE_ISOCHRONOUS) { +#endif + ep->dwc_ep.desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&ep-> -+ dwc_ep.dma_desc_addr, -+ MAX_DMA_DESC_CNT); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &ep->dwc_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT); + if (!ep->dwc_ep.desc_addr) { + DWC_WARN("%s, can't allocate DMA descriptor\n", + __func__); @@ -53967,6 +51467,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; + gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; + fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + + ep = get_ep_from_handle(pcd, ep_handle); + @@ -54021,7 +51522,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + + /* Cannot call dma_free_coherent() with IRQs disabled */ + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, desc_addr, dma_desc_addr, + MAX_DMA_DESC_CNT); + + goto out_unlocked; @@ -54422,6 +51923,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, + int zero, void *req_handle, int atomic_alloc) +{ ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + dwc_irqflags_t flags; + dwc_otg_pcd_request_t *req; + dwc_otg_pcd_ep_t *ep; @@ -54458,7 +51960,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + req->dw_align_buf = NULL; + if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable + && !GET_CORE_IF(pcd)->dma_desc_enable) -+ req->dw_align_buf = DWC_DMA_ALLOC(buflen, ++ req->dw_align_buf = DWC_DMA_ALLOC(dev, buflen, + &req->dw_align_buf_dma); + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); + @@ -55055,10 +52557,10 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h new file mode 100644 -index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c2837ddcfa8 +index 0000000000000000000000000000000000000000..a70ebd049d2cca3bf988a1f809832eebede14f96 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -@@ -0,0 +1,266 @@ +@@ -0,0 +1,273 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ + * $Revision: #48 $ @@ -55099,6 +52601,8 @@ index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c28 +#include "usb.h" +#include "dwc_otg_cil.h" +#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_driver.h" ++ +struct cfiobject; + +/** @@ -55314,6 +52818,11 @@ index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c28 + +}; + ++static inline struct device *dwc_otg_pcd_to_dev(struct dwc_otg_pcd *pcd) ++{ ++ return &pcd->otg_dev->os_dep.platformdev->dev; ++} ++ +//FIXME this functions should be static, and this prototypes should be removed +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, @@ -55327,10 +52836,10 @@ index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c28 +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h new file mode 100644 -index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c64b496b4 +index 0000000000000000000000000000000000000000..4c1d591fbc098b2f4a745669e4f243e068735b20 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -@@ -0,0 +1,360 @@ +@@ -0,0 +1,361 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ + * $Revision: #11 $ @@ -55370,6 +52879,7 @@ index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c + +//#include "dwc_os.h" +#include "dwc_otg_core_if.h" ++#include "dwc_otg_driver.h" + +/** @file + * This file defines DWC_OTG PCD Core API. @@ -55472,7 +52982,7 @@ index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c + * + * @param core_if The DWC_OTG Core + */ -+extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); ++extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev); + +/** Frees PCD allocated by dwc_otg_pcd_init + * @@ -55693,10 +53203,10 @@ index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c new file mode 100644 -index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c34226d094f84 +index 0000000000000000000000000000000000000000..e55ea9c74be46167a41dc14a2d88a1228878b1bb --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -@@ -0,0 +1,5147 @@ +@@ -0,0 +1,5148 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ + * $Revision: #116 $ @@ -57843,6 +55353,7 @@ index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c3422 +static void complete_ep(dwc_otg_pcd_ep_t * ep) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ struct device *dev = dwc_otg_pcd_to_dev(ep->pcd); + dwc_otg_dev_if_t *dev_if = core_if->dev_if; + dwc_otg_dev_in_ep_regs_t *in_ep_regs = + dev_if->in_ep_regs[ep->dwc_ep.num]; @@ -58183,7 +55694,7 @@ index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c3422 + if (!ep->dwc_ep.is_in) { + dwc_memcpy(req->buf, req->dw_align_buf, req->length); + } -+ DWC_DMA_FREE(req->length, req->dw_align_buf, ++ DWC_DMA_FREE(dev, req->length, req->dw_align_buf, + req->dw_align_buf_dma); + } + @@ -60846,10 +58357,10 @@ index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c3422 +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c new file mode 100644 -index 0000000000000000000000000000000000000000..5624f32c9ea9117599df451af29fca2e3bca36de +index 0000000000000000000000000000000000000000..e799f15f294706ad7ac328dcb9ce68fbd0e71d38 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -0,0 +1,1279 @@ +@@ -0,0 +1,1280 @@ + /* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ + * $Revision: #21 $ @@ -61122,6 +58633,7 @@ index 0000000000000000000000000000000000000000..5624f32c9ea9117599df451af29fca2e + } + + buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); ++ WARN_ON(!buf); + + /* Check dword alignment */ + if (((int)buf & 0x3UL) != 0) { @@ -62058,7 +59570,7 @@ index 0000000000000000000000000000000000000000..5624f32c9ea9117599df451af29fca2e + + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); + -+ otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); ++ otg_dev->pcd = dwc_otg_pcd_init(otg_dev); + + if (!otg_dev->pcd) { + DWC_ERROR("dwc_otg_pcd_init failed\n"); @@ -65389,10 +62901,10 @@ index 0000000000000000000000000000000000000000..cdc9963176e5a4a0d5250613b61e26c5 +test_main(); +0; -From 8e1c17d3d0343deb70fe8cd422d6d3dc19a770fa Mon Sep 17 00:00:00 2001 +From 37fd2725a8d6b6f18331ba65f01ef63aa9fa3f7c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 035/208] bcm2708 framebuffer driver +Subject: [PATCH 032/111] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -65474,7 +62986,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/video/fbdev/bcm2708_fb.c diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index 88b008fb8a4ec9f4f4458b8b65a5e7d4ccef57e5..78a9e6119fa13437862080d815e84d68f7010d1f 100644 +index 5d3b0db5ce0af34997a3aa748292b6bd8d48c191..0ff4f80531e013f028ca4d05559c5464f8cfa5ef 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -228,6 +228,20 @@ config FB_TILEBLITTING @@ -65499,10 +63011,10 @@ index 88b008fb8a4ec9f4f4458b8b65a5e7d4ccef57e5..78a9e6119fa13437862080d815e84d68 tristate "Aeroflex Gaisler framebuffer support" depends on FB && SPARC diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index f6731867dd26dfc4318799e5204cd583a5d27670..ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2 100644 +index ee8c81405a7f9af1f190c98ddcfa53666ad97b0f..8cd1193b98690b9c4f49098ab14389504d65af3a 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o +@@ -10,6 +10,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o # Hardware specific drivers go first @@ -68851,10 +66363,10 @@ index 3c14e43b82fefe1d32f591d1b2f61d2cd28d0fa8..7626beb6a5bb8df601ddf0f6e6909d1f +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 -From 153d404162b1f45c70ea0113ab3057c534cd9532 Mon Sep 17 00:00:00 2001 +From 9a807a8f74d42575774841b923e278774777f81a Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 036/208] dmaengine: Add support for BCM2708 +Subject: [PATCH 033/111] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69004,19 +66516,28 @@ Signed-off-by: Noralf Trønnes bcm2708-dmaengine - Fix arm64 portability/build issues --- - drivers/dma/Kconfig | 4 + + drivers/dma/Kconfig | 6 +- drivers/dma/Makefile | 1 + drivers/dma/bcm2708-dmaengine.c | 281 ++++++++++++++++++++++++++++++ include/linux/platform_data/dma-bcm2708.h | 143 +++++++++++++++ - 4 files changed, 429 insertions(+) + 4 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/bcm2708-dmaengine.c create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index f7b3ac574968b35aeb1fb6b3ba8d4f1bf61599f9..2a2108062687ff33ff540c987f6367fa3b8aad9d 100644 +index 9c931d36c6a499a02f4f215f8cd77d3f2254a3b9..9ccee1058e4c5c208a196d6d89e700d09754f977 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig -@@ -502,6 +502,10 @@ config TIMB_DMA +@@ -108,7 +108,7 @@ config COH901318 + + config DMA_BCM2835 + tristate "BCM2835 DMA engine support" +- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 ++ depends on ARCH_BCM2835 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + +@@ -499,6 +499,10 @@ config TIMB_DMA help Enable support for the Timberdale FPGA DMA engine. @@ -69476,10 +66997,10 @@ index 0000000000000000000000000000000000000000..c5bfff2765be4606077e6c8af73040ec + +#endif /* _PLAT_BCM2708_DMA_H */ -From 7c69e53eea36e2bc92fb5d1e7e631aa0d4691a68 Mon Sep 17 00:00:00 2001 +From 74ba2b578d504eaed03b226d2945433cc1e2999b Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 037/208] MMC: added alternative MMC driver +Subject: [PATCH 034/111] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69565,8 +67086,8 @@ Signed-off-by: Phil Elwell drivers/mmc/core/quirks.c | 10 + drivers/mmc/host/Kconfig | 29 + drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-mmc.c | 1571 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 1611 insertions(+) + drivers/mmc/host/bcm2835-mmc.c | 1574 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 1614 insertions(+) create mode 100644 drivers/mmc/host/bcm2835-mmc.c diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c @@ -69650,10 +67171,10 @@ index e2bdaaf431841535b936600af56b8e38f52f9845..5133b680970c93fbb9695f83296f0f70 obj-$(CONFIG_MMC_MTK) += mtk-sd.o diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c new file mode 100644 -index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad098eec9a19 +index 0000000000000000000000000000000000000000..4fe8d1fe44578fbefcd48f8c327ba3d03f3d0a2a --- /dev/null +++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -0,0 +1,1571 @@ +@@ -0,0 +1,1574 @@ +/* + * BCM2835 MMC host driver. + * @@ -71115,8 +68636,11 @@ index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad09 +#endif + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { -+ dev_err(dev, "could not get clk\n"); + ret = PTR_ERR(clk); ++ if (ret == -EPROBE_DEFER) ++ dev_info(dev, "could not get clk, deferring probe\n"); ++ else ++ dev_err(dev, "could not get clk\n"); + goto err; + } + @@ -71226,10 +68750,10 @@ index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad09 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 4acaf78a70bd0f9c2fd25d5c9cc229a397eafe06 Mon Sep 17 00:00:00 2001 +From d8a2f68ba20a9bed7751795dda754f7861c71073 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 038/208] Adding bcm2835-sdhost driver, and an overlay to +Subject: [PATCH 035/111] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -71390,23 +68914,32 @@ See: https://github.com/raspberrypi/linux/pull/1492 Signed-off-by: Phil Elwell --- - drivers/mmc/host/Kconfig | 10 + + drivers/mmc/host/Kconfig | 12 +- drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-sdhost.c | 2185 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 2196 insertions(+) + drivers/mmc/host/bcm2835-sdhost.c | 2189 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 2201 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/host/bcm2835-sdhost.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 405d62909dd6ac5351684c002414cc02135d98ba..205d836b52e3bbcf8956fec98072c6ee7804a403 100644 +index 405d62909dd6ac5351684c002414cc02135d98ba..87d251e93913b216359383812cae196e91bf6cfb 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig +@@ -6,7 +6,7 @@ comment "MMC/SD/SDIO Host Controller Drivers" + + config MMC_BCM2835 + tristate "MMC support on BCM2835" +- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + help + This selects the MMC Interface on BCM2835. + @@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER If unsure, say 2 here. +config MMC_BCM2835_SDHOST + tristate "Support for the SDHost controller on BCM2708/9" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + help + This selects the SDHost controller on BCM2835/6. + @@ -71431,10 +68964,10 @@ index 5133b680970c93fbb9695f83296f0f70b4977240..adbc4586fec94aa8bd70f5ca3e2c90d1 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c new file mode 100644 -index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5da69c0d33 +index 0000000000000000000000000000000000000000..a9bc79bfdbb71807819dfe2d8f1651445997f92a --- /dev/null +++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -0,0 +1,2185 @@ +@@ -0,0 +1,2189 @@ +/* + * BCM2835 SD host driver. + * @@ -71672,10 +69205,10 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d +#define LOG_ENTRIES (256*1) +#define LOG_SIZE (sizeof(LOG_ENTRY_T)*LOG_ENTRIES) + -+static void log_init(u32 bus_to_phys) ++static void log_init(struct device *dev, u32 bus_to_phys) +{ + spin_lock_init(&log_lock); -+ sdhost_log_buf = dma_zalloc_coherent(NULL, LOG_SIZE, &sdhost_log_addr, ++ sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr, + GFP_KERNEL); + if (sdhost_log_buf) { + pr_info("sdhost: log_buf @ %p (%x)\n", @@ -73474,7 +71007,6 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d + return -ENODEV; + } + host->bus_addr = be32_to_cpup(addr); -+ log_init(iomem->start - host->bus_addr); + pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n", + (unsigned long)host->ioaddr, + (unsigned long)iomem->start, @@ -73526,8 +71058,11 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { -+ dev_err(dev, "could not get clk\n"); + ret = PTR_ERR(clk); ++ if (ret == -EPROBE_DEFER) ++ dev_info(dev, "could not get clk, deferring probe\n"); ++ else ++ dev_err(dev, "could not get clk\n"); + goto err; + } + @@ -73544,6 +71079,8 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d + (unsigned long)host->max_clk, + (int)host->irq); + ++ log_init(dev, iomem->start - host->bus_addr); ++ + if (node) + mmc_of_parse(mmc); + else @@ -73621,10 +71158,10 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From a93caaa8ea2e62422122b1a66434e42b56328838 Mon Sep 17 00:00:00 2001 +From 89171c41359e357f80ccc5b5c463f8bd3ee0b001 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 11 May 2016 12:50:33 +0100 -Subject: [PATCH 039/208] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards +Subject: [PATCH 036/111] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards Some SD cards have been found that corrupt data when small blocks are erased. Add a quirk to indicate that ERASE should not be used, @@ -73653,10 +71190,10 @@ Signed-off-by: Phil Elwell 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index 17891f17f39d88941990177b21d05479ec708037..c0163b8bdd20c33f65d952f6446d9bd2ca7bb3a6 100644 +index 709a872ed484a9da1ce620238c3222190c612f86..894c105be9ce7f83147a62c433c787b90a5e7c17 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c -@@ -134,6 +134,13 @@ enum { +@@ -135,6 +135,13 @@ enum { module_param(perdev_minors, int, 0444); MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); @@ -73732,10 +71269,10 @@ index 17891f17f39d88941990177b21d05479ec708037..c0163b8bdd20c33f65d952f6446d9bd2 if (mmc_blk_alloc_parts(card, md)) goto out; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index e55cde6d436dddae261c69ef36ca4de93eaa01ac..48e341b6ba6dde26605e7f9e8b9aa84c7ea268fa 100644 +index 2553d903a82b9eaa8577c1269bc9f63e18b00085..59a4044ea4c2e1283b1cad8afc7e67efaf8653fb 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c -@@ -2289,7 +2289,8 @@ EXPORT_SYMBOL(mmc_erase); +@@ -2409,7 +2409,8 @@ EXPORT_SYMBOL(mmc_erase); int mmc_can_erase(struct mmc_card *card) { if ((card->host->caps & MMC_CAP_ERASE) && @@ -73746,7 +71283,7 @@ index e55cde6d436dddae261c69ef36ca4de93eaa01ac..48e341b6ba6dde26605e7f9e8b9aa84c return 0; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h -index d8673ca968ba2d65fb3da39680583ca5152641e4..510c3872929b3267fb6665bb69d26f5aca740a28 100644 +index 73fad83acbcb6a157587180516f9ffe7c61eb7d7..e7c9d3098ac06e3c6554fa3373a311f937cd6f96 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -283,6 +283,9 @@ struct mmc_card { @@ -73760,10 +71297,10 @@ index d8673ca968ba2d65fb3da39680583ca5152641e4..510c3872929b3267fb6665bb69d26f5a unsigned int erase_shift; /* if erase unit is power 2 */ unsigned int pref_erase; /* in sectors */ -From a27a20db497c1caeba48369323b1821981851d35 Mon Sep 17 00:00:00 2001 +From 9fdd0d7cfa05e00b524b177adabf050922e57afb Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 040/208] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 037/111] cma: Add vc_cma driver to enable use of CMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -73784,10 +71321,10 @@ Signed-off-by: Noralf Trønnes drivers/char/Makefile | 1 + drivers/char/broadcom/Kconfig | 15 + drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_cma/Makefile | 14 + + drivers/char/broadcom/vc_cma/Makefile | 7 + drivers/char/broadcom/vc_cma/vc_cma.c | 1193 +++++++++++++++++++++++++++++++++ include/linux/broadcom/vc_cma.h | 36 + - 7 files changed, 1262 insertions(+) + 7 files changed, 1255 insertions(+) create mode 100644 drivers/char/broadcom/Kconfig create mode 100644 drivers/char/broadcom/Makefile create mode 100644 drivers/char/broadcom/vc_cma/Makefile @@ -73846,20 +71383,13 @@ index 0000000000000000000000000000000000000000..13c5bca291ccc0df090c4e61169ace8f +obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ diff --git a/drivers/char/broadcom/vc_cma/Makefile b/drivers/char/broadcom/vc_cma/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..6a94de4a7576f7c608f5bd01eb9f21a1a852120f +index 0000000000000000000000000000000000000000..d222313e28995bb54e9448192f5c99a352dde2e8 --- /dev/null +++ b/drivers/char/broadcom/vc_cma/Makefile -@@ -0,0 +1,14 @@ -+ccflags-y += -Wall -Wstrict-prototypes -Wno-trigraphs -+ccflags-y += -Werror -+ccflags-y += -Iinclude/linux/broadcom -+ccflags-y += -Idrivers/misc/vc04_services -+ccflags-y += -Idrivers/misc/vc04_services/interface/vchi -+ccflags-y += -Idrivers/misc/vc04_services/interface/vchiq_arm -+ -+ccflags-y += -D__KERNEL__ -+ccflags-y += -D__linux__ -+ccflags-y += -Werror +@@ -0,0 +1,7 @@ ++ccflags-$(CONFIG_BCM_VC_CMA) += -Wall -Wstrict-prototypes -Wno-trigraphs -Werror ++ccflags-$(CONFIG_BCM_VC_CMA) += -Iinclude/linux/broadcom -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vchi -Idrivers/staging/vc04_services/interface/vchiq_arm ++ccflags-$(CONFIG_BCM_VC_CMA) += -D__KERNEL__ -D__linux__ + +obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o + @@ -75106,10 +72636,10 @@ index 0000000000000000000000000000000000000000..be2819d5d41f9d5ed65daf8eedb94c9e + +#endif /* VC_CMA_H */ -From 81396ee5aaaa0cdc1c4c7fadd11dd1d7a3e88fae Mon Sep 17 00:00:00 2001 +From 193d82ddc048edea6b73997a51324a5078d17206 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 041/208] bcm2708: alsa sound driver +Subject: [PATCH 038/111] bcm2708: alsa sound driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -75164,7 +72694,7 @@ See: https://github.com/raspberrypi/linux/issues/1560 snd-bcm2835: Use bcm2835_hw params in preallocate --- - sound/arm/Kconfig | 8 + + sound/arm/Kconfig | 7 + sound/arm/Makefile | 5 + sound/arm/bcm2835-ctl.c | 350 +++++++++++++++ sound/arm/bcm2835-pcm.c | 563 +++++++++++++++++++++++ @@ -75172,7 +72702,7 @@ snd-bcm2835: Use bcm2835_hw params in preallocate sound/arm/bcm2835.c | 511 +++++++++++++++++++++ sound/arm/bcm2835.h | 167 +++++++ sound/arm/vc_vchi_audioserv_defs.h | 116 +++++ - 8 files changed, 2609 insertions(+) + 8 files changed, 2608 insertions(+) create mode 100755 sound/arm/bcm2835-ctl.c create mode 100755 sound/arm/bcm2835-pcm.c create mode 100755 sound/arm/bcm2835-vchiq.c @@ -75181,17 +72711,16 @@ snd-bcm2835: Use bcm2835_hw params in preallocate create mode 100644 sound/arm/vc_vchi_audioserv_defs.h diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 65171f6657a2984ccc14ce907a4c7c87d77d196b..8883c2f3a3269742e2bf6fc995643fb282f3509a 100644 +index 65171f6657a2984ccc14ce907a4c7c87d77d196b..02b6d263035ca18c9ce53229369dfb00915c260b 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig -@@ -32,6 +32,14 @@ config SND_PXA2XX_AC97 +@@ -32,6 +32,13 @@ config SND_PXA2XX_AC97 Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. +config SND_BCM2835 + tristate "BCM2835 ALSA driver" -+ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ -+ && BCM2708_VCHIQ && SND ++ depends on ARCH_BCM2835 && BCM2708_VCHIQ && SND + select SND_PCM + help + Say Y or M if you want to support BCM2835 Alsa pcm card driver @@ -75200,7 +72729,7 @@ index 65171f6657a2984ccc14ce907a4c7c87d77d196b..8883c2f3a3269742e2bf6fc995643fb2 config SND_PXA2XX_LIB diff --git a/sound/arm/Makefile b/sound/arm/Makefile -index 8c0c851d464109819beb296c2624bbec7af131e9..6796d7f5c7803ccfdaadbe56b2520c5454678686 100644 +index 8c0c851d464109819beb296c2624bbec7af131e9..26aabea79a0b5f141f7644a96684470d9b72f681 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -14,3 +14,8 @@ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o @@ -75211,7 +72740,7 @@ index 8c0c851d464109819beb296c2624bbec7af131e9..6796d7f5c7803ccfdaadbe56b2520c54 +obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o +snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o + -+ccflags-y += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 ++ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 diff --git a/sound/arm/bcm2835-ctl.c b/sound/arm/bcm2835-ctl.c new file mode 100755 index 0000000000000000000000000000000000000000..75dc3224be7ce8353378e9676ad2c6847dd0750b @@ -77845,13378 +75374,11 @@ index 0000000000000000000000000000000000000000..af3e6eb690113fc32ce9e06bd2f0f294 + +#endif // _VC_AUDIO_DEFS_H_ -From 5c7989bc7855400db08a481fef1a9caf9e32be2a Mon Sep 17 00:00:00 2001 +From 28996ccfaf3ff7a0873b2d895cab663cce800fdd Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 042/208] bcm2708 vchiq driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: popcornmix - -vchiq: create_pagelist copes with vmalloc memory - -Signed-off-by: Daniel Stone - -vchiq: fix the shim message release - -Signed-off-by: Daniel Stone - -vchiq: export additional symbols - -Signed-off-by: Daniel Stone - -VCHIQ: Make service closure fully synchronous (drv) - -This is one half of a two-part patch, the other half of which is to -the vchiq_lib user library. With these patches, calls to -vchiq_close_service and vchiq_remove_service won't return until any -associated callbacks have been delivered to the callback thread. - -VCHIQ: Add per-service tracing - -The new service option VCHIQ_SERVICE_OPTION_TRACE is a boolean that -toggles tracing for the specified service. - -This commit also introduces vchi_service_set_option and the associated -option VCHI_SERVICE_OPTION_TRACE. - -vchiq: Make the synchronous-CLOSE logic more tolerant - -vchiq: Move logging control into debugfs - -vchiq: Take care of a corner case tickled by VCSM - -Closing a connection that isn't fully open requires care, since one -side does not know the other side's port number. Code was present to -handle the case where a CLOSE is sent immediately after an OPEN, i.e. -before the OPENACK has been received, but this was incorrectly being -used when an OPEN from a client using port 0 was rejected. - -(In the observed failure, the host was attempting to use the VCSM -service, which isn't present in the 'cutdown' firmware. The failure -was intermittent because sometimes the keepalive service would -grab port 0.) - -This case can be distinguished because the client's remoteport will -still be VCHIQ_PORT_FREE, and the srvstate will be OPENING. Either -condition is sufficient to differentiate it from the special case -described above. - -vchiq: Avoid high load when blocked and unkillable - -vchiq: Include SIGSTOP and SIGCONT in list of signals not-masked by vchiq to allow gdb to work - -vchiq_arm: Complete support for SYNCHRONOUS mode - -vchiq: Remove inline from suspend/resume - -vchiq: Allocation does not need to be atomic - -vchiq: Fix wrong condition check - -The log level is checked from within the log call. Remove the check in the call. - -Signed-off-by: Pranith Kumar - -BCM270x: Add vchiq device to platform file and Device Tree - -Prepare to turn the vchiq module into a driver. - -Signed-off-by: Noralf Trønnes - -bcm2708: vchiq: Add Device Tree support - -Turn vchiq into a driver and stop hardcoding resources. -Use devm_* functions in probe path to simplify cleanup. -A global variable is used to hold the register address. This is done -to keep this patch as small as possible. -Also make available on ARCH_BCM2835. -Based on work by Lubomir Rintel. - -Signed-off-by: Noralf Trønnes - -vchiq: Change logging level for inbound data - -vchiq_arm: Two cacheing fixes - -1) Make fragment size vary with cache line size -Without this patch, non-cache-line-aligned transfers may corrupt -(or be corrupted by) adjacent data structures. - -Both ARM and VC need to be updated to enable this feature. This is -ensured by having the loader apply a new DT parameter - -cache-line-size. The existence of this parameter guarantees that the -kernel is capable, and the parameter will only be modified from the -safe default if the loader is capable. - -2) Flush/invalidate vmalloc'd memory, and invalidate after reads - -vchiq: fix NULL pointer dereference when closing driver - -The following code run as root will cause a null pointer dereference oops: - - int fd = open("/dev/vc-cma", O_RDONLY); - if (fd < 0) - err(1, "open failed"); - (void)close(fd); - -[ 1704.877721] Unable to handle kernel NULL pointer dereference at virtual address 00000000 -[ 1704.877725] pgd = b899c000 -[ 1704.877736] [00000000] *pgd=37fab831, *pte=00000000, *ppte=00000000 -[ 1704.877748] Internal error: Oops: 817 [#1] PREEMPT SMP ARM -[ 1704.877765] Modules linked in: evdev i2c_bcm2708 uio_pdrv_genirq uio -[ 1704.877774] CPU: 2 PID: 3656 Comm: stress-ng-fstat Not tainted 3.19.1-12-generic-bcm2709 #12-Ubuntu -[ 1704.877777] Hardware name: BCM2709 -[ 1704.877783] task: b8ab9b00 ti: b7e68000 task.ti: b7e68000 -[ 1704.877798] PC is at __down_interruptible+0x50/0xec -[ 1704.877806] LR is at down_interruptible+0x5c/0x68 -[ 1704.877813] pc : [<80630ee8>] lr : [<800704b0>] psr: 60080093 -sp : b7e69e50 ip : b7e69e88 fp : b7e69e84 -[ 1704.877817] r10: b88123c8 r9 : 00000010 r8 : 00000001 -[ 1704.877822] r7 : b8ab9b00 r6 : 7fffffff r5 : 80a1cc34 r4 : 80a1cc34 -[ 1704.877826] r3 : b7e69e50 r2 : 00000000 r1 : 00000000 r0 : 80a1cc34 -[ 1704.877833] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user -[ 1704.877838] Control: 10c5387d Table: 3899c06a DAC: 00000015 -[ 1704.877843] Process do-oops (pid: 3656, stack limit = 0xb7e68238) -[ 1704.877848] Stack: (0xb7e69e50 to 0xb7e6a000) -[ 1704.877856] 9e40: 80a1cc3c 00000000 00000010 b88123c8 -[ 1704.877865] 9e60: b7e69e84 80a1cc34 fff9fee9 ffffffff b7e68000 00000009 b7e69ea4 b7e69e88 -[ 1704.877874] 9e80: 800704b0 80630ea4 fff9fee9 60080013 80a1cc28 fff9fee9 b7e69edc b7e69ea8 -[ 1704.877884] 9ea0: 8040f558 80070460 fff9fee9 ffffffff 00000000 00000000 00000009 80a1cb7c -[ 1704.877893] 9ec0: 00000000 80a1cb7c 00000000 00000010 b7e69ef4 b7e69ee0 803e1ba4 8040f514 -[ 1704.877902] 9ee0: 00000e48 80a1cb7c b7e69f14 b7e69ef8 803e1c9c 803e1b74 b88123c0 b92acb18 -[ 1704.877911] 9f00: b8812790 b8d815d8 b7e69f24 b7e69f18 803e2250 803e1bc8 b7e69f5c b7e69f28 -[ 1704.877921] 9f20: 80167bac 803e222c 00000000 00000000 b7e69f54 b8ab9ffc 00000000 8098c794 -[ 1704.877930] 9f40: b8ab9b00 8000efc4 b7e68000 00000000 b7e69f6c b7e69f60 80167d6c 80167b28 -[ 1704.877939] 9f60: b7e69f8c b7e69f70 80047d38 80167d60 b7e68000 b7e68010 8000efc4 b7e69fb0 -[ 1704.877949] 9f80: b7e69fac b7e69f90 80012820 80047c84 01155490 011549a8 00000001 00000006 -[ 1704.877957] 9fa0: 00000000 b7e69fb0 8000ee5c 80012790 00000000 353d8c0f 7efc4308 00000000 -[ 1704.877966] 9fc0: 01155490 011549a8 00000001 00000006 00000000 00000000 76cf3ba0 00000003 -[ 1704.877975] 9fe0: 00000000 7efc42e4 0002272f 76e2ed66 60080030 00000003 00000000 00000000 -[ 1704.877998] [<80630ee8>] (__down_interruptible) from [<800704b0>] (down_interruptible+0x5c/0x68) -[ 1704.878015] [<800704b0>] (down_interruptible) from [<8040f558>] (vchiu_queue_push+0x50/0xd8) -[ 1704.878032] [<8040f558>] (vchiu_queue_push) from [<803e1ba4>] (send_worker_msg+0x3c/0x54) -[ 1704.878045] [<803e1ba4>] (send_worker_msg) from [<803e1c9c>] (vc_cma_set_reserve+0xe0/0x1c4) -[ 1704.878057] [<803e1c9c>] (vc_cma_set_reserve) from [<803e2250>] (vc_cma_release+0x30/0x38) -[ 1704.878069] [<803e2250>] (vc_cma_release) from [<80167bac>] (__fput+0x90/0x1e0) -[ 1704.878082] [<80167bac>] (__fput) from [<80167d6c>] (____fput+0x18/0x1c) -[ 1704.878094] [<80167d6c>] (____fput) from [<80047d38>] (task_work_run+0xc0/0xf8) -[ 1704.878109] [<80047d38>] (task_work_run) from [<80012820>] (do_work_pending+0x9c/0xc4) -[ 1704.878123] [<80012820>] (do_work_pending) from [<8000ee5c>] (work_pending+0xc/0x20) -[ 1704.878133] Code: e50b1034 e3a01000 e50b2030 e580300c (e5823000) - -..the fix is to ensure that we have actually initialized the queue before we attempt -to push any items onto it. This occurs if we do an open() followed by a close() without -any activity in between. - -Signed-off-by: Colin Ian King - -vchiq_arm: Sort out the vmalloc case - -See: https://github.com/raspberrypi/linux/issues/1055 - -vchiq: hack: Add include depecated dma include file - -vchiq_arm: Tweak the logging output - -Signed-off-by: Phil Elwell - -vchiq_arm: Access the dequeue_pending flag locked - -Reading through this code looking for another problem (now found in userland) -the use of dequeue_pending outside a lock didn't seem safe. - -Signed-off-by: Phil Elwell - -vchiq_arm: Service callbacks must not fail - -Service callbacks are not allowed to return an error. The internal callback -that delivers events and messages to user tasks does not enqueue them if -the service is closing, but this is not an error and should not be -reported as such. - -Signed-off-by: Phil Elwell - -vchiq_arm: do not use page_cache_release(page) macro (#1403) - -This macro is gone since 1fa64f198b9f8d6ec0f7aec7c18dc94684391140. - -Signed-off-by: Slawomir Stepien - -vchiq: Upate to match get_user_pages prototype - -vchiq_arm: Add completion records under the mutex - -An issue was observed when flushing openmax components -which generate a large number of messages returning -buffers to host. - -We occasionally found a duplicate message from 16 -messages prior, resulting in a buffer returned twice. - -While only one thread adds completions, without the -mutex you don't get the protection of the automatic -memory barrier you get with synchronisation objects. - -Signed-off-by: Phil Elwell ---- - arch/arm/mach-bcm2708/include/mach/platform.h | 2 + - arch/arm/mach-bcm2709/include/mach/platform.h | 2 + - drivers/misc/Kconfig | 1 + - drivers/misc/Makefile | 1 + - drivers/misc/vc04_services/Kconfig | 9 + - drivers/misc/vc04_services/Makefile | 14 + - .../interface/vchi/connections/connection.h | 328 ++ - .../interface/vchi/message_drivers/message.h | 204 + - drivers/misc/vc04_services/interface/vchi/vchi.h | 378 ++ - .../misc/vc04_services/interface/vchi/vchi_cfg.h | 224 ++ - .../interface/vchi/vchi_cfg_internal.h | 71 + - .../vc04_services/interface/vchi/vchi_common.h | 175 + - .../misc/vc04_services/interface/vchi/vchi_mh.h | 42 + - .../misc/vc04_services/interface/vchiq_arm/vchiq.h | 40 + - .../vc04_services/interface/vchiq_arm/vchiq_2835.h | 42 + - .../interface/vchiq_arm/vchiq_2835_arm.c | 586 +++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2921 +++++++++++++++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 220 ++ - .../interface/vchiq_arm/vchiq_build_info.h | 37 + - .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 69 + - .../interface/vchiq_arm/vchiq_connected.c | 120 + - .../interface/vchiq_arm/vchiq_connected.h | 50 + - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 3933 ++++++++++++++++++++ - .../vc04_services/interface/vchiq_arm/vchiq_core.h | 712 ++++ - .../interface/vchiq_arm/vchiq_debugfs.c | 383 ++ - .../interface/vchiq_arm/vchiq_debugfs.h | 52 + - .../interface/vchiq_arm/vchiq_genversion | 87 + - .../vc04_services/interface/vchiq_arm/vchiq_if.h | 189 + - .../interface/vchiq_arm/vchiq_ioctl.h | 131 + - .../interface/vchiq_arm/vchiq_kern_lib.c | 458 +++ - .../interface/vchiq_arm/vchiq_killable.h | 69 + - .../interface/vchiq_arm/vchiq_memdrv.h | 71 + - .../interface/vchiq_arm/vchiq_pagelist.h | 58 + - .../vc04_services/interface/vchiq_arm/vchiq_shim.c | 860 +++++ - .../vc04_services/interface/vchiq_arm/vchiq_util.c | 156 + - .../vc04_services/interface/vchiq_arm/vchiq_util.h | 82 + - .../interface/vchiq_arm/vchiq_version.c | 59 + - 37 files changed, 12836 insertions(+) - create mode 100644 drivers/misc/vc04_services/Kconfig - create mode 100644 drivers/misc/vc04_services/Makefile - create mode 100644 drivers/misc/vc04_services/interface/vchi/connections/connection.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/message_drivers/message.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_cfg.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_common.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_mh.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c - -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -index 4fb43cf391e50e702d0a0588ceff397c79c501d7..e98ec5acc70ba9eb2bc7ff560ed3c92e21518b73 100644 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -78,6 +78,8 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - /* - * Watchdog -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -index 311b9f26fab7dd770bdcd684c7691442b0872d55..9a638f528fcebc9206419a2cc68f3c9856dda3c3 100644 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -78,6 +78,8 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - /* - * Watchdog -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index d002528289667732e9032f68aa0dba6624abfd9c..dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -802,6 +802,7 @@ source "drivers/misc/lis3lv02d/Kconfig" - source "drivers/misc/altera-stapl/Kconfig" - source "drivers/misc/mei/Kconfig" - source "drivers/misc/vmw_vmci/Kconfig" -+source "drivers/misc/vc04_services/Kconfig" - source "drivers/misc/mic/Kconfig" - source "drivers/misc/genwqe/Kconfig" - source "drivers/misc/echo/Kconfig" -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index fb32516ddfe2e4f8112beee9e831bcc4eb729667..bdf0f5fe7be52b16e12e0bbc79ebfe58a084794d 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_INTEL_MEI) += mei/ - obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ - obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o - obj-$(CONFIG_SRAM) += sram.o -+obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ - obj-y += mic/ - obj-$(CONFIG_GENWQE) += genwqe/ - obj-$(CONFIG_ECHO) += echo/ -diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..db8e1beb89f9f8c48ea5964016c8285ea82497d8 ---- /dev/null -+++ b/drivers/misc/vc04_services/Kconfig -@@ -0,0 +1,9 @@ -+config BCM2708_VCHIQ -+ tristate "Videocore VCHIQ" -+ depends on RASPBERRYPI_FIRMWARE -+ default y -+ help -+ Kernel to VideoCore communication interface for the -+ BCM2708 family of products. -+ Defaults to Y when the Broadcom Videocore services -+ are included in the build, N otherwise. -diff --git a/drivers/misc/vc04_services/Makefile b/drivers/misc/vc04_services/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..8d038feb42105cb2cad688690086ba69379b12e1 ---- /dev/null -+++ b/drivers/misc/vc04_services/Makefile -@@ -0,0 +1,14 @@ -+obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o -+ -+vchiq-objs := \ -+ interface/vchiq_arm/vchiq_core.o \ -+ interface/vchiq_arm/vchiq_arm.o \ -+ interface/vchiq_arm/vchiq_kern_lib.o \ -+ interface/vchiq_arm/vchiq_2835_arm.o \ -+ interface/vchiq_arm/vchiq_debugfs.o \ -+ interface/vchiq_arm/vchiq_shim.o \ -+ interface/vchiq_arm/vchiq_util.o \ -+ interface/vchiq_arm/vchiq_connected.o \ -+ -+ccflags-y += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -+ -diff --git a/drivers/misc/vc04_services/interface/vchi/connections/connection.h b/drivers/misc/vc04_services/interface/vchi/connections/connection.h -new file mode 100644 -index 0000000000000000000000000000000000000000..fef6ac34c6d2c04dfdba66f33850e72c24c613c2 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/connections/connection.h -@@ -0,0 +1,328 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef CONNECTION_H_ -+#define CONNECTION_H_ -+ -+#include -+#include -+#include -+ -+#include "interface/vchi/vchi_cfg_internal.h" -+#include "interface/vchi/vchi_common.h" -+#include "interface/vchi/message_drivers/message.h" -+ -+/****************************************************************************** -+ Global defs -+ *****************************************************************************/ -+ -+// Opaque handle for a connection / service pair -+typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T; -+ -+// opaque handle to the connection state information -+typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T; -+ -+typedef struct vchi_connection_t VCHI_CONNECTION_T; -+ -+ -+/****************************************************************************** -+ API -+ *****************************************************************************/ -+ -+// Routine to init a connection with a particular low level driver -+typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection, -+ const VCHI_MESSAGE_DRIVER_T * driver ); -+ -+// Routine to control CRC enabling at a connection level -+typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle, -+ VCHI_CRC_CONTROL_T control ); -+ -+// Routine to create a service -+typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle, -+ int32_t service_id, -+ uint32_t rx_fifo_size, -+ uint32_t tx_fifo_size, -+ int server, -+ VCHI_CALLBACK_T callback, -+ void *callback_param, -+ int32_t want_crc, -+ int32_t want_unaligned_bulk_rx, -+ int32_t want_unaligned_bulk_tx, -+ VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle ); -+ -+// Routine to close a service -+typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle ); -+ -+// Routine to queue a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// scatter-gather (vector) message queueing -+typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// Routine to dequeue a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *data, -+ uint32_t max_data_size_to_read, -+ uint32_t *actual_msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to peek at a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to hold a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags, -+ void **message_handle ); -+ -+// Routine to initialise a received message iterator -+typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ VCHI_MSG_ITER_T *iter, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to release a held message -+typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *message_handle ); -+ -+// Routine to get info on a held message -+typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *message_handle, -+ void **data, -+ int32_t *msg_size, -+ uint32_t *tx_timestamp, -+ uint32_t *rx_timestamp ); -+ -+// Routine to check whether the iterator has a next message -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ const VCHI_MSG_ITER_T *iter ); -+ -+// Routine to advance the iterator -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ VCHI_MSG_ITER_T *iter, -+ void **data, -+ uint32_t *msg_size ); -+ -+// Routine to remove the last message returned by the iterator -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ VCHI_MSG_ITER_T *iter ); -+ -+// Routine to hold the last message returned by the iterator -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ VCHI_MSG_ITER_T *iter, -+ void **msg_handle ); -+ -+// Routine to transmit bulk data -+typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ const void *data_src, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle ); -+ -+// Routine to receive data -+typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *data_dst, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle ); -+ -+// Routine to report if a server is available -+typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t peer_flags ); -+ -+// Routine to report the number of RX slots available -+typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state ); -+ -+// Routine to report the RX slot size -+typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state ); -+ -+// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO -+typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state, -+ int32_t service, -+ uint32_t length, -+ MESSAGE_TX_CHANNEL_T channel, -+ uint32_t channel_params, -+ uint32_t data_length, -+ uint32_t data_offset); -+ -+// Callback to inform a service that a Xon or Xoff message has been received -+typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t xoff); -+ -+// Callback to inform a service that a server available reply message has been received -+typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, uint32_t flags); -+ -+// Callback to indicate that bulk auxiliary messages have arrived -+typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state); -+ -+// Callback to indicate that bulk auxiliary messages have arrived -+typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle); -+ -+// Callback with all the connection info you require -+typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size); -+ -+// Callback to inform of a disconnect -+typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags); -+ -+// Callback to inform of a power control request -+typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, int32_t enable); -+ -+// allocate memory suitably aligned for this connection -+typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length); -+ -+// free memory allocated by buffer_allocate -+typedef void (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address); -+ -+ -+/****************************************************************************** -+ System driver struct -+ *****************************************************************************/ -+ -+struct opaque_vchi_connection_api_t -+{ -+ // Routine to init the connection -+ VCHI_CONNECTION_INIT_T init; -+ -+ // Connection-level CRC control -+ VCHI_CONNECTION_CRC_CONTROL_T crc_control; -+ -+ // Routine to connect to or create service -+ VCHI_CONNECTION_SERVICE_CONNECT_T service_connect; -+ -+ // Routine to disconnect from a service -+ VCHI_CONNECTION_SERVICE_DISCONNECT_T service_disconnect; -+ -+ // Routine to queue a message -+ VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T service_queue_msg; -+ -+ // scatter-gather (vector) message queue -+ VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T service_queue_msgv; -+ -+ // Routine to dequeue a message -+ VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T service_dequeue_msg; -+ -+ // Routine to peek at a message -+ VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T service_peek_msg; -+ -+ // Routine to hold a message -+ VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T service_hold_msg; -+ -+ // Routine to initialise a received message iterator -+ VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg; -+ -+ // Routine to release a message -+ VCHI_CONNECTION_HELD_MSG_RELEASE_T held_msg_release; -+ -+ // Routine to get information on a held message -+ VCHI_CONNECTION_HELD_MSG_INFO_T held_msg_info; -+ -+ // Routine to check for next message on iterator -+ VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T msg_iter_has_next; -+ -+ // Routine to get next message on iterator -+ VCHI_CONNECTION_MSG_ITER_NEXT_T msg_iter_next; -+ -+ // Routine to remove the last message returned by iterator -+ VCHI_CONNECTION_MSG_ITER_REMOVE_T msg_iter_remove; -+ -+ // Routine to hold the last message returned by iterator -+ VCHI_CONNECTION_MSG_ITER_HOLD_T msg_iter_hold; -+ -+ // Routine to transmit bulk data -+ VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T bulk_queue_transmit; -+ -+ // Routine to receive data -+ VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T bulk_queue_receive; -+ -+ // Routine to report the available servers -+ VCHI_CONNECTION_SERVER_PRESENT server_present; -+ -+ // Routine to report the number of RX slots available -+ VCHI_CONNECTION_RX_SLOTS_AVAILABLE connection_rx_slots_available; -+ -+ // Routine to report the RX slot size -+ VCHI_CONNECTION_RX_SLOT_SIZE connection_rx_slot_size; -+ -+ // Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO -+ VCHI_CONNECTION_RX_BULK_BUFFER_ADDED rx_bulk_buffer_added; -+ -+ // Callback to inform a service that a Xon or Xoff message has been received -+ VCHI_CONNECTION_FLOW_CONTROL flow_control; -+ -+ // Callback to inform a service that a server available reply message has been received -+ VCHI_CONNECTION_SERVER_AVAILABLE_REPLY server_available_reply; -+ -+ // Callback to indicate that bulk auxiliary messages have arrived -+ VCHI_CONNECTION_BULK_AUX_RECEIVED bulk_aux_received; -+ -+ // Callback to indicate that a bulk auxiliary message has been transmitted -+ VCHI_CONNECTION_BULK_AUX_TRANSMITTED bulk_aux_transmitted; -+ -+ // Callback to provide information about the connection -+ VCHI_CONNECTION_INFO connection_info; -+ -+ // Callback to notify that peer has requested disconnect -+ VCHI_CONNECTION_DISCONNECT disconnect; -+ -+ // Callback to notify that peer has requested power change -+ VCHI_CONNECTION_POWER_CONTROL power_control; -+ -+ // allocate memory suitably aligned for this connection -+ VCHI_BUFFER_ALLOCATE buffer_allocate; -+ -+ // free memory allocated by buffer_allocate -+ VCHI_BUFFER_FREE buffer_free; -+ -+}; -+ -+struct vchi_connection_t { -+ const VCHI_CONNECTION_API_T *api; -+ VCHI_CONNECTION_STATE_T *state; -+#ifdef VCHI_COARSE_LOCKING -+ struct semaphore sem; -+#endif -+}; -+ -+ -+#endif /* CONNECTION_H_ */ -+ -+/****************************** End of file **********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h b/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h -new file mode 100644 -index 0000000000000000000000000000000000000000..8b3f76735bd45ab09a12dc6e17e335241fd11755 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h -@@ -0,0 +1,204 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef _VCHI_MESSAGE_H_ -+#define _VCHI_MESSAGE_H_ -+ -+#include -+#include -+#include -+ -+#include "interface/vchi/vchi_cfg_internal.h" -+#include "interface/vchi/vchi_common.h" -+ -+ -+typedef enum message_event_type { -+ MESSAGE_EVENT_NONE, -+ MESSAGE_EVENT_NOP, -+ MESSAGE_EVENT_MESSAGE, -+ MESSAGE_EVENT_SLOT_COMPLETE, -+ MESSAGE_EVENT_RX_BULK_PAUSED, -+ MESSAGE_EVENT_RX_BULK_COMPLETE, -+ MESSAGE_EVENT_TX_COMPLETE, -+ MESSAGE_EVENT_MSG_DISCARDED -+} MESSAGE_EVENT_TYPE_T; -+ -+typedef enum vchi_msg_flags -+{ -+ VCHI_MSG_FLAGS_NONE = 0x0, -+ VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1 -+} VCHI_MSG_FLAGS_T; -+ -+typedef enum message_tx_channel -+{ -+ MESSAGE_TX_CHANNEL_MESSAGE = 0, -+ MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards -+} MESSAGE_TX_CHANNEL_T; -+ -+// Macros used for cycling through bulk channels -+#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) -+#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) -+ -+typedef enum message_rx_channel -+{ -+ MESSAGE_RX_CHANNEL_MESSAGE = 0, -+ MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards -+} MESSAGE_RX_CHANNEL_T; -+ -+// Message receive slot information -+typedef struct rx_msg_slot_info { -+ -+ struct rx_msg_slot_info *next; -+ //struct slot_info *prev; -+#if !defined VCHI_COARSE_LOCKING -+ struct semaphore sem; -+#endif -+ -+ uint8_t *addr; // base address of slot -+ uint32_t len; // length of slot in bytes -+ -+ uint32_t write_ptr; // hardware causes this to advance -+ uint32_t read_ptr; // this module does the reading -+ int active; // is this slot in the hardware dma fifo? -+ uint32_t msgs_parsed; // count how many messages are in this slot -+ uint32_t msgs_released; // how many messages have been released -+ void *state; // connection state information -+ uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services -+} RX_MSG_SLOTINFO_T; -+ -+// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out. -+// In particular, it mustn't use addr and len - they're the client buffer, but the message -+// driver will be tasked with sending the aligned core section. -+typedef struct rx_bulk_slotinfo_t { -+ struct rx_bulk_slotinfo_t *next; -+ -+ struct semaphore *blocking; -+ -+ // needed by DMA -+ void *addr; -+ uint32_t len; -+ -+ // needed for the callback -+ void *service; -+ void *handle; -+ VCHI_FLAGS_T flags; -+} RX_BULK_SLOTINFO_T; -+ -+ -+/* ---------------------------------------------------------------------- -+ * each connection driver will have a pool of the following struct. -+ * -+ * the pool will be managed by vchi_qman_* -+ * this means there will be multiple queues (single linked lists) -+ * a given struct message_info will be on exactly one of these queues -+ * at any one time -+ * -------------------------------------------------------------------- */ -+typedef struct rx_message_info { -+ -+ struct message_info *next; -+ //struct message_info *prev; -+ -+ uint8_t *addr; -+ uint32_t len; -+ RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message -+ uint32_t tx_timestamp; -+ uint32_t rx_timestamp; -+ -+} RX_MESSAGE_INFO_T; -+ -+typedef struct { -+ MESSAGE_EVENT_TYPE_T type; -+ -+ struct { -+ // for messages -+ void *addr; // address of message -+ uint16_t slot_delta; // whether this message indicated slot delta -+ uint32_t len; // length of message -+ RX_MSG_SLOTINFO_T *slot; // slot this message is in -+ int32_t service; // service id this message is destined for -+ uint32_t tx_timestamp; // timestamp from the header -+ uint32_t rx_timestamp; // timestamp when we parsed it -+ } message; -+ -+ // FIXME: cleanup slot reporting... -+ RX_MSG_SLOTINFO_T *rx_msg; -+ RX_BULK_SLOTINFO_T *rx_bulk; -+ void *tx_handle; -+ MESSAGE_TX_CHANNEL_T tx_channel; -+ -+} MESSAGE_EVENT_T; -+ -+ -+// callbacks -+typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state ); -+ -+typedef struct { -+ VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback; -+} VCHI_MESSAGE_DRIVER_OPEN_T; -+ -+ -+// handle to this instance of message driver (as returned by ->open) -+typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T; -+ -+struct opaque_vchi_message_driver_t { -+ VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state ); -+ int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle ); -+ int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle ); -+ int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, int32_t enable ); -+ int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message -+ int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk) -+ int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk) -+ void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver -+ int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle ); -+ int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, int32_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void -+ *address, uint32_t length_avail, uint32_t max_total_length, int32_t pad_to_fill, int32_t allow_partial ); -+ -+ int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count ); -+ int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length ); -+ void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length ); -+ void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address ); -+ int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); -+ int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); -+ -+ int32_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); -+ uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); -+ int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); -+ int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel ); -+ void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len ); -+ void (*debug)( VCHI_MDRIVER_HANDLE_T *handle ); -+}; -+ -+ -+#endif // _VCHI_MESSAGE_H_ -+ -+/****************************** End of file ***********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi.h b/drivers/misc/vc04_services/interface/vchi/vchi.h -new file mode 100644 -index 0000000000000000000000000000000000000000..1b17e98f737979eef19906609bc19ecd19455618 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi.h -@@ -0,0 +1,378 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_H_ -+#define VCHI_H_ -+ -+#include "interface/vchi/vchi_cfg.h" -+#include "interface/vchi/vchi_common.h" -+#include "interface/vchi/connections/connection.h" -+#include "vchi_mh.h" -+ -+ -+/****************************************************************************** -+ Global defs -+ *****************************************************************************/ -+ -+#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1)) -+#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1)) -+#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1)))) -+ -+#ifdef USE_VCHIQ_ARM -+#define VCHI_BULK_ALIGNED(x) 1 -+#else -+#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0) -+#endif -+ -+struct vchi_version { -+ uint32_t version; -+ uint32_t version_min; -+}; -+#define VCHI_VERSION(v_) { v_, v_ } -+#define VCHI_VERSION_EX(v_, m_) { v_, m_ } -+ -+typedef enum -+{ -+ VCHI_VEC_POINTER, -+ VCHI_VEC_HANDLE, -+ VCHI_VEC_LIST -+} VCHI_MSG_VECTOR_TYPE_T; -+ -+typedef struct vchi_msg_vector_ex { -+ -+ VCHI_MSG_VECTOR_TYPE_T type; -+ union -+ { -+ // a memory handle -+ struct -+ { -+ VCHI_MEM_HANDLE_T handle; -+ uint32_t offset; -+ int32_t vec_len; -+ } handle; -+ -+ // an ordinary data pointer -+ struct -+ { -+ const void *vec_base; -+ int32_t vec_len; -+ } ptr; -+ -+ // a nested vector list -+ struct -+ { -+ struct vchi_msg_vector_ex *vec; -+ uint32_t vec_len; -+ } list; -+ } u; -+} VCHI_MSG_VECTOR_EX_T; -+ -+ -+// Construct an entry in a msg vector for a pointer (p) of length (l) -+#define VCHI_VEC_POINTER(p,l) VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } } -+ -+// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l) -+#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE, { { (h), (o), (l) } } -+ -+// Macros to manipulate 'FOURCC' values -+#define MAKE_FOURCC(x) ((int32_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] )) -+#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF -+ -+ -+// Opaque service information -+struct opaque_vchi_service_t; -+ -+// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold, -+// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only. -+typedef struct -+{ -+ struct opaque_vchi_service_t *service; -+ void *message; -+} VCHI_HELD_MSG_T; -+ -+ -+ -+// structure used to provide the information needed to open a server or a client -+typedef struct { -+ struct vchi_version version; -+ int32_t service_id; -+ VCHI_CONNECTION_T *connection; -+ uint32_t rx_fifo_size; -+ uint32_t tx_fifo_size; -+ VCHI_CALLBACK_T callback; -+ void *callback_param; -+ /* client intends to receive bulk transfers of -+ odd lengths or into unaligned buffers */ -+ int32_t want_unaligned_bulk_rx; -+ /* client intends to transmit bulk transfers of -+ odd lengths or out of unaligned buffers */ -+ int32_t want_unaligned_bulk_tx; -+ /* client wants to check CRCs on (bulk) xfers. -+ Only needs to be set at 1 end - will do both directions. */ -+ int32_t want_crc; -+} SERVICE_CREATION_T; -+ -+// Opaque handle for a VCHI instance -+typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T; -+ -+// Opaque handle for a server or client -+typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T; -+ -+// Service registration & startup -+typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections); -+ -+typedef struct service_info_tag { -+ const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */ -+ VCHI_SERVICE_INIT init; /* Service initialisation function */ -+ void *vll_handle; /* VLL handle; NULL when unloaded or a "static VLL" in build */ -+} SERVICE_INFO_T; -+ -+/****************************************************************************** -+ Global funcs - implementation is specific to which side you are on (local / remote) -+ *****************************************************************************/ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table, -+ const VCHI_MESSAGE_DRIVER_T * low_level); -+ -+ -+// Routine used to initialise the vchi on both local + remote connections -+extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle ); -+ -+extern int32_t vchi_exit( void ); -+ -+extern int32_t vchi_connect( VCHI_CONNECTION_T **connections, -+ const uint32_t num_connections, -+ VCHI_INSTANCE_T instance_handle ); -+ -+//When this is called, ensure that all services have no data pending. -+//Bulk transfers can remain 'queued' -+extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle ); -+ -+// Global control over bulk CRC checking -+extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection, -+ VCHI_CRC_CONTROL_T control ); -+ -+// helper functions -+extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length); -+extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address); -+extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle); -+ -+ -+/****************************************************************************** -+ Global service API -+ *****************************************************************************/ -+// Routine to create a named service -+extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle ); -+ -+// Routine to destory a service -+extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to open a named service -+extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle); -+ -+extern int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, -+ short *peer_version ); -+ -+// Routine to close a named service -+extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to increment ref count on a named service -+extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to decrement ref count on a named service -+extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to set a control option for a named service -+extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle, -+ VCHI_SERVICE_OPTION_T option, -+ int value); -+ -+// Routine to send a message across a service -+extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle, -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// scatter-gather (vector) and send message -+int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_EX_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// legacy scatter-gather (vector) and send message, only handles pointers -+int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// Routine to receive a msg from a service -+// Dequeue is equivalent to hold, copy into client buffer, release -+extern int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle, -+ void *data, -+ uint32_t max_data_size_to_read, -+ uint32_t *actual_msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to look at a message in place. -+// The message is not dequeued, so a subsequent call to peek or dequeue -+// will return the same message. -+extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to remove a message after it has been read in place with peek -+// The first message on the queue is dequeued. -+extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to look at a message in place. -+// The message is dequeued, so the caller is left holding it; the descriptor is -+// filled in and must be released when the user has finished with the message. -+extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle, -+ void **data, // } may be NULL, as info can be -+ uint32_t *msg_size, // } obtained from HELD_MSG_T -+ VCHI_FLAGS_T flags, -+ VCHI_HELD_MSG_T *message_descriptor ); -+ -+// Initialise an iterator to look through messages in place -+extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_ITER_T *iter, -+ VCHI_FLAGS_T flags ); -+ -+/****************************************************************************** -+ Global service support API - operations on held messages and message iterators -+ *****************************************************************************/ -+ -+// Routine to get the address of a held message -+extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to get the size of a held message -+extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to get the transmit timestamp as written into the header by the peer -+extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to get the reception timestamp, written as we parsed the header -+extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to release a held message after it has been processed -+extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message ); -+ -+// Indicates whether the iterator has a next message. -+extern int32_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter ); -+ -+// Return the pointer and length for the next message and advance the iterator. -+extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter, -+ void **data, -+ uint32_t *msg_size ); -+ -+// Remove the last message returned by vchi_msg_iter_next. -+// Can only be called once after each call to vchi_msg_iter_next. -+extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter ); -+ -+// Hold the last message returned by vchi_msg_iter_next. -+// Can only be called once after each call to vchi_msg_iter_next. -+extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter, -+ VCHI_HELD_MSG_T *message ); -+ -+// Return information for the next message, and hold it, advancing the iterator. -+extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter, -+ void **data, // } may be NULL -+ uint32_t *msg_size, // } -+ VCHI_HELD_MSG_T *message ); -+ -+ -+/****************************************************************************** -+ Global bulk API -+ *****************************************************************************/ -+ -+// Routine to prepare interface for a transfer from the other side -+extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle, -+ void *data_dst, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *transfer_handle ); -+ -+ -+// Prepare interface for a transfer from the other side into relocatable memory. -+int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T h_dst, -+ uint32_t offset, -+ uint32_t data_size, -+ const VCHI_FLAGS_T flags, -+ void * const bulk_handle ); -+ -+// Routine to queue up data ready for transfer to the other (once they have signalled they are ready) -+extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle, -+ const void *data_src, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *transfer_handle ); -+ -+ -+/****************************************************************************** -+ Configuration plumbing -+ *****************************************************************************/ -+ -+// function prototypes for the different mid layers (the state info gives the different physical connections) -+extern const VCHI_CONNECTION_API_T *single_get_func_table( void ); -+//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void ); -+//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void ); -+ -+// declare all message drivers here -+const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void ); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+extern int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T h_src, -+ uint32_t offset, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *transfer_handle ); -+#endif /* VCHI_H_ */ -+ -+/****************************** End of file **********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h b/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h -new file mode 100644 -index 0000000000000000000000000000000000000000..26bc2d38d725e3c4c24a4cb894da11e65d01625a ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h -@@ -0,0 +1,224 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_CFG_H_ -+#define VCHI_CFG_H_ -+ -+/**************************************************************************************** -+ * Defines in this first section are part of the VCHI API and may be examined by VCHI -+ * services. -+ ***************************************************************************************/ -+ -+/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */ -+/* Really determined by the message driver, and should be available from a run-time call. */ -+#ifndef VCHI_BULK_ALIGN -+# if __VCCOREVER__ >= 0x04000000 -+# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans -+# else -+# define VCHI_BULK_ALIGN 16 -+# endif -+#endif -+ -+/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */ -+/* May be less than or greater than VCHI_BULK_ALIGN */ -+/* Really determined by the message driver, and should be available from a run-time call. */ -+#ifndef VCHI_BULK_GRANULARITY -+# if __VCCOREVER__ >= 0x04000000 -+# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans -+# else -+# define VCHI_BULK_GRANULARITY 16 -+# endif -+#endif -+ -+/* The largest possible message to be queued with vchi_msg_queue. */ -+#ifndef VCHI_MAX_MSG_SIZE -+# if defined VCHI_LOCAL_HOST_PORT -+# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk? -+# else -+# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!! -+# endif -+#endif -+ -+/****************************************************************************************** -+ * Defines below are system configuration options, and should not be used by VCHI services. -+ *****************************************************************************************/ -+ -+/* How many connections can we support? A localhost implementation uses 2 connections, -+ * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW -+ * driver. */ -+#ifndef VCHI_MAX_NUM_CONNECTIONS -+# define VCHI_MAX_NUM_CONNECTIONS 3 -+#endif -+ -+/* How many services can we open per connection? Extending this doesn't cost processing time, just a small -+ * amount of static memory. */ -+#ifndef VCHI_MAX_SERVICES_PER_CONNECTION -+# define VCHI_MAX_SERVICES_PER_CONNECTION 36 -+#endif -+ -+/* Adjust if using a message driver that supports more logical TX channels */ -+#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION -+# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels -+#endif -+ -+/* Adjust if using a message driver that supports more logical RX channels */ -+#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION -+# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI -+#endif -+ -+/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective -+ * receive queue space, less message headers. */ -+#ifndef VCHI_NUM_READ_SLOTS -+# if defined(VCHI_LOCAL_HOST_PORT) -+# define VCHI_NUM_READ_SLOTS 4 -+# else -+# define VCHI_NUM_READ_SLOTS 48 -+# endif -+#endif -+ -+/* Do we utilise overrun facility for receive message slots? Can aid peer transmit -+ * performance. Only define on VideoCore end, talking to host. -+ */ -+//#define VCHI_MSG_RX_OVERRUN -+ -+/* How many transmit slots do we use. Generally don't need many, as the hardware driver -+ * underneath VCHI will usually have its own buffering. */ -+#ifndef VCHI_NUM_WRITE_SLOTS -+# define VCHI_NUM_WRITE_SLOTS 4 -+#endif -+ -+/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots, -+ * then it's taking up too much buffer space, and the peer service will be told to stop -+ * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS -+ * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency -+ * is too high. */ -+#ifndef VCHI_XOFF_THRESHOLD -+# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2) -+#endif -+ -+/* After we've sent an XOFF, the peer will be told to resume transmission once the local -+ * service has dequeued/released enough messages that it's now occupying -+ * VCHI_XON_THRESHOLD slots or fewer. */ -+#ifndef VCHI_XON_THRESHOLD -+# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4) -+#endif -+ -+/* A size below which a bulk transfer omits the handshake completely and always goes -+ * via the message channel, if bulk auxiliary is being sent on that service. (The user -+ * can guarantee this by enabling unaligned transmits). -+ * Not API. */ -+#ifndef VCHI_MIN_BULK_SIZE -+# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 ) -+#endif -+ -+/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between -+ * speed and latency; the smaller the chunk size the better change of messages and other -+ * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not -+ * break transmissions into chunks. -+ */ -+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI -+# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024) -+#endif -+ -+/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode -+ * with multiple-line frames. Only use if the receiver can cope. */ -+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2 -+# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0 -+#endif -+ -+/* How many TX messages can we have pending in our transmit slots. Once exhausted, -+ * vchi_msg_queue will be blocked. */ -+#ifndef VCHI_TX_MSG_QUEUE_SIZE -+# define VCHI_TX_MSG_QUEUE_SIZE 256 -+#endif -+ -+/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing -+ * will be suspended until older messages are dequeued/released. */ -+#ifndef VCHI_RX_MSG_QUEUE_SIZE -+# define VCHI_RX_MSG_QUEUE_SIZE 256 -+#endif -+ -+/* Really should be able to cope if we run out of received message descriptors, by -+ * suspending parsing as the comment above says, but we don't. This sweeps the issue -+ * under the carpet. */ -+#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS -+# undef VCHI_RX_MSG_QUEUE_SIZE -+# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS -+#endif -+ -+/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit -+ * will be blocked. */ -+#ifndef VCHI_TX_BULK_QUEUE_SIZE -+# define VCHI_TX_BULK_QUEUE_SIZE 64 -+#endif -+ -+/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive -+ * will be blocked. */ -+#ifndef VCHI_RX_BULK_QUEUE_SIZE -+# define VCHI_RX_BULK_QUEUE_SIZE 64 -+#endif -+ -+/* A limit on how many outstanding bulk requests we expect the peer to give us. If -+ * the peer asks for more than this, VCHI will fail and assert. The number is determined -+ * by the peer's hardware - it's the number of outstanding requests that can be queued -+ * on all bulk channels. VC3's MPHI peripheral allows 16. */ -+#ifndef VCHI_MAX_PEER_BULK_REQUESTS -+# define VCHI_MAX_PEER_BULK_REQUESTS 32 -+#endif -+ -+/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2 -+ * transmitter on and off. -+ */ -+/*#define VCHI_CCP2TX_MANUAL_POWER*/ -+ -+#ifndef VCHI_CCP2TX_MANUAL_POWER -+ -+/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set -+ * negative for no IDLE. -+ */ -+# ifndef VCHI_CCP2TX_IDLE_TIMEOUT -+# define VCHI_CCP2TX_IDLE_TIMEOUT 5 -+# endif -+ -+/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set -+ * negative for no OFF. -+ */ -+# ifndef VCHI_CCP2TX_OFF_TIMEOUT -+# define VCHI_CCP2TX_OFF_TIMEOUT 1000 -+# endif -+ -+#endif /* VCHI_CCP2TX_MANUAL_POWER */ -+ -+#endif /* VCHI_CFG_H_ */ -+ -+/****************************** End of file **********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h b/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h -new file mode 100644 -index 0000000000000000000000000000000000000000..35dcba4837d492307f3b273acaefa752cdbd6478 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h -@@ -0,0 +1,71 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_CFG_INTERNAL_H_ -+#define VCHI_CFG_INTERNAL_H_ -+ -+/**************************************************************************************** -+ * Control optimisation attempts. -+ ***************************************************************************************/ -+ -+// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second -+#define VCHI_COARSE_LOCKING -+ -+// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx) -+// (only relevant if VCHI_COARSE_LOCKING) -+#define VCHI_ELIDE_BLOCK_EXIT_LOCK -+ -+// Avoid lock on non-blocking peek -+// (only relevant if VCHI_COARSE_LOCKING) -+#define VCHI_AVOID_PEEK_LOCK -+ -+// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation. -+#define VCHI_MULTIPLE_HANDLER_THREADS -+ -+// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash -+// our way through the pool of descriptors. -+#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD -+ -+// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING. -+#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS -+ -+// Don't use message descriptors for TX messages that don't need them -+#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS -+ -+// Nano-locks for multiqueue -+//#define VCHI_MQUEUE_NANOLOCKS -+ -+// Lock-free(er) dequeuing -+//#define VCHI_RX_NANOLOCKS -+ -+#endif /*VCHI_CFG_INTERNAL_H_*/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_common.h b/drivers/misc/vc04_services/interface/vchi/vchi_common.h -new file mode 100644 -index 0000000000000000000000000000000000000000..d535a72970d3f1ee63d2038550db8f4e43589c72 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_common.h -@@ -0,0 +1,175 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_COMMON_H_ -+#define VCHI_COMMON_H_ -+ -+ -+//flags used when sending messages (must be bitmapped) -+typedef enum -+{ -+ VCHI_FLAGS_NONE = 0x0, -+ VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side) -+ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go -+ VCHI_FLAGS_ALLOW_PARTIAL = 0x8, -+ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10, -+ VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20, -+ -+ VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only -+ VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only -+ VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only -+ VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only -+ VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only -+ VCHI_FLAGS_INTERNAL = 0xFF0000 -+} VCHI_FLAGS_T; -+ -+// constants for vchi_crc_control() -+typedef enum { -+ VCHI_CRC_NOTHING = -1, -+ VCHI_CRC_PER_SERVICE = 0, -+ VCHI_CRC_EVERYTHING = 1, -+} VCHI_CRC_CONTROL_T; -+ -+//callback reasons when an event occurs on a service -+typedef enum -+{ -+ VCHI_CALLBACK_REASON_MIN, -+ -+ //This indicates that there is data available -+ //handle is the msg id that was transmitted with the data -+ // When a message is received and there was no FULL message available previously, send callback -+ // Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails -+ VCHI_CALLBACK_MSG_AVAILABLE, -+ VCHI_CALLBACK_MSG_SENT, -+ VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented -+ -+ // This indicates that a transfer from the other side has completed -+ VCHI_CALLBACK_BULK_RECEIVED, -+ //This indicates that data queued up to be sent has now gone -+ //handle is the msg id that was used when sending the data -+ VCHI_CALLBACK_BULK_SENT, -+ VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented -+ VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented -+ -+ VCHI_CALLBACK_SERVICE_CLOSED, -+ -+ // this side has sent XOFF to peer due to lack of data consumption by service -+ // (suggests the service may need to take some recovery action if it has -+ // been deliberately holding off consuming data) -+ VCHI_CALLBACK_SENT_XOFF, -+ VCHI_CALLBACK_SENT_XON, -+ -+ // indicates that a bulk transfer has finished reading the source buffer -+ VCHI_CALLBACK_BULK_DATA_READ, -+ -+ // power notification events (currently host side only) -+ VCHI_CALLBACK_PEER_OFF, -+ VCHI_CALLBACK_PEER_SUSPENDED, -+ VCHI_CALLBACK_PEER_ON, -+ VCHI_CALLBACK_PEER_RESUMED, -+ VCHI_CALLBACK_FORCED_POWER_OFF, -+ -+#ifdef USE_VCHIQ_ARM -+ // some extra notifications provided by vchiq_arm -+ VCHI_CALLBACK_SERVICE_OPENED, -+ VCHI_CALLBACK_BULK_RECEIVE_ABORTED, -+ VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, -+#endif -+ -+ VCHI_CALLBACK_REASON_MAX -+} VCHI_CALLBACK_REASON_T; -+ -+// service control options -+typedef enum -+{ -+ VCHI_SERVICE_OPTION_MIN, -+ -+ VCHI_SERVICE_OPTION_TRACE, -+ VCHI_SERVICE_OPTION_SYNCHRONOUS, -+ -+ VCHI_SERVICE_OPTION_MAX -+} VCHI_SERVICE_OPTION_T; -+ -+ -+//Callback used by all services / bulk transfers -+typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param -+ VCHI_CALLBACK_REASON_T reason, -+ void *handle ); //for transmitting msg's only -+ -+ -+ -+/* -+ * Define vector struct for scatter-gather (vector) operations -+ * Vectors can be nested - if a vector element has negative length, then -+ * the data pointer is treated as pointing to another vector array, with -+ * '-vec_len' elements. Thus to append a header onto an existing vector, -+ * you can do this: -+ * -+ * void foo(const VCHI_MSG_VECTOR_T *v, int n) -+ * { -+ * VCHI_MSG_VECTOR_T nv[2]; -+ * nv[0].vec_base = my_header; -+ * nv[0].vec_len = sizeof my_header; -+ * nv[1].vec_base = v; -+ * nv[1].vec_len = -n; -+ * ... -+ * -+ */ -+typedef struct vchi_msg_vector { -+ const void *vec_base; -+ int32_t vec_len; -+} VCHI_MSG_VECTOR_T; -+ -+// Opaque type for a connection API -+typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T; -+ -+// Opaque type for a message driver -+typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T; -+ -+ -+// Iterator structure for reading ahead through received message queue. Allocated by client, -+// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only. -+// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead - -+// will not proceed to messages received since. Behaviour is undefined if an iterator -+// is used again after messages for that service are removed/dequeued by any -+// means other than vchi_msg_iter_... calls on the iterator itself. -+typedef struct { -+ struct opaque_vchi_service_t *service; -+ void *last; -+ void *next; -+ void *remove; -+} VCHI_MSG_ITER_T; -+ -+ -+#endif // VCHI_COMMON_H_ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_mh.h b/drivers/misc/vc04_services/interface/vchi/vchi_mh.h -new file mode 100644 -index 0000000000000000000000000000000000000000..198bd076b6668d729e0b6619a1f38eb927a2398b ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_mh.h -@@ -0,0 +1,42 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_MH_H_ -+#define VCHI_MH_H_ -+ -+#include -+ -+typedef int32_t VCHI_MEM_HANDLE_T; -+#define VCHI_MEM_HANDLE_INVALID 0 -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h -new file mode 100644 -index 0000000000000000000000000000000000000000..ad398bae6ee4c3d64fc1a37808398397a9a0fefe ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h -@@ -0,0 +1,40 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_VCHIQ_H -+#define VCHIQ_VCHIQ_H -+ -+#include "vchiq_if.h" -+#include "vchiq_util.h" -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h -new file mode 100644 -index 0000000000000000000000000000000000000000..7ea5c64d5343d43786903161518ef1ce0287e27d ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h -@@ -0,0 +1,42 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_2835_H -+#define VCHIQ_2835_H -+ -+#include "vchiq_pagelist.h" -+ -+#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0 -+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 -+ -+#endif /* VCHIQ_2835_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -new file mode 100644 -index 0000000000000000000000000000000000000000..4cb5bff237288a4ee80d80ba53a2efe96f2749f3 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -0,0 +1,586 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define dmac_map_area __glue(_CACHE,_dma_map_area) -+#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) -+ -+extern void dmac_map_area(const void *, size_t, int); -+extern void dmac_unmap_area(const void *, size_t, int); -+ -+#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) -+ -+#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) -+ -+#include "vchiq_arm.h" -+#include "vchiq_2835.h" -+#include "vchiq_connected.h" -+#include "vchiq_killable.h" -+ -+#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) -+ -+#define BELL0 0x00 -+#define BELL2 0x08 -+ -+typedef struct vchiq_2835_state_struct { -+ int inited; -+ VCHIQ_ARM_STATE_T arm_state; -+} VCHIQ_2835_ARM_STATE_T; -+ -+static void __iomem *g_regs; -+static unsigned int g_cache_line_size = sizeof(CACHE_LINE_SIZE); -+static unsigned int g_fragments_size; -+static char *g_fragments_base; -+static char *g_free_fragments; -+static struct semaphore g_free_fragments_sema; -+static unsigned long g_virt_to_bus_offset; -+ -+extern int vchiq_arm_log_level; -+ -+static DEFINE_SEMAPHORE(g_free_fragments_mutex); -+ -+static irqreturn_t -+vchiq_doorbell_irq(int irq, void *dev_id); -+ -+static int -+create_pagelist(char __user *buf, size_t count, unsigned short type, -+ struct task_struct *task, PAGELIST_T ** ppagelist); -+ -+static void -+free_pagelist(PAGELIST_T *pagelist, int actual); -+ -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) -+{ -+ struct device *dev = &pdev->dev; -+ struct rpi_firmware *fw = platform_get_drvdata(pdev); -+ VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; -+ struct resource *res; -+ void *slot_mem; -+ dma_addr_t slot_phys; -+ u32 channelbase; -+ int slot_mem_size, frag_mem_size; -+ int err, irq, i; -+ -+ g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); -+ -+ (void)of_property_read_u32(dev->of_node, "cache-line-size", -+ &g_cache_line_size); -+ g_fragments_size = 2 * g_cache_line_size; -+ -+ /* Allocate space for the channels in coherent memory */ -+ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); -+ frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS); -+ -+ slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, -+ &slot_phys, GFP_KERNEL); -+ if (!slot_mem) { -+ dev_err(dev, "could not allocate DMA memory\n"); -+ return -ENOMEM; -+ } -+ -+ WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); -+ -+ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); -+ if (!vchiq_slot_zero) -+ return -EINVAL; -+ -+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = -+ (int)slot_phys + slot_mem_size; -+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = -+ MAX_FRAGMENTS; -+ -+ g_fragments_base = (char *)slot_mem + slot_mem_size; -+ slot_mem_size += frag_mem_size; -+ -+ g_free_fragments = g_fragments_base; -+ for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { -+ *(char **)&g_fragments_base[i*g_fragments_size] = -+ &g_fragments_base[(i + 1)*g_fragments_size]; -+ } -+ *(char **)&g_fragments_base[i * g_fragments_size] = NULL; -+ sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); -+ -+ if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) -+ return -EINVAL; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ g_regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(g_regs)) -+ return PTR_ERR(g_regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "failed to get IRQ\n"); -+ return irq; -+ } -+ -+ err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, -+ "VCHIQ doorbell", state); -+ if (err) { -+ dev_err(dev, "failed to register irq=%d\n", irq); -+ return err; -+ } -+ -+ /* Send the base address of the slots to VideoCore */ -+ channelbase = slot_phys; -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT, -+ &channelbase, sizeof(channelbase)); -+ if (err || channelbase) { -+ dev_err(dev, "failed to set channelbase\n"); -+ return err ? : -ENXIO; -+ } -+ -+ vchiq_log_info(vchiq_arm_log_level, -+ "vchiq_init - done (slots %x, phys %pad)", -+ (unsigned int)vchiq_slot_zero, &slot_phys); -+ -+ vchiq_call_connected_callbacks(); -+ -+ return 0; -+} -+ -+VCHIQ_STATUS_T -+vchiq_platform_init_state(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ state->platform_state = kzalloc(sizeof(VCHIQ_2835_ARM_STATE_T), GFP_KERNEL); -+ ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 1; -+ status = vchiq_arm_init_state(state, &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state); -+ if(status != VCHIQ_SUCCESS) -+ { -+ ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 0; -+ } -+ return status; -+} -+ -+VCHIQ_ARM_STATE_T* -+vchiq_platform_get_arm_state(VCHIQ_STATE_T *state) -+{ -+ if(!((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited) -+ { -+ BUG(); -+ } -+ return &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state; -+} -+ -+void -+remote_event_signal(REMOTE_EVENT_T *event) -+{ -+ wmb(); -+ -+ event->fired = 1; -+ -+ dsb(); /* data barrier operation */ -+ -+ if (event->armed) -+ writel(0, g_regs + BELL2); /* trigger vc interrupt */ -+} -+ -+int -+vchiq_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ((uint32_t)src < TASK_SIZE) { -+ return copy_from_user(dst, src, size); -+ } else { -+ memcpy(dst, src, size); -+ return 0; -+ } -+} -+ -+VCHIQ_STATUS_T -+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, -+ void *offset, int size, int dir) -+{ -+ PAGELIST_T *pagelist; -+ int ret; -+ -+ WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID); -+ -+ ret = create_pagelist((char __user *)offset, size, -+ (dir == VCHIQ_BULK_RECEIVE) -+ ? PAGELIST_READ -+ : PAGELIST_WRITE, -+ current, -+ &pagelist); -+ if (ret != 0) -+ return VCHIQ_ERROR; -+ -+ bulk->handle = memhandle; -+ bulk->data = VCHIQ_ARM_ADDRESS(pagelist); -+ -+ /* Store the pagelist address in remote_data, which isn't used by the -+ slave. */ -+ bulk->remote_data = pagelist; -+ -+ return VCHIQ_SUCCESS; -+} -+ -+void -+vchiq_complete_bulk(VCHIQ_BULK_T *bulk) -+{ -+ if (bulk && bulk->remote_data && bulk->actual) -+ free_pagelist((PAGELIST_T *)bulk->remote_data, bulk->actual); -+} -+ -+void -+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk) -+{ -+ /* -+ * This should only be called on the master (VideoCore) side, but -+ * provide an implementation to avoid the need for ifdefery. -+ */ -+ BUG(); -+} -+ -+void -+vchiq_dump_platform_state(void *dump_context) -+{ -+ char buf[80]; -+ int len; -+ len = snprintf(buf, sizeof(buf), -+ " Platform: 2835 (VC master)"); -+ vchiq_dump(dump_context, buf, len + 1); -+} -+ -+VCHIQ_STATUS_T -+vchiq_platform_suspend(VCHIQ_STATE_T *state) -+{ -+ return VCHIQ_ERROR; -+} -+ -+VCHIQ_STATUS_T -+vchiq_platform_resume(VCHIQ_STATE_T *state) -+{ -+ return VCHIQ_SUCCESS; -+} -+ -+void -+vchiq_platform_paused(VCHIQ_STATE_T *state) -+{ -+} -+ -+void -+vchiq_platform_resumed(VCHIQ_STATE_T *state) -+{ -+} -+ -+int -+vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state) -+{ -+ return 1; // autosuspend not supported - videocore always wanted -+} -+ -+int -+vchiq_platform_use_suspend_timer(void) -+{ -+ return 0; -+} -+void -+vchiq_dump_platform_use_state(VCHIQ_STATE_T *state) -+{ -+ vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use"); -+} -+void -+vchiq_platform_handle_timeout(VCHIQ_STATE_T *state) -+{ -+ (void)state; -+} -+/* -+ * Local functions -+ */ -+ -+static irqreturn_t -+vchiq_doorbell_irq(int irq, void *dev_id) -+{ -+ VCHIQ_STATE_T *state = dev_id; -+ irqreturn_t ret = IRQ_NONE; -+ unsigned int status; -+ -+ /* Read (and clear) the doorbell */ -+ status = readl(g_regs + BELL0); -+ -+ if (status & 0x4) { /* Was the doorbell rung? */ -+ remote_event_pollall(state); -+ ret = IRQ_HANDLED; -+ } -+ -+ return ret; -+} -+ -+/* There is a potential problem with partial cache lines (pages?) -+** at the ends of the block when reading. If the CPU accessed anything in -+** the same line (page?) then it may have pulled old data into the cache, -+** obscuring the new data underneath. We can solve this by transferring the -+** partial cache lines separately, and allowing the ARM to copy into the -+** cached area. -+ -+** N.B. This implementation plays slightly fast and loose with the Linux -+** driver programming rules, e.g. its use of dmac_map_area instead of -+** dma_map_single, but it isn't a multi-platform driver and it benefits -+** from increased speed as a result. -+*/ -+ -+static int -+create_pagelist(char __user *buf, size_t count, unsigned short type, -+ struct task_struct *task, PAGELIST_T ** ppagelist) -+{ -+ PAGELIST_T *pagelist; -+ struct page **pages; -+ unsigned long *addrs; -+ unsigned int num_pages, offset, i; -+ char *addr, *base_addr, *next_addr; -+ int run, addridx, actual_pages; -+ unsigned long *need_release; -+ -+ offset = (unsigned int)buf & (PAGE_SIZE - 1); -+ num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; -+ -+ *ppagelist = NULL; -+ -+ /* Allocate enough storage to hold the page pointers and the page -+ ** list -+ */ -+ pagelist = kmalloc(sizeof(PAGELIST_T) + -+ (num_pages * sizeof(unsigned long)) + -+ sizeof(unsigned long) + -+ (num_pages * sizeof(pages[0])), -+ GFP_KERNEL); -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "create_pagelist - %x", (unsigned int)pagelist); -+ if (!pagelist) -+ return -ENOMEM; -+ -+ addrs = pagelist->addrs; -+ need_release = (unsigned long *)(addrs + num_pages); -+ pages = (struct page **)(addrs + num_pages + 1); -+ -+ if (is_vmalloc_addr(buf)) { -+ int dir = (type == PAGELIST_WRITE) ? -+ DMA_TO_DEVICE : DMA_FROM_DEVICE; -+ unsigned long length = count; -+ unsigned int off = offset; -+ -+ for (actual_pages = 0; actual_pages < num_pages; -+ actual_pages++) { -+ struct page *pg = vmalloc_to_page(buf + (actual_pages * -+ PAGE_SIZE)); -+ size_t bytes = PAGE_SIZE - off; -+ -+ if (bytes > length) -+ bytes = length; -+ pages[actual_pages] = pg; -+ dmac_map_area(page_address(pg) + off, bytes, dir); -+ length -= bytes; -+ off = 0; -+ } -+ *need_release = 0; /* do not try and release vmalloc pages */ -+ } else { -+ down_read(&task->mm->mmap_sem); -+ actual_pages = get_user_pages( -+ (unsigned long)buf & ~(PAGE_SIZE - 1), -+ num_pages, -+ (type == PAGELIST_READ) /*Write */ , -+ 0 /*Force */ , -+ pages, -+ NULL /*vmas */); -+ up_read(&task->mm->mmap_sem); -+ -+ if (actual_pages != num_pages) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "create_pagelist - only %d/%d pages locked", -+ actual_pages, -+ num_pages); -+ -+ /* This is probably due to the process being killed */ -+ while (actual_pages > 0) -+ { -+ actual_pages--; -+ put_page(pages[actual_pages]); -+ } -+ kfree(pagelist); -+ if (actual_pages == 0) -+ actual_pages = -ENOMEM; -+ return actual_pages; -+ } -+ *need_release = 1; /* release user pages */ -+ } -+ -+ pagelist->length = count; -+ pagelist->type = type; -+ pagelist->offset = offset; -+ -+ /* Group the pages into runs of contiguous pages */ -+ -+ base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0])); -+ next_addr = base_addr + PAGE_SIZE; -+ addridx = 0; -+ run = 0; -+ -+ for (i = 1; i < num_pages; i++) { -+ addr = VCHIQ_ARM_ADDRESS(page_address(pages[i])); -+ if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) { -+ next_addr += PAGE_SIZE; -+ run++; -+ } else { -+ addrs[addridx] = (unsigned long)base_addr + run; -+ addridx++; -+ base_addr = addr; -+ next_addr = addr + PAGE_SIZE; -+ run = 0; -+ } -+ } -+ -+ addrs[addridx] = (unsigned long)base_addr + run; -+ addridx++; -+ -+ /* Partial cache lines (fragments) require special measures */ -+ if ((type == PAGELIST_READ) && -+ ((pagelist->offset & (g_cache_line_size - 1)) || -+ ((pagelist->offset + pagelist->length) & -+ (g_cache_line_size - 1)))) { -+ char *fragments; -+ -+ if (down_interruptible(&g_free_fragments_sema) != 0) { -+ kfree(pagelist); -+ return -EINTR; -+ } -+ -+ WARN_ON(g_free_fragments == NULL); -+ -+ down(&g_free_fragments_mutex); -+ fragments = g_free_fragments; -+ WARN_ON(fragments == NULL); -+ g_free_fragments = *(char **) g_free_fragments; -+ up(&g_free_fragments_mutex); -+ pagelist->type = PAGELIST_READ_WITH_FRAGMENTS + -+ (fragments - g_fragments_base) / g_fragments_size; -+ } -+ -+ dmac_flush_range(pagelist, addrs + num_pages); -+ -+ *ppagelist = pagelist; -+ -+ return 0; -+} -+ -+static void -+free_pagelist(PAGELIST_T *pagelist, int actual) -+{ -+ unsigned long *need_release; -+ struct page **pages; -+ unsigned int num_pages, i; -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "free_pagelist - %x, %d", (unsigned int)pagelist, actual); -+ -+ num_pages = -+ (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / -+ PAGE_SIZE; -+ -+ need_release = (unsigned long *)(pagelist->addrs + num_pages); -+ pages = (struct page **)(pagelist->addrs + num_pages + 1); -+ -+ /* Deal with any partial cache lines (fragments) */ -+ if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) { -+ char *fragments = g_fragments_base + -+ (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * -+ g_fragments_size; -+ int head_bytes, tail_bytes; -+ head_bytes = (g_cache_line_size - pagelist->offset) & -+ (g_cache_line_size - 1); -+ tail_bytes = (pagelist->offset + actual) & -+ (g_cache_line_size - 1); -+ -+ if ((actual >= 0) && (head_bytes != 0)) { -+ if (head_bytes > actual) -+ head_bytes = actual; -+ -+ memcpy((char *)page_address(pages[0]) + -+ pagelist->offset, -+ fragments, -+ head_bytes); -+ } -+ if ((actual >= 0) && (head_bytes < actual) && -+ (tail_bytes != 0)) { -+ memcpy((char *)page_address(pages[num_pages - 1]) + -+ ((pagelist->offset + actual) & -+ (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)), -+ fragments + g_cache_line_size, -+ tail_bytes); -+ } -+ -+ down(&g_free_fragments_mutex); -+ *(char **)fragments = g_free_fragments; -+ g_free_fragments = fragments; -+ up(&g_free_fragments_mutex); -+ up(&g_free_fragments_sema); -+ } -+ -+ if (*need_release) { -+ unsigned int length = pagelist->length; -+ unsigned int offset = pagelist->offset; -+ -+ for (i = 0; i < num_pages; i++) { -+ struct page *pg = pages[i]; -+ -+ if (pagelist->type != PAGELIST_WRITE) { -+ unsigned int bytes = PAGE_SIZE - offset; -+ -+ if (bytes > length) -+ bytes = length; -+ dmac_unmap_area(page_address(pg) + offset, -+ bytes, DMA_FROM_DEVICE); -+ length -= bytes; -+ offset = 0; -+ set_page_dirty(pg); -+ } -+ put_page(pg); -+ } -+ } -+ -+ kfree(pagelist); -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -new file mode 100644 -index 0000000000000000000000000000000000000000..2dfccafc765b2211bd7b8ead5e9e52bd8fe13913 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -0,0 +1,2921 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "vchiq_core.h" -+#include "vchiq_ioctl.h" -+#include "vchiq_arm.h" -+#include "vchiq_debugfs.h" -+#include "vchiq_killable.h" -+ -+#define DEVICE_NAME "vchiq" -+ -+/* Override the default prefix, which would be vchiq_arm (from the filename) */ -+#undef MODULE_PARAM_PREFIX -+#define MODULE_PARAM_PREFIX DEVICE_NAME "." -+ -+#define VCHIQ_MINOR 0 -+ -+/* Some per-instance constants */ -+#define MAX_COMPLETIONS 128 -+#define MAX_SERVICES 64 -+#define MAX_ELEMENTS 8 -+#define MSG_QUEUE_SIZE 128 -+ -+#define KEEPALIVE_VER 1 -+#define KEEPALIVE_VER_MIN KEEPALIVE_VER -+ -+/* Run time control of log level, based on KERN_XXX level. */ -+int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT; -+int vchiq_susp_log_level = VCHIQ_LOG_ERROR; -+ -+#define SUSPEND_TIMER_TIMEOUT_MS 100 -+#define SUSPEND_RETRY_TIMER_TIMEOUT_MS 1000 -+ -+#define VC_SUSPEND_NUM_OFFSET 3 /* number of values before idle which are -ve */ -+static const char *const suspend_state_names[] = { -+ "VC_SUSPEND_FORCE_CANCELED", -+ "VC_SUSPEND_REJECTED", -+ "VC_SUSPEND_FAILED", -+ "VC_SUSPEND_IDLE", -+ "VC_SUSPEND_REQUESTED", -+ "VC_SUSPEND_IN_PROGRESS", -+ "VC_SUSPEND_SUSPENDED" -+}; -+#define VC_RESUME_NUM_OFFSET 1 /* number of values before idle which are -ve */ -+static const char *const resume_state_names[] = { -+ "VC_RESUME_FAILED", -+ "VC_RESUME_IDLE", -+ "VC_RESUME_REQUESTED", -+ "VC_RESUME_IN_PROGRESS", -+ "VC_RESUME_RESUMED" -+}; -+/* The number of times we allow force suspend to timeout before actually -+** _forcing_ suspend. This is to cater for SW which fails to release vchiq -+** correctly - we don't want to prevent ARM suspend indefinitely in this case. -+*/ -+#define FORCE_SUSPEND_FAIL_MAX 8 -+ -+/* The time in ms allowed for videocore to go idle when force suspend has been -+ * requested */ -+#define FORCE_SUSPEND_TIMEOUT_MS 200 -+ -+ -+static void suspend_timer_callback(unsigned long context); -+ -+ -+typedef struct user_service_struct { -+ VCHIQ_SERVICE_T *service; -+ void *userdata; -+ VCHIQ_INSTANCE_T instance; -+ char is_vchi; -+ char dequeue_pending; -+ char close_pending; -+ int message_available_pos; -+ int msg_insert; -+ int msg_remove; -+ struct semaphore insert_event; -+ struct semaphore remove_event; -+ struct semaphore close_event; -+ VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE]; -+} USER_SERVICE_T; -+ -+struct bulk_waiter_node { -+ struct bulk_waiter bulk_waiter; -+ int pid; -+ struct list_head list; -+}; -+ -+struct vchiq_instance_struct { -+ VCHIQ_STATE_T *state; -+ VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS]; -+ int completion_insert; -+ int completion_remove; -+ struct semaphore insert_event; -+ struct semaphore remove_event; -+ struct mutex completion_mutex; -+ -+ int connected; -+ int closing; -+ int pid; -+ int mark; -+ int use_close_delivered; -+ int trace; -+ -+ struct list_head bulk_waiter_list; -+ struct mutex bulk_waiter_list_mutex; -+ -+ VCHIQ_DEBUGFS_NODE_T debugfs_node; -+}; -+ -+typedef struct dump_context_struct { -+ char __user *buf; -+ size_t actual; -+ size_t space; -+ loff_t offset; -+} DUMP_CONTEXT_T; -+ -+static struct cdev vchiq_cdev; -+static dev_t vchiq_devid; -+static VCHIQ_STATE_T g_state; -+static struct class *vchiq_class; -+static struct device *vchiq_dev; -+static DEFINE_SPINLOCK(msg_queue_spinlock); -+ -+static const char *const ioctl_names[] = { -+ "CONNECT", -+ "SHUTDOWN", -+ "CREATE_SERVICE", -+ "REMOVE_SERVICE", -+ "QUEUE_MESSAGE", -+ "QUEUE_BULK_TRANSMIT", -+ "QUEUE_BULK_RECEIVE", -+ "AWAIT_COMPLETION", -+ "DEQUEUE_MESSAGE", -+ "GET_CLIENT_ID", -+ "GET_CONFIG", -+ "CLOSE_SERVICE", -+ "USE_SERVICE", -+ "RELEASE_SERVICE", -+ "SET_SERVICE_OPTION", -+ "DUMP_PHYS_MEM", -+ "LIB_VERSION", -+ "CLOSE_DELIVERED" -+}; -+ -+vchiq_static_assert((sizeof(ioctl_names)/sizeof(ioctl_names[0])) == -+ (VCHIQ_IOC_MAX + 1)); -+ -+static void -+dump_phys_mem(void *virt_addr, uint32_t num_bytes); -+ -+/**************************************************************************** -+* -+* add_completion -+* -+***************************************************************************/ -+ -+static VCHIQ_STATUS_T -+add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service, -+ void *bulk_userdata) -+{ -+ VCHIQ_COMPLETION_DATA_T *completion; -+ int insert; -+ DEBUG_INITIALISE(g_state.local) -+ -+ insert = instance->completion_insert; -+ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { -+ /* Out of space - wait for the client */ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ vchiq_log_trace(vchiq_arm_log_level, -+ "add_completion - completion queue full"); -+ DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); -+ -+ if (down_interruptible(&instance->remove_event) != 0) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback interrupted"); -+ return VCHIQ_RETRY; -+ } -+ -+ if (instance->closing) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback closing"); -+ return VCHIQ_SUCCESS; -+ } -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ } -+ -+ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; -+ -+ completion->header = header; -+ completion->reason = reason; -+ /* N.B. service_userdata is updated while processing AWAIT_COMPLETION */ -+ completion->service_userdata = user_service->service; -+ completion->bulk_userdata = bulk_userdata; -+ -+ if (reason == VCHIQ_SERVICE_CLOSED) { -+ /* Take an extra reference, to be held until -+ this CLOSED notification is delivered. */ -+ lock_service(user_service->service); -+ if (instance->use_close_delivered) -+ user_service->close_pending = 1; -+ } -+ -+ /* A write barrier is needed here to ensure that the entire completion -+ record is written out before the insert point. */ -+ wmb(); -+ -+ if (reason == VCHIQ_MESSAGE_AVAILABLE) -+ user_service->message_available_pos = insert; -+ -+ instance->completion_insert = ++insert; -+ -+ up(&instance->insert_event); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+/**************************************************************************** -+* -+* service_callback -+* -+***************************************************************************/ -+ -+static VCHIQ_STATUS_T -+service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, -+ VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) -+{ -+ /* How do we ensure the callback goes to the right client? -+ ** The service_user data points to a USER_SERVICE_T record containing -+ ** the original callback and the user state structure, which contains a -+ ** circular buffer for completion records. -+ */ -+ USER_SERVICE_T *user_service; -+ VCHIQ_SERVICE_T *service; -+ VCHIQ_INSTANCE_T instance; -+ int skip_completion = 0; -+ DEBUG_INITIALISE(g_state.local) -+ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ -+ service = handle_to_service(handle); -+ BUG_ON(!service); -+ user_service = (USER_SERVICE_T *)service->base.userdata; -+ instance = user_service->instance; -+ -+ if (!instance || instance->closing) -+ return VCHIQ_SUCCESS; -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "service_callback - service %lx(%d,%p), reason %d, header %lx, " -+ "instance %lx, bulk_userdata %lx", -+ (unsigned long)user_service, -+ service->localport, user_service->userdata, -+ reason, (unsigned long)header, -+ (unsigned long)instance, (unsigned long)bulk_userdata); -+ -+ if (header && user_service->is_vchi) { -+ spin_lock(&msg_queue_spinlock); -+ while (user_service->msg_insert == -+ (user_service->msg_remove + MSG_QUEUE_SIZE)) { -+ spin_unlock(&msg_queue_spinlock); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ DEBUG_COUNT(MSG_QUEUE_FULL_COUNT); -+ vchiq_log_trace(vchiq_arm_log_level, -+ "service_callback - msg queue full"); -+ /* If there is no MESSAGE_AVAILABLE in the completion -+ ** queue, add one -+ */ -+ if ((user_service->message_available_pos - -+ instance->completion_remove) < 0) { -+ VCHIQ_STATUS_T status; -+ vchiq_log_info(vchiq_arm_log_level, -+ "Inserting extra MESSAGE_AVAILABLE"); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ status = add_completion(instance, reason, -+ NULL, user_service, bulk_userdata); -+ if (status != VCHIQ_SUCCESS) { -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return status; -+ } -+ } -+ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ if (down_interruptible(&user_service->remove_event) -+ != 0) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback interrupted"); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_RETRY; -+ } else if (instance->closing) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback closing"); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_ERROR; -+ } -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ spin_lock(&msg_queue_spinlock); -+ } -+ -+ user_service->msg_queue[user_service->msg_insert & -+ (MSG_QUEUE_SIZE - 1)] = header; -+ user_service->msg_insert++; -+ -+ /* If there is a thread waiting in DEQUEUE_MESSAGE, or if -+ ** there is a MESSAGE_AVAILABLE in the completion queue then -+ ** bypass the completion queue. -+ */ -+ if (((user_service->message_available_pos - -+ instance->completion_remove) >= 0) || -+ user_service->dequeue_pending) { -+ user_service->dequeue_pending = 0; -+ skip_completion = 1; -+ } -+ -+ spin_unlock(&msg_queue_spinlock); -+ -+ up(&user_service->insert_event); -+ -+ header = NULL; -+ } -+ -+ if (skip_completion) { -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_SUCCESS; -+ } -+ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ -+ return add_completion(instance, reason, header, user_service, -+ bulk_userdata); -+} -+ -+/**************************************************************************** -+* -+* user_service_free -+* -+***************************************************************************/ -+static void -+user_service_free(void *userdata) -+{ -+ kfree(userdata); -+} -+ -+/**************************************************************************** -+* -+* close_delivered -+* -+***************************************************************************/ -+static void close_delivered(USER_SERVICE_T *user_service) -+{ -+ vchiq_log_info(vchiq_arm_log_level, -+ "close_delivered(handle=%x)", -+ user_service->service->handle); -+ -+ if (user_service->close_pending) { -+ /* Allow the underlying service to be culled */ -+ unlock_service(user_service->service); -+ -+ /* Wake the user-thread blocked in close_ or remove_service */ -+ up(&user_service->close_event); -+ -+ user_service->close_pending = 0; -+ } -+} -+ -+/**************************************************************************** -+* -+* vchiq_ioctl -+* -+***************************************************************************/ -+static long -+vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ VCHIQ_INSTANCE_T instance = file->private_data; -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ VCHIQ_SERVICE_T *service = NULL; -+ long ret = 0; -+ int i, rc; -+ DEBUG_INITIALISE(g_state.local) -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "vchiq_ioctl - instance %x, cmd %s, arg %lx", -+ (unsigned int)instance, -+ ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && -+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ? -+ ioctl_names[_IOC_NR(cmd)] : "", arg); -+ -+ switch (cmd) { -+ case VCHIQ_IOC_SHUTDOWN: -+ if (!instance->connected) -+ break; -+ -+ /* Remove all services */ -+ i = 0; -+ while ((service = next_service_by_instance(instance->state, -+ instance, &i)) != NULL) { -+ status = vchiq_remove_service(service->handle); -+ unlock_service(service); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ service = NULL; -+ -+ if (status == VCHIQ_SUCCESS) { -+ /* Wake the completion thread and ask it to exit */ -+ instance->closing = 1; -+ up(&instance->insert_event); -+ } -+ -+ break; -+ -+ case VCHIQ_IOC_CONNECT: -+ if (instance->connected) { -+ ret = -EINVAL; -+ break; -+ } -+ rc = mutex_lock_interruptible(&instance->state->mutex); -+ if (rc != 0) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "vchiq: connect: could not lock mutex for " -+ "state %d: %d", -+ instance->state->id, rc); -+ ret = -EINTR; -+ break; -+ } -+ status = vchiq_connect_internal(instance->state, instance); -+ mutex_unlock(&instance->state->mutex); -+ -+ if (status == VCHIQ_SUCCESS) -+ instance->connected = 1; -+ else -+ vchiq_log_error(vchiq_arm_log_level, -+ "vchiq: could not connect: %d", status); -+ break; -+ -+ case VCHIQ_IOC_CREATE_SERVICE: { -+ VCHIQ_CREATE_SERVICE_T args; -+ USER_SERVICE_T *user_service = NULL; -+ void *userdata; -+ int srvstate; -+ -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL); -+ if (!user_service) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ if (args.is_open) { -+ if (!instance->connected) { -+ ret = -ENOTCONN; -+ kfree(user_service); -+ break; -+ } -+ srvstate = VCHIQ_SRVSTATE_OPENING; -+ } else { -+ srvstate = -+ instance->connected ? -+ VCHIQ_SRVSTATE_LISTENING : -+ VCHIQ_SRVSTATE_HIDDEN; -+ } -+ -+ userdata = args.params.userdata; -+ args.params.callback = service_callback; -+ args.params.userdata = user_service; -+ service = vchiq_add_service_internal( -+ instance->state, -+ &args.params, srvstate, -+ instance, user_service_free); -+ -+ if (service != NULL) { -+ user_service->service = service; -+ user_service->userdata = userdata; -+ user_service->instance = instance; -+ user_service->is_vchi = (args.is_vchi != 0); -+ user_service->dequeue_pending = 0; -+ user_service->close_pending = 0; -+ user_service->message_available_pos = -+ instance->completion_remove - 1; -+ user_service->msg_insert = 0; -+ user_service->msg_remove = 0; -+ sema_init(&user_service->insert_event, 0); -+ sema_init(&user_service->remove_event, 0); -+ sema_init(&user_service->close_event, 0); -+ -+ if (args.is_open) { -+ status = vchiq_open_service_internal -+ (service, instance->pid); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_remove_service(service->handle); -+ service = NULL; -+ ret = (status == VCHIQ_RETRY) ? -+ -EINTR : -EIO; -+ break; -+ } -+ } -+ -+ if (copy_to_user((void __user *) -+ &(((VCHIQ_CREATE_SERVICE_T __user *) -+ arg)->handle), -+ (const void *)&service->handle, -+ sizeof(service->handle)) != 0) { -+ ret = -EFAULT; -+ vchiq_remove_service(service->handle); -+ } -+ -+ service = NULL; -+ } else { -+ ret = -EEXIST; -+ kfree(user_service); -+ } -+ } break; -+ -+ case VCHIQ_IOC_CLOSE_SERVICE: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_service_for_instance(instance, handle); -+ if (service != NULL) { -+ USER_SERVICE_T *user_service = -+ (USER_SERVICE_T *)service->base.userdata; -+ /* close_pending is false on first entry, and when the -+ wait in vchiq_close_service has been interrupted. */ -+ if (!user_service->close_pending) { -+ status = vchiq_close_service(service->handle); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ -+ /* close_pending is true once the underlying service -+ has been closed until the client library calls the -+ CLOSE_DELIVERED ioctl, signalling close_event. */ -+ if (user_service->close_pending && -+ down_interruptible(&user_service->close_event)) -+ status = VCHIQ_RETRY; -+ } -+ else -+ ret = -EINVAL; -+ } break; -+ -+ case VCHIQ_IOC_REMOVE_SERVICE: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_service_for_instance(instance, handle); -+ if (service != NULL) { -+ USER_SERVICE_T *user_service = -+ (USER_SERVICE_T *)service->base.userdata; -+ /* close_pending is false on first entry, and when the -+ wait in vchiq_close_service has been interrupted. */ -+ if (!user_service->close_pending) { -+ status = vchiq_remove_service(service->handle); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ -+ /* close_pending is true once the underlying service -+ has been closed until the client library calls the -+ CLOSE_DELIVERED ioctl, signalling close_event. */ -+ if (user_service->close_pending && -+ down_interruptible(&user_service->close_event)) -+ status = VCHIQ_RETRY; -+ } -+ else -+ ret = -EINVAL; -+ } break; -+ -+ case VCHIQ_IOC_USE_SERVICE: -+ case VCHIQ_IOC_RELEASE_SERVICE: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_service_for_instance(instance, handle); -+ if (service != NULL) { -+ status = (cmd == VCHIQ_IOC_USE_SERVICE) ? -+ vchiq_use_service_internal(service) : -+ vchiq_release_service_internal(service); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s: cmd %s returned error %d for " -+ "service %c%c%c%c:%03d", -+ __func__, -+ (cmd == VCHIQ_IOC_USE_SERVICE) ? -+ "VCHIQ_IOC_USE_SERVICE" : -+ "VCHIQ_IOC_RELEASE_SERVICE", -+ status, -+ VCHIQ_FOURCC_AS_4CHARS( -+ service->base.fourcc), -+ service->client_id); -+ ret = -EINVAL; -+ } -+ } else -+ ret = -EINVAL; -+ } break; -+ -+ case VCHIQ_IOC_QUEUE_MESSAGE: { -+ VCHIQ_QUEUE_MESSAGE_T args; -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ service = find_service_for_instance(instance, args.handle); -+ -+ if ((service != NULL) && (args.count <= MAX_ELEMENTS)) { -+ /* Copy elements into kernel space */ -+ VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; -+ if (copy_from_user(elements, args.elements, -+ args.count * sizeof(VCHIQ_ELEMENT_T)) == 0) -+ status = vchiq_queue_message -+ (args.handle, -+ elements, args.count); -+ else -+ ret = -EFAULT; -+ } else { -+ ret = -EINVAL; -+ } -+ } break; -+ -+ case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: -+ case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { -+ VCHIQ_QUEUE_BULK_TRANSFER_T args; -+ struct bulk_waiter_node *waiter = NULL; -+ VCHIQ_BULK_DIR_T dir = -+ (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ? -+ VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE; -+ -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ service = find_service_for_instance(instance, args.handle); -+ if (!service) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (args.mode == VCHIQ_BULK_MODE_BLOCKING) { -+ waiter = kzalloc(sizeof(struct bulk_waiter_node), -+ GFP_KERNEL); -+ if (!waiter) { -+ ret = -ENOMEM; -+ break; -+ } -+ args.userdata = &waiter->bulk_waiter; -+ } else if (args.mode == VCHIQ_BULK_MODE_WAITING) { -+ struct list_head *pos; -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_for_each(pos, &instance->bulk_waiter_list) { -+ if (list_entry(pos, struct bulk_waiter_node, -+ list)->pid == current->pid) { -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ break; -+ } -+ -+ } -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ if (!waiter) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "no bulk_waiter found for pid %d", -+ current->pid); -+ ret = -ESRCH; -+ break; -+ } -+ vchiq_log_info(vchiq_arm_log_level, -+ "found bulk_waiter %x for pid %d", -+ (unsigned int)waiter, current->pid); -+ args.userdata = &waiter->bulk_waiter; -+ } -+ status = vchiq_bulk_transfer -+ (args.handle, -+ VCHI_MEM_HANDLE_INVALID, -+ args.data, args.size, -+ args.userdata, args.mode, -+ dir); -+ if (!waiter) -+ break; -+ if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || -+ !waiter->bulk_waiter.bulk) { -+ if (waiter->bulk_waiter.bulk) { -+ /* Cancel the signal when the transfer -+ ** completes. */ -+ spin_lock(&bulk_waiter_spinlock); -+ waiter->bulk_waiter.bulk->userdata = NULL; -+ spin_unlock(&bulk_waiter_spinlock); -+ } -+ kfree(waiter); -+ } else { -+ const VCHIQ_BULK_MODE_T mode_waiting = -+ VCHIQ_BULK_MODE_WAITING; -+ waiter->pid = current->pid; -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_add(&waiter->list, &instance->bulk_waiter_list); -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ vchiq_log_info(vchiq_arm_log_level, -+ "saved bulk_waiter %x for pid %d", -+ (unsigned int)waiter, current->pid); -+ -+ if (copy_to_user((void __user *) -+ &(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *) -+ arg)->mode), -+ (const void *)&mode_waiting, -+ sizeof(mode_waiting)) != 0) -+ ret = -EFAULT; -+ } -+ } break; -+ -+ case VCHIQ_IOC_AWAIT_COMPLETION: { -+ VCHIQ_AWAIT_COMPLETION_T args; -+ -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ if (!instance->connected) { -+ ret = -ENOTCONN; -+ break; -+ } -+ -+ if (copy_from_user(&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ mutex_lock(&instance->completion_mutex); -+ -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ while ((instance->completion_remove == -+ instance->completion_insert) -+ && !instance->closing) { -+ int rc; -+ -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ mutex_unlock(&instance->completion_mutex); -+ rc = down_interruptible(&instance->insert_event); -+ mutex_lock(&instance->completion_mutex); -+ if (rc != 0) { -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ vchiq_log_info(vchiq_arm_log_level, -+ "AWAIT_COMPLETION interrupted"); -+ ret = -EINTR; -+ break; -+ } -+ } -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ -+ if (ret == 0) { -+ int msgbufcount = args.msgbufcount; -+ int remove; -+ -+ remove = instance->completion_remove; -+ -+ for (ret = 0; ret < args.count; ret++) { -+ VCHIQ_COMPLETION_DATA_T *completion; -+ VCHIQ_SERVICE_T *service; -+ USER_SERVICE_T *user_service; -+ VCHIQ_HEADER_T *header; -+ -+ if (remove == instance->completion_insert) -+ break; -+ -+ completion = &instance->completions[ -+ remove & (MAX_COMPLETIONS - 1)]; -+ -+ -+ /* A read memory barrier is needed to prevent -+ ** the prefetch of a stale completion record -+ */ -+ rmb(); -+ -+ service = completion->service_userdata; -+ user_service = service->base.userdata; -+ completion->service_userdata = -+ user_service->userdata; -+ -+ header = completion->header; -+ if (header) { -+ void __user *msgbuf; -+ int msglen; -+ -+ msglen = header->size + -+ sizeof(VCHIQ_HEADER_T); -+ /* This must be a VCHIQ-style service */ -+ if (args.msgbufsize < msglen) { -+ vchiq_log_error( -+ vchiq_arm_log_level, -+ "header %x: msgbufsize" -+ " %x < msglen %x", -+ (unsigned int)header, -+ args.msgbufsize, -+ msglen); -+ WARN(1, "invalid message " -+ "size\n"); -+ if (ret == 0) -+ ret = -EMSGSIZE; -+ break; -+ } -+ if (msgbufcount <= 0) -+ /* Stall here for lack of a -+ ** buffer for the message. */ -+ break; -+ /* Get the pointer from user space */ -+ msgbufcount--; -+ if (copy_from_user(&msgbuf, -+ (const void __user *) -+ &args.msgbufs[msgbufcount], -+ sizeof(msgbuf)) != 0) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ -+ /* Copy the message to user space */ -+ if (copy_to_user(msgbuf, header, -+ msglen) != 0) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ -+ /* Now it has been copied, the message -+ ** can be released. */ -+ vchiq_release_message(service->handle, -+ header); -+ -+ /* The completion must point to the -+ ** msgbuf. */ -+ completion->header = msgbuf; -+ } -+ -+ if ((completion->reason == -+ VCHIQ_SERVICE_CLOSED) && -+ !instance->use_close_delivered) -+ unlock_service(service); -+ -+ if (copy_to_user((void __user *)( -+ (size_t)args.buf + -+ ret * sizeof(VCHIQ_COMPLETION_DATA_T)), -+ completion, -+ sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ -+ /* Ensure that the above copy has completed -+ ** before advancing the remove pointer. */ -+ mb(); -+ -+ instance->completion_remove = ++remove; -+ } -+ -+ if (msgbufcount != args.msgbufcount) { -+ if (copy_to_user((void __user *) -+ &((VCHIQ_AWAIT_COMPLETION_T *)arg)-> -+ msgbufcount, -+ &msgbufcount, -+ sizeof(msgbufcount)) != 0) { -+ ret = -EFAULT; -+ } -+ } -+ } -+ -+ if (ret != 0) -+ up(&instance->remove_event); -+ mutex_unlock(&instance->completion_mutex); -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ } break; -+ -+ case VCHIQ_IOC_DEQUEUE_MESSAGE: { -+ VCHIQ_DEQUEUE_MESSAGE_T args; -+ USER_SERVICE_T *user_service; -+ VCHIQ_HEADER_T *header; -+ -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ service = find_service_for_instance(instance, args.handle); -+ if (!service) { -+ ret = -EINVAL; -+ break; -+ } -+ user_service = (USER_SERVICE_T *)service->base.userdata; -+ if (user_service->is_vchi == 0) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ spin_lock(&msg_queue_spinlock); -+ if (user_service->msg_remove == user_service->msg_insert) { -+ if (!args.blocking) { -+ spin_unlock(&msg_queue_spinlock); -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ ret = -EWOULDBLOCK; -+ break; -+ } -+ user_service->dequeue_pending = 1; -+ do { -+ spin_unlock(&msg_queue_spinlock); -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ if (down_interruptible( -+ &user_service->insert_event) != 0) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "DEQUEUE_MESSAGE interrupted"); -+ ret = -EINTR; -+ break; -+ } -+ spin_lock(&msg_queue_spinlock); -+ } while (user_service->msg_remove == -+ user_service->msg_insert); -+ -+ if (ret) -+ break; -+ } -+ -+ BUG_ON((int)(user_service->msg_insert - -+ user_service->msg_remove) < 0); -+ -+ header = user_service->msg_queue[user_service->msg_remove & -+ (MSG_QUEUE_SIZE - 1)]; -+ user_service->msg_remove++; -+ spin_unlock(&msg_queue_spinlock); -+ -+ up(&user_service->remove_event); -+ if (header == NULL) -+ ret = -ENOTCONN; -+ else if (header->size <= args.bufsize) { -+ /* Copy to user space if msgbuf is not NULL */ -+ if ((args.buf == NULL) || -+ (copy_to_user((void __user *)args.buf, -+ header->data, -+ header->size) == 0)) { -+ ret = header->size; -+ vchiq_release_message( -+ service->handle, -+ header); -+ } else -+ ret = -EFAULT; -+ } else { -+ vchiq_log_error(vchiq_arm_log_level, -+ "header %x: bufsize %x < size %x", -+ (unsigned int)header, args.bufsize, -+ header->size); -+ WARN(1, "invalid size\n"); -+ ret = -EMSGSIZE; -+ } -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ } break; -+ -+ case VCHIQ_IOC_GET_CLIENT_ID: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ ret = vchiq_get_client_id(handle); -+ } break; -+ -+ case VCHIQ_IOC_GET_CONFIG: { -+ VCHIQ_GET_CONFIG_T args; -+ VCHIQ_CONFIG_T config; -+ -+ if (copy_from_user(&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ if (args.config_size > sizeof(config)) { -+ ret = -EINVAL; -+ break; -+ } -+ status = vchiq_get_config(instance, args.config_size, &config); -+ if (status == VCHIQ_SUCCESS) { -+ if (copy_to_user((void __user *)args.pconfig, -+ &config, args.config_size) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ } -+ } break; -+ -+ case VCHIQ_IOC_SET_SERVICE_OPTION: { -+ VCHIQ_SET_SERVICE_OPTION_T args; -+ -+ if (copy_from_user( -+ &args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ service = find_service_for_instance(instance, args.handle); -+ if (!service) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ status = vchiq_set_service_option( -+ args.handle, args.option, args.value); -+ } break; -+ -+ case VCHIQ_IOC_DUMP_PHYS_MEM: { -+ VCHIQ_DUMP_MEM_T args; -+ -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ dump_phys_mem(args.virt_addr, args.num_bytes); -+ } break; -+ -+ case VCHIQ_IOC_LIB_VERSION: { -+ unsigned int lib_version = (unsigned int)arg; -+ -+ if (lib_version < VCHIQ_VERSION_MIN) -+ ret = -EINVAL; -+ else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED) -+ instance->use_close_delivered = 1; -+ } break; -+ -+ case VCHIQ_IOC_CLOSE_DELIVERED: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_closed_service_for_instance(instance, handle); -+ if (service != NULL) { -+ USER_SERVICE_T *user_service = -+ (USER_SERVICE_T *)service->base.userdata; -+ close_delivered(user_service); -+ } -+ else -+ ret = -EINVAL; -+ } break; -+ -+ default: -+ ret = -ENOTTY; -+ break; -+ } -+ -+ if (service) -+ unlock_service(service); -+ -+ if (ret == 0) { -+ if (status == VCHIQ_ERROR) -+ ret = -EIO; -+ else if (status == VCHIQ_RETRY) -+ ret = -EINTR; -+ } -+ -+ if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) && -+ (ret != -EWOULDBLOCK)) -+ vchiq_log_info(vchiq_arm_log_level, -+ " ioctl instance %lx, cmd %s -> status %d, %ld", -+ (unsigned long)instance, -+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? -+ ioctl_names[_IOC_NR(cmd)] : -+ "", -+ status, ret); -+ else -+ vchiq_log_trace(vchiq_arm_log_level, -+ " ioctl instance %lx, cmd %s -> status %d, %ld", -+ (unsigned long)instance, -+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? -+ ioctl_names[_IOC_NR(cmd)] : -+ "", -+ status, ret); -+ -+ return ret; -+} -+ -+/**************************************************************************** -+* -+* vchiq_open -+* -+***************************************************************************/ -+ -+static int -+vchiq_open(struct inode *inode, struct file *file) -+{ -+ int dev = iminor(inode) & 0x0f; -+ vchiq_log_info(vchiq_arm_log_level, "vchiq_open"); -+ switch (dev) { -+ case VCHIQ_MINOR: { -+ int ret; -+ VCHIQ_STATE_T *state = vchiq_get_state(); -+ VCHIQ_INSTANCE_T instance; -+ -+ if (!state) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "vchiq has no connection to VideoCore"); -+ return -ENOTCONN; -+ } -+ -+ instance = kzalloc(sizeof(*instance), GFP_KERNEL); -+ if (!instance) -+ return -ENOMEM; -+ -+ instance->state = state; -+ instance->pid = current->tgid; -+ -+ ret = vchiq_debugfs_add_instance(instance); -+ if (ret != 0) { -+ kfree(instance); -+ return ret; -+ } -+ -+ sema_init(&instance->insert_event, 0); -+ sema_init(&instance->remove_event, 0); -+ mutex_init(&instance->completion_mutex); -+ mutex_init(&instance->bulk_waiter_list_mutex); -+ INIT_LIST_HEAD(&instance->bulk_waiter_list); -+ -+ file->private_data = instance; -+ } break; -+ -+ default: -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unknown minor device: %d", dev); -+ return -ENXIO; -+ } -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vchiq_release -+* -+***************************************************************************/ -+ -+static int -+vchiq_release(struct inode *inode, struct file *file) -+{ -+ int dev = iminor(inode) & 0x0f; -+ int ret = 0; -+ switch (dev) { -+ case VCHIQ_MINOR: { -+ VCHIQ_INSTANCE_T instance = file->private_data; -+ VCHIQ_STATE_T *state = vchiq_get_state(); -+ VCHIQ_SERVICE_T *service; -+ int i; -+ -+ vchiq_log_info(vchiq_arm_log_level, -+ "vchiq_release: instance=%lx", -+ (unsigned long)instance); -+ -+ if (!state) { -+ ret = -EPERM; -+ goto out; -+ } -+ -+ /* Ensure videocore is awake to allow termination. */ -+ vchiq_use_internal(instance->state, NULL, -+ USE_TYPE_VCHIQ); -+ -+ mutex_lock(&instance->completion_mutex); -+ -+ /* Wake the completion thread and ask it to exit */ -+ instance->closing = 1; -+ up(&instance->insert_event); -+ -+ mutex_unlock(&instance->completion_mutex); -+ -+ /* Wake the slot handler if the completion queue is full. */ -+ up(&instance->remove_event); -+ -+ /* Mark all services for termination... */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, -+ &i)) != NULL) { -+ USER_SERVICE_T *user_service = service->base.userdata; -+ -+ /* Wake the slot handler if the msg queue is full. */ -+ up(&user_service->remove_event); -+ -+ vchiq_terminate_service_internal(service); -+ unlock_service(service); -+ } -+ -+ /* ...and wait for them to die */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, &i)) -+ != NULL) { -+ USER_SERVICE_T *user_service = service->base.userdata; -+ -+ down(&service->remove_event); -+ -+ BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); -+ -+ spin_lock(&msg_queue_spinlock); -+ -+ while (user_service->msg_remove != -+ user_service->msg_insert) { -+ VCHIQ_HEADER_T *header = user_service-> -+ msg_queue[user_service->msg_remove & -+ (MSG_QUEUE_SIZE - 1)]; -+ user_service->msg_remove++; -+ spin_unlock(&msg_queue_spinlock); -+ -+ if (header) -+ vchiq_release_message( -+ service->handle, -+ header); -+ spin_lock(&msg_queue_spinlock); -+ } -+ -+ spin_unlock(&msg_queue_spinlock); -+ -+ unlock_service(service); -+ } -+ -+ /* Release any closed services */ -+ while (instance->completion_remove != -+ instance->completion_insert) { -+ VCHIQ_COMPLETION_DATA_T *completion; -+ VCHIQ_SERVICE_T *service; -+ completion = &instance->completions[ -+ instance->completion_remove & -+ (MAX_COMPLETIONS - 1)]; -+ service = completion->service_userdata; -+ if (completion->reason == VCHIQ_SERVICE_CLOSED) -+ { -+ USER_SERVICE_T *user_service = -+ service->base.userdata; -+ -+ /* Wake any blocked user-thread */ -+ if (instance->use_close_delivered) -+ up(&user_service->close_event); -+ unlock_service(service); -+ } -+ instance->completion_remove++; -+ } -+ -+ /* Release the PEER service count. */ -+ vchiq_release_internal(instance->state, NULL); -+ -+ { -+ struct list_head *pos, *next; -+ list_for_each_safe(pos, next, -+ &instance->bulk_waiter_list) { -+ struct bulk_waiter_node *waiter; -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ vchiq_log_info(vchiq_arm_log_level, -+ "bulk_waiter - cleaned up %x " -+ "for pid %d", -+ (unsigned int)waiter, waiter->pid); -+ kfree(waiter); -+ } -+ } -+ -+ vchiq_debugfs_remove_instance(instance); -+ -+ kfree(instance); -+ file->private_data = NULL; -+ } break; -+ -+ default: -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unknown minor device: %d", dev); -+ ret = -ENXIO; -+ } -+ -+out: -+ return ret; -+} -+ -+/**************************************************************************** -+* -+* vchiq_dump -+* -+***************************************************************************/ -+ -+void -+vchiq_dump(void *dump_context, const char *str, int len) -+{ -+ DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context; -+ -+ if (context->actual < context->space) { -+ int copy_bytes; -+ if (context->offset > 0) { -+ int skip_bytes = min(len, (int)context->offset); -+ str += skip_bytes; -+ len -= skip_bytes; -+ context->offset -= skip_bytes; -+ if (context->offset > 0) -+ return; -+ } -+ copy_bytes = min(len, (int)(context->space - context->actual)); -+ if (copy_bytes == 0) -+ return; -+ if (copy_to_user(context->buf + context->actual, str, -+ copy_bytes)) -+ context->actual = -EFAULT; -+ context->actual += copy_bytes; -+ len -= copy_bytes; -+ -+ /* If tne terminating NUL is included in the length, then it -+ ** marks the end of a line and should be replaced with a -+ ** carriage return. */ -+ if ((len == 0) && (str[copy_bytes - 1] == '\0')) { -+ char cr = '\n'; -+ if (copy_to_user(context->buf + context->actual - 1, -+ &cr, 1)) -+ context->actual = -EFAULT; -+ } -+ } -+} -+ -+/**************************************************************************** -+* -+* vchiq_dump_platform_instance_state -+* -+***************************************************************************/ -+ -+void -+vchiq_dump_platform_instances(void *dump_context) -+{ -+ VCHIQ_STATE_T *state = vchiq_get_state(); -+ char buf[80]; -+ int len; -+ int i; -+ -+ /* There is no list of instances, so instead scan all services, -+ marking those that have been dumped. */ -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ VCHIQ_INSTANCE_T instance; -+ -+ if (service && (service->base.callback == service_callback)) { -+ instance = service->instance; -+ if (instance) -+ instance->mark = 0; -+ } -+ } -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ VCHIQ_INSTANCE_T instance; -+ -+ if (service && (service->base.callback == service_callback)) { -+ instance = service->instance; -+ if (instance && !instance->mark) { -+ len = snprintf(buf, sizeof(buf), -+ "Instance %x: pid %d,%s completions " -+ "%d/%d", -+ (unsigned int)instance, instance->pid, -+ instance->connected ? " connected, " : -+ "", -+ instance->completion_insert - -+ instance->completion_remove, -+ MAX_COMPLETIONS); -+ -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ instance->mark = 1; -+ } -+ } -+ } -+} -+ -+/**************************************************************************** -+* -+* vchiq_dump_platform_service_state -+* -+***************************************************************************/ -+ -+void -+vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service) -+{ -+ USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata; -+ char buf[80]; -+ int len; -+ -+ len = snprintf(buf, sizeof(buf), " instance %x", -+ (unsigned int)service->instance); -+ -+ if ((service->base.callback == service_callback) && -+ user_service->is_vchi) { -+ len += snprintf(buf + len, sizeof(buf) - len, -+ ", %d/%d messages", -+ user_service->msg_insert - user_service->msg_remove, -+ MSG_QUEUE_SIZE); -+ -+ if (user_service->dequeue_pending) -+ len += snprintf(buf + len, sizeof(buf) - len, -+ " (dequeue pending)"); -+ } -+ -+ vchiq_dump(dump_context, buf, len + 1); -+} -+ -+/**************************************************************************** -+* -+* dump_user_mem -+* -+***************************************************************************/ -+ -+static void -+dump_phys_mem(void *virt_addr, uint32_t num_bytes) -+{ -+ int rc; -+ uint8_t *end_virt_addr = virt_addr + num_bytes; -+ int num_pages; -+ int offset; -+ int end_offset; -+ int page_idx; -+ int prev_idx; -+ struct page *page; -+ struct page **pages; -+ uint8_t *kmapped_virt_ptr; -+ -+ /* Align virtAddr and endVirtAddr to 16 byte boundaries. */ -+ -+ virt_addr = (void *)((unsigned long)virt_addr & ~0x0fuL); -+ end_virt_addr = (void *)(((unsigned long)end_virt_addr + 15uL) & -+ ~0x0fuL); -+ -+ offset = (int)(long)virt_addr & (PAGE_SIZE - 1); -+ end_offset = (int)(long)end_virt_addr & (PAGE_SIZE - 1); -+ -+ num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE; -+ -+ pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL); -+ if (pages == NULL) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to allocation memory for %d pages\n", -+ num_pages); -+ return; -+ } -+ -+ down_read(¤t->mm->mmap_sem); -+ rc = get_user_pages( -+ (unsigned long)virt_addr, /* start */ -+ num_pages, /* len */ -+ 0, /* write */ -+ 0, /* force */ -+ pages, /* pages (array of page pointers) */ -+ NULL); /* vmas */ -+ up_read(¤t->mm->mmap_sem); -+ -+ prev_idx = -1; -+ page = NULL; -+ -+ while (offset < end_offset) { -+ -+ int page_offset = offset % PAGE_SIZE; -+ page_idx = offset / PAGE_SIZE; -+ -+ if (page_idx != prev_idx) { -+ -+ if (page != NULL) -+ kunmap(page); -+ page = pages[page_idx]; -+ kmapped_virt_ptr = kmap(page); -+ -+ prev_idx = page_idx; -+ } -+ -+ if (vchiq_arm_log_level >= VCHIQ_LOG_TRACE) -+ vchiq_log_dump_mem("ph", -+ (uint32_t)(unsigned long)&kmapped_virt_ptr[ -+ page_offset], -+ &kmapped_virt_ptr[page_offset], 16); -+ -+ offset += 16; -+ } -+ if (page != NULL) -+ kunmap(page); -+ -+ for (page_idx = 0; page_idx < num_pages; page_idx++) -+ put_page(pages[page_idx]); -+ -+ kfree(pages); -+} -+ -+/**************************************************************************** -+* -+* vchiq_read -+* -+***************************************************************************/ -+ -+static ssize_t -+vchiq_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ DUMP_CONTEXT_T context; -+ context.buf = buf; -+ context.actual = 0; -+ context.space = count; -+ context.offset = *ppos; -+ -+ vchiq_dump_state(&context, &g_state); -+ -+ *ppos += context.actual; -+ -+ return context.actual; -+} -+ -+VCHIQ_STATE_T * -+vchiq_get_state(void) -+{ -+ -+ if (g_state.remote == NULL) -+ printk(KERN_ERR "%s: g_state.remote == NULL\n", __func__); -+ else if (g_state.remote->initialised != 1) -+ printk(KERN_NOTICE "%s: g_state.remote->initialised != 1 (%d)\n", -+ __func__, g_state.remote->initialised); -+ -+ return ((g_state.remote != NULL) && -+ (g_state.remote->initialised == 1)) ? &g_state : NULL; -+} -+ -+static const struct file_operations -+vchiq_fops = { -+ .owner = THIS_MODULE, -+ .unlocked_ioctl = vchiq_ioctl, -+ .open = vchiq_open, -+ .release = vchiq_release, -+ .read = vchiq_read -+}; -+ -+/* -+ * Autosuspend related functionality -+ */ -+ -+int -+vchiq_videocore_wanted(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ if (!arm_state) -+ /* autosuspend not supported - always return wanted */ -+ return 1; -+ else if (arm_state->blocked_count) -+ return 1; -+ else if (!arm_state->videocore_use_count) -+ /* usage count zero - check for override unless we're forcing */ -+ if (arm_state->resume_blocked) -+ return 0; -+ else -+ return vchiq_platform_videocore_wanted(state); -+ else -+ /* non-zero usage count - videocore still required */ -+ return 1; -+} -+ -+static VCHIQ_STATUS_T -+vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, -+ VCHIQ_SERVICE_HANDLE_T service_user, -+ void *bulk_user) -+{ -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s callback reason %d", __func__, reason); -+ return 0; -+} -+ -+static int -+vchiq_keepalive_thread_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ -+ VCHIQ_STATUS_T status; -+ VCHIQ_INSTANCE_T instance; -+ VCHIQ_SERVICE_HANDLE_T ka_handle; -+ -+ VCHIQ_SERVICE_PARAMS_T params = { -+ .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), -+ .callback = vchiq_keepalive_vchiq_callback, -+ .version = KEEPALIVE_VER, -+ .version_min = KEEPALIVE_VER_MIN -+ }; -+ -+ status = vchiq_initialise(&instance); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_initialise failed %d", __func__, status); -+ goto exit; -+ } -+ -+ status = vchiq_connect(instance); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_connect failed %d", __func__, status); -+ goto shutdown; -+ } -+ -+ status = vchiq_add_service(instance, ¶ms, &ka_handle); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_open_service failed %d", __func__, status); -+ goto shutdown; -+ } -+ -+ while (1) { -+ long rc = 0, uc = 0; -+ if (wait_for_completion_interruptible(&arm_state->ka_evt) -+ != 0) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s interrupted", __func__); -+ flush_signals(current); -+ continue; -+ } -+ -+ /* read and clear counters. Do release_count then use_count to -+ * prevent getting more releases than uses */ -+ rc = atomic_xchg(&arm_state->ka_release_count, 0); -+ uc = atomic_xchg(&arm_state->ka_use_count, 0); -+ -+ /* Call use/release service the requisite number of times. -+ * Process use before release so use counts don't go negative */ -+ while (uc--) { -+ atomic_inc(&arm_state->ka_use_ack_count); -+ status = vchiq_use_service(ka_handle); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_use_service error %d", -+ __func__, status); -+ } -+ } -+ while (rc--) { -+ status = vchiq_release_service(ka_handle); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_release_service error %d", -+ __func__, status); -+ } -+ } -+ } -+ -+shutdown: -+ vchiq_shutdown(instance); -+exit: -+ return 0; -+} -+ -+ -+ -+VCHIQ_STATUS_T -+vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (arm_state) { -+ rwlock_init(&arm_state->susp_res_lock); -+ -+ init_completion(&arm_state->ka_evt); -+ atomic_set(&arm_state->ka_use_count, 0); -+ atomic_set(&arm_state->ka_use_ack_count, 0); -+ atomic_set(&arm_state->ka_release_count, 0); -+ -+ init_completion(&arm_state->vc_suspend_complete); -+ -+ init_completion(&arm_state->vc_resume_complete); -+ /* Initialise to 'done' state. We only want to block on resume -+ * completion while videocore is suspended. */ -+ set_resume_state(arm_state, VC_RESUME_RESUMED); -+ -+ init_completion(&arm_state->resume_blocker); -+ /* Initialise to 'done' state. We only want to block on this -+ * completion while resume is blocked */ -+ complete_all(&arm_state->resume_blocker); -+ -+ init_completion(&arm_state->blocked_blocker); -+ /* Initialise to 'done' state. We only want to block on this -+ * completion while things are waiting on the resume blocker */ -+ complete_all(&arm_state->blocked_blocker); -+ -+ arm_state->suspend_timer_timeout = SUSPEND_TIMER_TIMEOUT_MS; -+ arm_state->suspend_timer_running = 0; -+ init_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer.data = (unsigned long)(state); -+ arm_state->suspend_timer.function = suspend_timer_callback; -+ -+ arm_state->first_connect = 0; -+ -+ } -+ return status; -+} -+ -+/* -+** Functions to modify the state variables; -+** set_suspend_state -+** set_resume_state -+** -+** There are more state variables than we might like, so ensure they remain in -+** step. Suspend and resume state are maintained separately, since most of -+** these state machines can operate independently. However, there are a few -+** states where state transitions in one state machine cause a reset to the -+** other state machine. In addition, there are some completion events which -+** need to occur on state machine reset and end-state(s), so these are also -+** dealt with in these functions. -+** -+** In all states we set the state variable according to the input, but in some -+** cases we perform additional steps outlined below; -+** -+** VC_SUSPEND_IDLE - Initialise the suspend completion at the same time. -+** The suspend completion is completed after any suspend -+** attempt. When we reset the state machine we also reset -+** the completion. This reset occurs when videocore is -+** resumed, and also if we initiate suspend after a suspend -+** failure. -+** -+** VC_SUSPEND_IN_PROGRESS - This state is considered the point of no return for -+** suspend - ie from this point on we must try to suspend -+** before resuming can occur. We therefore also reset the -+** resume state machine to VC_RESUME_IDLE in this state. -+** -+** VC_SUSPEND_SUSPENDED - Suspend has completed successfully. Also call -+** complete_all on the suspend completion to notify -+** anything waiting for suspend to happen. -+** -+** VC_SUSPEND_REJECTED - Videocore rejected suspend. Videocore will also -+** initiate resume, so no need to alter resume state. -+** We call complete_all on the suspend completion to notify -+** of suspend rejection. -+** -+** VC_SUSPEND_FAILED - We failed to initiate videocore suspend. We notify the -+** suspend completion and reset the resume state machine. -+** -+** VC_RESUME_IDLE - Initialise the resume completion at the same time. The -+** resume completion is in it's 'done' state whenever -+** videcore is running. Therfore, the VC_RESUME_IDLE state -+** implies that videocore is suspended. -+** Hence, any thread which needs to wait until videocore is -+** running can wait on this completion - it will only block -+** if videocore is suspended. -+** -+** VC_RESUME_RESUMED - Resume has completed successfully. Videocore is running. -+** Call complete_all on the resume completion to unblock -+** any threads waiting for resume. Also reset the suspend -+** state machine to it's idle state. -+** -+** VC_RESUME_FAILED - Currently unused - no mechanism to fail resume exists. -+*/ -+ -+void -+set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_suspend_status new_state) -+{ -+ /* set the state in all cases */ -+ arm_state->vc_suspend_state = new_state; -+ -+ /* state specific additional actions */ -+ switch (new_state) { -+ case VC_SUSPEND_FORCE_CANCELED: -+ complete_all(&arm_state->vc_suspend_complete); -+ break; -+ case VC_SUSPEND_REJECTED: -+ complete_all(&arm_state->vc_suspend_complete); -+ break; -+ case VC_SUSPEND_FAILED: -+ complete_all(&arm_state->vc_suspend_complete); -+ arm_state->vc_resume_state = VC_RESUME_RESUMED; -+ complete_all(&arm_state->vc_resume_complete); -+ break; -+ case VC_SUSPEND_IDLE: -+ reinit_completion(&arm_state->vc_suspend_complete); -+ break; -+ case VC_SUSPEND_REQUESTED: -+ break; -+ case VC_SUSPEND_IN_PROGRESS: -+ set_resume_state(arm_state, VC_RESUME_IDLE); -+ break; -+ case VC_SUSPEND_SUSPENDED: -+ complete_all(&arm_state->vc_suspend_complete); -+ break; -+ default: -+ BUG(); -+ break; -+ } -+} -+ -+void -+set_resume_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_resume_status new_state) -+{ -+ /* set the state in all cases */ -+ arm_state->vc_resume_state = new_state; -+ -+ /* state specific additional actions */ -+ switch (new_state) { -+ case VC_RESUME_FAILED: -+ break; -+ case VC_RESUME_IDLE: -+ reinit_completion(&arm_state->vc_resume_complete); -+ break; -+ case VC_RESUME_REQUESTED: -+ break; -+ case VC_RESUME_IN_PROGRESS: -+ break; -+ case VC_RESUME_RESUMED: -+ complete_all(&arm_state->vc_resume_complete); -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ break; -+ default: -+ BUG(); -+ break; -+ } -+} -+ -+ -+/* should be called with the write lock held */ -+inline void -+start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ del_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer.expires = jiffies + -+ msecs_to_jiffies(arm_state-> -+ suspend_timer_timeout); -+ add_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer_running = 1; -+} -+ -+/* should be called with the write lock held */ -+static inline void -+stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ if (arm_state->suspend_timer_running) { -+ del_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer_running = 0; -+ } -+} -+ -+static inline int -+need_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && -+ (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && -+ vchiq_videocore_wanted(state); -+} -+ -+static int -+block_resume(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ int status = VCHIQ_SUCCESS; -+ const unsigned long timeout_val = -+ msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS); -+ int resume_count = 0; -+ -+ /* Allow any threads which were blocked by the last force suspend to -+ * complete if they haven't already. Only give this one shot; if -+ * blocked_count is incremented after blocked_blocker is completed -+ * (which only happens when blocked_count hits 0) then those threads -+ * will have to wait until next time around */ -+ if (arm_state->blocked_count) { -+ reinit_completion(&arm_state->blocked_blocker); -+ write_unlock_bh(&arm_state->susp_res_lock); -+ vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " -+ "blocked clients", __func__); -+ if (wait_for_completion_interruptible_timeout( -+ &arm_state->blocked_blocker, timeout_val) -+ <= 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s wait for " -+ "previously blocked clients failed" , __func__); -+ status = VCHIQ_ERROR; -+ write_lock_bh(&arm_state->susp_res_lock); -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s previously blocked " -+ "clients resumed", __func__); -+ write_lock_bh(&arm_state->susp_res_lock); -+ } -+ -+ /* We need to wait for resume to complete if it's in process */ -+ while (arm_state->vc_resume_state != VC_RESUME_RESUMED && -+ arm_state->vc_resume_state > VC_RESUME_IDLE) { -+ if (resume_count > 1) { -+ status = VCHIQ_ERROR; -+ vchiq_log_error(vchiq_susp_log_level, "%s waited too " -+ "many times for resume" , __func__); -+ goto out; -+ } -+ write_unlock_bh(&arm_state->susp_res_lock); -+ vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", -+ __func__); -+ if (wait_for_completion_interruptible_timeout( -+ &arm_state->vc_resume_complete, timeout_val) -+ <= 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s wait for " -+ "resume failed (%s)", __func__, -+ resume_state_names[arm_state->vc_resume_state + -+ VC_RESUME_NUM_OFFSET]); -+ status = VCHIQ_ERROR; -+ write_lock_bh(&arm_state->susp_res_lock); -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s resumed", __func__); -+ write_lock_bh(&arm_state->susp_res_lock); -+ resume_count++; -+ } -+ reinit_completion(&arm_state->resume_blocker); -+ arm_state->resume_blocked = 1; -+ -+out: -+ return status; -+} -+ -+static inline void -+unblock_resume(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ complete_all(&arm_state->resume_blocker); -+ arm_state->resume_blocked = 0; -+} -+ -+/* Initiate suspend via slot handler. Should be called with the write lock -+ * held */ -+VCHIQ_STATUS_T -+vchiq_arm_vcsuspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ status = VCHIQ_SUCCESS; -+ -+ -+ switch (arm_state->vc_suspend_state) { -+ case VC_SUSPEND_REQUESTED: -+ vchiq_log_info(vchiq_susp_log_level, "%s: suspend already " -+ "requested", __func__); -+ break; -+ case VC_SUSPEND_IN_PROGRESS: -+ vchiq_log_info(vchiq_susp_log_level, "%s: suspend already in " -+ "progress", __func__); -+ break; -+ -+ default: -+ /* We don't expect to be in other states, so log but continue -+ * anyway */ -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s unexpected suspend state %s", __func__, -+ suspend_state_names[arm_state->vc_suspend_state + -+ VC_SUSPEND_NUM_OFFSET]); -+ /* fall through */ -+ case VC_SUSPEND_REJECTED: -+ case VC_SUSPEND_FAILED: -+ /* Ensure any idle state actions have been run */ -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ /* fall through */ -+ case VC_SUSPEND_IDLE: -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: suspending", __func__); -+ set_suspend_state(arm_state, VC_SUSPEND_REQUESTED); -+ /* kick the slot handler thread to initiate suspend */ -+ request_poll(state, NULL, 0); -+ break; -+ } -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); -+ return status; -+} -+ -+void -+vchiq_platform_check_suspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int susp = 0; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->vc_suspend_state == VC_SUSPEND_REQUESTED && -+ arm_state->vc_resume_state == VC_RESUME_RESUMED) { -+ set_suspend_state(arm_state, VC_SUSPEND_IN_PROGRESS); -+ susp = 1; -+ } -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (susp) -+ vchiq_platform_suspend(state); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return; -+} -+ -+ -+static void -+output_timeout_error(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ char service_err[50] = ""; -+ int vc_use_count = arm_state->videocore_use_count; -+ int active_services = state->unused_service; -+ int i; -+ -+ if (!arm_state->videocore_use_count) { -+ snprintf(service_err, 50, " Videocore usecount is 0"); -+ goto output_msg; -+ } -+ for (i = 0; i < active_services; i++) { -+ VCHIQ_SERVICE_T *service_ptr = state->services[i]; -+ if (service_ptr && service_ptr->service_use_count && -+ (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) { -+ snprintf(service_err, 50, " %c%c%c%c(%d) service has " -+ "use count %d%s", VCHIQ_FOURCC_AS_4CHARS( -+ service_ptr->base.fourcc), -+ service_ptr->client_id, -+ service_ptr->service_use_count, -+ service_ptr->service_use_count == -+ vc_use_count ? "" : " (+ more)"); -+ break; -+ } -+ } -+ -+output_msg: -+ vchiq_log_error(vchiq_susp_log_level, -+ "timed out waiting for vc suspend (%d).%s", -+ arm_state->autosuspend_override, service_err); -+ -+} -+ -+/* Try to get videocore into suspended state, regardless of autosuspend state. -+** We don't actually force suspend, since videocore may get into a bad state -+** if we force suspend at a bad time. Instead, we wait for autosuspend to -+** determine a good point to suspend. If this doesn't happen within 100ms we -+** report failure. -+** -+** Returns VCHIQ_SUCCESS if videocore suspended successfully, VCHIQ_RETRY if -+** videocore failed to suspend in time or VCHIQ_ERROR if interrupted. -+*/ -+VCHIQ_STATUS_T -+vchiq_arm_force_suspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ long rc = 0; -+ int repeat = -1; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ -+ status = block_resume(arm_state); -+ if (status != VCHIQ_SUCCESS) -+ goto unlock; -+ if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { -+ /* Already suspended - just block resume and exit */ -+ vchiq_log_info(vchiq_susp_log_level, "%s already suspended", -+ __func__); -+ status = VCHIQ_SUCCESS; -+ goto unlock; -+ } else if (arm_state->vc_suspend_state <= VC_SUSPEND_IDLE) { -+ /* initiate suspend immediately in the case that we're waiting -+ * for the timeout */ -+ stop_suspend_timer(arm_state); -+ if (!vchiq_videocore_wanted(state)) { -+ vchiq_log_info(vchiq_susp_log_level, "%s videocore " -+ "idle, initiating suspend", __func__); -+ status = vchiq_arm_vcsuspend(state); -+ } else if (arm_state->autosuspend_override < -+ FORCE_SUSPEND_FAIL_MAX) { -+ vchiq_log_info(vchiq_susp_log_level, "%s letting " -+ "videocore go idle", __func__); -+ status = VCHIQ_SUCCESS; -+ } else { -+ vchiq_log_warning(vchiq_susp_log_level, "%s failed too " -+ "many times - attempting suspend", __func__); -+ status = vchiq_arm_vcsuspend(state); -+ } -+ } else { -+ vchiq_log_info(vchiq_susp_log_level, "%s videocore suspend " -+ "in progress - wait for completion", __func__); -+ status = VCHIQ_SUCCESS; -+ } -+ -+ /* Wait for suspend to happen due to system idle (not forced..) */ -+ if (status != VCHIQ_SUCCESS) -+ goto unblock_resume; -+ -+ do { -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ rc = wait_for_completion_interruptible_timeout( -+ &arm_state->vc_suspend_complete, -+ msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS)); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (rc < 0) { -+ vchiq_log_warning(vchiq_susp_log_level, "%s " -+ "interrupted waiting for suspend", __func__); -+ status = VCHIQ_ERROR; -+ goto unblock_resume; -+ } else if (rc == 0) { -+ if (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) { -+ /* Repeat timeout once if in progress */ -+ if (repeat < 0) { -+ repeat = 1; -+ continue; -+ } -+ } -+ arm_state->autosuspend_override++; -+ output_timeout_error(state); -+ -+ status = VCHIQ_RETRY; -+ goto unblock_resume; -+ } -+ } while (0 < (repeat--)); -+ -+ /* Check and report state in case we need to abort ARM suspend */ -+ if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED) { -+ status = VCHIQ_RETRY; -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s videocore suspend failed (state %s)", __func__, -+ suspend_state_names[arm_state->vc_suspend_state + -+ VC_SUSPEND_NUM_OFFSET]); -+ /* Reset the state only if it's still in an error state. -+ * Something could have already initiated another suspend. */ -+ if (arm_state->vc_suspend_state < VC_SUSPEND_IDLE) -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ -+ goto unblock_resume; -+ } -+ -+ /* successfully suspended - unlock and exit */ -+ goto unlock; -+ -+unblock_resume: -+ /* all error states need to unblock resume before exit */ -+ unblock_resume(arm_state); -+ -+unlock: -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); -+ return status; -+} -+ -+void -+vchiq_check_suspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED && -+ arm_state->first_connect && -+ !vchiq_videocore_wanted(state)) { -+ vchiq_arm_vcsuspend(state); -+ } -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return; -+} -+ -+ -+int -+vchiq_arm_allow_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int resume = 0; -+ int ret = -1; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ unblock_resume(arm_state); -+ resume = vchiq_check_resume(state); -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (resume) { -+ if (wait_for_completion_interruptible( -+ &arm_state->vc_resume_complete) < 0) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s interrupted", __func__); -+ /* failed, cannot accurately derive suspend -+ * state, so exit early. */ -+ goto out; -+ } -+ } -+ -+ read_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: Videocore remains suspended", __func__); -+ } else { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: Videocore resumed", __func__); -+ ret = 0; -+ } -+ read_unlock_bh(&arm_state->susp_res_lock); -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); -+ return ret; -+} -+ -+/* This function should be called with the write lock held */ -+int -+vchiq_check_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int resume = 0; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ if (need_resume(state)) { -+ set_resume_state(arm_state, VC_RESUME_REQUESTED); -+ request_poll(state, NULL, 0); -+ resume = 1; -+ } -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return resume; -+} -+ -+void -+vchiq_platform_check_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int res = 0; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->wake_address == 0) { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: already awake", __func__); -+ goto unlock; -+ } -+ if (arm_state->vc_resume_state == VC_RESUME_IN_PROGRESS) { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: already resuming", __func__); -+ goto unlock; -+ } -+ -+ if (arm_state->vc_resume_state == VC_RESUME_REQUESTED) { -+ set_resume_state(arm_state, VC_RESUME_IN_PROGRESS); -+ res = 1; -+ } else -+ vchiq_log_trace(vchiq_susp_log_level, -+ "%s: not resuming (resume state %s)", __func__, -+ resume_state_names[arm_state->vc_resume_state + -+ VC_RESUME_NUM_OFFSET]); -+ -+unlock: -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (res) -+ vchiq_platform_resume(state); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return; -+ -+} -+ -+ -+ -+VCHIQ_STATUS_T -+vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ enum USE_TYPE_E use_type) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; -+ char entity[16]; -+ int *entity_uc; -+ int local_uc, local_entity_uc; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ if (use_type == USE_TYPE_VCHIQ) { -+ sprintf(entity, "VCHIQ: "); -+ entity_uc = &arm_state->peer_use_count; -+ } else if (service) { -+ sprintf(entity, "%c%c%c%c:%03d", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->client_id); -+ entity_uc = &service->service_use_count; -+ } else { -+ vchiq_log_error(vchiq_susp_log_level, "%s null service " -+ "ptr", __func__); -+ ret = VCHIQ_ERROR; -+ goto out; -+ } -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ while (arm_state->resume_blocked) { -+ /* If we call 'use' while force suspend is waiting for suspend, -+ * then we're about to block the thread which the force is -+ * waiting to complete, so we're bound to just time out. In this -+ * case, set the suspend state such that the wait will be -+ * canceled, so we can complete as quickly as possible. */ -+ if (arm_state->resume_blocked && arm_state->vc_suspend_state == -+ VC_SUSPEND_IDLE) { -+ set_suspend_state(arm_state, VC_SUSPEND_FORCE_CANCELED); -+ break; -+ } -+ /* If suspend is already in progress then we need to block */ -+ if (!try_wait_for_completion(&arm_state->resume_blocker)) { -+ /* Indicate that there are threads waiting on the resume -+ * blocker. These need to be allowed to complete before -+ * a _second_ call to force suspend can complete, -+ * otherwise low priority threads might never actually -+ * continue */ -+ arm_state->blocked_count++; -+ write_unlock_bh(&arm_state->susp_res_lock); -+ vchiq_log_info(vchiq_susp_log_level, "%s %s resume " -+ "blocked - waiting...", __func__, entity); -+ if (wait_for_completion_killable( -+ &arm_state->resume_blocker) != 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s %s " -+ "wait for resume blocker interrupted", -+ __func__, entity); -+ ret = VCHIQ_ERROR; -+ write_lock_bh(&arm_state->susp_res_lock); -+ arm_state->blocked_count--; -+ write_unlock_bh(&arm_state->susp_res_lock); -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s %s resume " -+ "unblocked", __func__, entity); -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (--arm_state->blocked_count == 0) -+ complete_all(&arm_state->blocked_blocker); -+ } -+ } -+ -+ stop_suspend_timer(arm_state); -+ -+ local_uc = ++arm_state->videocore_use_count; -+ local_entity_uc = ++(*entity_uc); -+ -+ /* If there's a pending request which hasn't yet been serviced then -+ * just clear it. If we're past VC_SUSPEND_REQUESTED state then -+ * vc_resume_complete will block until we either resume or fail to -+ * suspend */ -+ if (arm_state->vc_suspend_state <= VC_SUSPEND_REQUESTED) -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ -+ if ((use_type != USE_TYPE_SERVICE_NO_RESUME) && need_resume(state)) { -+ set_resume_state(arm_state, VC_RESUME_REQUESTED); -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s %s count %d, state count %d", -+ __func__, entity, local_entity_uc, local_uc); -+ request_poll(state, NULL, 0); -+ } else -+ vchiq_log_trace(vchiq_susp_log_level, -+ "%s %s count %d, state count %d", -+ __func__, entity, *entity_uc, local_uc); -+ -+ -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ /* Completion is in a done state when we're not suspended, so this won't -+ * block for the non-suspended case. */ -+ if (!try_wait_for_completion(&arm_state->vc_resume_complete)) { -+ vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume", -+ __func__, entity); -+ if (wait_for_completion_killable( -+ &arm_state->vc_resume_complete) != 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s %s wait for " -+ "resume interrupted", __func__, entity); -+ ret = VCHIQ_ERROR; -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s %s resumed", __func__, -+ entity); -+ } -+ -+ if (ret == VCHIQ_SUCCESS) { -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); -+ while (ack_cnt && (status == VCHIQ_SUCCESS)) { -+ /* Send the use notify to videocore */ -+ status = vchiq_send_remote_use_active(state); -+ if (status == VCHIQ_SUCCESS) -+ ack_cnt--; -+ else -+ atomic_add(ack_cnt, -+ &arm_state->ka_use_ack_count); -+ } -+ } -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); -+ return ret; -+} -+ -+VCHIQ_STATUS_T -+vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; -+ char entity[16]; -+ int *entity_uc; -+ int local_uc, local_entity_uc; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ if (service) { -+ sprintf(entity, "%c%c%c%c:%03d", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->client_id); -+ entity_uc = &service->service_use_count; -+ } else { -+ sprintf(entity, "PEER: "); -+ entity_uc = &arm_state->peer_use_count; -+ } -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (!arm_state->videocore_use_count || !(*entity_uc)) { -+ /* Don't use BUG_ON - don't allow user thread to crash kernel */ -+ WARN_ON(!arm_state->videocore_use_count); -+ WARN_ON(!(*entity_uc)); -+ ret = VCHIQ_ERROR; -+ goto unlock; -+ } -+ local_uc = --arm_state->videocore_use_count; -+ local_entity_uc = --(*entity_uc); -+ -+ if (!vchiq_videocore_wanted(state)) { -+ if (vchiq_platform_use_suspend_timer() && -+ !arm_state->resume_blocked) { -+ /* Only use the timer if we're not trying to force -+ * suspend (=> resume_blocked) */ -+ start_suspend_timer(arm_state); -+ } else { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s %s count %d, state count %d - suspending", -+ __func__, entity, *entity_uc, -+ arm_state->videocore_use_count); -+ vchiq_arm_vcsuspend(state); -+ } -+ } else -+ vchiq_log_trace(vchiq_susp_log_level, -+ "%s %s count %d, state count %d", -+ __func__, entity, *entity_uc, -+ arm_state->videocore_use_count); -+ -+unlock: -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); -+ return ret; -+} -+ -+void -+vchiq_on_remote_use(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ atomic_inc(&arm_state->ka_use_count); -+ complete(&arm_state->ka_evt); -+} -+ -+void -+vchiq_on_remote_release(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ atomic_inc(&arm_state->ka_release_count); -+ complete(&arm_state->ka_evt); -+} -+ -+VCHIQ_STATUS_T -+vchiq_use_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); -+} -+ -+VCHIQ_STATUS_T -+vchiq_release_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ return vchiq_release_internal(service->state, service); -+} -+ -+VCHIQ_DEBUGFS_NODE_T * -+vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) -+{ -+ return &instance->debugfs_node; -+} -+ -+int -+vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_SERVICE_T *service; -+ int use_count = 0, i; -+ i = 0; -+ while ((service = next_service_by_instance(instance->state, -+ instance, &i)) != NULL) { -+ use_count += service->service_use_count; -+ unlock_service(service); -+ } -+ return use_count; -+} -+ -+int -+vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance) -+{ -+ return instance->pid; -+} -+ -+int -+vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance) -+{ -+ return instance->trace; -+} -+ -+void -+vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) -+{ -+ VCHIQ_SERVICE_T *service; -+ int i; -+ i = 0; -+ while ((service = next_service_by_instance(instance->state, -+ instance, &i)) != NULL) { -+ service->trace = trace; -+ unlock_service(service); -+ } -+ instance->trace = (trace != 0); -+} -+ -+static void suspend_timer_callback(unsigned long context) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *)context; -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ if (!arm_state) -+ goto out; -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s - suspend timer expired - check suspend", __func__); -+ vchiq_check_suspend(state); -+out: -+ return; -+} -+ -+VCHIQ_STATUS_T -+vchiq_use_service_no_resume(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ if (service) { -+ ret = vchiq_use_internal(service->state, service, -+ USE_TYPE_SERVICE_NO_RESUME); -+ unlock_service(service); -+ } -+ return ret; -+} -+ -+VCHIQ_STATUS_T -+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ if (service) { -+ ret = vchiq_use_internal(service->state, service, -+ USE_TYPE_SERVICE); -+ unlock_service(service); -+ } -+ return ret; -+} -+ -+VCHIQ_STATUS_T -+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ if (service) { -+ ret = vchiq_release_internal(service->state, service); -+ unlock_service(service); -+ } -+ return ret; -+} -+ -+void -+vchiq_dump_service_use_state(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int i, j = 0; -+ /* Only dump 64 services */ -+ static const int local_max_services = 64; -+ /* If there's more than 64 services, only dump ones with -+ * non-zero counts */ -+ int only_nonzero = 0; -+ static const char *nz = "<-- preventing suspend"; -+ -+ enum vc_suspend_status vc_suspend_state; -+ enum vc_resume_status vc_resume_state; -+ int peer_count; -+ int vc_use_count; -+ int active_services; -+ struct service_data_struct { -+ int fourcc; -+ int clientid; -+ int use_count; -+ } service_data[local_max_services]; -+ -+ if (!arm_state) -+ return; -+ -+ read_lock_bh(&arm_state->susp_res_lock); -+ vc_suspend_state = arm_state->vc_suspend_state; -+ vc_resume_state = arm_state->vc_resume_state; -+ peer_count = arm_state->peer_use_count; -+ vc_use_count = arm_state->videocore_use_count; -+ active_services = state->unused_service; -+ if (active_services > local_max_services) -+ only_nonzero = 1; -+ -+ for (i = 0; (i < active_services) && (j < local_max_services); i++) { -+ VCHIQ_SERVICE_T *service_ptr = state->services[i]; -+ if (!service_ptr) -+ continue; -+ -+ if (only_nonzero && !service_ptr->service_use_count) -+ continue; -+ -+ if (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE) { -+ service_data[j].fourcc = service_ptr->base.fourcc; -+ service_data[j].clientid = service_ptr->client_id; -+ service_data[j++].use_count = service_ptr-> -+ service_use_count; -+ } -+ } -+ -+ read_unlock_bh(&arm_state->susp_res_lock); -+ -+ vchiq_log_warning(vchiq_susp_log_level, -+ "-- Videcore suspend state: %s --", -+ suspend_state_names[vc_suspend_state + VC_SUSPEND_NUM_OFFSET]); -+ vchiq_log_warning(vchiq_susp_log_level, -+ "-- Videcore resume state: %s --", -+ resume_state_names[vc_resume_state + VC_RESUME_NUM_OFFSET]); -+ -+ if (only_nonzero) -+ vchiq_log_warning(vchiq_susp_log_level, "Too many active " -+ "services (%d). Only dumping up to first %d services " -+ "with non-zero use-count", active_services, -+ local_max_services); -+ -+ for (i = 0; i < j; i++) { -+ vchiq_log_warning(vchiq_susp_log_level, -+ "----- %c%c%c%c:%d service count %d %s", -+ VCHIQ_FOURCC_AS_4CHARS(service_data[i].fourcc), -+ service_data[i].clientid, -+ service_data[i].use_count, -+ service_data[i].use_count ? nz : ""); -+ } -+ vchiq_log_warning(vchiq_susp_log_level, -+ "----- VCHIQ use count count %d", peer_count); -+ vchiq_log_warning(vchiq_susp_log_level, -+ "--- Overall vchiq instance use count %d", vc_use_count); -+ -+ vchiq_dump_platform_use_state(state); -+} -+ -+VCHIQ_STATUS_T -+vchiq_check_service(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_ARM_STATE_T *arm_state; -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ -+ if (!service || !service->state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ arm_state = vchiq_platform_get_arm_state(service->state); -+ -+ read_lock_bh(&arm_state->susp_res_lock); -+ if (service->service_use_count) -+ ret = VCHIQ_SUCCESS; -+ read_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (ret == VCHIQ_ERROR) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s ERROR - %c%c%c%c:%d service count %d, " -+ "state count %d, videocore suspend state %s", __func__, -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->client_id, service->service_use_count, -+ arm_state->videocore_use_count, -+ suspend_state_names[arm_state->vc_suspend_state + -+ VC_SUSPEND_NUM_OFFSET]); -+ vchiq_dump_service_use_state(service->state); -+ } -+out: -+ return ret; -+} -+ -+/* stub functions */ -+void vchiq_on_remote_use_active(VCHIQ_STATE_T *state) -+{ -+ (void)state; -+} -+ -+void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, -+ VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id, -+ get_conn_state_name(oldstate), get_conn_state_name(newstate)); -+ if (state->conn_state == VCHIQ_CONNSTATE_CONNECTED) { -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (!arm_state->first_connect) { -+ char threadname[10]; -+ arm_state->first_connect = 1; -+ write_unlock_bh(&arm_state->susp_res_lock); -+ snprintf(threadname, sizeof(threadname), "VCHIQka-%d", -+ state->id); -+ arm_state->ka_thread = kthread_create( -+ &vchiq_keepalive_thread_func, -+ (void *)state, -+ threadname); -+ if (arm_state->ka_thread == NULL) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "vchiq: FATAL: couldn't create thread %s", -+ threadname); -+ } else { -+ wake_up_process(arm_state->ka_thread); -+ } -+ } else -+ write_unlock_bh(&arm_state->susp_res_lock); -+ } -+} -+ -+static int vchiq_probe(struct platform_device *pdev) -+{ -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ int err; -+ void *ptr_err; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+/* Remove comment when booting without Device Tree is no longer supported -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+*/ -+ fw = rpi_firmware_get(fw_node); -+ if (!fw) -+ return -EPROBE_DEFER; -+ -+ platform_set_drvdata(pdev, fw); -+ -+ /* create debugfs entries */ -+ err = vchiq_debugfs_init(); -+ if (err != 0) -+ goto failed_debugfs_init; -+ -+ err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME); -+ if (err != 0) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to allocate device number"); -+ goto failed_alloc_chrdev; -+ } -+ cdev_init(&vchiq_cdev, &vchiq_fops); -+ vchiq_cdev.owner = THIS_MODULE; -+ err = cdev_add(&vchiq_cdev, vchiq_devid, 1); -+ if (err != 0) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to register device"); -+ goto failed_cdev_add; -+ } -+ -+ /* create sysfs entries */ -+ vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); -+ ptr_err = vchiq_class; -+ if (IS_ERR(ptr_err)) -+ goto failed_class_create; -+ -+ vchiq_dev = device_create(vchiq_class, NULL, -+ vchiq_devid, NULL, "vchiq"); -+ ptr_err = vchiq_dev; -+ if (IS_ERR(ptr_err)) -+ goto failed_device_create; -+ -+ err = vchiq_platform_init(pdev, &g_state); -+ if (err != 0) -+ goto failed_platform_init; -+ -+ vchiq_log_info(vchiq_arm_log_level, -+ "vchiq: initialised - version %d (min %d), device %d.%d", -+ VCHIQ_VERSION, VCHIQ_VERSION_MIN, -+ MAJOR(vchiq_devid), MINOR(vchiq_devid)); -+ -+ return 0; -+ -+failed_platform_init: -+ device_destroy(vchiq_class, vchiq_devid); -+failed_device_create: -+ class_destroy(vchiq_class); -+failed_class_create: -+ cdev_del(&vchiq_cdev); -+ err = PTR_ERR(ptr_err); -+failed_cdev_add: -+ unregister_chrdev_region(vchiq_devid, 1); -+failed_alloc_chrdev: -+ vchiq_debugfs_deinit(); -+failed_debugfs_init: -+ vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq"); -+ return err; -+} -+ -+static int vchiq_remove(struct platform_device *pdev) -+{ -+ device_destroy(vchiq_class, vchiq_devid); -+ class_destroy(vchiq_class); -+ cdev_del(&vchiq_cdev); -+ unregister_chrdev_region(vchiq_devid, 1); -+ -+ return 0; -+} -+ -+static const struct of_device_id vchiq_of_match[] = { -+ { .compatible = "brcm,bcm2835-vchiq", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, vchiq_of_match); -+ -+static struct platform_driver vchiq_driver = { -+ .driver = { -+ .name = "bcm2835_vchiq", -+ .owner = THIS_MODULE, -+ .of_match_table = vchiq_of_match, -+ }, -+ .probe = vchiq_probe, -+ .remove = vchiq_remove, -+}; -+module_platform_driver(vchiq_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -new file mode 100644 -index 0000000000000000000000000000000000000000..9740e1afbc9dc6223f2fea5106916062a3e783ce ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -@@ -0,0 +1,220 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_ARM_H -+#define VCHIQ_ARM_H -+ -+#include -+#include -+#include -+#include -+#include "vchiq_core.h" -+#include "vchiq_debugfs.h" -+ -+ -+enum vc_suspend_status { -+ VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */ -+ VC_SUSPEND_REJECTED = -2, /* Videocore rejected suspend request */ -+ VC_SUSPEND_FAILED = -1, /* Videocore suspend failed */ -+ VC_SUSPEND_IDLE = 0, /* VC active, no suspend actions */ -+ VC_SUSPEND_REQUESTED, /* User has requested suspend */ -+ VC_SUSPEND_IN_PROGRESS, /* Slot handler has recvd suspend request */ -+ VC_SUSPEND_SUSPENDED /* Videocore suspend succeeded */ -+}; -+ -+enum vc_resume_status { -+ VC_RESUME_FAILED = -1, /* Videocore resume failed */ -+ VC_RESUME_IDLE = 0, /* VC suspended, no resume actions */ -+ VC_RESUME_REQUESTED, /* User has requested resume */ -+ VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */ -+ VC_RESUME_RESUMED /* Videocore resumed successfully (active) */ -+}; -+ -+ -+enum USE_TYPE_E { -+ USE_TYPE_SERVICE, -+ USE_TYPE_SERVICE_NO_RESUME, -+ USE_TYPE_VCHIQ -+}; -+ -+ -+ -+typedef struct vchiq_arm_state_struct { -+ /* Keepalive-related data */ -+ struct task_struct *ka_thread; -+ struct completion ka_evt; -+ atomic_t ka_use_count; -+ atomic_t ka_use_ack_count; -+ atomic_t ka_release_count; -+ -+ struct completion vc_suspend_complete; -+ struct completion vc_resume_complete; -+ -+ rwlock_t susp_res_lock; -+ enum vc_suspend_status vc_suspend_state; -+ enum vc_resume_status vc_resume_state; -+ -+ unsigned int wake_address; -+ -+ struct timer_list suspend_timer; -+ int suspend_timer_timeout; -+ int suspend_timer_running; -+ -+ /* Global use count for videocore. -+ ** This is equal to the sum of the use counts for all services. When -+ ** this hits zero the videocore suspend procedure will be initiated. -+ */ -+ int videocore_use_count; -+ -+ /* Use count to track requests from videocore peer. -+ ** This use count is not associated with a service, so needs to be -+ ** tracked separately with the state. -+ */ -+ int peer_use_count; -+ -+ /* Flag to indicate whether resume is blocked. This happens when the -+ ** ARM is suspending -+ */ -+ struct completion resume_blocker; -+ int resume_blocked; -+ struct completion blocked_blocker; -+ int blocked_count; -+ -+ int autosuspend_override; -+ -+ /* Flag to indicate that the first vchiq connect has made it through. -+ ** This means that both sides should be fully ready, and we should -+ ** be able to suspend after this point. -+ */ -+ int first_connect; -+ -+ unsigned long long suspend_start_time; -+ unsigned long long sleep_start_time; -+ unsigned long long resume_start_time; -+ unsigned long long last_wake_time; -+ -+} VCHIQ_ARM_STATE_T; -+ -+extern int vchiq_arm_log_level; -+extern int vchiq_susp_log_level; -+ -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATE_T * -+vchiq_get_state(void); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_vcsuspend(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_force_suspend(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_arm_allow_resume(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_vcresume(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state); -+ -+extern int -+vchiq_check_resume(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_check_suspend(VCHIQ_STATE_T *state); -+ VCHIQ_STATUS_T -+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_STATUS_T -+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_STATUS_T -+vchiq_check_service(VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_platform_suspend(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_platform_use_suspend_timer(void); -+ -+extern void -+vchiq_dump_platform_use_state(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_dump_service_use_state(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_ARM_STATE_T* -+vchiq_platform_get_arm_state(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_videocore_wanted(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ enum USE_TYPE_E use_type); -+extern VCHIQ_STATUS_T -+vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_DEBUGFS_NODE_T * -+vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance); -+ -+extern int -+vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance); -+ -+extern int -+vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance); -+ -+extern int -+vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance); -+ -+extern void -+vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace); -+ -+extern void -+set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_suspend_status new_state); -+ -+extern void -+set_resume_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_resume_status new_state); -+ -+extern void -+start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state); -+ -+ -+#endif /* VCHIQ_ARM_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h -new file mode 100644 -index 0000000000000000000000000000000000000000..df645813bdaeb2cd6296154af434ebc1b0c5939a ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h -@@ -0,0 +1,37 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+const char *vchiq_get_build_hostname(void); -+const char *vchiq_get_build_version(void); -+const char *vchiq_get_build_time(void); -+const char *vchiq_get_build_date(void); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h -new file mode 100644 -index 0000000000000000000000000000000000000000..d2797db702f9fd2e35beb3dd2d5ac9323ccedfc6 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h -@@ -0,0 +1,69 @@ -+/** -+ * Copyright (c) 2010-2014 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_CFG_H -+#define VCHIQ_CFG_H -+ -+#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I') -+/* The version of VCHIQ - change with any non-trivial change */ -+#define VCHIQ_VERSION 8 -+/* The minimum compatible version - update to match VCHIQ_VERSION with any -+** incompatible change */ -+#define VCHIQ_VERSION_MIN 3 -+ -+/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */ -+#define VCHIQ_VERSION_LIB_VERSION 7 -+ -+/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */ -+#define VCHIQ_VERSION_CLOSE_DELIVERED 7 -+ -+/* The version that made it safe to use SYNCHRONOUS mode */ -+#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8 -+ -+#define VCHIQ_MAX_STATES 1 -+#define VCHIQ_MAX_SERVICES 4096 -+#define VCHIQ_MAX_SLOTS 128 -+#define VCHIQ_MAX_SLOTS_PER_SIDE 64 -+ -+#define VCHIQ_NUM_CURRENT_BULKS 32 -+#define VCHIQ_NUM_SERVICE_BULKS 4 -+ -+#ifndef VCHIQ_ENABLE_DEBUG -+#define VCHIQ_ENABLE_DEBUG 1 -+#endif -+ -+#ifndef VCHIQ_ENABLE_STATS -+#define VCHIQ_ENABLE_STATS 1 -+#endif -+ -+#endif /* VCHIQ_CFG_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c -new file mode 100644 -index 0000000000000000000000000000000000000000..5efc62ffb2f5e441cb307d0a575565338b407249 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c -@@ -0,0 +1,120 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "vchiq_connected.h" -+#include "vchiq_core.h" -+#include "vchiq_killable.h" -+#include -+#include -+ -+#define MAX_CALLBACKS 10 -+ -+static int g_connected; -+static int g_num_deferred_callbacks; -+static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; -+static int g_once_init; -+static struct mutex g_connected_mutex; -+ -+/**************************************************************************** -+* -+* Function to initialize our lock. -+* -+***************************************************************************/ -+ -+static void connected_init(void) -+{ -+ if (!g_once_init) { -+ mutex_init(&g_connected_mutex); -+ g_once_init = 1; -+ } -+} -+ -+/**************************************************************************** -+* -+* This function is used to defer initialization until the vchiq stack is -+* initialized. If the stack is already initialized, then the callback will -+* be made immediately, otherwise it will be deferred until -+* vchiq_call_connected_callbacks is called. -+* -+***************************************************************************/ -+ -+void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) -+{ -+ connected_init(); -+ -+ if (mutex_lock_interruptible(&g_connected_mutex) != 0) -+ return; -+ -+ if (g_connected) -+ /* We're already connected. Call the callback immediately. */ -+ -+ callback(); -+ else { -+ if (g_num_deferred_callbacks >= MAX_CALLBACKS) -+ vchiq_log_error(vchiq_core_log_level, -+ "There already %d callback registered - " -+ "please increase MAX_CALLBACKS", -+ g_num_deferred_callbacks); -+ else { -+ g_deferred_callback[g_num_deferred_callbacks] = -+ callback; -+ g_num_deferred_callbacks++; -+ } -+ } -+ mutex_unlock(&g_connected_mutex); -+} -+ -+/**************************************************************************** -+* -+* This function is called by the vchiq stack once it has been connected to -+* the videocore and clients can start to use the stack. -+* -+***************************************************************************/ -+ -+void vchiq_call_connected_callbacks(void) -+{ -+ int i; -+ -+ connected_init(); -+ -+ if (mutex_lock_interruptible(&g_connected_mutex) != 0) -+ return; -+ -+ for (i = 0; i < g_num_deferred_callbacks; i++) -+ g_deferred_callback[i](); -+ -+ g_num_deferred_callbacks = 0; -+ g_connected = 1; -+ mutex_unlock(&g_connected_mutex); -+} -+EXPORT_SYMBOL(vchiq_add_connected_callback); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h -new file mode 100644 -index 0000000000000000000000000000000000000000..863b3e335c1aa4bbe7f8652e0e6c3713ea1aed45 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h -@@ -0,0 +1,50 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_CONNECTED_H -+#define VCHIQ_CONNECTED_H -+ -+/* ---- Include Files ----------------------------------------------------- */ -+ -+/* ---- Constants and Types ---------------------------------------------- */ -+ -+typedef void (*VCHIQ_CONNECTED_CALLBACK_T)(void); -+ -+/* ---- Variable Externs ------------------------------------------------- */ -+ -+/* ---- Function Prototypes ---------------------------------------------- */ -+ -+void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback); -+void vchiq_call_connected_callbacks(void); -+ -+#endif /* VCHIQ_CONNECTED_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -new file mode 100644 -index 0000000000000000000000000000000000000000..71a3bedc55314f3b22dbff40c05dedf03b5e7169 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -0,0 +1,3933 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "vchiq_core.h" -+#include "vchiq_killable.h" -+ -+#define VCHIQ_SLOT_HANDLER_STACK 8192 -+ -+#define HANDLE_STATE_SHIFT 12 -+ -+#define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index)) -+#define SLOT_DATA_FROM_INDEX(state, index) (state->slot_data + (index)) -+#define SLOT_INDEX_FROM_DATA(state, data) \ -+ (((unsigned int)((char *)data - (char *)state->slot_data)) / \ -+ VCHIQ_SLOT_SIZE) -+#define SLOT_INDEX_FROM_INFO(state, info) \ -+ ((unsigned int)(info - state->slot_info)) -+#define SLOT_QUEUE_INDEX_FROM_POS(pos) \ -+ ((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE)) -+ -+#define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1)) -+ -+#define SRVTRACE_LEVEL(srv) \ -+ (((srv) && (srv)->trace) ? VCHIQ_LOG_TRACE : vchiq_core_msg_log_level) -+#define SRVTRACE_ENABLED(srv, lev) \ -+ (((srv) && (srv)->trace) || (vchiq_core_msg_log_level >= (lev))) -+ -+struct vchiq_open_payload { -+ int fourcc; -+ int client_id; -+ short version; -+ short version_min; -+}; -+ -+struct vchiq_openack_payload { -+ short version; -+}; -+ -+enum -+{ -+ QMFLAGS_IS_BLOCKING = (1 << 0), -+ QMFLAGS_NO_MUTEX_LOCK = (1 << 1), -+ QMFLAGS_NO_MUTEX_UNLOCK = (1 << 2) -+}; -+ -+/* we require this for consistency between endpoints */ -+vchiq_static_assert(sizeof(VCHIQ_HEADER_T) == 8); -+vchiq_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T))); -+vchiq_static_assert(IS_POW2(VCHIQ_NUM_CURRENT_BULKS)); -+vchiq_static_assert(IS_POW2(VCHIQ_NUM_SERVICE_BULKS)); -+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SERVICES)); -+vchiq_static_assert(VCHIQ_VERSION >= VCHIQ_VERSION_MIN); -+ -+/* Run time control of log level, based on KERN_XXX level. */ -+int vchiq_core_log_level = VCHIQ_LOG_DEFAULT; -+int vchiq_core_msg_log_level = VCHIQ_LOG_DEFAULT; -+int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT; -+ -+static atomic_t pause_bulks_count = ATOMIC_INIT(0); -+ -+static DEFINE_SPINLOCK(service_spinlock); -+DEFINE_SPINLOCK(bulk_waiter_spinlock); -+DEFINE_SPINLOCK(quota_spinlock); -+ -+VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; -+static unsigned int handle_seq; -+ -+static const char *const srvstate_names[] = { -+ "FREE", -+ "HIDDEN", -+ "LISTENING", -+ "OPENING", -+ "OPEN", -+ "OPENSYNC", -+ "CLOSESENT", -+ "CLOSERECVD", -+ "CLOSEWAIT", -+ "CLOSED" -+}; -+ -+static const char *const reason_names[] = { -+ "SERVICE_OPENED", -+ "SERVICE_CLOSED", -+ "MESSAGE_AVAILABLE", -+ "BULK_TRANSMIT_DONE", -+ "BULK_RECEIVE_DONE", -+ "BULK_TRANSMIT_ABORTED", -+ "BULK_RECEIVE_ABORTED" -+}; -+ -+static const char *const conn_state_names[] = { -+ "DISCONNECTED", -+ "CONNECTING", -+ "CONNECTED", -+ "PAUSING", -+ "PAUSE_SENT", -+ "PAUSED", -+ "RESUMING", -+ "PAUSE_TIMEOUT", -+ "RESUME_TIMEOUT" -+}; -+ -+ -+static void -+release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header); -+ -+static const char *msg_type_str(unsigned int msg_type) -+{ -+ switch (msg_type) { -+ case VCHIQ_MSG_PADDING: return "PADDING"; -+ case VCHIQ_MSG_CONNECT: return "CONNECT"; -+ case VCHIQ_MSG_OPEN: return "OPEN"; -+ case VCHIQ_MSG_OPENACK: return "OPENACK"; -+ case VCHIQ_MSG_CLOSE: return "CLOSE"; -+ case VCHIQ_MSG_DATA: return "DATA"; -+ case VCHIQ_MSG_BULK_RX: return "BULK_RX"; -+ case VCHIQ_MSG_BULK_TX: return "BULK_TX"; -+ case VCHIQ_MSG_BULK_RX_DONE: return "BULK_RX_DONE"; -+ case VCHIQ_MSG_BULK_TX_DONE: return "BULK_TX_DONE"; -+ case VCHIQ_MSG_PAUSE: return "PAUSE"; -+ case VCHIQ_MSG_RESUME: return "RESUME"; -+ case VCHIQ_MSG_REMOTE_USE: return "REMOTE_USE"; -+ case VCHIQ_MSG_REMOTE_RELEASE: return "REMOTE_RELEASE"; -+ case VCHIQ_MSG_REMOTE_USE_ACTIVE: return "REMOTE_USE_ACTIVE"; -+ } -+ return "???"; -+} -+ -+static inline void -+vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate) -+{ -+ vchiq_log_info(vchiq_core_log_level, "%d: srv:%d %s->%s", -+ service->state->id, service->localport, -+ srvstate_names[service->srvstate], -+ srvstate_names[newstate]); -+ service->srvstate = newstate; -+} -+ -+VCHIQ_SERVICE_T * -+find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service; -+ -+ spin_lock(&service_spinlock); -+ service = handle_to_service(handle); -+ if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (service->handle == handle)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid service handle 0x%x", handle); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+find_service_by_port(VCHIQ_STATE_T *state, int localport) -+{ -+ VCHIQ_SERVICE_T *service = NULL; -+ if ((unsigned int)localport <= VCHIQ_PORT_MAX) { -+ spin_lock(&service_spinlock); -+ service = state->services[localport]; -+ if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ } -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid port %d", localport); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+find_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle) { -+ VCHIQ_SERVICE_T *service; -+ -+ spin_lock(&service_spinlock); -+ service = handle_to_service(handle); -+ if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (service->handle == handle) && -+ (service->instance == instance)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid service handle 0x%x", handle); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle) { -+ VCHIQ_SERVICE_T *service; -+ -+ spin_lock(&service_spinlock); -+ service = handle_to_service(handle); -+ if (service && -+ ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_CLOSED)) && -+ (service->handle == handle) && -+ (service->instance == instance)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid service handle 0x%x", handle); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, -+ int *pidx) -+{ -+ VCHIQ_SERVICE_T *service = NULL; -+ int idx = *pidx; -+ -+ spin_lock(&service_spinlock); -+ while (idx < state->unused_service) { -+ VCHIQ_SERVICE_T *srv = state->services[idx++]; -+ if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (srv->instance == instance)) { -+ service = srv; -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ break; -+ } -+ } -+ spin_unlock(&service_spinlock); -+ -+ *pidx = idx; -+ -+ return service; -+} -+ -+void -+lock_service(VCHIQ_SERVICE_T *service) -+{ -+ spin_lock(&service_spinlock); -+ BUG_ON(!service || (service->ref_count == 0)); -+ if (service) -+ service->ref_count++; -+ spin_unlock(&service_spinlock); -+} -+ -+void -+unlock_service(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ spin_lock(&service_spinlock); -+ BUG_ON(!service || (service->ref_count == 0)); -+ if (service && service->ref_count) { -+ service->ref_count--; -+ if (!service->ref_count) { -+ BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); -+ state->services[service->localport] = NULL; -+ } else -+ service = NULL; -+ } -+ spin_unlock(&service_spinlock); -+ -+ if (service && service->userdata_term) -+ service->userdata_term(service->base.userdata); -+ -+ kfree(service); -+} -+ -+int -+vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ int id; -+ -+ id = service ? service->client_id : 0; -+ if (service) -+ unlock_service(service); -+ -+ return id; -+} -+ -+void * -+vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service = handle_to_service(handle); -+ -+ return service ? service->base.userdata : NULL; -+} -+ -+int -+vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service = handle_to_service(handle); -+ -+ return service ? service->base.fourcc : 0; -+} -+ -+static void -+mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ VCHIQ_SERVICE_QUOTA_T *service_quota; -+ -+ service->closing = 1; -+ -+ /* Synchronise with other threads. */ -+ mutex_lock(&state->recycle_mutex); -+ mutex_unlock(&state->recycle_mutex); -+ if (!sh_thread || (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT)) { -+ /* If we're pausing then the slot_mutex is held until resume -+ * by the slot handler. Therefore don't try to acquire this -+ * mutex if we're the slot handler and in the pause sent state. -+ * We don't need to in this case anyway. */ -+ mutex_lock(&state->slot_mutex); -+ mutex_unlock(&state->slot_mutex); -+ } -+ -+ /* Unblock any sending thread. */ -+ service_quota = &state->service_quotas[service->localport]; -+ up(&service_quota->quota_event); -+} -+ -+static void -+mark_service_closing(VCHIQ_SERVICE_T *service) -+{ -+ mark_service_closing_internal(service, 0); -+} -+ -+static inline VCHIQ_STATUS_T -+make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, void *bulk_userdata) -+{ -+ VCHIQ_STATUS_T status; -+ vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %x, %x)", -+ service->state->id, service->localport, reason_names[reason], -+ (unsigned int)header, (unsigned int)bulk_userdata); -+ status = service->base.callback(reason, header, service->handle, -+ bulk_userdata); -+ if (status == VCHIQ_ERROR) { -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: ignoring ERROR from callback to service %x", -+ service->state->id, service->handle); -+ status = VCHIQ_SUCCESS; -+ } -+ return status; -+} -+ -+inline void -+vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate) -+{ -+ VCHIQ_CONNSTATE_T oldstate = state->conn_state; -+ vchiq_log_info(vchiq_core_log_level, "%d: %s->%s", state->id, -+ conn_state_names[oldstate], -+ conn_state_names[newstate]); -+ state->conn_state = newstate; -+ vchiq_platform_conn_state_changed(state, oldstate, newstate); -+} -+ -+static inline void -+remote_event_create(REMOTE_EVENT_T *event) -+{ -+ event->armed = 0; -+ /* Don't clear the 'fired' flag because it may already have been set -+ ** by the other side. */ -+ sema_init(event->event, 0); -+} -+ -+static inline void -+remote_event_destroy(REMOTE_EVENT_T *event) -+{ -+ (void)event; -+} -+ -+static inline int -+remote_event_wait(REMOTE_EVENT_T *event) -+{ -+ if (!event->fired) { -+ event->armed = 1; -+ dsb(); -+ if (!event->fired) { -+ if (down_interruptible(event->event) != 0) { -+ event->armed = 0; -+ return 0; -+ } -+ } -+ event->armed = 0; -+ wmb(); -+ } -+ -+ event->fired = 0; -+ return 1; -+} -+ -+static inline void -+remote_event_signal_local(REMOTE_EVENT_T *event) -+{ -+ event->armed = 0; -+ up(event->event); -+} -+ -+static inline void -+remote_event_poll(REMOTE_EVENT_T *event) -+{ -+ if (event->fired && event->armed) -+ remote_event_signal_local(event); -+} -+ -+void -+remote_event_pollall(VCHIQ_STATE_T *state) -+{ -+ remote_event_poll(&state->local->sync_trigger); -+ remote_event_poll(&state->local->sync_release); -+ remote_event_poll(&state->local->trigger); -+ remote_event_poll(&state->local->recycle); -+} -+ -+/* Round up message sizes so that any space at the end of a slot is always big -+** enough for a header. This relies on header size being a power of two, which -+** has been verified earlier by a static assertion. */ -+ -+static inline unsigned int -+calc_stride(unsigned int size) -+{ -+ /* Allow room for the header */ -+ size += sizeof(VCHIQ_HEADER_T); -+ -+ /* Round up */ -+ return (size + sizeof(VCHIQ_HEADER_T) - 1) & ~(sizeof(VCHIQ_HEADER_T) -+ - 1); -+} -+ -+/* Called by the slot handler thread */ -+static VCHIQ_SERVICE_T * -+get_listening_service(VCHIQ_STATE_T *state, int fourcc) -+{ -+ int i; -+ -+ WARN_ON(fourcc == VCHIQ_FOURCC_INVALID); -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ if (service && -+ (service->public_fourcc == fourcc) && -+ ((service->srvstate == VCHIQ_SRVSTATE_LISTENING) || -+ ((service->srvstate == VCHIQ_SRVSTATE_OPEN) && -+ (service->remoteport == VCHIQ_PORT_FREE)))) { -+ lock_service(service); -+ return service; -+ } -+ } -+ -+ return NULL; -+} -+ -+/* Called by the slot handler thread */ -+static VCHIQ_SERVICE_T * -+get_connected_service(VCHIQ_STATE_T *state, unsigned int port) -+{ -+ int i; -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN) -+ && (service->remoteport == port)) { -+ lock_service(service); -+ return service; -+ } -+ } -+ return NULL; -+} -+ -+inline void -+request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) -+{ -+ uint32_t value; -+ -+ if (service) { -+ do { -+ value = atomic_read(&service->poll_flags); -+ } while (atomic_cmpxchg(&service->poll_flags, value, -+ value | (1 << poll_type)) != value); -+ -+ do { -+ value = atomic_read(&state->poll_services[ -+ service->localport>>5]); -+ } while (atomic_cmpxchg( -+ &state->poll_services[service->localport>>5], -+ value, value | (1 << (service->localport & 0x1f))) -+ != value); -+ } -+ -+ state->poll_needed = 1; -+ wmb(); -+ -+ /* ... and ensure the slot handler runs. */ -+ remote_event_signal_local(&state->local->trigger); -+} -+ -+/* Called from queue_message, by the slot handler and application threads, -+** with slot_mutex held */ -+static VCHIQ_HEADER_T * -+reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking) -+{ -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ int tx_pos = state->local_tx_pos; -+ int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK); -+ -+ if (space > slot_space) { -+ VCHIQ_HEADER_T *header; -+ /* Fill the remaining space with padding */ -+ WARN_ON(state->tx_data == NULL); -+ header = (VCHIQ_HEADER_T *) -+ (state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); -+ header->msgid = VCHIQ_MSGID_PADDING; -+ header->size = slot_space - sizeof(VCHIQ_HEADER_T); -+ -+ tx_pos += slot_space; -+ } -+ -+ /* If necessary, get the next slot. */ -+ if ((tx_pos & VCHIQ_SLOT_MASK) == 0) { -+ int slot_index; -+ -+ /* If there is no free slot... */ -+ -+ if (down_trylock(&state->slot_available_event) != 0) { -+ /* ...wait for one. */ -+ -+ VCHIQ_STATS_INC(state, slot_stalls); -+ -+ /* But first, flush through the last slot. */ -+ state->local_tx_pos = tx_pos; -+ local->tx_pos = tx_pos; -+ remote_event_signal(&state->remote->trigger); -+ -+ if (!is_blocking || -+ (down_interruptible( -+ &state->slot_available_event) != 0)) -+ return NULL; /* No space available */ -+ } -+ -+ BUG_ON(tx_pos == -+ (state->slot_queue_available * VCHIQ_SLOT_SIZE)); -+ -+ slot_index = local->slot_queue[ -+ SLOT_QUEUE_INDEX_FROM_POS(tx_pos) & -+ VCHIQ_SLOT_QUEUE_MASK]; -+ state->tx_data = -+ (char *)SLOT_DATA_FROM_INDEX(state, slot_index); -+ } -+ -+ state->local_tx_pos = tx_pos + space; -+ -+ return (VCHIQ_HEADER_T *)(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); -+} -+ -+/* Called by the recycle thread. */ -+static void -+process_free_queue(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; -+ int slot_queue_available; -+ -+ /* Find slots which have been freed by the other side, and return them -+ ** to the available queue. */ -+ slot_queue_available = state->slot_queue_available; -+ -+ /* Use a memory barrier to ensure that any state that may have been -+ ** modified by another thread is not masked by stale prefetched -+ ** values. */ -+ mb(); -+ -+ while (slot_queue_available != local->slot_queue_recycle) { -+ unsigned int pos; -+ int slot_index = local->slot_queue[slot_queue_available++ & -+ VCHIQ_SLOT_QUEUE_MASK]; -+ char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); -+ int data_found = 0; -+ -+ rmb(); -+ -+ vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", -+ state->id, slot_index, (unsigned int)data, -+ local->slot_queue_recycle, slot_queue_available); -+ -+ /* Initialise the bitmask for services which have used this -+ ** slot */ -+ BITSET_ZERO(service_found); -+ -+ pos = 0; -+ -+ while (pos < VCHIQ_SLOT_SIZE) { -+ VCHIQ_HEADER_T *header = -+ (VCHIQ_HEADER_T *)(data + pos); -+ int msgid = header->msgid; -+ if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) { -+ int port = VCHIQ_MSG_SRCPORT(msgid); -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &state->service_quotas[port]; -+ int count; -+ spin_lock("a_spinlock); -+ count = service_quota->message_use_count; -+ if (count > 0) -+ service_quota->message_use_count = -+ count - 1; -+ spin_unlock("a_spinlock); -+ -+ if (count == service_quota->message_quota) -+ /* Signal the service that it -+ ** has dropped below its quota -+ */ -+ up(&service_quota->quota_event); -+ else if (count == 0) { -+ vchiq_log_error(vchiq_core_log_level, -+ "service %d " -+ "message_use_count=%d " -+ "(header %x, msgid %x, " -+ "header->msgid %x, " -+ "header->size %x)", -+ port, -+ service_quota-> -+ message_use_count, -+ (unsigned int)header, msgid, -+ header->msgid, -+ header->size); -+ WARN(1, "invalid message use count\n"); -+ } -+ if (!BITSET_IS_SET(service_found, port)) { -+ /* Set the found bit for this service */ -+ BITSET_SET(service_found, port); -+ -+ spin_lock("a_spinlock); -+ count = service_quota->slot_use_count; -+ if (count > 0) -+ service_quota->slot_use_count = -+ count - 1; -+ spin_unlock("a_spinlock); -+ -+ if (count > 0) { -+ /* Signal the service in case -+ ** it has dropped below its -+ ** quota */ -+ up(&service_quota->quota_event); -+ vchiq_log_trace( -+ vchiq_core_log_level, -+ "%d: pfq:%d %x@%x - " -+ "slot_use->%d", -+ state->id, port, -+ header->size, -+ (unsigned int)header, -+ count - 1); -+ } else { -+ vchiq_log_error( -+ vchiq_core_log_level, -+ "service %d " -+ "slot_use_count" -+ "=%d (header %x" -+ ", msgid %x, " -+ "header->msgid" -+ " %x, header->" -+ "size %x)", -+ port, count, -+ (unsigned int)header, -+ msgid, -+ header->msgid, -+ header->size); -+ WARN(1, "bad slot use count\n"); -+ } -+ } -+ -+ data_found = 1; -+ } -+ -+ pos += calc_stride(header->size); -+ if (pos > VCHIQ_SLOT_SIZE) { -+ vchiq_log_error(vchiq_core_log_level, -+ "pfq - pos %x: header %x, msgid %x, " -+ "header->msgid %x, header->size %x", -+ pos, (unsigned int)header, msgid, -+ header->msgid, header->size); -+ WARN(1, "invalid slot position\n"); -+ } -+ } -+ -+ if (data_found) { -+ int count; -+ spin_lock("a_spinlock); -+ count = state->data_use_count; -+ if (count > 0) -+ state->data_use_count = -+ count - 1; -+ spin_unlock("a_spinlock); -+ if (count == state->data_quota) -+ up(&state->data_quota_event); -+ } -+ -+ mb(); -+ -+ state->slot_queue_available = slot_queue_available; -+ up(&state->slot_available_event); -+ } -+} -+ -+/* Called by the slot handler and application threads */ -+static VCHIQ_STATUS_T -+queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ int msgid, const VCHIQ_ELEMENT_T *elements, -+ int count, int size, int flags) -+{ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_SERVICE_QUOTA_T *service_quota = NULL; -+ VCHIQ_HEADER_T *header; -+ int type = VCHIQ_MSG_TYPE(msgid); -+ -+ unsigned int stride; -+ -+ local = state->local; -+ -+ stride = calc_stride(size); -+ -+ WARN_ON(!(stride <= VCHIQ_SLOT_SIZE)); -+ -+ if (!(flags & QMFLAGS_NO_MUTEX_LOCK) && -+ (mutex_lock_interruptible(&state->slot_mutex) != 0)) -+ return VCHIQ_RETRY; -+ -+ if (type == VCHIQ_MSG_DATA) { -+ int tx_end_index; -+ -+ BUG_ON(!service); -+ BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | -+ QMFLAGS_NO_MUTEX_UNLOCK)) != 0); -+ -+ if (service->closing) { -+ /* The service has been closed */ -+ mutex_unlock(&state->slot_mutex); -+ return VCHIQ_ERROR; -+ } -+ -+ service_quota = &state->service_quotas[service->localport]; -+ -+ spin_lock("a_spinlock); -+ -+ /* Ensure this service doesn't use more than its quota of -+ ** messages or slots */ -+ tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( -+ state->local_tx_pos + stride - 1); -+ -+ /* Ensure data messages don't use more than their quota of -+ ** slots */ -+ while ((tx_end_index != state->previous_data_index) && -+ (state->data_use_count == state->data_quota)) { -+ VCHIQ_STATS_INC(state, data_stalls); -+ spin_unlock("a_spinlock); -+ mutex_unlock(&state->slot_mutex); -+ -+ if (down_interruptible(&state->data_quota_event) -+ != 0) -+ return VCHIQ_RETRY; -+ -+ mutex_lock(&state->slot_mutex); -+ spin_lock("a_spinlock); -+ tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( -+ state->local_tx_pos + stride - 1); -+ if ((tx_end_index == state->previous_data_index) || -+ (state->data_use_count < state->data_quota)) { -+ /* Pass the signal on to other waiters */ -+ up(&state->data_quota_event); -+ break; -+ } -+ } -+ -+ while ((service_quota->message_use_count == -+ service_quota->message_quota) || -+ ((tx_end_index != service_quota->previous_tx_index) && -+ (service_quota->slot_use_count == -+ service_quota->slot_quota))) { -+ spin_unlock("a_spinlock); -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: qm:%d %s,%x - quota stall " -+ "(msg %d, slot %d)", -+ state->id, service->localport, -+ msg_type_str(type), size, -+ service_quota->message_use_count, -+ service_quota->slot_use_count); -+ VCHIQ_SERVICE_STATS_INC(service, quota_stalls); -+ mutex_unlock(&state->slot_mutex); -+ if (down_interruptible(&service_quota->quota_event) -+ != 0) -+ return VCHIQ_RETRY; -+ if (service->closing) -+ return VCHIQ_ERROR; -+ if (mutex_lock_interruptible(&state->slot_mutex) != 0) -+ return VCHIQ_RETRY; -+ if (service->srvstate != VCHIQ_SRVSTATE_OPEN) { -+ /* The service has been closed */ -+ mutex_unlock(&state->slot_mutex); -+ return VCHIQ_ERROR; -+ } -+ spin_lock("a_spinlock); -+ tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( -+ state->local_tx_pos + stride - 1); -+ } -+ -+ spin_unlock("a_spinlock); -+ } -+ -+ header = reserve_space(state, stride, flags & QMFLAGS_IS_BLOCKING); -+ -+ if (!header) { -+ if (service) -+ VCHIQ_SERVICE_STATS_INC(service, slot_stalls); -+ /* In the event of a failure, return the mutex to the -+ state it was in */ -+ if (!(flags & QMFLAGS_NO_MUTEX_LOCK)) -+ mutex_unlock(&state->slot_mutex); -+ return VCHIQ_RETRY; -+ } -+ -+ if (type == VCHIQ_MSG_DATA) { -+ int i, pos; -+ int tx_end_index; -+ int slot_use_count; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: qm %s@%x,%x (%d->%d)", -+ state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ -+ BUG_ON(!service); -+ BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | -+ QMFLAGS_NO_MUTEX_UNLOCK)) != 0); -+ -+ for (i = 0, pos = 0; i < (unsigned int)count; -+ pos += elements[i++].size) -+ if (elements[i].size) { -+ if (vchiq_copy_from_user -+ (header->data + pos, elements[i].data, -+ (size_t) elements[i].size) != -+ VCHIQ_SUCCESS) { -+ mutex_unlock(&state->slot_mutex); -+ VCHIQ_SERVICE_STATS_INC(service, -+ error_count); -+ return VCHIQ_ERROR; -+ } -+ } -+ -+ if (SRVTRACE_ENABLED(service, -+ VCHIQ_LOG_INFO)) -+ vchiq_log_dump_mem("Sent", 0, -+ header->data, -+ min(16, pos)); -+ -+ spin_lock("a_spinlock); -+ service_quota->message_use_count++; -+ -+ tx_end_index = -+ SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos - 1); -+ -+ /* If this transmission can't fit in the last slot used by any -+ ** service, the data_use_count must be increased. */ -+ if (tx_end_index != state->previous_data_index) { -+ state->previous_data_index = tx_end_index; -+ state->data_use_count++; -+ } -+ -+ /* If this isn't the same slot last used by this service, -+ ** the service's slot_use_count must be increased. */ -+ if (tx_end_index != service_quota->previous_tx_index) { -+ service_quota->previous_tx_index = tx_end_index; -+ slot_use_count = ++service_quota->slot_use_count; -+ } else { -+ slot_use_count = 0; -+ } -+ -+ spin_unlock("a_spinlock); -+ -+ if (slot_use_count) -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: qm:%d %s,%x - slot_use->%d (hdr %p)", -+ state->id, service->localport, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), size, -+ slot_use_count, header); -+ -+ VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); -+ } else { -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: qm %s@%x,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ if (size != 0) { -+ WARN_ON(!((count == 1) && (size == elements[0].size))); -+ memcpy(header->data, elements[0].data, -+ elements[0].size); -+ } -+ VCHIQ_STATS_INC(state, ctrl_tx_count); -+ } -+ -+ header->msgid = msgid; -+ header->size = size; -+ -+ { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ VCHIQ_MSG_TYPE(msgid), -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid), -+ size); -+ } -+ -+ /* Make sure the new header is visible to the peer. */ -+ wmb(); -+ -+ /* Make the new tx_pos visible to the peer. */ -+ local->tx_pos = state->local_tx_pos; -+ wmb(); -+ -+ if (service && (type == VCHIQ_MSG_CLOSE)) -+ vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT); -+ -+ if (!(flags & QMFLAGS_NO_MUTEX_UNLOCK)) -+ mutex_unlock(&state->slot_mutex); -+ -+ remote_event_signal(&state->remote->trigger); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+/* Called by the slot handler and application threads */ -+static VCHIQ_STATUS_T -+queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ int msgid, const VCHIQ_ELEMENT_T *elements, -+ int count, int size, int is_blocking) -+{ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_HEADER_T *header; -+ -+ local = state->local; -+ -+ if ((VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME) && -+ (mutex_lock_interruptible(&state->sync_mutex) != 0)) -+ return VCHIQ_RETRY; -+ -+ remote_event_wait(&local->sync_release); -+ -+ rmb(); -+ -+ header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, -+ local->slot_sync); -+ -+ { -+ int oldmsgid = header->msgid; -+ if (oldmsgid != VCHIQ_MSGID_PADDING) -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: qms - msgid %x, not PADDING", -+ state->id, oldmsgid); -+ } -+ -+ if (service) { -+ int i, pos; -+ -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: qms %s@%x,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ -+ for (i = 0, pos = 0; i < (unsigned int)count; -+ pos += elements[i++].size) -+ if (elements[i].size) { -+ if (vchiq_copy_from_user -+ (header->data + pos, elements[i].data, -+ (size_t) elements[i].size) != -+ VCHIQ_SUCCESS) { -+ mutex_unlock(&state->sync_mutex); -+ VCHIQ_SERVICE_STATS_INC(service, -+ error_count); -+ return VCHIQ_ERROR; -+ } -+ } -+ -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) -+ vchiq_log_dump_mem("Sent Sync", -+ 0, header->data, -+ min(16, pos)); -+ -+ VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); -+ } else { -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: qms %s@%x,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ if (size != 0) { -+ WARN_ON(!((count == 1) && (size == elements[0].size))); -+ memcpy(header->data, elements[0].data, -+ elements[0].size); -+ } -+ VCHIQ_STATS_INC(state, ctrl_tx_count); -+ } -+ -+ header->size = size; -+ header->msgid = msgid; -+ -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ -+ vchiq_log_trace(vchiq_sync_log_level, -+ "Sent Sync Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ VCHIQ_MSG_TYPE(msgid), -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid), -+ size); -+ } -+ -+ /* Make sure the new header is visible to the peer. */ -+ wmb(); -+ -+ remote_event_signal(&state->remote->sync_trigger); -+ -+ if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE) -+ mutex_unlock(&state->sync_mutex); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+static inline void -+claim_slot(VCHIQ_SLOT_INFO_T *slot) -+{ -+ slot->use_count++; -+} -+ -+static void -+release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info, -+ VCHIQ_HEADER_T *header, VCHIQ_SERVICE_T *service) -+{ -+ int release_count; -+ -+ mutex_lock(&state->recycle_mutex); -+ -+ if (header) { -+ int msgid = header->msgid; -+ if (((msgid & VCHIQ_MSGID_CLAIMED) == 0) || -+ (service && service->closing)) { -+ mutex_unlock(&state->recycle_mutex); -+ return; -+ } -+ -+ /* Rewrite the message header to prevent a double -+ ** release */ -+ header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED; -+ } -+ -+ release_count = slot_info->release_count; -+ slot_info->release_count = ++release_count; -+ -+ if (release_count == slot_info->use_count) { -+ int slot_queue_recycle; -+ /* Add to the freed queue */ -+ -+ /* A read barrier is necessary here to prevent speculative -+ ** fetches of remote->slot_queue_recycle from overtaking the -+ ** mutex. */ -+ rmb(); -+ -+ slot_queue_recycle = state->remote->slot_queue_recycle; -+ state->remote->slot_queue[slot_queue_recycle & -+ VCHIQ_SLOT_QUEUE_MASK] = -+ SLOT_INDEX_FROM_INFO(state, slot_info); -+ state->remote->slot_queue_recycle = slot_queue_recycle + 1; -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: release_slot %d - recycle->%x", -+ state->id, SLOT_INDEX_FROM_INFO(state, slot_info), -+ state->remote->slot_queue_recycle); -+ -+ /* A write barrier is necessary, but remote_event_signal -+ ** contains one. */ -+ remote_event_signal(&state->remote->recycle); -+ } -+ -+ mutex_unlock(&state->recycle_mutex); -+} -+ -+/* Called by the slot handler - don't hold the bulk mutex */ -+static VCHIQ_STATUS_T -+notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, -+ int retry_poll) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: nb:%d %cx - p=%x rn=%x r=%x", -+ service->state->id, service->localport, -+ (queue == &service->bulk_tx) ? 't' : 'r', -+ queue->process, queue->remote_notify, queue->remove); -+ -+ if (service->state->is_master) { -+ while (queue->remote_notify != queue->process) { -+ VCHIQ_BULK_T *bulk = -+ &queue->bulks[BULK_INDEX(queue->remote_notify)]; -+ int msgtype = (bulk->dir == VCHIQ_BULK_TRANSMIT) ? -+ VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE; -+ int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport, -+ service->remoteport); -+ VCHIQ_ELEMENT_T element = { &bulk->actual, 4 }; -+ /* Only reply to non-dummy bulk requests */ -+ if (bulk->remote_data) { -+ status = queue_message(service->state, NULL, -+ msgid, &element, 1, 4, 0); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ queue->remote_notify++; -+ } -+ } else { -+ queue->remote_notify = queue->process; -+ } -+ -+ if (status == VCHIQ_SUCCESS) { -+ while (queue->remove != queue->remote_notify) { -+ VCHIQ_BULK_T *bulk = -+ &queue->bulks[BULK_INDEX(queue->remove)]; -+ -+ /* Only generate callbacks for non-dummy bulk -+ ** requests, and non-terminated services */ -+ if (bulk->data && service->instance) { -+ if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { -+ if (bulk->dir == VCHIQ_BULK_TRANSMIT) { -+ VCHIQ_SERVICE_STATS_INC(service, -+ bulk_tx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, -+ bulk_tx_bytes, -+ bulk->actual); -+ } else { -+ VCHIQ_SERVICE_STATS_INC(service, -+ bulk_rx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, -+ bulk_rx_bytes, -+ bulk->actual); -+ } -+ } else { -+ VCHIQ_SERVICE_STATS_INC(service, -+ bulk_aborted_count); -+ } -+ if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { -+ struct bulk_waiter *waiter; -+ spin_lock(&bulk_waiter_spinlock); -+ waiter = bulk->userdata; -+ if (waiter) { -+ waiter->actual = bulk->actual; -+ up(&waiter->event); -+ } -+ spin_unlock(&bulk_waiter_spinlock); -+ } else if (bulk->mode == -+ VCHIQ_BULK_MODE_CALLBACK) { -+ VCHIQ_REASON_T reason = (bulk->dir == -+ VCHIQ_BULK_TRANSMIT) ? -+ ((bulk->actual == -+ VCHIQ_BULK_ACTUAL_ABORTED) ? -+ VCHIQ_BULK_TRANSMIT_ABORTED : -+ VCHIQ_BULK_TRANSMIT_DONE) : -+ ((bulk->actual == -+ VCHIQ_BULK_ACTUAL_ABORTED) ? -+ VCHIQ_BULK_RECEIVE_ABORTED : -+ VCHIQ_BULK_RECEIVE_DONE); -+ status = make_service_callback(service, -+ reason, NULL, bulk->userdata); -+ if (status == VCHIQ_RETRY) -+ break; -+ } -+ } -+ -+ queue->remove++; -+ up(&service->bulk_remove_event); -+ } -+ if (!retry_poll) -+ status = VCHIQ_SUCCESS; -+ } -+ -+ if (status == VCHIQ_RETRY) -+ request_poll(service->state, service, -+ (queue == &service->bulk_tx) ? -+ VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); -+ -+ return status; -+} -+ -+/* Called by the slot handler thread */ -+static void -+poll_services(VCHIQ_STATE_T *state) -+{ -+ int group, i; -+ -+ for (group = 0; group < BITSET_SIZE(state->unused_service); group++) { -+ uint32_t flags; -+ flags = atomic_xchg(&state->poll_services[group], 0); -+ for (i = 0; flags; i++) { -+ if (flags & (1 << i)) { -+ VCHIQ_SERVICE_T *service = -+ find_service_by_port(state, -+ (group<<5) + i); -+ uint32_t service_flags; -+ flags &= ~(1 << i); -+ if (!service) -+ continue; -+ service_flags = -+ atomic_xchg(&service->poll_flags, 0); -+ if (service_flags & -+ (1 << VCHIQ_POLL_REMOVE)) { -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: ps - remove %d<->%d", -+ state->id, service->localport, -+ service->remoteport); -+ -+ /* Make it look like a client, because -+ it must be removed and not left in -+ the LISTENING state. */ -+ service->public_fourcc = -+ VCHIQ_FOURCC_INVALID; -+ -+ if (vchiq_close_service_internal( -+ service, 0/*!close_recvd*/) != -+ VCHIQ_SUCCESS) -+ request_poll(state, service, -+ VCHIQ_POLL_REMOVE); -+ } else if (service_flags & -+ (1 << VCHIQ_POLL_TERMINATE)) { -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: ps - terminate %d<->%d", -+ state->id, service->localport, -+ service->remoteport); -+ if (vchiq_close_service_internal( -+ service, 0/*!close_recvd*/) != -+ VCHIQ_SUCCESS) -+ request_poll(state, service, -+ VCHIQ_POLL_TERMINATE); -+ } -+ if (service_flags & (1 << VCHIQ_POLL_TXNOTIFY)) -+ notify_bulks(service, -+ &service->bulk_tx, -+ 1/*retry_poll*/); -+ if (service_flags & (1 << VCHIQ_POLL_RXNOTIFY)) -+ notify_bulks(service, -+ &service->bulk_rx, -+ 1/*retry_poll*/); -+ unlock_service(service); -+ } -+ } -+ } -+} -+ -+/* Called by the slot handler or application threads, holding the bulk mutex. */ -+static int -+resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ int resolved = 0; -+ int rc; -+ -+ while ((queue->process != queue->local_insert) && -+ (queue->process != queue->remote_insert)) { -+ VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: rb:%d %cx - li=%x ri=%x p=%x", -+ state->id, service->localport, -+ (queue == &service->bulk_tx) ? 't' : 'r', -+ queue->local_insert, queue->remote_insert, -+ queue->process); -+ -+ WARN_ON(!((int)(queue->local_insert - queue->process) > 0)); -+ WARN_ON(!((int)(queue->remote_insert - queue->process) > 0)); -+ -+ rc = mutex_lock_interruptible(&state->bulk_transfer_mutex); -+ if (rc != 0) -+ break; -+ -+ vchiq_transfer_bulk(bulk); -+ mutex_unlock(&state->bulk_transfer_mutex); -+ -+ if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { -+ const char *header = (queue == &service->bulk_tx) ? -+ "Send Bulk to" : "Recv Bulk from"; -+ if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "%s %c%c%c%c d:%d len:%d %x<->%x", -+ header, -+ VCHIQ_FOURCC_AS_4CHARS( -+ service->base.fourcc), -+ service->remoteport, -+ bulk->size, -+ (unsigned int)bulk->data, -+ (unsigned int)bulk->remote_data); -+ else -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "%s %c%c%c%c d:%d ABORTED - tx len:%d," -+ " rx len:%d %x<->%x", -+ header, -+ VCHIQ_FOURCC_AS_4CHARS( -+ service->base.fourcc), -+ service->remoteport, -+ bulk->size, -+ bulk->remote_size, -+ (unsigned int)bulk->data, -+ (unsigned int)bulk->remote_data); -+ } -+ -+ vchiq_complete_bulk(bulk); -+ queue->process++; -+ resolved++; -+ } -+ return resolved; -+} -+ -+/* Called with the bulk_mutex held */ -+static void -+abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) -+{ -+ int is_tx = (queue == &service->bulk_tx); -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: aob:%d %cx - li=%x ri=%x p=%x", -+ service->state->id, service->localport, is_tx ? 't' : 'r', -+ queue->local_insert, queue->remote_insert, queue->process); -+ -+ WARN_ON(!((int)(queue->local_insert - queue->process) >= 0)); -+ WARN_ON(!((int)(queue->remote_insert - queue->process) >= 0)); -+ -+ while ((queue->process != queue->local_insert) || -+ (queue->process != queue->remote_insert)) { -+ VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; -+ -+ if (queue->process == queue->remote_insert) { -+ /* fabricate a matching dummy bulk */ -+ bulk->remote_data = NULL; -+ bulk->remote_size = 0; -+ queue->remote_insert++; -+ } -+ -+ if (queue->process != queue->local_insert) { -+ vchiq_complete_bulk(bulk); -+ -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "%s %c%c%c%c d:%d ABORTED - tx len:%d, " -+ "rx len:%d", -+ is_tx ? "Send Bulk to" : "Recv Bulk from", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->remoteport, -+ bulk->size, -+ bulk->remote_size); -+ } else { -+ /* fabricate a matching dummy bulk */ -+ bulk->data = NULL; -+ bulk->size = 0; -+ bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; -+ bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT : -+ VCHIQ_BULK_RECEIVE; -+ queue->local_insert++; -+ } -+ -+ queue->process++; -+ } -+} -+ -+/* Called from the slot handler thread */ -+static void -+pause_bulks(VCHIQ_STATE_T *state) -+{ -+ if (unlikely(atomic_inc_return(&pause_bulks_count) != 1)) { -+ WARN_ON_ONCE(1); -+ atomic_set(&pause_bulks_count, 1); -+ return; -+ } -+ -+ /* Block bulk transfers from all services */ -+ mutex_lock(&state->bulk_transfer_mutex); -+} -+ -+/* Called from the slot handler thread */ -+static void -+resume_bulks(VCHIQ_STATE_T *state) -+{ -+ int i; -+ if (unlikely(atomic_dec_return(&pause_bulks_count) != 0)) { -+ WARN_ON_ONCE(1); -+ atomic_set(&pause_bulks_count, 0); -+ return; -+ } -+ -+ /* Allow bulk transfers from all services */ -+ mutex_unlock(&state->bulk_transfer_mutex); -+ -+ if (state->deferred_bulks == 0) -+ return; -+ -+ /* Deal with any bulks which had to be deferred due to being in -+ * paused state. Don't try to match up to number of deferred bulks -+ * in case we've had something come and close the service in the -+ * interim - just process all bulk queues for all services */ -+ vchiq_log_info(vchiq_core_log_level, "%s: processing %d deferred bulks", -+ __func__, state->deferred_bulks); -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ int resolved_rx = 0; -+ int resolved_tx = 0; -+ if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN)) -+ continue; -+ -+ mutex_lock(&service->bulk_mutex); -+ resolved_rx = resolve_bulks(service, &service->bulk_rx); -+ resolved_tx = resolve_bulks(service, &service->bulk_tx); -+ mutex_unlock(&service->bulk_mutex); -+ if (resolved_rx) -+ notify_bulks(service, &service->bulk_rx, 1); -+ if (resolved_tx) -+ notify_bulks(service, &service->bulk_tx, 1); -+ } -+ state->deferred_bulks = 0; -+} -+ -+static int -+parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) -+{ -+ VCHIQ_SERVICE_T *service = NULL; -+ int msgid, size; -+ int type; -+ unsigned int localport, remoteport; -+ -+ msgid = header->msgid; -+ size = header->size; -+ type = VCHIQ_MSG_TYPE(msgid); -+ localport = VCHIQ_MSG_DSTPORT(msgid); -+ remoteport = VCHIQ_MSG_SRCPORT(msgid); -+ if (size >= sizeof(struct vchiq_open_payload)) { -+ const struct vchiq_open_payload *payload = -+ (struct vchiq_open_payload *)header->data; -+ unsigned int fourcc; -+ -+ fourcc = payload->fourcc; -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs OPEN@%x (%d->'%c%c%c%c')", -+ state->id, (unsigned int)header, -+ localport, -+ VCHIQ_FOURCC_AS_4CHARS(fourcc)); -+ -+ service = get_listening_service(state, fourcc); -+ -+ if (service) { -+ /* A matching service exists */ -+ short version = payload->version; -+ short version_min = payload->version_min; -+ if ((service->version < version_min) || -+ (version < service->version_min)) { -+ /* Version mismatch */ -+ vchiq_loud_error_header(); -+ vchiq_loud_error("%d: service %d (%c%c%c%c) " -+ "version mismatch - local (%d, min %d)" -+ " vs. remote (%d, min %d)", -+ state->id, service->localport, -+ VCHIQ_FOURCC_AS_4CHARS(fourcc), -+ service->version, service->version_min, -+ version, version_min); -+ vchiq_loud_error_footer(); -+ unlock_service(service); -+ service = NULL; -+ goto fail_open; -+ } -+ service->peer_version = version; -+ -+ if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { -+ struct vchiq_openack_payload ack_payload = { -+ service->version -+ }; -+ VCHIQ_ELEMENT_T body = { -+ &ack_payload, -+ sizeof(ack_payload) -+ }; -+ -+ if (state->version_common < -+ VCHIQ_VERSION_SYNCHRONOUS_MODE) -+ service->sync = 0; -+ -+ /* Acknowledge the OPEN */ -+ if (service->sync && -+ (state->version_common >= -+ VCHIQ_VERSION_SYNCHRONOUS_MODE)) { -+ if (queue_message_sync(state, NULL, -+ VCHIQ_MAKE_MSG( -+ VCHIQ_MSG_OPENACK, -+ service->localport, -+ remoteport), -+ &body, 1, sizeof(ack_payload), -+ 0) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ } else { -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG( -+ VCHIQ_MSG_OPENACK, -+ service->localport, -+ remoteport), -+ &body, 1, sizeof(ack_payload), -+ 0) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ } -+ -+ /* The service is now open */ -+ vchiq_set_service_state(service, -+ service->sync ? VCHIQ_SRVSTATE_OPENSYNC -+ : VCHIQ_SRVSTATE_OPEN); -+ } -+ -+ service->remoteport = remoteport; -+ service->client_id = ((int *)header->data)[1]; -+ if (make_service_callback(service, VCHIQ_SERVICE_OPENED, -+ NULL, NULL) == VCHIQ_RETRY) { -+ /* Bail out if not ready */ -+ service->remoteport = VCHIQ_PORT_FREE; -+ goto bail_not_ready; -+ } -+ -+ /* Success - the message has been dealt with */ -+ unlock_service(service); -+ return 1; -+ } -+ } -+ -+fail_open: -+ /* No available service, or an invalid request - send a CLOSE */ -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, VCHIQ_MSG_SRCPORT(msgid)), -+ NULL, 0, 0, 0) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ -+ return 1; -+ -+bail_not_ready: -+ if (service) -+ unlock_service(service); -+ -+ return 0; -+} -+ -+/* Called by the slot handler thread */ -+static void -+parse_rx_slots(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_SHARED_STATE_T *remote = state->remote; -+ VCHIQ_SERVICE_T *service = NULL; -+ int tx_pos; -+ DEBUG_INITIALISE(state->local) -+ -+ tx_pos = remote->tx_pos; -+ -+ while (state->rx_pos != tx_pos) { -+ VCHIQ_HEADER_T *header; -+ int msgid, size; -+ int type; -+ unsigned int localport, remoteport; -+ -+ DEBUG_TRACE(PARSE_LINE); -+ if (!state->rx_data) { -+ int rx_index; -+ WARN_ON(!((state->rx_pos & VCHIQ_SLOT_MASK) == 0)); -+ rx_index = remote->slot_queue[ -+ SLOT_QUEUE_INDEX_FROM_POS(state->rx_pos) & -+ VCHIQ_SLOT_QUEUE_MASK]; -+ state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state, -+ rx_index); -+ state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index); -+ -+ /* Initialise use_count to one, and increment -+ ** release_count at the end of the slot to avoid -+ ** releasing the slot prematurely. */ -+ state->rx_info->use_count = 1; -+ state->rx_info->release_count = 0; -+ } -+ -+ header = (VCHIQ_HEADER_T *)(state->rx_data + -+ (state->rx_pos & VCHIQ_SLOT_MASK)); -+ DEBUG_VALUE(PARSE_HEADER, (int)header); -+ msgid = header->msgid; -+ DEBUG_VALUE(PARSE_MSGID, msgid); -+ size = header->size; -+ type = VCHIQ_MSG_TYPE(msgid); -+ localport = VCHIQ_MSG_DSTPORT(msgid); -+ remoteport = VCHIQ_MSG_SRCPORT(msgid); -+ -+ if (type != VCHIQ_MSG_DATA) -+ VCHIQ_STATS_INC(state, ctrl_rx_count); -+ -+ switch (type) { -+ case VCHIQ_MSG_OPENACK: -+ case VCHIQ_MSG_CLOSE: -+ case VCHIQ_MSG_DATA: -+ case VCHIQ_MSG_BULK_RX: -+ case VCHIQ_MSG_BULK_TX: -+ case VCHIQ_MSG_BULK_RX_DONE: -+ case VCHIQ_MSG_BULK_TX_DONE: -+ service = find_service_by_port(state, localport); -+ if ((!service || -+ ((service->remoteport != remoteport) && -+ (service->remoteport != VCHIQ_PORT_FREE))) && -+ (localport == 0) && -+ (type == VCHIQ_MSG_CLOSE)) { -+ /* This could be a CLOSE from a client which -+ hadn't yet received the OPENACK - look for -+ the connected service */ -+ if (service) -+ unlock_service(service); -+ service = get_connected_service(state, -+ remoteport); -+ if (service) -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) - " -+ "found connected service %d", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ service->localport); -+ } -+ -+ if (!service) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) - " -+ "invalid/closed service %d", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, localport); -+ goto skip_message; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d " -+ "len:%d", -+ msg_type_str(type), type, -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ remoteport, localport, size); -+ if (size > 0) -+ vchiq_log_dump_mem("Rcvd", 0, header->data, -+ min(16, size)); -+ } -+ -+ if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) -+ > VCHIQ_SLOT_SIZE) { -+ vchiq_log_error(vchiq_core_log_level, -+ "header %x (msgid %x) - size %x too big for " -+ "slot", -+ (unsigned int)header, (unsigned int)msgid, -+ (unsigned int)size); -+ WARN(1, "oversized for slot\n"); -+ } -+ -+ switch (type) { -+ case VCHIQ_MSG_OPEN: -+ WARN_ON(!(VCHIQ_MSG_DSTPORT(msgid) == 0)); -+ if (!parse_open(state, header)) -+ goto bail_not_ready; -+ break; -+ case VCHIQ_MSG_OPENACK: -+ if (size >= sizeof(struct vchiq_openack_payload)) { -+ const struct vchiq_openack_payload *payload = -+ (struct vchiq_openack_payload *) -+ header->data; -+ service->peer_version = payload->version; -+ } -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs OPENACK@%x,%x (%d->%d) v:%d", -+ state->id, (unsigned int)header, size, -+ remoteport, localport, service->peer_version); -+ if (service->srvstate == -+ VCHIQ_SRVSTATE_OPENING) { -+ service->remoteport = remoteport; -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_OPEN); -+ up(&service->remove_event); -+ } else -+ vchiq_log_error(vchiq_core_log_level, -+ "OPENACK received in state %s", -+ srvstate_names[service->srvstate]); -+ break; -+ case VCHIQ_MSG_CLOSE: -+ WARN_ON(size != 0); /* There should be no data */ -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs CLOSE@%x (%d->%d)", -+ state->id, (unsigned int)header, -+ remoteport, localport); -+ -+ mark_service_closing_internal(service, 1); -+ -+ if (vchiq_close_service_internal(service, -+ 1/*close_recvd*/) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "Close Service %c%c%c%c s:%u d:%d", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->localport, -+ service->remoteport); -+ break; -+ case VCHIQ_MSG_DATA: -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs DATA@%x,%x (%d->%d)", -+ state->id, (unsigned int)header, size, -+ remoteport, localport); -+ -+ if ((service->remoteport == remoteport) -+ && (service->srvstate == -+ VCHIQ_SRVSTATE_OPEN)) { -+ header->msgid = msgid | VCHIQ_MSGID_CLAIMED; -+ claim_slot(state->rx_info); -+ DEBUG_TRACE(PARSE_LINE); -+ if (make_service_callback(service, -+ VCHIQ_MESSAGE_AVAILABLE, header, -+ NULL) == VCHIQ_RETRY) { -+ DEBUG_TRACE(PARSE_LINE); -+ goto bail_not_ready; -+ } -+ VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes, -+ size); -+ } else { -+ VCHIQ_STATS_INC(state, error_count); -+ } -+ break; -+ case VCHIQ_MSG_CONNECT: -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs CONNECT@%x", -+ state->id, (unsigned int)header); -+ state->version_common = ((VCHIQ_SLOT_ZERO_T *) -+ state->slot_data)->version; -+ up(&state->connect); -+ break; -+ case VCHIQ_MSG_BULK_RX: -+ case VCHIQ_MSG_BULK_TX: { -+ VCHIQ_BULK_QUEUE_T *queue; -+ WARN_ON(!state->is_master); -+ queue = (type == VCHIQ_MSG_BULK_RX) ? -+ &service->bulk_tx : &service->bulk_rx; -+ if ((service->remoteport == remoteport) -+ && (service->srvstate == -+ VCHIQ_SRVSTATE_OPEN)) { -+ VCHIQ_BULK_T *bulk; -+ int resolved = 0; -+ -+ DEBUG_TRACE(PARSE_LINE); -+ if (mutex_lock_interruptible( -+ &service->bulk_mutex) != 0) { -+ DEBUG_TRACE(PARSE_LINE); -+ goto bail_not_ready; -+ } -+ -+ WARN_ON(!(queue->remote_insert < queue->remove + -+ VCHIQ_NUM_SERVICE_BULKS)); -+ bulk = &queue->bulks[ -+ BULK_INDEX(queue->remote_insert)]; -+ bulk->remote_data = -+ (void *)((int *)header->data)[0]; -+ bulk->remote_size = ((int *)header->data)[1]; -+ wmb(); -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) %x@%x", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ bulk->remote_size, -+ (unsigned int)bulk->remote_data); -+ -+ queue->remote_insert++; -+ -+ if (atomic_read(&pause_bulks_count)) { -+ state->deferred_bulks++; -+ vchiq_log_info(vchiq_core_log_level, -+ "%s: deferring bulk (%d)", -+ __func__, -+ state->deferred_bulks); -+ if (state->conn_state != -+ VCHIQ_CONNSTATE_PAUSE_SENT) -+ vchiq_log_error( -+ vchiq_core_log_level, -+ "%s: bulks paused in " -+ "unexpected state %s", -+ __func__, -+ conn_state_names[ -+ state->conn_state]); -+ } else if (state->conn_state == -+ VCHIQ_CONNSTATE_CONNECTED) { -+ DEBUG_TRACE(PARSE_LINE); -+ resolved = resolve_bulks(service, -+ queue); -+ } -+ -+ mutex_unlock(&service->bulk_mutex); -+ if (resolved) -+ notify_bulks(service, queue, -+ 1/*retry_poll*/); -+ } -+ } break; -+ case VCHIQ_MSG_BULK_RX_DONE: -+ case VCHIQ_MSG_BULK_TX_DONE: -+ WARN_ON(state->is_master); -+ if ((service->remoteport == remoteport) -+ && (service->srvstate != -+ VCHIQ_SRVSTATE_FREE)) { -+ VCHIQ_BULK_QUEUE_T *queue; -+ VCHIQ_BULK_T *bulk; -+ -+ queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? -+ &service->bulk_rx : &service->bulk_tx; -+ -+ DEBUG_TRACE(PARSE_LINE); -+ if (mutex_lock_interruptible( -+ &service->bulk_mutex) != 0) { -+ DEBUG_TRACE(PARSE_LINE); -+ goto bail_not_ready; -+ } -+ if ((int)(queue->remote_insert - -+ queue->local_insert) >= 0) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) " -+ "unexpected (ri=%d,li=%d)", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ queue->remote_insert, -+ queue->local_insert); -+ mutex_unlock(&service->bulk_mutex); -+ break; -+ } -+ -+ BUG_ON(queue->process == queue->local_insert); -+ BUG_ON(queue->process != queue->remote_insert); -+ -+ bulk = &queue->bulks[ -+ BULK_INDEX(queue->remote_insert)]; -+ bulk->actual = *(int *)header->data; -+ queue->remote_insert++; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) %x@%x", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ bulk->actual, (unsigned int)bulk->data); -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs:%d %cx li=%x ri=%x p=%x", -+ state->id, localport, -+ (type == VCHIQ_MSG_BULK_RX_DONE) ? -+ 'r' : 't', -+ queue->local_insert, -+ queue->remote_insert, queue->process); -+ -+ DEBUG_TRACE(PARSE_LINE); -+ WARN_ON(queue->process == queue->local_insert); -+ vchiq_complete_bulk(bulk); -+ queue->process++; -+ mutex_unlock(&service->bulk_mutex); -+ DEBUG_TRACE(PARSE_LINE); -+ notify_bulks(service, queue, 1/*retry_poll*/); -+ DEBUG_TRACE(PARSE_LINE); -+ } -+ break; -+ case VCHIQ_MSG_PADDING: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs PADDING@%x,%x", -+ state->id, (unsigned int)header, size); -+ break; -+ case VCHIQ_MSG_PAUSE: -+ /* If initiated, signal the application thread */ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs PAUSE@%x,%x", -+ state->id, (unsigned int)header, size); -+ if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: PAUSE received in state PAUSED", -+ state->id); -+ break; -+ } -+ if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) { -+ /* Send a PAUSE in response */ -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), -+ NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK) -+ == VCHIQ_RETRY) -+ goto bail_not_ready; -+ if (state->is_master) -+ pause_bulks(state); -+ } -+ /* At this point slot_mutex is held */ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); -+ vchiq_platform_paused(state); -+ break; -+ case VCHIQ_MSG_RESUME: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs RESUME@%x,%x", -+ state->id, (unsigned int)header, size); -+ /* Release the slot mutex */ -+ mutex_unlock(&state->slot_mutex); -+ if (state->is_master) -+ resume_bulks(state); -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); -+ vchiq_platform_resumed(state); -+ break; -+ -+ case VCHIQ_MSG_REMOTE_USE: -+ vchiq_on_remote_use(state); -+ break; -+ case VCHIQ_MSG_REMOTE_RELEASE: -+ vchiq_on_remote_release(state); -+ break; -+ case VCHIQ_MSG_REMOTE_USE_ACTIVE: -+ vchiq_on_remote_use_active(state); -+ break; -+ -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: prs invalid msgid %x@%x,%x", -+ state->id, msgid, (unsigned int)header, size); -+ WARN(1, "invalid message\n"); -+ break; -+ } -+ -+skip_message: -+ if (service) { -+ unlock_service(service); -+ service = NULL; -+ } -+ -+ state->rx_pos += calc_stride(size); -+ -+ DEBUG_TRACE(PARSE_LINE); -+ /* Perform some housekeeping when the end of the slot is -+ ** reached. */ -+ if ((state->rx_pos & VCHIQ_SLOT_MASK) == 0) { -+ /* Remove the extra reference count. */ -+ release_slot(state, state->rx_info, NULL, NULL); -+ state->rx_data = NULL; -+ } -+ } -+ -+bail_not_ready: -+ if (service) -+ unlock_service(service); -+} -+ -+/* Called by the slot handler thread */ -+static int -+slot_handler_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ DEBUG_INITIALISE(local) -+ -+ while (1) { -+ DEBUG_COUNT(SLOT_HANDLER_COUNT); -+ DEBUG_TRACE(SLOT_HANDLER_LINE); -+ remote_event_wait(&local->trigger); -+ -+ rmb(); -+ -+ DEBUG_TRACE(SLOT_HANDLER_LINE); -+ if (state->poll_needed) { -+ /* Check if we need to suspend - may change our -+ * conn_state */ -+ vchiq_platform_check_suspend(state); -+ -+ state->poll_needed = 0; -+ -+ /* Handle service polling and other rare conditions here -+ ** out of the mainline code */ -+ switch (state->conn_state) { -+ case VCHIQ_CONNSTATE_CONNECTED: -+ /* Poll the services as requested */ -+ poll_services(state); -+ break; -+ -+ case VCHIQ_CONNSTATE_PAUSING: -+ if (state->is_master) -+ pause_bulks(state); -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), -+ NULL, 0, 0, -+ QMFLAGS_NO_MUTEX_UNLOCK) -+ != VCHIQ_RETRY) { -+ vchiq_set_conn_state(state, -+ VCHIQ_CONNSTATE_PAUSE_SENT); -+ } else { -+ if (state->is_master) -+ resume_bulks(state); -+ /* Retry later */ -+ state->poll_needed = 1; -+ } -+ break; -+ -+ case VCHIQ_CONNSTATE_PAUSED: -+ vchiq_platform_resume(state); -+ break; -+ -+ case VCHIQ_CONNSTATE_RESUMING: -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), -+ NULL, 0, 0, QMFLAGS_NO_MUTEX_LOCK) -+ != VCHIQ_RETRY) { -+ if (state->is_master) -+ resume_bulks(state); -+ vchiq_set_conn_state(state, -+ VCHIQ_CONNSTATE_CONNECTED); -+ vchiq_platform_resumed(state); -+ } else { -+ /* This should really be impossible, -+ ** since the PAUSE should have flushed -+ ** through outstanding messages. */ -+ vchiq_log_error(vchiq_core_log_level, -+ "Failed to send RESUME " -+ "message"); -+ BUG(); -+ } -+ break; -+ -+ case VCHIQ_CONNSTATE_PAUSE_TIMEOUT: -+ case VCHIQ_CONNSTATE_RESUME_TIMEOUT: -+ vchiq_platform_handle_timeout(state); -+ break; -+ default: -+ break; -+ } -+ -+ -+ } -+ -+ DEBUG_TRACE(SLOT_HANDLER_LINE); -+ parse_rx_slots(state); -+ } -+ return 0; -+} -+ -+ -+/* Called by the recycle thread */ -+static int -+recycle_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ -+ while (1) { -+ remote_event_wait(&local->recycle); -+ -+ process_free_queue(state); -+ } -+ return 0; -+} -+ -+ -+/* Called by the sync thread */ -+static int -+sync_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, -+ state->remote->slot_sync); -+ -+ while (1) { -+ VCHIQ_SERVICE_T *service; -+ int msgid, size; -+ int type; -+ unsigned int localport, remoteport; -+ -+ remote_event_wait(&local->sync_trigger); -+ -+ rmb(); -+ -+ msgid = header->msgid; -+ size = header->size; -+ type = VCHIQ_MSG_TYPE(msgid); -+ localport = VCHIQ_MSG_DSTPORT(msgid); -+ remoteport = VCHIQ_MSG_SRCPORT(msgid); -+ -+ service = find_service_by_port(state, localport); -+ -+ if (!service) { -+ vchiq_log_error(vchiq_sync_log_level, -+ "%d: sf %s@%x (%d->%d) - " -+ "invalid/closed service %d", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, localport); -+ release_message_sync(state, header); -+ continue; -+ } -+ -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ vchiq_log_trace(vchiq_sync_log_level, -+ "Rcvd Msg %s from %c%c%c%c s:%d d:%d len:%d", -+ msg_type_str(type), -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ remoteport, localport, size); -+ if (size > 0) -+ vchiq_log_dump_mem("Rcvd", 0, header->data, -+ min(16, size)); -+ } -+ -+ switch (type) { -+ case VCHIQ_MSG_OPENACK: -+ if (size >= sizeof(struct vchiq_openack_payload)) { -+ const struct vchiq_openack_payload *payload = -+ (struct vchiq_openack_payload *) -+ header->data; -+ service->peer_version = payload->version; -+ } -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: sf OPENACK@%x,%x (%d->%d) v:%d", -+ state->id, (unsigned int)header, size, -+ remoteport, localport, service->peer_version); -+ if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { -+ service->remoteport = remoteport; -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_OPENSYNC); -+ service->sync = 1; -+ up(&service->remove_event); -+ } -+ release_message_sync(state, header); -+ break; -+ -+ case VCHIQ_MSG_DATA: -+ vchiq_log_trace(vchiq_sync_log_level, -+ "%d: sf DATA@%x,%x (%d->%d)", -+ state->id, (unsigned int)header, size, -+ remoteport, localport); -+ -+ if ((service->remoteport == remoteport) && -+ (service->srvstate == -+ VCHIQ_SRVSTATE_OPENSYNC)) { -+ if (make_service_callback(service, -+ VCHIQ_MESSAGE_AVAILABLE, header, -+ NULL) == VCHIQ_RETRY) -+ vchiq_log_error(vchiq_sync_log_level, -+ "synchronous callback to " -+ "service %d returns " -+ "VCHIQ_RETRY", -+ localport); -+ } -+ break; -+ -+ default: -+ vchiq_log_error(vchiq_sync_log_level, -+ "%d: sf unexpected msgid %x@%x,%x", -+ state->id, msgid, (unsigned int)header, size); -+ release_message_sync(state, header); -+ break; -+ } -+ -+ unlock_service(service); -+ } -+ -+ return 0; -+} -+ -+ -+static void -+init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue) -+{ -+ queue->local_insert = 0; -+ queue->remote_insert = 0; -+ queue->process = 0; -+ queue->remote_notify = 0; -+ queue->remove = 0; -+} -+ -+ -+inline const char * -+get_conn_state_name(VCHIQ_CONNSTATE_T conn_state) -+{ -+ return conn_state_names[conn_state]; -+} -+ -+ -+VCHIQ_SLOT_ZERO_T * -+vchiq_init_slots(void *mem_base, int mem_size) -+{ -+ int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK; -+ VCHIQ_SLOT_ZERO_T *slot_zero = -+ (VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align); -+ int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE; -+ int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS; -+ -+ /* Ensure there is enough memory to run an absolutely minimum system */ -+ num_slots -= first_data_slot; -+ -+ if (num_slots < 4) { -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_init_slots - insufficient memory %x bytes", -+ mem_size); -+ return NULL; -+ } -+ -+ memset(slot_zero, 0, sizeof(VCHIQ_SLOT_ZERO_T)); -+ -+ slot_zero->magic = VCHIQ_MAGIC; -+ slot_zero->version = VCHIQ_VERSION; -+ slot_zero->version_min = VCHIQ_VERSION_MIN; -+ slot_zero->slot_zero_size = sizeof(VCHIQ_SLOT_ZERO_T); -+ slot_zero->slot_size = VCHIQ_SLOT_SIZE; -+ slot_zero->max_slots = VCHIQ_MAX_SLOTS; -+ slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE; -+ -+ slot_zero->master.slot_sync = first_data_slot; -+ slot_zero->master.slot_first = first_data_slot + 1; -+ slot_zero->master.slot_last = first_data_slot + (num_slots/2) - 1; -+ slot_zero->slave.slot_sync = first_data_slot + (num_slots/2); -+ slot_zero->slave.slot_first = first_data_slot + (num_slots/2) + 1; -+ slot_zero->slave.slot_last = first_data_slot + num_slots - 1; -+ -+ return slot_zero; -+} -+ -+VCHIQ_STATUS_T -+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, -+ int is_master) -+{ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_SHARED_STATE_T *remote; -+ VCHIQ_STATUS_T status; -+ char threadname[10]; -+ static int id; -+ int i; -+ -+ vchiq_log_warning(vchiq_core_log_level, -+ "%s: slot_zero = 0x%08lx, is_master = %d", -+ __func__, (unsigned long)slot_zero, is_master); -+ -+ /* Check the input configuration */ -+ -+ if (slot_zero->magic != VCHIQ_MAGIC) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("Invalid VCHIQ magic value found."); -+ vchiq_loud_error("slot_zero=%x: magic=%x (expected %x)", -+ (unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if (slot_zero->version < VCHIQ_VERSION_MIN) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("Incompatible VCHIQ versions found."); -+ vchiq_loud_error("slot_zero=%x: VideoCore version=%d " -+ "(minimum %d)", -+ (unsigned int)slot_zero, slot_zero->version, -+ VCHIQ_VERSION_MIN); -+ vchiq_loud_error("Restart with a newer VideoCore image."); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if (VCHIQ_VERSION < slot_zero->version_min) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("Incompatible VCHIQ versions found."); -+ vchiq_loud_error("slot_zero=%x: version=%d (VideoCore " -+ "minimum %d)", -+ (unsigned int)slot_zero, VCHIQ_VERSION, -+ slot_zero->version_min); -+ vchiq_loud_error("Restart with a newer kernel."); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if ((slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) || -+ (slot_zero->slot_size != VCHIQ_SLOT_SIZE) || -+ (slot_zero->max_slots != VCHIQ_MAX_SLOTS) || -+ (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) { -+ vchiq_loud_error_header(); -+ if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) -+ vchiq_loud_error("slot_zero=%x: slot_zero_size=%x " -+ "(expected %x)", -+ (unsigned int)slot_zero, -+ slot_zero->slot_zero_size, -+ sizeof(VCHIQ_SLOT_ZERO_T)); -+ if (slot_zero->slot_size != VCHIQ_SLOT_SIZE) -+ vchiq_loud_error("slot_zero=%x: slot_size=%d " -+ "(expected %d", -+ (unsigned int)slot_zero, slot_zero->slot_size, -+ VCHIQ_SLOT_SIZE); -+ if (slot_zero->max_slots != VCHIQ_MAX_SLOTS) -+ vchiq_loud_error("slot_zero=%x: max_slots=%d " -+ "(expected %d)", -+ (unsigned int)slot_zero, slot_zero->max_slots, -+ VCHIQ_MAX_SLOTS); -+ if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE) -+ vchiq_loud_error("slot_zero=%x: max_slots_per_side=%d " -+ "(expected %d)", -+ (unsigned int)slot_zero, -+ slot_zero->max_slots_per_side, -+ VCHIQ_MAX_SLOTS_PER_SIDE); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if (VCHIQ_VERSION < slot_zero->version) -+ slot_zero->version = VCHIQ_VERSION; -+ -+ if (is_master) { -+ local = &slot_zero->master; -+ remote = &slot_zero->slave; -+ } else { -+ local = &slot_zero->slave; -+ remote = &slot_zero->master; -+ } -+ -+ if (local->initialised) { -+ vchiq_loud_error_header(); -+ if (remote->initialised) -+ vchiq_loud_error("local state has already been " -+ "initialised"); -+ else -+ vchiq_loud_error("master/slave mismatch - two %ss", -+ is_master ? "master" : "slave"); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ memset(state, 0, sizeof(VCHIQ_STATE_T)); -+ -+ state->id = id++; -+ state->is_master = is_master; -+ -+ /* -+ initialize shared state pointers -+ */ -+ -+ state->local = local; -+ state->remote = remote; -+ state->slot_data = (VCHIQ_SLOT_T *)slot_zero; -+ -+ /* -+ initialize events and mutexes -+ */ -+ -+ sema_init(&state->connect, 0); -+ mutex_init(&state->mutex); -+ sema_init(&state->trigger_event, 0); -+ sema_init(&state->recycle_event, 0); -+ sema_init(&state->sync_trigger_event, 0); -+ sema_init(&state->sync_release_event, 0); -+ -+ mutex_init(&state->slot_mutex); -+ mutex_init(&state->recycle_mutex); -+ mutex_init(&state->sync_mutex); -+ mutex_init(&state->bulk_transfer_mutex); -+ -+ sema_init(&state->slot_available_event, 0); -+ sema_init(&state->slot_remove_event, 0); -+ sema_init(&state->data_quota_event, 0); -+ -+ state->slot_queue_available = 0; -+ -+ for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &state->service_quotas[i]; -+ sema_init(&service_quota->quota_event, 0); -+ } -+ -+ for (i = local->slot_first; i <= local->slot_last; i++) { -+ local->slot_queue[state->slot_queue_available++] = i; -+ up(&state->slot_available_event); -+ } -+ -+ state->default_slot_quota = state->slot_queue_available/2; -+ state->default_message_quota = -+ min((unsigned short)(state->default_slot_quota * 256), -+ (unsigned short)~0); -+ -+ state->previous_data_index = -1; -+ state->data_use_count = 0; -+ state->data_quota = state->slot_queue_available - 1; -+ -+ local->trigger.event = &state->trigger_event; -+ remote_event_create(&local->trigger); -+ local->tx_pos = 0; -+ -+ local->recycle.event = &state->recycle_event; -+ remote_event_create(&local->recycle); -+ local->slot_queue_recycle = state->slot_queue_available; -+ -+ local->sync_trigger.event = &state->sync_trigger_event; -+ remote_event_create(&local->sync_trigger); -+ -+ local->sync_release.event = &state->sync_release_event; -+ remote_event_create(&local->sync_release); -+ -+ /* At start-of-day, the slot is empty and available */ -+ ((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid -+ = VCHIQ_MSGID_PADDING; -+ remote_event_signal_local(&local->sync_release); -+ -+ local->debug[DEBUG_ENTRIES] = DEBUG_MAX; -+ -+ status = vchiq_platform_init_state(state); -+ -+ /* -+ bring up slot handler thread -+ */ -+ snprintf(threadname, sizeof(threadname), "VCHIQ-%d", state->id); -+ state->slot_handler_thread = kthread_create(&slot_handler_func, -+ (void *)state, -+ threadname); -+ -+ if (state->slot_handler_thread == NULL) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("couldn't create thread %s", threadname); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ set_user_nice(state->slot_handler_thread, -19); -+ wake_up_process(state->slot_handler_thread); -+ -+ snprintf(threadname, sizeof(threadname), "VCHIQr-%d", state->id); -+ state->recycle_thread = kthread_create(&recycle_func, -+ (void *)state, -+ threadname); -+ if (state->recycle_thread == NULL) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("couldn't create thread %s", threadname); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ set_user_nice(state->recycle_thread, -19); -+ wake_up_process(state->recycle_thread); -+ -+ snprintf(threadname, sizeof(threadname), "VCHIQs-%d", state->id); -+ state->sync_thread = kthread_create(&sync_func, -+ (void *)state, -+ threadname); -+ if (state->sync_thread == NULL) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("couldn't create thread %s", threadname); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ set_user_nice(state->sync_thread, -20); -+ wake_up_process(state->sync_thread); -+ -+ BUG_ON(state->id >= VCHIQ_MAX_STATES); -+ vchiq_states[state->id] = state; -+ -+ /* Indicate readiness to the other side */ -+ local->initialised = 1; -+ -+ return status; -+} -+ -+/* Called from application thread when a client or server service is created. */ -+VCHIQ_SERVICE_T * -+vchiq_add_service_internal(VCHIQ_STATE_T *state, -+ const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, -+ VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term) -+{ -+ VCHIQ_SERVICE_T *service; -+ -+ service = kmalloc(sizeof(VCHIQ_SERVICE_T), GFP_KERNEL); -+ if (service) { -+ service->base.fourcc = params->fourcc; -+ service->base.callback = params->callback; -+ service->base.userdata = params->userdata; -+ service->handle = VCHIQ_SERVICE_HANDLE_INVALID; -+ service->ref_count = 1; -+ service->srvstate = VCHIQ_SRVSTATE_FREE; -+ service->userdata_term = userdata_term; -+ service->localport = VCHIQ_PORT_FREE; -+ service->remoteport = VCHIQ_PORT_FREE; -+ -+ service->public_fourcc = (srvstate == VCHIQ_SRVSTATE_OPENING) ? -+ VCHIQ_FOURCC_INVALID : params->fourcc; -+ service->client_id = 0; -+ service->auto_close = 1; -+ service->sync = 0; -+ service->closing = 0; -+ service->trace = 0; -+ atomic_set(&service->poll_flags, 0); -+ service->version = params->version; -+ service->version_min = params->version_min; -+ service->state = state; -+ service->instance = instance; -+ service->service_use_count = 0; -+ init_bulk_queue(&service->bulk_tx); -+ init_bulk_queue(&service->bulk_rx); -+ sema_init(&service->remove_event, 0); -+ sema_init(&service->bulk_remove_event, 0); -+ mutex_init(&service->bulk_mutex); -+ memset(&service->stats, 0, sizeof(service->stats)); -+ } else { -+ vchiq_log_error(vchiq_core_log_level, -+ "Out of memory"); -+ } -+ -+ if (service) { -+ VCHIQ_SERVICE_T **pservice = NULL; -+ int i; -+ -+ /* Although it is perfectly possible to use service_spinlock -+ ** to protect the creation of services, it is overkill as it -+ ** disables interrupts while the array is searched. -+ ** The only danger is of another thread trying to create a -+ ** service - service deletion is safe. -+ ** Therefore it is preferable to use state->mutex which, -+ ** although slower to claim, doesn't block interrupts while -+ ** it is held. -+ */ -+ -+ mutex_lock(&state->mutex); -+ -+ /* Prepare to use a previously unused service */ -+ if (state->unused_service < VCHIQ_MAX_SERVICES) -+ pservice = &state->services[state->unused_service]; -+ -+ if (srvstate == VCHIQ_SRVSTATE_OPENING) { -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *srv = state->services[i]; -+ if (!srv) { -+ pservice = &state->services[i]; -+ break; -+ } -+ } -+ } else { -+ for (i = (state->unused_service - 1); i >= 0; i--) { -+ VCHIQ_SERVICE_T *srv = state->services[i]; -+ if (!srv) -+ pservice = &state->services[i]; -+ else if ((srv->public_fourcc == params->fourcc) -+ && ((srv->instance != instance) || -+ (srv->base.callback != -+ params->callback))) { -+ /* There is another server using this -+ ** fourcc which doesn't match. */ -+ pservice = NULL; -+ break; -+ } -+ } -+ } -+ -+ if (pservice) { -+ service->localport = (pservice - state->services); -+ if (!handle_seq) -+ handle_seq = VCHIQ_MAX_STATES * -+ VCHIQ_MAX_SERVICES; -+ service->handle = handle_seq | -+ (state->id * VCHIQ_MAX_SERVICES) | -+ service->localport; -+ handle_seq += VCHIQ_MAX_STATES * VCHIQ_MAX_SERVICES; -+ *pservice = service; -+ if (pservice == &state->services[state->unused_service]) -+ state->unused_service++; -+ } -+ -+ mutex_unlock(&state->mutex); -+ -+ if (!pservice) { -+ kfree(service); -+ service = NULL; -+ } -+ } -+ -+ if (service) { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &state->service_quotas[service->localport]; -+ service_quota->slot_quota = state->default_slot_quota; -+ service_quota->message_quota = state->default_message_quota; -+ if (service_quota->slot_use_count == 0) -+ service_quota->previous_tx_index = -+ SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos) -+ - 1; -+ -+ /* Bring this service online */ -+ vchiq_set_service_state(service, srvstate); -+ -+ vchiq_log_info(vchiq_core_msg_log_level, -+ "%s Service %c%c%c%c SrcPort:%d", -+ (srvstate == VCHIQ_SRVSTATE_OPENING) -+ ? "Open" : "Add", -+ VCHIQ_FOURCC_AS_4CHARS(params->fourcc), -+ service->localport); -+ } -+ -+ /* Don't unlock the service - leave it with a ref_count of 1. */ -+ -+ return service; -+} -+ -+VCHIQ_STATUS_T -+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) -+{ -+ struct vchiq_open_payload payload = { -+ service->base.fourcc, -+ client_id, -+ service->version, -+ service->version_min -+ }; -+ VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) }; -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ service->client_id = client_id; -+ vchiq_use_service_internal(service); -+ status = queue_message(service->state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0), -+ &body, 1, sizeof(payload), QMFLAGS_IS_BLOCKING); -+ if (status == VCHIQ_SUCCESS) { -+ /* Wait for the ACK/NAK */ -+ if (down_interruptible(&service->remove_event) != 0) { -+ status = VCHIQ_RETRY; -+ vchiq_release_service_internal(service); -+ } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && -+ (service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) { -+ if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: osi - srvstate = %s (ref %d)", -+ service->state->id, -+ srvstate_names[service->srvstate], -+ service->ref_count); -+ status = VCHIQ_ERROR; -+ VCHIQ_SERVICE_STATS_INC(service, error_count); -+ vchiq_release_service_internal(service); -+ } -+ } -+ return status; -+} -+ -+static void -+release_service_messages(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ int slot_last = state->remote->slot_last; -+ int i; -+ -+ /* Release any claimed messages aimed at this service */ -+ -+ if (service->sync) { -+ VCHIQ_HEADER_T *header = -+ (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, -+ state->remote->slot_sync); -+ if (VCHIQ_MSG_DSTPORT(header->msgid) == service->localport) -+ release_message_sync(state, header); -+ -+ return; -+ } -+ -+ for (i = state->remote->slot_first; i <= slot_last; i++) { -+ VCHIQ_SLOT_INFO_T *slot_info = -+ SLOT_INFO_FROM_INDEX(state, i); -+ if (slot_info->release_count != slot_info->use_count) { -+ char *data = -+ (char *)SLOT_DATA_FROM_INDEX(state, i); -+ unsigned int pos, end; -+ -+ end = VCHIQ_SLOT_SIZE; -+ if (data == state->rx_data) -+ /* This buffer is still being read from - stop -+ ** at the current read position */ -+ end = state->rx_pos & VCHIQ_SLOT_MASK; -+ -+ pos = 0; -+ -+ while (pos < end) { -+ VCHIQ_HEADER_T *header = -+ (VCHIQ_HEADER_T *)(data + pos); -+ int msgid = header->msgid; -+ int port = VCHIQ_MSG_DSTPORT(msgid); -+ if ((port == service->localport) && -+ (msgid & VCHIQ_MSGID_CLAIMED)) { -+ vchiq_log_info(vchiq_core_log_level, -+ " fsi - hdr %x", -+ (unsigned int)header); -+ release_slot(state, slot_info, header, -+ NULL); -+ } -+ pos += calc_stride(header->size); -+ if (pos > VCHIQ_SLOT_SIZE) { -+ vchiq_log_error(vchiq_core_log_level, -+ "fsi - pos %x: header %x, " -+ "msgid %x, header->msgid %x, " -+ "header->size %x", -+ pos, (unsigned int)header, -+ msgid, header->msgid, -+ header->size); -+ WARN(1, "invalid slot position\n"); -+ } -+ } -+ } -+ } -+} -+ -+static int -+do_abort_bulks(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATUS_T status; -+ -+ /* Abort any outstanding bulk transfers */ -+ if (mutex_lock_interruptible(&service->bulk_mutex) != 0) -+ return 0; -+ abort_outstanding_bulks(service, &service->bulk_tx); -+ abort_outstanding_bulks(service, &service->bulk_rx); -+ mutex_unlock(&service->bulk_mutex); -+ -+ status = notify_bulks(service, &service->bulk_tx, 0/*!retry_poll*/); -+ if (status == VCHIQ_SUCCESS) -+ status = notify_bulks(service, &service->bulk_rx, -+ 0/*!retry_poll*/); -+ return (status == VCHIQ_SUCCESS); -+} -+ -+static VCHIQ_STATUS_T -+close_service_complete(VCHIQ_SERVICE_T *service, int failstate) -+{ -+ VCHIQ_STATUS_T status; -+ int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); -+ int newstate; -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_OPEN: -+ case VCHIQ_SRVSTATE_CLOSESENT: -+ case VCHIQ_SRVSTATE_CLOSERECVD: -+ if (is_server) { -+ if (service->auto_close) { -+ service->client_id = 0; -+ service->remoteport = VCHIQ_PORT_FREE; -+ newstate = VCHIQ_SRVSTATE_LISTENING; -+ } else -+ newstate = VCHIQ_SRVSTATE_CLOSEWAIT; -+ } else -+ newstate = VCHIQ_SRVSTATE_CLOSED; -+ vchiq_set_service_state(service, newstate); -+ break; -+ case VCHIQ_SRVSTATE_LISTENING: -+ break; -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "close_service_complete(%x) called in state %s", -+ service->handle, srvstate_names[service->srvstate]); -+ WARN(1, "close_service_complete in unexpected state\n"); -+ return VCHIQ_ERROR; -+ } -+ -+ status = make_service_callback(service, -+ VCHIQ_SERVICE_CLOSED, NULL, NULL); -+ -+ if (status != VCHIQ_RETRY) { -+ int uc = service->service_use_count; -+ int i; -+ /* Complete the close process */ -+ for (i = 0; i < uc; i++) -+ /* cater for cases where close is forced and the -+ ** client may not close all it's handles */ -+ vchiq_release_service_internal(service); -+ -+ service->client_id = 0; -+ service->remoteport = VCHIQ_PORT_FREE; -+ -+ if (service->srvstate == VCHIQ_SRVSTATE_CLOSED) -+ vchiq_free_service_internal(service); -+ else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) { -+ if (is_server) -+ service->closing = 0; -+ -+ up(&service->remove_event); -+ } -+ } else -+ vchiq_set_service_state(service, failstate); -+ -+ return status; -+} -+ -+/* Called by the slot handler */ -+VCHIQ_STATUS_T -+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); -+ -+ vchiq_log_info(vchiq_core_log_level, "%d: csi:%d,%d (%s)", -+ service->state->id, service->localport, close_recvd, -+ srvstate_names[service->srvstate]); -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_CLOSED: -+ case VCHIQ_SRVSTATE_HIDDEN: -+ case VCHIQ_SRVSTATE_LISTENING: -+ case VCHIQ_SRVSTATE_CLOSEWAIT: -+ if (close_recvd) -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_close_service_internal(1) called " -+ "in state %s", -+ srvstate_names[service->srvstate]); -+ else if (is_server) { -+ if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { -+ status = VCHIQ_ERROR; -+ } else { -+ service->client_id = 0; -+ service->remoteport = VCHIQ_PORT_FREE; -+ if (service->srvstate == -+ VCHIQ_SRVSTATE_CLOSEWAIT) -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_LISTENING); -+ } -+ up(&service->remove_event); -+ } else -+ vchiq_free_service_internal(service); -+ break; -+ case VCHIQ_SRVSTATE_OPENING: -+ if (close_recvd) { -+ /* The open was rejected - tell the user */ -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_CLOSEWAIT); -+ up(&service->remove_event); -+ } else { -+ /* Shutdown mid-open - let the other side know */ -+ status = queue_message(state, service, -+ VCHIQ_MAKE_MSG -+ (VCHIQ_MSG_CLOSE, -+ service->localport, -+ VCHIQ_MSG_DSTPORT(service->remoteport)), -+ NULL, 0, 0, 0); -+ } -+ break; -+ -+ case VCHIQ_SRVSTATE_OPENSYNC: -+ mutex_lock(&state->sync_mutex); -+ /* Drop through */ -+ -+ case VCHIQ_SRVSTATE_OPEN: -+ if (state->is_master || close_recvd) { -+ if (!do_abort_bulks(service)) -+ status = VCHIQ_RETRY; -+ } -+ -+ release_service_messages(service); -+ -+ if (status == VCHIQ_SUCCESS) -+ status = queue_message(state, service, -+ VCHIQ_MAKE_MSG -+ (VCHIQ_MSG_CLOSE, -+ service->localport, -+ VCHIQ_MSG_DSTPORT(service->remoteport)), -+ NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK); -+ -+ if (status == VCHIQ_SUCCESS) { -+ if (!close_recvd) { -+ /* Change the state while the mutex is -+ still held */ -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_CLOSESENT); -+ mutex_unlock(&state->slot_mutex); -+ if (service->sync) -+ mutex_unlock(&state->sync_mutex); -+ break; -+ } -+ } else if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) { -+ mutex_unlock(&state->sync_mutex); -+ break; -+ } else -+ break; -+ -+ /* Change the state while the mutex is still held */ -+ vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD); -+ mutex_unlock(&state->slot_mutex); -+ if (service->sync) -+ mutex_unlock(&state->sync_mutex); -+ -+ status = close_service_complete(service, -+ VCHIQ_SRVSTATE_CLOSERECVD); -+ break; -+ -+ case VCHIQ_SRVSTATE_CLOSESENT: -+ if (!close_recvd) -+ /* This happens when a process is killed mid-close */ -+ break; -+ -+ if (!state->is_master) { -+ if (!do_abort_bulks(service)) { -+ status = VCHIQ_RETRY; -+ break; -+ } -+ } -+ -+ if (status == VCHIQ_SUCCESS) -+ status = close_service_complete(service, -+ VCHIQ_SRVSTATE_CLOSERECVD); -+ break; -+ -+ case VCHIQ_SRVSTATE_CLOSERECVD: -+ if (!close_recvd && is_server) -+ /* Force into LISTENING mode */ -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_LISTENING); -+ status = close_service_complete(service, -+ VCHIQ_SRVSTATE_CLOSERECVD); -+ break; -+ -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_close_service_internal(%d) called in state %s", -+ close_recvd, srvstate_names[service->srvstate]); -+ break; -+ } -+ -+ return status; -+} -+ -+/* Called from the application process upon process death */ -+void -+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ -+ vchiq_log_info(vchiq_core_log_level, "%d: tsi - (%d<->%d)", -+ state->id, service->localport, service->remoteport); -+ -+ mark_service_closing(service); -+ -+ /* Mark the service for removal by the slot handler */ -+ request_poll(state, service, VCHIQ_POLL_REMOVE); -+} -+ -+/* Called from the slot handler */ -+void -+vchiq_free_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ -+ vchiq_log_info(vchiq_core_log_level, "%d: fsi - (%d)", -+ state->id, service->localport); -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_OPENING: -+ case VCHIQ_SRVSTATE_CLOSED: -+ case VCHIQ_SRVSTATE_HIDDEN: -+ case VCHIQ_SRVSTATE_LISTENING: -+ case VCHIQ_SRVSTATE_CLOSEWAIT: -+ break; -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: fsi - (%d) in state %s", -+ state->id, service->localport, -+ srvstate_names[service->srvstate]); -+ return; -+ } -+ -+ vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE); -+ -+ up(&service->remove_event); -+ -+ /* Release the initial lock */ -+ unlock_service(service); -+} -+ -+VCHIQ_STATUS_T -+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_SERVICE_T *service; -+ int i; -+ -+ /* Find all services registered to this client and enable them. */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, -+ &i)) != NULL) { -+ if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN) -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_LISTENING); -+ unlock_service(service); -+ } -+ -+ if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) { -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0, -+ 0, QMFLAGS_IS_BLOCKING) == VCHIQ_RETRY) -+ return VCHIQ_RETRY; -+ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING); -+ } -+ -+ if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) { -+ if (down_interruptible(&state->connect) != 0) -+ return VCHIQ_RETRY; -+ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); -+ up(&state->connect); -+ } -+ -+ return VCHIQ_SUCCESS; -+} -+ -+VCHIQ_STATUS_T -+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_SERVICE_T *service; -+ int i; -+ -+ /* Find all services registered to this client and enable them. */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, -+ &i)) != NULL) { -+ (void)vchiq_remove_service(service->handle); -+ unlock_service(service); -+ } -+ -+ return VCHIQ_SUCCESS; -+} -+ -+VCHIQ_STATUS_T -+vchiq_pause_internal(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ switch (state->conn_state) { -+ case VCHIQ_CONNSTATE_CONNECTED: -+ /* Request a pause */ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSING); -+ request_poll(state, NULL, 0); -+ break; -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_pause_internal in state %s\n", -+ conn_state_names[state->conn_state]); -+ status = VCHIQ_ERROR; -+ VCHIQ_STATS_INC(state, error_count); -+ break; -+ } -+ -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_resume_internal(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_RESUMING); -+ request_poll(state, NULL, 0); -+ } else { -+ status = VCHIQ_ERROR; -+ VCHIQ_STATS_INC(state, error_count); -+ } -+ -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ /* Unregister the service */ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (!service) -+ return VCHIQ_ERROR; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: close_service:%d", -+ service->state->id, service->localport); -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || -+ (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)) { -+ unlock_service(service); -+ return VCHIQ_ERROR; -+ } -+ -+ mark_service_closing(service); -+ -+ if (current == service->state->slot_handler_thread) { -+ status = vchiq_close_service_internal(service, -+ 0/*!close_recvd*/); -+ BUG_ON(status == VCHIQ_RETRY); -+ } else { -+ /* Mark the service for termination by the slot handler */ -+ request_poll(service->state, service, VCHIQ_POLL_TERMINATE); -+ } -+ -+ while (1) { -+ if (down_interruptible(&service->remove_event) != 0) { -+ status = VCHIQ_RETRY; -+ break; -+ } -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || -+ (service->srvstate == VCHIQ_SRVSTATE_OPEN)) -+ break; -+ -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: close_service:%d - waiting in state %s", -+ service->state->id, service->localport, -+ srvstate_names[service->srvstate]); -+ } -+ -+ if ((status == VCHIQ_SUCCESS) && -+ (service->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (service->srvstate != VCHIQ_SRVSTATE_LISTENING)) -+ status = VCHIQ_ERROR; -+ -+ unlock_service(service); -+ -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ /* Unregister the service */ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (!service) -+ return VCHIQ_ERROR; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: remove_service:%d", -+ service->state->id, service->localport); -+ -+ if (service->srvstate == VCHIQ_SRVSTATE_FREE) { -+ unlock_service(service); -+ return VCHIQ_ERROR; -+ } -+ -+ mark_service_closing(service); -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || -+ (current == service->state->slot_handler_thread)) { -+ /* Make it look like a client, because it must be removed and -+ not left in the LISTENING state. */ -+ service->public_fourcc = VCHIQ_FOURCC_INVALID; -+ -+ status = vchiq_close_service_internal(service, -+ 0/*!close_recvd*/); -+ BUG_ON(status == VCHIQ_RETRY); -+ } else { -+ /* Mark the service for removal by the slot handler */ -+ request_poll(service->state, service, VCHIQ_POLL_REMOVE); -+ } -+ while (1) { -+ if (down_interruptible(&service->remove_event) != 0) { -+ status = VCHIQ_RETRY; -+ break; -+ } -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_OPEN)) -+ break; -+ -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: remove_service:%d - waiting in state %s", -+ service->state->id, service->localport, -+ srvstate_names[service->srvstate]); -+ } -+ -+ if ((status == VCHIQ_SUCCESS) && -+ (service->srvstate != VCHIQ_SRVSTATE_FREE)) -+ status = VCHIQ_ERROR; -+ -+ unlock_service(service); -+ -+ return status; -+} -+ -+ -+/* This function may be called by kernel threads or user threads. -+ * User threads may receive VCHIQ_RETRY to indicate that a signal has been -+ * received and the call should be retried after being returned to user -+ * context. -+ * When called in blocking mode, the userdata field points to a bulk_waiter -+ * structure. -+ */ -+VCHIQ_STATUS_T -+vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_BULK_QUEUE_T *queue; -+ VCHIQ_BULK_T *bulk; -+ VCHIQ_STATE_T *state; -+ struct bulk_waiter *bulk_waiter = NULL; -+ const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; -+ const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? -+ VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX; -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ -+ if (!service || -+ (service->srvstate != VCHIQ_SRVSTATE_OPEN) || -+ ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) || -+ (vchiq_check_service(service) != VCHIQ_SUCCESS)) -+ goto error_exit; -+ -+ switch (mode) { -+ case VCHIQ_BULK_MODE_NOCALLBACK: -+ case VCHIQ_BULK_MODE_CALLBACK: -+ break; -+ case VCHIQ_BULK_MODE_BLOCKING: -+ bulk_waiter = (struct bulk_waiter *)userdata; -+ sema_init(&bulk_waiter->event, 0); -+ bulk_waiter->actual = 0; -+ bulk_waiter->bulk = NULL; -+ break; -+ case VCHIQ_BULK_MODE_WAITING: -+ bulk_waiter = (struct bulk_waiter *)userdata; -+ bulk = bulk_waiter->bulk; -+ goto waiting; -+ default: -+ goto error_exit; -+ } -+ -+ state = service->state; -+ -+ queue = (dir == VCHIQ_BULK_TRANSMIT) ? -+ &service->bulk_tx : &service->bulk_rx; -+ -+ if (mutex_lock_interruptible(&service->bulk_mutex) != 0) { -+ status = VCHIQ_RETRY; -+ goto error_exit; -+ } -+ -+ if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) { -+ VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); -+ do { -+ mutex_unlock(&service->bulk_mutex); -+ if (down_interruptible(&service->bulk_remove_event) -+ != 0) { -+ status = VCHIQ_RETRY; -+ goto error_exit; -+ } -+ if (mutex_lock_interruptible(&service->bulk_mutex) -+ != 0) { -+ status = VCHIQ_RETRY; -+ goto error_exit; -+ } -+ } while (queue->local_insert == queue->remove + -+ VCHIQ_NUM_SERVICE_BULKS); -+ } -+ -+ bulk = &queue->bulks[BULK_INDEX(queue->local_insert)]; -+ -+ bulk->mode = mode; -+ bulk->dir = dir; -+ bulk->userdata = userdata; -+ bulk->size = size; -+ bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; -+ -+ if (vchiq_prepare_bulk_data(bulk, memhandle, offset, size, dir) != -+ VCHIQ_SUCCESS) -+ goto unlock_error_exit; -+ -+ wmb(); -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: bt (%d->%d) %cx %x@%x %x", -+ state->id, -+ service->localport, service->remoteport, dir_char, -+ size, (unsigned int)bulk->data, (unsigned int)userdata); -+ -+ /* The slot mutex must be held when the service is being closed, so -+ claim it here to ensure that isn't happening */ -+ if (mutex_lock_interruptible(&state->slot_mutex) != 0) { -+ status = VCHIQ_RETRY; -+ goto cancel_bulk_error_exit; -+ } -+ -+ if (service->srvstate != VCHIQ_SRVSTATE_OPEN) -+ goto unlock_both_error_exit; -+ -+ if (state->is_master) { -+ queue->local_insert++; -+ if (resolve_bulks(service, queue)) -+ request_poll(state, service, -+ (dir == VCHIQ_BULK_TRANSMIT) ? -+ VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); -+ } else { -+ int payload[2] = { (int)bulk->data, bulk->size }; -+ VCHIQ_ELEMENT_T element = { payload, sizeof(payload) }; -+ -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(dir_msgtype, -+ service->localport, service->remoteport), -+ &element, 1, sizeof(payload), -+ QMFLAGS_IS_BLOCKING | -+ QMFLAGS_NO_MUTEX_LOCK | -+ QMFLAGS_NO_MUTEX_UNLOCK); -+ if (status != VCHIQ_SUCCESS) { -+ goto unlock_both_error_exit; -+ } -+ queue->local_insert++; -+ } -+ -+ mutex_unlock(&state->slot_mutex); -+ mutex_unlock(&service->bulk_mutex); -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: bt:%d %cx li=%x ri=%x p=%x", -+ state->id, -+ service->localport, dir_char, -+ queue->local_insert, queue->remote_insert, queue->process); -+ -+waiting: -+ unlock_service(service); -+ -+ status = VCHIQ_SUCCESS; -+ -+ if (bulk_waiter) { -+ bulk_waiter->bulk = bulk; -+ if (down_interruptible(&bulk_waiter->event) != 0) -+ status = VCHIQ_RETRY; -+ else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) -+ status = VCHIQ_ERROR; -+ } -+ -+ return status; -+ -+unlock_both_error_exit: -+ mutex_unlock(&state->slot_mutex); -+cancel_bulk_error_exit: -+ vchiq_complete_bulk(bulk); -+unlock_error_exit: -+ mutex_unlock(&service->bulk_mutex); -+ -+error_exit: -+ if (service) -+ unlock_service(service); -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, -+ const VCHIQ_ELEMENT_T *elements, unsigned int count) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ -+ unsigned int size = 0; -+ unsigned int i; -+ -+ if (!service || -+ (vchiq_check_service(service) != VCHIQ_SUCCESS)) -+ goto error_exit; -+ -+ for (i = 0; i < (unsigned int)count; i++) { -+ if (elements[i].size) { -+ if (elements[i].data == NULL) { -+ VCHIQ_SERVICE_STATS_INC(service, error_count); -+ goto error_exit; -+ } -+ size += elements[i].size; -+ } -+ } -+ -+ if (size > VCHIQ_MAX_MSG_SIZE) { -+ VCHIQ_SERVICE_STATS_INC(service, error_count); -+ goto error_exit; -+ } -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_OPEN: -+ status = queue_message(service->state, service, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, -+ service->localport, -+ service->remoteport), -+ elements, count, size, 1); -+ break; -+ case VCHIQ_SRVSTATE_OPENSYNC: -+ status = queue_message_sync(service->state, service, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, -+ service->localport, -+ service->remoteport), -+ elements, count, size, 1); -+ break; -+ default: -+ status = VCHIQ_ERROR; -+ break; -+ } -+ -+error_exit: -+ if (service) -+ unlock_service(service); -+ -+ return status; -+} -+ -+void -+vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_SHARED_STATE_T *remote; -+ VCHIQ_STATE_T *state; -+ int slot_index; -+ -+ if (!service) -+ return; -+ -+ state = service->state; -+ remote = state->remote; -+ -+ slot_index = SLOT_INDEX_FROM_DATA(state, (void *)header); -+ -+ if ((slot_index >= remote->slot_first) && -+ (slot_index <= remote->slot_last)) { -+ int msgid = header->msgid; -+ if (msgid & VCHIQ_MSGID_CLAIMED) { -+ VCHIQ_SLOT_INFO_T *slot_info = -+ SLOT_INFO_FROM_INDEX(state, slot_index); -+ -+ release_slot(state, slot_info, header, service); -+ } -+ } else if (slot_index == remote->slot_sync) -+ release_message_sync(state, header); -+ -+ unlock_service(service); -+} -+ -+static void -+release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) -+{ -+ header->msgid = VCHIQ_MSGID_PADDING; -+ wmb(); -+ remote_event_signal(&state->remote->sync_release); -+} -+ -+VCHIQ_STATUS_T -+vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, short *peer_version) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ -+ if (!service || -+ (vchiq_check_service(service) != VCHIQ_SUCCESS) || -+ !peer_version) -+ goto exit; -+ *peer_version = service->peer_version; -+ status = VCHIQ_SUCCESS; -+ -+exit: -+ if (service) -+ unlock_service(service); -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_get_config(VCHIQ_INSTANCE_T instance, -+ int config_size, VCHIQ_CONFIG_T *pconfig) -+{ -+ VCHIQ_CONFIG_T config; -+ -+ (void)instance; -+ -+ config.max_msg_size = VCHIQ_MAX_MSG_SIZE; -+ config.bulk_threshold = VCHIQ_MAX_MSG_SIZE; -+ config.max_outstanding_bulks = VCHIQ_NUM_SERVICE_BULKS; -+ config.max_services = VCHIQ_MAX_SERVICES; -+ config.version = VCHIQ_VERSION; -+ config.version_min = VCHIQ_VERSION_MIN; -+ -+ if (config_size > sizeof(VCHIQ_CONFIG_T)) -+ return VCHIQ_ERROR; -+ -+ memcpy(pconfig, &config, -+ min(config_size, (int)(sizeof(VCHIQ_CONFIG_T)))); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+VCHIQ_STATUS_T -+vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, -+ VCHIQ_SERVICE_OPTION_T option, int value) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ -+ if (service) { -+ switch (option) { -+ case VCHIQ_SERVICE_OPTION_AUTOCLOSE: -+ service->auto_close = value; -+ status = VCHIQ_SUCCESS; -+ break; -+ -+ case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &service->state->service_quotas[ -+ service->localport]; -+ if (value == 0) -+ value = service->state->default_slot_quota; -+ if ((value >= service_quota->slot_use_count) && -+ (value < (unsigned short)~0)) { -+ service_quota->slot_quota = value; -+ if ((value >= service_quota->slot_use_count) && -+ (service_quota->message_quota >= -+ service_quota->message_use_count)) { -+ /* Signal the service that it may have -+ ** dropped below its quota */ -+ up(&service_quota->quota_event); -+ } -+ status = VCHIQ_SUCCESS; -+ } -+ } break; -+ -+ case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA: { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &service->state->service_quotas[ -+ service->localport]; -+ if (value == 0) -+ value = service->state->default_message_quota; -+ if ((value >= service_quota->message_use_count) && -+ (value < (unsigned short)~0)) { -+ service_quota->message_quota = value; -+ if ((value >= -+ service_quota->message_use_count) && -+ (service_quota->slot_quota >= -+ service_quota->slot_use_count)) -+ /* Signal the service that it may have -+ ** dropped below its quota */ -+ up(&service_quota->quota_event); -+ status = VCHIQ_SUCCESS; -+ } -+ } break; -+ -+ case VCHIQ_SERVICE_OPTION_SYNCHRONOUS: -+ if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || -+ (service->srvstate == -+ VCHIQ_SRVSTATE_LISTENING)) { -+ service->sync = value; -+ status = VCHIQ_SUCCESS; -+ } -+ break; -+ -+ case VCHIQ_SERVICE_OPTION_TRACE: -+ service->trace = value; -+ status = VCHIQ_SUCCESS; -+ break; -+ -+ default: -+ break; -+ } -+ unlock_service(service); -+ } -+ -+ return status; -+} -+ -+void -+vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state, -+ VCHIQ_SHARED_STATE_T *shared, const char *label) -+{ -+ static const char *const debug_names[] = { -+ "", -+ "SLOT_HANDLER_COUNT", -+ "SLOT_HANDLER_LINE", -+ "PARSE_LINE", -+ "PARSE_HEADER", -+ "PARSE_MSGID", -+ "AWAIT_COMPLETION_LINE", -+ "DEQUEUE_MESSAGE_LINE", -+ "SERVICE_CALLBACK_LINE", -+ "MSG_QUEUE_FULL_COUNT", -+ "COMPLETION_QUEUE_FULL_COUNT" -+ }; -+ int i; -+ -+ char buf[80]; -+ int len; -+ len = snprintf(buf, sizeof(buf), -+ " %s: slots %d-%d tx_pos=%x recycle=%x", -+ label, shared->slot_first, shared->slot_last, -+ shared->tx_pos, shared->slot_queue_recycle); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Slots claimed:"); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ for (i = shared->slot_first; i <= shared->slot_last; i++) { -+ VCHIQ_SLOT_INFO_T slot_info = *SLOT_INFO_FROM_INDEX(state, i); -+ if (slot_info.use_count != slot_info.release_count) { -+ len = snprintf(buf, sizeof(buf), -+ " %d: %d/%d", i, slot_info.use_count, -+ slot_info.release_count); -+ vchiq_dump(dump_context, buf, len + 1); -+ } -+ } -+ -+ for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { -+ len = snprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", -+ debug_names[i], shared->debug[i], shared->debug[i]); -+ vchiq_dump(dump_context, buf, len + 1); -+ } -+} -+ -+void -+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) -+{ -+ char buf[80]; -+ int len; -+ int i; -+ -+ len = snprintf(buf, sizeof(buf), "State %d: %s", state->id, -+ conn_state_names[state->conn_state]); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " tx_pos=%x(@%x), rx_pos=%x(@%x)", -+ state->local->tx_pos, -+ (uint32_t)state->tx_data + -+ (state->local_tx_pos & VCHIQ_SLOT_MASK), -+ state->rx_pos, -+ (uint32_t)state->rx_data + -+ (state->rx_pos & VCHIQ_SLOT_MASK)); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Version: %d (min %d)", -+ VCHIQ_VERSION, VCHIQ_VERSION_MIN); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ if (VCHIQ_ENABLE_STATS) { -+ len = snprintf(buf, sizeof(buf), -+ " Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, " -+ "error_count=%d", -+ state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, -+ state->stats.error_count); -+ vchiq_dump(dump_context, buf, len + 1); -+ } -+ -+ len = snprintf(buf, sizeof(buf), -+ " Slots: %d available (%d data), %d recyclable, %d stalls " -+ "(%d data)", -+ ((state->slot_queue_available * VCHIQ_SLOT_SIZE) - -+ state->local_tx_pos) / VCHIQ_SLOT_SIZE, -+ state->data_quota - state->data_use_count, -+ state->local->slot_queue_recycle - state->slot_queue_available, -+ state->stats.slot_stalls, state->stats.data_stalls); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ vchiq_dump_platform_state(dump_context); -+ -+ vchiq_dump_shared_state(dump_context, state, state->local, "Local"); -+ vchiq_dump_shared_state(dump_context, state, state->remote, "Remote"); -+ -+ vchiq_dump_platform_instances(dump_context); -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = find_service_by_port(state, i); -+ -+ if (service) { -+ vchiq_dump_service_state(dump_context, service); -+ unlock_service(service); -+ } -+ } -+} -+ -+void -+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service) -+{ -+ char buf[80]; -+ int len; -+ -+ len = snprintf(buf, sizeof(buf), "Service %d: %s (ref %u)", -+ service->localport, srvstate_names[service->srvstate], -+ service->ref_count - 1); /*Don't include the lock just taken*/ -+ -+ if (service->srvstate != VCHIQ_SRVSTATE_FREE) { -+ char remoteport[30]; -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &service->state->service_quotas[service->localport]; -+ int fourcc = service->base.fourcc; -+ int tx_pending, rx_pending; -+ if (service->remoteport != VCHIQ_PORT_FREE) { -+ int len2 = snprintf(remoteport, sizeof(remoteport), -+ "%d", service->remoteport); -+ if (service->public_fourcc != VCHIQ_FOURCC_INVALID) -+ snprintf(remoteport + len2, -+ sizeof(remoteport) - len2, -+ " (client %x)", service->client_id); -+ } else -+ strcpy(remoteport, "n/a"); -+ -+ len += snprintf(buf + len, sizeof(buf) - len, -+ " '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)", -+ VCHIQ_FOURCC_AS_4CHARS(fourcc), -+ remoteport, -+ service_quota->message_use_count, -+ service_quota->message_quota, -+ service_quota->slot_use_count, -+ service_quota->slot_quota); -+ -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ tx_pending = service->bulk_tx.local_insert - -+ service->bulk_tx.remote_insert; -+ -+ rx_pending = service->bulk_rx.local_insert - -+ service->bulk_rx.remote_insert; -+ -+ len = snprintf(buf, sizeof(buf), -+ " Bulk: tx_pending=%d (size %d)," -+ " rx_pending=%d (size %d)", -+ tx_pending, -+ tx_pending ? service->bulk_tx.bulks[ -+ BULK_INDEX(service->bulk_tx.remove)].size : 0, -+ rx_pending, -+ rx_pending ? service->bulk_rx.bulks[ -+ BULK_INDEX(service->bulk_rx.remove)].size : 0); -+ -+ if (VCHIQ_ENABLE_STATS) { -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Ctrl: tx_count=%d, tx_bytes=%llu, " -+ "rx_count=%d, rx_bytes=%llu", -+ service->stats.ctrl_tx_count, -+ service->stats.ctrl_tx_bytes, -+ service->stats.ctrl_rx_count, -+ service->stats.ctrl_rx_bytes); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Bulk: tx_count=%d, tx_bytes=%llu, " -+ "rx_count=%d, rx_bytes=%llu", -+ service->stats.bulk_tx_count, -+ service->stats.bulk_tx_bytes, -+ service->stats.bulk_rx_count, -+ service->stats.bulk_rx_bytes); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " %d quota stalls, %d slot stalls, " -+ "%d bulk stalls, %d aborted, %d errors", -+ service->stats.quota_stalls, -+ service->stats.slot_stalls, -+ service->stats.bulk_stalls, -+ service->stats.bulk_aborted_count, -+ service->stats.error_count); -+ } -+ } -+ -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ if (service->srvstate != VCHIQ_SRVSTATE_FREE) -+ vchiq_dump_platform_service_state(dump_context, service); -+} -+ -+ -+void -+vchiq_loud_error_header(void) -+{ -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+ vchiq_log_error(vchiq_core_log_level, "====="); -+} -+ -+void -+vchiq_loud_error_footer(void) -+{ -+ vchiq_log_error(vchiq_core_log_level, "====="); -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+} -+ -+ -+VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_RETRY; -+ if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE, 0, 0), -+ NULL, 0, 0, 0); -+ return status; -+} -+ -+VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_RETRY; -+ if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_RELEASE, 0, 0), -+ NULL, 0, 0, 0); -+ return status; -+} -+ -+VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_RETRY; -+ if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE_ACTIVE, 0, 0), -+ NULL, 0, 0, 0); -+ return status; -+} -+ -+void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, -+ size_t numBytes) -+{ -+ const uint8_t *mem = (const uint8_t *)voidMem; -+ size_t offset; -+ char lineBuf[100]; -+ char *s; -+ -+ while (numBytes > 0) { -+ s = lineBuf; -+ -+ for (offset = 0; offset < 16; offset++) { -+ if (offset < numBytes) -+ s += snprintf(s, 4, "%02x ", mem[offset]); -+ else -+ s += snprintf(s, 4, " "); -+ } -+ -+ for (offset = 0; offset < 16; offset++) { -+ if (offset < numBytes) { -+ uint8_t ch = mem[offset]; -+ -+ if ((ch < ' ') || (ch > '~')) -+ ch = '.'; -+ *s++ = (char)ch; -+ } -+ } -+ *s++ = '\0'; -+ -+ if ((label != NULL) && (*label != '\0')) -+ vchiq_log_trace(VCHIQ_LOG_TRACE, -+ "%s: %08x: %s", label, addr, lineBuf); -+ else -+ vchiq_log_trace(VCHIQ_LOG_TRACE, -+ "%08x: %s", addr, lineBuf); -+ -+ addr += 16; -+ mem += 16; -+ if (numBytes > 16) -+ numBytes -= 16; -+ else -+ numBytes = 0; -+ } -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h -new file mode 100644 -index 0000000000000000000000000000000000000000..9be484c776d044a51bb3904c6a1e2cd11a852e35 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h -@@ -0,0 +1,712 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_CORE_H -+#define VCHIQ_CORE_H -+ -+#include -+#include -+#include -+ -+#include "vchiq_cfg.h" -+ -+#include "vchiq.h" -+ -+/* Run time control of log level, based on KERN_XXX level. */ -+#define VCHIQ_LOG_DEFAULT 4 -+#define VCHIQ_LOG_ERROR 3 -+#define VCHIQ_LOG_WARNING 4 -+#define VCHIQ_LOG_INFO 6 -+#define VCHIQ_LOG_TRACE 7 -+ -+#define VCHIQ_LOG_PREFIX KERN_INFO "vchiq: " -+ -+#ifndef vchiq_log_error -+#define vchiq_log_error(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_ERROR) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+#ifndef vchiq_log_warning -+#define vchiq_log_warning(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_WARNING) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+#ifndef vchiq_log_info -+#define vchiq_log_info(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_INFO) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+#ifndef vchiq_log_trace -+#define vchiq_log_trace(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_TRACE) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+ -+#define vchiq_loud_error(...) \ -+ vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__) -+ -+#ifndef vchiq_static_assert -+#define vchiq_static_assert(cond) __attribute__((unused)) \ -+ extern int vchiq_static_assert[(cond) ? 1 : -1] -+#endif -+ -+#define IS_POW2(x) (x && ((x & (x - 1)) == 0)) -+ -+/* Ensure that the slot size and maximum number of slots are powers of 2 */ -+vchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE)); -+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS)); -+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE)); -+ -+#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) -+#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) -+#define VCHIQ_SLOT_ZERO_SLOTS ((sizeof(VCHIQ_SLOT_ZERO_T) + \ -+ VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE) -+ -+#define VCHIQ_MSG_PADDING 0 /* - */ -+#define VCHIQ_MSG_CONNECT 1 /* - */ -+#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */ -+#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */ -+#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */ -+#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */ -+#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */ -+#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */ -+#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */ -+#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */ -+#define VCHIQ_MSG_PAUSE 10 /* - */ -+#define VCHIQ_MSG_RESUME 11 /* - */ -+#define VCHIQ_MSG_REMOTE_USE 12 /* - */ -+#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */ -+#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */ -+ -+#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1) -+#define VCHIQ_PORT_FREE 0x1000 -+#define VCHIQ_PORT_IS_VALID(port) (port < VCHIQ_PORT_FREE) -+#define VCHIQ_MAKE_MSG(type, srcport, dstport) \ -+ ((type<<24) | (srcport<<12) | (dstport<<0)) -+#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)msgid >> 24) -+#define VCHIQ_MSG_SRCPORT(msgid) \ -+ (unsigned short)(((unsigned int)msgid >> 12) & 0xfff) -+#define VCHIQ_MSG_DSTPORT(msgid) \ -+ ((unsigned short)msgid & 0xfff) -+ -+#define VCHIQ_FOURCC_AS_4CHARS(fourcc) \ -+ ((fourcc) >> 24) & 0xff, \ -+ ((fourcc) >> 16) & 0xff, \ -+ ((fourcc) >> 8) & 0xff, \ -+ (fourcc) & 0xff -+ -+/* Ensure the fields are wide enough */ -+vchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) -+ == 0); -+vchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); -+vchiq_static_assert((unsigned int)VCHIQ_PORT_MAX < -+ (unsigned int)VCHIQ_PORT_FREE); -+ -+#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) -+#define VCHIQ_MSGID_CLAIMED 0x40000000 -+ -+#define VCHIQ_FOURCC_INVALID 0x00000000 -+#define VCHIQ_FOURCC_IS_LEGAL(fourcc) (fourcc != VCHIQ_FOURCC_INVALID) -+ -+#define VCHIQ_BULK_ACTUAL_ABORTED -1 -+ -+typedef uint32_t BITSET_T; -+ -+vchiq_static_assert((sizeof(BITSET_T) * 8) == 32); -+ -+#define BITSET_SIZE(b) ((b + 31) >> 5) -+#define BITSET_WORD(b) (b >> 5) -+#define BITSET_BIT(b) (1 << (b & 31)) -+#define BITSET_ZERO(bs) memset(bs, 0, sizeof(bs)) -+#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) -+#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) -+#define BITSET_CLR(bs, b) (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b)) -+ -+#if VCHIQ_ENABLE_STATS -+#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++) -+#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++) -+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \ -+ (service->stats. stat += addend) -+#else -+#define VCHIQ_STATS_INC(state, stat) ((void)0) -+#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0) -+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0) -+#endif -+ -+enum { -+ DEBUG_ENTRIES, -+#if VCHIQ_ENABLE_DEBUG -+ DEBUG_SLOT_HANDLER_COUNT, -+ DEBUG_SLOT_HANDLER_LINE, -+ DEBUG_PARSE_LINE, -+ DEBUG_PARSE_HEADER, -+ DEBUG_PARSE_MSGID, -+ DEBUG_AWAIT_COMPLETION_LINE, -+ DEBUG_DEQUEUE_MESSAGE_LINE, -+ DEBUG_SERVICE_CALLBACK_LINE, -+ DEBUG_MSG_QUEUE_FULL_COUNT, -+ DEBUG_COMPLETION_QUEUE_FULL_COUNT, -+#endif -+ DEBUG_MAX -+}; -+ -+#if VCHIQ_ENABLE_DEBUG -+ -+#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug; -+#define DEBUG_TRACE(d) \ -+ do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0) -+#define DEBUG_VALUE(d, v) \ -+ do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0) -+#define DEBUG_COUNT(d) \ -+ do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0) -+ -+#else /* VCHIQ_ENABLE_DEBUG */ -+ -+#define DEBUG_INITIALISE(local) -+#define DEBUG_TRACE(d) -+#define DEBUG_VALUE(d, v) -+#define DEBUG_COUNT(d) -+ -+#endif /* VCHIQ_ENABLE_DEBUG */ -+ -+typedef enum { -+ VCHIQ_CONNSTATE_DISCONNECTED, -+ VCHIQ_CONNSTATE_CONNECTING, -+ VCHIQ_CONNSTATE_CONNECTED, -+ VCHIQ_CONNSTATE_PAUSING, -+ VCHIQ_CONNSTATE_PAUSE_SENT, -+ VCHIQ_CONNSTATE_PAUSED, -+ VCHIQ_CONNSTATE_RESUMING, -+ VCHIQ_CONNSTATE_PAUSE_TIMEOUT, -+ VCHIQ_CONNSTATE_RESUME_TIMEOUT -+} VCHIQ_CONNSTATE_T; -+ -+enum { -+ VCHIQ_SRVSTATE_FREE, -+ VCHIQ_SRVSTATE_HIDDEN, -+ VCHIQ_SRVSTATE_LISTENING, -+ VCHIQ_SRVSTATE_OPENING, -+ VCHIQ_SRVSTATE_OPEN, -+ VCHIQ_SRVSTATE_OPENSYNC, -+ VCHIQ_SRVSTATE_CLOSESENT, -+ VCHIQ_SRVSTATE_CLOSERECVD, -+ VCHIQ_SRVSTATE_CLOSEWAIT, -+ VCHIQ_SRVSTATE_CLOSED -+}; -+ -+enum { -+ VCHIQ_POLL_TERMINATE, -+ VCHIQ_POLL_REMOVE, -+ VCHIQ_POLL_TXNOTIFY, -+ VCHIQ_POLL_RXNOTIFY, -+ VCHIQ_POLL_COUNT -+}; -+ -+typedef enum { -+ VCHIQ_BULK_TRANSMIT, -+ VCHIQ_BULK_RECEIVE -+} VCHIQ_BULK_DIR_T; -+ -+typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata); -+ -+typedef struct vchiq_bulk_struct { -+ short mode; -+ short dir; -+ void *userdata; -+ VCHI_MEM_HANDLE_T handle; -+ void *data; -+ int size; -+ void *remote_data; -+ int remote_size; -+ int actual; -+} VCHIQ_BULK_T; -+ -+typedef struct vchiq_bulk_queue_struct { -+ int local_insert; /* Where to insert the next local bulk */ -+ int remote_insert; /* Where to insert the next remote bulk (master) */ -+ int process; /* Bulk to transfer next */ -+ int remote_notify; /* Bulk to notify the remote client of next (mstr) */ -+ int remove; /* Bulk to notify the local client of, and remove, -+ ** next */ -+ VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS]; -+} VCHIQ_BULK_QUEUE_T; -+ -+typedef struct remote_event_struct { -+ int armed; -+ int fired; -+ struct semaphore *event; -+} REMOTE_EVENT_T; -+ -+typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T; -+ -+typedef struct vchiq_state_struct VCHIQ_STATE_T; -+ -+typedef struct vchiq_slot_struct { -+ char data[VCHIQ_SLOT_SIZE]; -+} VCHIQ_SLOT_T; -+ -+typedef struct vchiq_slot_info_struct { -+ /* Use two counters rather than one to avoid the need for a mutex. */ -+ short use_count; -+ short release_count; -+} VCHIQ_SLOT_INFO_T; -+ -+typedef struct vchiq_service_struct { -+ VCHIQ_SERVICE_BASE_T base; -+ VCHIQ_SERVICE_HANDLE_T handle; -+ unsigned int ref_count; -+ int srvstate; -+ VCHIQ_USERDATA_TERM_T userdata_term; -+ unsigned int localport; -+ unsigned int remoteport; -+ int public_fourcc; -+ int client_id; -+ char auto_close; -+ char sync; -+ char closing; -+ char trace; -+ atomic_t poll_flags; -+ short version; -+ short version_min; -+ short peer_version; -+ -+ VCHIQ_STATE_T *state; -+ VCHIQ_INSTANCE_T instance; -+ -+ int service_use_count; -+ -+ VCHIQ_BULK_QUEUE_T bulk_tx; -+ VCHIQ_BULK_QUEUE_T bulk_rx; -+ -+ struct semaphore remove_event; -+ struct semaphore bulk_remove_event; -+ struct mutex bulk_mutex; -+ -+ struct service_stats_struct { -+ int quota_stalls; -+ int slot_stalls; -+ int bulk_stalls; -+ int error_count; -+ int ctrl_tx_count; -+ int ctrl_rx_count; -+ int bulk_tx_count; -+ int bulk_rx_count; -+ int bulk_aborted_count; -+ uint64_t ctrl_tx_bytes; -+ uint64_t ctrl_rx_bytes; -+ uint64_t bulk_tx_bytes; -+ uint64_t bulk_rx_bytes; -+ } stats; -+} VCHIQ_SERVICE_T; -+ -+/* The quota information is outside VCHIQ_SERVICE_T so that it can be -+ statically allocated, since for accounting reasons a service's slot -+ usage is carried over between users of the same port number. -+ */ -+typedef struct vchiq_service_quota_struct { -+ unsigned short slot_quota; -+ unsigned short slot_use_count; -+ unsigned short message_quota; -+ unsigned short message_use_count; -+ struct semaphore quota_event; -+ int previous_tx_index; -+} VCHIQ_SERVICE_QUOTA_T; -+ -+typedef struct vchiq_shared_state_struct { -+ -+ /* A non-zero value here indicates that the content is valid. */ -+ int initialised; -+ -+ /* The first and last (inclusive) slots allocated to the owner. */ -+ int slot_first; -+ int slot_last; -+ -+ /* The slot allocated to synchronous messages from the owner. */ -+ int slot_sync; -+ -+ /* Signalling this event indicates that owner's slot handler thread -+ ** should run. */ -+ REMOTE_EVENT_T trigger; -+ -+ /* Indicates the byte position within the stream where the next message -+ ** will be written. The least significant bits are an index into the -+ ** slot. The next bits are the index of the slot in slot_queue. */ -+ int tx_pos; -+ -+ /* This event should be signalled when a slot is recycled. */ -+ REMOTE_EVENT_T recycle; -+ -+ /* The slot_queue index where the next recycled slot will be written. */ -+ int slot_queue_recycle; -+ -+ /* This event should be signalled when a synchronous message is sent. */ -+ REMOTE_EVENT_T sync_trigger; -+ -+ /* This event should be signalled when a synchronous message has been -+ ** released. */ -+ REMOTE_EVENT_T sync_release; -+ -+ /* A circular buffer of slot indexes. */ -+ int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; -+ -+ /* Debugging state */ -+ int debug[DEBUG_MAX]; -+} VCHIQ_SHARED_STATE_T; -+ -+typedef struct vchiq_slot_zero_struct { -+ int magic; -+ short version; -+ short version_min; -+ int slot_zero_size; -+ int slot_size; -+ int max_slots; -+ int max_slots_per_side; -+ int platform_data[2]; -+ VCHIQ_SHARED_STATE_T master; -+ VCHIQ_SHARED_STATE_T slave; -+ VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS]; -+} VCHIQ_SLOT_ZERO_T; -+ -+struct vchiq_state_struct { -+ int id; -+ int initialised; -+ VCHIQ_CONNSTATE_T conn_state; -+ int is_master; -+ short version_common; -+ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_SHARED_STATE_T *remote; -+ VCHIQ_SLOT_T *slot_data; -+ -+ unsigned short default_slot_quota; -+ unsigned short default_message_quota; -+ -+ /* Event indicating connect message received */ -+ struct semaphore connect; -+ -+ /* Mutex protecting services */ -+ struct mutex mutex; -+ VCHIQ_INSTANCE_T *instance; -+ -+ /* Processes incoming messages */ -+ struct task_struct *slot_handler_thread; -+ -+ /* Processes recycled slots */ -+ struct task_struct *recycle_thread; -+ -+ /* Processes synchronous messages */ -+ struct task_struct *sync_thread; -+ -+ /* Local implementation of the trigger remote event */ -+ struct semaphore trigger_event; -+ -+ /* Local implementation of the recycle remote event */ -+ struct semaphore recycle_event; -+ -+ /* Local implementation of the sync trigger remote event */ -+ struct semaphore sync_trigger_event; -+ -+ /* Local implementation of the sync release remote event */ -+ struct semaphore sync_release_event; -+ -+ char *tx_data; -+ char *rx_data; -+ VCHIQ_SLOT_INFO_T *rx_info; -+ -+ struct mutex slot_mutex; -+ -+ struct mutex recycle_mutex; -+ -+ struct mutex sync_mutex; -+ -+ struct mutex bulk_transfer_mutex; -+ -+ /* Indicates the byte position within the stream from where the next -+ ** message will be read. The least significant bits are an index into -+ ** the slot.The next bits are the index of the slot in -+ ** remote->slot_queue. */ -+ int rx_pos; -+ -+ /* A cached copy of local->tx_pos. Only write to local->tx_pos, and read -+ from remote->tx_pos. */ -+ int local_tx_pos; -+ -+ /* The slot_queue index of the slot to become available next. */ -+ int slot_queue_available; -+ -+ /* A flag to indicate if any poll has been requested */ -+ int poll_needed; -+ -+ /* Ths index of the previous slot used for data messages. */ -+ int previous_data_index; -+ -+ /* The number of slots occupied by data messages. */ -+ unsigned short data_use_count; -+ -+ /* The maximum number of slots to be occupied by data messages. */ -+ unsigned short data_quota; -+ -+ /* An array of bit sets indicating which services must be polled. */ -+ atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; -+ -+ /* The number of the first unused service */ -+ int unused_service; -+ -+ /* Signalled when a free slot becomes available. */ -+ struct semaphore slot_available_event; -+ -+ struct semaphore slot_remove_event; -+ -+ /* Signalled when a free data slot becomes available. */ -+ struct semaphore data_quota_event; -+ -+ /* Incremented when there are bulk transfers which cannot be processed -+ * whilst paused and must be processed on resume */ -+ int deferred_bulks; -+ -+ struct state_stats_struct { -+ int slot_stalls; -+ int data_stalls; -+ int ctrl_tx_count; -+ int ctrl_rx_count; -+ int error_count; -+ } stats; -+ -+ VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES]; -+ VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES]; -+ VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS]; -+ -+ VCHIQ_PLATFORM_STATE_T platform_state; -+}; -+ -+struct bulk_waiter { -+ VCHIQ_BULK_T *bulk; -+ struct semaphore event; -+ int actual; -+}; -+ -+extern spinlock_t bulk_waiter_spinlock; -+ -+extern int vchiq_core_log_level; -+extern int vchiq_core_msg_log_level; -+extern int vchiq_sync_log_level; -+ -+extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; -+ -+extern const char * -+get_conn_state_name(VCHIQ_CONNSTATE_T conn_state); -+ -+extern VCHIQ_SLOT_ZERO_T * -+vchiq_init_slots(void *mem_base, int mem_size); -+ -+extern VCHIQ_STATUS_T -+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, -+ int is_master); -+ -+extern VCHIQ_STATUS_T -+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); -+ -+extern VCHIQ_SERVICE_T * -+vchiq_add_service_internal(VCHIQ_STATE_T *state, -+ const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, -+ VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term); -+ -+extern VCHIQ_STATUS_T -+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id); -+ -+extern VCHIQ_STATUS_T -+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd); -+ -+extern void -+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_free_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); -+ -+extern VCHIQ_STATUS_T -+vchiq_pause_internal(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_resume_internal(VCHIQ_STATE_T *state); -+ -+extern void -+remote_event_pollall(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir); -+ -+extern void -+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_loud_error_header(void); -+ -+extern void -+vchiq_loud_error_footer(void); -+ -+extern void -+request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type); -+ -+static inline VCHIQ_SERVICE_T * -+handle_to_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & -+ (VCHIQ_MAX_STATES - 1)]; -+ if (!state) -+ return NULL; -+ -+ return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; -+} -+ -+extern VCHIQ_SERVICE_T * -+find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_SERVICE_T * -+find_service_by_port(VCHIQ_STATE_T *state, int localport); -+ -+extern VCHIQ_SERVICE_T * -+find_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_SERVICE_T * -+find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_SERVICE_T * -+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, -+ int *pidx); -+ -+extern void -+lock_service(VCHIQ_SERVICE_T *service); -+ -+extern void -+unlock_service(VCHIQ_SERVICE_T *service); -+ -+/* The following functions are called from vchiq_core, and external -+** implementations must be provided. */ -+ -+extern VCHIQ_STATUS_T -+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, -+ VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir); -+ -+extern void -+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk); -+ -+extern void -+vchiq_complete_bulk(VCHIQ_BULK_T *bulk); -+ -+extern VCHIQ_STATUS_T -+vchiq_copy_from_user(void *dst, const void *src, int size); -+ -+extern void -+remote_event_signal(REMOTE_EVENT_T *event); -+ -+void -+vchiq_platform_check_suspend(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_platform_paused(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_platform_resume(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_platform_resumed(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_dump(void *dump_context, const char *str, int len); -+ -+extern void -+vchiq_dump_platform_state(void *dump_context); -+ -+extern void -+vchiq_dump_platform_instances(void *dump_context); -+ -+extern void -+vchiq_dump_platform_service_state(void *dump_context, -+ VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_use_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_release_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_on_remote_use(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_on_remote_release(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_platform_init_state(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_check_service(VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_on_remote_use_active(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_send_remote_use(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_send_remote_release(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_send_remote_use_active(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, -+ VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); -+ -+extern void -+vchiq_platform_handle_timeout(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate); -+ -+ -+extern void -+vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, -+ size_t numBytes); -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c -new file mode 100644 -index 0000000000000000000000000000000000000000..7e032130d967a69384926ddbe614e9af4be8f22e ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c -@@ -0,0 +1,383 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+ -+#include -+#include "vchiq_core.h" -+#include "vchiq_arm.h" -+#include "vchiq_debugfs.h" -+ -+#ifdef CONFIG_DEBUG_FS -+ -+/**************************************************************************** -+* -+* log category entries -+* -+***************************************************************************/ -+#define DEBUGFS_WRITE_BUF_SIZE 256 -+ -+#define VCHIQ_LOG_ERROR_STR "error" -+#define VCHIQ_LOG_WARNING_STR "warning" -+#define VCHIQ_LOG_INFO_STR "info" -+#define VCHIQ_LOG_TRACE_STR "trace" -+ -+ -+/* Top-level debug info */ -+struct vchiq_debugfs_info { -+ /* Global 'vchiq' debugfs entry used by all instances */ -+ struct dentry *vchiq_cfg_dir; -+ -+ /* one entry per client process */ -+ struct dentry *clients; -+ -+ /* log categories */ -+ struct dentry *log_categories; -+}; -+ -+static struct vchiq_debugfs_info debugfs_info; -+ -+/* Log category debugfs entries */ -+struct vchiq_debugfs_log_entry { -+ const char *name; -+ int *plevel; -+ struct dentry *dir; -+}; -+ -+static struct vchiq_debugfs_log_entry vchiq_debugfs_log_entries[] = { -+ { "core", &vchiq_core_log_level }, -+ { "msg", &vchiq_core_msg_log_level }, -+ { "sync", &vchiq_sync_log_level }, -+ { "susp", &vchiq_susp_log_level }, -+ { "arm", &vchiq_arm_log_level }, -+}; -+static int n_log_entries = -+ sizeof(vchiq_debugfs_log_entries)/sizeof(vchiq_debugfs_log_entries[0]); -+ -+ -+static struct dentry *vchiq_clients_top(void); -+static struct dentry *vchiq_debugfs_top(void); -+ -+static int debugfs_log_show(struct seq_file *f, void *offset) -+{ -+ int *levp = f->private; -+ char *log_value = NULL; -+ -+ switch (*levp) { -+ case VCHIQ_LOG_ERROR: -+ log_value = VCHIQ_LOG_ERROR_STR; -+ break; -+ case VCHIQ_LOG_WARNING: -+ log_value = VCHIQ_LOG_WARNING_STR; -+ break; -+ case VCHIQ_LOG_INFO: -+ log_value = VCHIQ_LOG_INFO_STR; -+ break; -+ case VCHIQ_LOG_TRACE: -+ log_value = VCHIQ_LOG_TRACE_STR; -+ break; -+ default: -+ break; -+ } -+ -+ seq_printf(f, "%s\n", log_value ? log_value : "(null)"); -+ -+ return 0; -+} -+ -+static int debugfs_log_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, debugfs_log_show, inode->i_private); -+} -+ -+static int debugfs_log_write(struct file *file, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct seq_file *f = (struct seq_file *)file->private_data; -+ int *levp = f->private; -+ char kbuf[DEBUGFS_WRITE_BUF_SIZE + 1]; -+ -+ memset(kbuf, 0, DEBUGFS_WRITE_BUF_SIZE + 1); -+ if (count >= DEBUGFS_WRITE_BUF_SIZE) -+ count = DEBUGFS_WRITE_BUF_SIZE; -+ -+ if (copy_from_user(kbuf, buffer, count) != 0) -+ return -EFAULT; -+ kbuf[count - 1] = 0; -+ -+ if (strncmp("error", kbuf, strlen("error")) == 0) -+ *levp = VCHIQ_LOG_ERROR; -+ else if (strncmp("warning", kbuf, strlen("warning")) == 0) -+ *levp = VCHIQ_LOG_WARNING; -+ else if (strncmp("info", kbuf, strlen("info")) == 0) -+ *levp = VCHIQ_LOG_INFO; -+ else if (strncmp("trace", kbuf, strlen("trace")) == 0) -+ *levp = VCHIQ_LOG_TRACE; -+ else -+ *levp = VCHIQ_LOG_DEFAULT; -+ -+ *ppos += count; -+ -+ return count; -+} -+ -+static const struct file_operations debugfs_log_fops = { -+ .owner = THIS_MODULE, -+ .open = debugfs_log_open, -+ .write = debugfs_log_write, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+/* create an entry under /vchiq/log for each log category */ -+static int vchiq_debugfs_create_log_entries(struct dentry *top) -+{ -+ struct dentry *dir; -+ size_t i; -+ int ret = 0; -+ dir = debugfs_create_dir("log", vchiq_debugfs_top()); -+ if (!dir) -+ return -ENOMEM; -+ debugfs_info.log_categories = dir; -+ -+ for (i = 0; i < n_log_entries; i++) { -+ void *levp = (void *)vchiq_debugfs_log_entries[i].plevel; -+ dir = debugfs_create_file(vchiq_debugfs_log_entries[i].name, -+ 0644, -+ debugfs_info.log_categories, -+ levp, -+ &debugfs_log_fops); -+ if (!dir) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ vchiq_debugfs_log_entries[i].dir = dir; -+ } -+ return ret; -+} -+ -+static int debugfs_usecount_show(struct seq_file *f, void *offset) -+{ -+ VCHIQ_INSTANCE_T instance = f->private; -+ int use_count; -+ -+ use_count = vchiq_instance_get_use_count(instance); -+ seq_printf(f, "%d\n", use_count); -+ -+ return 0; -+} -+ -+static int debugfs_usecount_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, debugfs_usecount_show, inode->i_private); -+} -+ -+static const struct file_operations debugfs_usecount_fops = { -+ .owner = THIS_MODULE, -+ .open = debugfs_usecount_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static int debugfs_trace_show(struct seq_file *f, void *offset) -+{ -+ VCHIQ_INSTANCE_T instance = f->private; -+ int trace; -+ -+ trace = vchiq_instance_get_trace(instance); -+ seq_printf(f, "%s\n", trace ? "Y" : "N"); -+ -+ return 0; -+} -+ -+static int debugfs_trace_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, debugfs_trace_show, inode->i_private); -+} -+ -+static int debugfs_trace_write(struct file *file, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct seq_file *f = (struct seq_file *)file->private_data; -+ VCHIQ_INSTANCE_T instance = f->private; -+ char firstchar; -+ -+ if (copy_from_user(&firstchar, buffer, 1) != 0) -+ return -EFAULT; -+ -+ switch (firstchar) { -+ case 'Y': -+ case 'y': -+ case '1': -+ vchiq_instance_set_trace(instance, 1); -+ break; -+ case 'N': -+ case 'n': -+ case '0': -+ vchiq_instance_set_trace(instance, 0); -+ break; -+ default: -+ break; -+ } -+ -+ *ppos += count; -+ -+ return count; -+} -+ -+static const struct file_operations debugfs_trace_fops = { -+ .owner = THIS_MODULE, -+ .open = debugfs_trace_open, -+ .write = debugfs_trace_write, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+/* add an instance (process) to the debugfs entries */ -+int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) -+{ -+ char pidstr[16]; -+ struct dentry *top, *use_count, *trace; -+ struct dentry *clients = vchiq_clients_top(); -+ -+ snprintf(pidstr, sizeof(pidstr), "%d", -+ vchiq_instance_get_pid(instance)); -+ -+ top = debugfs_create_dir(pidstr, clients); -+ if (!top) -+ goto fail_top; -+ -+ use_count = debugfs_create_file("use_count", -+ 0444, top, -+ instance, -+ &debugfs_usecount_fops); -+ if (!use_count) -+ goto fail_use_count; -+ -+ trace = debugfs_create_file("trace", -+ 0644, top, -+ instance, -+ &debugfs_trace_fops); -+ if (!trace) -+ goto fail_trace; -+ -+ vchiq_instance_get_debugfs_node(instance)->dentry = top; -+ -+ return 0; -+ -+fail_trace: -+ debugfs_remove(use_count); -+fail_use_count: -+ debugfs_remove(top); -+fail_top: -+ return -ENOMEM; -+} -+ -+void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_DEBUGFS_NODE_T *node = vchiq_instance_get_debugfs_node(instance); -+ debugfs_remove_recursive(node->dentry); -+} -+ -+ -+int vchiq_debugfs_init(void) -+{ -+ BUG_ON(debugfs_info.vchiq_cfg_dir != NULL); -+ -+ debugfs_info.vchiq_cfg_dir = debugfs_create_dir("vchiq", NULL); -+ if (debugfs_info.vchiq_cfg_dir == NULL) -+ goto fail; -+ -+ debugfs_info.clients = debugfs_create_dir("clients", -+ vchiq_debugfs_top()); -+ if (!debugfs_info.clients) -+ goto fail; -+ -+ if (vchiq_debugfs_create_log_entries(vchiq_debugfs_top()) != 0) -+ goto fail; -+ -+ return 0; -+ -+fail: -+ vchiq_debugfs_deinit(); -+ vchiq_log_error(vchiq_arm_log_level, -+ "%s: failed to create debugfs directory", -+ __func__); -+ -+ return -ENOMEM; -+} -+ -+/* remove all the debugfs entries */ -+void vchiq_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vchiq_debugfs_top()); -+} -+ -+static struct dentry *vchiq_clients_top(void) -+{ -+ return debugfs_info.clients; -+} -+ -+static struct dentry *vchiq_debugfs_top(void) -+{ -+ BUG_ON(debugfs_info.vchiq_cfg_dir == NULL); -+ return debugfs_info.vchiq_cfg_dir; -+} -+ -+#else /* CONFIG_DEBUG_FS */ -+ -+int vchiq_debugfs_init(void) -+{ -+ return 0; -+} -+ -+void vchiq_debugfs_deinit(void) -+{ -+} -+ -+int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) -+{ -+ return 0; -+} -+ -+void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) -+{ -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4d6a3788e9c508c9eb1379980c4f3a67791e428e ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h -@@ -0,0 +1,52 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_DEBUGFS_H -+#define VCHIQ_DEBUGFS_H -+ -+#include "vchiq_core.h" -+ -+typedef struct vchiq_debugfs_node_struct -+{ -+ struct dentry *dentry; -+} VCHIQ_DEBUGFS_NODE_T; -+ -+int vchiq_debugfs_init(void); -+ -+void vchiq_debugfs_deinit(void); -+ -+int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance); -+ -+void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance); -+ -+#endif /* VCHIQ_DEBUGFS_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion -new file mode 100644 -index 0000000000000000000000000000000000000000..9f5b6344b9b77f72ebd4ff6621c90fd0ac47efb1 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion -@@ -0,0 +1,87 @@ -+#!/usr/bin/perl -w -+ -+use strict; -+ -+# -+# Generate a version from available information -+# -+ -+my $prefix = shift @ARGV; -+my $root = shift @ARGV; -+ -+ -+if ( not defined $root ) { -+ die "usage: $0 prefix root-dir\n"; -+} -+ -+if ( ! -d $root ) { -+ die "root directory $root not found\n"; -+} -+ -+my $version = "unknown"; -+my $tainted = ""; -+ -+if ( -d "$root/.git" ) { -+ # attempt to work out git version. only do so -+ # on a linux build host, as cygwin builds are -+ # already slow enough -+ -+ if ( -f "/usr/bin/git" || -f "/usr/local/bin/git" ) { -+ if (not open(F, "git --git-dir $root/.git rev-parse --verify HEAD|")) { -+ $version = "no git version"; -+ } -+ else { -+ $version = ; -+ $version =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). -+ $version =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). -+ } -+ -+ if (open(G, "git --git-dir $root/.git status --porcelain|")) { -+ $tainted = ; -+ $tainted =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). -+ $tainted =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). -+ if (length $tainted) { -+ $version = join ' ', $version, "(tainted)"; -+ } -+ else { -+ $version = join ' ', $version, "(clean)"; -+ } -+ } -+ } -+} -+ -+my $hostname = `hostname`; -+$hostname =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). -+$hostname =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). -+ -+ -+print STDERR "Version $version\n"; -+print < -+ -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_hostname, "$hostname" ); -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_version, "$version" ); -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_time, __TIME__ ); -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_date, __DATE__ ); -+ -+const char *vchiq_get_build_hostname( void ) -+{ -+ return vchiq_build_hostname; -+} -+ -+const char *vchiq_get_build_version( void ) -+{ -+ return vchiq_build_version; -+} -+ -+const char *vchiq_get_build_date( void ) -+{ -+ return vchiq_build_date; -+} -+ -+const char *vchiq_get_build_time( void ) -+{ -+ return vchiq_build_time; -+} -+EOF -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h -new file mode 100644 -index 0000000000000000000000000000000000000000..8067bbe7ce8d70c41b2e6e0466d20a4612e39d93 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h -@@ -0,0 +1,189 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_IF_H -+#define VCHIQ_IF_H -+ -+#include "interface/vchi/vchi_mh.h" -+ -+#define VCHIQ_SERVICE_HANDLE_INVALID 0 -+ -+#define VCHIQ_SLOT_SIZE 4096 -+#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T)) -+#define VCHIQ_CHANNEL_SIZE VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */ -+ -+#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ -+ (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) -+#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service) -+#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service) -+ -+typedef enum { -+ VCHIQ_SERVICE_OPENED, /* service, -, - */ -+ VCHIQ_SERVICE_CLOSED, /* service, -, - */ -+ VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */ -+ VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */ -+ VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */ -+ VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */ -+ VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */ -+} VCHIQ_REASON_T; -+ -+typedef enum { -+ VCHIQ_ERROR = -1, -+ VCHIQ_SUCCESS = 0, -+ VCHIQ_RETRY = 1 -+} VCHIQ_STATUS_T; -+ -+typedef enum { -+ VCHIQ_BULK_MODE_CALLBACK, -+ VCHIQ_BULK_MODE_BLOCKING, -+ VCHIQ_BULK_MODE_NOCALLBACK, -+ VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */ -+} VCHIQ_BULK_MODE_T; -+ -+typedef enum { -+ VCHIQ_SERVICE_OPTION_AUTOCLOSE, -+ VCHIQ_SERVICE_OPTION_SLOT_QUOTA, -+ VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, -+ VCHIQ_SERVICE_OPTION_SYNCHRONOUS, -+ VCHIQ_SERVICE_OPTION_TRACE -+} VCHIQ_SERVICE_OPTION_T; -+ -+typedef struct vchiq_header_struct { -+ /* The message identifier - opaque to applications. */ -+ int msgid; -+ -+ /* Size of message data. */ -+ unsigned int size; -+ -+ char data[0]; /* message */ -+} VCHIQ_HEADER_T; -+ -+typedef struct { -+ const void *data; -+ unsigned int size; -+} VCHIQ_ELEMENT_T; -+ -+typedef unsigned int VCHIQ_SERVICE_HANDLE_T; -+ -+typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *, -+ VCHIQ_SERVICE_HANDLE_T, void *); -+ -+typedef struct vchiq_service_base_struct { -+ int fourcc; -+ VCHIQ_CALLBACK_T callback; -+ void *userdata; -+} VCHIQ_SERVICE_BASE_T; -+ -+typedef struct vchiq_service_params_struct { -+ int fourcc; -+ VCHIQ_CALLBACK_T callback; -+ void *userdata; -+ short version; /* Increment for non-trivial changes */ -+ short version_min; /* Update for incompatible changes */ -+} VCHIQ_SERVICE_PARAMS_T; -+ -+typedef struct vchiq_config_struct { -+ unsigned int max_msg_size; -+ unsigned int bulk_threshold; /* The message size above which it -+ is better to use a bulk transfer -+ (<= max_msg_size) */ -+ unsigned int max_outstanding_bulks; -+ unsigned int max_services; -+ short version; /* The version of VCHIQ */ -+ short version_min; /* The minimum compatible version of VCHIQ */ -+} VCHIQ_CONFIG_T; -+ -+typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T; -+typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg); -+ -+extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance); -+extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance); -+extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance); -+extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *pservice); -+extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *pservice); -+extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_use_service_no_resume( -+ VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service); -+ -+extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service, -+ const VCHIQ_ELEMENT_T *elements, unsigned int count); -+extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service, -+ VCHIQ_HEADER_T *header); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, -+ const void *data, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, -+ void *data, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit_handle( -+ VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, -+ const void *offset, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive_handle( -+ VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, -+ void *offset, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, -+ const void *data, unsigned int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode); -+extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, -+ void *data, unsigned int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode); -+extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service, -+ VCHI_MEM_HANDLE_T handle, const void *offset, unsigned int size, -+ void *userdata, VCHIQ_BULK_MODE_T mode); -+extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service, -+ VCHI_MEM_HANDLE_T handle, void *offset, unsigned int size, -+ void *userdata, VCHIQ_BULK_MODE_T mode); -+extern int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service); -+extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service); -+extern int vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance, -+ int config_size, VCHIQ_CONFIG_T *pconfig); -+extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service, -+ VCHIQ_SERVICE_OPTION_T option, int value); -+ -+extern VCHIQ_STATUS_T vchiq_remote_use(VCHIQ_INSTANCE_T instance, -+ VCHIQ_REMOTE_USE_CALLBACK_T callback, void *cb_arg); -+extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance); -+ -+extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service, -+ void *ptr, size_t num_bytes); -+ -+extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, -+ short *peer_version); -+ -+#endif /* VCHIQ_IF_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h -new file mode 100644 -index 0000000000000000000000000000000000000000..6137ae9de1c19cb0ffc486dc60505061a10aea6c ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h -@@ -0,0 +1,131 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_IOCTLS_H -+#define VCHIQ_IOCTLS_H -+ -+#include -+#include "vchiq_if.h" -+ -+#define VCHIQ_IOC_MAGIC 0xc4 -+#define VCHIQ_INVALID_HANDLE (~0) -+ -+typedef struct { -+ VCHIQ_SERVICE_PARAMS_T params; -+ int is_open; -+ int is_vchi; -+ unsigned int handle; /* OUT */ -+} VCHIQ_CREATE_SERVICE_T; -+ -+typedef struct { -+ unsigned int handle; -+ unsigned int count; -+ const VCHIQ_ELEMENT_T *elements; -+} VCHIQ_QUEUE_MESSAGE_T; -+ -+typedef struct { -+ unsigned int handle; -+ void *data; -+ unsigned int size; -+ void *userdata; -+ VCHIQ_BULK_MODE_T mode; -+} VCHIQ_QUEUE_BULK_TRANSFER_T; -+ -+typedef struct { -+ VCHIQ_REASON_T reason; -+ VCHIQ_HEADER_T *header; -+ void *service_userdata; -+ void *bulk_userdata; -+} VCHIQ_COMPLETION_DATA_T; -+ -+typedef struct { -+ unsigned int count; -+ VCHIQ_COMPLETION_DATA_T *buf; -+ unsigned int msgbufsize; -+ unsigned int msgbufcount; /* IN/OUT */ -+ void **msgbufs; -+} VCHIQ_AWAIT_COMPLETION_T; -+ -+typedef struct { -+ unsigned int handle; -+ int blocking; -+ unsigned int bufsize; -+ void *buf; -+} VCHIQ_DEQUEUE_MESSAGE_T; -+ -+typedef struct { -+ unsigned int config_size; -+ VCHIQ_CONFIG_T *pconfig; -+} VCHIQ_GET_CONFIG_T; -+ -+typedef struct { -+ unsigned int handle; -+ VCHIQ_SERVICE_OPTION_T option; -+ int value; -+} VCHIQ_SET_SERVICE_OPTION_T; -+ -+typedef struct { -+ void *virt_addr; -+ size_t num_bytes; -+} VCHIQ_DUMP_MEM_T; -+ -+#define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0) -+#define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1) -+#define VCHIQ_IOC_CREATE_SERVICE \ -+ _IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T) -+#define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3) -+#define VCHIQ_IOC_QUEUE_MESSAGE \ -+ _IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T) -+#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \ -+ _IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T) -+#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \ -+ _IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T) -+#define VCHIQ_IOC_AWAIT_COMPLETION \ -+ _IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T) -+#define VCHIQ_IOC_DEQUEUE_MESSAGE \ -+ _IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T) -+#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9) -+#define VCHIQ_IOC_GET_CONFIG \ -+ _IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T) -+#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11) -+#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12) -+#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13) -+#define VCHIQ_IOC_SET_SERVICE_OPTION \ -+ _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T) -+#define VCHIQ_IOC_DUMP_PHYS_MEM \ -+ _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T) -+#define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16) -+#define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17) -+#define VCHIQ_IOC_MAX 17 -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c -new file mode 100644 -index 0000000000000000000000000000000000000000..25e7011edc5094372919d7e3be482f3bbd7b6155 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c -@@ -0,0 +1,458 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+ -+#include -+#include -+#include -+ -+#include "vchiq_core.h" -+#include "vchiq_arm.h" -+#include "vchiq_killable.h" -+ -+/* ---- Public Variables ------------------------------------------------- */ -+ -+/* ---- Private Constants and Types -------------------------------------- */ -+ -+struct bulk_waiter_node { -+ struct bulk_waiter bulk_waiter; -+ int pid; -+ struct list_head list; -+}; -+ -+struct vchiq_instance_struct { -+ VCHIQ_STATE_T *state; -+ -+ int connected; -+ -+ struct list_head bulk_waiter_list; -+ struct mutex bulk_waiter_list_mutex; -+}; -+ -+static VCHIQ_STATUS_T -+vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, VCHIQ_BULK_DIR_T dir); -+ -+/**************************************************************************** -+* -+* vchiq_initialise -+* -+***************************************************************************/ -+#define VCHIQ_INIT_RETRIES 10 -+VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_STATE_T *state; -+ VCHIQ_INSTANCE_T instance = NULL; -+ int i; -+ -+ vchiq_log_trace(vchiq_core_log_level, "%s called", __func__); -+ -+ /* VideoCore may not be ready due to boot up timing. -+ It may never be ready if kernel and firmware are mismatched, so don't block forever. */ -+ for (i=0; i0) { -+ vchiq_log_warning(vchiq_core_log_level, -+ "%s: videocore initialized after %d retries\n", __func__, i); -+ } -+ -+ instance = kzalloc(sizeof(*instance), GFP_KERNEL); -+ if (!instance) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%s: error allocating vchiq instance\n", __func__); -+ goto failed; -+ } -+ -+ instance->connected = 0; -+ instance->state = state; -+ mutex_init(&instance->bulk_waiter_list_mutex); -+ INIT_LIST_HEAD(&instance->bulk_waiter_list); -+ -+ *instanceOut = instance; -+ -+ status = VCHIQ_SUCCESS; -+ -+failed: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_initialise); -+ -+/**************************************************************************** -+* -+* vchiq_shutdown -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_STATUS_T status; -+ VCHIQ_STATE_T *state = instance->state; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ if (mutex_lock_interruptible(&state->mutex) != 0) -+ return VCHIQ_RETRY; -+ -+ /* Remove all services */ -+ status = vchiq_shutdown_internal(state, instance); -+ -+ mutex_unlock(&state->mutex); -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ if (status == VCHIQ_SUCCESS) { -+ struct list_head *pos, *next; -+ list_for_each_safe(pos, next, -+ &instance->bulk_waiter_list) { -+ struct bulk_waiter_node *waiter; -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ vchiq_log_info(vchiq_arm_log_level, -+ "bulk_waiter - cleaned up %x " -+ "for pid %d", -+ (unsigned int)waiter, waiter->pid); -+ kfree(waiter); -+ } -+ kfree(instance); -+ } -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_shutdown); -+ -+/**************************************************************************** -+* -+* vchiq_is_connected -+* -+***************************************************************************/ -+ -+int vchiq_is_connected(VCHIQ_INSTANCE_T instance) -+{ -+ return instance->connected; -+} -+ -+/**************************************************************************** -+* -+* vchiq_connect -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_STATUS_T status; -+ VCHIQ_STATE_T *state = instance->state; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ if (mutex_lock_interruptible(&state->mutex) != 0) { -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s: call to mutex_lock failed", __func__); -+ status = VCHIQ_RETRY; -+ goto failed; -+ } -+ status = vchiq_connect_internal(state, instance); -+ -+ if (status == VCHIQ_SUCCESS) -+ instance->connected = 1; -+ -+ mutex_unlock(&state->mutex); -+ -+failed: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_connect); -+ -+/**************************************************************************** -+* -+* vchiq_add_service -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_add_service( -+ VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *phandle) -+{ -+ VCHIQ_STATUS_T status; -+ VCHIQ_STATE_T *state = instance->state; -+ VCHIQ_SERVICE_T *service = NULL; -+ int srvstate; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ *phandle = VCHIQ_SERVICE_HANDLE_INVALID; -+ -+ srvstate = vchiq_is_connected(instance) -+ ? VCHIQ_SRVSTATE_LISTENING -+ : VCHIQ_SRVSTATE_HIDDEN; -+ -+ service = vchiq_add_service_internal( -+ state, -+ params, -+ srvstate, -+ instance, -+ NULL); -+ -+ if (service) { -+ *phandle = service->handle; -+ status = VCHIQ_SUCCESS; -+ } else -+ status = VCHIQ_ERROR; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_add_service); -+ -+/**************************************************************************** -+* -+* vchiq_open_service -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_open_service( -+ VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *phandle) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_STATE_T *state = instance->state; -+ VCHIQ_SERVICE_T *service = NULL; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ *phandle = VCHIQ_SERVICE_HANDLE_INVALID; -+ -+ if (!vchiq_is_connected(instance)) -+ goto failed; -+ -+ service = vchiq_add_service_internal(state, -+ params, -+ VCHIQ_SRVSTATE_OPENING, -+ instance, -+ NULL); -+ -+ if (service) { -+ *phandle = service->handle; -+ status = vchiq_open_service_internal(service, current->pid); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_remove_service(service->handle); -+ *phandle = VCHIQ_SERVICE_HANDLE_INVALID; -+ } -+ } -+ -+failed: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_open_service); -+ -+VCHIQ_STATUS_T -+vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, -+ const void *data, unsigned int size, void *userdata) -+{ -+ return vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, -+ VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT); -+} -+EXPORT_SYMBOL(vchiq_queue_bulk_transmit); -+ -+VCHIQ_STATUS_T -+vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, void *userdata) -+{ -+ return vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, data, size, userdata, -+ VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE); -+} -+EXPORT_SYMBOL(vchiq_queue_bulk_receive); -+ -+VCHIQ_STATUS_T -+vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data, -+ unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) -+{ -+ VCHIQ_STATUS_T status; -+ -+ switch (mode) { -+ case VCHIQ_BULK_MODE_NOCALLBACK: -+ case VCHIQ_BULK_MODE_CALLBACK: -+ status = vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, -+ mode, VCHIQ_BULK_TRANSMIT); -+ break; -+ case VCHIQ_BULK_MODE_BLOCKING: -+ status = vchiq_blocking_bulk_transfer(handle, -+ (void *)data, size, VCHIQ_BULK_TRANSMIT); -+ break; -+ default: -+ return VCHIQ_ERROR; -+ } -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_bulk_transmit); -+ -+VCHIQ_STATUS_T -+vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) -+{ -+ VCHIQ_STATUS_T status; -+ -+ switch (mode) { -+ case VCHIQ_BULK_MODE_NOCALLBACK: -+ case VCHIQ_BULK_MODE_CALLBACK: -+ status = vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, data, size, userdata, -+ mode, VCHIQ_BULK_RECEIVE); -+ break; -+ case VCHIQ_BULK_MODE_BLOCKING: -+ status = vchiq_blocking_bulk_transfer(handle, -+ (void *)data, size, VCHIQ_BULK_RECEIVE); -+ break; -+ default: -+ return VCHIQ_ERROR; -+ } -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_bulk_receive); -+ -+static VCHIQ_STATUS_T -+vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, VCHIQ_BULK_DIR_T dir) -+{ -+ VCHIQ_INSTANCE_T instance; -+ VCHIQ_SERVICE_T *service; -+ VCHIQ_STATUS_T status; -+ struct bulk_waiter_node *waiter = NULL; -+ struct list_head *pos; -+ -+ service = find_service_by_handle(handle); -+ if (!service) -+ return VCHIQ_ERROR; -+ -+ instance = service->instance; -+ -+ unlock_service(service); -+ -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_for_each(pos, &instance->bulk_waiter_list) { -+ if (list_entry(pos, struct bulk_waiter_node, -+ list)->pid == current->pid) { -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ break; -+ } -+ } -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ -+ if (waiter) { -+ VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; -+ if (bulk) { -+ /* This thread has an outstanding bulk transfer. */ -+ if ((bulk->data != data) || -+ (bulk->size != size)) { -+ /* This is not a retry of the previous one. -+ ** Cancel the signal when the transfer -+ ** completes. */ -+ spin_lock(&bulk_waiter_spinlock); -+ bulk->userdata = NULL; -+ spin_unlock(&bulk_waiter_spinlock); -+ } -+ } -+ } -+ -+ if (!waiter) { -+ waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL); -+ if (!waiter) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%s - out of memory", __func__); -+ return VCHIQ_ERROR; -+ } -+ } -+ -+ status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID, -+ data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING, -+ dir); -+ if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || -+ !waiter->bulk_waiter.bulk) { -+ VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; -+ if (bulk) { -+ /* Cancel the signal when the transfer -+ ** completes. */ -+ spin_lock(&bulk_waiter_spinlock); -+ bulk->userdata = NULL; -+ spin_unlock(&bulk_waiter_spinlock); -+ } -+ kfree(waiter); -+ } else { -+ waiter->pid = current->pid; -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_add(&waiter->list, &instance->bulk_waiter_list); -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ vchiq_log_info(vchiq_arm_log_level, -+ "saved bulk_waiter %x for pid %d", -+ (unsigned int)waiter, current->pid); -+ } -+ -+ return status; -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h -new file mode 100644 -index 0000000000000000000000000000000000000000..335446e05476c3dbb905a69e45b37a2702566bf6 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h -@@ -0,0 +1,69 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_KILLABLE_H -+#define VCHIQ_KILLABLE_H -+ -+#include -+#include -+ -+#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTRAP) | sigmask(SIGSTOP) | sigmask(SIGCONT)) -+ -+static inline int __must_check down_interruptible_killable(struct semaphore *sem) -+{ -+ /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ -+ int ret; -+ sigset_t blocked, oldset; -+ siginitsetinv(&blocked, SHUTDOWN_SIGS); -+ sigprocmask(SIG_SETMASK, &blocked, &oldset); -+ ret = down_interruptible(sem); -+ sigprocmask(SIG_SETMASK, &oldset, NULL); -+ return ret; -+} -+#define down_interruptible down_interruptible_killable -+ -+ -+static inline int __must_check mutex_lock_interruptible_killable(struct mutex *lock) -+{ -+ /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ -+ int ret; -+ sigset_t blocked, oldset; -+ siginitsetinv(&blocked, SHUTDOWN_SIGS); -+ sigprocmask(SIG_SETMASK, &blocked, &oldset); -+ ret = mutex_lock_interruptible(lock); -+ sigprocmask(SIG_SETMASK, &oldset, NULL); -+ return ret; -+} -+#define mutex_lock_interruptible mutex_lock_interruptible_killable -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h -new file mode 100644 -index 0000000000000000000000000000000000000000..d02e7764bd0d8721453d2e0a4900c26c12634c8b ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h -@@ -0,0 +1,71 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_MEMDRV_H -+#define VCHIQ_MEMDRV_H -+ -+/* ---- Include Files ----------------------------------------------------- */ -+ -+#include -+#include "vchiq_if.h" -+ -+/* ---- Constants and Types ---------------------------------------------- */ -+ -+typedef struct { -+ void *armSharedMemVirt; -+ dma_addr_t armSharedMemPhys; -+ size_t armSharedMemSize; -+ -+ void *vcSharedMemVirt; -+ dma_addr_t vcSharedMemPhys; -+ size_t vcSharedMemSize; -+} VCHIQ_SHARED_MEM_INFO_T; -+ -+/* ---- Variable Externs ------------------------------------------------- */ -+ -+/* ---- Function Prototypes ---------------------------------------------- */ -+ -+void vchiq_get_shared_mem_info(VCHIQ_SHARED_MEM_INFO_T *info); -+ -+VCHIQ_STATUS_T vchiq_memdrv_initialise(void); -+ -+VCHIQ_STATUS_T vchiq_userdrv_create_instance( -+ const VCHIQ_PLATFORM_DATA_T * platform_data); -+ -+VCHIQ_STATUS_T vchiq_userdrv_suspend( -+ const VCHIQ_PLATFORM_DATA_T * platform_data); -+ -+VCHIQ_STATUS_T vchiq_userdrv_resume( -+ const VCHIQ_PLATFORM_DATA_T * platform_data); -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h -new file mode 100644 -index 0000000000000000000000000000000000000000..54a3ecec69ef6702c382a7af339d21b87ec8a346 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h -@@ -0,0 +1,58 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_PAGELIST_H -+#define VCHIQ_PAGELIST_H -+ -+#ifndef PAGE_SIZE -+#define PAGE_SIZE 4096 -+#endif -+#define CACHE_LINE_SIZE 32 -+#define PAGELIST_WRITE 0 -+#define PAGELIST_READ 1 -+#define PAGELIST_READ_WITH_FRAGMENTS 2 -+ -+typedef struct pagelist_struct { -+ unsigned long length; -+ unsigned short type; -+ unsigned short offset; -+ unsigned long addrs[1]; /* N.B. 12 LSBs hold the number of following -+ pages at consecutive addresses. */ -+} PAGELIST_T; -+ -+typedef struct fragments_struct { -+ char headbuf[CACHE_LINE_SIZE]; -+ char tailbuf[CACHE_LINE_SIZE]; -+} FRAGMENTS_T; -+ -+#endif /* VCHIQ_PAGELIST_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c -new file mode 100644 -index 0000000000000000000000000000000000000000..8072ff613636121d50293693d0bd2aaf0b6e07b5 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c -@@ -0,0 +1,860 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+#include -+#include -+ -+#include "interface/vchi/vchi.h" -+#include "vchiq.h" -+#include "vchiq_core.h" -+ -+#include "vchiq_util.h" -+ -+#include -+ -+#define vchiq_status_to_vchi(status) ((int32_t)status) -+ -+typedef struct { -+ VCHIQ_SERVICE_HANDLE_T handle; -+ -+ VCHIU_QUEUE_T queue; -+ -+ VCHI_CALLBACK_T callback; -+ void *callback_param; -+} SHIM_SERVICE_T; -+ -+/* ---------------------------------------------------------------------- -+ * return pointer to the mphi message driver function table -+ * -------------------------------------------------------------------- */ -+const VCHI_MESSAGE_DRIVER_T * -+vchi_mphi_message_driver_func_table(void) -+{ -+ return NULL; -+} -+ -+/* ---------------------------------------------------------------------- -+ * return a pointer to the 'single' connection driver fops -+ * -------------------------------------------------------------------- */ -+const VCHI_CONNECTION_API_T * -+single_get_func_table(void) -+{ -+ return NULL; -+} -+ -+VCHI_CONNECTION_T *vchi_create_connection( -+ const VCHI_CONNECTION_API_T *function_table, -+ const VCHI_MESSAGE_DRIVER_T *low_level) -+{ -+ (void)function_table; -+ (void)low_level; -+ return NULL; -+} -+ -+/*********************************************************** -+ * Name: vchi_msg_peek -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle, -+ * void **data, -+ * uint32_t *msg_size, -+ -+ -+ * VCHI_FLAGS_T flags -+ * -+ * Description: Routine to return a pointer to the current message (to allow in -+ * place processing). The message can be removed using -+ * vchi_msg_remove when you're finished -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ WARN_ON((flags != VCHI_FLAGS_NONE) && -+ (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); -+ -+ if (flags == VCHI_FLAGS_NONE) -+ if (vchiu_queue_is_empty(&service->queue)) -+ return -1; -+ -+ header = vchiu_queue_peek(&service->queue); -+ -+ *data = header->data; -+ *msg_size = header->size; -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_peek); -+ -+/*********************************************************** -+ * Name: vchi_msg_remove -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle, -+ * -+ * Description: Routine to remove a message (after it has been read with -+ * vchi_msg_peek) -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ header = vchiu_queue_pop(&service->queue); -+ -+ vchiq_release_message(service->handle, header); -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_remove); -+ -+/*********************************************************** -+ * Name: vchi_msg_queue -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * const void *data, -+ * uint32_t data_size, -+ * VCHI_FLAGS_T flags, -+ * void *msg_handle, -+ * -+ * Description: Thin wrapper to queue a message onto a connection -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_ELEMENT_T element = {data, data_size}; -+ VCHIQ_STATUS_T status; -+ -+ (void)msg_handle; -+ -+ WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); -+ -+ status = vchiq_queue_message(service->handle, &element, 1); -+ -+ /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to -+ ** implement a retry mechanism since this function is supposed -+ ** to block until queued -+ */ -+ while (status == VCHIQ_RETRY) { -+ msleep(1); -+ status = vchiq_queue_message(service->handle, &element, 1); -+ } -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_msg_queue); -+ -+/*********************************************************** -+ * Name: vchi_bulk_queue_receive -+ * -+ * Arguments: VCHI_BULK_HANDLE_T handle, -+ * void *data_dst, -+ * const uint32_t data_size, -+ * VCHI_FLAGS_T flags -+ * void *bulk_handle -+ * -+ * Description: Routine to setup a rcv buffer -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, -+ void *data_dst, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_BULK_MODE_T mode; -+ VCHIQ_STATUS_T status; -+ -+ switch ((int)flags) { -+ case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE -+ | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ WARN_ON(!service->callback); -+ mode = VCHIQ_BULK_MODE_CALLBACK; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: -+ mode = VCHIQ_BULK_MODE_BLOCKING; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ case VCHI_FLAGS_NONE: -+ mode = VCHIQ_BULK_MODE_NOCALLBACK; -+ break; -+ default: -+ WARN(1, "unsupported message\n"); -+ return vchiq_status_to_vchi(VCHIQ_ERROR); -+ } -+ -+ status = vchiq_bulk_receive(service->handle, data_dst, data_size, -+ bulk_handle, mode); -+ -+ /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to -+ ** implement a retry mechanism since this function is supposed -+ ** to block until queued -+ */ -+ while (status == VCHIQ_RETRY) { -+ msleep(1); -+ status = vchiq_bulk_receive(service->handle, data_dst, -+ data_size, bulk_handle, mode); -+ } -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_bulk_queue_receive); -+ -+/*********************************************************** -+ * Name: vchi_bulk_queue_transmit -+ * -+ * Arguments: VCHI_BULK_HANDLE_T handle, -+ * const void *data_src, -+ * uint32_t data_size, -+ * VCHI_FLAGS_T flags, -+ * void *bulk_handle -+ * -+ * Description: Routine to transmit some data -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, -+ const void *data_src, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_BULK_MODE_T mode; -+ VCHIQ_STATUS_T status; -+ -+ switch ((int)flags) { -+ case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE -+ | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ WARN_ON(!service->callback); -+ mode = VCHIQ_BULK_MODE_CALLBACK; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: -+ case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: -+ mode = VCHIQ_BULK_MODE_BLOCKING; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ case VCHI_FLAGS_NONE: -+ mode = VCHIQ_BULK_MODE_NOCALLBACK; -+ break; -+ default: -+ WARN(1, "unsupported message\n"); -+ return vchiq_status_to_vchi(VCHIQ_ERROR); -+ } -+ -+ status = vchiq_bulk_transmit(service->handle, data_src, data_size, -+ bulk_handle, mode); -+ -+ /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to -+ ** implement a retry mechanism since this function is supposed -+ ** to block until queued -+ */ -+ while (status == VCHIQ_RETRY) { -+ msleep(1); -+ status = vchiq_bulk_transmit(service->handle, data_src, -+ data_size, bulk_handle, mode); -+ } -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_bulk_queue_transmit); -+ -+/*********************************************************** -+ * Name: vchi_msg_dequeue -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * void *data, -+ * uint32_t max_data_size_to_read, -+ * uint32_t *actual_msg_size -+ * VCHI_FLAGS_T flags -+ * -+ * Description: Routine to dequeue a message into the supplied buffer -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, -+ void *data, -+ uint32_t max_data_size_to_read, -+ uint32_t *actual_msg_size, -+ VCHI_FLAGS_T flags) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ WARN_ON((flags != VCHI_FLAGS_NONE) && -+ (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); -+ -+ if (flags == VCHI_FLAGS_NONE) -+ if (vchiu_queue_is_empty(&service->queue)) -+ return -1; -+ -+ header = vchiu_queue_pop(&service->queue); -+ -+ memcpy(data, header->data, header->size < max_data_size_to_read ? -+ header->size : max_data_size_to_read); -+ -+ *actual_msg_size = header->size; -+ -+ vchiq_release_message(service->handle, header); -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_dequeue); -+ -+/*********************************************************** -+ * Name: vchi_msg_queuev -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * VCHI_MSG_VECTOR_T *vector, -+ * uint32_t count, -+ * VCHI_FLAGS_T flags, -+ * void *msg_handle -+ * -+ * Description: Thin wrapper to queue a message onto a connection -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+ -+vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); -+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == -+ offsetof(VCHIQ_ELEMENT_T, data)); -+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == -+ offsetof(VCHIQ_ELEMENT_T, size)); -+ -+int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ -+ (void)msg_handle; -+ -+ WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); -+ -+ return vchiq_status_to_vchi(vchiq_queue_message(service->handle, -+ (const VCHIQ_ELEMENT_T *)vector, count)); -+} -+EXPORT_SYMBOL(vchi_msg_queuev); -+ -+/*********************************************************** -+ * Name: vchi_held_msg_release -+ * -+ * Arguments: VCHI_HELD_MSG_T *message -+ * -+ * Description: Routine to release a held message (after it has been read with -+ * vchi_msg_hold) -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) -+{ -+ vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, -+ (VCHIQ_HEADER_T *)message->message); -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_held_msg_release); -+ -+/*********************************************************** -+ * Name: vchi_msg_hold -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * void **data, -+ * uint32_t *msg_size, -+ * VCHI_FLAGS_T flags, -+ * VCHI_HELD_MSG_T *message_handle -+ * -+ * Description: Routine to return a pointer to the current message (to allow -+ * in place processing). The message is dequeued - don't forget -+ * to release the message using vchi_held_msg_release when you're -+ * finished. -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags, -+ VCHI_HELD_MSG_T *message_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ WARN_ON((flags != VCHI_FLAGS_NONE) && -+ (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); -+ -+ if (flags == VCHI_FLAGS_NONE) -+ if (vchiu_queue_is_empty(&service->queue)) -+ return -1; -+ -+ header = vchiu_queue_pop(&service->queue); -+ -+ *data = header->data; -+ *msg_size = header->size; -+ -+ message_handle->service = -+ (struct opaque_vchi_service_t *)service->handle; -+ message_handle->message = header; -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_hold); -+ -+/*********************************************************** -+ * Name: vchi_initialise -+ * -+ * Arguments: VCHI_INSTANCE_T *instance_handle -+ * -+ * Description: Initialises the hardware but does not transmit anything -+ * When run as a Host App this will be called twice hence the need -+ * to malloc the state information -+ * -+ * Returns: 0 if successful, failure otherwise -+ * -+ ***********************************************************/ -+ -+int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle) -+{ -+ VCHIQ_INSTANCE_T instance; -+ VCHIQ_STATUS_T status; -+ -+ status = vchiq_initialise(&instance); -+ -+ *instance_handle = (VCHI_INSTANCE_T)instance; -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_initialise); -+ -+/*********************************************************** -+ * Name: vchi_connect -+ * -+ * Arguments: VCHI_CONNECTION_T **connections -+ * const uint32_t num_connections -+ * VCHI_INSTANCE_T instance_handle) -+ * -+ * Description: Starts the command service on each connection, -+ * causing INIT messages to be pinged back and forth -+ * -+ * Returns: 0 if successful, failure otherwise -+ * -+ ***********************************************************/ -+int32_t vchi_connect(VCHI_CONNECTION_T **connections, -+ const uint32_t num_connections, -+ VCHI_INSTANCE_T instance_handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ -+ (void)connections; -+ (void)num_connections; -+ -+ return vchiq_connect(instance); -+} -+EXPORT_SYMBOL(vchi_connect); -+ -+ -+/*********************************************************** -+ * Name: vchi_disconnect -+ * -+ * Arguments: VCHI_INSTANCE_T instance_handle -+ * -+ * Description: Stops the command service on each connection, -+ * causing DE-INIT messages to be pinged back and forth -+ * -+ * Returns: 0 if successful, failure otherwise -+ * -+ ***********************************************************/ -+int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ return vchiq_status_to_vchi(vchiq_shutdown(instance)); -+} -+EXPORT_SYMBOL(vchi_disconnect); -+ -+ -+/*********************************************************** -+ * Name: vchi_service_open -+ * Name: vchi_service_create -+ * -+ * Arguments: VCHI_INSTANCE_T *instance_handle -+ * SERVICE_CREATION_T *setup, -+ * VCHI_SERVICE_HANDLE_T *handle -+ * -+ * Description: Routine to open a service -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+ -+static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) -+{ -+ SHIM_SERVICE_T *service = -+ (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle); -+ -+ if (!service->callback) -+ goto release; -+ -+ switch (reason) { -+ case VCHIQ_MESSAGE_AVAILABLE: -+ vchiu_queue_push(&service->queue, header); -+ -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_MSG_AVAILABLE, NULL); -+ -+ goto done; -+ break; -+ -+ case VCHIQ_BULK_TRANSMIT_DONE: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_SENT, bulk_user); -+ break; -+ -+ case VCHIQ_BULK_RECEIVE_DONE: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_RECEIVED, bulk_user); -+ break; -+ -+ case VCHIQ_SERVICE_CLOSED: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_SERVICE_CLOSED, NULL); -+ break; -+ -+ case VCHIQ_SERVICE_OPENED: -+ /* No equivalent VCHI reason */ -+ break; -+ -+ case VCHIQ_BULK_TRANSMIT_ABORTED: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, -+ bulk_user); -+ break; -+ -+ case VCHIQ_BULK_RECEIVE_ABORTED: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_RECEIVE_ABORTED, -+ bulk_user); -+ break; -+ -+ default: -+ WARN(1, "not supported\n"); -+ break; -+ } -+ -+release: -+ vchiq_release_message(service->handle, header); -+done: -+ return VCHIQ_SUCCESS; -+} -+ -+static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance, -+ SERVICE_CREATION_T *setup) -+{ -+ SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL); -+ -+ (void)instance; -+ -+ if (service) { -+ if (vchiu_queue_init(&service->queue, 64)) { -+ service->callback = setup->callback; -+ service->callback_param = setup->callback_param; -+ } else { -+ kfree(service); -+ service = NULL; -+ } -+ } -+ -+ return service; -+} -+ -+static void service_free(SHIM_SERVICE_T *service) -+{ -+ if (service) { -+ vchiu_queue_delete(&service->queue); -+ kfree(service); -+ } -+} -+ -+int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ SHIM_SERVICE_T *service = service_alloc(instance, setup); -+ -+ *handle = (VCHI_SERVICE_HANDLE_T)service; -+ -+ if (service) { -+ VCHIQ_SERVICE_PARAMS_T params; -+ VCHIQ_STATUS_T status; -+ -+ memset(¶ms, 0, sizeof(params)); -+ params.fourcc = setup->service_id; -+ params.callback = shim_callback; -+ params.userdata = service; -+ params.version = setup->version.version; -+ params.version_min = setup->version.version_min; -+ -+ status = vchiq_open_service(instance, ¶ms, -+ &service->handle); -+ if (status != VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ *handle = NULL; -+ } -+ } -+ -+ return (service != NULL) ? 0 : -1; -+} -+EXPORT_SYMBOL(vchi_service_open); -+ -+int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ SHIM_SERVICE_T *service = service_alloc(instance, setup); -+ -+ *handle = (VCHI_SERVICE_HANDLE_T)service; -+ -+ if (service) { -+ VCHIQ_SERVICE_PARAMS_T params; -+ VCHIQ_STATUS_T status; -+ -+ memset(¶ms, 0, sizeof(params)); -+ params.fourcc = setup->service_id; -+ params.callback = shim_callback; -+ params.userdata = service; -+ params.version = setup->version.version; -+ params.version_min = setup->version.version_min; -+ status = vchiq_add_service(instance, ¶ms, &service->handle); -+ -+ if (status != VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ *handle = NULL; -+ } -+ } -+ -+ return (service != NULL) ? 0 : -1; -+} -+EXPORT_SYMBOL(vchi_service_create); -+ -+int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) { -+ VCHIQ_STATUS_T status = vchiq_close_service(service->handle); -+ if (status == VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ } -+ -+ ret = vchiq_status_to_vchi(status); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_close); -+ -+int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) { -+ VCHIQ_STATUS_T status = vchiq_remove_service(service->handle); -+ if (status == VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ } -+ -+ ret = vchiq_status_to_vchi(status); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_destroy); -+ -+int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle, -+ VCHI_SERVICE_OPTION_T option, -+ int value) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_SERVICE_OPTION_T vchiq_option; -+ switch (option) { -+ case VCHI_SERVICE_OPTION_TRACE: -+ vchiq_option = VCHIQ_SERVICE_OPTION_TRACE; -+ break; -+ case VCHI_SERVICE_OPTION_SYNCHRONOUS: -+ vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS; -+ break; -+ default: -+ service = NULL; -+ break; -+ } -+ if (service) { -+ VCHIQ_STATUS_T status = -+ vchiq_set_service_option(service->handle, -+ vchiq_option, -+ value); -+ -+ ret = vchiq_status_to_vchi(status); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_set_option); -+ -+int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version ) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if(service) -+ { -+ VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version); -+ ret = vchiq_status_to_vchi( status ); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_get_peer_version); -+ -+/* ---------------------------------------------------------------------- -+ * read a uint32_t from buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+uint32_t -+vchi_readbuf_uint32(const void *_ptr) -+{ -+ const unsigned char *ptr = _ptr; -+ return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); -+} -+ -+/* ---------------------------------------------------------------------- -+ * write a uint32_t to buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+void -+vchi_writebuf_uint32(void *_ptr, uint32_t value) -+{ -+ unsigned char *ptr = _ptr; -+ ptr[0] = (unsigned char)((value >> 0) & 0xFF); -+ ptr[1] = (unsigned char)((value >> 8) & 0xFF); -+ ptr[2] = (unsigned char)((value >> 16) & 0xFF); -+ ptr[3] = (unsigned char)((value >> 24) & 0xFF); -+} -+ -+/* ---------------------------------------------------------------------- -+ * read a uint16_t from buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+uint16_t -+vchi_readbuf_uint16(const void *_ptr) -+{ -+ const unsigned char *ptr = _ptr; -+ return ptr[0] | (ptr[1] << 8); -+} -+ -+/* ---------------------------------------------------------------------- -+ * write a uint16_t into the buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+void -+vchi_writebuf_uint16(void *_ptr, uint16_t value) -+{ -+ unsigned char *ptr = _ptr; -+ ptr[0] = (value >> 0) & 0xFF; -+ ptr[1] = (value >> 8) & 0xFF; -+} -+ -+/*********************************************************** -+ * Name: vchi_service_use -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle -+ * -+ * Description: Routine to increment refcount on a service -+ * -+ * Returns: void -+ * -+ ***********************************************************/ -+int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) -+ ret = vchiq_status_to_vchi(vchiq_use_service(service->handle)); -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_use); -+ -+/*********************************************************** -+ * Name: vchi_service_release -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle -+ * -+ * Description: Routine to decrement refcount on a service -+ * -+ * Returns: void -+ * -+ ***********************************************************/ -+int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) -+ ret = vchiq_status_to_vchi( -+ vchiq_release_service(service->handle)); -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_release); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c -new file mode 100644 -index 0000000000000000000000000000000000000000..384acb8d2eae12eca8aa955c274467f120e8824f ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c -@@ -0,0 +1,156 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "vchiq_util.h" -+#include "vchiq_killable.h" -+ -+static inline int is_pow2(int i) -+{ -+ return i && !(i & (i - 1)); -+} -+ -+int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) -+{ -+ WARN_ON(!is_pow2(size)); -+ -+ queue->size = size; -+ queue->read = 0; -+ queue->write = 0; -+ queue->initialized = 1; -+ -+ sema_init(&queue->pop, 0); -+ sema_init(&queue->push, 0); -+ -+ queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL); -+ if (queue->storage == NULL) { -+ vchiu_queue_delete(queue); -+ return 0; -+ } -+ return 1; -+} -+ -+void vchiu_queue_delete(VCHIU_QUEUE_T *queue) -+{ -+ if (queue->storage != NULL) -+ kfree(queue->storage); -+} -+ -+int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue) -+{ -+ return queue->read == queue->write; -+} -+ -+int vchiu_queue_is_full(VCHIU_QUEUE_T *queue) -+{ -+ return queue->write == queue->read + queue->size; -+} -+ -+void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header) -+{ -+ if (!queue->initialized) -+ return; -+ -+ while (queue->write == queue->read + queue->size) { -+ if (down_interruptible(&queue->pop) != 0) { -+ flush_signals(current); -+ } -+ } -+ -+ /* -+ * Write to queue->storage must be visible after read from -+ * queue->read -+ */ -+ smp_mb(); -+ -+ queue->storage[queue->write & (queue->size - 1)] = header; -+ -+ /* -+ * Write to queue->storage must be visible before write to -+ * queue->write -+ */ -+ smp_wmb(); -+ -+ queue->write++; -+ -+ up(&queue->push); -+} -+ -+VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue) -+{ -+ while (queue->write == queue->read) { -+ if (down_interruptible(&queue->push) != 0) { -+ flush_signals(current); -+ } -+ } -+ -+ up(&queue->push); // We haven't removed anything from the queue. -+ -+ /* -+ * Read from queue->storage must be visible after read from -+ * queue->write -+ */ -+ smp_rmb(); -+ -+ return queue->storage[queue->read & (queue->size - 1)]; -+} -+ -+VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue) -+{ -+ VCHIQ_HEADER_T *header; -+ -+ while (queue->write == queue->read) { -+ if (down_interruptible(&queue->push) != 0) { -+ flush_signals(current); -+ } -+ } -+ -+ /* -+ * Read from queue->storage must be visible after read from -+ * queue->write -+ */ -+ smp_rmb(); -+ -+ header = queue->storage[queue->read & (queue->size - 1)]; -+ -+ /* -+ * Read from queue->storage must be visible before write to -+ * queue->read -+ */ -+ smp_mb(); -+ -+ queue->read++; -+ -+ up(&queue->pop); -+ -+ return header; -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4055d4bf9f740ab9f10a7e44673b9795681981f7 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h -@@ -0,0 +1,82 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_UTIL_H -+#define VCHIQ_UTIL_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for time_t */ -+#include -+#include -+ -+#include "vchiq_if.h" -+ -+typedef struct { -+ int size; -+ int read; -+ int write; -+ int initialized; -+ -+ struct semaphore pop; -+ struct semaphore push; -+ -+ VCHIQ_HEADER_T **storage; -+} VCHIU_QUEUE_T; -+ -+extern int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size); -+extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue); -+ -+extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue); -+extern int vchiu_queue_is_full(VCHIU_QUEUE_T *queue); -+ -+extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header); -+ -+extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue); -+extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue); -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c -new file mode 100644 -index 0000000000000000000000000000000000000000..b6bfa21155e431e93bfb2c149d32437184c2b6e3 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c -@@ -0,0 +1,59 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+#include "vchiq_build_info.h" -+#include -+ -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_hostname, "dc4-arm-01" ); -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_version, "9245b4c35b99b3870e1f7dc598c5692b3c66a6f0 (tainted)" ); -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_time, __TIME__ ); -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_date, __DATE__ ); -+ -+const char *vchiq_get_build_hostname( void ) -+{ -+ return vchiq_build_hostname; -+} -+ -+const char *vchiq_get_build_version( void ) -+{ -+ return vchiq_build_version; -+} -+ -+const char *vchiq_get_build_date( void ) -+{ -+ return vchiq_build_date; -+} -+ -+const char *vchiq_get_build_time( void ) -+{ -+ return vchiq_build_time; -+} - -From 566c5c2c2ff0ad35cccf0ad61a4ebd9f9dfb2e4b Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 17 Jun 2015 16:07:06 +0100 -Subject: [PATCH 043/208] vc_mem: Add vc_mem driver +Date: Fri, 28 Oct 2016 15:36:43 +0100 +Subject: [PATCH 039/111] vc_mem: Add vc_mem driver for querying firmware + memory addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -91229,496 +75391,14 @@ Make the vc_mem module available for ARCH_BCM2835 by moving it. Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 --- - arch/arm/mach-bcm2709/vc_mem.c | 431 ---------------------------- - drivers/char/broadcom/Kconfig | 12 +- - drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_mem.c | 422 +++++++++++++++++++++++++++ - include/linux/broadcom/vc_mem.h | 35 +++ - 6 files changed, 469 insertions(+), 467 deletions(-) - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - delete mode 100644 arch/arm/mach-bcm2709/vc_mem.c + drivers/char/broadcom/Kconfig | 12 +- + drivers/char/broadcom/Makefile | 1 + + drivers/char/broadcom/vc_mem.c | 422 ++++++++++++++++++++++++++++++++++++++++ + include/linux/broadcom/vc_mem.h | 35 ++++ + 4 files changed, 469 insertions(+), 1 deletion(-) create mode 100644 drivers/char/broadcom/vc_mem.c create mode 100644 include/linux/broadcom/vc_mem.h -diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -deleted file mode 100644 -index 4a4a33845cbc02f0e0d5368fed3609f6ba9ff92b..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/vc_mem.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#if !defined( VC_MEM_H ) --#define VC_MEM_H -- --#include -- --#define VC_MEM_IOC_MAGIC 'v' -- --#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) --#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) --#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) --#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -- --#if defined( __KERNEL__ ) --#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -- --extern unsigned long mm_vc_mem_phys_addr; --extern unsigned int mm_vc_mem_size; --extern int vc_mem_get_current_size( void ); --#endif -- --#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -deleted file mode 100644 -index d2adfd1db2421984ea8ab8fb809d1adb0765714e..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/vc_mem.c -+++ /dev/null -@@ -1,431 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_ARCH_KONA --#include --#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) --#else --#include --#endif -- --#include "mach/vc_mem.h" -- --#define DRIVER_NAME "vc-mem" -- --// Device (/dev) related variables --static dev_t vc_mem_devnum = 0; --static struct class *vc_mem_class = NULL; --static struct cdev vc_mem_cdev; --static int vc_mem_inited = 0; -- --#ifdef CONFIG_DEBUG_FS --static struct dentry *vc_mem_debugfs_entry; --#endif -- --/* -- * Videocore memory addresses and size -- * -- * Drivers that wish to know the videocore memory addresses and sizes should -- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -- * headers. This allows the other drivers to not be tied down to a a certain -- * address/size at compile time. -- * -- * In the future, the goal is to have the videocore memory virtual address and -- * size be calculated at boot time rather than at compile time. The decision of -- * where the videocore memory resides and its size would be in the hands of the -- * bootloader (and/or kernel). When that happens, the values of these variables -- * would be calculated and assigned in the init function. -- */ --// in the 2835 VC in mapped above ARM, but ARM has full access to VC space --unsigned long mm_vc_mem_phys_addr = 0x00000000; --unsigned int mm_vc_mem_size = 0; --unsigned int mm_vc_mem_base = 0; -- --EXPORT_SYMBOL(mm_vc_mem_phys_addr); --EXPORT_SYMBOL(mm_vc_mem_size); --EXPORT_SYMBOL(mm_vc_mem_base); -- --static uint phys_addr = 0; --static uint mem_size = 0; --static uint mem_base = 0; -- -- --/**************************************************************************** --* --* vc_mem_open --* --***************************************************************************/ -- --static int --vc_mem_open(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_release --* --***************************************************************************/ -- --static int --vc_mem_release(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_get_size --* --***************************************************************************/ -- --static void --vc_mem_get_size(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_base --* --***************************************************************************/ -- --static void --vc_mem_get_base(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_current_size --* --***************************************************************************/ -- --int --vc_mem_get_current_size(void) --{ -- return mm_vc_mem_size; --} -- --EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -- --/**************************************************************************** --* --* vc_mem_ioctl --* --***************************************************************************/ -- --static long --vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) --{ -- int rc = 0; -- -- (void) cmd; -- (void) arg; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- switch (cmd) { -- case VC_MEM_IOC_MEM_PHYS_ADDR: -- { -- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -- __func__, (void *) mm_vc_mem_phys_addr); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -- sizeof (mm_vc_mem_phys_addr)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_SIZE: -- { -- // Get the videocore memory size first -- vc_mem_get_size(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -- mm_vc_mem_size); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_size, -- sizeof (mm_vc_mem_size)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_BASE: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_LOAD: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- default: -- { -- return -ENOTTY; -- } -- } -- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -- -- return rc; --} -- --/**************************************************************************** --* --* vc_mem_mmap --* --***************************************************************************/ -- --static int --vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) --{ -- int rc = 0; -- unsigned long length = vma->vm_end - vma->vm_start; -- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -- -- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -- __func__, (long) vma->vm_start, (long) vma->vm_end, -- (long) vma->vm_pgoff); -- -- if (offset + length > mm_vc_mem_size) { -- pr_err("%s: length %ld is too big\n", __func__, length); -- return -EINVAL; -- } -- // Do not cache the memory map -- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- -- rc = remap_pfn_range(vma, vma->vm_start, -- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -- vma->vm_pgoff, length, vma->vm_page_prot); -- if (rc != 0) { -- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -- } -- -- return rc; --} -- --/**************************************************************************** --* --* File Operations for the driver. --* --***************************************************************************/ -- --static const struct file_operations vc_mem_fops = { -- .owner = THIS_MODULE, -- .open = vc_mem_open, -- .release = vc_mem_release, -- .unlocked_ioctl = vc_mem_ioctl, -- .mmap = vc_mem_mmap, --}; -- --#ifdef CONFIG_DEBUG_FS --static void vc_mem_debugfs_deinit(void) --{ -- debugfs_remove_recursive(vc_mem_debugfs_entry); -- vc_mem_debugfs_entry = NULL; --} -- -- --static int vc_mem_debugfs_init( -- struct device *dev) --{ -- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -- if (!vc_mem_debugfs_entry) { -- dev_warn(dev, "could not create debugfs entry\n"); -- return -EFAULT; -- } -- -- if (!debugfs_create_x32("vc_mem_phys_addr", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_phys_addr)) { -- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_size", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_size)) { -- dev_warn(dev, "%s:could not create vc_mem_size entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_base", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_base)) { -- dev_warn(dev, "%s:could not create vc_mem_base entry\n", -- __func__); -- goto fail; -- } -- -- return 0; -- --fail: -- vc_mem_debugfs_deinit(); -- return -EFAULT; --} -- --#endif /* CONFIG_DEBUG_FS */ -- -- --/**************************************************************************** --* --* vc_mem_init --* --***************************************************************************/ -- --static int __init --vc_mem_init(void) --{ -- int rc = -EFAULT; -- struct device *dev; -- -- pr_debug("%s: called\n", __func__); -- -- mm_vc_mem_phys_addr = phys_addr; -- mm_vc_mem_size = mem_size; -- mm_vc_mem_base = mem_base; -- -- vc_mem_get_size(); -- -- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -- -- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -- __func__, rc); -- goto out_err; -- } -- -- cdev_init(&vc_mem_cdev, &vc_mem_fops); -- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -- goto out_unregister; -- } -- -- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vc_mem_class)) { -- rc = PTR_ERR(vc_mem_class); -- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -- goto out_cdev_del; -- } -- -- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -- DRIVER_NAME); -- if (IS_ERR(dev)) { -- rc = PTR_ERR(dev); -- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -- goto out_class_destroy; -- } -- --#ifdef CONFIG_DEBUG_FS -- /* don't fail if the debug entries cannot be created */ -- vc_mem_debugfs_init(dev); --#endif -- -- vc_mem_inited = 1; -- return 0; -- -- device_destroy(vc_mem_class, vc_mem_devnum); -- -- out_class_destroy: -- class_destroy(vc_mem_class); -- vc_mem_class = NULL; -- -- out_cdev_del: -- cdev_del(&vc_mem_cdev); -- -- out_unregister: -- unregister_chrdev_region(vc_mem_devnum, 1); -- -- out_err: -- return -1; --} -- --/**************************************************************************** --* --* vc_mem_exit --* --***************************************************************************/ -- --static void __exit --vc_mem_exit(void) --{ -- pr_debug("%s: called\n", __func__); -- -- if (vc_mem_inited) { --#if CONFIG_DEBUG_FS -- vc_mem_debugfs_deinit(); --#endif -- device_destroy(vc_mem_class, vc_mem_devnum); -- class_destroy(vc_mem_class); -- cdev_del(&vc_mem_cdev); -- unregister_chrdev_region(vc_mem_devnum, 1); -- } --} -- --module_init(vc_mem_init); --module_exit(vc_mem_exit); --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Broadcom Corporation"); -- --module_param(phys_addr, uint, 0644); --module_param(mem_size, uint, 0644); --module_param(mem_base, uint, 0644); diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig index 2d8bd6e5016aab7340636c1f5dc4dd0cbacae6c0..70379287f6261fd833202ac47de1bcca8b84959a 100644 --- a/drivers/char/broadcom/Kconfig @@ -92221,10 +75901,10 @@ index 0000000000000000000000000000000000000000..20a475377eb3078ea1ecaef2b24efc35 + +#endif /* _VC_MEM_H */ -From 1a374ac5d04091feae0ddeca584c67ca348fcfae Mon Sep 17 00:00:00 2001 +From 81ba2928873a89c6233776e594f2a001d87cc11b Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 044/208] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 040/111] vcsm: VideoCore shared memory service for BCM2835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -92267,14 +75947,14 @@ Signed-off-by: Noralf Trønnes --- drivers/char/broadcom/Kconfig | 9 + drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_sm/Makefile | 20 + + drivers/char/broadcom/vc_sm/Makefile | 9 + drivers/char/broadcom/vc_sm/vc_sm_defs.h | 181 ++ drivers/char/broadcom/vc_sm/vc_sm_knl.h | 55 + drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 492 +++++ drivers/char/broadcom/vc_sm/vc_vchi_sm.h | 82 + drivers/char/broadcom/vc_sm/vmcs_sm.c | 3213 ++++++++++++++++++++++++++++++ include/linux/broadcom/vmcs_sm_ioctl.h | 248 +++ - 9 files changed, 4301 insertions(+) + 9 files changed, 4290 insertions(+) create mode 100644 drivers/char/broadcom/vc_sm/Makefile create mode 100644 drivers/char/broadcom/vc_sm/vc_sm_defs.h create mode 100644 drivers/char/broadcom/vc_sm/vc_sm_knl.h @@ -92310,24 +75990,13 @@ index fce918c369f7a9430136fea3ab098350339f1b01..de8feb98c63ff1e6437d80a6db85a8d3 +obj-$(CONFIG_BCM_VC_SM) += vc_sm/ diff --git a/drivers/char/broadcom/vc_sm/Makefile b/drivers/char/broadcom/vc_sm/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..68fa2aa7f725d3587c47c22489efc3418e48dce8 +index 0000000000000000000000000000000000000000..19ce263bc273dcdb24ea2b4431e4cafcf4ca4a2b --- /dev/null +++ b/drivers/char/broadcom/vc_sm/Makefile -@@ -0,0 +1,20 @@ -+EXTRA_CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -+ -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services" -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchi" -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchiq_arm" -+EXTRA_CFLAGS += -I"$(srctree)/fs/" -+ -+EXTRA_CFLAGS += -DOS_ASSERT_FAILURE -+EXTRA_CFLAGS += -D__STDC_VERSION=199901L -+EXTRA_CFLAGS += -D__STDC_VERSION__=199901L -+EXTRA_CFLAGS += -D__VCCOREVER__=0 -+EXTRA_CFLAGS += -D__KERNEL__ -+EXTRA_CFLAGS += -D__linux__ -+EXTRA_CFLAGS += -Werror +@@ -0,0 +1,9 @@ ++ccflags-$(CONFIG_BCM_VC_SM) += -Werror -Wall -Wstrict-prototypes -Wno-trigraphs -O2 ++ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"$(srctree)/fs/" ++ccflags-$(CONFIG_BCM_VC_SM) += -DOS_ASSERT_FAILURE -D__STDC_VERSION=199901L -D__STDC_VERSION__=199901L -D__VCCOREVER__=0 -D__KERNEL__ -D__linux__ + +obj-$(CONFIG_BCM_VC_SM) := vc-sm.o + @@ -96642,10 +80311,10 @@ index 0000000000000000000000000000000000000000..334f36d0d697b047df2922b5f2db67f3 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ -From 9a1ccb17b43b5109f5490c1d6bf5bacbf4e11a1b Mon Sep 17 00:00:00 2001 +From c79d4c54a6a03c79b998430d2d08afbc63c6d110 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 21 Aug 2015 23:14:48 +0100 -Subject: [PATCH 045/208] Add /dev/gpiomem device for rootless user GPIO access +Subject: [PATCH 041/111] Add /dev/gpiomem device for rootless user GPIO access Signed-off-by: Luke Wren @@ -96956,10 +80625,10 @@ index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae64 +MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +MODULE_AUTHOR("Luke Wren "); -From f4db6af82e4cb6535fa14fdf29b90769f2ce3f05 Mon Sep 17 00:00:00 2001 +From d89f74a85fef14e7b1661b2252fa2b08a859eb94 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:14:45 +0100 -Subject: [PATCH 046/208] Add SMI driver +Subject: [PATCH 042/111] Add SMI driver Signed-off-by: Luke Wren --- @@ -97057,7 +80726,7 @@ index 0000000000000000000000000000000000000000..b76dc694f1ac0b8044000ae54d312c80 +}; + diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index b75c9b2639fb0e63dd2623ddc1dcaac5759c132b..2292ed2ac9f457a7d491110e673666136faa5a5e 100644 +index b75c9b2639fb0e63dd2623ddc1dcaac5759c132b..f7885466f5bf9c0cf45f2057d07a0d24151f10c3 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig @@ -41,3 +41,11 @@ config BCM2835_DEVGPIOMEM @@ -97066,7 +80735,7 @@ index b75c9b2639fb0e63dd2623ddc1dcaac5759c132b..2292ed2ac9f457a7d491110e67366613 +config BCM2835_SMI_DEV + tristate "Character device driver for BCM2835 Secondary Memory Interface" -+ depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI ++ depends on BCM2835_SMI + default m + help + This driver provides a character device interface (ioctl + read/write) to @@ -97491,7 +81160,7 @@ index 0000000000000000000000000000000000000000..d6efd92fdfe46df5cfe219d2123e0dff + "Character device driver for BCM2835's secondary memory interface"); +MODULE_AUTHOR("Luke Wren "); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2..cff8c3df50c4b13d40fd1143eb86a66756bc097c 100644 +index 64971baf11faebaff879c58067d23fd9bf29895a..779f7d61a1779decd4dcbba3bc0e6b330e47f335 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -10,6 +10,14 @@ config SENSORS_LIS3LV02D @@ -97500,7 +81169,7 @@ index dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2..cff8c3df50c4b13d40fd1143eb86a667 +config BCM2835_SMI + tristate "Broadcom 283x Secondary Memory Interface driver" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + default m + help + Driver for enabling and using Broadcom's Secondary/Slow Memory Interface. @@ -97510,7 +81179,7 @@ index dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2..cff8c3df50c4b13d40fd1143eb86a667 tristate "Analog Devices Digital Potentiometers" depends on (I2C || SPI) && SYSFS diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index bdf0f5fe7be52b16e12e0bbc79ebfe58a084794d..d31dd62a64dfb98f07d1cae048b31961600d79f9 100644 +index 31983366090a781441a3235cac5883d6fbb27fa4..6c400f0fb92f5af49e04911b7f103ce1a60af093 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o @@ -97518,9 +81187,9 @@ index bdf0f5fe7be52b16e12e0bbc79ebfe58a084794d..d31dd62a64dfb98f07d1cae048b31961 obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o +obj-$(CONFIG_BCM2835_SMI) += bcm2835_smi.o - obj-$(CONFIG_BMP085) += bmp085.o - obj-$(CONFIG_BMP085_I2C) += bmp085-i2c.o - obj-$(CONFIG_BMP085_SPI) += bmp085-spi.o + obj-$(CONFIG_DUMMY_IRQ) += dummy-irq.o + obj-$(CONFIG_ICS932S401) += ics932s401.o + obj-$(CONFIG_LKDTM) += lkdtm.o diff --git a/drivers/misc/bcm2835_smi.c b/drivers/misc/bcm2835_smi.c new file mode 100644 index 0000000000000000000000000000000000000000..63a4ea08b9930a3a31a985f0a1d969b488ed49ec @@ -98910,10 +82579,10 @@ index 0000000000000000000000000000000000000000..ee3a75edfc033eeb0d90a687ffb68b10 + +#endif /* BCM2835_SMI_H */ -From 5b3d8d4688eb4eeaea69a189323e9c5fc0354e69 Mon Sep 17 00:00:00 2001 +From 5c4de9dbae5990f716e77e360a6367588597c2d6 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 26 Apr 2016 14:59:21 +0000 -Subject: [PATCH 047/208] MISC: bcm2835: smi: use clock manager and fix reload +Subject: [PATCH 043/111] MISC: bcm2835: smi: use clock manager and fix reload issues Use clock manager instead of self-made clockmanager. @@ -99083,10 +82752,10 @@ index 63a4ea08b9930a3a31a985f0a1d969b488ed49ec..1261540703127d1d63b9f3c87042c6e5 return 0; } -From c6d205f0fe1e94bc2f07fd3c0891c79719fb4acb Mon Sep 17 00:00:00 2001 +From 0b8fd06e2579f9d9fca4c995c99567e29d4f9ffe Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:16:10 +0100 -Subject: [PATCH 048/208] Add SMI NAND driver +Subject: [PATCH 044/111] Add SMI NAND driver Signed-off-by: Luke Wren --- @@ -99148,7 +82817,7 @@ index 0000000000000000000000000000000000000000..159544d6579070d376d146bd24a86653 +}; \ No newline at end of file diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig -index 21ff58099f3bfd5c042040d2ee7e4bbcbdb6a074..b6a0529b2c15f37983169e3429b67bedb71fb14e 100644 +index 7b7a887b4709f0122f32b60833d8c2e36bc4dead..2db503816a8d5d763bef1b08e3f458d1a2e87751 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -41,6 +41,13 @@ config MTD_SM_COMMON @@ -99157,7 +82826,7 @@ index 21ff58099f3bfd5c042040d2ee7e4bbcbdb6a074..b6a0529b2c15f37983169e3429b67bed +config MTD_NAND_BCM2835_SMI + tristate "Use Broadcom's Secondary Memory Interface as a NAND controller (BCM283x)" -+ depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI && MTD_NAND ++ depends on BCM2835_SMI + default m + help + Uses the BCM2835's SMI peripheral as a NAND controller. @@ -99451,10 +83120,10 @@ index 0000000000000000000000000000000000000000..02adda6da18bd0ba9ab19a104975b79d + ("Driver for NAND chips using Broadcom Secondary Memory Interface"); +MODULE_AUTHOR("Luke Wren "); -From feab27c42b831d89424f2efc1c5eb7a98972712d Mon Sep 17 00:00:00 2001 +From 81a230faec239611f15b7854b0536575b4fec75d Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 049/208] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 045/111] lirc: added support for RaspberryPi GPIO lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others See: https://github.com/raspberrypi/linux/issues/525 @@ -100317,17 +83986,17 @@ index 0000000000000000000000000000000000000000..fb69624ccef00ddbdccf8256d6baf1b1 + +#endif -From fff2289d895dbfc79c794d5a1cd1d8d24435c926 Mon Sep 17 00:00:00 2001 +From f983fc96a1764f6e1de49aa0190ec988bf9ae29d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 050/208] Add cpufreq driver +Subject: [PATCH 046/111] Add cpufreq driver Signed-off-by: popcornmix --- drivers/cpufreq/Kconfig.arm | 9 ++ drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/bcm2835-cpufreq.c | 213 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 223 insertions(+) + drivers/cpufreq/bcm2835-cpufreq.c | 218 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 228 insertions(+) create mode 100644 drivers/cpufreq/bcm2835-cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm @@ -100364,10 +84033,10 @@ index 0a9b6a093646bd1dd60ee092e362b24527f0ef1e..92a628a670c12c39c2be73fc91f65da5 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c new file mode 100644 -index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245c71cf868 +index 0000000000000000000000000000000000000000..414fbdc10dfbfc6e4bb47870a7af3fd5780f9c9a --- /dev/null +++ b/drivers/cpufreq/bcm2835-cpufreq.c -@@ -0,0 +1,213 @@ +@@ -0,0 +1,218 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -100415,12 +84084,8 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 + +/* ---------- GLOBALS ---------- */ +static struct cpufreq_driver bcm2835_cpufreq_driver; /* the cpufreq driver global */ -+ -+static struct cpufreq_frequency_table bcm2835_freq_table[] = { -+ {0, 0, 0}, -+ {0, 0, 0}, -+ {0, 0, CPUFREQ_TABLE_END}, -+}; ++static unsigned int min_frequency, max_frequency; ++static struct cpufreq_frequency_table bcm2835_freq_table[3]; + +/* + =============================================== @@ -100525,10 +84190,19 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 + } + + /* now find out what the maximum and minimum frequencies are */ -+ bcm2835_freq_table[0].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); -+ bcm2835_freq_table[1].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); ++ min_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); ++ max_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); + -+ print_info("min=%d max=%d\n", bcm2835_freq_table[0].frequency, bcm2835_freq_table[1].frequency); ++ if (min_frequency == max_frequency) { ++ bcm2835_freq_table[0].frequency = min_frequency; ++ bcm2835_freq_table[1].frequency = CPUFREQ_TABLE_END; ++ } else { ++ bcm2835_freq_table[0].frequency = min_frequency; ++ bcm2835_freq_table[1].frequency = max_frequency; ++ bcm2835_freq_table[2].frequency = CPUFREQ_TABLE_END; ++ } ++ ++ print_info("min=%d max=%d\n", min_frequency, max_frequency); + return cpufreq_generic_init(policy, bcm2835_freq_table, transition_latency); +} + @@ -100540,7 +84214,7 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 + +static int bcm2835_cpufreq_driver_target_index(struct cpufreq_policy *policy, unsigned int state) +{ -+ unsigned int target_freq = bcm2835_freq_table[state].frequency; ++ unsigned int target_freq = state == 0 ? min_frequency : max_frequency; + unsigned int cur = bcm2835_cpufreq_set_clock(policy->cur, target_freq); + + if (!cur) @@ -100562,7 +84236,7 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 +{ + unsigned int actual_rate = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_CLOCK_RATE); + print_debug("cpu%d: freq=%d\n", cpu, actual_rate); -+ return actual_rate <= bcm2835_freq_table[0].frequency ? bcm2835_freq_table[0].frequency : bcm2835_freq_table[1].frequency; ++ return actual_rate <= min_frequency ? min_frequency : max_frequency; +} + +/* the CPUFreq driver */ @@ -100582,10 +84256,10 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From 37aa96d5731f2657672c71c63c1e1a196b62be02 Mon Sep 17 00:00:00 2001 +From e15412c1981d5de69b4d6e4b4eae8b99c2f4980d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 051/208] Added hwmon/thermal driver for reporting core +Subject: [PATCH 047/111] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -100606,10 +84280,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index 2d702ca6556f5b6185a95ec007ada7b124226272..32ab74bb842d658b6b937e38fa69b8abd31de94b 100644 +index a13541bdc726899807dd8723c92c21312fbc6439..de45ea51555e5f47498c18a969751ea6dc52d6b9 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -282,6 +282,13 @@ config INTEL_POWERCLAMP +@@ -302,6 +302,13 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. @@ -100624,11 +84298,11 @@ index 2d702ca6556f5b6185a95ec007ada7b124226272..32ab74bb842d658b6b937e38fa69b8ab tristate "X86 package temperature thermal driver" depends on X86_THERMAL_VECTOR diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile -index 10b07c14f8a9f75363323d0c69542606d8dfed96..ac19930164fdcc773035a95af8136ec2f36fc8b7 100644 +index c92eb22a41ff89f3f1c61c61977de7eb9ba516ae..bcf9e7503c940821ca260774ba9e1cebf185cd3e 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o - obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o +@@ -41,6 +41,7 @@ obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o + obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o +obj-$(CONFIG_THERMAL_BCM2835) += bcm2835-thermal.o @@ -100751,10 +84425,10 @@ index 0000000000000000000000000000000000000000..c63fb9f9d143e19612a18fe530c7b2b3 +MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); +MODULE_LICENSE("GPL"); -From e92628a6bd90876e0ccea0ac20eaa0ac2445c14c Mon Sep 17 00:00:00 2001 +From 38c98a91730d6c9d0fb64287a0094611e80b74ee Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 052/208] Add Chris Boot's i2c driver +Subject: [PATCH 048/111] Add Chris Boot's i2c driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -100851,14 +84525,14 @@ Check if FIFO can accept data before writing. To avoid a peripheral read on the last iteration of a loop, both bcm2708_bsc_fifo_fill and ~drain are changed as well. --- - drivers/i2c/busses/Kconfig | 21 +- + drivers/i2c/busses/Kconfig | 19 ++ drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-bcm2708.c | 512 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 534 insertions(+), 1 deletion(-) + 3 files changed, 533 insertions(+) create mode 100644 drivers/i2c/busses/i2c-bcm2708.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 5c3993b261298ef3c9571e76307fe912548b9538..37f463232d6db91940763345600b095dbd8b5c58 100644 +index d252276feadf6b0b05cbe370330ed7cef5a16857..b81d8133639a34dcec85df50f064d8e9a9ba22fa 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" @@ -100867,7 +84541,7 @@ index 5c3993b261298ef3c9571e76307fe912548b9538..37f463232d6db91940763345600b095d +config I2C_BCM2708 + tristate "BCM2708 BSC" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + help + Enabling this option will add BSC (Broadcom Serial Controller) + support for the BCM2708. BSC is a Broadcom proprietary bus compatible @@ -100887,17 +84561,8 @@ index 5c3993b261298ef3c9571e76307fe912548b9538..37f463232d6db91940763345600b095d config I2C_ALI1535 tristate "ALI 1535" depends on PCI -@@ -366,7 +385,7 @@ config I2C_AXXIA - - config I2C_BCM2835 - tristate "Broadcom BCM2835 I2C controller" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - If you say yes to this option, support will be included for the - BCM2835 I2C controller. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index 37f2819b4560b0e0947b74c214f5c5a0952bc0ae..e309579e691599031f25bd9b9b36430753f004a7 100644 +index 29764cc20a440752841272ddfed3993048ecd105..26ae016a15e72cbb2e742aa89238636e3b846b8e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -2,6 +2,8 @@ @@ -101428,10 +85093,10 @@ index 0000000000000000000000000000000000000000..962f2e5c7455d91bf32925d785f5f16b +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 10a9053f8e51e5f87b5e3b772c5785ea42971dd7 Mon Sep 17 00:00:00 2001 +From 2580b23fea5c030382c691631a510744f7b9e839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:27:06 +0200 -Subject: [PATCH 053/208] char: broadcom: Add vcio module +Subject: [PATCH 049/111] char: broadcom: Add vcio module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101448,7 +85113,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/char/broadcom/vcio.c diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 2292ed2ac9f457a7d491110e673666136faa5a5e..5489f19f05c620a30541e1a222d77b6ee4356d97 100644 +index f7885466f5bf9c0cf45f2057d07a0d24151f10c3..032164919350db25c586c36f0e05d3e4891fb835 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig @@ -22,6 +22,12 @@ config BCM2708_VCMEM @@ -101657,10 +85322,10 @@ index 0000000000000000000000000000000000000000..c19bc2075c77879563ef5e59038b5a14 +MODULE_DESCRIPTION("Mailbox userspace access"); +MODULE_LICENSE("GPL"); -From d583497e3d8d54010157aed484835a06a45572e7 Mon Sep 17 00:00:00 2001 +From 3802654fe78a70cf73b7b50064ae12b3ad7352a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:25:01 +0200 -Subject: [PATCH 054/208] firmware: bcm2835: Support ARCH_BCM270x +Subject: [PATCH 050/111] firmware: bcm2835: Support ARCH_BCM270x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101670,13 +85335,22 @@ Turn on USB power. Load driver early because of lacking support for deferred probing in many drivers. +Signed-off-by: Noralf Trønnes + +firmware: bcm2835: Don't turn on USB power + +The raspberrypi-power driver is now used to turn on USB power. + +This partly reverts commit: +firmware: bcm2835: Support ARCH_BCM270x + Signed-off-by: Noralf Trønnes --- - drivers/firmware/raspberrypi.c | 41 +++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 39 insertions(+), 2 deletions(-) + drivers/firmware/raspberrypi.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c -index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b868a85f2b5 100644 +index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..3f070bd38a91511c986e3fb114b15bd4ac32634c 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c @@ -28,6 +28,8 @@ struct rpi_firmware { @@ -101688,33 +85362,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 static DEFINE_MUTEX(transaction_lock); static void response_callback(struct mbox_client *cl, void *msg) -@@ -183,6 +185,25 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) - } - } - -+static int raspberrypi_firmware_set_power(struct rpi_firmware *fw, -+ u32 domain, bool on) -+{ -+ struct { -+ u32 domain; -+ u32 on; -+ } packet; -+ int ret; -+ -+ packet.domain = domain; -+ packet.on = on; -+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POWER_STATE, -+ &packet, sizeof(packet)); -+ if (!ret && packet.on != on) -+ ret = -EINVAL; -+ -+ return ret; -+} -+ - static int rpi_firmware_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -207,9 +228,13 @@ static int rpi_firmware_probe(struct platform_device *pdev) +@@ -207,6 +209,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) init_completion(&fw->c); platform_set_drvdata(pdev, fw); @@ -101722,13 +85370,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 rpi_firmware_print_firmware_revision(fw); -+ if (raspberrypi_firmware_set_power(fw, 3, true)) -+ dev_err(dev, "failed to turn on USB power\n"); -+ - return 0; - } - -@@ -218,6 +243,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) +@@ -218,6 +221,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) struct rpi_firmware *fw = platform_get_drvdata(pdev); mbox_free_channel(fw->chan); @@ -101736,7 +85378,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 return 0; } -@@ -230,7 +256,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) +@@ -230,7 +234,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) */ struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) { @@ -101745,7 +85387,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 if (!pdev) return NULL; -@@ -253,7 +279,18 @@ static struct platform_driver rpi_firmware_driver = { +@@ -253,7 +257,18 @@ static struct platform_driver rpi_firmware_driver = { .probe = rpi_firmware_probe, .remove = rpi_firmware_remove, }; @@ -101766,10 +85408,10 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Raspberry Pi firmware driver"); -From 9296e7af762cee3eaeae26c298130bb2cffe4dae Mon Sep 17 00:00:00 2001 +From 722c4b9747c8488a8e9b037948b44085646e874a Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 055/208] bcm2835: add v4l2 camera device +Subject: [PATCH 051/111] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -102149,13 +85791,22 @@ two formats. Detect the old firmware, and reverse the formats if necessary. Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> + +BCM2835-v4l2: Fix a conformance test failure + +Format ioctls: + test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK + warn: v4l2-test-formats.cpp(1195): S_PARM is supported but + doesn't report V4L2_CAP_TIMEPERFRAME. + fail: v4l2-test-formats.cpp(1118): node->has_frmintervals + && !cap->capability --- Documentation/video4linux/bcm2835-v4l2.txt | 60 + drivers/media/platform/Kconfig | 2 + drivers/media/platform/Makefile | 2 + drivers/media/platform/bcm2835/Kconfig | 25 + drivers/media/platform/bcm2835/Makefile | 5 + - drivers/media/platform/bcm2835/bcm2835-camera.c | 2015 ++++++++++++++++++++++ + drivers/media/platform/bcm2835/bcm2835-camera.c | 2016 ++++++++++++++++++++++ drivers/media/platform/bcm2835/bcm2835-camera.h | 145 ++ drivers/media/platform/bcm2835/controls.c | 1345 +++++++++++++++ drivers/media/platform/bcm2835/mmal-common.h | 53 + @@ -102167,7 +85818,7 @@ Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> drivers/media/platform/bcm2835/mmal-parameters.h | 689 ++++++++ drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 ++++++++++++++++++++ drivers/media/platform/bcm2835/mmal-vchiq.h | 178 ++ - 17 files changed, 7204 insertions(+) + 17 files changed, 7205 insertions(+) create mode 100644 Documentation/video4linux/bcm2835-v4l2.txt create mode 100644 drivers/media/platform/bcm2835/Kconfig create mode 100644 drivers/media/platform/bcm2835/Makefile @@ -102251,7 +85902,7 @@ index 0000000000000000000000000000000000000000..c585a8fadf91c5a04453e442fc29ed89 + +$ v4l2-ctl --list-formats diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 552b635cfce7f02b4f3e65d1d641e9e39903ec43..d22e5d5dd939451aa62988f69c6a80ae545011d4 100644 +index ce4a96fccc433c69269a14455ba94e053b515d91..0ea7ea95d824bf95747678e83ee7a61dea6f55cd 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -11,6 +11,8 @@ menuconfig V4L_PLATFORM_DRIVERS @@ -102264,7 +85915,7 @@ index 552b635cfce7f02b4f3e65d1d641e9e39903ec43..d22e5d5dd939451aa62988f69c6a80ae config VIDEO_VIA_CAMERA diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 21771c1a13fbcf9460900826ae2ecb8e2dbaa469..a7a0df8ab6e7672c2e44714a95c95790f55abeb4 100644 +index 40b18d12726ec52d0acfd15894337366eb420e89..b9f01f61c500a9b502d976b4c595be5013610aec 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -2,6 +2,8 @@ @@ -102278,7 +85929,7 @@ index 21771c1a13fbcf9460900826ae2ecb8e2dbaa469..a7a0df8ab6e7672c2e44714a95c95790 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig new file mode 100644 -index 0000000000000000000000000000000000000000..99a5cbccf0f3fa66ad5190ec0942b0c232c3e824 +index 0000000000000000000000000000000000000000..58d5f9600d726cb20e6d04c54c58c53ac3a586d2 --- /dev/null +++ b/drivers/media/platform/bcm2835/Kconfig @@ -0,0 +1,25 @@ @@ -102286,7 +85937,7 @@ index 0000000000000000000000000000000000000000..99a5cbccf0f3fa66ad5190ec0942b0c2 + +config VIDEO_BCM2835 + bool "Broadcom BCM2835 camera interface driver" -+ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) ++ depends on VIDEO_V4L2 && ARCH_BCM2835 + ---help--- + Say Y here to enable camera host interface devices for + Broadcom BCM2835 SoC. This operates over the VCHIQ interface @@ -102309,7 +85960,7 @@ index 0000000000000000000000000000000000000000..99a5cbccf0f3fa66ad5190ec0942b0c2 +endif # VIDEO_BM2835 diff --git a/drivers/media/platform/bcm2835/Makefile b/drivers/media/platform/bcm2835/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..f17c79c33e4a07a2294907d3c748b4d62fc55e21 +index 0000000000000000000000000000000000000000..b14ea91ac79c60f83bc63156436ef8cbcc893e9b --- /dev/null +++ b/drivers/media/platform/bcm2835/Makefile @@ -0,0 +1,5 @@ @@ -102317,13 +85968,13 @@ index 0000000000000000000000000000000000000000..f17c79c33e4a07a2294907d3c748b4d6 + +obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o + -+ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 ++ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c new file mode 100644 -index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478809eb161 +index 0000000000000000000000000000000000000000..4f03949aecf3afbf2e04df38289447195a8847a6 --- /dev/null +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -0,0 +1,2015 @@ +@@ -0,0 +1,2016 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -102570,7 +86221,7 @@ index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478 + +static int queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, -+ unsigned int sizes[], void *alloc_ctxs[]) ++ unsigned int sizes[], struct device *alloc_ctxs[]) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); + unsigned long size; @@ -103725,6 +87376,7 @@ index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478 + dev->capture.timeperframe = tpf; + parm->parm.capture.timeperframe = tpf; + parm->parm.capture.readbuffers = 1; ++ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + + fps_param.num = 0; /* Select variable fps, and then use + * FPS_RANGE to select the actual limits. @@ -109501,10 +93153,10 @@ index 0000000000000000000000000000000000000000..9d1d11e4a53e510c04a416d92d195a7d + +#endif /* MMAL_VCHIQ_H */ -From 11b448942d10a35fb98c8b1f91c78b8ede600c37 Mon Sep 17 00:00:00 2001 +From badabbef8c2ed82582e881b667ff7fe28f7180e0 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 056/208] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 052/111] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -109562,10 +93214,17 @@ scripts/knlinfo: Decode DDTK atom Show the DDTK atom as being a boolean. Signed-off-by: Phil Elwell + +mkknlimg: Retain downstream-kernel detection + +With the death of ARCH_BCM2708 and ARCH_BCM2709, a new way is needed to +determine if this is a "downstream" build that wants the firmware to +load a bcm27xx .dtb. The vc_cma driver is used downstream but not +upstream, making vc_cma_init a suitable predicate symbol. --- - scripts/knlinfo | 171 ++++++++++++++++++++++++++++++++++++ - scripts/mkknlimg | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 434 insertions(+) + scripts/knlinfo | 171 +++++++++++++++++++++++++++++++++++ + scripts/mkknlimg | 264 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 435 insertions(+) create mode 100755 scripts/knlinfo create mode 100755 scripts/mkknlimg @@ -109748,10 +93407,10 @@ index 0000000000000000000000000000000000000000..263ec937eaa70b4fd00bff18599db7f2 +} diff --git a/scripts/mkknlimg b/scripts/mkknlimg new file mode 100755 -index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa60624f87f98 +index 0000000000000000000000000000000000000000..60206de7fa9a49bd027c635306674a29a568652f --- /dev/null +++ b/scripts/mkknlimg -@@ -0,0 +1,263 @@ +@@ -0,0 +1,264 @@ +#!/usr/bin/env perl +# ---------------------------------------------------------------------- +# mkknlimg by Phil Elwell for Raspberry Pi @@ -109831,7 +93490,8 @@ index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa606 + 'brcm,bcm2709' => FLAG_PI | FLAG_DTOK | FLAG_270X, + 'brcm,bcm2835' => FLAG_PI | FLAG_DTOK | FLAG_283X, + 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, -+ 'of_overlay_apply' => FLAG_DTOK | FLAG_DDTK, ++ 'of_cfs_init' => FLAG_DTOK | FLAG_DDTK, ++ 'vc_cma_init' => FLAG_PI | FLAG_270X, +}; + +my $res = try_extract($kernel_file, $tmpfile1); @@ -110016,10 +93676,10 @@ index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa606 + return $trailer; +} -From 804f05236652ec5169092c4b102faa5979b92b27 Mon Sep 17 00:00:00 2001 +From 5588e71a027a865ad341fe3d30dd47c2c1772d57 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 10 Aug 2015 09:49:15 +0100 -Subject: [PATCH 057/208] scripts/dtc: Update to upstream version 1.4.1 +Subject: [PATCH 053/111] scripts/dtc: Update to upstream version 1.4.1 Includes the new localfixups format. @@ -112870,10 +96530,13 @@ index ad9b05ae698b0495ecbda42ffcf4743555313a27..2595dfda020fd9e03f0beff5006f229d -#define DTC_VERSION "DTC 1.4.1-g53bf130b" +#define DTC_VERSION "DTC 1.4.1-g25efc119" -From 87dc2c03954f71140aa60b8e5a2f35ad8236cd08 Mon Sep 17 00:00:00 2001 +From c5c6e46a51b163e9a3faf7422693f14b7bdb94d8 Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 058/208] BCM2708: Add core Device Tree support +Subject: [PATCH 054/111] BCM2708: Add core Device Tree support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Add the bare minimum needed to boot BCM2708 from a Device Tree. @@ -112938,23 +96601,137 @@ The "mmc" overlay reverts to using the other controller. squash: Add cprman to dt BCM270X_DT: Use clk_core for I2C interfaces + +BCM270X_DT: Use bcm283x.dtsi, bcm2835.dtsi and bcm2836.dtsi + +The mainline Device Tree files are quite close to downstream now. +Let's use bcm283x.dtsi, bcm2835.dtsi and bcm2836.dtsi as base files +for our dts files. + +Mainline dts files are based on these files: + + bcm2835-rpi.dtsi + bcm2835.dtsi bcm2836.dtsi + bcm283x.dtsi + +Current downstream are based on these: + + bcm2708.dtsi bcm2709.dtsi bcm2710.dtsi + bcm2708_common.dtsi + +This patch introduces this dependency: + + bcm2708.dtsi bcm2709.dtsi + bcm2708-rpi.dtsi + bcm270x.dtsi + bcm2835.dtsi bcm2836.dtsi + bcm283x.dtsi + +And: + bcm2710.dtsi + bcm2708-rpi.dtsi + bcm270x.dtsi + bcm283x.dtsi + +bcm270x.dtsi contains the downstream bcm283x.dtsi diff. +bcm2708-rpi.dtsi is the downstream version of bcm2835-rpi.dtsi. + +Other changes: +- The led node has moved from /soc/leds to /leds. This is not a problem + since the label is used to reference it. +- The clk_osc reg property changes from 6 to 3. +- The gpu nodes has their interrupt property set in the base file. +- the clocks label does not point to the /clocks node anymore, but + points to the cprman node. This is not a problem since the overlays + that use the clock node refer to it directly: target-path = "/clocks"; +- some nodes now have 2 labels since mainline and downstream differs in + this respect: cprman/clocks, spi0/spi, gpu/vc4. +- some nodes doesn't have an explicit status = "okay" since they're not + disabled in the base file: watchdog and random. +- gpiomem doesn't need an explicit status = "okay". +- bcm2708-rpi-cm.dts got the hpd-gpios property from bcm2708_common.dtsi, + it's now set directly in that file. +- bcm2709-rpi-2-b.dts has the timer node moved from /soc/timer to /timer. +- Removed clock-frequency property on the bcm{2709,2710}.dtsi timer nodes. + +Signed-off-by: Noralf Trønnes + +BCM270X_DT: Use raspberrypi-power to turn on USB power + +Use the raspberrypi-power driver to turn on USB power. + +Signed-off-by: Noralf Trønnes + +BCM270X_DT: Add a .dtbo target, use for overlays + +Change the filenames and extensions to keep the pre-DDT style of +overlay (-overlay.dtb) distinct from new ones that use a +different style of local fixups (.dtbo), and to match other +platforms. + +The RPi firmware uses the DDTK trailer atom to choose which type of +overlay to use for each kernel. + +Signed-off-by: Phil Elwell + +BCM270X_DT: Don't generate "linux,phandle" props + +The EPAPR standard says to use "phandle" properties to store phandles, +rather than the deprecated "linux,phandle" version. By default, dtc +generates both, but adding "-H epapr" causes it to only generate +"phandle"s, saving some space and clutter. + +Signed-off-by: Phil Elwell + +BCM270X_DT: Add overlay for enc28j60 on SPI2 + +Works on SPI2 for compute module + +BCM270X_DT: Add midi-uart0 overlay + +MIDI requires 31.25kbaud, a baudrate unsupported by Linux. The +midi-uart0 overlay configures uart0 (ttyAMA0) to use a fake clock +so that requesting 38.4kbaud actually gets 31.25kbaud. + +Signed-off-by: Phil Elwell + +BCM270X_DT: Add i2c-sensor overlay + +The i2c-sensor overlay is a container for various pressure and +temperature sensors, currently bmp085 and bmp280. The standalone +bmp085_i2c-sensor overlay is now deprecated. + +Signed-off-by: Phil Elwell + +BCM270X_DT: overlays/*-overlay.dtb -> overlays/*.dtbo (#1752) + +We now create overlays as .dtbo files. + +build: support for .dtbo files for dtb overlays + +Kernel 4.4.6+ on RaspberryPi support .dtbo files for overlays, instead of .dtb. +Patch the kernel, which has faulty rules to generate .dtbo the way yocto does + +Signed-off-by: Herve Jourdain +Signed-off-by: Khem Raj --- - arch/arm/boot/dts/Makefile | 32 + - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 162 +++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 152 +++ - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 106 ++ + arch/arm/Makefile | 2 + + arch/arm/boot/.gitignore | 2 +- + arch/arm/boot/dts/Makefile | 19 + + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 156 +++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 146 +++ + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 105 ++ arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 50 + - arch/arm/boot/dts/bcm2708.dtsi | 40 + - arch/arm/boot/dts/bcm2708_common.dtsi | 436 +++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 162 +++ - arch/arm/boot/dts/bcm2709.dtsi | 102 ++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 213 ++++ - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 162 +++ - arch/arm/boot/dts/bcm2710.dtsi | 165 +++ - arch/arm/boot/dts/bcm2835-rpi-cm.dts | 93 ++ - arch/arm/boot/dts/bcm2835-rpi-cm.dtsi | 30 + - arch/arm/boot/dts/overlays/Makefile | 111 ++ - arch/arm/boot/dts/overlays/README | 1302 ++++++++++++++++++++ + arch/arm/boot/dts/bcm2708-rpi.dtsi | 109 ++ + arch/arm/boot/dts/bcm2708.dtsi | 16 + + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 156 +++ + arch/arm/boot/dts/bcm2709.dtsi | 22 + + arch/arm/boot/dts/bcm270x.dtsi | 141 ++ + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 203 +++ + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 155 +++ + arch/arm/boot/dts/bcm2710.dtsi | 155 +++ + arch/arm/boot/dts/overlays/Makefile | 105 ++ + arch/arm/boot/dts/overlays/README | 1368 ++++++++++++++++++++ .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 53 + arch/arm/boot/dts/overlays/ads1015-overlay.dts | 98 ++ arch/arm/boot/dts/overlays/ads7846-overlay.dts | 89 ++ @@ -112971,6 +96748,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 20 + arch/arm/boot/dts/overlays/dwc2-overlay.dts | 29 + arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 53 + + .../boot/dts/overlays/enc28j60-spi2-overlay.dts | 47 + arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 44 + .../boot/dts/overlays/gpio-poweroff-overlay.dts | 34 + .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 + @@ -112980,10 +96758,12 @@ BCM270X_DT: Use clk_core for I2C interfaces .../dts/overlays/hifiberry-digi-pro-overlay.dts | 41 + arch/arm/boot/dts/overlays/hy28a-overlay.dts | 93 ++ arch/arm/boot/dts/overlays/hy28b-overlay.dts | 148 +++ + arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts | 13 + arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 43 + - arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 139 +++ + arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 139 ++ .../boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts | 26 + - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 73 ++ + arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 83 ++ + arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 34 + .../arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts | 61 + .../arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts | 37 + .../boot/dts/overlays/i2s-gpio28-31-overlay.dts | 18 + @@ -112997,6 +96777,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/mcp23s17-overlay.dts | 732 +++++++++++ .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 73 ++ .../arm/boot/dts/overlays/mcp2515-can1-overlay.dts | 73 ++ + arch/arm/boot/dts/overlays/midi-uart0-overlay.dts | 36 + arch/arm/boot/dts/overlays/mmc-overlay.dts | 38 + arch/arm/boot/dts/overlays/mz61581-overlay.dts | 117 ++ arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts | 27 + @@ -113004,9 +96785,11 @@ BCM270X_DT: Use clk_core for I2C interfaces .../boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 64 + arch/arm/boot/dts/overlays/piscreen-overlay.dts | 102 ++ arch/arm/boot/dts/overlays/piscreen2r-overlay.dts | 106 ++ - arch/arm/boot/dts/overlays/pitft22-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/pisound-overlay.dts | 114 ++ + arch/arm/boot/dts/overlays/pitft22-overlay.dts | 69 + .../dts/overlays/pitft28-capacitive-overlay.dts | 91 ++ .../dts/overlays/pitft28-resistive-overlay.dts | 121 ++ + .../dts/overlays/pitft35-resistive-overlay.dts | 121 ++ arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 35 + arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts | 47 + arch/arm/boot/dts/overlays/pwm-overlay.dts | 43 + @@ -113026,38 +96809,40 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/sdio-overlay.dts | 36 + arch/arm/boot/dts/overlays/sdtweak-overlay.dts | 23 + arch/arm/boot/dts/overlays/smi-dev-overlay.dts | 18 + - arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 69 + arch/arm/boot/dts/overlays/smi-overlay.dts | 37 + .../boot/dts/overlays/spi-gpio35-39-overlay.dts | 31 + arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 33 + arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts | 26 + arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts | 57 + - arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 69 + arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts | 81 ++ arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts | 57 + - arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts | 69 + arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts | 81 ++ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 224 ++++ arch/arm/boot/dts/overlays/uart1-overlay.dts | 38 + + .../arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 89 ++ arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 136 ++ arch/arm/boot/dts/overlays/vga666-overlay.dts | 30 + arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 + .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 + arch/arm/boot/dts/overlays/wittypi-overlay.dts | 44 + - 105 files changed, 8906 insertions(+) + scripts/Makefile.dtbinst | 10 +- + scripts/Makefile.lib | 11 + + 115 files changed, 8979 insertions(+), 4 deletions(-) create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts - create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dts create mode 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi + create mode 100644 arch/arm/boot/dts/bcm2708-rpi.dtsi create mode 100644 arch/arm/boot/dts/bcm2708.dtsi - create mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi create mode 100644 arch/arm/boot/dts/bcm2709-rpi-2-b.dts create mode 100644 arch/arm/boot/dts/bcm2709.dtsi + create mode 100644 arch/arm/boot/dts/bcm270x.dtsi create mode 100644 arch/arm/boot/dts/bcm2710-rpi-3-b.dts create mode 100644 arch/arm/boot/dts/bcm2710-rpi-cm3.dts create mode 100644 arch/arm/boot/dts/bcm2710.dtsi - create mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dts - create mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dtsi create mode 100644 arch/arm/boot/dts/overlays/Makefile create mode 100644 arch/arm/boot/dts/overlays/README create mode 100644 arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts @@ -113076,6 +96861,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/dwc-otg-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dwc2-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/gpio-ir-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts @@ -113085,10 +96871,12 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/hy28a-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/hy28b-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-mux-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts @@ -113102,6 +96890,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/mcp23s17-overlay.dts create mode 100755 arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart0-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mmc-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mz61581-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts @@ -113109,9 +96898,11 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/piscreen-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/piscreen2r-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pisound-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pitft22-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pps-gpio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pwm-overlay.dts @@ -113144,45 +96935,55 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/tinylcd35-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/uart1-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vga666-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/wittypi-overlay.dts +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 6be9ee148b78b964004392045199ec8d1540134e..b1c49e2a0c5f5ef2939102625171b26cd5372016 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -334,6 +334,8 @@ $(INSTALL_TARGETS): + + %.dtb: | scripts + $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ ++%.dtbo: | scripts ++ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ + + PHONY += dtbs dtbs_install + +diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore +index 3c79f85975aaa26c7c2e353fefc54d71d89bc5bf..eaaeb17e5986e5f7178b2851169444ac7e45be8d 100644 +--- a/arch/arm/boot/.gitignore ++++ b/arch/arm/boot/.gitignore +@@ -3,4 +3,4 @@ zImage + xipImage + bootpImage + uImage +-*.dtb ++*.dtb* diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index faacd52370d24061e705d4e97785c254cf147f8c..71f794ecc710ac533731854bd95961a6a4175b64 100644 +index c558ba75cbccf909063e0f4f131f7efdfd28867b..ec218dcb67019acacd4a6c73c74d12ef4f4204d8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -1,5 +1,27 @@ +@@ -1,5 +1,13 @@ ifeq ($(CONFIG_OF),y) -+dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b.dtb -+dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b-plus.dtb -+dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-cm.dtb -+dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-cm.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2709-rpi-2-b.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb -+ -+# Raspberry Pi -+ifeq ($(CONFIG_ARCH_BCM2708),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2709),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(RPI_DT_OVERLAYS),y) -+ dts-dirs += overlays -+endif ++dtb-$(CONFIG_ARCH_BCM2835) += \ ++ bcm2708-rpi-b.dtb \ ++ bcm2708-rpi-b-plus.dtb \ ++ bcm2708-rpi-cm.dtb \ ++ bcm2709-rpi-2-b.dtb \ ++ bcm2710-rpi-3-b.dtb \ ++ bcm2710-rpi-cm3.dtb + dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -919,10 +941,20 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ +@@ -954,10 +962,21 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \ aspeed-ast2500-evb.dtb @@ -113196,25 +96997,25 @@ index faacd52370d24061e705d4e97785c254cf147f8c..71f794ecc710ac533731854bd95961a6 dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) always := $(dtb-y) -+subdir-y := $(dts-dirs) ++subdir-y := overlays clean-files := *.dtb + -+# Enable fixups to support overlays on BCM2708 platforms -+ifeq ($(RPI_DT_OVERLAYS),y) ++# Enable fixups to support overlays on BCM2835 platforms ++ifeq ($(CONFIG_ARCH_BCM2835),y) + DTC_FLAGS ?= -@ -H epapr ++ dts-dirs += overlays +endif diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts new file mode 100644 -index 0000000000000000000000000000000000000000..6c16c325cd2887a42c42665273834618c1937918 +index 0000000000000000000000000000000000000000..360da5c928dc5599b0d2a9055728087604c6b189 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,162 @@ +@@ -0,0 +1,156 @@ +/dts-v1/; + +#include "bcm2708.dtsi" + +/ { -+ compatible = "brcm,bcm2708"; + model = "Raspberry Pi Model B+"; +}; + @@ -113309,15 +97110,10 @@ index 0000000000000000000000000000000000000000..6c16c325cd2887a42c42665273834618 +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -113373,16 +97169,15 @@ index 0000000000000000000000000000000000000000..6c16c325cd2887a42c42665273834618 +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..7c132437671d43e76445a4bf1184cc9a316b0965 +index 0000000000000000000000000000000000000000..9c49659ab246bce0656f3514f3b924bc4826b421 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,152 @@ +@@ -0,0 +1,146 @@ +/dts-v1/; + +#include "bcm2708.dtsi" + +/ { -+ compatible = "brcm,bcm2708"; + model = "Raspberry Pi Model B"; +}; + @@ -113477,15 +97272,10 @@ index 0000000000000000000000000000000000000000..7c132437671d43e76445a4bf1184cc9a +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -113530,11 +97320,11 @@ index 0000000000000000000000000000000000000000..7c132437671d43e76445a4bf1184cc9a + }; +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -new file mode 100755 -index 0000000000000000000000000000000000000000..ce9f54ff7e4ce76ad25ad0a19cf2ad48ba9df01a +new file mode 100644 +index 0000000000000000000000000000000000000000..eb8662f0d222b4c0a9a2bcb8bccb13e86a0006b3 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -0,0 +1,106 @@ +@@ -0,0 +1,105 @@ +/dts-v1/; + +#include "bcm2708-rpi-cm.dtsi" @@ -113618,13 +97408,12 @@ index 0000000000000000000000000000000000000000..ce9f54ff7e4ce76ad25ad0a19cf2ad48 +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; +}; + +/ { @@ -113697,67 +97486,22 @@ index 0000000000000000000000000000000000000000..d33d462b4090e4a4f967a37212918b9c + sd_overclock = <&mmc>,"brcm,overclock-50:0"; + }; +}; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi +diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..f5a44cd4fef0ee221ed6ae1c43ca81dabffa110d +index 0000000000000000000000000000000000000000..46cf8602c3b96e477b05b57dbfe5e349930c9d9a --- /dev/null -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -0,0 +1,40 @@ -+#include "bcm2708_common.dtsi" ++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi +@@ -0,0 +1,109 @@ ++/* Downstream version of bcm2835-rpi.dtsi */ ++ ++#include + +/ { -+ compatible = "brcm,bcm2708"; -+ model = "BCM2708"; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; ++ memory { ++ device_type = "memory"; ++ reg = <0x0 0x0>; + }; + -+ soc { -+ ranges = <0x7e000000 0x20000000 0x01000000>; -+ -+ timer@7e003000 { -+ compatible = "brcm,bcm2835-system-timer"; -+ reg = <0x7e003000 0x1000>; -+ interrupts = <1 0>, <1 1>, <1 2>, <1 3>; -+ clock-frequency = <1000000>; -+ }; -+ -+ arm-pmu { -+ compatible = "arm,arm1176-pmu"; -+ }; -+ -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ status = "okay"; -+ }; -+ }; -+}; -+ -+&intc { -+ compatible = "brcm,bcm2835-armctrl-ic"; -+}; -+ -+&watchdog { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de13b5717ef ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -0,0 +1,436 @@ -+#include "dt-bindings/clock/bcm2835.h" -+#include -+#include "dt-bindings/power/raspberrypi-power.h" -+#include "dt-bindings/gpio/gpio.h" -+#include "skeleton.dtsi" -+ -+/ { -+ interrupt-parent = <&intc>; -+ + aliases { + audio = &audio; + aux = &aux; @@ -113771,7 +97515,7 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + gpio = &gpio; + uart0 = &uart0; + sdhost = &sdhost; -+ i2s = &i2s; ++ i2s = &i2s; + spi0 = &spi0; + i2c0 = &i2c0; + uart1 = &uart1; @@ -113785,333 +97529,16 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + fb = &fb; + vchiq = &vchiq; + thermal = &thermal; -+ clocks = &clocks; + }; + -+ soc: soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; ++ leds: leds { ++ compatible = "gpio-leds"; ++ }; + -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ reg = <0x7e007000 0xf00>; -+ interrupts = <1 16>, -+ <1 17>, -+ <1 18>, -+ <1 19>, -+ <1 20>, -+ <1 21>, -+ <1 22>, -+ <1 23>, -+ <1 24>, -+ <1 25>, -+ <1 26>, -+ /* dma channel 11-14 share one irq */ -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ /* unused shared irq for all channels */ -+ <1 28>; -+ interrupt-names = "dma0", -+ "dma1", -+ "dma2", -+ "dma3", -+ "dma4", -+ "dma5", -+ "dma6", -+ "dma7", -+ "dma8", -+ "dma9", -+ "dma10", -+ "dma11", -+ "dma12", -+ "dma13", -+ "dma14", -+ "dma-shared-all"; -+ -+ #dma-cells = <1>; -+ brcm,dma-channel-mask = <0x7f34>; -+ }; -+ -+ intc: interrupt-controller@7e00b200 { -+#ifdef RPI364 -+ compatible = "brcm,bcm2835-armctrl-ic", "brcm,bcm2708-armctrl-ic"; -+#else -+ compatible = "brcm,bcm2708-armctrl-ic"; -+#endif -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ mailbox: mailbox@7e00b800 { -+ compatible = "brcm,bcm2835-mbox"; -+ reg = <0x7e00b880 0x40>; -+ interrupts = <0 1>; -+ #mbox-cells = <0>; -+ }; -+ -+ watchdog: watchdog@7e100000 { -+ compatible = "brcm,bcm2835-pm-wdt"; -+ reg = <0x7e100000 0x28>; -+ status = "disabled"; -+ }; -+ -+ cprman: cprman@7e101000 { -+ compatible = "brcm,bcm2835-cprman"; -+ #clock-cells = <1>; -+ reg = <0x7e101000 0x2000>; -+ -+ /* CPRMAN derives everything from the platform's -+ * oscillator. -+ */ -+ clocks = <&clk_osc>; -+ }; -+ -+ random: rng@7e104000 { -+ compatible = "brcm,bcm2835-rng"; -+ reg = <0x7e104000 0x10>; -+ status = "disabled"; -+ }; -+ -+ gpio: gpio@7e200000 { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ uart0: serial@7e201000 { -+ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; -+ reg = <0x7e201000 0x1000>; -+ interrupts = <2 25>; -+ clocks = <&cprman BCM2835_CLOCK_UART>, -+ <&cprman BCM2835_CLOCK_VPU>; -+ clock-names = "uartclk","apb_pclk"; -+ arm,primecell-periphid = <0x00241011>; // For an explanation, see -+ // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 -+ status = "disabled"; -+ }; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ interrupts = <2 24>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ dmas = <&dma 13>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ brcm,pio-limit = <1>; -+ status = "disabled"; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2835-i2s"; -+ #sound-dai-cells = <0>; -+ reg = <0x7e203000 0x24>; -+ clocks = <&cprman BCM2835_CLOCK_PCM>; -+ -+ dmas = <&dma 2>, <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2835-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ /* the dma channels */ -+ dmas = <&dma 6>, <&dma 7>; -+ dma-names = "tx", "rx"; -+ /* the chipselects used - <0> means native GPIO -+ * add more gpios if necessary as <&gpio 6 1> -+ * (but do not forget to make them output!) -+ */ -+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pixelvalve0: pixelvalve@7e206000 { -+ compatible = "brcm,bcm2835-pixelvalve0"; -+ reg = <0x7e206000 0x100>; -+ status = "disabled"; -+ }; -+ -+ dpi: dpi@7e208000 { -+ compatible = "brcm,bcm2835-dpi"; -+ reg = <0x7e208000 0x8c>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>, -+ <&cprman BCM2835_CLOCK_DPI>; -+ clock-names = "core", "pixel"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pixelvalve1: pixelvalve@7e207000 { -+ compatible = "brcm,bcm2835-pixelvalve1"; -+ reg = <0x7e207000 0x100>; -+ status = "disabled"; -+ }; -+ -+ pwm: pwm@7e20c000 { -+ compatible = "brcm,bcm2835-pwm"; -+ reg = <0x7e20c000 0x28>; -+ clocks = <&cprman BCM2835_CLOCK_PWM>; -+ assigned-clocks = <&cprman BCM2835_CLOCK_PWM>; -+ assigned-clock-rates = <10000000>; -+ #pwm-cells = <2>; -+ status = "disabled"; -+ }; -+ -+ aux: aux@0x7e215000 { -+ compatible = "brcm,bcm2835-aux"; -+ #clock-cells = <1>; -+ reg = <0x7e215000 0x8>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ }; -+ -+ uart1: serial@7e215040 { -+ compatible = "brcm,bcm2835-aux-uart"; -+ reg = <0x7e215040 0x40>; -+ interrupts = <1 29>; -+ clocks = <&aux BCM2835_AUX_CLOCK_UART>; -+ status = "disabled"; -+ }; -+ -+ spi1: spi@7e215080 { -+ compatible = "brcm,bcm2835-aux-spi"; -+ reg = <0x7e215080 0x40>; -+ interrupts = <1 29>; -+ clocks = <&aux BCM2835_AUX_CLOCK_SPI1>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ spi2: spi@7e2150C0 { -+ compatible = "brcm,bcm2835-aux-spi"; -+ reg = <0x7e2150C0 0x40>; -+ interrupts = <1 29>; -+ clocks = <&aux BCM2835_AUX_CLOCK_SPI2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&cprman BCM2835_CLOCK_EMMC>; -+ dmas = <&dma 11>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ status = "disabled"; -+ }; -+ -+ hvs: hvs@7e400000 { -+ compatible = "brcm,bcm2835-hvs"; -+ reg = <0x7e400000 0x6000>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c2: i2c@7e805000 { -+ // Beware - this is shared with the HDMI module. -+ // Careless use may break (really) your display. -+ // Caveat emptor. -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e805000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ smi: smi@7e600000 { -+ compatible = "brcm,bcm2835-smi"; -+ reg = <0x7e600000 0x100>; -+ interrupts = <2 16>; -+ clocks = <&cprman BCM2835_CLOCK_SMI>; -+ assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; -+ assigned-clock-rates = <125000000>; -+ dmas = <&dma 4>; -+ dma-names = "rx-tx"; -+ status = "disabled"; -+ }; -+ -+ pixelvalve2: pixelvalve@7e807000 { -+ compatible = "brcm,bcm2835-pixelvalve2"; -+ reg = <0x7e807000 0x100>; -+ status = "disabled"; -+ }; -+ -+ hdmi: hdmi@7e902000 { -+ compatible = "brcm,bcm2835-hdmi"; -+ reg = <0x7e902000 0x600>, -+ <0x7e808000 0x100>; -+ ddc = <&i2c2>; -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; -+ clocks = <&cprman BCM2835_PLLH_PIX>, -+ <&cprman BCM2835_CLOCK_HSM>; -+ clock-names = "pixel", "hdmi"; -+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>; -+ status = "disabled"; -+ }; -+ -+#ifdef RPI364 -+ usb: usb@7e980000 { -+ compatible = "brcm,bcm2835-usb"; -+ reg = <0x7e980000 0x10000>; -+ interrupts = <1 9>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+#else -+ usb: usb@7e980000 { -+ compatible = "brcm,bcm2708-usb"; -+ reg = <0x7e980000 0x10000>, -+ <0x7e006000 0x1000>; -+ interrupts = <2 0>, -+ <1 9>; -+ }; -+#endif -+ -+ v3d: v3d@7ec00000 { -+ compatible = "brcm,vc4-v3d"; -+ reg = <0x7ec00000 0x1000>; -+ status = "disabled"; ++ soc { ++ gpiomem { ++ compatible = "brcm,bcm2835-gpiomem"; ++ reg = <0x7e200000 0x1000>; + }; + + firmware: firmware { @@ -114125,10 +97552,6 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + #power-domain-cells = <1>; + }; + -+ leds: leds { -+ compatible = "gpio-leds"; -+ }; -+ + fb: fb { + compatible = "brcm,bcm2708-fb"; + firmware = <&firmware>; @@ -114148,11 +97571,6 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + firmware = <&firmware>; + }; + -+ gpu: gpu { -+ compatible = "brcm,bcm2835-vc4"; -+ status = "disabled"; -+ }; -+ + /* Onboard audio */ + audio: audio { + compatible = "brcm,bcm2835-audio"; @@ -114164,39 +97582,58 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + sound: sound { + status = "disabled"; + }; -+ }; + -+ clocks: clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* The oscillator is the root of the clock tree. */ -+ clk_osc: clock@6 { -+ compatible = "fixed-clock"; -+ reg = <6>; -+ #clock-cells = <0>; -+ clock-output-names = "osc"; -+ clock-frequency = <19200000>; -+ }; + }; + + __overrides__ { + cache_line_size = <&vchiq>, "cache-line-size:0"; + }; +}; ++ ++&dma { ++ brcm,dma-channel-mask = <0x7f34>; ++}; ++ ++&hdmi { ++ power-domains = <&power RPI_POWER_DOMAIN_HDMI>; ++}; ++ ++&usb { ++ power-domains = <&power RPI_POWER_DOMAIN_USB>; ++}; +diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi +new file mode 100644 +index 0000000000000000000000000000000000000000..0f72bd90c591a2e8752d7437fa7e8c6308bd8c3f +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708.dtsi +@@ -0,0 +1,16 @@ ++#include "bcm2835.dtsi" ++#include "bcm270x.dtsi" ++#include "bcm2708-rpi.dtsi" ++ ++/ { ++ soc { ++ timer@7e003000 { ++ compatible = "brcm,bcm2835-system-timer"; ++ reg = <0x7e003000 0x1000>; ++ interrupts = <1 0>, <1 1>, <1 2>, <1 3>; ++ clock-frequency = <1000000>; ++ }; ++ }; ++ ++ /delete-node/ cpus; ++}; diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..74fe4cc1d667e9508ca860bcc8c837fed0cbb855 +index 0000000000000000000000000000000000000000..19c83823420fc3cc20a01d07091100cb8720ff4d --- /dev/null +++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,162 @@ +@@ -0,0 +1,156 @@ +/dts-v1/; + +#include "bcm2709.dtsi" + +/ { -+ compatible = "brcm,bcm2709"; + model = "Raspberry Pi 2 Model B"; +}; + @@ -114291,15 +97728,10 @@ index 0000000000000000000000000000000000000000..74fe4cc1d667e9508ca860bcc8c837fe +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -114355,118 +97787,185 @@ index 0000000000000000000000000000000000000000..74fe4cc1d667e9508ca860bcc8c837fe +}; diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..a8cfd7c4df5bcf7692d13882833c97852649932d +index 0000000000000000000000000000000000000000..343437db94820bb75a9b81e8bc6ecf6f31d9f04c --- /dev/null +++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -0,0 +1,102 @@ -+#include "bcm2708_common.dtsi" +@@ -0,0 +1,22 @@ ++#include "bcm2836.dtsi" ++#include "bcm270x.dtsi" ++#include "bcm2708-rpi.dtsi" + +/ { -+ compatible = "brcm,bcm2709"; -+ model = "BCM2709"; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; -+ + soc { + ranges = <0x7e000000 0x3f000000 0x01000000>, + <0x40000000 0x40000000 0x00040000>; + -+ local_intc: local_intc { -+ compatible = "brcm,bcm2836-l1-intc"; -+ reg = <0x40000000 0x100>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ interrupt-parent = <&local_intc>; -+ }; -+ -+ arm-pmu { -+ compatible = "arm,cortex-a7-pmu"; -+ interrupt-parent = <&local_intc>; -+ interrupts = <9>; -+ }; -+ -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ status = "okay"; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ clock-frequency = <19200000>; -+ interrupt-parent = <&local_intc>; -+ interrupts = <0>, // PHYS_SECURE_PPI -+ <1>, // PHYS_NONSECURE_PPI -+ <3>, // VIRT_PPI -+ <2>; // HYP_PPI -+ always-on; -+ }; -+ + syscon@40000000 { + compatible = "brcm,bcm2836-arm-local", "syscon"; + reg = <0x40000000 0x100>; + }; + }; + -+ cpus: cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ v7_cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf00>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf01>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf02>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf03>; -+ clock-frequency = <800000000>; -+ }; -+ }; -+ + __overrides__ { + arm_freq = <&v7_cpu0>, "clock-frequency:0", -+ <&v7_cpu1>, "clock-frequency:0", -+ <&v7_cpu2>, "clock-frequency:0", -+ <&v7_cpu3>, "clock-frequency:0"; ++ <&v7_cpu1>, "clock-frequency:0", ++ <&v7_cpu2>, "clock-frequency:0", ++ <&v7_cpu3>, "clock-frequency:0"; + }; +}; +diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi +new file mode 100644 +index 0000000000000000000000000000000000000000..a46cb4a8b1419edd95e0e07c18b0f373222dc2bf +--- /dev/null ++++ b/arch/arm/boot/dts/bcm270x.dtsi +@@ -0,0 +1,141 @@ ++/* Downstream bcm283x.dtsi diff */ ++#include "dt-bindings/power/raspberrypi-power.h" + -+&watchdog { -+ status = "okay"; -+}; ++/ { ++ chosen { ++ bootargs = ""; ++ }; + -+&intc { -+ compatible = "brcm,bcm2836-armctrl-ic"; -+ interrupt-parent = <&local_intc>; -+ interrupts = <8>; ++ soc: soc { ++ ++ /delete-node/ timer@7e003000; ++ ++ watchdog: watchdog@7e100000 { ++ /* Add alias */ ++ }; ++ ++ cprman: cprman@7e101000 { ++ /* Add alias */ ++ }; ++ ++ random: rng@7e104000 { ++ /* Add alias */ ++ }; ++ ++ gpio@7e200000 { /* gpio */ ++ interrupts = <2 17>, <2 18>; ++ }; ++ ++ sdhost: sdhost@7e202000 { ++ compatible = "brcm,bcm2835-sdhost"; ++ reg = <0x7e202000 0x100>; ++ interrupts = <2 24>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>; ++ dmas = <&dma 13>; ++ dma-names = "rx-tx"; ++ brcm,overclock-50 = <0>; ++ brcm,pio-limit = <1>; ++ status = "disabled"; ++ }; ++ ++ i2s@7e203000 { /* i2s */ ++ #sound-dai-cells = <0>; ++ reg = <0x7e203000 0x24>; ++ clocks = <&clocks BCM2835_CLOCK_PCM>; ++ }; ++ ++ spi0: spi@7e204000 { ++ /* Add alias */ ++ dmas = <&dma 6>, <&dma 7>; ++ dma-names = "tx", "rx"; ++ }; ++ ++ pixelvalve0: pixelvalve@7e206000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ pixelvalve1: pixelvalve@7e207000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ dpi: dpi@7e208000 { ++ compatible = "brcm,bcm2835-dpi"; ++ reg = <0x7e208000 0x8c>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>, ++ <&clocks BCM2835_CLOCK_DPI>; ++ clock-names = "core", "pixel"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ /delete-node/ sdhci@7e300000; ++ ++ mmc: mmc@7e300000 { ++ compatible = "brcm,bcm2835-mmc"; ++ reg = <0x7e300000 0x100>; ++ interrupts = <2 30>; ++ clocks = <&clocks BCM2835_CLOCK_EMMC>; ++ dmas = <&dma 11>; ++ dma-names = "rx-tx"; ++ brcm,overclock-50 = <0>; ++ status = "disabled"; ++ }; ++ ++ hvs: hvs@7e400000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ firmwarekms: firmwarekms@7e600000 { ++ compatible = "raspberrypi,rpi-firmware-kms"; ++ /* SMI interrupt reg */ ++ reg = <0x7e600000 0x100>; ++ interrupts = <2 16>; ++ brcm,firmware = <&firmware>; ++ status = "disabled"; ++ }; ++ ++ smi: smi@7e600000 { ++ compatible = "brcm,bcm2835-smi"; ++ reg = <0x7e600000 0x100>; ++ interrupts = <2 16>; ++ clocks = <&clocks BCM2835_CLOCK_SMI>; ++ assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; ++ assigned-clock-rates = <125000000>; ++ dmas = <&dma 4>; ++ dma-names = "rx-tx"; ++ status = "disabled"; ++ }; ++ ++ pixelvalve2: pixelvalve@7e807000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ hdmi@7e902000 { /* hdmi */ ++ status = "disabled"; ++ }; ++ ++ usb@7e980000 { /* usb */ ++ compatible = "brcm,bcm2708-usb"; ++ reg = <0x7e980000 0x10000>, ++ <0x7e006000 0x1000>; ++ interrupts = <2 0>, ++ <1 9>; ++ }; ++ ++ v3d@7ec00000 { /* vd3 */ ++ compatible = "brcm,vc4-v3d"; ++ power-domains = <&power RPI_POWER_DOMAIN_V3D>; ++ status = "disabled"; ++ }; ++ ++ gpu: gpu { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ }; +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc221f99953d +index 0000000000000000000000000000000000000000..12764a3495b2372ffaf47e32ea0d21326ca83686 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -0,0 +1,213 @@ +@@ -0,0 +1,203 @@ +/dts-v1/; + +#ifdef RPI364 @@ -114476,7 +97975,6 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 +#include "bcm2710.dtsi" + +/ { -+ compatible = "brcm,bcm2710","brcm,bcm2709"; + model = "Raspberry Pi 3 Model B"; +}; + @@ -114622,15 +98120,10 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -114639,10 +98132,6 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 + }; +}; + -+&hdmi { -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; -+}; -+ +&audio { + pinctrl-names = "default"; + pinctrl-0 = <&audio_pins>; @@ -114682,24 +98171,22 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts new file mode 100644 -index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540cfea71886 +index 0000000000000000000000000000000000000000..41874c25a84226c0e4af92ec4059e0a571fe6123 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -0,0 +1,162 @@ +@@ -0,0 +1,155 @@ +/dts-v1/; + +#include "bcm2710.dtsi" + +/ { -+ compatible = "brcm,bcm2710","brcm,bcm2709"; + model = "Raspberry Pi Compute Module 3"; +}; + +&gpio { -+ -+ mmc_pins: mmc_pins { ++ sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; -+ brcm,function = <7>; /* alt3 */ ++ brcm,function = <4>; /* alt0 */ + brcm,pull = <0 2 2 2 2 2>; + }; + @@ -114734,9 +98221,9 @@ index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540c + }; +}; + -+&mmc { ++&sdhost { + pinctrl-names = "default"; -+ pinctrl-0 = <&mmc_pins>; ++ pinctrl-0 = <&sdhost_pins>; + non-removable; + bus-width = <4>; + status = "okay"; @@ -114796,15 +98283,10 @@ index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540c +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -114850,27 +98332,22 @@ index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540c +}; diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..223bd9627b3dcaac5458909dc59c877eed751ce4 +index 0000000000000000000000000000000000000000..f6def5d7e5d622cf09e8f87332c7374fe28da08b --- /dev/null +++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -0,0 +1,165 @@ -+#include "bcm2708_common.dtsi" +@@ -0,0 +1,155 @@ ++#include "bcm283x.dtsi" ++#include "bcm270x.dtsi" ++#include "bcm2708-rpi.dtsi" + +/ { -+ compatible = "brcm,bcm2710","brcm,bcm2709"; -+ model = "BCM2710"; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; ++ compatible = "brcm,bcm2837", "brcm,bcm2836"; ++ model = "BCM2837"; + + soc { + ranges = <0x7e000000 0x3f000000 0x01000000>, + <0x40000000 0x40000000 0x00040000>; -+#ifdef RPI364 + dma-ranges = <0xc0000000 0x00000000 0x3f000000>; -+#endif + + local_intc: local_intc { + compatible = "brcm,bcm2836-l1-intc"; @@ -114890,19 +98367,12 @@ index 0000000000000000000000000000000000000000..223bd9627b3dcaac5458909dc59c877e + interrupts = <9>; + }; + -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ status = "okay"; -+ }; -+ + timer { +#ifdef RPI364 + compatible = "arm,armv8-timer", "arm,armv7-timer"; +#else + compatible = "arm,armv7-timer"; +#endif -+ clock-frequency = <19200000>; + interrupt-parent = <&local_intc>; + interrupts = <0>, // PHYS_SECURE_PPI + <1>, // PHYS_NONSECURE_PPI @@ -115007,276 +98477,137 @@ index 0000000000000000000000000000000000000000..223bd9627b3dcaac5458909dc59c877e +#endif +}; + -+&watchdog { -+ status = "okay"; -+}; -+ +&intc { + compatible = "brcm,bcm2836-armctrl-ic"; -+#ifdef RPI364 + reg = <0x7e00b200 0x200>; -+#endif + interrupt-parent = <&local_intc>; + interrupts = <8>; +}; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dts b/arch/arm/boot/dts/bcm2835-rpi-cm.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..c6e6860a6d4356a613f4f7ab41c6befc76740a15 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2835-rpi-cm.dts -@@ -0,0 +1,93 @@ -+/dts-v1/; + -+#include "bcm2835-rpi-cm.dtsi" -+ -+/ { -+ model = "Raspberry Pi Compute Module"; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&gpio { -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; -+ }; -+ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; -+ }; -+ -+ i2s_pins: i2s { -+ brcm,pins = <18 19 20 21>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -+ -+/ { -+ __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; -+ uart1_clkrate = <&uart1>,"clock-frequency:0"; -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ i2c2_iknowwhatimdoing = <&i2c2>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; -+ i2c2_baudrate = <&i2c2>,"clock-frequency:0"; -+ core_freq = <&clk_core>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..9c4000fc686a9882b9ddde24fdcf937d52b0f86f ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -@@ -0,0 +1,30 @@ -+#include "bcm2835.dtsi" -+ -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 47 0>; -+ }; -+}; -+ -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ -+&fb { -+ status = "okay"; -+}; -+ -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; -+ }; ++#ifdef RPI364 ++&usb { ++ compatible = "brcm,bcm2835-usb"; ++ reg = <0x7e980000 0x10000>; ++ interrupts = <1 9>; +}; ++#endif diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..b6ed1a3c06a7a67d1dd79bb7e55421d8eccba492 +index 0000000000000000000000000000000000000000..11dba31712840a9e4b91acd4565c2d6266315273 --- /dev/null +++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,111 @@ -+ifeq ($(CONFIG_OF),y) -+ +@@ -0,0 +1,105 @@ +# Overlays for the Raspberry Pi platform + -+ifeq ($(CONFIG_ARCH_BCM2708),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2709),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif -+ -+dtbo-$(RPI_DT_OVERLAYS) += adau1977-adc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += ads1015.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += ads7846.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += allo-piano-dac-pcm512x-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += audremap.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dionaudio-loco.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dpi18.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-amp.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacplus.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi-pro.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += iqaudio-digi-wm8804-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp23s17.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mz61581.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pi3-act-led.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pi3-disable-bt.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pi3-miniuart-bt.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += piscreen.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pps-gpio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pwm.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pwm-2chan.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += qca7000.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += raspidac3.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-backlight.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-display.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-ft5406.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-proto.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-sense.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rra-digidac1-wm8741-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sc16is750-i2c.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sc16is752-spi1.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi0-hw-cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += vga666.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += w1-gpio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += w1-gpio-pullup.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += wittypi.dtbo ++dtbo-$(CONFIG_ARCH_BCM2835) += \ ++ adau1977-adc.dtbo \ ++ ads1015.dtbo \ ++ ads7846.dtbo \ ++ akkordion-iqdacplus.dtbo \ ++ allo-piano-dac-pcm512x-audio.dtbo \ ++ at86rf233.dtbo \ ++ audioinjector-wm8731-audio.dtbo \ ++ audremap.dtbo \ ++ bmp085_i2c-sensor.dtbo \ ++ dht11.dtbo \ ++ dionaudio-loco.dtbo \ ++ dpi18.dtbo \ ++ dpi24.dtbo \ ++ dwc-otg.dtbo \ ++ dwc2.dtbo \ ++ enc28j60.dtbo \ ++ enc28j60-spi2.dtbo \ ++ gpio-ir.dtbo \ ++ gpio-poweroff.dtbo \ ++ hifiberry-amp.dtbo \ ++ hifiberry-dac.dtbo \ ++ hifiberry-dacplus.dtbo \ ++ hifiberry-digi.dtbo \ ++ hifiberry-digi-pro.dtbo \ ++ hy28a.dtbo \ ++ hy28b.dtbo \ ++ i2c-bcm2708.dtbo \ ++ i2c-gpio.dtbo \ ++ i2c-mux.dtbo \ ++ i2c-pwm-pca9685a.dtbo \ ++ i2c-rtc.dtbo \ ++ i2c-sensor.dtbo \ ++ i2c0-bcm2708.dtbo \ ++ i2c1-bcm2708.dtbo \ ++ i2s-gpio28-31.dtbo \ ++ iqaudio-dac.dtbo \ ++ iqaudio-dacplus.dtbo \ ++ iqaudio-digi-wm8804-audio.dtbo \ ++ justboom-dac.dtbo \ ++ justboom-digi.dtbo \ ++ lirc-rpi.dtbo \ ++ mcp23017.dtbo \ ++ mcp23s17.dtbo \ ++ mcp2515-can0.dtbo \ ++ mcp2515-can1.dtbo \ ++ midi-uart0.dtbo \ ++ mmc.dtbo \ ++ mz61581.dtbo \ ++ pi3-act-led.dtbo \ ++ pi3-disable-bt.dtbo \ ++ pi3-miniuart-bt.dtbo \ ++ piscreen.dtbo \ ++ piscreen2r.dtbo \ ++ pisound.dtbo \ ++ pitft22.dtbo \ ++ pitft28-capacitive.dtbo \ ++ pitft28-resistive.dtbo \ ++ pitft35-resistive.dtbo \ ++ pps-gpio.dtbo \ ++ pwm.dtbo \ ++ pwm-2chan.dtbo \ ++ qca7000.dtbo \ ++ raspidac3.dtbo \ ++ rpi-backlight.dtbo \ ++ rpi-dac.dtbo \ ++ rpi-display.dtbo \ ++ rpi-ft5406.dtbo \ ++ rpi-proto.dtbo \ ++ rpi-sense.dtbo \ ++ rra-digidac1-wm8741-audio.dtbo \ ++ sc16is750-i2c.dtbo \ ++ sc16is752-spi1.dtbo \ ++ sdhost.dtbo \ ++ sdio.dtbo \ ++ sdio-1bit.dtbo \ ++ sdtweak.dtbo \ ++ smi.dtbo \ ++ smi-dev.dtbo \ ++ smi-nand.dtbo \ ++ spi-gpio35-39.dtbo \ ++ spi-rtc.dtbo \ ++ spi0-hw-cs.dtbo \ ++ spi1-1cs.dtbo \ ++ spi1-2cs.dtbo \ ++ spi1-3cs.dtbo \ ++ spi2-1cs.dtbo \ ++ spi2-2cs.dtbo \ ++ spi2-3cs.dtbo \ ++ tinylcd35.dtbo \ ++ uart1.dtbo \ ++ vc4-fkms-v3d.dtbo \ ++ vc4-kms-v3d.dtbo \ ++ vga666.dtbo \ ++ w1-gpio.dtbo \ ++ w1-gpio-pullup.dtbo \ ++ wittypi.dtbo + +targets += dtbs dtbs_install +targets += $(dtbo-y) + -+endif -+ +always := $(dtbo-y) +clean-files := *.dtbo diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README new file mode 100644 -index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a08679298b26 +index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9f5c392bd --- /dev/null +++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,1302 @@ +@@ -0,0 +1,1368 @@ +Introduction +============ + @@ -115340,7 +98671,7 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + dtoverlay=lirc-rpi + -+This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By ++This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By +default it will use GPIOs 17 (out) and 18 (in), but this can be modified using +DT parameters: + @@ -115562,8 +98893,7 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + +Name: bmp085_i2c-sensor -+Info: Configures the BMP085/BMP180 digital barometric pressure and temperature -+ sensors from Bosch Sensortec ++Info: This overlay is now deprecated - see i2c-sensor +Load: dtoverlay=bmp085_i2c-sensor +Params: + @@ -115623,13 +98953,21 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + +Name: enc28j60 -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) ++Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI0 +Load: dtoverlay=enc28j60,= +Params: int_pin GPIO used for INT (default 25) + + speed SPI bus speed (default 12000000) + + ++Name: enc28j60-spi2 ++Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI2 ++Load: dtoverlay=enc28j60-spi2,= ++Params: int_pin GPIO used for INT (default 39) ++ ++ speed SPI bus speed (default 12000000) ++ ++ +Name: gpio-ir +Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- + based gpio_ir_recv driver maps received keys directly to a @@ -115742,6 +99080,12 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + ledgpio GPIO used to control backlight + + ++Name: i2c-bcm2708 ++Info: Fall back to the i2c_bcm2708 driver for the i2c_arm bus. ++Load: dtoverlay=i2c-bcm2708 ++Params: ++ ++ +Name: i2c-gpio +Info: Adds support for software i2c controller on gpio pins +Load: dtoverlay=i2c-gpio,= @@ -115777,7 +99121,11 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 +Name: i2c-rtc +Info: Adds support for a number of I2C Real Time Clock devices +Load: dtoverlay=i2c-rtc,= -+Params: ds1307 Select the DS1307 device ++Params: abx80x Select one of the ABx80x family: ++ AB0801, AB0803, AB0804, AB0805, ++ AB1801, AB1803, AB1804, AB1805 ++ ++ ds1307 Select the DS1307 device + + ds1339 Select the DS1339 device + @@ -115793,12 +99141,25 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + pcf8563 Select the PCF8563 device + -+ trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) ++ trickle-diode-type Diode type for trickle charge - "standard" or ++ "schottky" (ABx80x only) ++ ++ trickle-resistor-ohms Resistor value for trickle charge (DS1339, ++ ABx80x) + + wakeup-source Specify that the RTC can be used as a wakeup + source + + ++Name: i2c-sensor ++Info: Adds support for a number of I2C barometric pressure and temperature ++ sensors on i2c_arm ++Load: dtoverlay=i2c-sensor,= ++Params: bmp085 Select the Bosch sensortronic BMP085 ++ ++ bmp280 Select the Bosch sensortronic BMP280 ++ ++ +Name: i2c0-bcm2708 +Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations + are usable on all platforms. @@ -115982,6 +99343,13 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + interrupt GPIO for interrupt signal + + ++Name: midi-uart0 ++Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets ++ 31.25kbaud, the frequency required for MIDI ++Load: dtoverlay=midi-uart0 ++Params: ++ ++ +Name: mmc +Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock +Load: dtoverlay=mmc,= @@ -116081,6 +99449,12 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + xohms Touchpanel sensitivity (X-plate resistance) + + ++Name: pisound ++Info: Configures the Blokas Labs pisound card ++Load: dtoverlay=pisound ++Params: ++ ++ +Name: pitft22 +Info: Adafruit PiTFT 2.2" screen +Load: dtoverlay=pitft22,= @@ -116127,6 +99501,18 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + debug Debug output level {0-7} + + ++Name: pitft35-resistive ++Info: Adafruit PiTFT 3.5" resistive touch screen ++Load: dtoverlay=pitft35-resistive,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ +Name: pps-gpio +Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). +Load: dtoverlay=pps-gpio,= @@ -116508,6 +99894,17 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15) + + ++Name: vc4-fkms-v3d ++Info: Enable Eric Anholt's DRM VC4 V3D driver on top of the dispmanx ++ display stack. ++Load: dtoverlay=vc4-fkms-v3d, ++Params: cma-256 CMA is 256MB, 256MB-aligned (needs 1GB) ++ cma-192 CMA is 192MB, 256MB-aligned (needs 1GB) ++ cma-128 CMA is 128MB, 128MB-aligned ++ cma-96 CMA is 96MB, 128MB-aligned ++ cma-64 CMA is 64MB, 64MB-aligned ++ ++ +Name: vc4-kms-v3d +Info: Enable Eric Anholt's DRM VC4 HDMI/HVS/V3D driver. Running startx or + booting to GUI while this overlay is in use will cause interesting @@ -117395,6 +100792,59 @@ index 0000000000000000000000000000000000000000..db8a8feed94c010e368065fdd88b0286 + speed = <ð1>, "spi-max-frequency:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..946c9d2107a83335b11f094e75945a509595ab7c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts +@@ -0,0 +1,47 @@ ++// Overlay for the Microchip ENC28J60 Ethernet Controller - SPI2 Compute Module ++// Interrupt pin: 39 ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&spi2>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ ++ eth1: enc28j60@0{ ++ compatible = "microchip,enc28j60"; ++ reg = <0>; /* CE0 */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð1_pins>; ++ interrupt-parent = <&gpio>; ++ interrupts = <39 0x2>; /* falling edge */ ++ spi-max-frequency = <12000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ eth1_pins: eth1_pins { ++ brcm,pins = <39>; ++ brcm,function = <0>; /* in */ ++ brcm,pull = <0>; /* none */ ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ int_pin = <ð1>, "interrupts:0", ++ <ð1_pins>, "brcm,pins:0"; ++ speed = <ð1>, "spi-max-frequency:0"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..af5baf7ddc92be7a59ad3d5f9a9fefba915bed05 @@ -117977,6 +101427,25 @@ index 0000000000000000000000000000000000000000..8018aebde8e557f45ffd63eb86f6c7a1 + <&hy28b_pins>, "brcm,pins:2"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..0afc6b405414c97428278dd3e8836759092aedb5 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ compatible = "brcm,bcm2708-i2c"; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..b72b32e936774d901bc253b06e025c2dd48bdb1b @@ -118205,10 +101674,10 @@ index 0000000000000000000000000000000000000000..d1ffd2326669e46ad68939f94713cc99 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194fa3462435 +index 0000000000000000000000000000000000000000..1efcf0b712c9c5c19210545002ac1f0931db58f5 --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -0,0 +1,73 @@ +@@ -0,0 +1,83 @@ +// Definitions for several I2C based Real Time Clocks +/dts-v1/; +/plugin/; @@ -118223,6 +101692,13 @@ index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194f + #size-cells = <0>; + status = "okay"; + ++ abx80x: abx80x@69 { ++ compatible = "abracon,abx80x"; ++ reg = <0x69>; ++ abracon,tc-diode = "standard"; ++ abracon,tc-resistor = <0>; ++ status = "disable"; ++ }; + ds1307: ds1307@68 { + compatible = "maxim,ds1307"; + reg = <0x68>; @@ -118267,6 +101743,7 @@ index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194f + }; + }; + __overrides__ { ++ abx80x = <&abx80x>,"status"; + ds1307 = <&ds1307>,"status"; + ds1339 = <&ds1339>,"status"; + ds3231 = <&ds3231>,"status"; @@ -118275,13 +101752,55 @@ index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194f + pcf2127 = <&pcf2127>,"status"; + pcf8523 = <&pcf8523>,"status"; + pcf8563 = <&pcf8563>,"status"; -+ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; ++ trickle-diode-type = <&abx80x>,"abracon,tc-diode"; ++ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0", ++ <&abx80x>,"abracon,tc-resistor"; + wakeup-source = <&ds1339>,"wakeup-source?", + <&ds3231>,"wakeup-source?", + <&mcp7940x>,"wakeup-source?", + <&mcp7941x>,"wakeup-source?"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..f6d134c095af2398fc55ae7d2b0e86456c30627c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +@@ -0,0 +1,34 @@ ++// Definitions for a few digital barometric pressure and temperature sensors ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ bmp085: bmp085@77 { ++ compatible = "bosch,bmp085"; ++ reg = <0x77>; ++ default-oversampling = <3>; ++ status = "disable"; ++ }; ++ ++ bmp280: bmp280@76 { ++ compatible = "bosch,bmp280"; ++ reg = <0x76>; ++ status = "disable"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ bmp085 = <&bmp085>,"status"; ++ bmp280 = <&bmp280>,"status"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..1f4fc7b570604a50ff6d3f6d676c3c4642d66b17 @@ -119683,6 +103202,48 @@ index 0000000000000000000000000000000000000000..67bd0d9bdaa2ff767d284010a69ecfe3 + interrupt = <&can1_pins>,"brcm,pins:0",<&can1>,"interrupts:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..565af7cf79d761877be3bd06191f31aabf9e1e9b +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts +@@ -0,0 +1,36 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 48MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 48000000*38400/31250 = 58982400 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target-path = "/clocks"; ++ __overlay__ { ++ midi_clk: midi_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart0_pclk"; ++ clock-frequency = <58982400>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart0>; ++ __overlay__ { ++ clocks = <&midi_clk>, ++ <&clocks BCM2835_CLOCK_VPU>; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/mmc-overlay.dts b/arch/arm/boot/dts/overlays/mmc-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..d32b02ca01ced5ab3de00d66d5412c8fda4bc510 @@ -120225,6 +103786,126 @@ index 0000000000000000000000000000000000000000..9c0bed893057b9129c8f16b0b695b85b + }; +}; + +diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae26019055 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts +@@ -0,0 +1,114 @@ ++/* ++ * pisound Linux kernel module. ++ * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound ++ * ++ * 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; version 2 of the ++ * License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "blokaslabs,pisound"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ ++ pinctrl-0 = <&pisound_button_pins>; ++ ++ osr-gpios = ++ <&gpio 13 GPIO_ACTIVE_HIGH>, ++ <&gpio 26 GPIO_ACTIVE_HIGH>, ++ <&gpio 16 GPIO_ACTIVE_HIGH>; ++ ++ reset-gpios = ++ <&gpio 12 GPIO_ACTIVE_HIGH>, ++ <&gpio 24 GPIO_ACTIVE_HIGH>; ++ ++ data_available-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; ++ ++ button-gpios = <&gpio 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pisound_button_pins>; ++ ++ pisound_button_pins: pisound_button_pins { ++ brcm,pins = <17>; ++ brcm,function = <0>; // Input ++ brcm,pull = <2>; // Pull-Up ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&spi0>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pisound_spi: pisound_spi@0{ ++ compatible = "blokaslabs,pisound-spi"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/pitft22-overlay.dts b/arch/arm/boot/dts/overlays/pitft22-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..894ba2292f6be76356f3ab39376d84ebd72fa29d @@ -120524,6 +104205,133 @@ index 0000000000000000000000000000000000000000..ed2afc2f7fd6528f4e6d75bb2d534307 + debug = <&pitft>,"debug:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..25cb5cc9576dadc3539f4ea3c9507c592ccac9d6 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts +@@ -0,0 +1,121 @@ ++/* ++ * Device Tree overlay for Adafruit PiTFT 3.5" resistive touch screen ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spidev0>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spidev1>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&gpio>; ++ __overlay__ { ++ pitft_pins: pitft_pins { ++ brcm,pins = <24 25>; ++ brcm,function = <0 1>; /* in out */ ++ brcm,pull = <2 0>; /* pullup none */ ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pitft: pitft@0{ ++ compatible = "himax,hx8357d"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pitft_pins>; ++ ++ spi-max-frequency = <32000000>; ++ rotate = <90>; ++ fps = <25>; ++ bgr; ++ buswidth = <8>; ++ dc-gpios = <&gpio 25 0>; ++ debug = <0>; ++ }; ++ ++ pitft_ts@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stmpe610"; ++ reg = <1>; ++ ++ spi-max-frequency = <500000>; ++ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ ++ interrupts = <24 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ interrupt-controller; ++ ++ stmpe_touchscreen { ++ compatible = "st,stmpe-ts"; ++ st,sample-time = <4>; ++ st,mod-12b = <1>; ++ st,ref-sel = <0>; ++ st,adc-freq = <2>; ++ st,ave-ctrl = <3>; ++ st,touch-det-delay = <4>; ++ st,settling = <2>; ++ st,fraction-z = <7>; ++ st,i-drive = <0>; ++ }; ++ ++ stmpe_gpio: stmpe_gpio { ++ #gpio-cells = <2>; ++ compatible = "st,stmpe-gpio"; ++ /* ++ * only GPIO2 is wired/available ++ * and it is wired to the backlight ++ */ ++ st,norequest-mask = <0x7b>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@5 { ++ target-path = "/soc"; ++ __overlay__ { ++ backlight { ++ compatible = "gpio-backlight"; ++ gpios = <&stmpe_gpio 2 0>; ++ default-on; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ speed = <&pitft>,"spi-max-frequency:0"; ++ rotate = <&pitft>,"rotate:0"; ++ fps = <&pitft>,"fps:0"; ++ debug = <&pitft>,"debug:0"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..50143a4bb215807ba0a0d0562f5827fa29a04de4 @@ -122381,6 +106189,101 @@ index 0000000000000000000000000000000000000000..fa73e1feaeb1bf53a6755e81a998e71c + rxd1_pin = <&uart1_pins>,"brcm,pins:4"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..95a595a35cb4fbb707bf4b18161f6a46860aa4ae +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts +@@ -0,0 +1,89 @@ ++/* ++ * vc4-fkms-v3d-overlay.dts ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target-path = "/chosen"; ++ __overlay__ { ++ bootargs = "cma=256M@256M"; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=192M@256M"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=128M@128M"; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=96M@128M"; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=64M@64M"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&fb>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&firmwarekms>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&v3d>; ++ __overlay__ { ++ interrupts = <1 10>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&gpu>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target-path = "/soc/dma"; ++ __overlay__ { ++ brcm,dma-channel-mask = <0x7f35>; ++ }; ++ }; ++ ++ __overrides__ { ++ cma-256 = <0>,"+0-1-2-3-4"; ++ cma-192 = <0>,"-0+1-2-3-4"; ++ cma-128 = <0>,"-0-1+2-3-4"; ++ cma-96 = <0>,"-0-1-2+3-4"; ++ cma-64 = <0>,"-0-1-2-3+4"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..4f1cc20f90dc6780f74e08ebee00e5a1a6062c85 @@ -122701,60 +106604,6 @@ index 0000000000000000000000000000000000000000..8498134fdbb3912e9ce18282b53084d8 + }; + +}; - -From 65b456a37c0916b6315fec653abcfd712656d6c3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 24 Aug 2016 16:28:44 +0100 -Subject: [PATCH 059/208] kbuild: Ignore dtco targets when filtering symbols - ---- - scripts/Kbuild.include | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include -index 179219845dfcdfbeb586d12c5ec1296095d9fbf4..e0743e44f84188667a0c322e8c3d36f18385dcd3 100644 ---- a/scripts/Kbuild.include -+++ b/scripts/Kbuild.include -@@ -284,7 +284,7 @@ ksym_dep_filter = \ - $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ - as_*_S|cpp_s_S) \ - $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ -- boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ -+ boot*|build*|*cpp_lds_S|dtc*|host*|vdso*) : ;; \ - *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ - esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' - - -From c648634cfedb6adbaf9e793e9fc1ba79dcf4bc9d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 13 Mar 2015 20:00:21 +0000 -Subject: [PATCH 060/208] BCM270X_DT: Add a .dtbo target, use for overlays - -Change the filenames and extensions to keep the pre-DDT style of -overlay (-overlay.dtb) distinct from new ones that use a -different style of local fixups (.dtbo), and to match other -platforms. - -The RPi firmware uses the DDTK trailer atom to choose which type of -overlay to use for each kernel. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/.gitignore | 2 +- - scripts/Makefile.dtbinst | 10 +++++++--- - scripts/Makefile.lib | 10 ++++++++++ - 3 files changed, 18 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore -index 3c79f85975aaa26c7c2e353fefc54d71d89bc5bf..eaaeb17e5986e5f7178b2851169444ac7e45be8d 100644 ---- a/arch/arm/boot/.gitignore -+++ b/arch/arm/boot/.gitignore -@@ -3,4 +3,4 @@ zImage - xipImage - bootpImage - uImage --*.dtb -+*.dtb* diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..ad8dc1c93d04bc929b551c5a47f67d244116c7e7 100644 --- a/scripts/Makefile.dtbinst @@ -122790,16 +106639,17 @@ index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..ad8dc1c93d04bc929b551c5a47f67d24 .PHONY: $(PHONY) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index 0a07f9014944ed92a8e2e42983ae43be60b3e471..b1513a7c175885137034b9f7225788c0a7c35027 100644 +index 0a07f9014944ed92a8e2e42983ae43be60b3e471..1967878a843461c3ff1f473b9a030eb01b7c726e 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -312,6 +312,16 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ +@@ -312,6 +312,17 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep,dtc) +quiet_cmd_dtco = DTCO $@ -+cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -+ $(objtree)/scripts/dtc/dtc -@ -O dtb -o $@ -b 0 \ ++cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \ ++ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ ++ $(DTC) -@ -H epapr -O dtb -o $@ -b 0 \ + -i $(dir $<) $(DTC_FLAGS) \ + -d $(depfile).dtc.tmp $(dtc-tmp) ; \ + cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) @@ -122811,39 +106661,10 @@ index 0a07f9014944ed92a8e2e42983ae43be60b3e471..b1513a7c175885137034b9f7225788c0 # Bzip2 -From c02bd18e6291de77eb37462f47ce78063975157f Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 8 Apr 2016 17:43:27 +0100 -Subject: [PATCH 061/208] BCM270X_DT: Don't generate "linux,phandle" props - -The EPAPR standard says to use "phandle" properties to store phandles, -rather than the deprecated "linux,phandle" version. By default, dtc -generates both, but adding "-H epapr" causes it to only generate -"phandle"s, saving some space and clutter. - -Signed-off-by: Phil Elwell ---- - scripts/Makefile.lib | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index b1513a7c175885137034b9f7225788c0a7c35027..1d949b7410600dd3b04a3acde8c41cfead15bfa4 100644 ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -314,7 +314,7 @@ $(obj)/%.dtb: $(src)/%.dts FORCE - - quiet_cmd_dtco = DTCO $@ - cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -- $(objtree)/scripts/dtc/dtc -@ -O dtb -o $@ -b 0 \ -+ $(objtree)/scripts/dtc/dtc -@ -H epapr -O dtb -o $@ -b 0 \ - -i $(dir $<) $(DTC_FLAGS) \ - -d $(depfile).dtc.tmp $(dtc-tmp) ; \ - cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) - -From 397a180a518dd177c140287c66caf9ae4dcb4a1e Mon Sep 17 00:00:00 2001 +From 26a743327cb9976306f0f31d8badd36f6636a3d4 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 062/208] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 055/111] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -122873,10 +106694,10 @@ See: https://github.com/raspberrypi/linux/issues/1064 create mode 100644 drivers/leds/trigger/ledtrig-input.c diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index 9b991d46ed848a0de40185eef30d9691c7e07e88..f454881346bbf01ea98aa2662e82f8c66dd11318 100644 +index d400dcaf4d296444967065e98812c210c48a192d..6a27a693034825de2897bb7b338b60cc10c9e59f 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c -@@ -46,8 +46,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, +@@ -50,8 +50,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, led_dat->platform_gpio_blink_set(led_dat->gpiod, level, NULL, NULL); led_dat->blinking = 0; @@ -122893,7 +106714,7 @@ index 9b991d46ed848a0de40185eef30d9691c7e07e88..f454881346bbf01ea98aa2662e82f8c6 gpiod_set_value_cansleep(led_dat->gpiod, level); else gpiod_set_value(led_dat->gpiod, level); -@@ -61,6 +68,13 @@ static int gpio_led_set_blocking(struct led_classdev *led_cdev, +@@ -65,6 +72,13 @@ static int gpio_led_set_blocking(struct led_classdev *led_cdev, return 0; } @@ -122907,15 +106728,15 @@ index 9b991d46ed848a0de40185eef30d9691c7e07e88..f454881346bbf01ea98aa2662e82f8c6 static int gpio_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { -@@ -120,6 +134,8 @@ static int create_gpio_led(const struct gpio_led *template, +@@ -122,6 +136,8 @@ static int create_gpio_led(const struct gpio_led *template, led_dat->platform_gpio_blink_set = blink_set; led_dat->cdev.blink_set = gpio_blink_set; } + led_dat->cdev.brightness_set = gpio_led_set; + led_dat->cdev.brightness_get = gpio_led_get; - if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) - state = !!gpiod_get_value_cansleep(led_dat->gpiod); - else + if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) { + state = gpiod_get_value_cansleep(led_dat->gpiod); + if (state < 0) diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 3f9ddb9fafa77f1f1fe5535c5e947838761e4f35..c1b6c83f3b63f993452893f136c5da54d0ada8e7 100644 --- a/drivers/leds/trigger/Kconfig @@ -123005,7 +106826,7 @@ index 0000000000000000000000000000000000000000..27f8ebea43d86fc51c98db5c953da05b +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h -index 8a3b5d29602ffe665cfb26522180f3a696664371..d067976ddc2f34d5476bcd9321856b1c40e17e12 100644 +index ddfcb2df3656cf0ab6aebd1fa3d624a6ec2e94e9..271563eb835f9018712e2076a88f341d2d6db7db 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -52,6 +52,9 @@ struct led_classdev { @@ -123019,10 +106840,10 @@ index 8a3b5d29602ffe665cfb26522180f3a696664371..d067976ddc2f34d5476bcd9321856b1c /* Set LED brightness level * Must not sleep. Use brightness_set_blocking for drivers -From 43ca3a9b4fe3c10f5ce4a65732444c6df4f081f1 Mon Sep 17 00:00:00 2001 +From 1cca88ce52ad46a1096fea51c07a9842c06466f2 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 063/208] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 056/111] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -123031,11 +106852,150 @@ Provide an ioctl for userspace applications, but only if this operation is hardware accelerated (otherwide it does not make any sense). Signed-off-by: Siarhei Siamashka ---- - drivers/video/fbdev/core/fbmem.c | 36 ++++++++++++++++++++++++++++++++++++ - include/uapi/linux/fb.h | 5 +++++ - 2 files changed, 41 insertions(+) +bcm2708_fb: Add ioctl for reading gpu memory through dma +--- + drivers/video/fbdev/bcm2708_fb.c | 109 +++++++++++++++++++++++++++++++++++++++ + drivers/video/fbdev/core/fbmem.c | 36 +++++++++++++ + include/uapi/linux/fb.h | 12 +++++ + 3 files changed, 157 insertions(+) + +diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c +index 37f60813fe1dd95d9f5f725c07ec2e75c09857bf..53c5a0bdadb4be9251affdabed66305842a08e72 100644 +--- a/drivers/video/fbdev/bcm2708_fb.c ++++ b/drivers/video/fbdev/bcm2708_fb.c +@@ -31,8 +31,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + #include + + //#define BCM2708_FB_DEBUG +@@ -426,6 +428,110 @@ static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info + return result; + } + ++static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, int size) ++{ ++ int burst_size = (fb->dma_chan == 0) ? 8 : 2; ++ struct bcm2708_dma_cb *cb = fb->cb_base; ++ ++ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | ++ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | ++ BCM2708_DMA_D_INC; ++ cb->dst = dst; ++ cb->src = src; ++ cb->length = size; ++ cb->stride = 0; ++ cb->pad[0] = 0; ++ cb->pad[1] = 0; ++ cb->next = 0; ++ ++ if (size < dma_busy_wait_threshold) { ++ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); ++ bcm_dma_wait_idle(fb->dma_chan_base); ++ } else { ++ void __iomem *dma_chan = fb->dma_chan_base; ++ cb->info |= BCM2708_DMA_INT_EN; ++ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); ++ while (bcm_dma_is_busy(dma_chan)) { ++ wait_event_interruptible( ++ fb->dma_waitq, ++ !bcm_dma_is_busy(dma_chan)); ++ } ++ fb->stats.dma_irqs++; ++ } ++ fb->stats.dma_copies++; ++} ++ ++#define INTALIAS_NORMAL(x) ((x)&~0xc0000000) // address with no aliases ++#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000) // cache coherent but non-allocating in L1 and L2 ++ ++static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) ++{ ++ struct fb_dmacopy ioparam; ++ size_t size = PAGE_SIZE; ++ u32 *buf = NULL; ++ dma_addr_t bus_addr; ++ long rc = 0; ++ size_t offset; ++ struct { u32 base, length; } gpu = {}; ++ ++ /* restrict this to root user */ ++ if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) ++ { ++ rc = -EFAULT; ++ goto out; ++ } ++ ++ /* Get the parameter data. ++ */ ++ if (copy_from_user ++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { ++ pr_err("[%s]: failed to copy-from-user\n", ++ __func__); ++ rc = -EFAULT; ++ goto out; ++ } ++ ++ rc = rpi_firmware_property(fb->fw, ++ RPI_FIRMWARE_GET_VC_MEMORY, ++ &gpu, sizeof(gpu)); ++ if (rc != 0 || gpu.base == 0 || gpu.length == 0) { ++ pr_err("[%s]: Unable to determine gpu memory %ld,%x,%x)\n", __func__, rc, gpu.base, gpu.length); ++ return -EFAULT; ++ } ++ ++ if (INTALIAS_NORMAL(ioparam.src) < gpu.base || INTALIAS_NORMAL(ioparam.src) >= gpu.base + gpu.length) { ++ pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__, INTALIAS_NORMAL(ioparam.src), gpu.base, gpu.base + gpu.length); ++ return -EFAULT; ++ } ++ ++ buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr, ++ GFP_ATOMIC); ++ if (!buf) { ++ pr_err("[%s]: failed to dma_alloc_coherent(%d)\n", ++ __func__, size); ++ rc = -ENOMEM; ++ goto out; ++ } ++ ++ for (offset = 0; offset < ioparam.length; offset += size) { ++ size_t remaining = ioparam.length - offset; ++ size_t s = min(size, remaining); ++ unsigned char *p = (unsigned char *)ioparam.src + offset; ++ unsigned char *q = (unsigned char *)ioparam.dst + offset; ++ dma_memcpy(fb, bus_addr, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); ++ if (copy_to_user(q, buf, s) != 0) { ++ pr_err("[%s]: failed to copy-to-user\n", ++ __func__); ++ rc = -EFAULT; ++ goto out; ++ } ++ } ++out: ++ if (buf) ++ dma_free_coherent(fb->fb.device, PAGE_ALIGN(size), buf, bus_addr); ++ return rc; ++} ++ + static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) + { + struct bcm2708_fb *fb = to_bcm2708(info); +@@ -438,6 +544,9 @@ static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long a + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, + &dummy, sizeof(dummy)); + break; ++ case FBIODMACOPY: ++ ret = vc_mem_copy(fb, arg); ++ break; + default: + dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd); + return -ENOTTY; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 76c1ad96fb37d4f07bbde6462f54825f566acbac..7bf48e478c056fcd745026902961506d5826615d 100644 --- a/drivers/video/fbdev/core/fbmem.c @@ -123105,10 +107065,10 @@ index 76c1ad96fb37d4f07bbde6462f54825f566acbac..7bf48e478c056fcd745026902961506d case FBIOBLANK: ret = do_fb_ioctl(info, cmd, arg); diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..fa72af0c981710fe80bacf4cf6612f6da19046ee 100644 +index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..703fa8a70574323abe2fb32599254582cd5d891f 100644 --- a/include/uapi/linux/fb.h +++ b/include/uapi/linux/fb.h -@@ -34,6 +34,11 @@ +@@ -34,6 +34,12 @@ #define FBIOPUT_MODEINFO 0x4617 #define FBIOGET_DISPINFO 0x4618 #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) @@ -123117,14 +107077,28 @@ index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..fa72af0c981710fe80bacf4cf6612f6d + * be concurrently added to the mainline kernel + */ +#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) ++#define FBIODMACOPY _IOW('z', 0x22, struct fb_dmacopy) #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ +@@ -346,6 +352,12 @@ struct fb_copyarea { + __u32 sy; + }; + ++struct fb_dmacopy { ++ void *dst; ++ __u32 src; ++ __u32 length; ++}; ++ + struct fb_fillrect { + __u32 dx; /* screen-relative */ + __u32 dy; -From 26923981303957954bcbc91fff432e1ac2633648 Mon Sep 17 00:00:00 2001 +From 8bccd20de5c5a27255761c7b4393f6fdd9730571 Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 064/208] Speed up console framebuffer imageblit function +Subject: [PATCH 057/111] Speed up console framebuffer imageblit function Especially on platforms with a slower CPU but a relatively high framebuffer fill bandwidth, like current ARM devices, the existing @@ -123333,10 +107307,10 @@ index a2bb276a8b2463eee98eb237c4647bc00cd93601..436494fba15abecb400ef28688466faf start_index, pitch_index); } else -From 71619935735369868d063609734855d0bdcc347d Mon Sep 17 00:00:00 2001 +From 10bc9c9562b39ebd10858de412b6336668171a39 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 065/208] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 058/111] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) 1-wire: Add support for configuring pin for w1-gpio kernel module @@ -123586,10 +107560,10 @@ index d58594a3232492e33f1dd4babd3798b03e0f0203..feae94256256316fd9d850c3d83325af unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From d3fec7c3a52ebf2123c4c379f48f349fbef17578 Mon Sep 17 00:00:00 2001 +From b5f0005bf497b78d9b6a40f364f8a6dba5676bbc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 066/208] config: Enable CONFIG_MEMCG, but leave it disabled +Subject: [PATCH 059/111] config: Enable CONFIG_MEMCG, but leave it disabled (due to memory cost). Enable with cgroup_enable=memory. --- @@ -123597,10 +107571,10 @@ Subject: [PATCH 066/208] config: Enable CONFIG_MEMCG, but leave it disabled 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index d6b729beba4930bbb1a1ddc4a6a6b8533bbf94e0..69e8d214f663572319f784fe17032b1ef4c588b4 100644 +index 85bc9beb046d9a6deda2e3564f4d5bd01d6fc27b..4acdbef46a8f0556469b5580a39c18ce0496c69d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c -@@ -5609,7 +5609,7 @@ int __init cgroup_init_early(void) +@@ -5629,7 +5629,7 @@ int __init cgroup_init_early(void) return 0; } @@ -123609,7 +107583,7 @@ index d6b729beba4930bbb1a1ddc4a6a6b8533bbf94e0..69e8d214f663572319f784fe17032b1e /** * cgroup_init - cgroup initialization -@@ -6139,6 +6139,28 @@ static int __init cgroup_no_v1(char *str) +@@ -6166,6 +6166,28 @@ static int __init cgroup_no_v1(char *str) } __setup("cgroup_no_v1=", cgroup_no_v1); @@ -123639,10 +107613,10 @@ index d6b729beba4930bbb1a1ddc4a6a6b8533bbf94e0..69e8d214f663572319f784fe17032b1e * css_tryget_online_from_dir - get corresponding css from a cgroup dentry * @dentry: directory dentry of interest -From 4a63703bb5d6cff1731ed710841ff6b3f62b3434 Mon Sep 17 00:00:00 2001 +From f64e7d0ea8c5f3aba4fdc4833493403bcdf10557 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 067/208] hid: Reduce default mouse polling interval to 60Hz +Subject: [PATCH 060/111] hid: Reduce default mouse polling interval to 60Hz Reduces overhead when using X --- @@ -123678,26 +107652,31 @@ index ae83af649a607f67239f1a64bf45dd4b5770cc7d..4a7af9d0b910f59d17421ce14138400d ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { -From a9b48b08d46cfbfd35b45dc3738412a8d9ecf6d0 Mon Sep 17 00:00:00 2001 +From 06547c09139ecfe3ee97ca218f8fb7b0373a672b Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 068/208] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 061/111] rpi-ft5406: Add touchscreen driver for pi LCD display Fix driver detection failure Check that the buffer response is non-zero meaning the touchscreen was detected rpi-ft5406: Use firmware API + +RPI-FT5406: Enable aarch64 support through explicit iomem interface + +Signed-off-by: Gerhard de Clercq --- - drivers/input/touchscreen/Kconfig | 7 + - drivers/input/touchscreen/Makefile | 1 + - drivers/input/touchscreen/rpi-ft5406.c | 246 +++++++++++++++++++++++++++++++++ - 3 files changed, 254 insertions(+) + drivers/input/touchscreen/Kconfig | 7 + + drivers/input/touchscreen/Makefile | 1 + + drivers/input/touchscreen/rpi-ft5406.c | 292 +++++++++++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 4 files changed, 301 insertions(+) create mode 100644 drivers/input/touchscreen/rpi-ft5406.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig -index 2fb1f430a4318fcddf65a85a813aae96861da09c..f43fc4561170d1649d77e5b4918ca56ec48e95e8 100644 +index efca0133e266b84439bed072f86b6d4c3e147ece..0bf78ff1ae888a1afe3825aab5316f365ef96bfe 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig -@@ -630,6 +630,13 @@ config TOUCHSCREEN_EDT_FT5X06 +@@ -638,6 +638,13 @@ config TOUCHSCREEN_EDT_FT5X06 To compile this driver as a module, choose M here: the module will be called edt-ft5x06. @@ -123712,7 +107691,7 @@ index 2fb1f430a4318fcddf65a85a813aae96861da09c..f43fc4561170d1649d77e5b4918ca56e tristate "Renesas MIGO-R touchscreen" depends on (SH_MIGOR || COMPILE_TEST) && I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile -index b4373d6be4021687c1f4fc4b4bc0faa054141ec0..9665772864cff27a33c0533e5147f29656e791bd 100644 +index 81b86451782d4479147fbb1a8c70cdc0f6f08eac..f720bc30ada9c2b5907228e852e3955ce9f48c12 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o @@ -123725,10 +107704,10 @@ index b4373d6be4021687c1f4fc4b4bc0faa054141ec0..9665772864cff27a33c0533e5147f296 obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c new file mode 100644 -index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d0bebdddc +index 0000000000000000000000000000000000000000..9d7d05482355d168c5c0c42508cd978979ee5f14 --- /dev/null +++ b/drivers/input/touchscreen/rpi-ft5406.c -@@ -0,0 +1,246 @@ +@@ -0,0 +1,292 @@ +/* + * Driver for memory based ft5406 touchscreen + * @@ -123751,7 +107730,9 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d +#include +#include +#include ++#include +#include ++#include +#include + +#define MAXIMUM_SUPPORTED_POINTS 10 @@ -123776,7 +107757,7 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + struct platform_device * pdev; + struct input_dev * input_dev; + void __iomem * ts_base; -+ struct ft5406_regs * regs; ++ dma_addr_t bus_addr; + struct task_struct * thread; +}; + @@ -123797,8 +107778,8 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + { + // 60fps polling + msleep_interruptible(17); -+ memcpy_fromio(®s, ts->regs, sizeof(*ts->regs)); -+ writel(99, &ts->regs->num_points); ++ memcpy_fromio(®s, ts->ts_base, sizeof(struct ft5406_regs)); ++ iowrite8(99, ts->ts_base + offsetof(struct ft5406_regs, num_points)); + // Do not output if theres no new information (num_points is 99) + // or we have no touch points and don't need to release any + if(!(regs.num_points == 99 || (regs.num_points == 0 && known_ids == 0))) @@ -123848,18 +107829,19 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + +static int ft5406_probe(struct platform_device *pdev) +{ -+ int ret; -+ struct input_dev * input_dev = input_allocate_device(); ++ int err = 0; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; + struct ft5406 * ts; + struct device_node *fw_node; + struct rpi_firmware *fw; + u32 touchbuf; + -+ dev_info(&pdev->dev, "Probing device\n"); ++ dev_info(dev, "Probing device\n"); + -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ fw_node = of_parse_phandle(np, "firmware", 0); + if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); ++ dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + @@ -123867,89 +107849,132 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + if (!fw) + return -EPROBE_DEFER; + -+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, ++ ts = devm_kzalloc(dev, sizeof(struct ft5406), GFP_KERNEL); ++ if (!ts) { ++ dev_err(dev, "Failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ ts->input_dev = input_allocate_device(); ++ if (!ts->input_dev) { ++ dev_err(dev, "Failed to allocate input device\n"); ++ return -ENOMEM; ++ } ++ ++ ts->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->bus_addr, GFP_KERNEL); ++ if (!ts->ts_base) { ++ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", ++ __func__, PAGE_SIZE); ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ touchbuf = (u32)ts->bus_addr; ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, + &touchbuf, sizeof(touchbuf)); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to get touch buffer\n"); -+ return ret; ++ ++ if (err || touchbuf != 0) { ++ dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n", err); ++ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ ts->ts_base = 0; ++ ts->bus_addr = 0; + } + -+ if (!touchbuf) { -+ dev_err(&pdev->dev, "Touchscreen not detected\n"); -+ return -ENODEV; ++ if (!ts->ts_base) { ++ dev_warn(dev, "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n", err, touchbuf, ts->ts_base, ts->bus_addr); ++ ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, ++ &touchbuf, sizeof(touchbuf)); ++ if (err) { ++ dev_err(dev, "Failed to get touch buffer\n"); ++ goto out; ++ } ++ ++ if (!touchbuf) { ++ dev_err(dev, "Touchscreen not detected\n"); ++ err = -ENODEV; ++ goto out; ++ } ++ ++ dev_dbg(dev, "Got TS buffer 0x%x\n", touchbuf); ++ ++ // mmap the physical memory ++ touchbuf &= ~0xc0000000; ++ ts->ts_base = ioremap(touchbuf, sizeof(struct ft5406_regs)); ++ if (ts->ts_base == NULL) ++ { ++ dev_err(dev, "Failed to map physical address\n"); ++ err = -ENOMEM; ++ goto out; ++ } + } -+ -+ dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", touchbuf); -+ -+ ts = kzalloc(sizeof(struct ft5406), GFP_KERNEL); -+ -+ if (!ts || !input_dev) { -+ ret = -ENOMEM; -+ dev_err(&pdev->dev, "Failed to allocate memory\n"); -+ return ret; -+ } -+ ts->input_dev = input_dev; + platform_set_drvdata(pdev, ts); + ts->pdev = pdev; + -+ input_dev->name = "FT5406 memory based driver"; ++ ts->input_dev->name = "FT5406 memory based driver"; + -+ __set_bit(EV_KEY, input_dev->evbit); -+ __set_bit(EV_SYN, input_dev->evbit); -+ __set_bit(EV_ABS, input_dev->evbit); ++ __set_bit(EV_KEY, ts->input_dev->evbit); ++ __set_bit(EV_SYN, ts->input_dev->evbit); ++ __set_bit(EV_ABS, ts->input_dev->evbit); + -+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, + SCREEN_WIDTH, 0, 0); -+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, + SCREEN_HEIGHT, 0, 0); + -+ input_mt_init_slots(input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); ++ input_mt_init_slots(ts->input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); + -+ input_set_drvdata(input_dev, ts); ++ input_set_drvdata(ts->input_dev, ts); + -+ ret = input_register_device(input_dev); -+ if (ret) { -+ dev_err(&pdev->dev, "could not register input device, %d\n", -+ ret); -+ return ret; ++ err = input_register_device(ts->input_dev); ++ if (err) { ++ dev_err(dev, "could not register input device, %d\n", ++ err); ++ goto out; + } -+ -+ // mmap the physical memory -+ touchbuf &= ~0xc0000000; -+ ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -+ if(ts->ts_base == NULL) -+ { -+ dev_err(&pdev->dev, "Failed to map physical address\n"); -+ input_unregister_device(input_dev); -+ kzfree(ts); -+ return -ENOMEM; -+ } -+ -+ ts->regs = (struct ft5406_regs *) ts->ts_base; + + // create thread to poll the touch events + ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); + if(ts->thread == NULL) + { -+ dev_err(&pdev->dev, "Failed to create kernel thread"); -+ iounmap(ts->ts_base); -+ input_unregister_device(input_dev); -+ kzfree(ts); ++ dev_err(dev, "Failed to create kernel thread"); ++ err = -ENOMEM; ++ goto out; + } + + return 0; ++ ++out: ++ if (ts->bus_addr) { ++ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ ts->bus_addr = 0; ++ ts->ts_base = NULL; ++ } else if (ts->ts_base) { ++ iounmap(ts->ts_base); ++ ts->ts_base = NULL; ++ } ++ if (ts->input_dev) { ++ input_unregister_device(ts->input_dev); ++ ts->input_dev = NULL; ++ } ++ return err; +} + +static int ft5406_remove(struct platform_device *pdev) +{ ++ struct device *dev = &pdev->dev; + struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev); + -+ dev_info(&pdev->dev, "Removing rpi-ft5406\n"); ++ dev_info(dev, "Removing rpi-ft5406\n"); + + kthread_stop(ts->thread); -+ iounmap(ts->ts_base); -+ input_unregister_device(ts->input_dev); -+ kzfree(ts); ++ ++ if (ts->bus_addr) ++ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ else if (ts->ts_base) ++ iounmap(ts->ts_base); ++ if (ts->input_dev) ++ input_unregister_device(ts->input_dev); + + return 0; +} @@ -123975,11 +108000,23 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d +MODULE_AUTHOR("Gordon Hollingworth"); +MODULE_DESCRIPTION("Touchscreen driver for memory based FT5406"); +MODULE_LICENSE("GPL"); +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +index 227a107214a02deadcca3db202da265eba1fdd21..b0f6e33bd30c35664ceee057f4c3ad32b914291d 100644 +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -115,6 +115,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + -From 79bd07b796e2fc05512634cc0c80bd3d6e641c6b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 069/208] Improve __copy_to_user and __copy_from_user +From c4de14efbb23ff522c321d5a9220b04560c559a7 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 28 Nov 2016 16:50:04 +0000 +Subject: [PATCH 062/111] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use @@ -124010,7 +108047,8 @@ Signed-off-by: Phil Elwell arch/arm/lib/memmove_rpi.S | 61 +++++ arch/arm/lib/memset_rpi.S | 123 +++++++++ arch/arm/lib/uaccess_with_memcpy.c | 120 ++++++++- - 12 files changed, 1373 insertions(+), 6 deletions(-) + arch/arm/mach-bcm/Kconfig | 7 + + 13 files changed, 1380 insertions(+), 6 deletions(-) create mode 100644 arch/arm/lib/arm-mem.h create mode 100644 arch/arm/lib/exports_rpi.c create mode 100644 arch/arm/lib/memcmp_rpi.S @@ -124020,14 +108058,14 @@ Signed-off-by: Phil Elwell create mode 100644 arch/arm/lib/memset_rpi.S diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h -index cf4f3aad0fc1c2154c6cf3839ff21bb1c46d6499..9fe7780002ce1847b9009ff9b741b56f34e19256 100644 +index cf4f3aad0fc1c2154c6cf3839ff21bb1c46d6499..d69b70a6007dfc647ad164d1ee90d253c0686dee 100644 --- a/arch/arm/include/asm/string.h +++ b/arch/arm/include/asm/string.h @@ -24,6 +24,11 @@ extern void * memchr(const void *, int, __kernel_size_t); #define __HAVE_ARCH_MEMSET extern void * memset(void *, int, __kernel_size_t); -+#ifdef CONFIG_MACH_BCM2708 ++#ifdef CONFIG_BCM2835_FAST_MEMCPY +#define __HAVE_ARCH_MEMCMP +extern int memcmp(const void *, const void *, size_t); +#endif @@ -124036,7 +108074,7 @@ index cf4f3aad0fc1c2154c6cf3839ff21bb1c46d6499..9fe7780002ce1847b9009ff9b741b56f #define memset(p,v,n) \ diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h -index a93c0f99acf7767c680158cf96acef87d1f0da51..cbad0e035c6b8f39463007071539797da586e620 100644 +index 1f59ea051bab814132074b09f55d3a57c800a471..028d151b80a3dfb4253e94b87cc391bdb0b16c49 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -477,6 +477,9 @@ do { \ @@ -124050,7 +108088,7 @@ index a93c0f99acf7767c680158cf96acef87d1f0da51..cbad0e035c6b8f39463007071539797d __copy_from_user(void *to, const void __user *from, unsigned long n) { diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile -index 27f4d96258a2e66193d6a3701bb4cf9a44399aad..5235717443bd221df0b190adeb7d90231a5e5693 100644 +index 27f4d96258a2e66193d6a3701bb4cf9a44399aad..96b390c9301f816d5c83c6ddb76ac74ba7a3b99d 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -6,9 +6,8 @@ @@ -124070,7 +108108,7 @@ index 27f4d96258a2e66193d6a3701bb4cf9a44399aad..5235717443bd221df0b190adeb7d9023 copy_from_user.o copy_to_user.o +# Choose optimised implementations for Raspberry Pi -+ifeq ($(CONFIG_MACH_BCM2708),y) ++ifeq ($(CONFIG_BCM2835_FAST_MEMCPY),y) + CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600 + CFLAGS_uaccess_with_memcpy.o += -DCOPY_TO_USER_THRESHOLD=672 + obj-$(CONFIG_MODULES) += exports_rpi.o @@ -124248,7 +108286,7 @@ index 0000000000000000000000000000000000000000..5d4bda19ad207c65e7b7c6d6d733087f +92: +.endm diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S -index 1512bebfbf1b18ad317648891385a24e93d1f35f..3da60dd2caab0968e2156cf8705ebbe5f2551a8b 100644 +index 7a4b060490012dd29f8a6d9fb8e24dfa58896bd1..fb40a1b3a5b7d42f93ae362e3326b7a72dc290dc 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S @@ -89,11 +89,13 @@ @@ -125440,7 +109478,7 @@ index 6bd1089b07e0960830ed6bd6a8345202b7efd8b0..cd17dd11ebe7bbe00089e70cd2ccea74 __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) { unsigned long ua_flags; -@@ -137,6 +182,57 @@ out: +@@ -137,6 +182,57 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) return n; } @@ -125534,11 +109572,29 @@ index 6bd1089b07e0960830ed6bd6a8345202b7efd8b0..cd17dd11ebe7bbe00089e70cd2ccea74 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) +diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig +index 333dc3c2e5ffbb2c5ab8fcfb6115b6162643cf20..46b787a6474ffa857da9b663948863ecfb46e862 100644 +--- a/arch/arm/mach-bcm/Kconfig ++++ b/arch/arm/mach-bcm/Kconfig +@@ -174,6 +174,13 @@ config ARCH_BCM_53573 + The base chip is BCM53573 and there are some packaging modifications + like BCM47189 and BCM47452. + ++config BCM2835_FAST_MEMCPY ++ bool "Enable optimized __copy_to_user and __copy_from_user" ++ depends on ARCH_BCM2835 && ARCH_MULTI_V6 ++ default y ++ help ++ Optimized versions of __copy_to_user and __copy_from_user for Pi1. ++ + config ARCH_BCM_63XX + bool "Broadcom BCM63xx DSL SoC" + depends on ARCH_MULTI_V7 -From 100203b956cc659d9e65a4086db54f28c304e1e8 Mon Sep 17 00:00:00 2001 +From 1e9511001925124be9b1d3461e87605255c58310 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 25 Jun 2015 12:16:11 +0100 -Subject: [PATCH 070/208] gpio-poweroff: Allow it to work on Raspberry Pi +Subject: [PATCH 063/111] gpio-poweroff: Allow it to work on Raspberry Pi The Raspberry Pi firmware manages the power-down and reboot process. To do this it installs a pm_power_off handler, causing @@ -125573,10 +109629,10 @@ index be3d81ff51cc3f510d85e4eed7a52960e51e7bc1..a030ae9fb1fca325061c093696e82186 "%s: pm_power_off function already registered", __func__); -From 75e0aa61e26876991add914994a59a0ccf3e6e12 Mon Sep 17 00:00:00 2001 +From da2deb13c51f74edf4a4851bf01f03503a208b2a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 14:32:47 +0100 -Subject: [PATCH 071/208] mfd: Add Raspberry Pi Sense HAT core driver +Subject: [PATCH 064/111] mfd: Add Raspberry Pi Sense HAT core driver --- drivers/input/joystick/Kconfig | 8 + @@ -125786,7 +109842,7 @@ index 0000000000000000000000000000000000000000..6a416769065d2198344792eb02d8e38d +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 580f4f280d6b7aebe9a4813acbfaf28ea92a7ba9..87cbe66ad08a2c300079de5772ceaab08db4217f 100644 +index c6df6442ba2b1b378386db03cb530fa6b6e3e723..b220064bd5feba3f9bb5ec198bcf8e5c4b930533 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -10,6 +10,14 @@ config MFD_CORE @@ -125805,10 +109861,10 @@ index 580f4f280d6b7aebe9a4813acbfaf28ea92a7ba9..87cbe66ad08a2c300079de5772ceaab0 tristate "AMD CS5535 and CS5536 southbridge core functions" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 2ba3ba35f745309de62050ab8442cea87a0edb2e..6f2b1d39e4a5c7860dcf971c47096759c578b6fc 100644 +index 9834e669d98573ce8c0b0a15b3f167dbf3485d87..1d8d58fe173c27bdf00daa646f4970e3aeb3ac08 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -207,3 +207,4 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o +@@ -211,3 +211,4 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o @@ -125977,10 +110033,10 @@ index 0000000000000000000000000000000000000000..eea9312dc96a496ce846b0c5a83e6e4f +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index 78a9e6119fa13437862080d815e84d68f7010d1f..ec1a5c27ead7dce18608eb6314f0ae8072fdf9bc 100644 +index 0ff4f80531e013f028ca4d05559c5464f8cfa5ef..2cd45bce38120d076d6a19804443557862978d4b 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig -@@ -2501,3 +2501,16 @@ config FB_SM712 +@@ -2504,3 +2504,16 @@ config FB_SM712 This driver is also available as a module. The module will be called sm712fb. If you want to compile it as a module, say M here and read . @@ -125998,10 +110054,10 @@ index 78a9e6119fa13437862080d815e84d68f7010d1f..ec1a5c27ead7dce18608eb6314f0ae80 + help + This is the framebuffer driver for the Raspberry Pi Sense HAT diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2..459f9d1d4a37bb386c207df0f3aab581b9eb5e9e 100644 +index 8cd1193b98690b9c4f49098ab14389504d65af3a..c9f1754bf2a6796bf5555fabb9e80f8991cb83bc 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile -@@ -148,6 +148,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o +@@ -147,6 +147,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_MXS) += mxsfb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o @@ -126441,10 +110497,10 @@ index 0000000000000000000000000000000000000000..56196dc2af10e464a1e3f98b028dca1c + +#endif -From 396b0f4386372c8b2ca36a812bad656738b82fe2 Mon Sep 17 00:00:00 2001 +From 63fe5b59d57d2cd54bbe96dc5e0743e977b404f5 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 072/208] ASoC: Add support for HifiBerry DAC +Subject: [PATCH 065/111] ASoC: Add support for HifiBerry DAC This adds a machine driver for the HifiBerry DAC. It is a sound card that can @@ -126452,14 +110508,14 @@ be stacked onto the Raspberry Pi. Signed-off-by: Florian Meier --- - sound/soc/bcm/Kconfig | 9 +++- + sound/soc/bcm/Kconfig | 9 ++- sound/soc/bcm/Makefile | 4 ++ - sound/soc/bcm/hifiberry_dac.c | 123 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 135 insertions(+), 1 deletion(-) + sound/soc/bcm/hifiberry_dac.c | 124 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 sound/soc/bcm/hifiberry_dac.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 03a303e52d5fe57bbdd8769d24bca59067c54c65..42e1358aa1e0f67a08912af7ea17b8756ab06b1c 100644 +index d528aaceaad95bc6bae2147ebe66249629d2512e..ad4817f44072bbc0a92d8a5ebd1b6b365fb4ed82 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -15,4 +15,11 @@ config SND_SOC_CYGNUS @@ -126490,10 +110546,10 @@ index fc739d0078842680802389500dea19334da8fb7b..be80079de3cefbd52f4b78db20ee9a5d +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c new file mode 100644 -index 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8 +index 0000000000000000000000000000000000000000..45f2b770ad9e67728ca599a7445d6ae9a01c0c29 --- /dev/null +++ b/sound/soc/bcm/hifiberry_dac.c -@@ -0,0 +1,123 @@ +@@ -0,0 +1,124 @@ +/* + * ASoC Driver for HifiBerry DAC + * @@ -126559,6 +110615,7 @@ index 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21 +/* audio machine driver */ +static struct snd_soc_card snd_rpi_hifiberry_dac = { + .name = "snd_rpi_hifiberry_dac", ++ .driver_name = "HifiberryDac", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_dac_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), @@ -126618,10 +110675,10 @@ index 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); +MODULE_LICENSE("GPL v2"); -From 39db6b2b07cc619b8f31e9698a1a3c6681d5b532 Mon Sep 17 00:00:00 2001 +From e7c31478dde01383847f0150428a449b46893a77 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Mon, 25 Jan 2016 15:48:59 +0000 -Subject: [PATCH 073/208] ASoC: Add support for Rpi-DAC +Subject: [PATCH 066/111] ASoC: Add support for Rpi-DAC --- sound/soc/bcm/Kconfig | 7 +++ @@ -126635,7 +110692,7 @@ Subject: [PATCH 073/208] ASoC: Add support for Rpi-DAC create mode 100644 sound/soc/codecs/pcm1794a.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 42e1358aa1e0f67a08912af7ea17b8756ab06b1c..8c1e353458a3460f2c3fe26991498ee16f19ecd1 100644 +index ad4817f44072bbc0a92d8a5ebd1b6b365fb4ed82..8209fffdc0be3136a99cbab4e5152759aa95594b 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -23,3 +23,10 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC @@ -126787,10 +110844,10 @@ index 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1 +MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 1cd6ab344d67def61db455d956ac2d7075a1f6d8..9a51aad8c267f08ce568b2eb23da0951b1dc246e 100644 +index c67667bb970f1729db65b027dd8e963b9ee95b7b..74a93e52bdc8116df3db08aaf98fffa1e6f6cc1b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -97,6 +97,7 @@ config SND_SOC_ALL_CODECS +@@ -98,6 +98,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM179X_I2C if I2C select SND_SOC_PCM179X_SPI if SPI_MASTER @@ -126798,7 +110855,7 @@ index 1cd6ab344d67def61db455d956ac2d7075a1f6d8..9a51aad8c267f08ce568b2eb23da0951 select SND_SOC_PCM3008 select SND_SOC_PCM3168A_I2C if I2C select SND_SOC_PCM3168A_SPI if SPI_MASTER -@@ -681,6 +682,10 @@ config SND_SOC_RT5616 +@@ -689,6 +690,10 @@ config SND_SOC_RT5616 tristate "Realtek RT5616 CODEC" depends on I2C @@ -126810,10 +110867,10 @@ index 1cd6ab344d67def61db455d956ac2d7075a1f6d8..9a51aad8c267f08ce568b2eb23da0951 tristate "Realtek ALC5631/RT5631 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 58036af2c7d9837b347ea2b6cdccaad72a711a53..d781f6c90383b3865ae2cc6516e7581bde004d9b 100644 +index 958cd4912fbc9820f965c0d2f38692857f410d3a..77786e7f44a7fa22d9b5beed3eb687e2b7a28526 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile -@@ -92,6 +92,7 @@ snd-soc-pcm1681-objs := pcm1681.o +@@ -93,6 +93,7 @@ snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o snd-soc-pcm179x-spi-objs := pcm179x-spi.o @@ -126821,7 +110878,7 @@ index 58036af2c7d9837b347ea2b6cdccaad72a711a53..d781f6c90383b3865ae2cc6516e7581b snd-soc-pcm3008-objs := pcm3008.o snd-soc-pcm3168a-objs := pcm3168a.o snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o -@@ -321,6 +322,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o +@@ -325,6 +326,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o @@ -126905,10 +110962,10 @@ index 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From a17eab5f9fbde48aabcbecad1b4d173aecdd2287 Mon Sep 17 00:00:00 2001 +From e55d838e108b015dba7611659f3fd9926e45aac5 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 074/208] ASoC: wm8804: Implement MCLK configuration options, +Subject: [PATCH 067/111] ASoC: wm8804: Implement MCLK configuration options, add 32bit support WM8804 can run with PLL frequencies of 256xfs and 128xfs for most sample rates. At 192kHz only 128xfs is supported. The existing driver selects 128xfs automatically for some lower samples rates. By using an @@ -126927,7 +110984,7 @@ Signed-off-by: Daniel Matuschek 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801dc0fa1c7b 100644 +index af95d648265b3e92e345101542b332aee35191d4..513f56ba132929662802d15cdc653af3d059a39c 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, @@ -126954,13 +111011,13 @@ index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801d - .idle_bias_off = true, + .idle_bias_off = false, - .dapm_widgets = wm8804_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + .component_driver = { + .dapm_widgets = wm8804_dapm_widgets, -From c4240b894be6cb535c9a3260dc9071eb38ede175 Mon Sep 17 00:00:00 2001 +From 556c9e016c3bdf1c62e3360d52638560bda63501 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 075/208] ASoC: BCM:Add support for HiFiBerry Digi. Driver is +Subject: [PATCH 068/111] ASoC: BCM:Add support for HiFiBerry Digi. Driver is based on the patched WM8804 driver. Signed-off-by: Daniel Matuschek @@ -126978,15 +111035,19 @@ HiFiBerry Digi: set SPDIF status bits for sample rate The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. While this is optional, some DACs and receivers do not accept this signal. This patch adds the sample rate bits in the SPDIF status block. + +Added HiFiBerry Digi+ Pro driver + +Signed-off-by: Daniel Matuschek --- sound/soc/bcm/Kconfig | 7 ++ sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_digi.c | 224 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 233 insertions(+) + sound/soc/bcm/hifiberry_digi.c | 276 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 285 insertions(+) create mode 100644 sound/soc/bcm/hifiberry_digi.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 8c1e353458a3460f2c3fe26991498ee16f19ecd1..ac1fbf74b808789641aa53b0418632bfee858e79 100644 +index 8209fffdc0be3136a99cbab4e5152759aa95594b..3cd4288a1e1c535210b01cd9561128fd4ea3e87f 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -24,6 +24,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC @@ -127019,10 +111080,10 @@ index 09501910f8152b8d516e098433339b5fc2640d0f..862f00fb43bfb0b8dc75d577df47ea4e obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c new file mode 100644 -index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408cc28c333 +index 0000000000000000000000000000000000000000..19dc953b7227ba86123fc7a2ba654499e0c581c5 --- /dev/null +++ b/sound/soc/bcm/hifiberry_digi.c -@@ -0,0 +1,224 @@ +@@ -0,0 +1,276 @@ +/* + * ASoC Driver for HifiBerry Digi + * @@ -127048,6 +111109,7 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +#include +#include +#include ++#include + +#include "../codecs/wm8804.h" + @@ -127055,9 +111117,34 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); + ++#define CLK_44EN_RATE 22579200UL ++#define CLK_48EN_RATE 24576000UL ++ ++static bool snd_rpi_hifiberry_is_digipro; ++static struct gpio_desc *snd_rpi_hifiberry_clk44gpio; ++static struct gpio_desc *snd_rpi_hifiberry_clk48gpio; + +static int samplerate=44100; + ++static uint32_t snd_rpi_hifiberry_digi_enable_clock(int sample_rate) ++{ ++ switch (sample_rate) { ++ case 11025: ++ case 22050: ++ case 44100: ++ case 88200: ++ case 176400: ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 1); ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 0); ++ return CLK_44EN_RATE; ++ default: ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 1); ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 0); ++ return CLK_48EN_RATE; ++ } ++} ++ ++ +static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; @@ -127065,6 +111152,14 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + /* enable TX output */ + snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); + ++ /* Initialize Digi+ Pro hardware */ ++ if (snd_rpi_hifiberry_is_digipro) { ++ struct snd_soc_dai_link *dai = rtd->dai_link; ++ ++ dai->name = "HiFiBerry Digi+ Pro"; ++ dai->stream_name = "HiFiBerry Digi+ Pro HiFi"; ++ } ++ + return 0; +} + @@ -127112,6 +111207,9 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + mclk_freq=samplerate*128; + mclk_div=WM8804_MCLKDIV_128FS; + } ++ ++ if (snd_rpi_hifiberry_is_digipro) ++ sysclk = snd_rpi_hifiberry_digi_enable_clock(samplerate); + + switch (samplerate) { + case 32000: @@ -127146,6 +111244,7 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, + sysclk, SND_SOC_CLOCK_OUT); ++ + if (ret < 0) { + dev_err(codec->dev, + "Failed to set WM8804 SYSCLK: %d\n", ret); @@ -127189,6 +111288,7 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +/* audio machine driver */ +static struct snd_soc_card snd_rpi_hifiberry_digi = { + .name = "snd_rpi_hifiberry_digi", ++ .driver_name = "HifiberryDigi", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_digi_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), @@ -127212,6 +111312,19 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + dai->platform_name = NULL; + dai->platform_of_node = i2s_node; + } ++ ++ snd_rpi_hifiberry_is_digipro = 1; ++ ++ snd_rpi_hifiberry_clk44gpio = ++ devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW); ++ if (IS_ERR(snd_rpi_hifiberry_clk44gpio)) ++ snd_rpi_hifiberry_is_digipro = 0; ++ ++ snd_rpi_hifiberry_clk48gpio = ++ devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW); ++ if (IS_ERR(snd_rpi_hifiberry_clk48gpio)) ++ snd_rpi_hifiberry_is_digipro = 0; ++ + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); @@ -127248,10 +111361,10 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); +MODULE_LICENSE("GPL v2"); -From d75574658dee579a87b081abf15d7b8f18006156 Mon Sep 17 00:00:00 2001 +From 2cffe8450f73abcb7ccdcef2b0f62e4ac7e064e6 Mon Sep 17 00:00:00 2001 From: Gordon Garrity Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 076/208] Add IQaudIO Sound Card support for Raspberry Pi +Subject: [PATCH 069/111] Add IQaudIO Sound Card support for Raspberry Pi Set a limit of 0dB on Digital Volume Control @@ -127312,7 +111425,7 @@ Signed-off-by: DigitalDreamtime create mode 100644 sound/soc/bcm/iqaudio-dac.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index ac1fbf74b808789641aa53b0418632bfee858e79..fa4a8fd28bb977edc66dd4e9bd5ebc8ce5e47916 100644 +index 3cd4288a1e1c535210b01cd9561128fd4ea3e87f..8272ba5302b1ddbd9c21ee50891d3cb0f0303c58 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -37,3 +37,10 @@ config SND_BCM2708_SOC_RPI_DAC @@ -127581,10 +111694,10 @@ index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); +MODULE_LICENSE("GPL v2"); -From ab9d6e71cd86d0b32c9100e19dd44a075e3e9645 Mon Sep 17 00:00:00 2001 +From 375717ae06cb32b14e2c615798b51d4bc384c0b0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jul 2016 17:06:50 +0100 -Subject: [PATCH 077/208] iqaudio-dac: Compile fix - untested +Subject: [PATCH 070/111] iqaudio-dac: Compile fix - untested --- sound/soc/bcm/iqaudio-dac.c | 6 +++++- @@ -127608,10 +111721,10 @@ index 4e8e6dec14bcf4a1ff286c43742d4097249d6777..aa15bc4b49ca95edec905fddd8fd0a6d if (dapm->dev != codec_dai->dev) return 0; -From 962edd733d593be9f0542a3aeb9a0591ab5ab5c1 Mon Sep 17 00:00:00 2001 +From 8c1655f7ed054fab977e814fa775ba3d0132a71e Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 078/208] Added support for HiFiBerry DAC+ +Subject: [PATCH 071/111] Added support for HiFiBerry DAC+ The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses a different codec chip (PCM5122), therefore a new driver is necessary. @@ -127641,14 +111754,14 @@ Signed-off-by: DigitalDreamtime drivers/clk/clk-hifiberry-dacpro.c | 160 +++++++++++++++++ sound/soc/bcm/Kconfig | 7 + sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_dacplus.c | 358 +++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/hifiberry_dacplus.c | 359 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/pcm512x.c | 3 +- - 6 files changed, 530 insertions(+), 1 deletion(-) + 6 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/clk-hifiberry-dacpro.c create mode 100644 sound/soc/bcm/hifiberry_dacplus.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index 3b6f9cf3464aaddca0a54886aa575a108c21b7ca..698a88576e9d760feaf824683edf4c9adcbe7c49 100644 +index 925081ec14c04935e1eb17bf2709640c7ae3ae10..2b6fcd8abf79da77aa85fdc53512aafd09f836cb 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o @@ -127656,9 +111769,9 @@ index 3b6f9cf3464aaddca0a54886aa575a108c21b7ca..698a88576e9d760feaf824683edf4c9a obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o - obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o - obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o + obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o + obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o diff --git a/drivers/clk/clk-hifiberry-dacpro.c b/drivers/clk/clk-hifiberry-dacpro.c new file mode 100644 index 0000000000000000000000000000000000000000..99cee2b1706c43170b4fc35c0023349b9019606c @@ -127826,7 +111939,7 @@ index 0000000000000000000000000000000000000000..99cee2b1706c43170b4fc35c0023349b +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:clk-hifiberry-dacpro"); diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index fa4a8fd28bb977edc66dd4e9bd5ebc8ce5e47916..3477304b789c87ebe75fde3876cb4a3a572b1bb8 100644 +index 8272ba5302b1ddbd9c21ee50891d3cb0f0303c58..4473cc728097bda0ce9fe68d4a9da348ec41f8b3 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -24,6 +24,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC @@ -127863,10 +111976,10 @@ index fcac518ca9b46ab2074fc859b8d2f1ff850ebc19..203afc03167acbcad15e836209956bc5 obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c new file mode 100644 -index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a80889221a1d6 +index 0000000000000000000000000000000000000000..bdc35e7e6bc12dc1cf04f5ffad8f9ab49a0b0266 --- /dev/null +++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -0,0 +1,358 @@ +@@ -0,0 +1,359 @@ +/* + * ASoC Driver for HiFiBerry DAC+ / DAC Pro + * @@ -128160,6 +112273,7 @@ index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a8088 +/* audio machine driver */ +static struct snd_soc_card snd_rpi_hifiberry_dacplus = { + .name = "snd_rpi_hifiberry_dacplus", ++ .driver_name = "HifiberryDacp", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_dacplus_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), @@ -128226,7 +112340,7 @@ index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a8088 +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c -index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb69f87d693 100644 +index 72b19e62f6267698aea45d2410d616d91c1825cb..c6839ef6e16754ed9de2698507b8986addd822fe 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -854,7 +854,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, @@ -128240,10 +112354,10 @@ index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb6 dev_err(dev, "No LRCLK?\n"); return -EINVAL; -From 291d3872c447b25b51ad03f52787442cec78dd1f Mon Sep 17 00:00:00 2001 +From 1f802ccf0a9e67907572ea2f881975a904ec3bf5 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 079/208] Added driver for HiFiBerry Amp amplifier add-on board +Subject: [PATCH 072/111] Added driver for HiFiBerry Amp amplifier add-on board The driver contains a low-level hardware driver for the TAS5713 and the drivers for the Raspberry Pi I2S subsystem. @@ -128261,18 +112375,18 @@ Some code to load the driver based on device-tree-overlays was missing. This is --- sound/soc/bcm/Kconfig | 7 + sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 128 +++++++++++++++ + sound/soc/bcm/hifiberry_amp.c | 129 +++++++++++++++ sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ - 7 files changed, 722 insertions(+) + 7 files changed, 723 insertions(+) create mode 100644 sound/soc/bcm/hifiberry_amp.c create mode 100644 sound/soc/codecs/tas5713.c create mode 100644 sound/soc/codecs/tas5713.h diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 3477304b789c87ebe75fde3876cb4a3a572b1bb8..f764110b86b790a2b639cc66b965e187d9f52ce3 100644 +index 4473cc728097bda0ce9fe68d4a9da348ec41f8b3..b1d877407dd69c9bd6b2787b0a559f4113bc21f2 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -38,6 +38,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI @@ -128309,10 +112423,10 @@ index 203afc03167acbcad15e836209956bc5ab151157..a4838e2cf8e93c9285836f95f4151dae obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c new file mode 100644 -index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1 +index 0000000000000000000000000000000000000000..d17c29780507dc31c50f1d567ff5cea7c8241ff5 --- /dev/null +++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,128 @@ +@@ -0,0 +1,129 @@ +/* + * ASoC Driver for HifiBerry AMP + * @@ -128376,6 +112490,7 @@ index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7d + +static struct snd_soc_card snd_rpi_hifiberry_amp = { + .name = "snd_rpi_hifiberry_amp", ++ .driver_name = "HifiberryAmp", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_amp_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), @@ -128442,10 +112557,10 @@ index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7d +MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 9a51aad8c267f08ce568b2eb23da0951b1dc246e..37674869e4ef2dc33b59ace8ef36e404d5a809a2 100644 +index 74a93e52bdc8116df3db08aaf98fffa1e6f6cc1b..9824cdd04b0c11c45b8cedd0187a0eba8f1dc2d4 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -136,6 +136,7 @@ config SND_SOC_ALL_CODECS +@@ -139,6 +139,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TFA9879 if I2C select SND_SOC_TLV320AIC23_I2C if I2C select SND_SOC_TLV320AIC23_SPI if SPI_MASTER @@ -128453,7 +112568,7 @@ index 9a51aad8c267f08ce568b2eb23da0951b1dc246e..37674869e4ef2dc33b59ace8ef36e404 select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC31XX if I2C select SND_SOC_TLV320AIC32X4_I2C if I2C -@@ -807,6 +808,9 @@ config SND_SOC_TFA9879 +@@ -821,6 +822,9 @@ config SND_SOC_TFA9879 tristate "NXP Semiconductors TFA9879 amplifier" depends on I2C @@ -128464,10 +112579,10 @@ index 9a51aad8c267f08ce568b2eb23da0951b1dc246e..37674869e4ef2dc33b59ace8ef36e404 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index d781f6c90383b3865ae2cc6516e7581bde004d9b..c21145c8a55a9a25e6a37d6e06c1ab5d37ddf603 100644 +index 77786e7f44a7fa22d9b5beed3eb687e2b7a28526..5a2db0d2fe2f49920eeccfecef62c969ae2e99a1 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile -@@ -141,6 +141,7 @@ snd-soc-tas5086-objs := tas5086.o +@@ -144,6 +144,7 @@ snd-soc-tas5086-objs := tas5086.o snd-soc-tas571x-objs := tas571x.o snd-soc-tas5720-objs := tas5720.o snd-soc-tfa9879-objs := tfa9879.o @@ -128475,7 +112590,7 @@ index d781f6c90383b3865ae2cc6516e7581bde004d9b..c21145c8a55a9a25e6a37d6e06c1ab5d snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -360,6 +361,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o +@@ -366,6 +367,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o @@ -129075,121 +113190,835 @@ index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8 + +#endif /* _TAS5713_H */ -From 11db210348ec63453d86cb144b3f5c17feedfacf Mon Sep 17 00:00:00 2001 -From: "Daniel Matuschek (HiFiBerry)" -Date: Tue, 26 Jul 2016 19:16:25 +0200 -Subject: [PATCH 080/208] Added HiFiBerry Digi+ Pro driver +From 7c0248b02d38aeb82181a3d86d999cc1e8b4e5b3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 12 Dec 2016 16:26:54 +0000 +Subject: [PATCH 073/111] Revert "Added driver for HiFiBerry Amp amplifier + add-on board" -Signed-off-by: Daniel Matuschek +This reverts commit 3e6b00833d92a50cbcc9922deb6e1bc8fcdbb587. --- - sound/soc/bcm/hifiberry_digi.c | 51 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 51 insertions(+) + sound/soc/bcm/Kconfig | 7 - + sound/soc/bcm/Makefile | 2 - + sound/soc/bcm/hifiberry_amp.c | 129 --------------- + sound/soc/codecs/Kconfig | 4 - + sound/soc/codecs/Makefile | 2 - + sound/soc/codecs/tas5713.c | 369 ------------------------------------------ + sound/soc/codecs/tas5713.h | 210 ------------------------ + 7 files changed, 723 deletions(-) + delete mode 100644 sound/soc/bcm/hifiberry_amp.c + delete mode 100644 sound/soc/codecs/tas5713.c + delete mode 100644 sound/soc/codecs/tas5713.h -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 9840e15d3e2be6396bc3ce6e74749408cc28c333..52ab9dea2e724c4238986ca53c59c8492f64e345 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index b1d877407dd69c9bd6b2787b0a559f4113bc21f2..4473cc728097bda0ce9fe68d4a9da348ec41f8b3 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -38,13 +38,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI + help + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - #include "../codecs/wm8804.h" +-config SND_BCM2708_SOC_HIFIBERRY_AMP +- tristate "Support for the HifiBerry Amp" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +- select SND_SOC_TAS5713 +- help +- Say Y or M if you want to add support for the HifiBerry Amp amplifier board. +- + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index a4838e2cf8e93c9285836f95f4151daea33e1bd1..203afc03167acbcad15e836209956bc5ab151157 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -12,13 +12,11 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o +-snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o -@@ -30,9 +31,34 @@ static short int auto_shutdown_output = 0; - module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o +-obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c +deleted file mode 100644 +index d17c29780507dc31c50f1d567ff5cea7c8241ff5..0000000000000000000000000000000000000000 +--- a/sound/soc/bcm/hifiberry_amp.c ++++ /dev/null +@@ -1,129 +0,0 @@ +-/* +- * ASoC Driver for HifiBerry AMP +- * +- * Author: Sebastian Eickhoff +- * Copyright 2014 +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * 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. +- */ +- +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) +-{ +- // ToDo: init of the dsp-registers. +- return 0; +-} +- +-static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params ) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- +- return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); +-} +- +-static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { +- .hw_params = snd_rpi_hifiberry_amp_hw_params, +-}; +- +-static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { +- { +- .name = "HifiBerry AMP", +- .stream_name = "HifiBerry AMP HiFi", +- .cpu_dai_name = "bcm2708-i2s.0", +- .codec_dai_name = "tas5713-hifi", +- .platform_name = "bcm2708-i2s.0", +- .codec_name = "tas5713.1-001b", +- .dai_fmt = SND_SOC_DAIFMT_I2S | +- SND_SOC_DAIFMT_NB_NF | +- SND_SOC_DAIFMT_CBS_CFS, +- .ops = &snd_rpi_hifiberry_amp_ops, +- .init = snd_rpi_hifiberry_amp_init, +- }, +-}; +- +- +-static struct snd_soc_card snd_rpi_hifiberry_amp = { +- .name = "snd_rpi_hifiberry_amp", +- .driver_name = "HifiberryAmp", +- .owner = THIS_MODULE, +- .dai_link = snd_rpi_hifiberry_amp_dai, +- .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), +-}; +- +-static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { +- { .compatible = "hifiberry,hifiberry-amp", }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); +- +- +-static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) +-{ +- int ret = 0; +- +- snd_rpi_hifiberry_amp.dev = &pdev->dev; +- +- if (pdev->dev.of_node) { +- struct device_node *i2s_node; +- struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; +- i2s_node = of_parse_phandle(pdev->dev.of_node, +- "i2s-controller", 0); +- +- if (i2s_node) { +- dai->cpu_dai_name = NULL; +- dai->cpu_of_node = i2s_node; +- dai->platform_name = NULL; +- dai->platform_of_node = i2s_node; +- } +- } +- +- ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); +- +- if (ret != 0) { +- dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); +- } +- +- return ret; +-} +- +- +-static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) +-{ +- return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); +-} +- +- +-static struct platform_driver snd_rpi_hifiberry_amp_driver = { +- .driver = { +- .name = "snd-hifiberry-amp", +- .owner = THIS_MODULE, +- .of_match_table = snd_rpi_hifiberry_amp_of_match, +- }, +- .probe = snd_rpi_hifiberry_amp_probe, +- .remove = snd_rpi_hifiberry_amp_remove, +-}; +- +- +-module_platform_driver(snd_rpi_hifiberry_amp_driver); +- +- +-MODULE_AUTHOR("Sebastian Eickhoff "); +-MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 9824cdd04b0c11c45b8cedd0187a0eba8f1dc2d4..74a93e52bdc8116df3db08aaf98fffa1e6f6cc1b 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -139,7 +139,6 @@ config SND_SOC_ALL_CODECS + select SND_SOC_TFA9879 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER +- select SND_SOC_TAS5713 if I2C + select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C + select SND_SOC_TLV320AIC32X4_I2C if I2C +@@ -822,9 +821,6 @@ config SND_SOC_TFA9879 + tristate "NXP Semiconductors TFA9879 amplifier" + depends on I2C -+#define CLK_44EN_RATE 22579200UL -+#define CLK_48EN_RATE 24576000UL -+ -+static bool snd_rpi_hifiberry_is_digipro; -+static struct gpio_desc *snd_rpi_hifiberry_clk44gpio; -+static struct gpio_desc *snd_rpi_hifiberry_clk48gpio; +-config SND_SOC_TAS5713 +- tristate +- + config SND_SOC_TLV320AIC23 + tristate - static int samplerate=44100; - -+static uint32_t snd_rpi_hifiberry_digi_enable_clock(int sample_rate) -+{ -+ switch (sample_rate) { -+ case 11025: -+ case 22050: -+ case 44100: -+ case 88200: -+ case 176400: -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 1); -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 0); -+ return CLK_44EN_RATE; -+ default: -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 1); -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 0); -+ return CLK_48EN_RATE; -+ } -+} -+ -+ - static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) - { - struct snd_soc_codec *codec = rtd->codec; -@@ -40,6 +66,14 @@ static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) - /* enable TX output */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); - -+ /* Initialize Digi+ Pro hardware */ -+ if (snd_rpi_hifiberry_is_digipro) { -+ struct snd_soc_dai_link *dai = rtd->dai_link; -+ -+ dai->name = "HiFiBerry Digi+ Pro"; -+ dai->stream_name = "HiFiBerry Digi+ Pro HiFi"; -+ } -+ - return 0; - } - -@@ -87,6 +121,9 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - mclk_freq=samplerate*128; - mclk_div=WM8804_MCLKDIV_128FS; - } -+ -+ if (snd_rpi_hifiberry_is_digipro) -+ sysclk = snd_rpi_hifiberry_digi_enable_clock(samplerate); - - switch (samplerate) { - case 32000: -@@ -121,6 +158,7 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - - ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, - sysclk, SND_SOC_CLOCK_OUT); -+ - if (ret < 0) { - dev_err(codec->dev, - "Failed to set WM8804 SYSCLK: %d\n", ret); -@@ -187,6 +225,19 @@ static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) - dai->platform_name = NULL; - dai->platform_of_node = i2s_node; - } -+ -+ snd_rpi_hifiberry_is_digipro = 1; -+ -+ snd_rpi_hifiberry_clk44gpio = -+ devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW); -+ if (IS_ERR(snd_rpi_hifiberry_clk44gpio)) -+ snd_rpi_hifiberry_is_digipro = 0; -+ -+ snd_rpi_hifiberry_clk48gpio = -+ devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW); -+ if (IS_ERR(snd_rpi_hifiberry_clk48gpio)) -+ snd_rpi_hifiberry_is_digipro = 0; -+ - } - - ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 5a2db0d2fe2f49920eeccfecef62c969ae2e99a1..77786e7f44a7fa22d9b5beed3eb687e2b7a28526 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -144,7 +144,6 @@ snd-soc-tas5086-objs := tas5086.o + snd-soc-tas571x-objs := tas571x.o + snd-soc-tas5720-objs := tas5720.o + snd-soc-tfa9879-objs := tfa9879.o +-snd-soc-tas5713-objs := tas5713.o + snd-soc-tlv320aic23-objs := tlv320aic23.o + snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o + snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o +@@ -367,7 +366,6 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o + obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o + obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o + obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o +-obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o + obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o +diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c +deleted file mode 100644 +index 9b2713861dcbed751842ca29c88eb1eae5867411..0000000000000000000000000000000000000000 +--- a/sound/soc/codecs/tas5713.c ++++ /dev/null +@@ -1,369 +0,0 @@ +-/* +- * ASoC Driver for TAS5713 +- * +- * Author: Sebastian Eickhoff +- * Copyright 2014 +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * 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. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include "tas5713.h" +- +- +-static struct i2c_client *i2c; +- +-struct tas5713_priv { +- struct regmap *regmap; +- int mclk_div; +- struct snd_soc_codec *codec; +-}; +- +-static struct tas5713_priv *priv_data; +- +- +- +- +-/* +- * _ _ ___ _ ___ _ _ +- * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ +- * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< +- * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ +- * +- */ +- +-static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); +- +- +-static const struct snd_kcontrol_new tas5713_snd_controls[] = { +- SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), +- SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) +-}; +- +- +- +- +-/* +- * __ __ _ _ ___ _ +- * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ +- * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| +- * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| +- * +- */ +- +-static int tas5713_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct snd_soc_dai *dai) +-{ +- u16 blen = 0x00; +- +- struct snd_soc_codec *codec; +- codec = dai->codec; +- priv_data->codec = dai->codec; +- +- switch (params_format(params)) { +- case SNDRV_PCM_FORMAT_S16_LE: +- blen = 0x03; +- break; +- case SNDRV_PCM_FORMAT_S20_3LE: +- blen = 0x1; +- break; +- case SNDRV_PCM_FORMAT_S24_LE: +- blen = 0x04; +- break; +- case SNDRV_PCM_FORMAT_S32_LE: +- blen = 0x05; +- break; +- default: +- dev_err(dai->dev, "Unsupported word length: %u\n", +- params_format(params)); +- return -EINVAL; +- } +- +- // set word length +- snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); +- +- return 0; +-} +- +- +-static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +-{ +- unsigned int val = 0; +- +- struct tas5713_priv *tas5713; +- struct snd_soc_codec *codec = dai->codec; +- tas5713 = snd_soc_codec_get_drvdata(codec); +- +- if (mute) { +- val = TAS5713_SOFT_MUTE_ALL; +- } +- +- return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); +-} +- +- +-static const struct snd_soc_dai_ops tas5713_dai_ops = { +- .hw_params = tas5713_hw_params, +- .mute_stream = tas5713_mute_stream, +-}; +- +- +-static struct snd_soc_dai_driver tas5713_dai = { +- .name = "tas5713-hifi", +- .playback = { +- .stream_name = "Playback", +- .channels_min = 2, +- .channels_max = 2, +- .rates = SNDRV_PCM_RATE_8000_48000, +- .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), +- }, +- .ops = &tas5713_dai_ops, +-}; +- +- +- +- +-/* +- * ___ _ ___ _ +- * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ +- * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| +- * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| +- * +- */ +- +-static int tas5713_remove(struct snd_soc_codec *codec) +-{ +- struct tas5713_priv *tas5713; +- +- tas5713 = snd_soc_codec_get_drvdata(codec); +- +- return 0; +-} +- +- +-static int tas5713_probe(struct snd_soc_codec *codec) +-{ +- struct tas5713_priv *tas5713; +- int i, ret; +- +- i2c = container_of(codec->dev, struct i2c_client, dev); +- +- tas5713 = snd_soc_codec_get_drvdata(codec); +- +- // Reset error +- ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); +- if (ret < 0) return ret; +- +- // Trim oscillator +- ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); +- if (ret < 0) return ret; +- msleep(1000); +- +- // Reset error +- ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); +- if (ret < 0) return ret; +- +- // Clock mode: 44/48kHz, MCLK=64xfs +- ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); +- if (ret < 0) return ret; +- +- // I2S 24bit +- ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); +- if (ret < 0) return ret; +- +- // Unmute +- ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); +- if (ret < 0) return ret; +- ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); +- if (ret < 0) return ret; +- +- // Set volume to 0db +- ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); +- if (ret < 0) return ret; +- +- // Now start programming the default initialization sequence +- for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { +- ret = i2c_master_send(i2c, +- tas5713_init_sequence[i].data, +- tas5713_init_sequence[i].size); +- if (ret < 0) { +- printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); +- } +- } +- +- // Unmute +- ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); +- if (ret < 0) return ret; +- +- return 0; +-} +- +- +-static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { +- .probe = tas5713_probe, +- .remove = tas5713_remove, +- .controls = tas5713_snd_controls, +- .num_controls = ARRAY_SIZE(tas5713_snd_controls), +-}; +- +- +- +- +-/* +- * ___ ___ ___ ___ _ +- * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ +- * | | / / (__ | |) | '_| \ V / -_) '_| +- * |___/___\___| |___/|_| |_|\_/\___|_| +- * +- */ +- +-static const struct reg_default tas5713_reg_defaults[] = { +- { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB +- { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB +- { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB +- { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB +-}; +- +- +-static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) +-{ +- switch (reg) { +- case TAS5713_DEVICE_ID: +- case TAS5713_ERROR_STATUS: +- return true; +- default: +- return false; +- } +-} +- +- +-static const struct of_device_id tas5713_of_match[] = { +- { .compatible = "ti,tas5713", }, +- { } +-}; +-MODULE_DEVICE_TABLE(of, tas5713_of_match); +- +- +-static struct regmap_config tas5713_regmap_config = { +- .reg_bits = 8, +- .val_bits = 8, +- +- .max_register = TAS5713_MAX_REGISTER, +- .volatile_reg = tas5713_reg_volatile, +- +- .cache_type = REGCACHE_RBTREE, +- .reg_defaults = tas5713_reg_defaults, +- .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), +-}; +- +- +-static int tas5713_i2c_probe(struct i2c_client *i2c, +- const struct i2c_device_id *id) +-{ +- int ret; +- +- priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); +- if (!priv_data) +- return -ENOMEM; +- +- priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); +- if (IS_ERR(priv_data->regmap)) { +- ret = PTR_ERR(priv_data->regmap); +- return ret; +- } +- +- i2c_set_clientdata(i2c, priv_data); +- +- ret = snd_soc_register_codec(&i2c->dev, +- &soc_codec_dev_tas5713, &tas5713_dai, 1); +- +- return ret; +-} +- +- +-static int tas5713_i2c_remove(struct i2c_client *i2c) +-{ +- snd_soc_unregister_codec(&i2c->dev); +- i2c_set_clientdata(i2c, NULL); +- +- kfree(priv_data); +- +- return 0; +-} +- +- +-static const struct i2c_device_id tas5713_i2c_id[] = { +- { "tas5713", 0 }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); +- +- +-static struct i2c_driver tas5713_i2c_driver = { +- .driver = { +- .name = "tas5713", +- .owner = THIS_MODULE, +- .of_match_table = tas5713_of_match, +- }, +- .probe = tas5713_i2c_probe, +- .remove = tas5713_i2c_remove, +- .id_table = tas5713_i2c_id +-}; +- +- +-static int __init tas5713_modinit(void) +-{ +- int ret = 0; +- +- ret = i2c_add_driver(&tas5713_i2c_driver); +- if (ret) { +- printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", +- ret); +- } +- +- return ret; +-} +-module_init(tas5713_modinit); +- +- +-static void __exit tas5713_exit(void) +-{ +- i2c_del_driver(&tas5713_i2c_driver); +-} +-module_exit(tas5713_exit); +- +- +-MODULE_AUTHOR("Sebastian Eickhoff "); +-MODULE_DESCRIPTION("ASoC driver for TAS5713"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h +deleted file mode 100644 +index 8f019e04898754d2f87e9630137be9e8f612a342..0000000000000000000000000000000000000000 +--- a/sound/soc/codecs/tas5713.h ++++ /dev/null +@@ -1,210 +0,0 @@ +-/* +- * ASoC Driver for TAS5713 +- * +- * Author: Sebastian Eickhoff +- * Copyright 2014 +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * 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. +- */ +- +-#ifndef _TAS5713_H +-#define _TAS5713_H +- +- +-// TAS5713 I2C-bus register addresses +- +-#define TAS5713_CLOCK_CTRL 0x00 +-#define TAS5713_DEVICE_ID 0x01 +-#define TAS5713_ERROR_STATUS 0x02 +-#define TAS5713_SYSTEM_CTRL1 0x03 +-#define TAS5713_SERIAL_DATA_INTERFACE 0x04 +-#define TAS5713_SYSTEM_CTRL2 0x05 +-#define TAS5713_SOFT_MUTE 0x06 +-#define TAS5713_VOL_MASTER 0x07 +-#define TAS5713_VOL_CH1 0x08 +-#define TAS5713_VOL_CH2 0x09 +-#define TAS5713_VOL_HEADPHONE 0x0A +-#define TAS5713_VOL_CONFIG 0x0E +-#define TAS5713_MODULATION_LIMIT 0x10 +-#define TAS5713_IC_DLY_CH1 0x11 +-#define TAS5713_IC_DLY_CH2 0x12 +-#define TAS5713_IC_DLY_CH3 0x13 +-#define TAS5713_IC_DLY_CH4 0x14 +- +-#define TAS5713_START_STOP_PERIOD 0x1A +-#define TAS5713_OSC_TRIM 0x1B +-#define TAS5713_BKND_ERR 0x1C +- +-#define TAS5713_INPUT_MUX 0x20 +-#define TAS5713_SRC_SELECT_CH4 0x21 +-#define TAS5713_PWM_MUX 0x25 +- +-#define TAS5713_CH1_BQ0 0x29 +-#define TAS5713_CH1_BQ1 0x2A +-#define TAS5713_CH1_BQ2 0x2B +-#define TAS5713_CH1_BQ3 0x2C +-#define TAS5713_CH1_BQ4 0x2D +-#define TAS5713_CH1_BQ5 0x2E +-#define TAS5713_CH1_BQ6 0x2F +-#define TAS5713_CH1_BQ7 0x58 +-#define TAS5713_CH1_BQ8 0x59 +- +-#define TAS5713_CH2_BQ0 0x30 +-#define TAS5713_CH2_BQ1 0x31 +-#define TAS5713_CH2_BQ2 0x32 +-#define TAS5713_CH2_BQ3 0x33 +-#define TAS5713_CH2_BQ4 0x34 +-#define TAS5713_CH2_BQ5 0x35 +-#define TAS5713_CH2_BQ6 0x36 +-#define TAS5713_CH2_BQ7 0x5C +-#define TAS5713_CH2_BQ8 0x5D +- +-#define TAS5713_CH4_BQ0 0x5A +-#define TAS5713_CH4_BQ1 0x5B +-#define TAS5713_CH3_BQ0 0x5E +-#define TAS5713_CH3_BQ1 0x5F +- +-#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B +-#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C +-#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E +-#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F +-#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 +-#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 +-#define TAS5713_DRC_CTRL 0x46 +- +-#define TAS5713_BANK_SW_CTRL 0x50 +-#define TAS5713_CH1_OUTPUT_MIXER 0x51 +-#define TAS5713_CH2_OUTPUT_MIXER 0x52 +-#define TAS5713_CH1_INPUT_MIXER 0x53 +-#define TAS5713_CH2_INPUT_MIXER 0x54 +-#define TAS5713_OUTPUT_POST_SCALE 0x56 +-#define TAS5713_OUTPUT_PRESCALE 0x57 +- +-#define TAS5713_IDF_POST_SCALE 0x62 +- +-#define TAS5713_CH1_INLINE_MIXER 0x70 +-#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 +-#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 +-#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 +-#define TAS5713_CH2_INLINE_MIXER 0x74 +-#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 +-#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 +-#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 +- +-#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 +-#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 +- +-#define TAS5713_REGISTER_COUNT 0x46 +-#define TAS5713_MAX_REGISTER 0xF9 +- +- +-// Bitmasks for registers +-#define TAS5713_SOFT_MUTE_ALL 0x07 +- +- +- +-struct tas5713_init_command { +- const int size; +- const char *const data; +-}; +- +-static const struct tas5713_init_command tas5713_init_sequence[] = { +- +- // Trim oscillator +- { .size = 2, .data = "\x1B\x00" }, +- // System control register 1 (0x03): block DC +- { .size = 2, .data = "\x03\x80" }, +- // Mute everything +- { .size = 2, .data = "\x05\x40" }, +- // Modulation limit register (0x10): 97.7% +- { .size = 2, .data = "\x10\x02" }, +- // Interchannel delay registers +- // (0x11, 0x12, 0x13, and 0x14): BD mode +- { .size = 2, .data = "\x11\xB8" }, +- { .size = 2, .data = "\x12\x60" }, +- { .size = 2, .data = "\x13\xA0" }, +- { .size = 2, .data = "\x14\x48" }, +- // PWM shutdown group register (0x19): no shutdown +- { .size = 2, .data = "\x19\x00" }, +- // Input multiplexer register (0x20): BD mode +- { .size = 2, .data = "\x20\x00\x89\x77\x72" }, +- // PWM output mux register (0x25) +- // Channel 1 --> OUTA, channel 1 neg --> OUTB +- // Channel 2 --> OUTC, channel 2 neg --> OUTD +- { .size = 5, .data = "\x25\x01\x02\x13\x45" }, +- // DRC control (0x46): DRC off +- { .size = 5, .data = "\x46\x00\x00\x00\x00" }, +- // BKND_ERR register (0x1C): 299ms reset period +- { .size = 2, .data = "\x1C\x07" }, +- // Mute channel 3 +- { .size = 2, .data = "\x0A\xFF" }, +- // Volume configuration register (0x0E): volume slew 512 steps +- { .size = 2, .data = "\x0E\x90" }, +- // Clock control register (0x00): 44/48kHz, MCLK=64xfs +- { .size = 2, .data = "\x00\x60" }, +- // Bank switch and eq control (0x50): no bank switching +- { .size = 5, .data = "\x50\x00\x00\x00\x00" }, +- // Volume registers (0x07, 0x08, 0x09, 0x0A) +- { .size = 2, .data = "\x07\x20" }, +- { .size = 2, .data = "\x08\x30" }, +- { .size = 2, .data = "\x09\x30" }, +- { .size = 2, .data = "\x0A\xFF" }, +- // 0x72, 0x73, 0x76, 0x77 input mixer: +- // no intermix between channels +- { .size = 5, .data = "\x72\x00\x00\x00\x00" }, +- { .size = 5, .data = "\x73\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x76\x00\x00\x00\x00" }, +- { .size = 5, .data = "\x77\x00\x80\x00\x00" }, +- // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: +- // no inline DRC inmix +- { .size = 5, .data = "\x70\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x71\x00\x00\x00\x00" }, +- { .size = 5, .data = "\x74\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x75\x00\x00\x00\x00" }, +- // 0x56, 0x57 Output scale +- { .size = 5, .data = "\x56\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x57\x00\x02\x00\x00" }, +- // 0x3B, 0x3c +- { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, +- { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, +- { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- // 0x51, 0x52: output mixer +- { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, +- { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, +- // PEQ defaults +- { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +-}; +- +- +-#endif /* _TAS5713_H */ -From ca49f7825bbd719ed413c05a07a4c004b598850c Mon Sep 17 00:00:00 2001 +From 3696c3507465b578e9db9edcf2567f9cc4f50ea9 Mon Sep 17 00:00:00 2001 From: Ryan Coe Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 081/208] Update ds1307 driver for device-tree support +Subject: [PATCH 074/111] Update ds1307 driver for device-tree support Signed-off-by: Ryan Coe --- @@ -129197,10 +114026,10 @@ Signed-off-by: Ryan Coe 1 file changed, 8 insertions(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index 8e1c5cb6ece6f60619e5cafcea4271e056d96778..f9536679b270a39a4d9639fdbd3420fecbf1d169 100644 +index 4e31036ee2596dec93accd26f627c5b95591ae9f..b92044cf03e750afa521a93519500e9d128486f4 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c -@@ -1631,6 +1631,14 @@ static int ds1307_remove(struct i2c_client *client) +@@ -1675,6 +1675,14 @@ static int ds1307_remove(struct i2c_client *client) return 0; } @@ -129216,10 +114045,10 @@ index 8e1c5cb6ece6f60619e5cafcea4271e056d96778..f9536679b270a39a4d9639fdbd3420fe .driver = { .name = "rtc-ds1307", -From cbc94ab92e62b8628bd4648e2391ee1582c199ba Mon Sep 17 00:00:00 2001 +From f4ce7691f7e0dd6c047041d87e29876365e6ee27 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 082/208] Add driver for rpi-proto +Subject: [PATCH 075/111] Add driver for rpi-proto Forward port of 3.10.x driver from https://github.com/koalo We are using a custom board and would like to use rpi 3.18.x @@ -129239,10 +114068,10 @@ Signed-off-by: Waldemar Brodkorb create mode 100644 sound/soc/bcm/rpi-proto.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index f764110b86b790a2b639cc66b965e187d9f52ce3..5b08c4dfb71597d6f6381146c4ce79e57f551b9c 100644 +index 4473cc728097bda0ce9fe68d4a9da348ec41f8b3..ac0dbaf29b821c4b21855f22104a986f6e0849ec 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -52,6 +52,13 @@ config SND_BCM2708_SOC_RPI_DAC +@@ -45,6 +45,13 @@ config SND_BCM2708_SOC_RPI_DAC help Say Y or M if you want to add support for RPi-DAC. @@ -129257,20 +114086,19 @@ index f764110b86b790a2b639cc66b965e187d9f52ce3..5b08c4dfb71597d6f6381146c4ce79e5 tristate "Support for IQaudIO-DAC" depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index a4838e2cf8e93c9285836f95f4151daea33e1bd1..680d1b6d5e16819094fbfaa6c42b458267b54819 100644 +index 203afc03167acbcad15e836209956bc5ab151157..3badc43cbe1fcb6972829a6d5eb3143cfa812da9 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -14,6 +14,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o +@@ -13,10 +13,12 @@ snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-hifiberry-amp-objs := hifiberry_amp.o snd-soc-rpi-dac-objs := rpi-dac.o +snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -21,4 +22,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o @@ -129435,10 +114263,10 @@ index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed67 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From e31208717f0fc90e3e5d82e10408540c9272a69e Mon Sep 17 00:00:00 2001 +From 3eaf5ac6549cc9b659ae23f1b02960801ae2b2ca Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:03:47 +0100 -Subject: [PATCH 083/208] RaspiDAC3 support +Subject: [PATCH 076/111] RaspiDAC3 support Signed-off-by: Jan Grulich @@ -129456,10 +114284,10 @@ Signed-off-by: Matthias Reichl create mode 100644 sound/soc/bcm/raspidac3.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 5b08c4dfb71597d6f6381146c4ce79e57f551b9c..e07f8b74497fe3b271290cc4e6a1c49a2e84c29c 100644 +index ac0dbaf29b821c4b21855f22104a986f6e0849ec..c59c835757a51aa8ad72933d35a83b73a889477c 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -65,3 +65,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC +@@ -58,3 +58,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC select SND_SOC_PCM512x_I2C help Say Y or M if you want to add support for IQaudIO-DAC. @@ -129472,10 +114300,10 @@ index 5b08c4dfb71597d6f6381146c4ce79e57f551b9c..e07f8b74497fe3b271290cc4e6a1c49a + help + Say Y or M if you want to add support for RaspiDAC Rev.3x. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 680d1b6d5e16819094fbfaa6c42b458267b54819..18253b39addf831780fefe85578e72007c0d51d9 100644 +index 3badc43cbe1fcb6972829a6d5eb3143cfa812da9..07d2b52376b1d16e427cf6f51cbf4779d6219ce0 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -16,6 +16,7 @@ snd-soc-hifiberry-amp-objs := hifiberry_amp.o +@@ -15,6 +15,7 @@ snd-soc-hifiberry-digi-objs := hifiberry_digi.o snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o @@ -129483,7 +114311,7 @@ index 680d1b6d5e16819094fbfaa6c42b458267b54819..18253b39addf831780fefe85578e7200 obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o -@@ -24,3 +25,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -22,3 +23,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o @@ -129681,10 +114509,10 @@ index 0000000000000000000000000000000000000000..dd9eeea2af0382307f437e6db09d1546 +MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); +MODULE_LICENSE("GPL v2"); -From 0dbf63d7ac2e0f2ccb758b7641bb24d75fa3e99e Mon Sep 17 00:00:00 2001 +From a86f56673950aa0eafca22c4d2c393744d49032d Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Thu, 7 Apr 2016 21:26:21 +0100 -Subject: [PATCH 084/208] Add Support for JustBoom Audio boards +Subject: [PATCH 077/111] Add Support for JustBoom Audio boards justboom-dac: Adjust for ALSA API change @@ -129702,10 +114530,10 @@ Signed-off-by: Phil Elwell create mode 100644 sound/soc/bcm/justboom-digi.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index e07f8b74497fe3b271290cc4e6a1c49a2e84c29c..b8fcd82f1e9ccabaae307b07fa17bdec57c173a1 100644 +index c59c835757a51aa8ad72933d35a83b73a889477c..b2f6339c318cdfe3516d73952a5be1fd32bc1156 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -59,6 +59,20 @@ config SND_BCM2708_SOC_RPI_PROTO +@@ -52,6 +52,20 @@ config SND_BCM2708_SOC_RPI_PROTO help Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). @@ -129727,22 +114555,22 @@ index e07f8b74497fe3b271290cc4e6a1c49a2e84c29c..b8fcd82f1e9ccabaae307b07fa17bdec tristate "Support for IQaudIO-DAC" depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 18253b39addf831780fefe85578e72007c0d51d9..ddffe5d69f29878afb4f286abe69c2c787cf169e 100644 +index 07d2b52376b1d16e427cf6f51cbf4779d6219ce0..cb8ab1901b172bdee0bd9cddd2f2e7ab2f36c16a 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -13,6 +13,8 @@ snd-soc-hifiberry-dac-objs := hifiberry_dac.o +@@ -12,6 +12,8 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-hifiberry-amp-objs := hifiberry_amp.o +snd-soc-justboom-dac-objs := justboom-dac.o +snd-soc-justboom-digi-objs := justboom-digi.o snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o -@@ -22,6 +24,8 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +@@ -20,6 +22,8 @@ snd-soc-raspidac3-objs := raspidac3.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o @@ -130138,10 +114966,10 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); +MODULE_LICENSE("GPL v2"); -From 3c1739ef8bbd37c97af637e792f7dc604eb0dbac Mon Sep 17 00:00:00 2001 +From 14fbb06425bbc30d2d42de634942532006313b58 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 3 May 2016 22:10:59 -0400 -Subject: [PATCH 085/208] ARM: adau1977-adc: Add basic machine driver for +Subject: [PATCH 078/111] ARM: adau1977-adc: Add basic machine driver for adau1977 codec driver. This commit adds basic support for the codec usage including: Device tree overlay, @@ -130157,10 +114985,10 @@ Signed-off-by: Andrey Grodzovsky create mode 100644 sound/soc/bcm/adau1977-adc.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index b8fcd82f1e9ccabaae307b07fa17bdec57c173a1..cacc10431c5b82b000f5b71b1c1256f19073dc16 100644 +index b2f6339c318cdfe3516d73952a5be1fd32bc1156..190a79dffa53a34c2df9b2c9b5160065c759de65 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -87,3 +87,10 @@ config SND_BCM2708_SOC_RASPIDAC3 +@@ -80,3 +80,10 @@ config SND_BCM2708_SOC_RASPIDAC3 select SND_SOC_TPA6130A2 help Say Y or M if you want to add support for RaspiDAC Rev.3x. @@ -130172,7 +115000,7 @@ index b8fcd82f1e9ccabaae307b07fa17bdec57c173a1..cacc10431c5b82b000f5b71b1c1256f1 + help + Say Y or M if you want to add support for ADAU1977 ADC. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index ddffe5d69f29878afb4f286abe69c2c787cf169e..63584bc364ed266b8e9eb30afab0a631b97b145c 100644 +index cb8ab1901b172bdee0bd9cddd2f2e7ab2f36c16a..9dd0785532aae24f3366cc2910d4dbc558cb0e5d 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -9,6 +9,7 @@ snd-soc-cygnus-objs := cygnus-pcm.o cygnus-ssp.o @@ -130183,7 +115011,7 @@ index ddffe5d69f29878afb4f286abe69c2c787cf169e..63584bc364ed266b8e9eb30afab0a631 snd-soc-hifiberry-dac-objs := hifiberry_dac.o snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o -@@ -20,6 +21,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o +@@ -19,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o snd-soc-raspidac3-objs := raspidac3.o @@ -130323,10 +115151,10 @@ index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d +MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); +MODULE_LICENSE("GPL v2"); -From d653d98735f512ced56df4968813e513fd93afdb Mon Sep 17 00:00:00 2001 +From e1215eff5db9d0e68052f3a3e9f87c2d8f5bae1c Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 16 May 2016 21:36:31 +1000 -Subject: [PATCH 086/208] New AudioInjector.net Pi soundcard with low jitter +Subject: [PATCH 079/111] New AudioInjector.net Pi soundcard with low jitter audio in and out. Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile. @@ -130340,15 +115168,15 @@ This patch adds headphone and microphone capability to the Audio Injector sound --- sound/soc/bcm/Kconfig | 7 ++ sound/soc/bcm/Makefile | 3 + - sound/soc/bcm/audioinjector-pi-soundcard.c | 191 +++++++++++++++++++++++++++++ - 3 files changed, 201 insertions(+) + sound/soc/bcm/audioinjector-pi-soundcard.c | 193 +++++++++++++++++++++++++++++ + 3 files changed, 203 insertions(+) create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index cacc10431c5b82b000f5b71b1c1256f19073dc16..214aa1314ef97dff7422a4743024ddb4ae114912 100644 +index 190a79dffa53a34c2df9b2c9b5160065c759de65..eb16c3a7fb316eb5938a54dfa864f66f9b167eb0 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -94,3 +94,10 @@ config SND_BCM2708_SOC_ADAU1977_ADC +@@ -87,3 +87,10 @@ config SND_BCM2708_SOC_ADAU1977_ADC select SND_SOC_ADAU1977_I2C help Say Y or M if you want to add support for ADAU1977 ADC. @@ -130360,10 +115188,10 @@ index cacc10431c5b82b000f5b71b1c1256f19073dc16..214aa1314ef97dff7422a4743024ddb4 + help + Say Y or M if you want to add support for audioinjector.net Pi Hat diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 63584bc364ed266b8e9eb30afab0a631b97b145c..eb21e3baff008959ba41b5c816ecaff4462900ed 100644 +index 9dd0785532aae24f3366cc2910d4dbc558cb0e5d..a68469644535a38305bb5b0f3780e03e0ca4f519 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -20,6 +20,7 @@ snd-soc-rpi-dac-objs := rpi-dac.o +@@ -19,6 +19,7 @@ snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o snd-soc-raspidac3-objs := raspidac3.o @@ -130371,7 +115199,7 @@ index 63584bc364ed266b8e9eb30afab0a631b97b145c..eb21e3baff008959ba41b5c816ecaff4 obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -32,3 +33,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +@@ -30,3 +31,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o @@ -130379,10 +115207,10 @@ index 63584bc364ed266b8e9eb30afab0a631b97b145c..eb21e3baff008959ba41b5c816ecaff4 + diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c new file mode 100644 -index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7c68d9e99 +index 0000000000000000000000000000000000000000..ef54e0f07ea03f59e9957b5d98f3e7fdc998e469 --- /dev/null +++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -0,0 +1,191 @@ +@@ -0,0 +1,193 @@ +/* + * ASoC Driver for AudioInjector Pi add on soundcard + * @@ -130415,7 +115243,7 @@ index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7 +#include "../codecs/wm8731.h" + +static const unsigned int bcm2835_rates_12000000[] = { -+ 32000, 44100, 48000, 96000, 88200, ++ 8000, 16000, 32000, 44100, 48000, 96000, 88200, +}; + +static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { @@ -130440,19 +115268,21 @@ index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7 + + switch (params_rate(params)){ + case 8000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1); ++ case 16000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 750); + case 32000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 375); + case 44100: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 272); + case 48000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 250); + case 88200: + return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); + case 96000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); + default: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); + } +} + @@ -130575,10 +115405,10 @@ index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7 +MODULE_ALIAS("platform:audioinjector-pi-soundcard"); + -From 83acbad0b2688cd44fbb7293d219394a8ff4f435 Mon Sep 17 00:00:00 2001 +From 3abc67377cca7ff4e63ad2496a53a4454b9d1555 Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Thu, 30 Jun 2016 18:38:42 +0100 -Subject: [PATCH 087/208] Add IQAudIO Digi WM8804 board support +Subject: [PATCH 080/111] Add IQAudIO Digi WM8804 board support Support IQAudIO Digi board with iqaudio_digi machine driver and iqaudio-digi-wm8804-audio overlay. @@ -130595,10 +115425,10 @@ Signed-off-by: DigitalDreamtime create mode 100644 sound/soc/bcm/iqaudio_digi.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 214aa1314ef97dff7422a4743024ddb4ae114912..f85c6b1e8835e1a76bfa5be1bee69aaeec631a70 100644 +index eb16c3a7fb316eb5938a54dfa864f66f9b167eb0..9cba69ab877ef73beb2dff2f4f82d1d243f7c604 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -80,6 +80,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC +@@ -73,6 +73,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC help Say Y or M if you want to add support for IQaudIO-DAC. @@ -130613,10 +115443,10 @@ index 214aa1314ef97dff7422a4743024ddb4ae114912..f85c6b1e8835e1a76bfa5be1bee69aae tristate "Support for RaspiDAC Rev.3x" depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index eb21e3baff008959ba41b5c816ecaff4462900ed..0316dcaa3148dc60dfe9d10dabb6b4d0b0eea875 100644 +index a68469644535a38305bb5b0f3780e03e0ca4f519..fa2739206b79a9f9d2e1173b2099e1156e4e08c8 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -19,6 +19,7 @@ snd-soc-justboom-digi-objs := justboom-digi.o +@@ -18,6 +18,7 @@ snd-soc-justboom-digi-objs := justboom-digi.o snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o @@ -130624,7 +115454,7 @@ index eb21e3baff008959ba41b5c816ecaff4462900ed..0316dcaa3148dc60dfe9d10dabb6b4d0 snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o -@@ -32,6 +33,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o +@@ -30,6 +31,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o @@ -130878,10 +115708,10 @@ index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e78163196 +MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); +MODULE_LICENSE("GPL v2"); -From 6004b4aced007bc18f0bf6b2fe006cc23f537e5c Mon Sep 17 00:00:00 2001 +From 8d49dfc240c29fc3296d25559303f72a521f0141 Mon Sep 17 00:00:00 2001 From: escalator2015 Date: Tue, 24 May 2016 16:20:09 +0100 -Subject: [PATCH 088/208] New driver for RRA DigiDAC1 soundcard using WM8741 + +Subject: [PATCH 081/111] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 --- @@ -130892,10 +115722,10 @@ Subject: [PATCH 088/208] New driver for RRA DigiDAC1 soundcard using WM8741 + create mode 100644 sound/soc/bcm/digidac1-soundcard.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index f85c6b1e8835e1a76bfa5be1bee69aaeec631a70..04edcfdbb6ce5910a0704e6f1d1edd6fd97631e3 100644 +index 9cba69ab877ef73beb2dff2f4f82d1d243f7c604..2be5b64fb0d5dcad0d5747626015a6886c3c273b 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -108,3 +108,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD +@@ -101,3 +101,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD select SND_SOC_WM8731 help Say Y or M if you want to add support for audioinjector.net Pi Hat @@ -130908,10 +115738,10 @@ index f85c6b1e8835e1a76bfa5be1bee69aaeec631a70..04edcfdbb6ce5910a0704e6f1d1edd6f + help + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 0316dcaa3148dc60dfe9d10dabb6b4d0b0eea875..b407091a168af15062df7bc6410e48e3f92acd49 100644 +index fa2739206b79a9f9d2e1173b2099e1156e4e08c8..a5c30c0bdacafb2bd09b6ac2f8a3bdc6a85a8404 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -22,6 +22,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o +@@ -21,6 +21,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o snd-soc-iqaudio-digi-objs := iqaudio_digi.o snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o @@ -130919,7 +115749,7 @@ index 0316dcaa3148dc60dfe9d10dabb6b4d0b0eea875..b407091a168af15062df7bc6410e48e3 obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -36,4 +37,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +@@ -34,4 +35,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o @@ -131354,10 +116184,10 @@ index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0 +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); +MODULE_LICENSE("GPL v2"); -From c9186592a8d8b0de5f1b198d154819283b3ff954 Mon Sep 17 00:00:00 2001 +From 9a617cde3a19d6e794a531fc97056d3712acc6d0 Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Sat, 2 Jul 2016 16:26:19 +0100 -Subject: [PATCH 089/208] Add support for Dion Audio LOCO DAC-AMP HAT +Subject: [PATCH 082/111] Add support for Dion Audio LOCO DAC-AMP HAT Using dedicated machine driver and pcm5102a codec driver. @@ -131370,10 +116200,10 @@ Signed-off-by: DigitalDreamtime create mode 100644 sound/soc/bcm/dionaudio_loco.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 04edcfdbb6ce5910a0704e6f1d1edd6fd97631e3..7eafe2c62d716d490df87f9c6fd92bf3b9100124 100644 +index 2be5b64fb0d5dcad0d5747626015a6886c3c273b..b8cb5eb7af9b3e6d8d100926e04bfef629641d1d 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -116,3 +116,10 @@ config SND_DIGIDAC1_SOUNDCARD +@@ -109,3 +109,10 @@ config SND_DIGIDAC1_SOUNDCARD select SND_SOC_WM8741 help Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. @@ -131385,10 +116215,10 @@ index 04edcfdbb6ce5910a0704e6f1d1edd6fd97631e3..7eafe2c62d716d490df87f9c6fd92bf3 + help + Say Y or M if you want to add support for Dion Audio LOCO. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index b407091a168af15062df7bc6410e48e3f92acd49..2c233080c40938c38f11bed79304830fda851ae4 100644 +index a5c30c0bdacafb2bd09b6ac2f8a3bdc6a85a8404..28cdf019dbc7aafda194c83817d260ad1a477666 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -23,6 +23,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_digi.o +@@ -22,6 +22,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_digi.o snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o @@ -131396,7 +116226,7 @@ index b407091a168af15062df7bc6410e48e3f92acd49..2c233080c40938c38f11bed79304830f obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -38,4 +39,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o +@@ -36,4 +37,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o @@ -131530,10 +116360,10 @@ index 0000000000000000000000000000000000000000..89e65317512bc774453ac8d0d5b0ff98 +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); +MODULE_LICENSE("GPL v2"); -From 20d707ddfb3d107dc828e607f181cce0a71d37de Mon Sep 17 00:00:00 2001 +From 3dcce9c448e2c55b6613864b70a105c7194a6c04 Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Mon, 19 Sep 2016 14:01:04 +0100 -Subject: [PATCH 090/208] Allo Piano DAC boards: Initial 2 channel (stereo) +Subject: [PATCH 083/111] Allo Piano DAC boards: Initial 2 channel (stereo) support (#1645) Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards, @@ -131558,10 +116388,10 @@ Tested-by: Clive Messer create mode 100644 sound/soc/bcm/allo-piano-dac.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 7eafe2c62d716d490df87f9c6fd92bf3b9100124..4ccaba67a887432afe7f527569c4e2865925734b 100644 +index b8cb5eb7af9b3e6d8d100926e04bfef629641d1d..4f0330a6c06115f077938cba3dc744d4ae10f056 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -123,3 +123,10 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO +@@ -116,3 +116,10 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO select SND_SOC_PCM5102a help Say Y or M if you want to add support for Dion Audio LOCO. @@ -131573,10 +116403,10 @@ index 7eafe2c62d716d490df87f9c6fd92bf3b9100124..4ccaba67a887432afe7f527569c4e286 + help + Say Y or M if you want to add support for Allo Piano DAC. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 2c233080c40938c38f11bed79304830fda851ae4..b9f98f0bcf3ee0d6b490e1bb185ba0de8f0f9701 100644 +index 28cdf019dbc7aafda194c83817d260ad1a477666..4b94a42efecaee41df37f3c59fddefa5fe78521c 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -24,6 +24,7 @@ snd-soc-raspidac3-objs := raspidac3.o +@@ -23,6 +23,7 @@ snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o snd-soc-dionaudio-loco-objs := dionaudio_loco.o @@ -131584,7 +116414,7 @@ index 2c233080c40938c38f11bed79304830fda851ae4..b9f98f0bcf3ee0d6b490e1bb185ba0de obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -40,3 +41,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o +@@ -38,3 +39,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o @@ -131740,8755 +116570,45 @@ index 0000000000000000000000000000000000000000..8e8e62e5a36a279b425ed4655cfbac99 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC"); +MODULE_LICENSE("GPL v2"); -From 957b05e2d651db6c7da732440955cb6e3e87155f Mon Sep 17 00:00:00 2001 -From: P33M -Date: Wed, 21 Oct 2015 14:55:21 +0100 -Subject: [PATCH 091/208] rpi_display: add backlight driver and overlay +From 6e56deb3cec1e3680db7ca2e00d3566fc981c194 Mon Sep 17 00:00:00 2001 +From: gtrainavicius +Date: Sun, 23 Oct 2016 12:06:53 +0300 +Subject: [PATCH 084/111] Support for Blokas Labs pisound board -Add a mailbox-driven backlight controller for the Raspberry Pi DSI -touchscreen display. Requires updated GPU firmware to recognise the -mailbox request. +Pisound dynamic overlay (#1760) -Signed-off-by: Gordon Hollingworth +Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay. + +Print a logline when the kernel module is removed. --- - drivers/video/backlight/Kconfig | 6 ++ - drivers/video/backlight/Makefile | 1 + - drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ - 3 files changed, 126 insertions(+) - create mode 100644 drivers/video/backlight/rpi_backlight.c - -diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig -index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 ---- a/drivers/video/backlight/Kconfig -+++ b/drivers/video/backlight/Kconfig -@@ -265,6 +265,12 @@ config BACKLIGHT_PWM - If you have a LCD backlight adjustable by PWM, say Y to enable - this driver. - -+config BACKLIGHT_RPI -+ tristate "Raspberry Pi display firmware driven backlight" -+ help -+ If you have the Raspberry Pi DSI touchscreen display, say Y to -+ enable the mailbox-controlled backlight driver. -+ - config BACKLIGHT_DA903X - tristate "Backlight Driver for DA9030/DA9034 using WLED" - depends on PMIC_DA903X -diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile -index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 ---- a/drivers/video/backlight/Makefile -+++ b/drivers/video/backlight/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o - obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o - obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o - obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o -+obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o - obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o - obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o - obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o -diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c -new file mode 100644 -index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad ---- /dev/null -+++ b/drivers/video/backlight/rpi_backlight.c -@@ -0,0 +1,119 @@ -+/* -+ * rpi_bl.c - Backlight controller through VPU -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct rpi_backlight { -+ struct device *dev; -+ struct device *fbdev; -+ struct rpi_firmware *fw; -+}; -+ -+static int rpi_backlight_update_status(struct backlight_device *bl) -+{ -+ struct rpi_backlight *gbl = bl_get_data(bl); -+ int brightness = bl->props.brightness; -+ int ret; -+ -+ if (bl->props.power != FB_BLANK_UNBLANK || -+ bl->props.fb_blank != FB_BLANK_UNBLANK || -+ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) -+ brightness = 0; -+ -+ ret = rpi_firmware_property(gbl->fw, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, -+ &brightness, sizeof(brightness)); -+ if (ret) { -+ dev_err(gbl->dev, "Failed to set brightness\n"); -+ return ret; -+ } -+ -+ if (brightness < 0) { -+ dev_err(gbl->dev, "Backlight change failed\n"); -+ return -EAGAIN; -+ } -+ -+ return 0; -+} -+ -+static const struct backlight_ops rpi_backlight_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .update_status = rpi_backlight_update_status, -+}; -+ -+static int rpi_backlight_probe(struct platform_device *pdev) -+{ -+ struct backlight_properties props; -+ struct backlight_device *bl; -+ struct rpi_backlight *gbl; -+ struct device_node *fw_node; -+ -+ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); -+ if (gbl == NULL) -+ return -ENOMEM; -+ -+ gbl->dev = &pdev->dev; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ gbl->fw = rpi_firmware_get(fw_node); -+ if (!gbl->fw) -+ return -EPROBE_DEFER; -+ -+ memset(&props, 0, sizeof(props)); -+ props.type = BACKLIGHT_RAW; -+ props.max_brightness = 255; -+ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), -+ &pdev->dev, gbl, &rpi_backlight_ops, -+ &props); -+ if (IS_ERR(bl)) { -+ dev_err(&pdev->dev, "failed to register backlight\n"); -+ return PTR_ERR(bl); -+ } -+ -+ bl->props.brightness = 255; -+ backlight_update_status(bl); -+ -+ platform_set_drvdata(pdev, bl); -+ return 0; -+} -+ -+static const struct of_device_id rpi_backlight_of_match[] = { -+ { .compatible = "raspberrypi,rpi-backlight" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); -+ -+static struct platform_driver rpi_backlight_driver = { -+ .driver = { -+ .name = "rpi-backlight", -+ .of_match_table = of_match_ptr(rpi_backlight_of_match), -+ }, -+ .probe = rpi_backlight_probe, -+}; -+ -+module_platform_driver(rpi_backlight_driver); -+ -+MODULE_AUTHOR("Gordon Hollingworth "); -+MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); -+MODULE_LICENSE("GPL"); - -From 20d35ff154f56e330bb4a3781721e271edecc54f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 23 Feb 2016 19:56:04 +0000 -Subject: [PATCH 092/208] bcm2835-virtgpio: Virtual GPIO driver - -Add a virtual GPIO driver that uses the firmware mailbox interface to -request that the VPU toggles LEDs. ---- - drivers/gpio/Kconfig | 6 ++ - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-bcm-virt.c | 179 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 186 insertions(+) - create mode 100644 drivers/gpio/gpio-bcm-virt.c - -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index 24caedb00a7a34f141bced4062f07a8d72439a63..343adff44f82b78d0a09d41518a2890c602fc83d 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -144,6 +144,12 @@ config GPIO_BCM_KONA - help - Turn on GPIO support for Broadcom "Kona" chips. - -+config GPIO_BCM_VIRT -+ bool "Broadcom Virt GPIO" -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) -+ help -+ Turn on virtual GPIO support for Broadcom BCM283X chips. -+ - config GPIO_BRCMSTB - tristate "BRCMSTB GPIO support" - default y if (ARCH_BRCMSTB || BMIPS_GENERIC) -diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index 2a035ed8f168196ec7596d303685b439b2c2938e..e6ccf796193b93a9e3d9bb190316c6a152f5eb9f 100644 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o - obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o - obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o -+obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o - obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o - obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o - obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o -diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c -new file mode 100644 -index 0000000000000000000000000000000000000000..f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4 ---- /dev/null -+++ b/drivers/gpio/gpio-bcm-virt.c -@@ -0,0 +1,179 @@ -+/* -+ * brcmvirt GPIO driver -+ * -+ * Copyright (C) 2012,2013 Dom Cobley -+ * Based on gpio-clps711x.c by Alexander Shiyan -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define MODULE_NAME "brcmvirt-gpio" -+#define NUM_GPIO 2 -+ -+struct brcmvirt_gpio { -+ struct gpio_chip gc; -+ u32 __iomem *ts_base; -+ /* two packed 16-bit counts of enabled and disables -+ Allows host to detect a brief enable that was missed */ -+ u32 enables_disables[NUM_GPIO]; -+}; -+ -+static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return -EINVAL; -+} -+ -+static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return 0; -+} -+ -+static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ unsigned v; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ v = readl(gpio->ts_base + off); -+ return (v >> off) & 1; -+} -+ -+static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ u16 enables, disables; -+ s16 diff; -+ bool lit; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ enables = gpio->enables_disables[off] >> 16; -+ disables = gpio->enables_disables[off] >> 0; -+ diff = (s16)(enables - disables); -+ lit = diff > 0; -+ if ((val && lit) || (!val && !lit)) -+ return; -+ if (val) -+ enables++; -+ else -+ disables++; -+ diff = (s16)(enables - disables); -+ BUG_ON(diff != 0 && diff != 1); -+ gpio->enables_disables[off] = (enables << 16) | (disables << 0); -+ writel(gpio->enables_disables[off], gpio->ts_base + off); -+} -+ -+static int brcmvirt_gpio_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ struct brcmvirt_gpio *ucb; -+ u32 gpiovirtbuf; -+ int err = 0; -+ -+ fw_node = of_parse_phandle(np, "firmware", 0); -+ if (!fw_node) { -+ dev_err(dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ fw = rpi_firmware_get(fw_node); -+ if (!fw) -+ return -EPROBE_DEFER; -+ -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, -+ &gpiovirtbuf, sizeof(gpiovirtbuf)); -+ -+ if (err) { -+ dev_err(dev, "Failed to get gpiovirtbuf\n"); -+ goto err; -+ } -+ -+ if (!gpiovirtbuf) { -+ dev_err(dev, "No virtgpio buffer\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); -+ if (!ucb) { -+ err = -EINVAL; -+ goto err; -+ } -+ -+ // mmap the physical memory -+ gpiovirtbuf &= ~0xc0000000; -+ ucb->ts_base = ioremap(gpiovirtbuf, 4096); -+ if (ucb->ts_base == NULL) { -+ dev_err(dev, "Failed to map physical address\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb->gc.label = MODULE_NAME; -+ ucb->gc.owner = THIS_MODULE; -+ //ucb->gc.dev = dev; -+ ucb->gc.of_node = np; -+ ucb->gc.base = 100; -+ ucb->gc.ngpio = NUM_GPIO; -+ -+ ucb->gc.direction_input = brcmvirt_gpio_dir_in; -+ ucb->gc.direction_output = brcmvirt_gpio_dir_out; -+ ucb->gc.get = brcmvirt_gpio_get; -+ ucb->gc.set = brcmvirt_gpio_set; -+ ucb->gc.can_sleep = true; -+ -+ err = gpiochip_add(&ucb->gc); -+ if (err) -+ goto err; -+ -+ platform_set_drvdata(pdev, ucb); -+ -+err: -+ return err; -+ -+} -+ -+static int brcmvirt_gpio_remove(struct platform_device *pdev) -+{ -+ int err = 0; -+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); -+ -+ gpiochip_remove(&ucb->gc); -+ iounmap(ucb->ts_base); -+ return err; -+} -+ -+static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { -+ { .compatible = "brcm,bcm2835-virtgpio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); -+ -+static struct platform_driver brcmvirt_gpio_driver = { -+ .driver = { -+ .name = MODULE_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), -+ }, -+ .probe = brcmvirt_gpio_probe, -+ .remove = brcmvirt_gpio_remove, -+}; -+module_platform_driver(brcmvirt_gpio_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dom Cobley "); -+MODULE_DESCRIPTION("brcmvirt GPIO driver"); -+MODULE_ALIAS("platform:brcmvirt-gpio"); - -From ff297e81b17d7bc931554a8246fe3eae8e6f47ef Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 4 Mar 2016 12:49:09 +0000 -Subject: [PATCH 093/208] DRM_VC4: Allow to be built for ARCH_BCM270x - ---- - drivers/gpu/drm/vc4/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index e53df59cb139f25f8e6ae916bca93abf0c49e063..f6e938208b73512f20eab46a383ca91bf675a845 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -1,6 +1,6 @@ - config DRM_VC4 - tristate "Broadcom VC4 Graphics" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - depends on DRM - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER - -From 50174cb70458ba4c0c70e88d3cd21defdd156bbb Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 23 Feb 2016 17:26:48 +0000 -Subject: [PATCH 094/208] amba_pl011: Don't use DT aliases for numbering - -The pl011 driver looks for DT aliases of the form "serial", -and if found uses as the device ID. This can cause -/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the -other serial port is provided by the 8250 driver which doesn't -use the same logic. ---- - drivers/tty/serial/amba-pl011.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 8a9e213387a79fcc335caad27520a68edf03f446..4a5a1c5cf9b345e255f4d79714a7ae461728fce0 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2414,7 +2414,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, - if (IS_ERR(base)) - return PTR_ERR(base); - -+ /* Don't use DT serial aliases - it causes the device to -+ be renumbered to ttyAMA1 if it is the second serial port in the -+ system, even though the other one is ttyS0. The 8250 driver -+ doesn't use this logic, so always remains ttyS0. - index = pl011_probe_dt_alias(index, dev); -+ */ - - uap->old_cr = 0; - uap->port.dev = dev; - -From 6a254068480d6ce7cc2ed93742c5412a8e46cda8 Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -Date: Wed, 3 Dec 2014 13:23:28 +0200 -Subject: [PATCH 095/208] OF: DT-Overlay configfs interface - -This is a port of Pantelis Antoniou's v3 port that makes use of the -new upstreamed configfs support for binary attributes. - -Original commit message: - -Add a runtime interface to using configfs for generic device tree overlay -usage. With it its possible to use device tree overlays without having -to use a per-platform overlay manager. - -Please see Documentation/devicetree/configfs-overlays.txt for more info. - -Changes since v2: -- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) -- Created a documentation entry -- Slight rewording in Kconfig - -Changes since v1: -- of_resolve() -> of_resolve_phandles(). - -Originally-signed-off-by: Pantelis Antoniou -Signed-off-by: Phil Elwell - -DT configfs: Fix build errors on other platforms - -Signed-off-by: Phil Elwell - -DT configfs: fix build error - -There is an error when compiling rpi-4.6.y branch: - CC drivers/of/configfs.o -drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] - .default_groups = of_cfs_def_groups, - ^ -drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') - -The .default_groups is linked list since commit -1ae1602de028acaa42a0f6ff18d19756f8e825c6. -This commit uses configfs_add_default_group to fix this problem. - -Signed-off-by: Slawomir Stepien ---- - Documentation/devicetree/configfs-overlays.txt | 31 +++ - drivers/of/Kconfig | 7 + - drivers/of/Makefile | 1 + - drivers/of/configfs.c | 311 +++++++++++++++++++++++++ - 4 files changed, 350 insertions(+) - create mode 100644 Documentation/devicetree/configfs-overlays.txt - create mode 100644 drivers/of/configfs.c - -diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt -new file mode 100644 -index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad ---- /dev/null -+++ b/Documentation/devicetree/configfs-overlays.txt -@@ -0,0 +1,31 @@ -+Howto use the configfs overlay interface. -+ -+A device-tree configfs entry is created in /config/device-tree/overlays -+and and it is manipulated using standard file system I/O. -+Note that this is a debug level interface, for use by developers and -+not necessarily something accessed by normal users due to the -+security implications of having direct access to the kernel's device tree. -+ -+* To create an overlay you mkdir the directory: -+ -+ # mkdir /config/device-tree/overlays/foo -+ -+* Either you echo the overlay firmware file to the path property file. -+ -+ # echo foo.dtbo >/config/device-tree/overlays/foo/path -+ -+* Or you cat the contents of the overlay to the dtbo file -+ -+ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo -+ -+The overlay file will be applied, and devices will be created/destroyed -+as required. -+ -+To remove it simply rmdir the directory. -+ -+ # rmdir /config/device-tree/overlays/foo -+ -+The rationalle of the dual interface (firmware & direct copy) is that each is -+better suited to different use patterns. The firmware interface is what's -+intended to be used by hardware managers in the kernel, while the copy interface -+make sense for developers (since it avoids problems with namespaces). -diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig -index bc07ad30c9bfa91fe0fcb0b544f2f07412a26680..f0fa9639d98a99bf7ac209f5b62283ed56a102f7 100644 ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -116,4 +116,11 @@ config OF_OVERLAY - config OF_NUMA - bool - -+config OF_CONFIGFS -+ bool "Device Tree Overlay ConfigFS interface" -+ select CONFIGFS_FS -+ select OF_OVERLAY -+ help -+ Enable a simple user-space driven DT overlay interface. -+ - endif # OF -diff --git a/drivers/of/Makefile b/drivers/of/Makefile -index d7efd9d458aab4554139e93c72a1688aa0eeef6a..aa5ef9dd1fedc14d4ae2d363818fc160df51bad9 100644 ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,4 +1,5 @@ - obj-y = base.o device.o platform.o -+obj-$(CONFIG_OF_CONFIGFS) += configfs.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o - obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o -diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c -new file mode 100644 -index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b6ea6cad7 ---- /dev/null -+++ b/drivers/of/configfs.c -@@ -0,0 +1,311 @@ -+/* -+ * Configfs entries for device-tree -+ * -+ * Copyright (C) 2013 - Pantelis Antoniou -+ * -+ * 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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "of_private.h" -+ -+struct cfs_overlay_item { -+ struct config_item item; -+ -+ char path[PATH_MAX]; -+ -+ const struct firmware *fw; -+ struct device_node *overlay; -+ int ov_id; -+ -+ void *dtbo; -+ int dtbo_size; -+}; -+ -+static int create_overlay(struct cfs_overlay_item *overlay, void *blob) -+{ -+ int err; -+ -+ /* unflatten the tree */ -+ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); -+ if (overlay->overlay == NULL) { -+ pr_err("%s: failed to unflatten tree\n", __func__); -+ err = -EINVAL; -+ goto out_err; -+ } -+ pr_debug("%s: unflattened OK\n", __func__); -+ -+ /* mark it as detached */ -+ of_node_set_flag(overlay->overlay, OF_DETACHED); -+ -+ /* perform resolution */ -+ err = of_resolve_phandles(overlay->overlay); -+ if (err != 0) { -+ pr_err("%s: Failed to resolve tree\n", __func__); -+ goto out_err; -+ } -+ pr_debug("%s: resolved OK\n", __func__); -+ -+ err = of_overlay_create(overlay->overlay); -+ if (err < 0) { -+ pr_err("%s: Failed to create overlay (err=%d)\n", -+ __func__, err); -+ goto out_err; -+ } -+ overlay->ov_id = err; -+ -+out_err: -+ return err; -+} -+ -+static inline struct cfs_overlay_item *to_cfs_overlay_item( -+ struct config_item *item) -+{ -+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; -+} -+ -+static ssize_t cfs_overlay_item_path_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ return sprintf(page, "%s\n", overlay->path); -+} -+ -+static ssize_t cfs_overlay_item_path_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ const char *p = page; -+ char *s; -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy to path buffer (and make sure it's always zero terminated */ -+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); -+ overlay->path[sizeof(overlay->path) - 1] = '\0'; -+ -+ /* strip trailing newlines */ -+ s = overlay->path + strlen(overlay->path); -+ while (s > overlay->path && *--s == '\n') -+ *s = '\0'; -+ -+ pr_debug("%s: path is '%s'\n", __func__, overlay->path); -+ -+ err = request_firmware(&overlay->fw, overlay->path, NULL); -+ if (err != 0) -+ goto out_err; -+ -+ err = create_overlay(overlay, (void *)overlay->fw->data); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ -+ release_firmware(overlay->fw); -+ overlay->fw = NULL; -+ -+ overlay->path[0] = '\0'; -+ return err; -+} -+ -+static ssize_t cfs_overlay_item_status_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ return sprintf(page, "%s\n", -+ overlay->ov_id >= 0 ? "applied" : "unapplied"); -+} -+ -+CONFIGFS_ATTR(cfs_overlay_item_, path); -+CONFIGFS_ATTR_RO(cfs_overlay_item_, status); -+ -+static struct configfs_attribute *cfs_overlay_attrs[] = { -+ &cfs_overlay_item_attr_path, -+ &cfs_overlay_item_attr_status, -+ NULL, -+}; -+ -+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, -+ void *buf, size_t max_count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ pr_debug("%s: buf=%p max_count=%zu\n", __func__, -+ buf, max_count); -+ -+ if (overlay->dtbo == NULL) -+ return 0; -+ -+ /* copy if buffer provided */ -+ if (buf != NULL) { -+ /* the buffer must be large enough */ -+ if (overlay->dtbo_size > max_count) -+ return -ENOSPC; -+ -+ memcpy(buf, overlay->dtbo, overlay->dtbo_size); -+ } -+ -+ return overlay->dtbo_size; -+} -+ -+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, -+ const void *buf, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy the contents */ -+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); -+ if (overlay->dtbo == NULL) -+ return -ENOMEM; -+ -+ overlay->dtbo_size = count; -+ -+ err = create_overlay(overlay, overlay->dtbo); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ -+ return err; -+} -+ -+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); -+ -+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { -+ &cfs_overlay_item_attr_dtbo, -+ NULL, -+}; -+ -+static void cfs_overlay_release(struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ if (overlay->ov_id >= 0) -+ of_overlay_destroy(overlay->ov_id); -+ if (overlay->fw) -+ release_firmware(overlay->fw); -+ /* kfree with NULL is safe */ -+ kfree(overlay->dtbo); -+ kfree(overlay); -+} -+ -+static struct configfs_item_operations cfs_overlay_item_ops = { -+ .release = cfs_overlay_release, -+}; -+ -+static struct config_item_type cfs_overlay_type = { -+ .ct_item_ops = &cfs_overlay_item_ops, -+ .ct_attrs = cfs_overlay_attrs, -+ .ct_bin_attrs = cfs_overlay_bin_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *cfs_overlay_group_make_item( -+ struct config_group *group, const char *name) -+{ -+ struct cfs_overlay_item *overlay; -+ -+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); -+ if (!overlay) -+ return ERR_PTR(-ENOMEM); -+ overlay->ov_id = -1; -+ -+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); -+ return &overlay->item; -+} -+ -+static void cfs_overlay_group_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ config_item_put(&overlay->item); -+} -+ -+static struct configfs_group_operations overlays_ops = { -+ .make_item = cfs_overlay_group_make_item, -+ .drop_item = cfs_overlay_group_drop_item, -+}; -+ -+static struct config_item_type overlays_type = { -+ .ct_group_ops = &overlays_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_group_operations of_cfs_ops = { -+ /* empty - we don't allow anything to be created */ -+}; -+ -+static struct config_item_type of_cfs_type = { -+ .ct_group_ops = &of_cfs_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group of_cfs_overlay_group; -+ -+static struct configfs_subsystem of_cfs_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "device-tree", -+ .ci_type = &of_cfs_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), -+}; -+ -+static int __init of_cfs_init(void) -+{ -+ int ret; -+ -+ pr_info("%s\n", __func__); -+ -+ config_group_init(&of_cfs_subsys.su_group); -+ config_group_init_type_name(&of_cfs_overlay_group, "overlays", -+ &overlays_type); -+ configfs_add_default_group(&of_cfs_overlay_group, -+ &of_cfs_subsys.su_group); -+ -+ ret = configfs_register_subsystem(&of_cfs_subsys); -+ if (ret != 0) { -+ pr_err("%s: failed to register subsys\n", __func__); -+ goto out; -+ } -+ pr_info("%s: OK\n", __func__); -+out: -+ return ret; -+} -+late_initcall(of_cfs_init); - -From 1fddcd40ba81c10c6895d5f7450648d22f4ff015 Mon Sep 17 00:00:00 2001 -From: Cheong2K -Date: Fri, 26 Feb 2016 18:20:10 +0800 -Subject: [PATCH 096/208] brcm: adds support for BCM43341 wifi - ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ - drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -index 68ab3ac156500864fbe27187311541986334ff3a..a008d3c264730e1611ce817b5a4a788b872c886c 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -603,6 +603,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); -+BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); -@@ -620,6 +621,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), -+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), -diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -index 3cc42bef6245529c37320f0ec6ab5e7b77f1d2f6..2ae9d0c9dbaaab6bc16610ac012039cd04886ada 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -@@ -35,6 +35,7 @@ - #define BRCM_CC_4330_CHIP_ID 0x4330 - #define BRCM_CC_4334_CHIP_ID 0x4334 - #define BRCM_CC_43340_CHIP_ID 43340 -+#define BRCM_CC_43341_CHIP_ID 43341 - #define BRCM_CC_43362_CHIP_ID 43362 - #define BRCM_CC_4335_CHIP_ID 0x4335 - #define BRCM_CC_4339_CHIP_ID 0x4339 - -From 4c93f16ed441b2c3ef4a6e4bbaf4da65d3947109 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 9 Mar 2016 17:25:59 +0000 -Subject: [PATCH 097/208] brcmfmac: Disable power management - -Disable wireless power saving in the brcmfmac WLAN driver. This is a -temporary measure until the connectivity loss resulting from power -saving is resolved. - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index abaf003a5b396f94e891c6569217ffbb595987e1..f6221c20ff8e2c07a9ddb329204cc59ce574117b 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2762,6 +2762,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, - * preference in cfg struct to apply this to - * FW later while initializing the dongle - */ -+ pr_info("power management disabled\n"); -+ enabled = false; - cfg->pwr_save = enabled; - if (!check_vif_up(ifp->vif)) { - - -From 27a452d3be16848428312107b1281a3a1a3d3752 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 Apr 2016 17:13:47 +0100 -Subject: [PATCH 098/208] brcmfmac: Use original country code as a fallback - -Commit 73345fd212980d2e28a5c6d83801c903bd773680: - - brcmfmac: Configure country code using device specific settings - -prevents region codes from working on devices that lack a region code -translation table. In the event of an absent table, preserve the old -behaviour of using the provided code as-is. - -Signed-off-by: Phil Elwell ---- - .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 20 +++++++++++++++----- - 1 file changed, 15 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index f6221c20ff8e2c07a9ddb329204cc59ce574117b..12bffe239e9d28ce8f73db48b3f5759ffe550162 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6740,12 +6740,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - struct brcmfmac_pd_cc *country_codes; - struct brcmfmac_pd_cc_entry *cc; - s32 found_index; -+ char ccode[BRCMF_COUNTRY_BUF_SZ]; -+ int rev; - int i; - -+ memcpy(ccode, alpha2, sizeof(ccode)); -+ rev = -1; -+ - country_codes = drvr->settings->country_codes; - if (!country_codes) { -- brcmf_dbg(TRACE, "No country codes configured for device\n"); -- return -EINVAL; -+ brcmf_dbg(TRACE, "No country codes configured for device" -+ " - use requested value\n"); -+ goto use_input_value; - } - - if ((alpha2[0] == ccreq->country_abbrev[0]) && -@@ -6769,10 +6775,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - brcmf_dbg(TRACE, "No country code match found\n"); - return -EINVAL; - } -- memset(ccreq, 0, sizeof(*ccreq)); -- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); -- memcpy(ccreq->ccode, country_codes->table[found_index].cc, -+ rev = country_codes->table[found_index].rev; -+ memcpy(ccode, country_codes->table[found_index].cc, - BRCMF_COUNTRY_BUF_SZ); -+ -+use_input_value: -+ memset(ccreq, 0, sizeof(*ccreq)); -+ ccreq->rev = cpu_to_le32(rev); -+ memcpy(ccreq->ccode, ccode, sizeof(ccode)); - ccreq->country_abbrev[0] = alpha2[0]; - ccreq->country_abbrev[1] = alpha2[1]; - ccreq->country_abbrev[2] = 0; - -From fb426eaf2b6cb5e4383d36f1b00c74afbed85c7b Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 13 Sep 2016 16:32:37 +0100 -Subject: [PATCH 099/208] brcmfmac: do not use internal roaming engine by - default - -Some evidence of curing disconnects with this disabled, so make it a default. -Can be overridden with module parameter roamoff=0 -See: http://projectable.me/optimize-my-pi-wi-fi/ ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -index 3e15d64c64813513bc22202dd9e468588699abb0..4051780f64f44a5ce522babe6c371a1beb79a824 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -@@ -69,7 +69,7 @@ static int brcmf_fcmode; - module_param_named(fcmode, brcmf_fcmode, int, 0); - MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); - --static int brcmf_roamoff; -+static int brcmf_roamoff = 1; - module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); - MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); - - -From 0b42c7b72a05fa0261c707571f0328fba44c8a9e Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 31 Aug 2016 17:10:09 +0100 -Subject: [PATCH 100/208] brcmfmac: Change stop_ap sequence - -Patch from Broadcom/Cypress to resolve a customer error - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index 12bffe239e9d28ce8f73db48b3f5759ffe550162..0c3cecb22763db2db5ccbc1789f50b2b361e4a9c 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -4750,12 +4750,15 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); - if (err < 0) - brcmf_err("BRCMF_C_DOWN error %d\n", err); -- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); -- if (err < 0) -- brcmf_err("setting AP mode failed %d\n", err); -+ - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); - if (err < 0) - brcmf_err("setting INFRA mode failed %d\n", err); -+ -+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); -+ if (err < 0) -+ brcmf_err("setting AP mode failed %d\n", err); -+ - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) - brcmf_fil_iovar_int_set(ifp, "mbss", 0); - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, - -From bae20097877011eea7b2342eee23788a14ceb380 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 17 Dec 2015 13:37:07 +0000 -Subject: [PATCH 101/208] hci_h5: Don't send conf_req when ACTIVE - -Without this patch, a modem and kernel can continuously bombard each -other with conf_req and conf_rsp messages, in a demented game of tag. ---- - drivers/bluetooth/hci_h5.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c -index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 ---- a/drivers/bluetooth/hci_h5.c -+++ b/drivers/bluetooth/hci_h5.c -@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) - h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_req, 2) == 0) { - h5_link_control(hu, conf_rsp, 2); -- h5_link_control(hu, conf_req, 3); -+ if (h5->state != H5_ACTIVE) -+ h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_rsp, 2) == 0) { - if (H5_HDR_LEN(hdr) > 2) - h5->tx_win = (data[2] & 0x07); - -From aa0a8cb875b64118fee48e451ea59561e3b18b1e Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 25 Jan 2016 13:03:33 -0800 -Subject: [PATCH 102/208] drm/vc4: Include vc4_drm.h in uapi in downstream - build. - -Signed-off-by: Eric Anholt ---- - include/uapi/drm/Kbuild | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild -index 9355dd8eff3ba39401dfe37e7fbf7737f0397f11..68828bf586f05a8d9b0a6ab409ee91a700e3d296 100644 ---- a/include/uapi/drm/Kbuild -+++ b/include/uapi/drm/Kbuild -@@ -15,6 +15,7 @@ header-y += radeon_drm.h - header-y += savage_drm.h - header-y += sis_drm.h - header-y += tegra_drm.h -+header-y += vc4_drm.h - header-y += via_drm.h - header-y += vmwgfx_drm.h - header-y += msm_drm.h - -From e6971437077eda153890c78e3428cd883499d7b2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 103/208] config: Add default configs - ---- - arch/arm/configs/bcm2709_defconfig | 1294 +++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1303 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 2597 insertions(+) - create mode 100644 arch/arm/configs/bcm2709_defconfig - create mode 100644 arch/arm/configs/bcmrpi_defconfig - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..dfbb3406e38b50bf38db84071f82c3a556da8057 ---- /dev/null -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1294 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_PHYS_OFFSET=0 -+CONFIG_LOCALVERSION="-v7" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2709=y -+# CONFIG_CACHE_L2X0 is not set -+CONFIG_SMP=y -+CONFIG_HAVE_ARM_ARCH_TIMER=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_IPVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=m -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VCIO=y -+CONFIG_BCM_VC_SM=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_BCM_VIRT=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=m -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+# CONFIG_CRYPTO_HW is not set -+CONFIG_ARM_CRYPTO=y -+CONFIG_CRYPTO_SHA1_ARM_NEON=m -+CONFIG_CRYPTO_AES_ARM_BS=m -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..cfe21355f7d95326b292be1b018b988fa3ffe865 ---- /dev/null -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1303 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_PHYS_OFFSET=0 -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2708=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_VFP=y -+CONFIG_BINFMT_MISC=m -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_IPVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=m -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VCIO=y -+CONFIG_BCM_VC_SM=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=m -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_DWC2=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_USB_GADGET=m -+CONFIG_USB_ZERO=m -+CONFIG_USB_AUDIO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_GADGETFS=m -+CONFIG_USB_MASS_STORAGE=m -+CONFIG_USB_G_SERIAL=m -+CONFIG_USB_MIDI_GADGET=m -+CONFIG_USB_G_PRINTER=m -+CONFIG_USB_CDC_COMPOSITE=m -+CONFIG_USB_G_ACM_MS=m -+CONFIG_USB_G_MULTI=m -+CONFIG_USB_G_HID=m -+CONFIG_USB_G_WEBCAM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_LATENCYTOP=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CRYPTD=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_SHA512=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+# CONFIG_CRYPTO_HW is not set -+CONFIG_ARM_CRYPTO=y -+CONFIG_CRYPTO_SHA1_ARM=m -+CONFIG_CRYPTO_AES_ARM=m -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y - -From fba149883c98450421b61cac552394f43efbfda2 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Wed, 24 Aug 2016 03:35:56 -0700 -Subject: [PATCH 104/208] Add arm64 configuration and device tree differences. - Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing - at the moment. - ---- - arch/arm64/Kconfig.platforms | 22 + - arch/arm64/boot/dts/broadcom/Makefile | 1 + - arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts | 3 + - arch/arm64/configs/bcmrpi3_defconfig | 1330 ++++++++++++++++++++++ - 4 files changed, 1356 insertions(+) - create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts - create mode 100644 arch/arm64/configs/bcmrpi3_defconfig - -diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index be5d824ebdba2dab24840bb7808abcc40da2053e..fee7af52fe1a9f8d49447a93df0017832e06c5d3 100644 ---- a/arch/arm64/Kconfig.platforms -+++ b/arch/arm64/Kconfig.platforms -@@ -1,5 +1,27 @@ - menu "Platform selection" - -+config MACH_BCM2709 -+ bool -+ -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ select MACH_BCM2709 -+ select HAVE_SMP -+ select ARM_AMBA -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select MULTI_IRQ_HANDLER -+ select SPARSE_IRQ -+ select MFD_SYSCON -+ select VC4 -+ select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - config ARCH_SUNXI - bool "Allwinner sunxi 64-bit SoC Family" - select GENERIC_IRQ_CHIP -diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index 05faf2a8a35ca5ba9049b9038dedb9be88eeb7c5..2152448c8cf5b22c573642d7ce45e85793f5fc9a 100644 ---- a/arch/arm64/boot/dts/broadcom/Makefile -+++ b/arch/arm64/boot/dts/broadcom/Makefile -@@ -1,6 +1,7 @@ - dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb - dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb - - always := $(dtb-y) - subdir-y := $(dts-dirs) -diff --git a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..deb33441da95220db0ed672e41639626fba682a5 ---- /dev/null -+++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts -@@ -0,0 +1,3 @@ -+#define RPI364 -+ -+#include "../../../../arm/boot/dts/bcm2710-rpi-3-b.dts" -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..1fcde8c1329bbfd329245a8bb17691999882ccfc ---- /dev/null -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -0,0 +1,1330 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_PHYS_OFFSET=0 -+CONFIG_LOCALVERSION="-v8" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_64BIT=y -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+ -+# -+# ARM errata workarounds via the alternatives framework -+# -+CONFIG_ARM64_ERRATUM_826319=n -+CONFIG_ARM64_ERRATUM_827319=n -+CONFIG_ARM64_ERRATUM_824069=n -+CONFIG_ARM64_ERRATUM_819472=n -+CONFIG_ARM64_ERRATUM_832075=n -+CONFIG_ARM64_ERRATUM_845719=n -+CONFIG_ARM64_ERRATUM_843419=n -+CONFIG_CAVIUM_ERRATUM_22375=n -+CONFIG_CAVIUM_ERRATUM_23154=n -+CONFIG_CAVIUM_ERRATUM_27456=n -+CONFIG_ARM64_4K_PAGES=y -+CONFIG_ARM64_VA_BITS_39=y -+CONFIG_ARM64_VA_BITS=39 -+CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=4 -+CONFIG_HOTPLUG_CPU=y -+ -+# -+# ARMv8.1 architectural features -+# -+CONFIG_ARM64_HW_AFDBM=n -+CONFIG_ARM64_PAN=n -+CONFIG_ARM64_LSE_ATOMICS=n -+CONFIG_ARM64_VHE=n -+ -+# -+# ARMv8.2 architectural features -+# -+CONFIG_ARM64_UAO=n -+CONFIG_ARM64_MODULE_CMODEL_LARGE=n -+CONFIG_RANDOMIZE_BASE=n -+ -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_TRIM_UNUSED_KSYMS=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2709=y -+# CONFIG_CACHE_L2X0 is not set -+CONFIG_SMP=y -+CONFIG_HAVE_ARM_ARCH_TIMER=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+CONFIG_COMPAT=y -+CONFIG_SYSVIPC_COMPAT=y -+ -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_IPVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=n -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=n -+CONFIG_BCM_VC_CMA=n -+CONFIG_BCM_VCIO=n -+CONFIG_BCM_VC_SM=n -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_BCM_VIRT=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=m -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=n -+CONFIG_VIDEO_BCM2835_MMAL=n -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_ARM=n -+CONFIG_SND_BCM2835=n -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=n -+CONFIG_USB_DWC2=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+CONFIG_ARM64_CRYPTO=y -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y -+CONFIG_BCM2708_VCHIQ=n - -From 54f507bf54343e3d66964683f676cbfef1beed5f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 5 Oct 2016 16:10:59 +0100 -Subject: [PATCH 105/208] bcm2835-cpufreq: Only report a single frequency when - max and min frequencies are the same - -4.8 kernel gives EINV error when max and min frequencies are the same (e.g. from using force_turbo=1) ---- - drivers/cpufreq/bcm2835-cpufreq.c | 27 ++++++++++++++++----------- - 1 file changed, 16 insertions(+), 11 deletions(-) - -diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c -index 3eb9e9326231b08e6ee95ad486485245c71cf868..414fbdc10dfbfc6e4bb47870a7af3fd5780f9c9a 100644 ---- a/drivers/cpufreq/bcm2835-cpufreq.c -+++ b/drivers/cpufreq/bcm2835-cpufreq.c -@@ -45,12 +45,8 @@ - - /* ---------- GLOBALS ---------- */ - static struct cpufreq_driver bcm2835_cpufreq_driver; /* the cpufreq driver global */ -- --static struct cpufreq_frequency_table bcm2835_freq_table[] = { -- {0, 0, 0}, -- {0, 0, 0}, -- {0, 0, CPUFREQ_TABLE_END}, --}; -+static unsigned int min_frequency, max_frequency; -+static struct cpufreq_frequency_table bcm2835_freq_table[3]; - - /* - =============================================== -@@ -155,10 +151,19 @@ static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy) - } - - /* now find out what the maximum and minimum frequencies are */ -- bcm2835_freq_table[0].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); -- bcm2835_freq_table[1].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); -+ min_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); -+ max_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); -+ -+ if (min_frequency == max_frequency) { -+ bcm2835_freq_table[0].frequency = min_frequency; -+ bcm2835_freq_table[1].frequency = CPUFREQ_TABLE_END; -+ } else { -+ bcm2835_freq_table[0].frequency = min_frequency; -+ bcm2835_freq_table[1].frequency = max_frequency; -+ bcm2835_freq_table[2].frequency = CPUFREQ_TABLE_END; -+ } - -- print_info("min=%d max=%d\n", bcm2835_freq_table[0].frequency, bcm2835_freq_table[1].frequency); -+ print_info("min=%d max=%d\n", min_frequency, max_frequency); - return cpufreq_generic_init(policy, bcm2835_freq_table, transition_latency); - } - -@@ -170,7 +175,7 @@ static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy) - - static int bcm2835_cpufreq_driver_target_index(struct cpufreq_policy *policy, unsigned int state) - { -- unsigned int target_freq = bcm2835_freq_table[state].frequency; -+ unsigned int target_freq = state == 0 ? min_frequency : max_frequency; - unsigned int cur = bcm2835_cpufreq_set_clock(policy->cur, target_freq); - - if (!cur) -@@ -192,7 +197,7 @@ static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu) - { - unsigned int actual_rate = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_CLOCK_RATE); - print_debug("cpu%d: freq=%d\n", cpu, actual_rate); -- return actual_rate <= bcm2835_freq_table[0].frequency ? bcm2835_freq_table[0].frequency : bcm2835_freq_table[1].frequency; -+ return actual_rate <= min_frequency ? min_frequency : max_frequency; - } - - /* the CPUFreq driver */ - -From 4896a5fdcc6c95ae207070fe78e3aad60e597ce3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 7 Oct 2016 12:37:09 +0100 -Subject: [PATCH 106/208] scripts/mkknlimg: Change string for DDT detection - -The old "of_overlay_apply" string does not appear in 4.8 kernel builds. -"of_cfs_init" is both present and a more accurate indication of support -for dynamically loading overlays (although the trailer is now of little -practical use and the firmware assumes DT support and will look for -both .dtbo and -overlay.dtb overlays). - -Signed-off-by: Phil Elwell ---- - scripts/mkknlimg | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -index 78c5845d2f01deb04b477327d83fa60624f87f98..a21f7e31bc904233e980e66ae3e6337e2eab0f1c 100755 ---- a/scripts/mkknlimg -+++ b/scripts/mkknlimg -@@ -77,7 +77,7 @@ my $wanted_strings = - 'brcm,bcm2709' => FLAG_PI | FLAG_DTOK | FLAG_270X, - 'brcm,bcm2835' => FLAG_PI | FLAG_DTOK | FLAG_283X, - 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, -- 'of_overlay_apply' => FLAG_DTOK | FLAG_DDTK, -+ 'of_cfs_init' => FLAG_DTOK | FLAG_DDTK, - }; - - my $res = try_extract($kernel_file, $tmpfile1); - -From dc56c6cc7558f783449f7ff3943aa7698d9a2144 Mon Sep 17 00:00:00 2001 -From: Herve Jourdain -Date: Fri, 20 May 2016 16:02:23 +0800 -Subject: [PATCH 107/208] build: support for .dtbo files for dtb overlays - -Kernel 4.4.6+ on RaspberryPi support .dtbo files for overlays, instead of .dtb. -Patch the kernel, which has faulty rules to generate .dtbo the way yocto does - -Signed-off-by: Herve Jourdain -Signed-off-by: Khem Raj ---- - arch/arm/Makefile | 2 ++ - scripts/Makefile.lib | 5 +++-- - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index d1e45094ab4338f95dab09e81d358cd723f5eb3d..275c53561cd7c3b1f52a60c95b5fb287fb3ccb62 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -337,6 +337,8 @@ $(INSTALL_TARGETS): - - %.dtb: | scripts - $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ -+%.dtbo: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ - - PHONY += dtbs dtbs_install - -diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index 1d949b7410600dd3b04a3acde8c41cfead15bfa4..1967878a843461c3ff1f473b9a030eb01b7c726e 100644 ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -313,8 +313,9 @@ $(obj)/%.dtb: $(src)/%.dts FORCE - $(call if_changed_dep,dtc) - - quiet_cmd_dtco = DTCO $@ --cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -- $(objtree)/scripts/dtc/dtc -@ -H epapr -O dtb -o $@ -b 0 \ -+cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \ -+ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -+ $(DTC) -@ -H epapr -O dtb -o $@ -b 0 \ - -i $(dir $<) $(DTC_FLAGS) \ - -d $(depfile).dtc.tmp $(dtc-tmp) ; \ - cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) - -From e8fc35c718297a56d13a92eb51d984ba28e5916e Mon Sep 17 00:00:00 2001 -From: Khem Raj -Date: Thu, 6 Oct 2016 19:42:55 -0700 -Subject: [PATCH 108/208] [media]bcm2835-camera: fix compilation warning/werror - -| /a/builder/mnt/build/tmp-glibc/work-shared/raspberrypi3/kernel-source/drivers/media/platform/bcm2835/bcm2835-camera.c:656:17: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types -] -| .queue_setup = queue_setup, -| ^~~~~~~~~~~ -| /a/builder/mnt/build/tmp-glibc/work-shared/raspberrypi3/kernel-source/drivers/media/platform/bcm2835/bcm28 -35-camera.c:656:17: note: (near initialization for 'bm2835_mmal_video_qops.queue_setup') - -use struct device* instead of void* - -Signed-off-by: Khem Raj ---- - drivers/media/platform/bcm2835/bcm2835-camera.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index 70f4db2741037381e638d1dda5a95478809eb161..cb5bab642eaab2f60d641801dd0afdac45b7698f 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -244,7 +244,7 @@ static struct mmal_fmt *get_format(struct v4l2_format *f) - - static int queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, -- unsigned int sizes[], void *alloc_ctxs[]) -+ unsigned int sizes[], struct device *alloc_ctxs[]) - { - struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); - unsigned long size; - -From 6c91352d35ed41686937484e2777a8af6652d2a3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 8 Oct 2016 16:26:46 +0200 -Subject: [PATCH 109/208] bcm2709: Drop platform smp and timer init code -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -irq-bcm2836 handles this through these functions: -bcm2835_init_local_timer_frequency() -bcm2836_arm_irqchip_smp_init() - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2709/bcm2709.c | 126 ---------------------------------------- - 1 file changed, 126 deletions(-) - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 90773a30b87abbfda1615326c6faf59b9db6d68e..d4c9d57d78a964fbbf799b534471462d3c3b88f1 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -208,19 +208,6 @@ void __init bcm2709_init(void) - system_serial_low = serial; - } - --static void __init bcm2709_timer_init(void) --{ -- // timer control -- writel(0, __io_address(ARM_LOCAL_CONTROL)); -- // timer pre_scaler -- writel(0x80000000, __io_address(ARM_LOCAL_PRESCALER)); // 19.2MHz -- //writel(0x06AAAAAB, __io_address(ARM_LOCAL_PRESCALER)); // 1MHz -- -- of_clk_init(NULL); -- clocksource_probe(); --} -- -- - void __init bcm2709_init_early(void) - { - /* -@@ -236,111 +223,6 @@ static void __init board_reserve(void) - vc_cma_reserve(); - } - -- --#ifdef CONFIG_SMP --#include -- --#include --#include --int dc4=0; --//void dc4_log(unsigned x) { if (dc4) writel((x), __io_address(ST_BASE+10 + raw_smp_processor_id()*4)); } --void dc4_log_dead(unsigned x) { if (dc4) writel((readl(__io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)) & 0xffff) | ((x)<<16), __io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)); } -- --static void bcm2835_send_doorbell(const struct cpumask *mask, unsigned int irq) --{ -- int cpu; -- /* -- * Ensure that stores to Normal memory are visible to the -- * other CPUs before issuing the IPI. -- */ -- dsb(); -- -- /* Convert our logical CPU mask into a physical one. */ -- for_each_cpu(cpu, mask) -- { -- /* submit softirq */ -- writel(1<%x)\n", __FUNCTION__, (unsigned)virt_to_phys((void *)secondary_startup), (unsigned)__io_address(ST_BASE + 0x10)); -- printk("[%s] ncores=%d\n", __FUNCTION__, ncores); -- -- for (i = 0; i < ncores; i++) { -- set_cpu_possible(i, true); -- /* enable IRQ (not FIQ) */ -- writel(0x1, __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 0x4 * i)); -- //writel(0xf, __io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 0x4 * i)); -- } -- set_smp_cross_call(bcm2835_send_doorbell); --} -- --/* -- * for arch/arm/kernel/smp.c:smp_prepare_cpus(unsigned int max_cpus) -- */ --void __init bcm2709_smp_prepare_cpus(unsigned int max_cpus) --{ -- //void __iomem *scu_base; -- -- printk("[%s] enter\n", __FUNCTION__); -- //scu_base = scu_base_addr(); -- //scu_enable(scu_base); --} -- --/* -- * for linux/arch/arm/kernel/smp.c:secondary_start_kernel(void) -- */ --void __init bcm2709_secondary_init(unsigned int cpu) --{ -- printk("[%s] enter cpu:%d\n", __FUNCTION__, cpu); -- //gic_secondary_init(0); --} -- --/* -- * for linux/arch/arm/kernel/smp.c:__cpu_up(..) -- */ --int __init bcm2709_boot_secondary(unsigned int cpu, struct task_struct *idle) --{ -- void secondary_startup(void); -- void *mbox_set = __io_address(ARM_LOCAL_MAILBOX3_SET0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -- void *mbox_clr = __io_address(ARM_LOCAL_MAILBOX3_CLR0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -- unsigned secondary_boot = (unsigned)virt_to_phys((void *)secondary_startup); -- int timeout=20; -- unsigned t = -1; -- //printk("[%s] enter cpu:%d (%x->%p) %x\n", __FUNCTION__, cpu, secondary_boot, wake, readl(wake)); -- -- dsb(); -- BUG_ON(readl(mbox_clr) != 0); -- writel(secondary_boot, mbox_set); -- -- while (--timeout > 0) { -- t = readl(mbox_clr); -- if (t == 0) break; -- cpu_relax(); -- } -- if (timeout==0) -- printk("[%s] cpu:%d failed to start (%x)\n", __FUNCTION__, cpu, t); -- else -- printk("[%s] cpu:%d started (%x) %d\n", __FUNCTION__, cpu, t, timeout); -- -- return 0; --} -- -- --struct smp_operations bcm2709_smp_ops __initdata = { -- .smp_init_cpus = bcm2709_smp_init_cpus, -- .smp_prepare_cpus = bcm2709_smp_prepare_cpus, -- .smp_secondary_init = bcm2709_secondary_init, -- .smp_boot_secondary = bcm2709_boot_secondary, --}; --#endif -- - static const char * const bcm2709_compat[] = { - "brcm,bcm2709", - "brcm,bcm2708", /* Could use bcm2708 in a pinch */ -@@ -349,11 +231,7 @@ static const char * const bcm2709_compat[] = { - - MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ --#ifdef CONFIG_SMP -- .smp = smp_ops(bcm2709_smp_ops), --#endif - .map_io = bcm2709_map_io, -- .init_time = bcm2709_timer_init, - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, -@@ -363,11 +241,7 @@ MACHINE_END - - MACHINE_START(BCM2708, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ --#ifdef CONFIG_SMP -- .smp = smp_ops(bcm2709_smp_ops), --#endif - .map_io = bcm2709_map_io, -- .init_time = bcm2709_timer_init, - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, - -From b9634bc3431cbe7aa5157750ab5943024019a99f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 3 Oct 2016 17:53:15 +0200 -Subject: [PATCH 110/208] BCM270X_DT: Use bcm283x.dtsi, bcm2835.dtsi and - bcm2836.dtsi -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The mainline Device Tree files are quite close to downstream now. -Let's use bcm283x.dtsi, bcm2835.dtsi and bcm2836.dtsi as base files -for our dts files. - -Mainline dts files are based on these files: - - bcm2835-rpi.dtsi - bcm2835.dtsi bcm2836.dtsi - bcm283x.dtsi - -Current downstream are based on these: - - bcm2708.dtsi bcm2709.dtsi bcm2710.dtsi - bcm2708_common.dtsi - -This patch introduces this dependency: - - bcm2708.dtsi bcm2709.dtsi - bcm2708-rpi.dtsi - bcm270x.dtsi - bcm2835.dtsi bcm2836.dtsi - bcm283x.dtsi - -And: - bcm2710.dtsi - bcm2708-rpi.dtsi - bcm270x.dtsi - bcm283x.dtsi - -bcm270x.dtsi contains the downstream bcm283x.dtsi diff. -bcm2708-rpi.dtsi is the downstream version of bcm2835-rpi.dtsi. - -Other changes: -- The led node has moved from /soc/leds to /leds. This is not a problem - since the label is used to reference it. -- The clk_osc reg property changes from 6 to 3. -- The gpu nodes has their interrupt property set in the base file. -- the clocks label does not point to the /clocks node anymore, but - points to the cprman node. This is not a problem since the overlays - that use the clock node refer to it directly: target-path = "/clocks"; -- some nodes now have 2 labels since mainline and downstream differs in - this respect: cprman/clocks, spi0/spi, gpu/vc4. -- some nodes doesn't have an explicit status = "okay" since they're not - disabled in the base file: watchdog and random. -- gpiomem doesn't need an explicit status = "okay". -- bcm2708-rpi-cm.dts got the hpd-gpios property from bcm2708_common.dtsi, - it's now set directly in that file. -- bcm2709-rpi-2-b.dts has the timer node moved from /soc/timer to /timer. -- Removed clock-frequency property on the bcm{2709,2710}.dtsi timer nodes. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 5 - - arch/arm/boot/dts/bcm2708-rpi-b.dts | 5 - - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 5 +- - arch/arm/boot/dts/bcm2708-rpi.dtsi | 105 ++++++++ - arch/arm/boot/dts/bcm2708.dtsi | 28 +- - arch/arm/boot/dts/bcm2708_common.dtsi | 436 ------------------------------- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 5 - - arch/arm/boot/dts/bcm2709.dtsi | 90 +------ - arch/arm/boot/dts/bcm270x.dtsi | 142 ++++++++++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 5 - - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 5 - - arch/arm/boot/dts/bcm2710.dtsi | 28 +- - 12 files changed, 272 insertions(+), 587 deletions(-) - mode change 100755 => 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dts - create mode 100644 arch/arm/boot/dts/bcm2708-rpi.dtsi - delete mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi - create mode 100644 arch/arm/boot/dts/bcm270x.dtsi - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 6c16c325cd2887a42c42665273834618c1937918..6bd8df44dc9163589074c1dec8a3ec69a47fb458 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -98,15 +98,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 7c132437671d43e76445a4bf1184cc9a316b0965..ba80832726004b1b0719f570a7d8b3a390344d56 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -98,15 +98,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -old mode 100755 -new mode 100644 -index ce9f54ff7e4ce76ad25ad0a19cf2ad48ba9df01a..eb8662f0d222b4c0a9a2bcb8bccb13e86a0006b3 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -81,13 +81,12 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; -+&hdmi { -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; - }; - - / { -diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..d85c05901c8f55f822b89c32d198f15559a2b4b0 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi -@@ -0,0 +1,105 @@ -+/* Downstream version of bcm2835-rpi.dtsi */ -+ -+#include -+ -+/ { -+ memory { -+ device_type = "memory"; -+ reg = <0x0 0x0>; -+ }; -+ -+ aliases { -+ audio = &audio; -+ aux = &aux; -+ sound = &sound; -+ soc = &soc; -+ dma = &dma; -+ intc = &intc; -+ watchdog = &watchdog; -+ random = &random; -+ mailbox = &mailbox; -+ gpio = &gpio; -+ uart0 = &uart0; -+ sdhost = &sdhost; -+ i2s = &i2s; -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ uart1 = &uart1; -+ spi1 = &spi1; -+ spi2 = &spi2; -+ mmc = &mmc; -+ i2c1 = &i2c1; -+ i2c2 = &i2c2; -+ usb = &usb; -+ leds = &leds; -+ fb = &fb; -+ vchiq = &vchiq; -+ thermal = &thermal; -+ }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ }; -+ -+ soc { -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ }; -+ -+ firmware: firmware { -+ compatible = "raspberrypi,bcm2835-firmware"; -+ mboxes = <&mailbox>; -+ }; -+ -+ power: power { -+ compatible = "raspberrypi,bcm2835-power"; -+ firmware = <&firmware>; -+ #power-domain-cells = <1>; -+ }; -+ -+ fb: fb { -+ compatible = "brcm,bcm2708-fb"; -+ firmware = <&firmware>; -+ status = "disabled"; -+ }; -+ -+ vchiq: vchiq { -+ compatible = "brcm,bcm2835-vchiq"; -+ reg = <0x7e00b840 0xf>; -+ interrupts = <0 2>; -+ cache-line-size = <32>; -+ firmware = <&firmware>; -+ }; -+ -+ thermal: thermal { -+ compatible = "brcm,bcm2835-thermal"; -+ firmware = <&firmware>; -+ }; -+ -+ /* Onboard audio */ -+ audio: audio { -+ compatible = "brcm,bcm2835-audio"; -+ brcm,pwm-channels = <8>; -+ status = "disabled"; -+ }; -+ -+ /* External sound card */ -+ sound: sound { -+ status = "disabled"; -+ }; -+ -+ }; -+ -+ __overrides__ { -+ cache_line_size = <&vchiq>, "cache-line-size:0"; -+ }; -+}; -+ -+&dma { -+ brcm,dma-channel-mask = <0x7f34>; -+}; -+ -+&hdmi { -+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>; -+}; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index f5a44cd4fef0ee221ed6ae1c43ca81dabffa110d..1bd2a707ef5c0d92f233296e6312916f5a550bd2 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -1,16 +1,14 @@ --#include "bcm2708_common.dtsi" -+#include "bcm2835.dtsi" -+#include "bcm270x.dtsi" -+#include "bcm2708-rpi.dtsi" - - / { + .../devicetree/bindings/vendor-prefixes.txt | 1 + + arch/arm/boot/dts/overlays/pisound-overlay.dts | 94 +- + sound/soc/bcm/Kconfig | 6 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/pisound.c | 989 +++++++++++++++++++++ + 5 files changed, 1048 insertions(+), 44 deletions(-) + create mode 100644 sound/soc/bcm/pisound.c + +diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt +index f0a48ea78659c933839554ca879babb1b621b264..779c19033acad30ed8fd71f015ee76caef1a0568 100644 +--- a/Documentation/devicetree/bindings/vendor-prefixes.txt ++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt +@@ -40,6 +40,7 @@ auvidea Auvidea GmbH + avago Avago Technologies + avic Shanghai AVIC Optoelectronics Co., Ltd. + axis Axis Communications AB ++blokaslabs Vilniaus Blokas UAB + boe BOE Technology Group Co., Ltd. + bosch Bosch Sensortec GmbH + boundary Boundary Devices Inc. +diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts +index 7cdfc29ba4fbffd3216376677922e7ae26019055..5197e656a3d741d14bd9dd6c812b4b93be1419a2 100644 +--- a/arch/arm/boot/dts/overlays/pisound-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts +@@ -26,6 +26,54 @@ compatible = "brcm,bcm2708"; - model = "BCM2708"; -- chosen { -- /* No padding required - the boot loader can do that. */ -- bootargs = ""; -- }; -- - soc { - ranges = <0x7e000000 0x20000000 0x01000000>; -+ /delete-property/ dma-ranges; - - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; -@@ -18,23 +16,7 @@ - interrupts = <1 0>, <1 1>, <1 2>, <1 3>; - clock-frequency = <1000000>; - }; -- -- arm-pmu { -- compatible = "arm,arm1176-pmu"; -- }; -- -- gpiomem { -- compatible = "brcm,bcm2835-gpiomem"; -- reg = <0x7e200000 0x1000>; -- status = "okay"; -- }; - }; --}; -- --&intc { -- compatible = "brcm,bcm2835-armctrl-ic"; --}; - --&watchdog { -- status = "okay"; -+ /delete-node/ cpus; - }; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -deleted file mode 100644 -index 6081b2aeb7ab1e1821506bcb93d36de13b5717ef..0000000000000000000000000000000000000000 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ /dev/null -@@ -1,436 +0,0 @@ --#include "dt-bindings/clock/bcm2835.h" --#include --#include "dt-bindings/power/raspberrypi-power.h" --#include "dt-bindings/gpio/gpio.h" --#include "skeleton.dtsi" -- --/ { -- interrupt-parent = <&intc>; -- -- aliases { -- audio = &audio; -- aux = &aux; -- sound = &sound; -- soc = &soc; -- dma = &dma; -- intc = &intc; -- watchdog = &watchdog; -- random = &random; -- mailbox = &mailbox; -- gpio = &gpio; -- uart0 = &uart0; -- sdhost = &sdhost; -- i2s = &i2s; -- spi0 = &spi0; -- i2c0 = &i2c0; -- uart1 = &uart1; -- spi1 = &spi1; -- spi2 = &spi2; -- mmc = &mmc; -- i2c1 = &i2c1; -- i2c2 = &i2c2; -- usb = &usb; -- leds = &leds; -- fb = &fb; -- vchiq = &vchiq; -- thermal = &thermal; -- clocks = &clocks; -- }; -- -- soc: soc { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <1>; -- -- dma: dma@7e007000 { -- compatible = "brcm,bcm2835-dma"; -- reg = <0x7e007000 0xf00>; -- interrupts = <1 16>, -- <1 17>, -- <1 18>, -- <1 19>, -- <1 20>, -- <1 21>, -- <1 22>, -- <1 23>, -- <1 24>, -- <1 25>, -- <1 26>, -- /* dma channel 11-14 share one irq */ -- <1 27>, -- <1 27>, -- <1 27>, -- <1 27>, -- /* unused shared irq for all channels */ -- <1 28>; -- interrupt-names = "dma0", -- "dma1", -- "dma2", -- "dma3", -- "dma4", -- "dma5", -- "dma6", -- "dma7", -- "dma8", -- "dma9", -- "dma10", -- "dma11", -- "dma12", -- "dma13", -- "dma14", -- "dma-shared-all"; -- -- #dma-cells = <1>; -- brcm,dma-channel-mask = <0x7f34>; -- }; -- -- intc: interrupt-controller@7e00b200 { --#ifdef RPI364 -- compatible = "brcm,bcm2835-armctrl-ic", "brcm,bcm2708-armctrl-ic"; --#else -- compatible = "brcm,bcm2708-armctrl-ic"; --#endif -- reg = <0x7e00b200 0x200>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- mailbox: mailbox@7e00b800 { -- compatible = "brcm,bcm2835-mbox"; -- reg = <0x7e00b880 0x40>; -- interrupts = <0 1>; -- #mbox-cells = <0>; -- }; -- -- watchdog: watchdog@7e100000 { -- compatible = "brcm,bcm2835-pm-wdt"; -- reg = <0x7e100000 0x28>; -- status = "disabled"; -- }; -- -- cprman: cprman@7e101000 { -- compatible = "brcm,bcm2835-cprman"; -- #clock-cells = <1>; -- reg = <0x7e101000 0x2000>; -- -- /* CPRMAN derives everything from the platform's -- * oscillator. -- */ -- clocks = <&clk_osc>; -- }; -- -- random: rng@7e104000 { -- compatible = "brcm,bcm2835-rng"; -- reg = <0x7e104000 0x10>; -- status = "disabled"; -- }; -- -- gpio: gpio@7e200000 { -- compatible = "brcm,bcm2835-gpio"; -- reg = <0x7e200000 0xb4>; -- interrupts = <2 17>, <2 18>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- uart0: serial@7e201000 { -- compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; -- reg = <0x7e201000 0x1000>; -- interrupts = <2 25>; -- clocks = <&cprman BCM2835_CLOCK_UART>, -- <&cprman BCM2835_CLOCK_VPU>; -- clock-names = "uartclk","apb_pclk"; -- arm,primecell-periphid = <0x00241011>; // For an explanation, see -- // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 -- status = "disabled"; -- }; -- -- sdhost: sdhost@7e202000 { -- compatible = "brcm,bcm2835-sdhost"; -- reg = <0x7e202000 0x100>; -- interrupts = <2 24>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- dmas = <&dma 13>; -- dma-names = "rx-tx"; -- brcm,overclock-50 = <0>; -- brcm,pio-limit = <1>; -- status = "disabled"; -- }; -- -- i2s: i2s@7e203000 { -- compatible = "brcm,bcm2835-i2s"; -- #sound-dai-cells = <0>; -- reg = <0x7e203000 0x24>; -- clocks = <&cprman BCM2835_CLOCK_PCM>; -- -- dmas = <&dma 2>, <&dma 3>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- spi0: spi@7e204000 { -- compatible = "brcm,bcm2835-spi"; -- reg = <0x7e204000 0x1000>; -- interrupts = <2 22>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- /* the dma channels */ -- dmas = <&dma 6>, <&dma 7>; -- dma-names = "tx", "rx"; -- /* the chipselects used - <0> means native GPIO -- * add more gpios if necessary as <&gpio 6 1> -- * (but do not forget to make them output!) -- */ -- cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -- }; -- -- i2c0: i2c@7e205000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e205000 0x1000>; -- interrupts = <2 21>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- pixelvalve0: pixelvalve@7e206000 { -- compatible = "brcm,bcm2835-pixelvalve0"; -- reg = <0x7e206000 0x100>; -- status = "disabled"; -- }; -- -- dpi: dpi@7e208000 { -- compatible = "brcm,bcm2835-dpi"; -- reg = <0x7e208000 0x8c>; -- clocks = <&cprman BCM2835_CLOCK_VPU>, -- <&cprman BCM2835_CLOCK_DPI>; -- clock-names = "core", "pixel"; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- pixelvalve1: pixelvalve@7e207000 { -- compatible = "brcm,bcm2835-pixelvalve1"; -- reg = <0x7e207000 0x100>; -- status = "disabled"; -- }; -- -- pwm: pwm@7e20c000 { -- compatible = "brcm,bcm2835-pwm"; -- reg = <0x7e20c000 0x28>; -- clocks = <&cprman BCM2835_CLOCK_PWM>; -- assigned-clocks = <&cprman BCM2835_CLOCK_PWM>; -- assigned-clock-rates = <10000000>; -- #pwm-cells = <2>; -- status = "disabled"; -- }; -- -- aux: aux@0x7e215000 { -- compatible = "brcm,bcm2835-aux"; -- #clock-cells = <1>; -- reg = <0x7e215000 0x8>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- }; -- -- uart1: serial@7e215040 { -- compatible = "brcm,bcm2835-aux-uart"; -- reg = <0x7e215040 0x40>; -- interrupts = <1 29>; -- clocks = <&aux BCM2835_AUX_CLOCK_UART>; -- status = "disabled"; -- }; -- -- spi1: spi@7e215080 { -- compatible = "brcm,bcm2835-aux-spi"; -- reg = <0x7e215080 0x40>; -- interrupts = <1 29>; -- clocks = <&aux BCM2835_AUX_CLOCK_SPI1>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- spi2: spi@7e2150C0 { -- compatible = "brcm,bcm2835-aux-spi"; -- reg = <0x7e2150C0 0x40>; -- interrupts = <1 29>; -- clocks = <&aux BCM2835_AUX_CLOCK_SPI2>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- mmc: mmc@7e300000 { -- compatible = "brcm,bcm2835-mmc"; -- reg = <0x7e300000 0x100>; -- interrupts = <2 30>; -- clocks = <&cprman BCM2835_CLOCK_EMMC>; -- dmas = <&dma 11>; -- dma-names = "rx-tx"; -- brcm,overclock-50 = <0>; -- status = "disabled"; -- }; -- -- hvs: hvs@7e400000 { -- compatible = "brcm,bcm2835-hvs"; -- reg = <0x7e400000 0x6000>; -- status = "disabled"; -- }; -- -- i2c1: i2c@7e804000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e804000 0x1000>; -- interrupts = <2 21>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c2: i2c@7e805000 { -- // Beware - this is shared with the HDMI module. -- // Careless use may break (really) your display. -- // Caveat emptor. -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e805000 0x1000>; -- interrupts = <2 21>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- smi: smi@7e600000 { -- compatible = "brcm,bcm2835-smi"; -- reg = <0x7e600000 0x100>; -- interrupts = <2 16>; -- clocks = <&cprman BCM2835_CLOCK_SMI>; -- assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; -- assigned-clock-rates = <125000000>; -- dmas = <&dma 4>; -- dma-names = "rx-tx"; -- status = "disabled"; -- }; -- -- pixelvalve2: pixelvalve@7e807000 { -- compatible = "brcm,bcm2835-pixelvalve2"; -- reg = <0x7e807000 0x100>; -- status = "disabled"; -- }; -- -- hdmi: hdmi@7e902000 { -- compatible = "brcm,bcm2835-hdmi"; -- reg = <0x7e902000 0x600>, -- <0x7e808000 0x100>; -- ddc = <&i2c2>; -- hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; -- clocks = <&cprman BCM2835_PLLH_PIX>, -- <&cprman BCM2835_CLOCK_HSM>; -- clock-names = "pixel", "hdmi"; -- power-domains = <&power RPI_POWER_DOMAIN_HDMI>; -- status = "disabled"; -- }; -- --#ifdef RPI364 -- usb: usb@7e980000 { -- compatible = "brcm,bcm2835-usb"; -- reg = <0x7e980000 0x10000>; -- interrupts = <1 9>; -- #address-cells = <1>; -- #size-cells = <0>; -- }; --#else -- usb: usb@7e980000 { -- compatible = "brcm,bcm2708-usb"; -- reg = <0x7e980000 0x10000>, -- <0x7e006000 0x1000>; -- interrupts = <2 0>, -- <1 9>; -- }; --#endif -- -- v3d: v3d@7ec00000 { -- compatible = "brcm,vc4-v3d"; -- reg = <0x7ec00000 0x1000>; -- status = "disabled"; -- }; -- -- firmware: firmware { -- compatible = "raspberrypi,bcm2835-firmware"; -- mboxes = <&mailbox>; -- }; -- -- power: power { -- compatible = "raspberrypi,bcm2835-power"; -- firmware = <&firmware>; -- #power-domain-cells = <1>; -- }; -- -- leds: leds { -- compatible = "gpio-leds"; -- }; -- -- fb: fb { -- compatible = "brcm,bcm2708-fb"; -- firmware = <&firmware>; -- status = "disabled"; -- }; -- -- vchiq: vchiq { -- compatible = "brcm,bcm2835-vchiq"; -- reg = <0x7e00b840 0xf>; -- interrupts = <0 2>; -- cache-line-size = <32>; -- firmware = <&firmware>; -- }; -- -- thermal: thermal { -- compatible = "brcm,bcm2835-thermal"; -- firmware = <&firmware>; -- }; -- -- gpu: gpu { -- compatible = "brcm,bcm2835-vc4"; -- status = "disabled"; -- }; -- -- /* Onboard audio */ -- audio: audio { -- compatible = "brcm,bcm2835-audio"; -- brcm,pwm-channels = <8>; -- status = "disabled"; -- }; -- -- /* External sound card */ -- sound: sound { -- status = "disabled"; -- }; -- }; -- -- clocks: clocks { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- /* The oscillator is the root of the clock tree. */ -- clk_osc: clock@6 { -- compatible = "fixed-clock"; -- reg = <6>; -- #clock-cells = <0>; -- clock-output-names = "osc"; -- clock-frequency = <19200000>; -- }; -- }; -- -- __overrides__ { -- cache_line_size = <&vchiq>, "cache-line-size:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 74fe4cc1d667e9508ca860bcc8c837fed0cbb855..4f79aaae149abc6f8ebc076d493eb8459e469862 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -98,15 +98,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index a8cfd7c4df5bcf7692d13882833c97852649932d..757d0053c1c07452babc63ca6ecd0a8f047b25dd 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -1,48 +1,15 @@ --#include "bcm2708_common.dtsi" -+#include "bcm2836.dtsi" -+#include "bcm270x.dtsi" -+#include "bcm2708-rpi.dtsi" - - / { - compatible = "brcm,bcm2709"; - model = "BCM2709"; - -- chosen { -- /* No padding required - the boot loader can do that. */ -- bootargs = ""; -- }; -- - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -- -- local_intc: local_intc { -- compatible = "brcm,bcm2836-l1-intc"; -- reg = <0x40000000 0x100>; -- interrupt-controller; -- #interrupt-cells = <1>; -- interrupt-parent = <&local_intc>; -- }; -- -- arm-pmu { -- compatible = "arm,cortex-a7-pmu"; -- interrupt-parent = <&local_intc>; -- interrupts = <9>; -- }; -- -- gpiomem { -- compatible = "brcm,bcm2835-gpiomem"; -- reg = <0x7e200000 0x1000>; -- status = "okay"; -- }; -- -- timer { -- compatible = "arm,armv7-timer"; -- clock-frequency = <19200000>; -- interrupt-parent = <&local_intc>; -- interrupts = <0>, // PHYS_SECURE_PPI -- <1>, // PHYS_NONSECURE_PPI -- <3>, // VIRT_PPI -- <2>; // HYP_PPI -- always-on; -- }; -+ /delete-property/ dma-ranges; - - syscon@40000000 { - compatible = "brcm,bcm2836-arm-local", "syscon"; -@@ -50,53 +17,10 @@ - }; - }; - -- cpus: cpus { -- #address-cells = <1>; -- #size-cells = <0>; -- -- v7_cpu0: cpu@0 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf00>; -- clock-frequency = <800000000>; -- }; -- -- v7_cpu1: cpu@1 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf01>; -- clock-frequency = <800000000>; -- }; -- -- v7_cpu2: cpu@2 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf02>; -- clock-frequency = <800000000>; -- }; -- -- v7_cpu3: cpu@3 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf03>; -- clock-frequency = <800000000>; -- }; -- }; -- - __overrides__ { - arm_freq = <&v7_cpu0>, "clock-frequency:0", -- <&v7_cpu1>, "clock-frequency:0", -- <&v7_cpu2>, "clock-frequency:0", -- <&v7_cpu3>, "clock-frequency:0"; -+ <&v7_cpu1>, "clock-frequency:0", -+ <&v7_cpu2>, "clock-frequency:0", -+ <&v7_cpu3>, "clock-frequency:0"; - }; - }; -- --&watchdog { -- status = "okay"; --}; -- --&intc { -- compatible = "brcm,bcm2836-armctrl-ic"; -- interrupt-parent = <&local_intc>; -- interrupts = <8>; --}; -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..7fb1f428332dc48bdd91dd4a0773f3bea7057238 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -0,0 +1,142 @@ -+/* Downstream bcm283x.dtsi diff */ -+ -+/ { -+ chosen { -+ bootargs = ""; -+ }; -+ -+ soc: soc { -+ -+ /delete-node/ timer@7e003000; -+ -+ watchdog: watchdog@7e100000 { -+ /* Add alias */ -+ }; -+ -+ cprman: cprman@7e101000 { -+ /* Add alias */ -+ }; -+ -+ random: rng@7e104000 { -+ /* Add alias */ -+ }; -+ -+ gpio@7e200000 { /* gpio */ -+ interrupts = <2 17>, <2 18>; -+ }; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ interrupts = <2 24>; -+ clocks = <&clocks BCM2835_CLOCK_VPU>; -+ dmas = <&dma 13>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ brcm,pio-limit = <1>; -+ status = "disabled"; -+ }; -+ -+ i2s@7e203000 { /* i2s */ -+ #sound-dai-cells = <0>; -+ reg = <0x7e203000 0x24>; -+ clocks = <&clocks BCM2835_CLOCK_PCM>; -+ }; -+ -+ spi0: spi@7e204000 { -+ /* Add alias */ -+ dmas = <&dma 6>, <&dma 7>; -+ dma-names = "tx", "rx"; -+ }; -+ -+ i2c@7e205000 { /* i2c0 */ -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ -+ pixelvalve0: pixelvalve@7e206000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ pixelvalve1: pixelvalve@7e207000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ dpi: dpi@7e208000 { -+ compatible = "brcm,bcm2835-dpi"; -+ reg = <0x7e208000 0x8c>; -+ clocks = <&clocks BCM2835_CLOCK_VPU>, -+ <&clocks BCM2835_CLOCK_DPI>; -+ clock-names = "core", "pixel"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ /delete-node/ sdhci@7e300000; -+ -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clocks BCM2835_CLOCK_EMMC>; -+ dmas = <&dma 11>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ status = "disabled"; -+ }; -+ -+ hvs: hvs@7e400000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ smi: smi@7e600000 { -+ compatible = "brcm,bcm2835-smi"; -+ reg = <0x7e600000 0x100>; -+ interrupts = <2 16>; -+ clocks = <&clocks BCM2835_CLOCK_SMI>; -+ assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; -+ assigned-clock-rates = <125000000>; -+ dmas = <&dma 4>; -+ dma-names = "rx-tx"; -+ status = "disabled"; -+ }; -+ -+ i2c@7e804000 { /* i2c1 */ -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ -+ i2c@7e805000 { /* i2c2 */ -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ -+ pixelvalve2: pixelvalve@7e807000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ hdmi@7e902000 { /* hdmi */ -+ status = "disabled"; -+ }; -+ -+ usb@7e980000 { /* usb */ -+ compatible = "brcm,bcm2708-usb"; -+ reg = <0x7e980000 0x10000>, -+ <0x7e006000 0x1000>; -+ interrupts = <2 0>, -+ <1 9>; -+ }; -+ -+ v3d@7ec00000 { /* vd3 */ -+ compatible = "brcm,vc4-v3d"; -+ status = "disabled"; -+ }; -+ -+ gpu: gpu { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index d9ae00f95e6261eea582d7a2c6dfbc221f99953d..30060663ca712578f6d697fd02a3b31d94301707 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -153,15 +153,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index 20388084b98cf942529eb60c55dc540cfea71886..b5a5ae7747455438f8eabd28e8c11c6aeb0c1ecc 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -108,15 +108,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index 223bd9627b3dcaac5458909dc59c877eed751ce4..491594c918cf5da94fbb19a606edb0dd9a28c3a9 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -1,14 +1,11 @@ --#include "bcm2708_common.dtsi" -+#include "bcm283x.dtsi" -+#include "bcm270x.dtsi" -+#include "bcm2708-rpi.dtsi" - - / { - compatible = "brcm,bcm2710","brcm,bcm2709"; - model = "BCM2710"; - -- chosen { -- /* No padding required - the boot loader can do that. */ -- bootargs = ""; -- }; -- - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -@@ -34,19 +31,12 @@ - interrupts = <9>; - }; - -- gpiomem { -- compatible = "brcm,bcm2835-gpiomem"; -- reg = <0x7e200000 0x1000>; -- status = "okay"; -- }; -- - timer { - #ifdef RPI364 - compatible = "arm,armv8-timer", "arm,armv7-timer"; - #else - compatible = "arm,armv7-timer"; - #endif -- clock-frequency = <19200000>; - interrupt-parent = <&local_intc>; - interrupts = <0>, // PHYS_SECURE_PPI - <1>, // PHYS_NONSECURE_PPI -@@ -151,10 +141,6 @@ - #endif - }; - --&watchdog { -- status = "okay"; --}; -- - &intc { - compatible = "brcm,bcm2836-armctrl-ic"; - #ifdef RPI364 -@@ -163,3 +149,11 @@ - interrupt-parent = <&local_intc>; - interrupts = <8>; - }; -+ -+#ifdef RPI364 -+&usb { -+ compatible = "brcm,bcm2835-usb"; -+ reg = <0x7e980000 0x10000>; -+ interrupts = <1 9>; -+}; -+#endif - -From 3011169b346afd96213eb70e42af510451aabfec Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 7 Oct 2016 16:50:59 +0200 -Subject: [PATCH 111/208] watchdog: bcm2835: Support setting reboot partition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The Raspberry Pi firmware looks at the RSTS register to know which -partition to boot from. The reboot syscall command -LINUX_REBOOT_CMD_RESTART2 supports passing in a string argument. - -Add support for passing in a partition number 0..63 to boot from. -Partition 63 is a special partiton indicating halt. -If the partition doesn't exist, the firmware falls back to partition 0. - -Signed-off-by: Noralf Trønnes ---- - drivers/watchdog/bcm2835_wdt.c | 61 +++++++++++++++++++++++++----------------- - 1 file changed, 36 insertions(+), 25 deletions(-) - -diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c -index 4dddd8298a227d64862f2e92954a465f2e44b3f6..1f545e024422f59280932713e6a1b05150b39b22 100644 ---- a/drivers/watchdog/bcm2835_wdt.c -+++ b/drivers/watchdog/bcm2835_wdt.c -@@ -35,13 +35,7 @@ - #define PM_RSTC_WRCFG_SET 0x00000030 - #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 - #define PM_RSTC_RESET 0x00000102 -- --/* -- * The Raspberry Pi firmware uses the RSTS register to know which partiton -- * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. -- * Partiton 63 is a special partition used by the firmware to indicate halt. -- */ --#define PM_RSTS_RASPBERRYPI_HALT 0x555 -+#define PM_RSTS_PARTITION_CLR 0xfffffaaa - - #define SECS_TO_WDOG_TICKS(x) ((x) << 16) - #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) -@@ -111,15 +105,28 @@ static struct watchdog_device bcm2835_wdt_wdd = { - .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), - }; - --static int --bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) -+/* -+ * The Raspberry Pi firmware uses the RSTS register to know which partiton -+ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. -+ * Partiton 63 is a special partition used by the firmware to indicate halt. -+ */ -+ -+static void bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition) - { -- struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, -- restart_handler); -- u32 val; -+ u32 val, rsts; -+ -+ rsts = (partition & BIT(0)) | ((partition & BIT(1)) << 1) | -+ ((partition & BIT(2)) << 2) | ((partition & BIT(3)) << 3) | -+ ((partition & BIT(4)) << 4) | ((partition & BIT(5)) << 5); -+ -+ val = readl_relaxed(wdt->base + PM_RSTS); -+ val &= PM_RSTS_PARTITION_CLR; -+ val |= PM_PASSWORD | rsts; -+ writel_relaxed(val, wdt->base + PM_RSTS); - - /* use a timeout of 10 ticks (~150us) */ - writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG); -+ - val = readl_relaxed(wdt->base + PM_RSTC); - val &= PM_RSTC_WRCFG_CLR; - val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; -@@ -127,6 +134,20 @@ bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) - - /* No sleeping, possibly atomic. */ - mdelay(1); -+} -+ -+static int bcm2835_restart_notifier_call(struct notifier_block *this, -+ unsigned long mode, void *cmd) -+{ -+ struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, -+ restart_handler); -+ unsigned long long val; -+ u8 partition = 0; -+ -+ if (cmd && !kstrtoull(cmd, 0, &val) && val <= 63) -+ partition = val; -+ -+ bcm2835_restart(wdt, partition); - - return 0; - } -@@ -142,19 +163,9 @@ static void bcm2835_power_off(void) - of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt"); - struct platform_device *pdev = of_find_device_by_node(np); - struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); -- u32 val; -- -- /* -- * We set the watchdog hard reset bit here to distinguish this reset -- * from the normal (full) reset. bootcode.bin will not reboot after a -- * hard reset. -- */ -- val = readl_relaxed(wdt->base + PM_RSTS); -- val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT; -- writel_relaxed(val, wdt->base + PM_RSTS); - -- /* Continue with normal reset mechanism */ -- bcm2835_restart(&wdt->restart_handler, REBOOT_HARD, NULL); -+ /* Partition 63 tells the firmware that this is a halt */ -+ bcm2835_restart(wdt, 63); - } - - static int bcm2835_wdt_probe(struct platform_device *pdev) -@@ -188,7 +199,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) - return err; - } - -- wdt->restart_handler.notifier_call = bcm2835_restart; -+ wdt->restart_handler.notifier_call = bcm2835_restart_notifier_call; - wdt->restart_handler.priority = 128; - register_restart_handler(&wdt->restart_handler); - if (pm_power_off == NULL) - -From 4bea90c43d3fd3e0594f3dc52746f42ca16b8eb1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 7 Oct 2016 17:07:46 +0200 -Subject: [PATCH 112/208] bcm270x: Use watchdog for reboot/poweroff -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The watchdog driver already has support for reboot/poweroff. -Make use of this and remove the code from the platform files. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 2 +- - arch/arm/configs/bcmrpi_defconfig | 2 +- - arch/arm/mach-bcm2708/bcm2708.c | 70 ------------------------------------- - arch/arm/mach-bcm2709/bcm2709.c | 71 -------------------------------------- - 4 files changed, 2 insertions(+), 143 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index dfbb3406e38b50bf38db84071f82c3a556da8057..aa708638cc6f3bceb189c2deef7307252901291f 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -650,7 +650,7 @@ CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y --CONFIG_BCM2835_WDT=m -+CONFIG_BCM2835_WDT=y - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index cfe21355f7d95326b292be1b018b988fa3ffe865..952104ab6c4cd0e9d8f7bd5f2fba7a72da75424e 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -641,7 +641,7 @@ CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y --CONFIG_BCM2835_WDT=m -+CONFIG_BCM2835_WDT=y - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 280628ba8907d2a4323fc86dfc6db7fc684aeabc..a8e2a5b114b2f12f18378ce5fff2a88419b6f52f 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -44,7 +44,6 @@ - - /* command line parameters */ - static unsigned boardrev, serial; --static unsigned reboot_part = 0; - - static struct map_desc bcm2708_io_desc[] __initdata = { - { -@@ -99,71 +98,6 @@ void __init bcm2708_map_io(void) - iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); - } - --int calc_rsts(int partition) --{ -- return PM_PASSWORD | -- ((partition & (1 << 0)) << 0) | -- ((partition & (1 << 1)) << 1) | -- ((partition & (1 << 2)) << 2) | -- ((partition & (1 << 3)) << 3) | -- ((partition & (1 << 4)) << 4) | -- ((partition & (1 << 5)) << 5); --} -- --static void bcm2708_restart(enum reboot_mode mode, const char *cmd) --{ -- extern char bcm2708_reboot_mode; -- uint32_t pm_rstc, pm_wdog; -- uint32_t timeout = 10; -- uint32_t pm_rsts = 0; -- -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < 1.3 booting with reboot=q -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -- } -- else if(bcm2708_reboot_mode == 'p') -- { -- // NOOBS < 1.3 halting -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -- } -- else -- { -- pm_rsts = calc_rsts(reboot_part); -- } -- -- writel(pm_rsts, __io_address(PM_RSTS)); -- -- /* Setup watchdog for reset */ -- pm_rstc = readl(__io_address(PM_RSTC)); -- -- pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -- pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -- -- writel(pm_wdog, __io_address(PM_WDOG)); -- writel(pm_rstc, __io_address(PM_RSTC)); --} -- --/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ --static void bcm2708_power_off(void) --{ -- extern char bcm2708_reboot_mode; -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < v1.3 -- bcm2708_restart('p', ""); -- } -- else -- { -- /* partition 63 is special code for HALT the bootloader knows not to boot*/ -- reboot_part = 63; -- /* continue with normal reset mechanism */ -- bcm2708_restart(0, ""); -- } --} -- - static void __init bcm2708_init_uart1(void) - { - struct device_node *np; -@@ -181,8 +115,6 @@ void __init bcm2708_init(void) - - vc_cma_early_init(); - -- pm_power_off = bcm2708_power_off; -- - ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, - NULL); - if (ret) { -@@ -222,10 +154,8 @@ MACHINE_START(BCM2708, "BCM2708") - .init_machine = bcm2708_init, - .init_early = bcm2708_init_early, - .reserve = board_reserve, -- .restart = bcm2708_restart, - .dt_compat = bcm2708_compat, - MACHINE_END - - module_param(boardrev, uint, 0644); - module_param(serial, uint, 0644); --module_param(reboot_part, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d4c9d57d78a964fbbf799b534471462d3c3b88f1..ed5c5414f7a3ad7284cda881e9e550777cd29282 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -51,7 +51,6 @@ - - /* command line parameters */ - static unsigned boardrev, serial; --static unsigned reboot_part = 0; - - static struct map_desc bcm2709_io_desc[] __initdata = { - { -@@ -111,71 +110,6 @@ void __init bcm2709_map_io(void) - iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); - } - --int calc_rsts(int partition) --{ -- return PM_PASSWORD | -- ((partition & (1 << 0)) << 0) | -- ((partition & (1 << 1)) << 1) | -- ((partition & (1 << 2)) << 2) | -- ((partition & (1 << 3)) << 3) | -- ((partition & (1 << 4)) << 4) | -- ((partition & (1 << 5)) << 5); --} -- --static void bcm2709_restart(enum reboot_mode mode, const char *cmd) --{ -- extern char bcm2708_reboot_mode; -- uint32_t pm_rstc, pm_wdog; -- uint32_t timeout = 10; -- uint32_t pm_rsts = 0; -- -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < 1.3 booting with reboot=q -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -- } -- else if(bcm2708_reboot_mode == 'p') -- { -- // NOOBS < 1.3 halting -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -- } -- else -- { -- pm_rsts = calc_rsts(reboot_part); -- } -- -- writel(pm_rsts, __io_address(PM_RSTS)); -- -- /* Setup watchdog for reset */ -- pm_rstc = readl(__io_address(PM_RSTC)); -- -- pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -- pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -- -- writel(pm_wdog, __io_address(PM_WDOG)); -- writel(pm_rstc, __io_address(PM_RSTC)); --} -- --/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ --static void bcm2709_power_off(void) --{ -- extern char bcm2708_reboot_mode; -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < v1.3 -- bcm2709_restart('p', ""); -- } -- else -- { -- /* partition 63 is special code for HALT the bootloader knows not to boot*/ -- reboot_part = 63; -- /* continue with normal reset mechanism */ -- bcm2709_restart(0, ""); -- } --} -- - static void __init bcm2709_init_uart1(void) - { - struct device_node *np; -@@ -193,8 +127,6 @@ void __init bcm2709_init(void) - - vc_cma_early_init(); - -- pm_power_off = bcm2709_power_off; -- - ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, - NULL); - if (ret) { -@@ -235,7 +167,6 @@ MACHINE_START(BCM2709, "BCM2709") - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, -- .restart = bcm2709_restart, - .dt_compat = bcm2709_compat, - MACHINE_END - -@@ -245,10 +176,8 @@ MACHINE_START(BCM2708, "BCM2709") - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, -- .restart = bcm2709_restart, - .dt_compat = bcm2709_compat, - MACHINE_END - - module_param(boardrev, uint, 0644); - module_param(serial, uint, 0644); --module_param(reboot_part, uint, 0644); - -From f384e2b3b12499f3677facd847263c2669f71d51 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:35:40 +0200 -Subject: [PATCH 113/208] bcm270x: Remove dead files -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -include/mach/vmalloc.h has not been used since 2011. -include/mach/entry-macro.S is leftover from the move to the mainline -irq driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 ---- - arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 ----------------------- - arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 ---- - 3 files changed, 163 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h - -diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h -deleted file mode 100644 -index 502c6178101be60b10c9eb31afec938b5534c33f..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/vmalloc.h -+++ /dev/null -@@ -1,20 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vmalloc.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#define VMALLOC_END (0xe8000000) -diff --git a/arch/arm/mach-bcm2709/include/mach/entry-macro.S b/arch/arm/mach-bcm2709/include/mach/entry-macro.S -deleted file mode 100644 -index d08591b63c1a1710c40350d343d3eddc97ae74c1..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/entry-macro.S -+++ /dev/null -@@ -1,123 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/entry-macro.S -- * -- * Low-level IRQ helper macros for BCM2708 platforms -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#include --#include -- -- .macro disable_fiq -- .endm -- -- .macro get_irqnr_preamble, base, tmp -- ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) -- .endm -- -- .macro arch_ret_to_user, tmp1, tmp2 -- .endm -- -- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -- /* get core number */ -- mrc p15, 0, \tmp, c0, c0, 5 -- ubfx \tmp, \tmp, #0, #2 -- -- /* get core's local interrupt controller */ -- ldr \irqstat, = __io_address(ARM_LOCAL_IRQ_PENDING0) @ local interrupt source -- add \irqstat, \irqstat, \tmp, lsl #2 -- ldr \tmp, [\irqstat] -- /* ignore gpu interrupt */ -- bic \tmp, #0x100 -- /* ignore mailbox interrupts */ -- bics \tmp, #0xf0 -- beq 1005f -- -- @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -- @ N.B. CLZ is an ARM5 instruction. -- mov \irqnr, #(ARM_IRQ_LOCAL_BASE + 31) -- sub \irqstat, \tmp, #1 -- eor \irqstat, \irqstat, \tmp -- clz \tmp, \irqstat -- sub \irqnr, \tmp -- b 1020f --1005: -- /* get core number */ -- mrc p15, 0, \tmp, c0, c0, 5 -- ubfx \tmp, \tmp, #0, #2 -- -- cmp \tmp, #1 -- beq 1020f -- cmp \tmp, #2 -- beq 1020f -- cmp \tmp, #3 -- beq 1020f -- -- /* get masked status */ -- ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] -- mov \irqnr, #(ARM_IRQ0_BASE + 31) -- and \tmp, \irqstat, #0x300 @ save bits 8 and 9 -- /* clear bits 8 and 9, and test */ -- bics \irqstat, \irqstat, #0x300 -- bne 1010f -- -- tst \tmp, #0x100 -- ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] -- movne \irqnr, #(ARM_IRQ1_BASE + 31) -- @ Mask out the interrupts also present in PEND0 - see SW-5809 -- bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) -- bicne \irqstat, #((1<<18) | (1<<19)) -- bne 1010f -- -- tst \tmp, #0x200 -- ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] -- movne \irqnr, #(ARM_IRQ2_BASE + 31) -- @ Mask out the interrupts also present in PEND0 - see SW-5809 -- bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) -- bicne \irqstat, #((1<<30)) -- beq 1020f -- --1010: -- @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -- @ N.B. CLZ is an ARM5 instruction. -- sub \tmp, \irqstat, #1 -- eor \irqstat, \irqstat, \tmp -- clz \tmp, \irqstat -- sub \irqnr, \tmp -- --1020: @ EQ will be set if no irqs pending -- -- .endm -- -- .macro test_for_ipi, irqnr, irqstat, base, tmp -- /* get core number */ -- mrc p15, 0, \tmp, c0, c0, 5 -- ubfx \tmp, \tmp, #0, #2 -- /* get core's mailbox interrupt control */ -- ldr \irqstat, = __io_address(ARM_LOCAL_MAILBOX0_CLR0) @ mbox_clr -- add \irqstat, \irqstat, \tmp, lsl #4 -- ldr \tmp, [\irqstat] -- cmp \tmp, #0 -- beq 1030f -- clz \tmp, \tmp -- rsb \irqnr, \tmp, #31 -- mov \tmp, #1 -- lsl \tmp, \irqnr -- str \tmp, [\irqstat] @ clear interrupt source -- dsb --1030: @ EQ will be set if no irqs pending -- .endm -diff --git a/arch/arm/mach-bcm2709/include/mach/vmalloc.h b/arch/arm/mach-bcm2709/include/mach/vmalloc.h -deleted file mode 100644 -index 6aa68260dd866c83527dffece8de483913231fb3..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/vmalloc.h -+++ /dev/null -@@ -1,20 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vmalloc.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#define VMALLOC_END (0xff000000) - -From 0b9d5789d2a90665ed8f46c3dcdff92d3da2e8d7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:37:43 +0200 -Subject: [PATCH 114/208] bcm270x: Drop bcm2835-aux-uart hack -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The gated bcm2835-aux clock is now used to enable uart1 so drop this hack. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 15 +-------------- - arch/arm/mach-bcm2709/bcm2709.c | 15 +-------------- - 2 files changed, 2 insertions(+), 28 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a8e2a5b114b2f12f18378ce5fff2a88419b6f52f..8d1e56db3a89295af18dff99f1ee572f56487e72 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -98,18 +98,7 @@ void __init bcm2708_map_io(void) - iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); - } - --static void __init bcm2708_init_uart1(void) --{ -- struct device_node *np; -- -- np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -- if (of_device_is_available(np)) { -- pr_info("bcm2708: Mini UART enabled\n"); -- writel(1, __io_address(UART1_BASE + 0x4)); -- } --} -- --void __init bcm2708_init(void) -+static void __init bcm2708_init(void) - { - int ret; - -@@ -122,8 +111,6 @@ void __init bcm2708_init(void) - BUG(); - } - -- bcm2708_init_uart1(); -- - system_rev = boardrev; - system_serial_low = serial; - } -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index ed5c5414f7a3ad7284cda881e9e550777cd29282..9a1ad48d13172856e3ec748db015cb95cd110b76 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -110,18 +110,7 @@ void __init bcm2709_map_io(void) - iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); - } - --static void __init bcm2709_init_uart1(void) --{ -- struct device_node *np; -- -- np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -- if (of_device_is_available(np)) { -- pr_info("bcm2709: Mini UART enabled\n"); -- writel(1, __io_address(UART1_BASE + 0x4)); -- } --} -- --void __init bcm2709_init(void) -+static void __init bcm2709_init(void) - { - int ret; - -@@ -134,8 +123,6 @@ void __init bcm2709_init(void) - BUG(); - } - -- bcm2709_init_uart1(); -- - system_rev = boardrev; - system_serial_low = serial; - } - -From 609fc508667ebfb25abaab84e856373ea13ad521 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:41:26 +0200 -Subject: [PATCH 115/208] bcm270x: Remove unnecessary of_platform_populate -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since 4.8 of_platform_default_populate_init() does the same and it is -called at arch_initcall_sync. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 10 ---------- - arch/arm/mach-bcm2709/bcm2709.c | 10 ---------- - 2 files changed, 20 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 8d1e56db3a89295af18dff99f1ee572f56487e72..0db44e566062751510494e2fe19926122aad7d5a 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -21,7 +21,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -100,17 +99,8 @@ void __init bcm2708_map_io(void) - - static void __init bcm2708_init(void) - { -- int ret; -- - vc_cma_early_init(); - -- ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -- NULL); -- if (ret) { -- pr_err("of_platform_populate failed: %d\n", ret); -- BUG(); -- } -- - system_rev = boardrev; - system_serial_low = serial; - } -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 9a1ad48d13172856e3ec748db015cb95cd110b76..d2762f558f644ac87c56ba9402a638a3c7a26397 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - - #include - #include -@@ -112,17 +111,8 @@ void __init bcm2709_map_io(void) - - static void __init bcm2709_init(void) - { -- int ret; -- - vc_cma_early_init(); - -- ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -- NULL); -- if (ret) { -- pr_err("of_platform_populate failed: %d\n", ret); -- BUG(); -- } -- - system_rev = boardrev; - system_serial_low = serial; - } - -From f24c1d7e84b995a5c72dcfeaa4dec996f816438e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:46:27 +0200 -Subject: [PATCH 116/208] bcm270x: Remove 4MB dma coherent pool -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Drop the call to init_dma_coherent_pool_size(). The default 256kB is -enough since vchiq dropped that atomic allocation some time back. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 11 ----------- - arch/arm/mach-bcm2709/bcm2709.c | 12 ------------ - 2 files changed, 23 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 0db44e566062751510494e2fe19926122aad7d5a..0dc1efd48f385eea9f712fc8e18ffc92966271f2 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -105,16 +105,6 @@ static void __init bcm2708_init(void) - system_serial_low = serial; - } - --void __init bcm2708_init_early(void) --{ -- /* -- * Some devices allocate their coherent buffers from atomic -- * context. Increase size of atomic coherent pool to make sure such -- * the allocations won't fail. -- */ -- init_dma_coherent_pool_size(SZ_4M); --} -- - static void __init board_reserve(void) - { - vc_cma_reserve(); -@@ -129,7 +119,6 @@ MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2708_map_io, - .init_machine = bcm2708_init, -- .init_early = bcm2708_init_early, - .reserve = board_reserve, - .dt_compat = bcm2708_compat, - MACHINE_END -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d2762f558f644ac87c56ba9402a638a3c7a26397..d0e43619669e851350c5d9d7bb7e9dd19ea6ff1b 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -117,16 +117,6 @@ static void __init bcm2709_init(void) - system_serial_low = serial; - } - --void __init bcm2709_init_early(void) --{ -- /* -- * Some devices allocate their coherent buffers from atomic -- * context. Increase size of atomic coherent pool to make sure such -- * the allocations won't fail. -- */ -- init_dma_coherent_pool_size(SZ_4M); --} -- - static void __init board_reserve(void) - { - vc_cma_reserve(); -@@ -142,7 +132,6 @@ MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, -- .init_early = bcm2709_init_early, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, - MACHINE_END -@@ -151,7 +140,6 @@ MACHINE_START(BCM2708, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, -- .init_early = bcm2709_init_early, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, - MACHINE_END - -From 0fcba7b96ea2778232431b7ae302e1473c1abdb5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 19:26:42 +0200 -Subject: [PATCH 117/208] bcm270x: Drop map_io device mapping -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -All drivers map their own io now so it's not necessary to do this -mapping anymore. The mapping for the uart debug console is handled by -debug_ll_io_init() if necessary. - -Remove local uart debug code and rely on mainline. -Use these kconfig options to enable: -CONFIG_DEBUG_BCM2835 -CONFIG_DEBUG_BCM2836 - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig.debug | 18 +-- - arch/arm/mach-bcm2708/bcm2708.c | 75 +-------- - arch/arm/mach-bcm2708/include/mach/debug-macro.S | 22 --- - arch/arm/mach-bcm2708/include/mach/platform.h | 114 -------------- - arch/arm/mach-bcm2708/include/mach/system.h | 37 ----- - arch/arm/mach-bcm2708/include/mach/uncompress.h | 84 ---------- - arch/arm/mach-bcm2709/bcm2709.c | 86 +--------- - arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 --- - arch/arm/mach-bcm2709/include/mach/platform.h | 190 ----------------------- - arch/arm/mach-bcm2709/include/mach/system.h | 37 ----- - arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 ---------- - 11 files changed, 11 insertions(+), 758 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S - delete mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h - delete mode 100644 arch/arm/mach-bcm2708/include/mach/system.h - delete mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S - delete mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/system.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h - -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index f47f4e70395635fafeacd680c4392cc51660ea8e..11aa81fcaaa8e476ded9b9f41e30ddefa11c1cae 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -147,12 +147,12 @@ choice - - config DEBUG_BCM2835 - bool "Kernel low-level debugging on BCM2835 PL011 UART" -- depends on ARCH_BCM2835 && ARCH_MULTI_V6 -+ depends on (ARCH_BCM2835 && ARCH_MULTI_V6) || ARCH_BCM2708 - select DEBUG_UART_PL01X - - config DEBUG_BCM2836 - bool "Kernel low-level debugging on BCM2836 PL011 UART" -- depends on ARCH_BCM2835 && ARCH_MULTI_V7 -+ depends on (ARCH_BCM2835 && ARCH_MULTI_V7) || ARCH_BCM2709 - select DEBUG_UART_PL01X - - config DEBUG_BCM_5301X -@@ -1312,14 +1312,6 @@ choice - options; the platform specific options are deprecated - and will be soon removed. - -- config DEBUG_BCM2708_UART0 -- bool "Broadcom BCM270X UART0 (PL011)" -- depends on ARCH_BCM2708 || ARCH_BCM2709 -- help -- Say Y here if you want the debug print routines to direct -- their output to UART 0. The port must have been initialised -- by the boot-loader before use. -- - endchoice - - config DEBUG_AT91_UART -@@ -1703,7 +1695,8 @@ config DEBUG_UART_8250_FLOW_CONTROL - - config DEBUG_UNCOMPRESS - bool -- depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M -+ depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -+ ARCH_BCM2708 || ARCH_BCM2709 - default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ - (!DEBUG_TEGRA_UART || !ZBOOT_ROM) - help -@@ -1720,7 +1713,8 @@ config DEBUG_UNCOMPRESS - config UNCOMPRESS_INCLUDE - string - default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \ -- PLAT_SAMSUNG || ARM_SINGLE_ARMV7M -+ PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -+ ARCH_BCM2708 || ARCH_BCM2709 - default "mach/uncompress.h" - - config EARLY_PRINTK -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 0dc1efd48f385eea9f712fc8e18ffc92966271f2..47d5f363334ea317f09a6d6b7c8f3f2f797a2be3 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -19,84 +19,16 @@ - */ - - #include --#include - #include --#include --#include --#include --#include -- --#include -- - #include - --/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -- * give us IO access only to 64Mbytes of physical memory (26 bits). We could -- * represent this window by setting our dmamasks to 26 bits but, in fact -- * we're not going to use addresses outside this range (they're not in real -- * memory) so we don't bother. -- * -- * In the future we might include code to use this IOMMU to remap other -- * physical addresses onto VideoCore memory then the use of 32-bits would be -- * more legitimate. -- */ -+#include -+#include -+#include - - /* command line parameters */ - static unsigned boardrev, serial; - --static struct map_desc bcm2708_io_desc[] __initdata = { -- { -- .virtual = IO_ADDRESS(ARMCTRL_BASE), -- .pfn = __phys_to_pfn(ARMCTRL_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART0_BASE), -- .pfn = __phys_to_pfn(UART0_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART1_BASE), -- .pfn = __phys_to_pfn(UART1_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(DMA_BASE), -- .pfn = __phys_to_pfn(DMA_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(MCORE_BASE), -- .pfn = __phys_to_pfn(MCORE_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(ST_BASE), -- .pfn = __phys_to_pfn(ST_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(USB_BASE), -- .pfn = __phys_to_pfn(USB_BASE), -- .length = SZ_128K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(PM_BASE), -- .pfn = __phys_to_pfn(PM_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(GPIO_BASE), -- .pfn = __phys_to_pfn(GPIO_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE} --}; -- --void __init bcm2708_map_io(void) --{ -- iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); --} -- - static void __init bcm2708_init(void) - { - vc_cma_early_init(); -@@ -117,7 +49,6 @@ static const char * const bcm2708_compat[] = { - - MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ -- .map_io = bcm2708_map_io, - .init_machine = bcm2708_init, - .reserve = board_reserve, - .dt_compat = bcm2708_compat, -diff --git a/arch/arm/mach-bcm2708/include/mach/debug-macro.S b/arch/arm/mach-bcm2708/include/mach/debug-macro.S -deleted file mode 100644 -index b24304a6755e965b8a28eb048b7f4e2d868820f9..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/debug-macro.S -+++ /dev/null -@@ -1,22 +0,0 @@ --/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -- * -- * Debugging macro include header -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 1994-1999 Russell King -- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * --*/ -- --#include -- -- .macro addruart, rp, rv, tmp -- ldr \rp, =UART0_BASE -- ldr \rv, =IO_ADDRESS(UART0_BASE) -- .endm -- --#include -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -deleted file mode 100644 -index e98ec5acc70ba9eb2bc7ff560ed3c92e21518b73..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ /dev/null -@@ -1,114 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/platform.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _BCM2708_PLATFORM_H --#define _BCM2708_PLATFORM_H -- -- --/* macros to get at IO space when running virtually */ --#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -- --#define __io_address(n) IOMEM(IO_ADDRESS(n)) -- -- --/* -- * SDRAM -- */ --#define BCM2708_SDRAM_BASE 0x00000000 -- --/* -- * Logic expansion modules -- * -- */ -- -- --/* ------------------------------------------------------------------------ -- * BCM2708 ARMCTRL Registers -- * ------------------------------------------------------------------------ -- */ -- --#define HW_REGISTER_RW(addr) (addr) --#define HW_REGISTER_RO(addr) (addr) -- --/* -- * Definitions and addresses for the ARM CONTROL logic -- * This file is manually generated. -- */ -- --#define BCM2708_PERI_BASE 0x20000000 --#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) --#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ --#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ --#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ --#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ --#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ --#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ --#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ --#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ --#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ --#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ --#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ --#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ --#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ --#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ --#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ --#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ --#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ --#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ --#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -- --#define ARMCTRL_BASE (ARM_BASE + 0x000) --#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ --#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ --#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ --#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ --#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ -- --/* -- * Watchdog -- */ --#define PM_RSTC (PM_BASE+0x1c) --#define PM_RSTS (PM_BASE+0x20) --#define PM_WDOG (PM_BASE+0x24) -- --#define PM_WDOG_RESET 0000000000 --#define PM_PASSWORD 0x5a000000 --#define PM_WDOG_TIME_SET 0x000fffff --#define PM_RSTC_WRCFG_CLR 0xffffffcf --#define PM_RSTC_WRCFG_SET 0x00000030 --#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 --#define PM_RSTC_RESET 0x00000102 -- --#define PM_RSTS_HADPOR_SET 0x00001000 --#define PM_RSTS_HADSRH_SET 0x00000400 --#define PM_RSTS_HADSRF_SET 0x00000200 --#define PM_RSTS_HADSRQ_SET 0x00000100 --#define PM_RSTS_HADWRH_SET 0x00000040 --#define PM_RSTS_HADWRF_SET 0x00000020 --#define PM_RSTS_HADWRQ_SET 0x00000010 --#define PM_RSTS_HADDRH_SET 0x00000004 --#define PM_RSTS_HADDRF_SET 0x00000002 --#define PM_RSTS_HADDRQ_SET 0x00000001 -- --#define UART0_CLOCK 3000000 -- --#endif -- --/* END */ -diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h -deleted file mode 100644 -index c9a9c9a881102c5354971d15203a746906761a70..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/system.h -+++ /dev/null -@@ -1,37 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/system.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * Copyright (C) 2000 Deep Blue Solutions Ltd -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_SYSTEM_H --#define __ASM_ARCH_SYSTEM_H -- --#include --#include -- --static inline void arch_idle(void) --{ -- /* -- * This should do all the clock switching -- * and wait for interrupt tricks -- */ -- cpu_do_idle(); --} -- --#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/uncompress.h b/arch/arm/mach-bcm2708/include/mach/uncompress.h -deleted file mode 100644 -index de7504bfc20ba24be8707861b8389783860adb77..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/uncompress.h -+++ /dev/null -@@ -1,84 +0,0 @@ --/* -- * arch/arm/mach-bcn2708/include/mach/uncompress.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include --#include -- --#define UART_BAUD 115200 -- --#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) --#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) --#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) --#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) --#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) --#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -- --/* -- * This does not append a newline -- */ --static inline void putc(int c) --{ -- while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -- barrier(); -- -- __raw_writel(c, BCM2708_UART_DR); --} -- --static inline void flush(void) --{ -- int fr; -- -- do { -- fr = __raw_readl(BCM2708_UART_FR); -- barrier(); -- } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); --} -- --static inline void arch_decomp_setup(void) --{ -- int temp, div, rem, frac; -- -- temp = 16 * UART_BAUD; -- div = UART0_CLOCK / temp; -- rem = UART0_CLOCK % temp; -- temp = (8 * rem) / UART_BAUD; -- frac = (temp >> 1) + (temp & 1); -- -- /* Make sure the UART is disabled before we start */ -- __raw_writel(0, BCM2708_UART_CR); -- -- /* Set the baud rate */ -- __raw_writel(div, BCM2708_UART_IBRD); -- __raw_writel(frac, BCM2708_UART_FBRD); -- -- /* Set the UART to 8n1, FIFO enabled */ -- __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -- -- /* Enable the UART */ -- __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -- BCM2708_UART_CR); --} -- --/* -- * nothing to do -- */ --#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d0e43619669e851350c5d9d7bb7e9dd19ea6ff1b..39d304327bc84899a521aaeed8c1edd83c26d2d6 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -19,96 +19,16 @@ - */ - - #include --#include --#include --#include --#include --#include - #include -+#include - --#include - #include --#include -- - #include --#include -- --#include -- --#include -- --/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -- * give us IO access only to 64Mbytes of physical memory (26 bits). We could -- * represent this window by setting our dmamasks to 26 bits but, in fact -- * we're not going to use addresses outside this range (they're not in real -- * memory) so we don't bother. -- * -- * In the future we might include code to use this IOMMU to remap other -- * physical addresses onto VideoCore memory then the use of 32-bits would be -- * more legitimate. -- */ -+#include - - /* command line parameters */ - static unsigned boardrev, serial; - --static struct map_desc bcm2709_io_desc[] __initdata = { -- { -- .virtual = IO_ADDRESS(ARMCTRL_BASE), -- .pfn = __phys_to_pfn(ARMCTRL_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART0_BASE), -- .pfn = __phys_to_pfn(UART0_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART1_BASE), -- .pfn = __phys_to_pfn(UART1_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(DMA_BASE), -- .pfn = __phys_to_pfn(DMA_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(MCORE_BASE), -- .pfn = __phys_to_pfn(MCORE_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(ST_BASE), -- .pfn = __phys_to_pfn(ST_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(USB_BASE), -- .pfn = __phys_to_pfn(USB_BASE), -- .length = SZ_128K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(PM_BASE), -- .pfn = __phys_to_pfn(PM_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(GPIO_BASE), -- .pfn = __phys_to_pfn(GPIO_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(ARM_LOCAL_BASE), -- .pfn = __phys_to_pfn(ARM_LOCAL_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, --}; -- --void __init bcm2709_map_io(void) --{ -- iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); --} -- - static void __init bcm2709_init(void) - { - vc_cma_early_init(); -@@ -130,7 +50,6 @@ static const char * const bcm2709_compat[] = { - - MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ -- .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, -@@ -138,7 +57,6 @@ MACHINE_END - - MACHINE_START(BCM2708, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ -- .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, -diff --git a/arch/arm/mach-bcm2709/include/mach/debug-macro.S b/arch/arm/mach-bcm2709/include/mach/debug-macro.S -deleted file mode 100644 -index b24304a6755e965b8a28eb048b7f4e2d868820f9..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/debug-macro.S -+++ /dev/null -@@ -1,22 +0,0 @@ --/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -- * -- * Debugging macro include header -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 1994-1999 Russell King -- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * --*/ -- --#include -- -- .macro addruart, rp, rv, tmp -- ldr \rp, =UART0_BASE -- ldr \rv, =IO_ADDRESS(UART0_BASE) -- .endm -- --#include -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -deleted file mode 100644 -index 9a638f528fcebc9206419a2cc68f3c9856dda3c3..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ /dev/null -@@ -1,190 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/platform.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _BCM2708_PLATFORM_H --#define _BCM2708_PLATFORM_H -- -- --/* macros to get at IO space when running virtually */ --#define IO_ADDRESS(x) (((x) & 0x00ffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -- --#define __io_address(n) IOMEM(IO_ADDRESS(n)) -- -- --/* -- * SDRAM -- */ --#define BCM2708_SDRAM_BASE 0x00000000 -- --/* -- * Logic expansion modules -- * -- */ -- -- --/* ------------------------------------------------------------------------ -- * BCM2708 ARMCTRL Registers -- * ------------------------------------------------------------------------ -- */ -- --#define HW_REGISTER_RW(addr) (addr) --#define HW_REGISTER_RO(addr) (addr) -- --/* -- * Definitions and addresses for the ARM CONTROL logic -- * This file is manually generated. -- */ -- --#define BCM2708_PERI_BASE 0x3F000000 --#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) --#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ --#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ --#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ --#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ --#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ --#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ --#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ --#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ --#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ --#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ --#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ --#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ --#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ --#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ --#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ --#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ --#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ --#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ --#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -- --#define ARMCTRL_BASE (ARM_BASE + 0x000) --#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ --#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ --#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ --#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ --#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ -- --/* -- * Watchdog -- */ --#define PM_RSTC (PM_BASE+0x1c) --#define PM_RSTS (PM_BASE+0x20) --#define PM_WDOG (PM_BASE+0x24) -- --#define PM_WDOG_RESET 0000000000 --#define PM_PASSWORD 0x5a000000 --#define PM_WDOG_TIME_SET 0x000fffff --#define PM_RSTC_WRCFG_CLR 0xffffffcf --#define PM_RSTC_WRCFG_SET 0x00000030 --#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 --#define PM_RSTC_RESET 0x00000102 -- --#define PM_RSTS_HADPOR_SET 0x00001000 --#define PM_RSTS_HADSRH_SET 0x00000400 --#define PM_RSTS_HADSRF_SET 0x00000200 --#define PM_RSTS_HADSRQ_SET 0x00000100 --#define PM_RSTS_HADWRH_SET 0x00000040 --#define PM_RSTS_HADWRF_SET 0x00000020 --#define PM_RSTS_HADWRQ_SET 0x00000010 --#define PM_RSTS_HADDRH_SET 0x00000004 --#define PM_RSTS_HADDRF_SET 0x00000002 --#define PM_RSTS_HADDRQ_SET 0x00000001 -- --#define UART0_CLOCK 3000000 -- --#define ARM_LOCAL_BASE 0x40000000 --#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) -- --#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) --#define ARM_LOCAL_PRESCALER HW_REGISTER_RW(ARM_LOCAL_BASE+0x008) --#define ARM_LOCAL_GPU_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x00C) --#define ARM_LOCAL_PM_ROUTING_SET HW_REGISTER_RW(ARM_LOCAL_BASE+0x010) --#define ARM_LOCAL_PM_ROUTING_CLR HW_REGISTER_RW(ARM_LOCAL_BASE+0x014) --#define ARM_LOCAL_TIMER_LS HW_REGISTER_RW(ARM_LOCAL_BASE+0x01C) --#define ARM_LOCAL_TIMER_MS HW_REGISTER_RW(ARM_LOCAL_BASE+0x020) --#define ARM_LOCAL_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x024) --#define ARM_LOCAL_AXI_COUNT HW_REGISTER_RW(ARM_LOCAL_BASE+0x02C) --#define ARM_LOCAL_AXI_IRQ HW_REGISTER_RW(ARM_LOCAL_BASE+0x030) --#define ARM_LOCAL_TIMER_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x034) --#define ARM_LOCAL_TIMER_WRITE HW_REGISTER_RW(ARM_LOCAL_BASE+0x038) -- --#define ARM_LOCAL_TIMER_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x040) --#define ARM_LOCAL_TIMER_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x044) --#define ARM_LOCAL_TIMER_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x048) --#define ARM_LOCAL_TIMER_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x04C) -- --#define ARM_LOCAL_MAILBOX_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x050) --#define ARM_LOCAL_MAILBOX_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x054) --#define ARM_LOCAL_MAILBOX_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x058) --#define ARM_LOCAL_MAILBOX_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x05C) -- --#define ARM_LOCAL_IRQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x060) --#define ARM_LOCAL_IRQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x064) --#define ARM_LOCAL_IRQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x068) --#define ARM_LOCAL_IRQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x06C) -- --#define ARM_LOCAL_FIQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x070) --#define ARM_LOCAL_FIQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x074) --#define ARM_LOCAL_FIQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x078) --#define ARM_LOCAL_FIQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x07C) -- --#define ARM_LOCAL_MAILBOX0_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x080) --#define ARM_LOCAL_MAILBOX1_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x084) --#define ARM_LOCAL_MAILBOX2_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x088) --#define ARM_LOCAL_MAILBOX3_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x08C) -- --#define ARM_LOCAL_MAILBOX0_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x090) --#define ARM_LOCAL_MAILBOX1_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x094) --#define ARM_LOCAL_MAILBOX2_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x098) --#define ARM_LOCAL_MAILBOX3_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x09C) -- --#define ARM_LOCAL_MAILBOX0_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A0) --#define ARM_LOCAL_MAILBOX1_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A4) --#define ARM_LOCAL_MAILBOX2_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A8) --#define ARM_LOCAL_MAILBOX3_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0AC) -- --#define ARM_LOCAL_MAILBOX0_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B0) --#define ARM_LOCAL_MAILBOX1_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B4) --#define ARM_LOCAL_MAILBOX2_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B8) --#define ARM_LOCAL_MAILBOX3_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0BC) -- --#define ARM_LOCAL_MAILBOX0_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C0) --#define ARM_LOCAL_MAILBOX1_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C4) --#define ARM_LOCAL_MAILBOX2_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C8) --#define ARM_LOCAL_MAILBOX3_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0CC) -- --#define ARM_LOCAL_MAILBOX0_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D0) --#define ARM_LOCAL_MAILBOX1_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D4) --#define ARM_LOCAL_MAILBOX2_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D8) --#define ARM_LOCAL_MAILBOX3_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0DC) -- --#define ARM_LOCAL_MAILBOX0_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E0) --#define ARM_LOCAL_MAILBOX1_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E4) --#define ARM_LOCAL_MAILBOX2_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E8) --#define ARM_LOCAL_MAILBOX3_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0EC) -- --#define ARM_LOCAL_MAILBOX0_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F0) --#define ARM_LOCAL_MAILBOX1_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F4) --#define ARM_LOCAL_MAILBOX2_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F8) --#define ARM_LOCAL_MAILBOX3_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0FC) -- --#endif -- --/* END */ -diff --git a/arch/arm/mach-bcm2709/include/mach/system.h b/arch/arm/mach-bcm2709/include/mach/system.h -deleted file mode 100644 -index c9a9c9a881102c5354971d15203a746906761a70..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/system.h -+++ /dev/null -@@ -1,37 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/system.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * Copyright (C) 2000 Deep Blue Solutions Ltd -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_SYSTEM_H --#define __ASM_ARCH_SYSTEM_H -- --#include --#include -- --static inline void arch_idle(void) --{ -- /* -- * This should do all the clock switching -- * and wait for interrupt tricks -- */ -- cpu_do_idle(); --} -- --#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/uncompress.h b/arch/arm/mach-bcm2709/include/mach/uncompress.h -deleted file mode 100644 -index de7504bfc20ba24be8707861b8389783860adb77..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/uncompress.h -+++ /dev/null -@@ -1,84 +0,0 @@ --/* -- * arch/arm/mach-bcn2708/include/mach/uncompress.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include --#include -- --#define UART_BAUD 115200 -- --#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) --#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) --#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) --#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) --#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) --#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -- --/* -- * This does not append a newline -- */ --static inline void putc(int c) --{ -- while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -- barrier(); -- -- __raw_writel(c, BCM2708_UART_DR); --} -- --static inline void flush(void) --{ -- int fr; -- -- do { -- fr = __raw_readl(BCM2708_UART_FR); -- barrier(); -- } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); --} -- --static inline void arch_decomp_setup(void) --{ -- int temp, div, rem, frac; -- -- temp = 16 * UART_BAUD; -- div = UART0_CLOCK / temp; -- rem = UART0_CLOCK % temp; -- temp = (8 * rem) / UART_BAUD; -- frac = (temp >> 1) + (temp & 1); -- -- /* Make sure the UART is disabled before we start */ -- __raw_writel(0, BCM2708_UART_CR); -- -- /* Set the baud rate */ -- __raw_writel(div, BCM2708_UART_IBRD); -- __raw_writel(frac, BCM2708_UART_FBRD); -- -- /* Set the UART to 8n1, FIFO enabled */ -- __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -- -- /* Enable the UART */ -- __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -- BCM2708_UART_CR); --} -- --/* -- * nothing to do -- */ --#define arch_decomp_wdog() - -From 038f7a212a81706150142e5415ddb060d46c76bf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 19:37:06 +0200 -Subject: [PATCH 118/208] bcm270x: Use DT_MACHINE_START -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We are all DT now so use DT_MACHINE_START. -Also drop the extra BCM2709-BCM2708 mix entry. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 3 +-- - arch/arm/mach-bcm2709/bcm2709.c | 11 +---------- - arch/arm/tools/mach-types | 2 -- - 3 files changed, 2 insertions(+), 14 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 47d5f363334ea317f09a6d6b7c8f3f2f797a2be3..ddf62c084981ecf02491ea6b2817782dae050ce1 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -22,7 +22,6 @@ - #include - #include - --#include - #include - #include - -@@ -47,7 +46,7 @@ static const char * const bcm2708_compat[] = { - NULL - }; - --MACHINE_START(BCM2708, "BCM2708") -+DT_MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ - .init_machine = bcm2708_init, - .reserve = board_reserve, -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 39d304327bc84899a521aaeed8c1edd83c26d2d6..9cf36118e57b3c362de9adcf089425023d4a601d 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -22,7 +22,6 @@ - #include - #include - --#include - #include - #include - -@@ -44,18 +43,10 @@ static void __init board_reserve(void) - - static const char * const bcm2709_compat[] = { - "brcm,bcm2709", -- "brcm,bcm2708", /* Could use bcm2708 in a pinch */ - NULL - }; - --MACHINE_START(BCM2709, "BCM2709") -- /* Maintainer: Broadcom Europe Ltd. */ -- .init_machine = bcm2709_init, -- .reserve = board_reserve, -- .dt_compat = bcm2709_compat, --MACHINE_END -- --MACHINE_START(BCM2708, "BCM2709") -+DT_MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ - .init_machine = bcm2709_init, - .reserve = board_reserve, -diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index b52d949ee91d96eb7672fbbb4969bfa1e7afc376..2ed1b8a922ed02b9e3545991873af77b4c1bf871 100644 ---- a/arch/arm/tools/mach-types -+++ b/arch/arm/tools/mach-types -@@ -522,8 +522,6 @@ torbreck MACH_TORBRECK TORBRECK 3090 - prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 - paz00 MACH_PAZ00 PAZ00 3128 - acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 --bcm2708 MACH_BCM2708 BCM2708 3138 --bcm2709 MACH_BCM2709 BCM2709 3139 - ag5evm MACH_AG5EVM AG5EVM 3189 - ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 - wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 - -From fde57b59c0e15f0416bc962bb82988aba3715acf Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 11 Oct 2016 17:48:07 +0100 -Subject: [PATCH 119/208] Use DT rather than modules params for board rev and - serial - ---- - arch/arm/mach-bcm2708/bcm2708.c | 18 +++++++++--------- - arch/arm/mach-bcm2709/bcm2709.c | 19 +++++++++---------- - 2 files changed, 18 insertions(+), 19 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index ddf62c084981ecf02491ea6b2817782dae050ce1..06b078569006a6d821d3d049f1a0fa5783c1c1b3 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -18,22 +18,24 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - --#include --#include -+#include - #include - - #include - #include - --/* command line parameters */ --static unsigned boardrev, serial; -- - static void __init bcm2708_init(void) - { -+ struct device_node *np = of_find_node_by_path("/system"); -+ u32 val; -+ u64 val64; -+ - vc_cma_early_init(); - -- system_rev = boardrev; -- system_serial_low = serial; -+ if (!of_property_read_u32(np, "linux,revision", &val)) -+ system_rev = val; -+ if (!of_property_read_u64(np, "linux,serial", &val64)) -+ system_serial_low = val64; - } - - static void __init board_reserve(void) -@@ -53,5 +55,3 @@ DT_MACHINE_START(BCM2708, "BCM2708") - .dt_compat = bcm2708_compat, - MACHINE_END - --module_param(boardrev, uint, 0644); --module_param(serial, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 9cf36118e57b3c362de9adcf089425023d4a601d..9f113736627175bdcb362e0eda469e09e3d5f2e0 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -18,22 +18,24 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - --#include --#include -+#include - #include - - #include - #include - --/* command line parameters */ --static unsigned boardrev, serial; -- - static void __init bcm2709_init(void) - { -+ struct device_node *np = of_find_node_by_path("/system"); -+ u32 val; -+ u64 val64; -+ - vc_cma_early_init(); - -- system_rev = boardrev; -- system_serial_low = serial; -+ if (!of_property_read_u32(np, "linux,revision", &val)) -+ system_rev = val; -+ if (!of_property_read_u64(np, "linux,serial", &val64)) -+ system_serial_low = val64; - } - - static void __init board_reserve(void) -@@ -52,6 +54,3 @@ DT_MACHINE_START(BCM2709, "BCM2709") - .reserve = board_reserve, - .dt_compat = bcm2709_compat, - MACHINE_END -- --module_param(boardrev, uint, 0644); --module_param(serial, uint, 0644); - -From c687c89cf84f71ee3e67c3b965106b5f4d9aa774 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 2 Sep 2016 16:45:27 +0100 -Subject: [PATCH 120/208] Register the clocks early during the boot process, so - that special/critical clocks can get enabled early on in the boot process - avoiding the risk of disabling a clock, pll_divider or pll when a claiming - driver fails to install propperly - maybe it needs to defer. - -Signed-off-by: Martin Sperl ---- - drivers/clk/bcm/clk-bcm2835.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index fbf616021704178a9d007219a0ea2a9f1704f0a6..cbbc8d4ddcffc797268c0ecb6477005fa14e228b 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1891,8 +1891,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - if (ret) - return ret; - -- return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, -- &cprman->onecell); -+ ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, -+ &cprman->onecell); -+ if (ret) -+ return ret; -+ -+ /* note that we have registered all the clocks */ -+ dev_dbg(dev, "registered %d clocks\n", asize); -+ -+ return 0; - } - - static const struct of_device_id bcm2835_clk_of_match[] = { -@@ -1909,7 +1916,11 @@ static struct platform_driver bcm2835_clk_driver = { - .probe = bcm2835_clk_probe, - }; - --builtin_platform_driver(bcm2835_clk_driver); -+static int __init __bcm2835_clk_driver_init(void) -+{ -+ return platform_driver_register(&bcm2835_clk_driver); -+} -+core_initcall(__bcm2835_clk_driver_init); - - MODULE_AUTHOR("Eric Anholt "); - MODULE_DESCRIPTION("BCM2835 clock driver"); - -From fd03919a330c5acea88972ccb762f5786b9b13f2 Mon Sep 17 00:00:00 2001 -From: Scott Ellis -Date: Tue, 27 Sep 2016 04:29:00 -0400 -Subject: [PATCH 121/208] Add Adafruit pitft35 touchscreen support (#1657) - -The dts comes from the Adafruit repository - - https://github.com/adafruit/Adafruit-Pi-Kernel-o-Matic/blob/pitft/pitft35r-overlay.dts - -Reformatted slightly to match conventions in the pitft28-resistive-overlay. - -Signed-off-by: Scott Ellis ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 12 ++ - .../dts/overlays/pitft35-resistive-overlay.dts | 121 +++++++++++++++++++++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 5 files changed, 136 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index b6ed1a3c06a7a67d1dd79bb7e55421d8eccba492..6179b21af2fa8ec63429c3d379fc46085681dc7e 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -64,6 +64,7 @@ dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft35-resistive.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pps-gpio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pwm.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pwm-2chan.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 1ebb94c005d68b17792f95bd9792a08679298b26..2252ab9f5bab5dd40be9ebefa8e37c5bfb07d00f 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -848,6 +848,18 @@ Params: speed Display SPI bus speed - debug Debug output level {0-7} - - -+Name: pitft35-resistive -+Info: Adafruit PiTFT 3.5" resistive touch screen -+Load: dtoverlay=pitft35-resistive,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ - Name: pps-gpio - Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). - Load: dtoverlay=pps-gpio,= -diff --git a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..25cb5cc9576dadc3539f4ea3c9507c592ccac9d6 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts -@@ -0,0 +1,121 @@ -+/* -+ * Device Tree overlay for Adafruit PiTFT 3.5" resistive touch screen -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; @@ -140505,441 +116625,11 @@ index 0000000000000000000000000000000000000000..25cb5cc9576dadc3539f4ea3c9507c59 + fragment@2 { + target = <&spidev1>; + __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target = <&gpio>; -+ __overlay__ { -+ pitft_pins: pitft_pins { -+ brcm,pins = <24 25>; -+ brcm,function = <0 1>; /* in out */ -+ brcm,pull = <2 0>; /* pullup none */ -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pitft: pitft@0{ -+ compatible = "himax,hx8357d"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pitft_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <90>; -+ fps = <25>; -+ bgr; -+ buswidth = <8>; -+ dc-gpios = <&gpio 25 0>; -+ debug = <0>; -+ }; -+ -+ pitft_ts@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stmpe610"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -+ interrupts = <24 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ interrupt-controller; -+ -+ stmpe_touchscreen { -+ compatible = "st,stmpe-ts"; -+ st,sample-time = <4>; -+ st,mod-12b = <1>; -+ st,ref-sel = <0>; -+ st,adc-freq = <2>; -+ st,ave-ctrl = <3>; -+ st,touch-det-delay = <4>; -+ st,settling = <2>; -+ st,fraction-z = <7>; -+ st,i-drive = <0>; -+ }; -+ -+ stmpe_gpio: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ /* -+ * only GPIO2 is wired/available -+ * and it is wired to the backlight -+ */ -+ st,norequest-mask = <0x7b>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@5 { -+ target-path = "/soc"; -+ __overlay__ { -+ backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&stmpe_gpio 2 0>; -+ default-on; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&pitft>,"spi-max-frequency:0"; -+ rotate = <&pitft>,"rotate:0"; -+ fps = <&pitft>,"fps:0"; -+ debug = <&pitft>,"debug:0"; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index aa708638cc6f3bceb189c2deef7307252901291f..aa57989600923198d4bfb913c4d2e8a565a93e07 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1111,6 +1111,7 @@ CONFIG_FB_TFT_BD663474=m - CONFIG_FB_TFT_HX8340BN=m - CONFIG_FB_TFT_HX8347D=m - CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m - CONFIG_FB_TFT_ILI9163=m - CONFIG_FB_TFT_ILI9320=m - CONFIG_FB_TFT_ILI9325=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 952104ab6c4cd0e9d8f7bd5f2fba7a72da75424e..26fa6c2b6b6d745178e666465ba226afee701ab1 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1117,6 +1117,7 @@ CONFIG_FB_TFT_BD663474=m - CONFIG_FB_TFT_HX8340BN=m - CONFIG_FB_TFT_HX8347D=m - CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m - CONFIG_FB_TFT_ILI9163=m - CONFIG_FB_TFT_ILI9320=m - CONFIG_FB_TFT_ILI9325=m - -From 0a83e0533ed80a1ae7f8dbbd570a2c245c9432de Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 10 Oct 2016 15:06:20 +0100 -Subject: [PATCH 122/208] BCM270X_DT: Update CM3 to use sdhost interface - ---- - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index b5a5ae7747455438f8eabd28e8c11c6aeb0c1ecc..d13e3d4dac4e198c8cac451e3f64ef687e2ace1b 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -8,10 +8,9 @@ - }; - - &gpio { -- -- mmc_pins: mmc_pins { -+ sdhost_pins: sdhost_pins { - brcm,pins = <48 49 50 51 52 53>; -- brcm,function = <7>; /* alt3 */ -+ brcm,function = <4>; /* alt0 */ - brcm,pull = <0 2 2 2 2 2>; - }; - -@@ -46,9 +45,9 @@ - }; - }; - --&mmc { -+&sdhost { - pinctrl-names = "default"; -- pinctrl-0 = <&mmc_pins>; -+ pinctrl-0 = <&sdhost_pins>; - non-removable; - bus-width = <4>; - status = "okay"; - -From e729cf9692cd384eb83f1291714965624604b8c0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 12 Oct 2016 15:10:14 +0100 -Subject: [PATCH 123/208] mmc: info (not err) msg on clock probe deferral - ---- - drivers/mmc/host/bcm2835-mmc.c | 5 ++++- - drivers/mmc/host/bcm2835-sdhost.c | 5 ++++- - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index ceb37930e167f47c9c848e8de757ad098eec9a19..4fe8d1fe44578fbefcd48f8c327ba3d03f3d0a2a 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -1459,8 +1459,11 @@ static int bcm2835_mmc_probe(struct platform_device *pdev) - #endif - clk = devm_clk_get(dev, NULL); - if (IS_ERR(clk)) { -- dev_err(dev, "could not get clk\n"); - ret = PTR_ERR(clk); -+ if (ret == -EPROBE_DEFER) -+ dev_info(dev, "could not get clk, deferring probe\n"); -+ else -+ dev_err(dev, "could not get clk\n"); - goto err; - } - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 23dea422182534e248435aeaee3ecb5da69c0d33..9e55d5ac08b5809c40fe391ae6e685fdb4d62df7 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -2089,8 +2089,11 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - - clk = devm_clk_get(dev, NULL); - if (IS_ERR(clk)) { -- dev_err(dev, "could not get clk\n"); - ret = PTR_ERR(clk); -+ if (ret == -EPROBE_DEFER) -+ dev_info(dev, "could not get clk, deferring probe\n"); -+ else -+ dev_err(dev, "could not get clk\n"); - goto err; - } - - -From 72b5f15453aca3a241e4fdc0751187f51d8d3f8e Mon Sep 17 00:00:00 2001 -From: Electron752 -Date: Sat, 15 Oct 2016 11:49:52 -0700 -Subject: [PATCH 124/208] ARM64: Modify default config to get raspbian to boot - (#1686) - -1. Enable emulation of deprecated instructions. -2. Enable ARM 8.1 and 8.2 features which are not detected at runtime. -3. Switch the default governer to powersave. -4. Include the watchdog timer driver in the kernel image rather then a module. - -Tested with raspbian-jessie 2016-09-23. ---- - arch/arm64/configs/bcmrpi3_defconfig | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -index 1fcde8c1329bbfd329245a8bb17691999882ccfc..d7406f5a4620151044b8f716b4d10bb818648e06 100644 ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -27,19 +27,23 @@ CONFIG_ARM64_VA_BITS=39 - CONFIG_SCHED_MC=y - CONFIG_NR_CPUS=4 - CONFIG_HOTPLUG_CPU=y -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y - - # - # ARMv8.1 architectural features - # --CONFIG_ARM64_HW_AFDBM=n --CONFIG_ARM64_PAN=n --CONFIG_ARM64_LSE_ATOMICS=n --CONFIG_ARM64_VHE=n -+CONFIG_ARM64_HW_AFDBM=y -+CONFIG_ARM64_PAN=y -+CONFIG_ARM64_LSE_ATOMICS=y -+CONFIG_ARM64_VHE=y - - # - # ARMv8.2 architectural features - # --CONFIG_ARM64_UAO=n -+CONFIG_ARM64_UAO=y - CONFIG_ARM64_MODULE_CMODEL_LARGE=n - CONFIG_RANDOMIZE_BASE=n - -@@ -98,7 +102,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_CPU_FREQ=y --CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y -@@ -687,7 +691,7 @@ CONFIG_SENSORS_SHTC1=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y --CONFIG_BCM2835_WDT=m -+CONFIG_BCM2835_WDT=y - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y - -From 058069f821d2a205b7e0d8b9741aee5a19e71814 Mon Sep 17 00:00:00 2001 -From: gtrainavicius -Date: Sun, 23 Oct 2016 12:06:53 +0300 -Subject: [PATCH 125/208] Support for Blokas Labs pisound board - ---- - .../devicetree/bindings/vendor-prefixes.txt | 1 + - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 + - arch/arm/boot/dts/overlays/pisound-overlay.dts | 114 +++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - sound/soc/bcm/Kconfig | 6 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/pisound.c | 987 +++++++++++++++++++++ - 9 files changed, 1119 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/pisound-overlay.dts - create mode 100644 sound/soc/bcm/pisound.c - -diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt -index 1992aa97d45ac8b0a9cfaefbaf5de40780c601ad..562cc57b75227e9dba77af035d26926b0ce8894e 100644 ---- a/Documentation/devicetree/bindings/vendor-prefixes.txt -+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt -@@ -39,6 +39,7 @@ auo AU Optronics Corporation - avago Avago Technologies - avic Shanghai AVIC Optoelectronics Co., Ltd. - axis Axis Communications AB -+blokaslabs Vilniaus Blokas UAB - boe BOE Technology Group Co., Ltd. - bosch Bosch Sensortec GmbH - boundary Boundary Devices Inc. -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 6179b21af2fa8ec63429c3d379fc46085681dc7e..555bb5050aaf8464e209f35c50dc1f5c0295e585 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -61,6 +61,7 @@ dtbo-$(RPI_DT_OVERLAYS) += pi3-disable-bt.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pi3-miniuart-bt.dtbo - dtbo-$(RPI_DT_OVERLAYS) += piscreen.dtbo - dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pisound.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 2252ab9f5bab5dd40be9ebefa8e37c5bfb07d00f..4f9f0ac43f4fe2cb9376fff5a214ffdaf8179591 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -802,6 +802,12 @@ Params: speed Display SPI bus speed - xohms Touchpanel sensitivity (X-plate resistance) - - -+Name: pisound -+Info: Configures the Blokas Labs pisound card -+Load: dtoverlay=pisound -+Params: -+ -+ - Name: pitft22 - Info: Adafruit PiTFT 2.2" screen - Load: dtoverlay=pitft22,= -diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae26019055 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts -@@ -0,0 +1,114 @@ -+/* -+ * pisound Linux kernel module. -+ * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound -+ * -+ * 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; version 2 of the -+ * License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+#include -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "blokaslabs,pisound"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ -+ pinctrl-0 = <&pisound_button_pins>; -+ -+ osr-gpios = -+ <&gpio 13 GPIO_ACTIVE_HIGH>, -+ <&gpio 26 GPIO_ACTIVE_HIGH>, -+ <&gpio 16 GPIO_ACTIVE_HIGH>; -+ -+ reset-gpios = -+ <&gpio 12 GPIO_ACTIVE_HIGH>, -+ <&gpio 24 GPIO_ACTIVE_HIGH>; -+ -+ data_available-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; -+ -+ button-gpios = <&gpio 17 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pisound_button_pins>; -+ -+ pisound_button_pins: pisound_button_pins { -+ brcm,pins = <17>; -+ brcm,function = <0>; // Input -+ brcm,pull = <2>; // Pull-Up -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2s>; -+ __overlay__ { + status = "okay"; + }; + }; + + fragment@3 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@5 { + target = <&spi0>; + __overlay__ { + #address-cells = <1>; @@ -140954,36 +116644,90 @@ index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae + }; + }; + }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index aa57989600923198d4bfb913c4d2e8a565a93e07..40841d8421e44f8863cb23c53802388b502e61a3 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -875,6 +875,7 @@ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 26fa6c2b6b6d745178e666465ba226afee701ab1..46b91678fef473334b9417409fd1c529c0415977 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -866,6 +866,7 @@ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m ++ ++ fragment@4 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@5 { + target = <&sound>; + __overlay__ { + compatible = "blokaslabs,pisound"; +@@ -49,7 +97,7 @@ + }; + }; + +- fragment@1 { ++ fragment@6 { + target = <&gpio>; + __overlay__ { + pinctrl-names = "default"; +@@ -63,52 +111,10 @@ + }; + }; + +- fragment@2 { ++ fragment@7 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; +- +- fragment@3 { +- target-path = "/"; +- __overlay__ { +- pcm5102a-codec { +- #sound-dai-cells = <0>; +- compatible = "ti,pcm5102a"; +- status = "okay"; +- }; +- }; +- }; +- +- fragment@4 { +- target = <&spi0>; +- __overlay__ { +- status = "okay"; +- +- spidev@0{ +- status = "disabled"; +- }; +- +- spidev@1{ +- status = "okay"; +- }; +- }; +- }; +- +- fragment@5 { +- target = <&spi0>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- +- pisound_spi: pisound_spi@0{ +- compatible = "blokaslabs,pisound-spi"; +- reg = <0>; +- pinctrl-names = "default"; +- pinctrl-0 = <&spi0_pins>; +- spi-max-frequency = <1000000>; +- }; +- }; +- }; + }; diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 4ccaba67a887432afe7f527569c4e2865925734b..aed7b47d8736ea3fb1810b0c77916855082f3b2d 100644 +index 4f0330a6c06115f077938cba3dc744d4ae10f056..a0ef6a028136beb27ed13a4136712a70a60f2966 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -130,3 +130,9 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC +@@ -123,3 +123,9 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC select SND_SOC_PCM512x_I2C help Say Y or M if you want to add support for Allo Piano DAC. @@ -140994,10 +116738,10 @@ index 4ccaba67a887432afe7f527569c4e2865925734b..aed7b47d8736ea3fb1810b0c77916855 + help + Say Y or M if you want to add support for Blokas Labs pisound. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index b9f98f0bcf3ee0d6b490e1bb185ba0de8f0f9701..5fb380a2f8a87ed5e67786f5afb31682128b70ed 100644 +index 4b94a42efecaee41df37f3c59fddefa5fe78521c..f720a3d3b5832844ee6d0558317c728f00c40b65 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -25,6 +25,7 @@ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o +@@ -24,6 +24,7 @@ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o snd-soc-dionaudio-loco-objs := dionaudio_loco.o snd-soc-allo-piano-dac-objs := allo-piano-dac.o @@ -141005,17 +116749,17 @@ index b9f98f0bcf3ee0d6b490e1bb185ba0de8f0f9701..5fb380a2f8a87ed5e67786f5afb31682 obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -42,3 +43,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundca +@@ -40,3 +41,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundca obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o +obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o diff --git a/sound/soc/bcm/pisound.c b/sound/soc/bcm/pisound.c new file mode 100644 -index 0000000000000000000000000000000000000000..b156e5793e4c482385dedafd85bbf190acc8162b +index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb2310b3b94d0 --- /dev/null +++ b/sound/soc/bcm/pisound.c -@@ -0,0 +1,987 @@ +@@ -0,0 +1,989 @@ +/* + * pisound Linux kernel module. + * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound @@ -141972,6 +117716,8 @@ index 0000000000000000000000000000000000000000..b156e5793e4c482385dedafd85bbf190 + +static int pisnd_remove(struct platform_device *pdev) +{ ++ printi("Unloading.\n"); ++ + if (pisnd_kobj) { + kobject_put(pisnd_kobj); + pisnd_kobj = NULL; @@ -142004,4374 +117750,339 @@ index 0000000000000000000000000000000000000000..b156e5793e4c482385dedafd85bbf190 +MODULE_DESCRIPTION("ASoC Driver for pisound, http://blokas.io/pisound"); +MODULE_LICENSE("GPL v2"); -From 5c4d2949f96142001b815fb44e7a6aedec2d83c2 Mon Sep 17 00:00:00 2001 -From: Giedrius Trainavicius -Date: Tue, 25 Oct 2016 01:47:20 +0300 -Subject: [PATCH 126/208] FIXUP: pisound: Fix a warning in DEBUG builds +From 98377297665ab6bf02efbf28cc1f1d0821d840c9 Mon Sep 17 00:00:00 2001 +From: P33M +Date: Wed, 21 Oct 2015 14:55:21 +0100 +Subject: [PATCH 085/111] rpi_display: add backlight driver and overlay -Also change a macro that enables debug level printing from DEBUG to -PISOUND_DEBUG. +Add a mailbox-driven backlight controller for the Raspberry Pi DSI +touchscreen display. Requires updated GPU firmware to recognise the +mailbox request. + +Signed-off-by: Gordon Hollingworth --- - sound/soc/bcm/pisound.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) + drivers/video/backlight/Kconfig | 6 ++ + drivers/video/backlight/Makefile | 1 + + drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ + 3 files changed, 126 insertions(+) + create mode 100644 drivers/video/backlight/rpi_backlight.c -diff --git a/sound/soc/bcm/pisound.c b/sound/soc/bcm/pisound.c -index b156e5793e4c482385dedafd85bbf190acc8162b..a3cd089a01447bdb6741ed6bba3b21d40061d7df 100644 ---- a/sound/soc/bcm/pisound.c -+++ b/sound/soc/bcm/pisound.c -@@ -55,7 +55,7 @@ static void pisnd_midi_uninit(void); - - #define PISOUND_LOG_PREFIX "pisound: " - --#ifdef DEBUG -+#ifdef PISOUND_DEBUG - # define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__) - #else - # define printd(...) do {} while (0) -@@ -119,7 +119,7 @@ static void pisnd_midi_recv_callback(void *substream) - while ((n = pisnd_spi_recv(data, sizeof(data)))) { - int res = snd_rawmidi_receive(substream, data, n); - (void)res; -- printd("midi recv 0x%02x, res = %d\n", data, res); -+ printd("midi recv %u bytes, res = %d\n", n, res); - } - } - - -From b50c2a9e07bcdf93ca4110cdba3792a9bfb93167 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:25:41 +0200 -Subject: [PATCH 127/208] bcm270x: Remove bcm2708_reboot_mode parameter -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This isn't used anymore now that the watchdog driver does restart/poweroff. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/kernel/process.c | 10 ---------- - 1 file changed, 10 deletions(-) - -diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 0a0332cb13a7475ee0c4d75a97685b7de6475c95..612eb530f33fcd19bc4539facb26fc30a2583979 100644 ---- a/arch/arm/kernel/process.c -+++ b/arch/arm/kernel/process.c -@@ -91,16 +91,6 @@ void arch_cpu_idle_exit(void) - ledtrig_cpu(CPU_LED_IDLE_END); - } - --char bcm2708_reboot_mode = 'h'; -- --int __init reboot_setup(char *str) --{ -- bcm2708_reboot_mode = str[0]; -- return 1; --} -- --__setup("reboot=", reboot_setup); -- - void __show_regs(struct pt_regs *regs) - { - unsigned long flags; - -From 7c233a345d15064604d3194b35b0aa56ea2f9b02 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 15:54:41 +0200 -Subject: [PATCH 128/208] bcm270x: Remove NEED_MACH_IO_H -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -NEED_MACH_IO_H isn't necessary since we don't have -PC card/PCI/ISA IO space. -The __io macro is only used in the {in,out}[bwl] macros. - -arch/arm/include/asm/io.h will give these defaults now: - -define __io(a) __typesafe_io((a) & IO_SPACE_LIMIT) -define IO_SPACE_LIMIT ((resource_size_t)0) - -This is the same as ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 1 - - arch/arm/mach-bcm2708/Kconfig | 1 - - arch/arm/mach-bcm2708/include/mach/io.h | 27 --------------------------- - arch/arm/mach-bcm2709/include/mach/io.h | 27 --------------------------- - 4 files changed, 56 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/io.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/io.h - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 018ee76322d9e013598887c50ebea9628ecb9ee3..962d632c2af85c752b848c3ba7a8f3f3ba32c222 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -355,7 +355,6 @@ config ARCH_BCM2709 - select MIGHT_HAVE_CACHE_L2X0 - select HAVE_SCHED_CLOCK - select NEED_MACH_MEMORY_H -- select NEED_MACH_IO_H - select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 6eabe844767f7fa9bdc09a897bab83e5149fc0dd..e93df839ab8c6cddb8d784d0af3b827276ba9120 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -4,7 +4,6 @@ menu "Broadcom BCM2708 Implementations" - config MACH_BCM2708 - bool "Broadcom BCM2708 Development Platform" - select NEED_MACH_MEMORY_H -- select NEED_MACH_IO_H - select CPU_V6 - select USE_OF - select ARCH_REQUIRE_GPIOLIB -diff --git a/arch/arm/mach-bcm2708/include/mach/io.h b/arch/arm/mach-bcm2708/include/mach/io.h -deleted file mode 100644 -index e6eb84d71006db417dbd0afc4d08d3b19b09a619..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/io.h -+++ /dev/null -@@ -1,27 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/io.h -- * -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARM_ARCH_IO_H --#define __ASM_ARM_ARCH_IO_H -- --#define IO_SPACE_LIMIT 0xffffffff -- --#define __io(a) __typesafe_io(a) -- --#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/io.h b/arch/arm/mach-bcm2709/include/mach/io.h -deleted file mode 100644 -index e6eb84d71006db417dbd0afc4d08d3b19b09a619..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/io.h -+++ /dev/null -@@ -1,27 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/io.h -- * -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARM_ARCH_IO_H --#define __ASM_ARM_ARCH_IO_H -- --#define IO_SPACE_LIMIT 0xffffffff -- --#define __io(a) __typesafe_io(a) -- --#endif - -From f30338340fc8707bd44a054991d9bba94297ac80 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:01:01 +0200 -Subject: [PATCH 129/208] dwc_otg: Pass struct device to dma_alloc*() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This makes it possible to get the bus address from Device Tree. - -Signed-off-by: Noralf Trønnes ---- - .../usb/host/dwc_common_port/dwc_common_linux.c | 19 +---- - drivers/usb/host/dwc_common_port/dwc_os.h | 18 ++--- - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 13 ++-- - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 6 ++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 23 ++++-- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 +- - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 3 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 87 +++++++++++++--------- - drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 7 ++ - drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 3 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 3 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 2 +- - 12 files changed, 105 insertions(+), 81 deletions(-) - -diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -index 46646841dda96fb2bed01152de552ccac5f0e5e4..0d641e6da24beeb07109e23847d1d6e81dc7d4ea 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c -+++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -@@ -337,27 +337,12 @@ void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) - - void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) - { --#ifdef xxCOSIM /* Only works for 32-bit cosim */ -- void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); --#else -- void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); --#endif -- if (!buf) { -- return NULL; -- } -- -- memset(buf, 0, (size_t)size); -- return buf; -+ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_KERNEL | GFP_DMA32); - } - - void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) - { -- void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); -- if (!buf) { -- return NULL; -- } -- memset(buf, 0, (size_t)size); -- return buf; -+ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_ATOMIC); - } - - void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) -diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h -index a2bbe232ffc3b58001d026864c3019792cdf5efa..9a86d299403bd1dfdcdb6532fad702b2b65138d7 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_os.h -+++ b/drivers/usb/host/dwc_common_port/dwc_os.h -@@ -675,9 +675,9 @@ extern void __DWC_FREE(void *mem_ctx, void *addr); - #define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) - - # ifdef DWC_LINUX --#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) --#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) --#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) -+#define DWC_DMA_ALLOC(_dev, _size_, _dma_) __DWC_DMA_ALLOC(_dev, _size_, _dma_) -+#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) __DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) -+#define DWC_DMA_FREE(_dev, _size_,_virt_, _dma_) __DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) - # endif - - # if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -@@ -708,12 +708,12 @@ extern void dwc_memory_debug_report(void); - #define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) - - # ifdef DWC_LINUX --#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ -- _dma_, __func__, __LINE__) --#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ -- _dma_, __func__, __LINE__) --#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ -- _virt_, _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC(_dev, _size_, _dma_) \ -+ dwc_dma_alloc_debug(_dev, _size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) \ -+ dwc_dma_alloc_atomic_debug(_dev, _size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) \ -+ dwc_dma_free_debug(_dev, _size_, _virt_, _dma_, __func__, __LINE__) - # endif - - # if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -index 135b611abe08e141c937612ab7baada6b13113fc..027414bb2bf9fc3f3652407724187f3c6dc5ff68 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -884,6 +884,7 @@ void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num) - */ - static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) - { -+ struct device *dev = dwc_otg_hcd_to_dev(dwc_otg_hcd); - int i; - - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); -@@ -916,7 +917,7 @@ static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) - - if (dwc_otg_hcd->core_if->dma_enable) { - if (dwc_otg_hcd->status_buf_dma) { -- DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ DWC_DMA_FREE(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, - dwc_otg_hcd->status_buf, - dwc_otg_hcd->status_buf_dma); - } -@@ -946,6 +947,7 @@ int init_hcd_usecs(dwc_otg_hcd_t *_hcd); - - int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - int retval = 0; - int num_channels; - int i; -@@ -1041,7 +1043,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - * for use as transaction bounce buffers in a 2-D array. Our access into this chunk is done by some - * moderately readable array casts. - */ -- hcd->fiq_dmab = DWC_DMA_ALLOC((sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); -+ hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); - DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d", - (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base, - sizeof(struct fiq_dma_channel) * num_channels); -@@ -1092,7 +1094,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - */ - if (hcd->core_if->dma_enable) { - hcd->status_buf = -- DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ DWC_DMA_ALLOC(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, - &hcd->status_buf_dma); - } else { - hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); -@@ -1187,6 +1189,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - uint32_t intr_enable; - unsigned long flags; - gintmsk_data_t gintmsk = { .d32 = 0, }; -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - - qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); - -@@ -1381,7 +1384,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - buf_size = 4096; - } - if (!qh->dw_align_buf) { -- qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, -+ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(dev, buf_size, - &qh->dw_align_buf_dma); - if (!qh->dw_align_buf) { - DWC_ERROR -@@ -1432,7 +1435,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); - } -- -+ - local_irq_restore(flags); - hc->qh = qh; - } -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -index 43dbed9fddbf5491bab33cc6e551b99ca8dce7dc..4539cd7b802d3e49ac9a6cb3f1d88b475a1ace16 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -41,6 +41,7 @@ - #include "dwc_list.h" - #include "dwc_otg_cil.h" - #include "dwc_otg_fiq_fsm.h" -+#include "dwc_otg_driver.h" - - - /** -@@ -613,6 +614,11 @@ struct dwc_otg_hcd { - #endif - }; - -+static inline struct device *dwc_otg_hcd_to_dev(struct dwc_otg_hcd *hcd) -+{ -+ return &hcd->otg_dev->os_dep.platformdev->dev; -+} -+ - /** @name Transaction Execution Functions */ - /** @{ */ - extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -index ee920c4d8f4a2980e4406cb878b81d809fec4e70..126e99ab2fc43f11d89a08ff0476181ead84029f 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -75,12 +75,12 @@ static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) - : qh->interval); - } - --static int desc_list_alloc(dwc_otg_qh_t * qh) -+static int desc_list_alloc(struct device *dev, dwc_otg_qh_t * qh) - { - int retval = 0; - - qh->desc_list = (dwc_otg_host_dma_desc_t *) -- DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), -+ DWC_DMA_ALLOC(dev, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), - &qh->desc_list_dma); - - if (!qh->desc_list) { -@@ -106,10 +106,10 @@ static int desc_list_alloc(dwc_otg_qh_t * qh) - - } - --static void desc_list_free(dwc_otg_qh_t * qh) -+static void desc_list_free(struct device *dev, dwc_otg_qh_t * qh) - { - if (qh->desc_list) { -- DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, -+ DWC_DMA_FREE(dev, max_desc_num(qh), qh->desc_list, - qh->desc_list_dma); - qh->desc_list = NULL; - } -@@ -122,11 +122,13 @@ static void desc_list_free(dwc_otg_qh_t * qh) - - static int frame_list_alloc(dwc_otg_hcd_t * hcd) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - int retval = 0; -+ - if (hcd->frame_list) - return 0; - -- hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, -+ hcd->frame_list = DWC_DMA_ALLOC(dev, 4 * MAX_FRLIST_EN_NUM, - &hcd->frame_list_dma); - if (!hcd->frame_list) { - retval = -DWC_E_NO_MEMORY; -@@ -140,10 +142,12 @@ static int frame_list_alloc(dwc_otg_hcd_t * hcd) - - static void frame_list_free(dwc_otg_hcd_t * hcd) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); -+ - if (!hcd->frame_list) - return; - -- DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); -+ DWC_DMA_FREE(dev, 4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); - hcd->frame_list = NULL; - } - -@@ -321,6 +325,7 @@ static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - int retval = 0; - - if (qh->do_split) { -@@ -328,7 +333,7 @@ int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - return -1; - } - -- retval = desc_list_alloc(qh); -+ retval = desc_list_alloc(dev, qh); - - if ((retval == 0) - && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { -@@ -355,7 +360,9 @@ int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -- desc_list_free(qh); -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); -+ -+ desc_list_free(dev, qh); - - /* - * Channel still assigned due to some reasons. -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 2ceed4212980f04ad082e78851c6a7e83aee1443..74cd5fa54aed5241b61371477ef67d706477fd30 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -517,6 +517,7 @@ int hcd_init(dwc_bus_dev_t *_dev) - ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = - dwc_otg_hcd; - otg_dev->hcd = dwc_otg_hcd; -+ otg_dev->hcd->otg_dev = otg_dev; - - if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { - goto error2; -@@ -531,7 +532,6 @@ int hcd_init(dwc_bus_dev_t *_dev) - } - } - -- otg_dev->hcd->otg_dev = otg_dev; - hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -index 3b2a60763b92fb2e9261a8ade3d4b33e3896cd62..c2dff94e8e6edd22e4427aaa1eac7aad972cb6bd 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -59,6 +59,7 @@ void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - uint32_t buf_size = 0; - uint8_t *align_buf_virt = NULL; - dwc_dma_t align_buf_dma; -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - - /* Free each QTD in the QTD list */ - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -@@ -82,7 +83,7 @@ void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - DWC_FREE(qh); - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - if (align_buf_virt) -- DWC_DMA_FREE(buf_size, align_buf_virt, align_buf_dma); -+ DWC_DMA_FREE(dev, buf_size, align_buf_virt, align_buf_dma); - return; - } - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -index ae0c72d02d007d5e7ce0f2dfb79b35d3d7ef86b8..9dabbe5c9791c5296d1cc7b663afa6ec462173cb 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -@@ -237,20 +237,22 @@ static dwc_otg_cil_callbacks_t pcd_callbacks = { - * This function allocates a DMA Descriptor chain for the Endpoint - * buffer to be used for a transfer to/from the specified endpoint. - */ --dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, -+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(struct device *dev, -+ dwc_dma_t * dma_desc_addr, - uint32_t count) - { -- return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), -+ return DWC_DMA_ALLOC_ATOMIC(dev, count * sizeof(dwc_otg_dev_dma_desc_t), - dma_desc_addr); - } - - /** - * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. - */ --void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, -+void dwc_otg_ep_free_desc_chain(struct device *dev, -+ dwc_otg_dev_dma_desc_t * desc_addr, - uint32_t dma_desc_addr, uint32_t count) - { -- DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, -+ DWC_DMA_FREE(dev, count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, - dma_desc_addr); - } - -@@ -1105,8 +1107,10 @@ static void start_xfer_tasklet_func(void *data) - * This function initialized the PCD portion of the driver. - * - */ --dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) -+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev) - { -+ struct device *dev = &otg_dev->os_dep.platformdev->dev; -+ dwc_otg_core_if_t *core_if = otg_dev->core_if; - dwc_otg_pcd_t *pcd = NULL; - dwc_otg_dev_if_t *dev_if; - int i; -@@ -1163,7 +1167,7 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - */ - if (GET_CORE_IF(pcd)->dma_enable) { - pcd->setup_pkt = -- DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_ALLOC(dev, sizeof(*pcd->setup_pkt) * 5, - &pcd->setup_pkt_dma_handle); - if (pcd->setup_pkt == NULL) { - DWC_FREE(pcd); -@@ -1171,10 +1175,10 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - } - - pcd->status_buf = -- DWC_DMA_ALLOC(sizeof(uint16_t), -+ DWC_DMA_ALLOC(dev, sizeof(uint16_t), - &pcd->status_buf_dma_handle); - if (pcd->status_buf == NULL) { -- DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, - pcd->setup_pkt, pcd->setup_pkt_dma_handle); - DWC_FREE(pcd); - return NULL; -@@ -1182,17 +1186,17 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - - if (GET_CORE_IF(pcd)->dma_desc_enable) { - dev_if->setup_desc_addr[0] = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_setup_desc_addr[0], 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_setup_desc_addr[0], 1); - dev_if->setup_desc_addr[1] = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_setup_desc_addr[1], 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_setup_desc_addr[1], 1); - dev_if->in_desc_addr = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_in_desc_addr, 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_in_desc_addr, 1); - dev_if->out_desc_addr = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_out_desc_addr, 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_out_desc_addr, 1); - pcd->data_terminated = 0; - - if (dev_if->setup_desc_addr[0] == 0 -@@ -1201,26 +1205,26 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - || dev_if->out_desc_addr == 0) { - - if (dev_if->out_desc_addr) -- dwc_otg_ep_free_desc_chain -- (dev_if->out_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->out_desc_addr, - dev_if->dma_out_desc_addr, 1); - if (dev_if->in_desc_addr) -- dwc_otg_ep_free_desc_chain -- (dev_if->in_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->in_desc_addr, - dev_if->dma_in_desc_addr, 1); - if (dev_if->setup_desc_addr[1]) -- dwc_otg_ep_free_desc_chain -- (dev_if->setup_desc_addr[1], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[1], - dev_if->dma_setup_desc_addr[1], 1); - if (dev_if->setup_desc_addr[0]) -- dwc_otg_ep_free_desc_chain -- (dev_if->setup_desc_addr[0], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[0], - dev_if->dma_setup_desc_addr[0], 1); - -- DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, - pcd->setup_pkt, - pcd->setup_pkt_dma_handle); -- DWC_DMA_FREE(sizeof(*pcd->status_buf), -+ DWC_DMA_FREE(dev, sizeof(*pcd->status_buf), - pcd->status_buf, - pcd->status_buf_dma_handle); - -@@ -1302,7 +1306,9 @@ fail: - void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) - { - dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - int i; -+ - if (pcd->core_if->core_params->dev_out_nak) { - for (i = 0; i < MAX_EPS_CHANNELS; i++) { - DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); -@@ -1311,20 +1317,24 @@ void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) - } - - if (GET_CORE_IF(pcd)->dma_enable) { -- DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, -+ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, - pcd->setup_pkt_dma_handle); -- DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, -+ DWC_DMA_FREE(dev, sizeof(uint16_t), pcd->status_buf, - pcd->status_buf_dma_handle); - if (GET_CORE_IF(pcd)->dma_desc_enable) { -- dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[0], - dev_if->dma_setup_desc_addr - [0], 1); -- dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[1], - dev_if->dma_setup_desc_addr - [1], 1); -- dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->in_desc_addr, - dev_if->dma_in_desc_addr, 1); -- dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->out_desc_addr, - dev_if->dma_out_desc_addr, - 1); - } -@@ -1463,6 +1473,7 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; - int retval = 0; - int i, epcount; -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - - desc = (const usb_endpoint_descriptor_t *)ep_desc; - -@@ -1571,9 +1582,9 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - if (ep->dwc_ep.type != UE_ISOCHRONOUS) { - #endif - ep->dwc_ep.desc_addr = -- dwc_otg_ep_alloc_desc_chain(&ep-> -- dwc_ep.dma_desc_addr, -- MAX_DMA_DESC_CNT); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &ep->dwc_ep.dma_desc_addr, -+ MAX_DMA_DESC_CNT); - if (!ep->dwc_ep.desc_addr) { - DWC_WARN("%s, can't allocate DMA descriptor\n", - __func__); -@@ -1624,6 +1635,7 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; - gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; - fifosize_data_t dptxfsiz = {.d32 = 0 }; -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - - ep = get_ep_from_handle(pcd, ep_handle); - -@@ -1678,7 +1690,7 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - - /* Cannot call dma_free_coherent() with IRQs disabled */ - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -- dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, desc_addr, dma_desc_addr, - MAX_DMA_DESC_CNT); - - goto out_unlocked; -@@ -2079,6 +2091,7 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, - int zero, void *req_handle, int atomic_alloc) - { -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - dwc_irqflags_t flags; - dwc_otg_pcd_request_t *req; - dwc_otg_pcd_ep_t *ep; -@@ -2115,7 +2128,7 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - req->dw_align_buf = NULL; - if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable - && !GET_CORE_IF(pcd)->dma_desc_enable) -- req->dw_align_buf = DWC_DMA_ALLOC(buflen, -+ req->dw_align_buf = DWC_DMA_ALLOC(dev, buflen, - &req->dw_align_buf_dma); - DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -index 8ef7ba648ad92b9b7e141f22db2a0c2837ddcfa8..a70ebd049d2cca3bf988a1f809832eebede14f96 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -@@ -38,6 +38,8 @@ - #include "usb.h" - #include "dwc_otg_cil.h" - #include "dwc_otg_pcd_if.h" -+#include "dwc_otg_driver.h" -+ - struct cfiobject; - - /** -@@ -253,6 +255,11 @@ struct dwc_otg_pcd { - - }; - -+static inline struct device *dwc_otg_pcd_to_dev(struct dwc_otg_pcd *pcd) -+{ -+ return &pcd->otg_dev->os_dep.platformdev->dev; -+} -+ - //FIXME this functions should be static, and this prototypes should be removed - extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); - extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -index c8d2e0e0c99486558a4964a8c82de80c64b496b4..4c1d591fbc098b2f4a745669e4f243e068735b20 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -@@ -37,6 +37,7 @@ - - //#include "dwc_os.h" - #include "dwc_otg_core_if.h" -+#include "dwc_otg_driver.h" - - /** @file - * This file defines DWC_OTG PCD Core API. -@@ -139,7 +140,7 @@ struct dwc_otg_pcd_function_ops { - * - * @param core_if The DWC_OTG Core - */ --extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); -+extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev); - - /** Frees PCD allocated by dwc_otg_pcd_init - * -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -index c8590b527110753b8064d35fab4c34226d094f84..e55ea9c74be46167a41dc14a2d88a1228878b1bb 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -@@ -2144,6 +2144,7 @@ static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep) - static void complete_ep(dwc_otg_pcd_ep_t * ep) - { - dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); -+ struct device *dev = dwc_otg_pcd_to_dev(ep->pcd); - dwc_otg_dev_if_t *dev_if = core_if->dev_if; - dwc_otg_dev_in_ep_regs_t *in_ep_regs = - dev_if->in_ep_regs[ep->dwc_ep.num]; -@@ -2484,7 +2485,7 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - if (!ep->dwc_ep.is_in) { - dwc_memcpy(req->buf, req->dw_align_buf, req->length); - } -- DWC_DMA_FREE(req->length, req->dw_align_buf, -+ DWC_DMA_FREE(dev, req->length, req->dw_align_buf, - req->dw_align_buf_dma); - } - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -index 5624f32c9ea9117599df451af29fca2e3bca36de..50aaeacdd12fff93d7a9cf1c54612367406c6bee 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -1206,7 +1206,7 @@ int pcd_init(dwc_bus_dev_t *_dev) - - DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); - -- otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); -+ otg_dev->pcd = dwc_otg_pcd_init(otg_dev); - - if (!otg_dev->pcd) { - DWC_ERROR("dwc_otg_pcd_init failed\n"); - -From 27dc18be13e874cdbe167edb6c2929ab4d2c2e1a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:05:36 +0200 -Subject: [PATCH 130/208] mmc: bcm2835-sdhost: Pass struct device to - dma_alloc*() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This makes it possible to get the bus address from Device Tree. -At the same time move the call to log_init() after getting the clock -to avoid allocating twice due to deferred probing. - -Signed-off-by: Noralf Trønnes ---- - drivers/mmc/host/bcm2835-sdhost.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 9e55d5ac08b5809c40fe391ae6e685fdb4d62df7..a9bc79bfdbb71807819dfe2d8f1651445997f92a 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -235,10 +235,10 @@ static void __iomem *timer_base; - #define LOG_ENTRIES (256*1) - #define LOG_SIZE (sizeof(LOG_ENTRY_T)*LOG_ENTRIES) - --static void log_init(u32 bus_to_phys) -+static void log_init(struct device *dev, u32 bus_to_phys) - { - spin_lock_init(&log_lock); -- sdhost_log_buf = dma_zalloc_coherent(NULL, LOG_SIZE, &sdhost_log_addr, -+ sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr, - GFP_KERNEL); - if (sdhost_log_buf) { - pr_info("sdhost: log_buf @ %p (%x)\n", -@@ -2037,7 +2037,6 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - return -ENODEV; - } - host->bus_addr = be32_to_cpup(addr); -- log_init(iomem->start - host->bus_addr); - pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n", - (unsigned long)host->ioaddr, - (unsigned long)iomem->start, -@@ -2110,6 +2109,8 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - (unsigned long)host->max_clk, - (int)host->irq); - -+ log_init(dev, iomem->start - host->bus_addr); -+ - if (node) - mmc_of_parse(mmc); - else - -From 22d03d1b65d08b5ed7bea59d49f1a455a3636cd9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:16:48 +0200 -Subject: [PATCH 131/208] bcm270x: Drop NEED_MACH_MEMORY_H and use DT - dma-ranges -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Drop NEED_MACH_MEMORY_H and use dma-ranges from the Device Tree to -get the bus address, like ARCH_BCM2835 does. - -This means that we go from this: - -arch/arm/mach-bcm270x/include/mach/memory.h: - -define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) -define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) -define __pfn_to_bus(x) (__pfn_to_phys(x) + BUS_OFFSET) -define __bus_to_pfn(x) __phys_to_pfn((x) - BUS_OFFSET - -To this: - -arch/arm/include/asm/memory.h: - -define __virt_to_bus __virt_to_phys -define __bus_to_virt __phys_to_virt -define __pfn_to_bus(x) __pfn_to_phys(x) -define __bus_to_pfn(x) __phys_to_pfn(x) - -Drivers now have to use the DMA API to get to the bus address. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 2 - - arch/arm/boot/dts/bcm2708.dtsi | 3 -- - arch/arm/boot/dts/bcm2709.dtsi | 1 - - arch/arm/mach-bcm2708/Kconfig | 8 ---- - arch/arm/mach-bcm2708/include/mach/memory.h | 57 ----------------------------- - arch/arm/mach-bcm2709/Kconfig | 7 ---- - arch/arm/mach-bcm2709/include/mach/memory.h | 57 ----------------------------- - 7 files changed, 135 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 962d632c2af85c752b848c3ba7a8f3f3ba32c222..82cbd045d7894e1b75460021a862f8b56f5ec645 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -334,7 +334,6 @@ config ARCH_BCM2708 - select CLKSRC_OF if OF - select HAVE_SCHED_CLOCK - select NEED_MACH_GPIO_H -- select NEED_MACH_MEMORY_H - select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS -@@ -354,7 +353,6 @@ config ARCH_BCM2709 - select ARM_AMBA - select MIGHT_HAVE_CACHE_L2X0 - select HAVE_SCHED_CLOCK -- select NEED_MACH_MEMORY_H - select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 1bd2a707ef5c0d92f233296e6312916f5a550bd2..663843965027da5dbaefbec1285e275c56746367 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -7,9 +7,6 @@ - model = "BCM2708"; - - soc { -- ranges = <0x7e000000 0x20000000 0x01000000>; -- /delete-property/ dma-ranges; -- - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; - reg = <0x7e003000 0x1000>; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index 757d0053c1c07452babc63ca6ecd0a8f047b25dd..b1d82f9026d02e8b5371cbb4d8a144e67207a276 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -9,7 +9,6 @@ - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -- /delete-property/ dma-ranges; - - syscon@40000000 { - compatible = "brcm,bcm2836-arm-local", "syscon"; -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index e93df839ab8c6cddb8d784d0af3b827276ba9120..265c3fb90f3debfc439491a89346e4863edec427 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -3,7 +3,6 @@ menu "Broadcom BCM2708 Implementations" - - config MACH_BCM2708 - bool "Broadcom BCM2708 Development Platform" -- select NEED_MACH_MEMORY_H - select CPU_V6 - select USE_OF - select ARCH_REQUIRE_GPIOLIB -@@ -12,11 +11,4 @@ config MACH_BCM2708 - help - Include support for the Broadcom(R) BCM2708 platform. - --config BCM2708_NOL2CACHE -- bool "Videocore L2 cache disable" -- depends on MACH_BCM2708 -- default n -- help -- Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -- - endmenu -diff --git a/arch/arm/mach-bcm2708/include/mach/memory.h b/arch/arm/mach-bcm2708/include/mach/memory.h -deleted file mode 100644 -index 7548a52dcf84affa4d1b0667e5e2f89f591891b8..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/memory.h -+++ /dev/null -@@ -1,57 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/memory.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_MEMORY_H --#define __ASM_ARCH_MEMORY_H -- --/* Memory overview: -- -- [ARMcore] <--virtual addr--> -- [ARMmmu] <--physical addr--> -- [GERTmap] <--bus add--> -- [VCperiph] -- --*/ -- --/* -- * Physical DRAM offset. -- */ --#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) --#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -- --#ifdef CONFIG_BCM2708_NOL2CACHE -- #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ --#else -- #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ --#endif -- --/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -- * will provide the offset into this area as well as setting the bits that -- * stop the L1 and L2 cache from being used -- * -- * WARNING: this only works because the ARM is given memory at a fixed location -- * (ARMMEM_OFFSET) -- */ --#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) --#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) --#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) --#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) --#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -- --#endif -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -index 643b4b984512a5f2ae33cee9beffa70a53e005ff..41f407ac1db3a86e87941153c1832b9fce1ead5d 100644 ---- a/arch/arm/mach-bcm2709/Kconfig -+++ b/arch/arm/mach-bcm2709/Kconfig -@@ -6,11 +6,4 @@ config MACH_BCM2709 - help - Include support for the Broadcom(R) BCM2709 platform. - --config BCM2708_NOL2CACHE -- bool "Videocore L2 cache disable" -- depends on MACH_BCM2709 -- default y -- help -- Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -- - endmenu -diff --git a/arch/arm/mach-bcm2709/include/mach/memory.h b/arch/arm/mach-bcm2709/include/mach/memory.h -deleted file mode 100644 -index 7548a52dcf84affa4d1b0667e5e2f89f591891b8..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/memory.h -+++ /dev/null -@@ -1,57 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/memory.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_MEMORY_H --#define __ASM_ARCH_MEMORY_H -- --/* Memory overview: -- -- [ARMcore] <--virtual addr--> -- [ARMmmu] <--physical addr--> -- [GERTmap] <--bus add--> -- [VCperiph] -- --*/ -- --/* -- * Physical DRAM offset. -- */ --#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) --#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -- --#ifdef CONFIG_BCM2708_NOL2CACHE -- #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ --#else -- #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ --#endif -- --/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -- * will provide the offset into this area as well as setting the bits that -- * stop the L1 and L2 cache from being used -- * -- * WARNING: this only works because the ARM is given memory at a fixed location -- * (ARMMEM_OFFSET) -- */ --#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) --#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) --#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) --#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) --#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -- --#endif - -From 26802db0c398a49668f6d029b50f59876a6f25f6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 15:55:09 +0200 -Subject: [PATCH 132/208] dts: Remove bcm2835-rpi-cm.dts -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This file doesn't build anymore and isn't used so remove it. -It was added as part of my ARCH_BCM2835 work last year, but the future -didn't pan out as expected. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 - - arch/arm/boot/dts/bcm2835-rpi-cm.dts | 93 ----------------------------------- - arch/arm/boot/dts/bcm2835-rpi-cm.dtsi | 30 ----------- - 3 files changed, 124 deletions(-) - delete mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dts - delete mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dtsi - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 71f794ecc710ac533731854bd95961a6a4175b64..0cb86b7a5ab212fee36a34b3672856d27c446593 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -3,7 +3,6 @@ ifeq ($(CONFIG_OF),y) - dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b.dtb - dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b-plus.dtb - dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-cm.dtb --dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-cm.dtb - dtb-$(CONFIG_ARCH_BCM2709) += bcm2709-rpi-2-b.dtb - dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dts b/arch/arm/boot/dts/bcm2835-rpi-cm.dts -deleted file mode 100644 -index c6e6860a6d4356a613f4f7ab41c6befc76740a15..0000000000000000000000000000000000000000 ---- a/arch/arm/boot/dts/bcm2835-rpi-cm.dts -+++ /dev/null -@@ -1,93 +0,0 @@ --/dts-v1/; -- --#include "bcm2835-rpi-cm.dtsi" -- --/ { -- model = "Raspberry Pi Compute Module"; --}; -- --&uart0 { -- status = "okay"; --}; -- --&gpio { -- spi0_pins: spi0_pins { -- brcm,pins = <7 8 9 10 11>; -- brcm,function = <4>; /* alt0 */ -- }; -- -- i2c0_pins: i2c0 { -- brcm,pins = <0 1>; -- brcm,function = <4>; -- }; -- -- i2c1_pins: i2c1 { -- brcm,pins = <2 3>; -- brcm,function = <4>; -- }; -- -- i2s_pins: i2s { -- brcm,pins = <18 19 20 21>; -- brcm,function = <4>; /* alt0 */ -- }; --}; -- --&spi0 { -- pinctrl-names = "default"; -- pinctrl-0 = <&spi0_pins>; -- -- spidev@0{ -- compatible = "spidev"; -- reg = <0>; /* CE0 */ -- #address-cells = <1>; -- #size-cells = <0>; -- spi-max-frequency = <500000>; -- }; -- -- spidev@1{ -- compatible = "spidev"; -- reg = <1>; /* CE1 */ -- #address-cells = <1>; -- #size-cells = <0>; -- spi-max-frequency = <500000>; -- }; --}; -- --&i2c0 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c0_pins>; -- clock-frequency = <100000>; --}; -- --&i2c1 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c1_pins>; -- clock-frequency = <100000>; --}; -- --&i2c2 { -- clock-frequency = <100000>; --}; -- --&i2s { -- #sound-dai-cells = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&i2s_pins>; --}; -- --/ { -- __overrides__ { -- uart0 = <&uart0>,"status"; -- uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; -- uart1_clkrate = <&uart1>,"clock-frequency:0"; -- i2s = <&i2s>,"status"; -- spi = <&spi0>,"status"; -- i2c0 = <&i2c0>,"status"; -- i2c1 = <&i2c1>,"status"; -- i2c2_iknowwhatimdoing = <&i2c2>,"status"; -- i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -- i2c1_baudrate = <&i2c1>,"clock-frequency:0"; -- i2c2_baudrate = <&i2c2>,"clock-frequency:0"; -- core_freq = <&clk_core>,"clock-frequency:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -deleted file mode 100644 -index 9c4000fc686a9882b9ddde24fdcf937d52b0f86f..0000000000000000000000000000000000000000 ---- a/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -+++ /dev/null -@@ -1,30 +0,0 @@ --#include "bcm2835.dtsi" -- --&leds { -- act_led: act { -- label = "led0"; -- linux,default-trigger = "mmc0"; -- gpios = <&gpio 47 0>; -- }; --}; -- --&mmc { -- status = "okay"; -- bus-width = <4>; --}; -- --&fb { -- status = "okay"; --}; -- --/ { -- __overrides__ { -- act_led_gpio = <&act_led>,"gpios:4"; -- act_led_activelow = <&act_led>,"gpios:8"; -- act_led_trigger = <&act_led>,"linux,default-trigger"; -- -- audio = <&audio>,"status"; -- watchdog = <&watchdog>,"status"; -- random = <&random>,"status"; -- }; --}; - -From b709b3aa0d39d58479b4a579866ed27cebf3a9ed Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 16:00:07 +0200 -Subject: [PATCH 133/208] bcm2708: Convert to ARCH_MULTIPLATFORM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert to multi platform and base it on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 21 -------------- - arch/arm/Makefile | 1 - - arch/arm/configs/bcmrpi_defconfig | 6 ++-- - arch/arm/mach-bcm/Kconfig | 14 +++++++++ - arch/arm/mach-bcm/board_bcm2835.c | 21 ++++++++++++++ - arch/arm/mach-bcm2708/Kconfig | 14 --------- - arch/arm/mach-bcm2708/Makefile | 5 ---- - arch/arm/mach-bcm2708/Makefile.boot | 3 -- - arch/arm/mach-bcm2708/bcm2708.c | 57 ------------------------------------- - drivers/clk/bcm/Makefile | 4 +-- - drivers/clocksource/Makefile | 2 +- - drivers/irqchip/Makefile | 1 - - 12 files changed, 42 insertions(+), 107 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/Kconfig - delete mode 100644 arch/arm/mach-bcm2708/Makefile - delete mode 100644 arch/arm/mach-bcm2708/Makefile.boot - delete mode 100644 arch/arm/mach-bcm2708/bcm2708.c - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 82cbd045d7894e1b75460021a862f8b56f5ec645..4578b06fda58702f040477cabd0a828afa7eccf4 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -326,26 +326,6 @@ choice - default ARM_SINGLE_ARMV7M if !MMU - default ARCH_MULTIPLATFORM if MMU - --config ARCH_BCM2708 -- bool "Broadcom BCM2708 family" -- select CPU_V6 -- select ARM_AMBA -- select CLKSRC_MMIO -- select CLKSRC_OF if OF -- select HAVE_SCHED_CLOCK -- select NEED_MACH_GPIO_H -- select COMMON_CLK -- select ARCH_HAS_CPUFREQ -- select GENERIC_CLOCKEVENTS -- select ARM_ERRATA_411920 -- select MACH_BCM2708 -- select MULTI_IRQ_HANDLER -- select SPARSE_IRQ -- select VC4 -- select FIQ -- help -- This enables support for Broadcom BCM2708 boards. -- - config ARCH_BCM2709 - bool "Broadcom BCM2709 family" - select CPU_V7 -@@ -754,7 +734,6 @@ config ARCH_VIRT - # Kconfigs may be included either alphabetically (according to the - # plat- suffix) or along side the corresponding mach-* source. - # --source "arch/arm/mach-bcm2708/Kconfig" - source "arch/arm/mach-bcm2709/Kconfig" - - source "arch/arm/mach-mvebu/Kconfig" -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 275c53561cd7c3b1f52a60c95b5fb287fb3ccb62..ca1877e0c75d53091c8eee3373e8b8eb210022a2 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -152,7 +152,6 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 - - # Machine directory name. This list is sorted alphanumerically - # by CONFIG_* macro name. --machine-$(CONFIG_ARCH_BCM2708) += bcm2708 - machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_ALPINE) += alpine - machine-$(CONFIG_ARCH_ARTPEC) += artpec -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 46b91678fef473334b9417409fd1c529c0415977..27c61471a12a38feda62447af8010530bc89c141 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1,5 +1,3 @@ --# CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_PHYS_OFFSET=0 - # CONFIG_LOCALVERSION_AUTO is not set - CONFIG_SYSVIPC=y - CONFIG_POSIX_MQUEUE=y -@@ -38,7 +36,11 @@ CONFIG_BLK_DEV_THROTTLING=y - CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_MULTI_V6=y -+# CONFIG_ARCH_MULTI_V7 is not set -+CONFIG_ARCH_BCM=y - CONFIG_ARCH_BCM2708=y -+# CONFIG_CACHE_L2X0 is not set - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y - CONFIG_OABI_COMPAT=y -diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 5f6ab16792a93b2dd2e3f9e647f8ac4062d4fa6d..9461147888e20c10eba7eeca9d8601bff7d849c0 100644 ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -160,6 +160,20 @@ config ARCH_BCM2835 - This enables support for the Broadcom BCM2835 and BCM2836 SoCs. - This SoC is used in the Raspberry Pi and Roku 2 devices. - -+config MACH_BCM2708 -+ bool "Enable optimized __copy_to_user and __copy_from_user" -+ depends on ARCH_BCM2708 -+ default y +diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig +index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 +--- a/drivers/video/backlight/Kconfig ++++ b/drivers/video/backlight/Kconfig +@@ -265,6 +265,12 @@ config BACKLIGHT_PWM + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. + ++config BACKLIGHT_RPI ++ tristate "Raspberry Pi display firmware driven backlight" + help -+ Optimized versions of __copy_to_user and __copy_from_user for Pi1. ++ If you have the Raspberry Pi DSI touchscreen display, say Y to ++ enable the mailbox-controlled backlight driver. + -+config ARCH_BCM2708 -+ bool "Broadcom BCM2708 family" -+ depends on ARCH_MULTI_V6 -+ select ARCH_BCM2835 -+ help -+ This enables support for Broadcom BCM2708 boards. -+ - config ARCH_BCM_63XX - bool "Broadcom BCM63xx DSL SoC" - depends on ARCH_MULTI_V7 -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index 8f152266ba9b470df2eaaed9ebcf158ed2079834..309a336df05191450aa162c91687592a7107a1b0 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -27,6 +28,7 @@ static void __init bcm2835_init(void) - u32 val; - u64 val64; - -+ vc_cma_early_init(); - bcm2835_init_clocks(); - - if (!of_property_read_u32(np, "linux,revision", &val)) -@@ -35,6 +37,11 @@ static void __init bcm2835_init(void) - system_serial_low = val64; - } - -+static void __init bcm2835_board_reserve(void) -+{ -+ vc_cma_reserve(); -+} -+ - static const char * const bcm2835_compat[] = { - #ifdef CONFIG_ARCH_MULTI_V6 - "brcm,bcm2835", -@@ -47,5 +54,19 @@ static const char * const bcm2835_compat[] = { - - DT_MACHINE_START(BCM2835, "BCM2835") - .init_machine = bcm2835_init, -+ .reserve = bcm2835_board_reserve, - .dt_compat = bcm2835_compat - MACHINE_END -+ -+#ifdef CONFIG_ARCH_BCM2708 -+static const char * const bcm2708_compat[] = { -+ "brcm,bcm2708", -+ NULL -+}; -+ -+DT_MACHINE_START(BCM2708, "BCM2708") -+ .init_machine = bcm2835_init, -+ .reserve = bcm2835_board_reserve, -+ .dt_compat = bcm2708_compat, -+MACHINE_END -+#endif -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -deleted file mode 100644 -index 265c3fb90f3debfc439491a89346e4863edec427..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ /dev/null -@@ -1,14 +0,0 @@ --menu "Broadcom BCM2708 Implementations" -- depends on ARCH_BCM2708 -- --config MACH_BCM2708 -- bool "Broadcom BCM2708 Development Platform" -- select CPU_V6 -- select USE_OF -- select ARCH_REQUIRE_GPIOLIB -- select PINCTRL -- select PINCTRL_BCM2835 -- help -- Include support for the Broadcom(R) BCM2708 platform. -- --endmenu -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -deleted file mode 100644 -index 3da1a1b4ea1fb04ae0b535b2915ea9f386f5701c..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/Makefile -+++ /dev/null -@@ -1,5 +0,0 @@ --# --# Makefile for the linux kernel. --# -- --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o -diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot -deleted file mode 100644 -index 67039c3e0c48fa6b94f1147b3316f74afcecba9e..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/Makefile.boot -+++ /dev/null -@@ -1,3 +0,0 @@ -- zreladdr-y := 0x00008000 --params_phys-y := 0x00000100 --initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -deleted file mode 100644 -index 06b078569006a6d821d3d049f1a0fa5783c1c1b3..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ /dev/null -@@ -1,57 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/bcm2708.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include -- --#include --#include -- --static void __init bcm2708_init(void) --{ -- struct device_node *np = of_find_node_by_path("/system"); -- u32 val; -- u64 val64; -- -- vc_cma_early_init(); -- -- if (!of_property_read_u32(np, "linux,revision", &val)) -- system_rev = val; -- if (!of_property_read_u64(np, "linux,serial", &val64)) -- system_serial_low = val64; --} -- --static void __init board_reserve(void) --{ -- vc_cma_reserve(); --} -- --static const char * const bcm2708_compat[] = { -- "brcm,bcm2708", -- NULL --}; -- --DT_MACHINE_START(BCM2708, "BCM2708") -- /* Maintainer: Broadcom Europe Ltd. */ -- .init_machine = bcm2708_init, -- .reserve = board_reserve, -- .dt_compat = bcm2708_compat, --MACHINE_END -- -diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile -index fcf1bb5d792111a31226c33dec6b1da309a36e0d..84dc055849c0cea70aad86898a0cac757a93cc9e 100644 ---- a/drivers/clk/bcm/Makefile -+++ b/drivers/clk/bcm/Makefile -@@ -4,8 +4,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o - obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o - obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o -diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile -index a60aa840b28f0fa73c496a2e0d5c816eed6f771a..fd9d6df0bbc0993c3b7862a08f89dc3a9725be9d 100644 ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -19,7 +19,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o - obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o - obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o - obj-$(CONFIG_ORION_TIMER) += time-orion.o --obj-$(CONFIG_BCM2835_TIMER)$(CONFIG_ARCH_BCM2708) += bcm2835_timer.o -+obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o - obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o - obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o - obj-$(CONFIG_MOXART_TIMER) += moxart_timer.o -diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index 75da978fac0e06819d8a9740b95ee3d7035c1059..662790c8fa9c972bbf3ac7f41b9f5eace912b69c 100644 ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -5,7 +5,6 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o - obj-$(CONFIG_ATH79) += irq-ath79-misc.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o --obj-$(CONFIG_ARCH_BCM2708) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o - obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o - -From ef5da26a574bc300c0cffe21b7a1a041c0676465 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 16:02:39 +0200 -Subject: [PATCH 134/208] bcm2709: Convert to ARCH_MULTIPLATFORM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert to multi platform and base it on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 25 ----------------- - arch/arm/Makefile | 1 - - arch/arm/configs/bcm2709_defconfig | 4 +-- - arch/arm/mach-bcm/Kconfig | 9 ++++++ - arch/arm/mach-bcm/board_bcm2835.c | 13 +++++++++ - arch/arm/mach-bcm2709/Kconfig | 9 ------ - arch/arm/mach-bcm2709/Makefile | 5 ---- - arch/arm/mach-bcm2709/Makefile.boot | 3 -- - arch/arm/mach-bcm2709/bcm2709.c | 56 ------------------------------------- - drivers/clk/bcm/Makefile | 4 +-- - drivers/irqchip/Makefile | 2 -- - 11 files changed, 25 insertions(+), 106 deletions(-) - delete mode 100644 arch/arm/mach-bcm2709/Kconfig - delete mode 100644 arch/arm/mach-bcm2709/Makefile - delete mode 100644 arch/arm/mach-bcm2709/Makefile.boot - delete mode 100644 arch/arm/mach-bcm2709/bcm2709.c - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 4578b06fda58702f040477cabd0a828afa7eccf4..a9c4e48bb7ec997bec394066914d26f337a2fec4 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -326,29 +326,6 @@ choice - default ARM_SINGLE_ARMV7M if !MMU - default ARCH_MULTIPLATFORM if MMU - --config ARCH_BCM2709 -- bool "Broadcom BCM2709 family" -- select CPU_V7 -- select HAVE_SMP -- select ARM_AMBA -- select MIGHT_HAVE_CACHE_L2X0 -- select HAVE_SCHED_CLOCK -- select COMMON_CLK -- select ARCH_HAS_CPUFREQ -- select GENERIC_CLOCKEVENTS -- select MACH_BCM2709 -- select MULTI_IRQ_HANDLER -- select SPARSE_IRQ -- select MFD_SYSCON -- select VC4 -- select FIQ -- select USE_OF -- select ARCH_REQUIRE_GPIOLIB -- select PINCTRL -- select PINCTRL_BCM2835 -- help -- This enables support for Broadcom BCM2709 boards. -- - config ARCH_MULTIPLATFORM - bool "Allow multiple platforms to be selected" - depends on MMU -@@ -734,8 +711,6 @@ config ARCH_VIRT - # Kconfigs may be included either alphabetically (according to the - # plat- suffix) or along side the corresponding mach-* source. - # --source "arch/arm/mach-bcm2709/Kconfig" -- - source "arch/arm/mach-mvebu/Kconfig" - - source "arch/arm/mach-alpine/Kconfig" -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index ca1877e0c75d53091c8eee3373e8b8eb210022a2..5eb5aef84c1953d12cce666b8a587e0f1f7dd10a 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -152,7 +152,6 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 - - # Machine directory name. This list is sorted alphanumerically - # by CONFIG_* macro name. --machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_ALPINE) += alpine - machine-$(CONFIG_ARCH_ARTPEC) += artpec - machine-$(CONFIG_ARCH_AT91) += at91 -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 40841d8421e44f8863cb23c53802388b502e61a3..d246dd91b12d40a2d59d5e6758548471f1b195a0 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1,5 +1,3 @@ --# CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_PHYS_OFFSET=0 - CONFIG_LOCALVERSION="-v7" - # CONFIG_LOCALVERSION_AUTO is not set - CONFIG_SYSVIPC=y -@@ -39,10 +37,10 @@ CONFIG_BLK_DEV_THROTTLING=y - CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM=y - CONFIG_ARCH_BCM2709=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_SMP=y --CONFIG_HAVE_ARM_ARCH_TIMER=y - CONFIG_VMSPLIT_2G=y - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y -diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 9461147888e20c10eba7eeca9d8601bff7d849c0..929a5fa241fa94134993c61a137d1f79b514d64b 100644 ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -174,6 +174,15 @@ config ARCH_BCM2708 - help - This enables support for Broadcom BCM2708 boards. - -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ depends on ARCH_MULTI_V7 -+ select ARCH_BCM2835 -+ select HAVE_SMP -+ select MFD_SYSCON -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - config ARCH_BCM_63XX - bool "Broadcom BCM63xx DSL SoC" - depends on ARCH_MULTI_V7 -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index 309a336df05191450aa162c91687592a7107a1b0..6ce49dea7856b243b38f180231afd25b57dee729 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -70,3 +70,16 @@ DT_MACHINE_START(BCM2708, "BCM2708") - .dt_compat = bcm2708_compat, - MACHINE_END - #endif -+ -+#ifdef CONFIG_ARCH_BCM2709 -+static const char * const bcm2709_compat[] = { -+ "brcm,bcm2709", -+ NULL -+}; -+ -+DT_MACHINE_START(BCM2709, "BCM2709") -+ .init_machine = bcm2835_init, -+ .reserve = bcm2835_board_reserve, -+ .dt_compat = bcm2709_compat, -+MACHINE_END -+#endif -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -deleted file mode 100644 -index 41f407ac1db3a86e87941153c1832b9fce1ead5d..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/Kconfig -+++ /dev/null -@@ -1,9 +0,0 @@ --menu "Broadcom BCM2709 Implementations" -- depends on ARCH_BCM2709 -- --config MACH_BCM2709 -- bool "Broadcom BCM2709 Development Platform" -- help -- Include support for the Broadcom(R) BCM2709 platform. -- --endmenu -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -deleted file mode 100644 -index 26cd67d3dc343dbd250fa97855a82c28bbd95af0..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/Makefile -+++ /dev/null -@@ -1,5 +0,0 @@ --# --# Makefile for the linux kernel. --# -- --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o -diff --git a/arch/arm/mach-bcm2709/Makefile.boot b/arch/arm/mach-bcm2709/Makefile.boot -deleted file mode 100644 -index 67039c3e0c48fa6b94f1147b3316f74afcecba9e..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/Makefile.boot -+++ /dev/null -@@ -1,3 +0,0 @@ -- zreladdr-y := 0x00008000 --params_phys-y := 0x00000100 --initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -deleted file mode 100644 -index 9f113736627175bdcb362e0eda469e09e3d5f2e0..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ /dev/null -@@ -1,56 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2709/bcm2709.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include -- --#include --#include -- --static void __init bcm2709_init(void) --{ -- struct device_node *np = of_find_node_by_path("/system"); -- u32 val; -- u64 val64; -- -- vc_cma_early_init(); -- -- if (!of_property_read_u32(np, "linux,revision", &val)) -- system_rev = val; -- if (!of_property_read_u64(np, "linux,serial", &val64)) -- system_serial_low = val64; --} -- --static void __init board_reserve(void) --{ -- vc_cma_reserve(); --} -- --static const char * const bcm2709_compat[] = { -- "brcm,bcm2709", -- NULL --}; -- --DT_MACHINE_START(BCM2709, "BCM2709") -- /* Maintainer: Broadcom Europe Ltd. */ -- .init_machine = bcm2709_init, -- .reserve = board_reserve, -- .dt_compat = bcm2709_compat, --MACHINE_END -diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile -index 84dc055849c0cea70aad86898a0cac757a93cc9e..1d79bd2c36f004669d1dcf78fa681025c3f074e2 100644 ---- a/drivers/clk/bcm/Makefile -+++ b/drivers/clk/bcm/Makefile -@@ -4,8 +4,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o -+obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o - obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o - obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o -diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index 662790c8fa9c972bbf3ac7f41b9f5eace912b69c..4c203b6b816357dce8d7a768ac81feaba91d431b 100644 ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -5,8 +5,6 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o - obj-$(CONFIG_ATH79) += irq-ath79-misc.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o --obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2835.o --obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o - obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o - obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o - -From aba21f030087d28e7f8dc7177efe4632ea1a2e85 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 17:32:02 +0200 -Subject: [PATCH 135/208] kconfig: Just use ARCH_BCM2835 for depends on -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -ARCH_BCM2708 and ARCH_BCM2709 selects ARCH_BCM2835 now, so the -dependencies can be simplified. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig.debug | 10 ++++------ - drivers/char/broadcom/Kconfig | 2 +- - drivers/char/hw_random/Kconfig | 2 +- - drivers/dma/Kconfig | 2 +- - drivers/gpio/Kconfig | 2 +- - drivers/gpu/drm/vc4/Kconfig | 2 +- - drivers/i2c/busses/Kconfig | 4 ++-- - drivers/mailbox/Kconfig | 2 +- - drivers/media/platform/bcm2835/Kconfig | 2 +- - drivers/misc/Kconfig | 2 +- - drivers/mmc/host/Kconfig | 4 ++-- - drivers/mtd/nand/Kconfig | 2 +- - drivers/pwm/Kconfig | 2 +- - drivers/soc/bcm/Kconfig | 2 +- - drivers/spi/Kconfig | 4 ++-- - drivers/tty/serial/8250/Kconfig | 2 +- - drivers/watchdog/Kconfig | 2 +- - sound/arm/Kconfig | 3 +-- - sound/soc/bcm/Kconfig | 2 +- - 19 files changed, 25 insertions(+), 28 deletions(-) - -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 11aa81fcaaa8e476ded9b9f41e30ddefa11c1cae..a9693b6987a6e41c69702f1003d0d8bd2279530e 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -147,12 +147,12 @@ choice - - config DEBUG_BCM2835 - bool "Kernel low-level debugging on BCM2835 PL011 UART" -- depends on (ARCH_BCM2835 && ARCH_MULTI_V6) || ARCH_BCM2708 -+ depends on ARCH_BCM2835 && ARCH_MULTI_V6 - select DEBUG_UART_PL01X - - config DEBUG_BCM2836 - bool "Kernel low-level debugging on BCM2836 PL011 UART" -- depends on (ARCH_BCM2835 && ARCH_MULTI_V7) || ARCH_BCM2709 -+ depends on ARCH_BCM2835 && ARCH_MULTI_V7 - select DEBUG_UART_PL01X - - config DEBUG_BCM_5301X -@@ -1695,8 +1695,7 @@ config DEBUG_UART_8250_FLOW_CONTROL - - config DEBUG_UNCOMPRESS - bool -- depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -- ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M - default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ - (!DEBUG_TEGRA_UART || !ZBOOT_ROM) - help -@@ -1713,8 +1712,7 @@ config DEBUG_UNCOMPRESS - config UNCOMPRESS_INCLUDE - string - default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \ -- PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -- ARCH_BCM2708 || ARCH_BCM2709 -+ PLAT_SAMSUNG || ARM_SINGLE_ARMV7M - default "mach/uncompress.h" - - config EARLY_PRINTK -diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 5489f19f05c620a30541e1a222d77b6ee4356d97..032164919350db25c586c36f0e05d3e4891fb835 100644 ---- a/drivers/char/broadcom/Kconfig -+++ b/drivers/char/broadcom/Kconfig -@@ -49,7 +49,7 @@ config BCM2835_DEVGPIOMEM - - config BCM2835_SMI_DEV - tristate "Character device driver for BCM2835 Secondary Memory Interface" -- depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI -+ depends on BCM2835_SMI - default m - help - This driver provides a character device interface (ioctl + read/write) to -diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 205b6b34d32c660d34c885e8391032d682c8870e..8c0770bf8881351c1d956d310c5d670684090770 100644 ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX - - config HW_RANDOM_BCM2835 - tristate "Broadcom BCM2835 Random Number Generator support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM_NSP || ARCH_BCM_5301X -+ depends on ARCH_BCM2835 || ARCH_BCM_NSP || ARCH_BCM_5301X - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 2a2108062687ff33ff540c987f6367fa3b8aad9d..61c3318e8c88e1cd88e4ccc20875321bb238d936 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -108,7 +108,7 @@ config COH901318 - - config DMA_BCM2835 - tristate "BCM2835 DMA engine support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index 343adff44f82b78d0a09d41518a2890c602fc83d..71d7754587afbb4d6446ebd5448ef7e7c110c47e 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -146,7 +146,7 @@ config GPIO_BCM_KONA - - config GPIO_BCM_VIRT - bool "Broadcom Virt GPIO" -- depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) - help - Turn on virtual GPIO support for Broadcom BCM283X chips. - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index f6e938208b73512f20eab46a383ca91bf675a845..e53df59cb139f25f8e6ae916bca93abf0c49e063 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -1,6 +1,6 @@ - config DRM_VC4 - tristate "Broadcom VC4 Graphics" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - depends on DRM - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 37f463232d6db91940763345600b095dbd8b5c58..9cd5735259276cfc823e6e51907a74db611a2ebc 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -10,7 +10,7 @@ comment "PC SMBus host controller drivers" - - config I2C_BCM2708 - tristate "BCM2708 BSC" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - help - Enabling this option will add BSC (Broadcom Serial Controller) - support for the BCM2708. BSC is a Broadcom proprietary bus compatible -@@ -385,7 +385,7 @@ config I2C_AXXIA - - config I2C_BCM2835 - tristate "Broadcom BCM2835 I2C controller" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - help - If you say yes to this option, support will be included for the - BCM2835 I2C controller. -diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index dc46b41705af8ea405dc961d9230058c7086db7d..7817d40d81e74ad282b1760b1dc50d090d10670d 100644 ---- a/drivers/mailbox/Kconfig -+++ b/drivers/mailbox/Kconfig -@@ -74,7 +74,7 @@ config ALTERA_MBOX - - config BCM2835_MBOX - tristate "BCM2835 Mailbox" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - help - An implementation of the BCM2385 Mailbox. It is used to invoke - the services of the Videocore. Say Y here if you want to use the -diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig -index 99a5cbccf0f3fa66ad5190ec0942b0c232c3e824..58d5f9600d726cb20e6d04c54c58c53ac3a586d2 100644 ---- a/drivers/media/platform/bcm2835/Kconfig -+++ b/drivers/media/platform/bcm2835/Kconfig -@@ -2,7 +2,7 @@ - - config VIDEO_BCM2835 - bool "Broadcom BCM2835 camera interface driver" -- depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) -+ depends on VIDEO_V4L2 && ARCH_BCM2835 - ---help--- - Say Y here to enable camera host interface devices for - Broadcom BCM2835 SoC. This operates over the VCHIQ interface -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index cff8c3df50c4b13d40fd1143eb86a66756bc097c..f34254bc14de8a33bb5922a680331b74f2fae4cb 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -12,7 +12,7 @@ config SENSORS_LIS3LV02D - - config BCM2835_SMI - tristate "Broadcom 283x Secondary Memory Interface driver" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - default m - help - Driver for enabling and using Broadcom's Secondary/Slow Memory Interface. -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 205d836b52e3bbcf8956fec98072c6ee7804a403..87d251e93913b216359383812cae196e91bf6cfb 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -6,7 +6,7 @@ comment "MMC/SD/SDIO Host Controller Drivers" - - config MMC_BCM2835 - tristate "MMC support on BCM2835" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - help - This selects the MMC Interface on BCM2835. - -@@ -35,7 +35,7 @@ config MMC_BCM2835_PIO_DMA_BARRIER - - config MMC_BCM2835_SDHOST - tristate "Support for the SDHost controller on BCM2708/9" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - help - This selects the SDHost controller on BCM2835/6. - -diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig -index b6a0529b2c15f37983169e3429b67bedb71fb14e..7825a51f7a4fee6468d16debab661fa3d210daee 100644 ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -43,7 +43,7 @@ config MTD_SM_COMMON - - config MTD_NAND_BCM2835_SMI - tristate "Use Broadcom's Secondary Memory Interface as a NAND controller (BCM283x)" -- depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI && MTD_NAND -+ depends on BCM2835_SMI - default m - help - Uses the BCM2835's SMI peripheral as a NAND controller. -diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig -index 549cf7a786e27e19863ec0ad53a8b2836afd0c2a..80a566a00d0437dcc8fca7715c1109e7c2d35f67 100644 ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -95,7 +95,7 @@ config PWM_BCM_KONA - - config PWM_BCM2835 - tristate "BCM2835 PWM support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - help - PWM framework driver for BCM2835 controller (Raspberry Pi) - -diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig -index 7d11a44f36d2e6f8697773cd49a72e53bca3a5a0..a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226 100644 ---- a/drivers/soc/bcm/Kconfig -+++ b/drivers/soc/bcm/Kconfig -@@ -2,7 +2,7 @@ menu "Broadcom SoC drivers" - - config RASPBERRYPI_POWER - bool "Raspberry Pi power domain driver" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || (COMPILE_TEST && OF) -+ depends on ARCH_BCM2835 || (COMPILE_TEST && OF) - depends on RASPBERRYPI_FIRMWARE=y - select PM_GENERIC_DOMAINS if PM - help -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 4b09be74af155c2a6e0590a6380242db40e6f914..d6fb8d4b778672fd006446c0eab710d35f6e6e3a 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -94,7 +94,7 @@ config SPI_AXI_SPI_ENGINE - config SPI_BCM2835 - tristate "BCM2835 SPI controller" - depends on GPIOLIB -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI master. - -@@ -105,7 +105,7 @@ config SPI_BCM2835 - - config SPI_BCM2835AUX - tristate "BCM2835 SPI auxiliary controller" -- depends on ((ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709) && GPIOLIB) || COMPILE_TEST -+ depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI aux master. - -diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig -index 748098f900d3474b5d535b24da76ad06e9690335..7c6f7afca5ddeed7b25fa6272246fc539bf31b04 100644 ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -291,7 +291,7 @@ config SERIAL_8250_ACORN - - config SERIAL_8250_BCM2835AUX - tristate "BCM2835 auxiliar mini UART support" -- depends on ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ - help - Support for the BCM2835 auxiliar mini UART. -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index 9a28f1fdf93a79104049c03ed51abc31d34165d5..1bffe006ca9a843e2e71bc1a461a2d67e97480c0 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1440,7 +1440,7 @@ config BCM63XX_WDT - - config BCM2835_WDT - tristate "Broadcom BCM2835 hardware watchdog" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - select WATCHDOG_CORE - help - Watchdog driver for the built in watchdog hardware in Broadcom -diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 8883c2f3a3269742e2bf6fc995643fb282f3509a..02b6d263035ca18c9ce53229369dfb00915c260b 100644 ---- a/sound/arm/Kconfig -+++ b/sound/arm/Kconfig -@@ -34,8 +34,7 @@ config SND_PXA2XX_AC97 - - config SND_BCM2835 - tristate "BCM2835 ALSA driver" -- depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ -- && BCM2708_VCHIQ && SND -+ depends on ARCH_BCM2835 && BCM2708_VCHIQ && SND - select SND_PCM - help - Say Y or M if you want to support BCM2835 Alsa pcm card driver -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index aed7b47d8736ea3fb1810b0c77916855082f3b2d..d024377e8450fb5402dcb5ea27161f774b04a8ec 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -1,6 +1,6 @@ - config SND_BCM2835_SOC_I2S - tristate "SoC Audio support for the Broadcom BCM2835 I2S module" -- depends on ARCH_BCM2835 || MACH_BCM2708 || MACH_BCM2709 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - select SND_SOC_GENERIC_DMAENGINE_PCM - select REGMAP_MMIO - help - -From d770fc68afb2244e1eae7cb99da07425244c500e Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 28 Oct 2016 13:55:36 +0100 -Subject: [PATCH 136/208] bcm270x: Use dma-ranges unconditionally on bcm2710 - -See: https://github.com/raspberrypi/linux/pull/1699 - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2710.dtsi | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index 491594c918cf5da94fbb19a606edb0dd9a28c3a9..df1a4ce1cd4e570876b7785b357d6c31f66191a4 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -9,9 +9,7 @@ - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; --#ifdef RPI364 - dma-ranges = <0xc0000000 0x00000000 0x3f000000>; --#endif - - local_intc: local_intc { - compatible = "brcm,bcm2836-l1-intc"; -@@ -143,9 +141,7 @@ - - &intc { - compatible = "brcm,bcm2836-armctrl-ic"; --#ifdef RPI364 - reg = <0x7e00b200 0x200>; --#endif - interrupt-parent = <&local_intc>; - interrupts = <8>; - }; - -From 3c5d9cfdf541f1da85a407745d790a5cef1d9b6c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 27 Oct 2016 21:57:56 +0200 -Subject: [PATCH 137/208] BCM270X_DT: Use raspberrypi-power to turn on USB - power -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use the raspberrypi-power driver to turn on USB power. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi -index d85c05901c8f55f822b89c32d198f15559a2b4b0..46cf8602c3b96e477b05b57dbfe5e349930c9d9a 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi -@@ -103,3 +103,7 @@ - &hdmi { - power-domains = <&power RPI_POWER_DOMAIN_HDMI>; - }; -+ -+&usb { -+ power-domains = <&power RPI_POWER_DOMAIN_USB>; -+}; - -From 3fc6c0966f06447cfabc8f5b220d32b59e9b7cf4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 27 Oct 2016 21:58:09 +0200 -Subject: [PATCH 138/208] firmware: bcm2835: Don't turn on USB power -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The raspberrypi-power driver is now used to turn on USB power. - -This partly reverts commit: -firmware: bcm2835: Support ARCH_BCM270x - -Signed-off-by: Noralf Trønnes ---- - drivers/firmware/raspberrypi.c | 22 ---------------------- - 1 file changed, 22 deletions(-) - -diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c -index b980d531b35b9981a88356ef1c8a7b868a85f2b5..3f070bd38a91511c986e3fb114b15bd4ac32634c 100644 ---- a/drivers/firmware/raspberrypi.c -+++ b/drivers/firmware/raspberrypi.c -@@ -185,25 +185,6 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) - } - } - --static int raspberrypi_firmware_set_power(struct rpi_firmware *fw, -- u32 domain, bool on) --{ -- struct { -- u32 domain; -- u32 on; -- } packet; -- int ret; -- -- packet.domain = domain; -- packet.on = on; -- ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POWER_STATE, -- &packet, sizeof(packet)); -- if (!ret && packet.on != on) -- ret = -EINVAL; -- -- return ret; --} -- - static int rpi_firmware_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -232,9 +213,6 @@ static int rpi_firmware_probe(struct platform_device *pdev) - - rpi_firmware_print_firmware_revision(fw); - -- if (raspberrypi_firmware_set_power(fw, 3, true)) -- dev_err(dev, "failed to turn on USB power\n"); -- - return 0; - } - - -From da310619ddd881d063323ee8e3bdc1c8b2b5d9a8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 31 Oct 2016 17:35:31 +0000 -Subject: [PATCH 139/208] bcm2835: Increase coherent allocation to 1M for - dwc_otg bounce buffers - ---- - arch/arm/mach-bcm/board_bcm2835.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index 6ce49dea7856b243b38f180231afd25b57dee729..efbd18020479c1cab40ce680446a4259c62c83cb 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -22,6 +22,8 @@ - #include - #include - -+#include -+ - static void __init bcm2835_init(void) - { - struct device_node *np = of_find_node_by_path("/system"); -@@ -37,6 +39,12 @@ static void __init bcm2835_init(void) - system_serial_low = val64; - } - -+static void __init bcm2835_init_early(void) -+{ -+ /* dwc_otg needs this for bounce buffers on non-aligned transfers */ -+ init_dma_coherent_pool_size(SZ_1M); -+} -+ - static void __init bcm2835_board_reserve(void) - { - vc_cma_reserve(); -@@ -55,6 +63,7 @@ static const char * const bcm2835_compat[] = { - DT_MACHINE_START(BCM2835, "BCM2835") - .init_machine = bcm2835_init, - .reserve = bcm2835_board_reserve, -+ .init_early = bcm2835_init_early, - .dt_compat = bcm2835_compat - MACHINE_END - -@@ -67,6 +76,7 @@ static const char * const bcm2708_compat[] = { - DT_MACHINE_START(BCM2708, "BCM2708") - .init_machine = bcm2835_init, - .reserve = bcm2835_board_reserve, -+ .init_early = bcm2835_init_early, - .dt_compat = bcm2708_compat, - MACHINE_END - #endif -@@ -80,6 +90,7 @@ static const char * const bcm2709_compat[] = { - DT_MACHINE_START(BCM2709, "BCM2709") - .init_machine = bcm2835_init, - .reserve = bcm2835_board_reserve, -+ .init_early = bcm2835_init_early, - .dt_compat = bcm2709_compat, - MACHINE_END - #endif - -From 48080e34503d7f5433c56d78586691429a431cdb Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 31 Oct 2016 17:35:57 +0000 -Subject: [PATCH 140/208] dwc_otg: Warn if dma_alloc_coherent fails - ---- - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -index 50aaeacdd12fff93d7a9cf1c54612367406c6bee..e799f15f294706ad7ac328dcb9ce68fbd0e71d38 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -270,6 +270,7 @@ static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, - } - - buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); -+ WARN_ON(!buf); - - /* Check dword alignment */ - if (((int)buf & 0x3UL) != 0) { - -From 556dcc28d787925ac811fede23d170daa24649fd Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Fri, 4 Nov 2016 16:13:07 -0700 -Subject: [PATCH 141/208] bcmrpi3_defconfig: Update config to be compatible - with latest Kconfig changes. - -This new config has been run through make savedefconfig. ---- - arch/arm64/configs/bcmrpi3_defconfig | 111 +++++++++++------------------------ - 1 file changed, 33 insertions(+), 78 deletions(-) - -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -index d7406f5a4620151044b8f716b4d10bb818648e06..cd1d39b467a947a015eb14568086a6ba4cfb729b 100644 ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -1,52 +1,9 @@ --# CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_PHYS_OFFSET=0 - CONFIG_LOCALVERSION="-v8" - # CONFIG_LOCALVERSION_AUTO is not set --CONFIG_64BIT=y - CONFIG_SYSVIPC=y - CONFIG_POSIX_MQUEUE=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y -- --# --# ARM errata workarounds via the alternatives framework --# --CONFIG_ARM64_ERRATUM_826319=n --CONFIG_ARM64_ERRATUM_827319=n --CONFIG_ARM64_ERRATUM_824069=n --CONFIG_ARM64_ERRATUM_819472=n --CONFIG_ARM64_ERRATUM_832075=n --CONFIG_ARM64_ERRATUM_845719=n --CONFIG_ARM64_ERRATUM_843419=n --CONFIG_CAVIUM_ERRATUM_22375=n --CONFIG_CAVIUM_ERRATUM_23154=n --CONFIG_CAVIUM_ERRATUM_27456=n --CONFIG_ARM64_4K_PAGES=y --CONFIG_ARM64_VA_BITS_39=y --CONFIG_ARM64_VA_BITS=39 --CONFIG_SCHED_MC=y --CONFIG_NR_CPUS=4 --CONFIG_HOTPLUG_CPU=y --CONFIG_ARMV8_DEPRECATED=y --CONFIG_SWP_EMULATION=y --CONFIG_CP15_BARRIER_EMULATION=y --CONFIG_SETEND_EMULATION=y -- --# --# ARMv8.1 architectural features --# --CONFIG_ARM64_HW_AFDBM=y --CONFIG_ARM64_PAN=y --CONFIG_ARM64_LSE_ATOMICS=y --CONFIG_ARM64_VHE=y -- --# --# ARMv8.2 architectural features --# --CONFIG_ARM64_UAO=y --CONFIG_ARM64_MODULE_CMODEL_LARGE=n --CONFIG_RANDOMIZE_BASE=n -- - CONFIG_BSD_PROCESS_ACCT=y - CONFIG_BSD_PROCESS_ACCT_V3=y - CONFIG_TASKSTATS=y -@@ -55,7 +12,6 @@ CONFIG_TASK_XACCT=y - CONFIG_TASK_IO_ACCOUNTING=y - CONFIG_IKCONFIG=m - CONFIG_IKCONFIG_PROC=y --CONFIG_NMI_LOG_BUF_SHIFT=12 - CONFIG_MEMCG=y - CONFIG_BLK_CGROUP=y - CONFIG_CGROUP_FREEZER=y -@@ -69,7 +25,6 @@ CONFIG_BLK_DEV_INITRD=y - CONFIG_EMBEDDED=y - # CONFIG_COMPAT_BRK is not set - CONFIG_PROFILING=y --CONFIG_OPROFILE=m - CONFIG_KPROBES=y - CONFIG_JUMP_LABEL=y - CONFIG_MODULES=y -@@ -82,25 +37,37 @@ CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_BCM2709=y --# CONFIG_CACHE_L2X0 is not set --CONFIG_SMP=y --CONFIG_HAVE_ARM_ARCH_TIMER=y --CONFIG_VMSPLIT_2G=y -+CONFIG_ARCH_BCM2835=y -+# CONFIG_ARM64_ERRATUM_826319 is not set -+# CONFIG_ARM64_ERRATUM_827319 is not set -+# CONFIG_ARM64_ERRATUM_824069 is not set -+# CONFIG_ARM64_ERRATUM_819472 is not set -+# CONFIG_ARM64_ERRATUM_832075 is not set -+# CONFIG_ARM64_ERRATUM_845719 is not set -+# CONFIG_ARM64_ERRATUM_843419 is not set -+# CONFIG_CAVIUM_ERRATUM_22375 is not set -+# CONFIG_CAVIUM_ERRATUM_23154 is not set -+# CONFIG_CAVIUM_ERRATUM_27456 is not set -+CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=4 -+CONFIG_HOTPLUG_CPU=y - CONFIG_PREEMPT_VOLUNTARY=y --CONFIG_AEABI=y --CONFIG_OABI_COMPAT=y --# CONFIG_CPU_SW_DOMAIN_PAN is not set - CONFIG_CLEANCACHE=y - CONFIG_FRONTSWAP=y - CONFIG_CMA=y - CONFIG_ZSMALLOC=m - CONFIG_PGTABLE_MAPPING=y --CONFIG_UACCESS_WITH_MEMCPY=y - CONFIG_SECCOMP=y --# CONFIG_ATAGS is not set --CONFIG_ZBOOT_ROM_TEXT=0x0 --CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y -+CONFIG_ARM64_LSE_ATOMICS=y - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_BINFMT_MISC=m -+CONFIG_COMPAT=y -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y - CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -@@ -108,15 +75,6 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y - CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y --CONFIG_VFP=y --CONFIG_NEON=y --CONFIG_KERNEL_MODE_NEON=y --CONFIG_BINFMT_MISC=m --CONFIG_COMPAT=y --CONFIG_SYSVIPC_COMPAT=y -- --# CONFIG_SUSPEND is not set --CONFIG_PM=y - CONFIG_NET=y - CONFIG_PACKET=y - CONFIG_UNIX=y -@@ -463,6 +421,7 @@ CONFIG_CDROM_PKTCDVD=m - CONFIG_ATA_OVER_ETH=m - CONFIG_EEPROM_AT24=m - CONFIG_TI_ST=m -+# CONFIG_BCM2708_VCHIQ is not set - CONFIG_SCSI=y - # CONFIG_SCSI_PROC_FS is not set - CONFIG_BLK_DEV_SD=y -@@ -580,7 +539,6 @@ CONFIG_RT2800USB_RT53XX=y - CONFIG_RT2800USB_RT55XX=y - CONFIG_RT2800USB_UNKNOWN=y - CONFIG_RTL8187=m --CONFIG_RTL8192CU=n - CONFIG_USB_ZD1201=m - CONFIG_ZD1211RW=m - CONFIG_MAC80211_HWSIM=m -@@ -626,10 +584,6 @@ CONFIG_SERIO_RAW=m - CONFIG_GAMEPORT=m - CONFIG_GAMEPORT_NS558=m - CONFIG_GAMEPORT_L4=m --CONFIG_BRCM_CHAR_DRIVERS=n --CONFIG_BCM_VC_CMA=n --CONFIG_BCM_VCIO=n --CONFIG_BCM_VC_SM=n - # CONFIG_LEGACY_PTYS is not set - # CONFIG_DEVKMEM is not set - CONFIG_SERIAL_8250=y -@@ -638,6 +592,9 @@ CONFIG_SERIAL_8250_CONSOLE=y - # CONFIG_SERIAL_8250_DMA is not set - CONFIG_SERIAL_8250_NR_UARTS=1 - CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y - CONFIG_SERIAL_OF_PLATFORM=y - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -@@ -682,12 +639,12 @@ CONFIG_W1_SLAVE_DS2781=m - CONFIG_W1_SLAVE_DS28E04=m - CONFIG_W1_SLAVE_BQ27000=m - CONFIG_BATTERY_DS2760=m --CONFIG_POWER_RESET=y - CONFIG_POWER_RESET_GPIO=y - CONFIG_HWMON=m - CONFIG_SENSORS_LM75=m - CONFIG_SENSORS_SHT21=m - CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y -@@ -835,8 +792,7 @@ CONFIG_VIDEO_EM28XX_V4L2=m - CONFIG_VIDEO_EM28XX_ALSA=m - CONFIG_VIDEO_EM28XX_DVB=m - CONFIG_V4L_PLATFORM_DRIVERS=y --CONFIG_VIDEO_BCM2835=n --CONFIG_VIDEO_BCM2835_MMAL=n -+CONFIG_VIDEO_BCM2835=y - CONFIG_RADIO_SI470X=y - CONFIG_USB_SI470X=m - CONFIG_I2C_SI470X=m -@@ -892,8 +848,6 @@ CONFIG_SND_VIRMIDI=m - CONFIG_SND_MTPAV=m - CONFIG_SND_SERIAL_U16550=m - CONFIG_SND_MPU401=m --CONFIG_SND_ARM=n --CONFIG_SND_BCM2835=n - CONFIG_SND_USB_AUDIO=m - CONFIG_SND_USB_UA101=m - CONFIG_SND_USB_CAIAQ=m -@@ -916,6 +870,8 @@ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m - CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m -@@ -979,8 +935,6 @@ CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - CONFIG_USB_MON=m --CONFIG_USB_DWCOTG=n --CONFIG_USB_DWC2=y - CONFIG_USB_PRINTER=m - CONFIG_USB_STORAGE=y - CONFIG_USB_STORAGE_REALTEK=m -@@ -1001,6 +955,7 @@ CONFIG_USB_MICROTEK=m - CONFIG_USBIP_CORE=m - CONFIG_USBIP_VHCI_HCD=m - CONFIG_USBIP_HOST=m -+CONFIG_USB_DWC2=y - CONFIG_USB_SERIAL=m - CONFIG_USB_SERIAL_GENERIC=y - CONFIG_USB_SERIAL_AIRCABLE=m -@@ -1153,6 +1108,7 @@ CONFIG_FB_TFT_BD663474=m - CONFIG_FB_TFT_HX8340BN=m - CONFIG_FB_TFT_HX8347D=m - CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m - CONFIG_FB_TFT_ILI9163=m - CONFIG_FB_TFT_ILI9320=m - CONFIG_FB_TFT_ILI9325=m -@@ -1331,4 +1287,3 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m - CONFIG_ARM64_CRYPTO=y - CONFIG_CRC_ITU_T=y - CONFIG_LIBCRC32C=y --CONFIG_BCM2708_VCHIQ=n - -From 8327ba9ec4f7544d9045f390e72e5305f79f0289 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 8 Nov 2016 21:35:38 +0000 -Subject: [PATCH 142/208] spi-bcm2835: Remove unused code - ---- - drivers/spi/spi-bcm2835.c | 61 ----------------------------------------------- - 1 file changed, 61 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 8493474d286f7a1ac6454a22c61c8c2cef9121bf..33d75ad38a7f77d085321ace9101900a83bebcac 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -679,17 +679,8 @@ static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - } - --static int chip_match_name(struct gpio_chip *chip, void *data) --{ -- return !strcmp(chip->label, data); --} -- - static int bcm2835_spi_setup(struct spi_device *spi) - { -- int err; -- struct gpio_chip *chip; -- struct device_node *pins; -- u32 pingroup_index; - /* - * sanity checking the native-chipselects - */ -@@ -707,58 +698,6 @@ static int bcm2835_spi_setup(struct spi_device *spi) - return -EINVAL; - } - --#if 0 -- /* now translate native cs to GPIO */ -- /* first look for chip select pins in the devices pin groups */ -- for (pingroup_index = 0; -- (pins = of_parse_phandle(spi->master->dev.of_node, -- "pinctrl-0", -- pingroup_index)) != 0; -- pingroup_index++) { -- u32 pin; -- u32 pin_index; -- for (pin_index = 0; -- of_property_read_u32_index(pins, -- "brcm,pins", -- pin_index, -- &pin) == 0; -- pin_index++) { -- if (((spi->chip_select == 0) && -- ((pin == 8) || (pin == 36) || (pin == 46))) || -- ((spi->chip_select == 1) && -- ((pin == 7) || (pin == 35)))) { -- spi->cs_gpio = pin; -- break; -- } -- } -- of_node_put(pins); -- } -- /* if that fails, assume GPIOs 7-11 are used */ -- if (!gpio_is_valid(spi->cs_gpio) ) { -- /* get the gpio chip for the base */ -- chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); -- if (!chip) -- return 0; -- -- /* and calculate the real CS */ -- spi->cs_gpio = chip->base + 8 - spi->chip_select; -- } -- -- /* and set up the "mode" and level */ -- dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -- spi->chip_select, spi->cs_gpio); -- -- /* set up GPIO as output and pull to the correct level */ -- err = gpio_direction_output(spi->cs_gpio, -- (spi->mode & SPI_CS_HIGH) ? 0 : 1); -- if (err) { -- dev_err(&spi->dev, -- "could not set CS%i gpio %i as output: %i", -- spi->chip_select, spi->cs_gpio, err); -- return err; -- } --#endif -- - return 0; - } - - -From a52fcdf0feb26148aa77f39f5ed28d40b45eb201 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 17 Sep 2016 15:07:10 +0200 -Subject: [PATCH 143/208] i2c: bcm2835: Fix hang for writing messages larger - than 16 bytes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Writing messages larger than the FIFO size results in a hang, rendering -the machine unusable. This is because the RXD status flag is set on the -first interrupt which results in bcm2835_drain_rxfifo() stealing bytes -from the buffer. The controller continues to trigger interrupts waiting -for the missing bytes, but bcm2835_fill_txfifo() has none to give. -In this situation wait_for_completion_timeout() apparently is unable to -stop the madness. - -The BCM2835 ARM Peripherals datasheet has this to say about the flags: - TXD: is set when the FIFO has space for at least one byte of data. - RXD: is set when the FIFO contains at least one byte of data. - TXW: is set during a write transfer and the FIFO is less than full. - RXR: is set during a read transfer and the FIFO is or more full. - -Implementing the logic from the downstream i2c-bcm2708 driver solved -the hang problem. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt -Reviewed-by: Martin Sperl ---- - drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index d4f3239b56865919e1b781b20a7c5ebcd76b4eb9..f283b714aa79e2e4685ed95b04b6b289f7e9eee7 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { - int irq; - struct i2c_adapter adapter; - struct completion completion; -+ struct i2c_msg *curr_msg; - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -@@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - return IRQ_HANDLED; - } - -- if (val & BCM2835_I2C_S_RXD) { -- bcm2835_drain_rxfifo(i2c_dev); -- if (!(val & BCM2835_I2C_S_DONE)) -- return IRQ_HANDLED; -- } -- - if (val & BCM2835_I2C_S_DONE) { -- if (i2c_dev->msg_buf_remaining) -+ if (i2c_dev->curr_msg->flags & I2C_M_RD) { -+ bcm2835_drain_rxfifo(i2c_dev); -+ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -+ } -+ -+ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) - i2c_dev->msg_err = BCM2835_I2C_S_LEN; - else - i2c_dev->msg_err = 0; -@@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - return IRQ_HANDLED; - } - -- if (val & BCM2835_I2C_S_TXD) { -+ if (val & BCM2835_I2C_S_TXW) { - bcm2835_fill_txfifo(i2c_dev); - return IRQ_HANDLED; - } - -+ if (val & BCM2835_I2C_S_RXR) { -+ bcm2835_drain_rxfifo(i2c_dev); -+ return IRQ_HANDLED; -+ } -+ - return IRQ_NONE; - } - -@@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - u32 c; - unsigned long time_left; - -+ i2c_dev->curr_msg = msg; - i2c_dev->msg_buf = msg->buf; - i2c_dev->msg_buf_remaining = msg->len; - reinit_completion(&i2c_dev->completion); - -From 2bfb98d7ef7b2599e323ce5bf7d55da796d1d73c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 18:24:38 +0200 -Subject: [PATCH 144/208] i2c: bcm2835: Protect against unexpected TXW/RXR - interrupts -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), -the driver has no way to fill/drain the FIFO to stop the interrupts. -In this case the controller has to be disabled and the transfer -completed to avoid hang. - -(CLKT | ERR) and DONE interrupts are completed in their own paths, and -the controller is disabled in the transfer function after completion. -Unite the code paths and do disabling inside the interrupt routine. - -Clear interrupt status bits in the united completion path instead of -trying to do it on every interrupt which isn't necessary. -Only CLKT, ERR and DONE can be cleared that way. - -Add the status value to the error value in case of TXW/RXR errors to -distinguish them from the other S_LEN error. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++--------- - 1 file changed, 31 insertions(+), 9 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index f283b714aa79e2e4685ed95b04b6b289f7e9eee7..d2ba1a4de36af512e8e3c97251bd3537ae61591a 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -50,8 +50,6 @@ - #define BCM2835_I2C_S_CLKT BIT(9) - #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ - --#define BCM2835_I2C_BITMSK_S 0x03FF -- - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - -@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) - } - } - + config BACKLIGHT_DA903X + tristate "Backlight Driver for DA9030/DA9034 using WLED" + depends on PMIC_DA903X +diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile +index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 +--- a/drivers/video/backlight/Makefile ++++ b/drivers/video/backlight/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o + obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o + obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o + obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o ++obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o + obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o + obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o + obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o +diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c +new file mode 100644 +index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad +--- /dev/null ++++ b/drivers/video/backlight/rpi_backlight.c +@@ -0,0 +1,119 @@ +/* -+ * Note about I2C_C_CLEAR on error: -+ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in -+ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through -+ * the state machine to send a NACK and a STOP. Since we're setting CLEAR -+ * without I2CEN, that NACK will be hanging around queued up for next time -+ * we start the engine. ++ * rpi_bl.c - Backlight controller through VPU ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. + */ + - static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - { - struct bcm2835_i2c_dev *i2c_dev = data; - u32 val, err; - - val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -- val &= BCM2835_I2C_BITMSK_S; -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); - - err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if (err) { - i2c_dev->msg_err = err; -- complete(&i2c_dev->completion); -- return IRQ_HANDLED; -+ goto complete; - } - - if (val & BCM2835_I2C_S_DONE) { -@@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - i2c_dev->msg_err = BCM2835_I2C_S_LEN; - else - i2c_dev->msg_err = 0; -- complete(&i2c_dev->completion); -- return IRQ_HANDLED; -+ goto complete; - } - - if (val & BCM2835_I2C_S_TXW) { -+ if (!i2c_dev->msg_buf_remaining) { -+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; -+ goto complete; -+ } ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + - bcm2835_fill_txfifo(i2c_dev); - return IRQ_HANDLED; - } - - if (val & BCM2835_I2C_S_RXR) { -+ if (!i2c_dev->msg_buf_remaining) { -+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; -+ goto complete; -+ } ++struct rpi_backlight { ++ struct device *dev; ++ struct device *fbdev; ++ struct rpi_firmware *fw; ++}; + - bcm2835_drain_rxfifo(i2c_dev); - return IRQ_HANDLED; - } - - return IRQ_NONE; -+ -+complete: -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT | -+ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE); -+ complete(&i2c_dev->completion); -+ -+ return IRQ_HANDLED; - } - - static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, -@@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - BCM2835_I2C_TIMEOUT); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); - if (!time_left) { -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, -+ BCM2835_I2C_C_CLEAR); - dev_err(i2c_dev->dev, "i2c transfer timed out\n"); - return -ETIMEDOUT; - } - -From 95c425e3ae8a01e772381b1d262599a85b6d1871 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 19 Sep 2016 17:19:41 +0200 -Subject: [PATCH 145/208] i2c: bcm2835: Use dev_dbg logging on transfer errors -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Writing to an AT24C32 generates on average 2x i2c transfer errors per -32-byte page write. Which amounts to a lot for a 4k write. This is due -to the fact that the chip doesn't respond during it's internal write -cycle when the at24 driver tries and retries the next write. -Only a handful drivers use dev_err() on transfer error, so switch to -dev_dbg() instead. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index d2ba1a4de36af512e8e3c97251bd3537ae61591a..54d510abd46a117c9238fc6d7edec84019d1f60d 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - (msg->flags & I2C_M_IGNORE_NAK)) - return 0; - -- dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); -+ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; - -From dd2fb326c9bea407665658538a993d907b681b90 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 22 Sep 2016 22:05:50 +0200 -Subject: [PATCH 146/208] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The controller can't support this flag, so remove it. - -Documentation/i2c/i2c-protocol states that all of the message is sent: - -I2C_M_IGNORE_NAK: - Normally message is interrupted immediately if there is [NA] from the - client. Setting this flag treats any [NA] as [A], and all of - message is sent. - -From the BCM2835 ARM Peripherals datasheet: - - The ERR field is set when the slave fails to acknowledge either - its address or a data byte written to it. - -So when the controller doesn't receive an ack, it sets ERR and raises -an interrupt. In other words, the whole message is not sent. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index 54d510abd46a117c9238fc6d7edec84019d1f60d..565ef69ce61423544dc0558c85ef318b0ae9c324 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - if (likely(!i2c_dev->msg_err)) - return 0; - -- if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && -- (msg->flags & I2C_M_IGNORE_NAK)) -- return 0; -- - dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - -From e8a3cc458193ad57270e74ceff8f5059ecdfb0ba Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 04:54:27 +0200 -Subject: [PATCH 147/208] i2c: bcm2835: Add support for Repeated Start - Condition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Documentation/i2c/i2c-protocol states that Combined transactions should -separate messages with a Start bit and end the whole transaction with a -Stop bit. This patch adds support for issuing only a Start between -messages instead of a Stop followed by a Start. - -This implementation differs from downstream i2c-bcm2708 in 2 respects: -- it uses an interrupt to detect that the transfer is active instead - of using polling. There is no interrupt for Transfer Active, but by - not prefilling the FIFO it's possible to use the TXW interrupt. -- when resetting/disabling the controller between transfers it writes - CLEAR to the control register instead of just zero. - Using just zero gave many errors. This might be the reason why - downstream had to disable this feature and make it available with a - module parameter. - -I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) -and AT24C32 (eeprom) in parallel without problems. - -Signed-off-by: Noralf Trønnes -Acked-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++--------------- - 1 file changed, 63 insertions(+), 38 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index 565ef69ce61423544dc0558c85ef318b0ae9c324..241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev { - struct i2c_adapter adapter; - struct completion completion; - struct i2c_msg *curr_msg; -+ int num_msgs; - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) - } - - /* -+ * Repeated Start Condition (Sr) -+ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it -+ * talks about reading from a slave with 10 bit address. This is achieved by -+ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then -+ * issue a read. -+ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the -+ * firmware actually does it using polling and says that it's a workaround for -+ * a problem in the state machine. -+ * It turns out that it is possible to use the TXW interrupt to know when the -+ * transfer is active, provided the FIFO has not been prefilled. -+ */ -+ -+static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) ++static int rpi_backlight_update_status(struct backlight_device *bl) +{ -+ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN; -+ struct i2c_msg *msg = i2c_dev->curr_msg; -+ bool last_msg = (i2c_dev->num_msgs == 1); ++ struct rpi_backlight *gbl = bl_get_data(bl); ++ int brightness = bl->props.brightness; ++ int ret; + -+ if (!i2c_dev->num_msgs) -+ return; ++ if (bl->props.power != FB_BLANK_UNBLANK || ++ bl->props.fb_blank != FB_BLANK_UNBLANK || ++ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) ++ brightness = 0; + -+ i2c_dev->num_msgs--; -+ i2c_dev->msg_buf = msg->buf; -+ i2c_dev->msg_buf_remaining = msg->len; -+ -+ if (msg->flags & I2C_M_RD) -+ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; -+ else -+ c |= BCM2835_I2C_C_INTT; -+ -+ if (last_msg) -+ c |= BCM2835_I2C_C_INTD; -+ -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+} -+ -+/* - * Note about I2C_C_CLEAR on error: - * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in - * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through -@@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - } - - bcm2835_fill_txfifo(i2c_dev); -+ -+ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { -+ i2c_dev->curr_msg++; -+ bcm2835_i2c_start_transfer(i2c_dev); -+ } -+ - return IRQ_HANDLED; - } - -@@ -175,30 +221,25 @@ complete: - return IRQ_HANDLED; - } - --static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, -- struct i2c_msg *msg) -+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], -+ int num) - { -- u32 c; -+ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - unsigned long time_left; -+ int i; - -- i2c_dev->curr_msg = msg; -- i2c_dev->msg_buf = msg->buf; -- i2c_dev->msg_buf_remaining = msg->len; -- reinit_completion(&i2c_dev->completion); -- -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -+ for (i = 0; i < (num - 1); i++) -+ if (msgs[i].flags & I2C_M_RD) { -+ dev_warn_once(i2c_dev->dev, -+ "only one read message supported, has to be last\n"); -+ return -EOPNOTSUPP; -+ } - -- if (msg->flags & I2C_M_RD) { -- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; -- } else { -- c = BCM2835_I2C_C_INTT; -- bcm2835_fill_txfifo(i2c_dev); -- } -- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; -+ i2c_dev->curr_msg = msgs; -+ i2c_dev->num_msgs = num; -+ reinit_completion(&i2c_dev->completion); - -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+ bcm2835_i2c_start_transfer(i2c_dev); - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - BCM2835_I2C_TIMEOUT); -@@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - return -ETIMEDOUT; - } - -- if (likely(!i2c_dev->msg_err)) -- return 0; -+ if (!i2c_dev->msg_err) -+ return num; - - dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; -- else -- return -EIO; --} -- --static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], -- int num) --{ -- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); -- int i; -- int ret = 0; -- -- for (i = 0; i < num; i++) { -- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); -- if (ret) -- break; -- } - -- return ret ?: i; -+ return -EIO; - } - - static u32 bcm2835_i2c_func(struct i2c_adapter *adap) - -From 3b97a07025c5bda264cdec1cf56d84d7c5ee90be Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 04:57:17 +0200 -Subject: [PATCH 148/208] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use i2c_adapter->timeout for the completion timeout value. The core -default is 1 second. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index 241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f..d2085dd3742eabebc537621968088261f8dc7ea8 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -53,8 +53,6 @@ - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - --#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) -- - struct bcm2835_i2c_dev { - struct device *dev; - void __iomem *regs; -@@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - bcm2835_i2c_start_transfer(i2c_dev); - - time_left = wait_for_completion_timeout(&i2c_dev->completion, -- BCM2835_I2C_TIMEOUT); -+ adap->timeout); - if (!time_left) { - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, - BCM2835_I2C_C_CLEAR); - -From e67fa8bf66a0efa9d4604cb77c6f7b44a887618b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 27 Sep 2016 01:00:08 +0200 -Subject: [PATCH 149/208] i2c: bcm2835: Add support for dynamic clock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Support a dynamic clock by reading the frequency and setting the -divisor in the transfer function instead of during probe. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Martin Sperl ---- - drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++--------------- - 1 file changed, 32 insertions(+), 19 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index d2085dd3742eabebc537621968088261f8dc7ea8..c3436f627028477f7e21b47e079fd5ab06ec188a 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev { - void __iomem *regs; - struct clk *clk; - int irq; -+ u32 bus_clk_rate; - struct i2c_adapter adapter; - struct completion completion; - struct i2c_msg *curr_msg; -@@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) - return readl(i2c_dev->regs + reg); - } - -+static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ u32 divider; -+ -+ divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), -+ i2c_dev->bus_clk_rate); -+ /* -+ * Per the datasheet, the register is always interpreted as an even -+ * number, by rounding down. In other words, the LSB is ignored. So, -+ * if the LSB is set, increment the divider to avoid any issue. -+ */ -+ if (divider & 1) -+ divider++; -+ if ((divider < BCM2835_I2C_CDIV_MIN) || -+ (divider > BCM2835_I2C_CDIV_MAX)) { -+ dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); -+ return -EINVAL; ++ ret = rpi_firmware_property(gbl->fw, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, ++ &brightness, sizeof(brightness)); ++ if (ret) { ++ dev_err(gbl->dev, "Failed to set brightness\n"); ++ return ret; + } + -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); ++ if (brightness < 0) { ++ dev_err(gbl->dev, "Backlight change failed\n"); ++ return -EAGAIN; ++ } + + return 0; +} + - static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) - { - u32 val; -@@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - { - struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - unsigned long time_left; -- int i; -+ int i, ret; - - for (i = 0; i < (num - 1); i++) - if (msgs[i].flags & I2C_M_RD) { -@@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - return -EOPNOTSUPP; - } - -+ ret = bcm2835_i2c_set_divider(i2c_dev); -+ if (ret) -+ return ret; -+ - i2c_dev->curr_msg = msgs; - i2c_dev->num_msgs = num; - reinit_completion(&i2c_dev->completion); -@@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) - { - struct bcm2835_i2c_dev *i2c_dev; - struct resource *mem, *irq; -- u32 bus_clk_rate, divider; - int ret; - struct i2c_adapter *adap; - -@@ -306,27 +334,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) - } - - ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", -- &bus_clk_rate); -+ &i2c_dev->bus_clk_rate); - if (ret < 0) { - dev_warn(&pdev->dev, - "Could not read clock-frequency property\n"); -- bus_clk_rate = 100000; -- } -- -- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); -- /* -- * Per the datasheet, the register is always interpreted as an even -- * number, by rounding down. In other words, the LSB is ignored. So, -- * if the LSB is set, increment the divider to avoid any issue. -- */ -- if (divider & 1) -- divider++; -- if ((divider < BCM2835_I2C_CDIV_MIN) || -- (divider > BCM2835_I2C_CDIV_MAX)) { -- dev_err(&pdev->dev, "Invalid clock-frequency\n"); -- return -ENODEV; -+ i2c_dev->bus_clk_rate = 100000; - } -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); - - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) { - -From 93b4f7766d563b91a30df26ee3305e88d6d56c76 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 15:15:41 +0100 -Subject: [PATCH 150/208] i2c: bcm2835: Add debug support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds a debug module parameter to aid in debugging transfer issues -by printing info to the kernel log. When enabled, status values are -collected in the interrupt routine and msg info in -bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid -affecting timing. Having printk in the isr can mask issues. - -debug values (additive): -1: Print info on error -2: Print info on all transfers -3: Print messages before transfer is started - -The value can be changed at runtime: -/sys/module/i2c_bcm2835/parameters/debug - -Example output, debug=3: -[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] -[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] - -Signed-off-by: Noralf Trønnes ---- - drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 98 insertions(+), 1 deletion(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index c3436f627028477f7e21b47e079fd5ab06ec188a..8642f580ce41803bd22c76a0fa80d083d0747be1 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -53,6 +53,18 @@ - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - -+static unsigned int debug; -+module_param(debug, uint, 0644); -+MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); -+ -+#define BCM2835_DEBUG_MAX 512 -+struct bcm2835_debug { -+ struct i2c_msg *msg; -+ int msg_idx; -+ size_t remain; -+ u32 status; ++static const struct backlight_ops rpi_backlight_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .update_status = rpi_backlight_update_status, +}; + - struct bcm2835_i2c_dev { - struct device *dev; - void __iomem *regs; -@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -+ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; -+ unsigned int debug_num; -+ unsigned int debug_num_msgs; - }; - -+static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) ++static int rpi_backlight_probe(struct platform_device *pdev) +{ -+ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ return; ++ struct backlight_properties props; ++ struct backlight_device *bl; ++ struct rpi_backlight *gbl; ++ struct device_node *fw_node; + -+ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; -+ i2c_dev->debug[i2c_dev->debug_num].msg_idx = -+ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; -+ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; -+ i2c_dev->debug[i2c_dev->debug_num].status = s; -+ i2c_dev->debug_num++; -+} ++ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); ++ if (gbl == NULL) ++ return -ENOMEM; + -+static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, -+ struct bcm2835_debug *d) -+{ -+ u32 s = d->status; ++ gbl->dev = &pdev->dev; + -+ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", -+ d->remain, s, -+ s & BCM2835_I2C_S_TA ? "TA " : "", -+ s & BCM2835_I2C_S_DONE ? "DONE " : "", -+ s & BCM2835_I2C_S_TXW ? "TXW " : "", -+ s & BCM2835_I2C_S_RXR ? "RXR " : "", -+ s & BCM2835_I2C_S_TXD ? "TXD " : "", -+ s & BCM2835_I2C_S_RXD ? "RXD " : "", -+ s & BCM2835_I2C_S_TXE ? "TXE " : "", -+ s & BCM2835_I2C_S_RXF ? "RXF " : "", -+ s & BCM2835_I2C_S_ERR ? "ERR " : "", -+ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, -+ struct i2c_msg *msg, int i, int total, -+ const char *fname) -+{ -+ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", -+ fname, i, total, -+ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, -+ msg->flags & I2C_M_TEN ? "TEN" : "", -+ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", -+ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", -+ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", -+ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", -+ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", -+ msg->flags & I2C_M_STOP ? "STOP" : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ struct bcm2835_debug *d; -+ unsigned int i; -+ -+ for (i = 0; i < i2c_dev->debug_num; i++) { -+ d = &i2c_dev->debug[i]; -+ if (d->status == ~0) -+ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, -+ i2c_dev->debug_num_msgs, "start_transfer"); -+ else -+ bcm2835_debug_print_status(i2c_dev, d); ++ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ if (!fw_node) { ++ dev_err(&pdev->dev, "Missing firmware node\n"); ++ return -ENOENT; + } -+ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ pr_info("BCM2835_DEBUG_MAX reached\n"); ++ ++ gbl->fw = rpi_firmware_get(fw_node); ++ if (!gbl->fw) ++ return -EPROBE_DEFER; ++ ++ memset(&props, 0, sizeof(props)); ++ props.type = BACKLIGHT_RAW; ++ props.max_brightness = 255; ++ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), ++ &pdev->dev, gbl, &rpi_backlight_ops, ++ &props); ++ if (IS_ERR(bl)) { ++ dev_err(&pdev->dev, "failed to register backlight\n"); ++ return PTR_ERR(bl); ++ } ++ ++ bl->props.brightness = 255; ++ backlight_update_status(bl); ++ ++ platform_set_drvdata(pdev, bl); ++ return 0; +} + - static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, - u32 reg, u32 val) - { -@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+ bcm2835_debug_add(i2c_dev, ~0); - } - - /* -@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - u32 val, err; - - val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -+ bcm2835_debug_add(i2c_dev, val); - - err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if (err) { -@@ -251,6 +335,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - unsigned long time_left; - int i, ret; - -+ if (debug) -+ i2c_dev->debug_num_msgs = num; -+ -+ if (debug > 2) -+ for (i = 0; i < num; i++) -+ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); -+ - for (i = 0; i < (num - 1); i++) - if (msgs[i].flags & I2C_M_RD) { - dev_warn_once(i2c_dev->dev, -@@ -270,6 +361,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - adap->timeout); -+ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) -+ bcm2835_debug_print(i2c_dev); -+ i2c_dev->debug_num_msgs = 0; -+ i2c_dev->debug_num = 0; - if (!time_left) { - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, - BCM2835_I2C_C_CLEAR); -@@ -280,7 +375,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - if (!i2c_dev->msg_err) - return num; - -- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); -+ if (debug) -+ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", -+ i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; - -From 37134679c255f5b1b4c42e85b454c9dac1308e7f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 20:03:29 +0100 -Subject: [PATCH 151/208] config: Enable i2c-bcm2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index d246dd91b12d40a2d59d5e6758548471f1b195a0..816f832a5f676d905bfae1e06ae8003e38d5cff3 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -606,6 +606,7 @@ CONFIG_I2C=y - CONFIG_I2C_CHARDEV=m - CONFIG_I2C_MUX_PCA954x=m - CONFIG_I2C_BCM2708=m -+CONFIG_I2C_BCM2835=m - CONFIG_I2C_GPIO=m - CONFIG_SPI=y - CONFIG_SPI_BCM2835=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 27c61471a12a38feda62447af8010530bc89c141..98b2e5992a45a6212ef9a8b9826431d9fc024169 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -602,6 +602,7 @@ CONFIG_I2C=y - CONFIG_I2C_CHARDEV=m - CONFIG_I2C_MUX_PCA954x=m - CONFIG_I2C_BCM2708=m -+CONFIG_I2C_BCM2835=m - CONFIG_I2C_GPIO=m - CONFIG_SPI=y - CONFIG_SPI_BCM2835=m - -From 0abcf1feef4457158239d560a7c5c103eb1b347c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 15:42:55 +0100 -Subject: [PATCH 152/208] BCM270X_DT: Use i2c-bcm2835 as default -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -i2c-bcm2835 has gotten an overhaul so we can now use as default. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm270x.dtsi | 12 ------------ - 1 file changed, 12 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -index 7fb1f428332dc48bdd91dd4a0773f3bea7057238..514b481d4f4095dc8b55a216ac7335934973e145 100644 ---- a/arch/arm/boot/dts/bcm270x.dtsi -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -49,10 +49,6 @@ - dma-names = "tx", "rx"; - }; - -- i2c@7e205000 { /* i2c0 */ -- compatible = "brcm,bcm2708-i2c"; -- }; -- - pixelvalve0: pixelvalve@7e206000 { - /* Add alias */ - status = "disabled"; -@@ -104,14 +100,6 @@ - status = "disabled"; - }; - -- i2c@7e804000 { /* i2c1 */ -- compatible = "brcm,bcm2708-i2c"; -- }; -- -- i2c@7e805000 { /* i2c2 */ -- compatible = "brcm,bcm2708-i2c"; -- }; -- - pixelvalve2: pixelvalve@7e807000 { - /* Add alias */ - status = "disabled"; - -From 279b8a1317b5d18d1d61de902d95fb6fa60b08cc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 11 Nov 2016 18:24:26 +0100 -Subject: [PATCH 153/208] BCM270X_DT: Add fallback overlay for i2c-bcm2708 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 ++++++ - arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts | 13 +++++++++++++ - 3 files changed, 20 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 555bb5050aaf8464e209f35c50dc1f5c0295e585..7ef449dcfb206f9ab36d63b04bce9f9694c8c697 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -37,6 +37,7 @@ dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi-pro.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-bcm2708.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 4f9f0ac43f4fe2cb9376fff5a214ffdaf8179591..585f999474ca67155314f2e47d815b081a24d712 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -463,6 +463,12 @@ Params: speed Display SPI bus speed - ledgpio GPIO used to control backlight - - -+Name: i2c-bcm2708 -+Info: Fall back to the i2c_bcm2708 driver for the i2c_arm bus. -+Load: dtoverlay=i2c-bcm2708 -+Params: -+ -+ - Name: i2c-gpio - Info: Adds support for software i2c controller on gpio pins - Load: dtoverlay=i2c-gpio,= -diff --git a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..0afc6b405414c97428278dd3e8836759092aedb5 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts -@@ -0,0 +1,13 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ }; ++static const struct of_device_id rpi_backlight_of_match[] = { ++ { .compatible = "raspberrypi,rpi-backlight" }, ++ { /* sentinel */ } +}; - -From 4825aaa3b75f9a89acec9cfc3d13eaa0ff1eac4d Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 30 Sep 2016 10:07:27 -0700 -Subject: [PATCH 154/208] clk: bcm2835: Clamp the PLL's requested rate to the - hardware limits. - -Fixes setting low-resolution video modes on HDMI. Now the PLLH_PIX -divider adjusts itself until the PLLH is within bounds. - -Signed-off-by: Eric Anholt -Signed-off-by: Stephen Boyd ---- - drivers/clk/bcm/clk-bcm2835.c | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index cbbc8d4ddcffc797268c0ecb6477005fa14e228b..89645d63af53a3559c4b2e88f9a592fe11f5103f 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -502,8 +502,12 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate, - static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) - { -+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw); -+ const struct bcm2835_pll_data *data = pll->data; - u32 ndiv, fdiv; - -+ rate = clamp(rate, data->min_rate, data->max_rate); ++MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); + - bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv); - - return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1); -@@ -608,13 +612,6 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, - u32 ana[4]; - int i; - -- if (rate < data->min_rate || rate > data->max_rate) { -- dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n", -- clk_hw_get_name(hw), rate, -- data->min_rate, data->max_rate); -- return -EINVAL; -- } -- - if (rate > data->max_fb_rate) { - use_fb_prediv = true; - rate /= 2; - -From 2d17a0acdfe3de2822caab8c0ad00f7ef2b8f4b2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 1 Nov 2016 13:10:05 +0000 -Subject: [PATCH 155/208] config: Add CONFIG_HTU21 module - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 816f832a5f676d905bfae1e06ae8003e38d5cff3..a620bb77fd7934a9977adf3944bb2f3be9d83443 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1148,6 +1148,7 @@ CONFIG_IIO_KFIFO_BUF=m - CONFIG_MCP320X=m - CONFIG_MCP3422=m - CONFIG_DHT11=m -+CONFIG_HTU21=m - CONFIG_PWM_BCM2835=m - CONFIG_PWM_PCA9685=m - CONFIG_RASPBERRYPI_FIRMWARE=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 98b2e5992a45a6212ef9a8b9826431d9fc024169..43fc0a37f8bf2701aac84962203e7219645d5d7b 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1158,6 +1158,7 @@ CONFIG_IIO_KFIFO_BUF=m - CONFIG_MCP320X=m - CONFIG_MCP3422=m - CONFIG_DHT11=m -+CONFIG_HTU21=m - CONFIG_PWM_BCM2835=m - CONFIG_PWM_PCA9685=m - CONFIG_RASPBERRYPI_FIRMWARE=y - -From dc65fdccea2ae766cfa58a888f96072dca195659 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 5 Nov 2016 14:14:43 +0000 -Subject: [PATCH 156/208] bcm2708_fb: Add ioctl for reading gpu memory through - dma - ---- - drivers/video/fbdev/bcm2708_fb.c | 109 +++++++++++++++++++++++++++++++++++++++ - include/uapi/linux/fb.h | 7 +++ - 2 files changed, 116 insertions(+) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 37f60813fe1dd95d9f5f725c07ec2e75c09857bf..a6179186f5a65ebeb99bea34c546f690bb2fd903 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -31,8 +31,10 @@ - #include - #include - #include -+#include - #include - #include -+#include - #include - - //#define BCM2708_FB_DEBUG -@@ -426,6 +428,110 @@ static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info - return result; - } - -+static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, int size) -+{ -+ int burst_size = (fb->dma_chan == 0) ? 8 : 2; -+ struct bcm2708_dma_cb *cb = fb->cb_base; -+ -+ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | -+ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | -+ BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE; -+ cb->dst = dst; -+ cb->src = src; -+ cb->length = size; -+ cb->stride = 0; -+ cb->pad[0] = 0; -+ cb->pad[1] = 0; -+ cb->next = 0; -+ -+ if (size < dma_busy_wait_threshold) { -+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); -+ bcm_dma_wait_idle(fb->dma_chan_base); -+ } else { -+ void __iomem *dma_chan = fb->dma_chan_base; -+ cb->info |= BCM2708_DMA_INT_EN; -+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); -+ while (bcm_dma_is_busy(dma_chan)) { -+ wait_event_interruptible( -+ fb->dma_waitq, -+ !bcm_dma_is_busy(dma_chan)); -+ } -+ fb->stats.dma_irqs++; -+ } -+ fb->stats.dma_copies++; -+} -+ -+#define INTALIAS_NORMAL(x) ((x)&~0xc0000000) // address with no aliases -+#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000) // cache coherent but non-allocating in L1 and L2 -+ -+static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) -+{ -+ struct fb_dmacopy ioparam; -+ size_t size = PAGE_SIZE; -+ u32 *buf = NULL; -+ dma_addr_t bus_addr; -+ long rc = 0; -+ size_t offset; -+ struct { u32 base, length; } gpu = {}; -+ -+ /* restrict this to root user */ -+ if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) -+ { -+ rc = -EFAULT; -+ goto out; -+ } -+ -+ /* Get the parameter data. -+ */ -+ if (copy_from_user -+ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { -+ pr_err("[%s]: failed to copy-from-user\n", -+ __func__); -+ rc = -EFAULT; -+ goto out; -+ } -+ -+ rc = rpi_firmware_property(fb->fw, -+ RPI_FIRMWARE_GET_VC_MEMORY, -+ &gpu, sizeof(gpu)); -+ if (rc != 0 || gpu.base == 0 || gpu.length == 0) { -+ pr_err("[%s]: Unable to determine gpu memory %ld,%x,%x)\n", __func__, rc, gpu.base, gpu.length); -+ return -EFAULT; -+ } -+ -+ if (INTALIAS_NORMAL(ioparam.src) < gpu.base || INTALIAS_NORMAL(ioparam.src) >= gpu.base + gpu.length) { -+ pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__, INTALIAS_NORMAL(ioparam.src), gpu.base, gpu.base + gpu.length); -+ return -EFAULT; -+ } -+ -+ buf = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &bus_addr, -+ GFP_ATOMIC); -+ if (!buf) { -+ pr_err("[%s]: failed to dma_alloc_coherent(%d)\n", -+ __func__, size); -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ for (offset = 0; offset < ioparam.length; offset += size) { -+ size_t remaining = ioparam.length - offset; -+ size_t s = min(size, remaining); -+ unsigned char *p = (unsigned char *)ioparam.src + offset; -+ unsigned char *q = (unsigned char *)ioparam.dst + offset; -+ dma_memcpy(fb, (dma_addr_t)buf, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); -+ if (copy_to_user(q, buf, s) != 0) { -+ pr_err("[%s]: failed to copy-to-user\n", -+ __func__); -+ rc = -EFAULT; -+ goto out; -+ } -+ } -+out: -+ if (buf) -+ dma_free_coherent(NULL, PAGE_ALIGN(size), buf, bus_addr); -+ return rc; -+} -+ - static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) - { - struct bcm2708_fb *fb = to_bcm2708(info); -@@ -438,6 +544,9 @@ static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long a - RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, - &dummy, sizeof(dummy)); - break; -+ case FBIODMACOPY: -+ ret = vc_mem_copy(fb, arg); -+ break; - default: - dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd); - return -ENOTTY; -diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index fa72af0c981710fe80bacf4cf6612f6da19046ee..289e7c03c1e3308d5a02fc783af4a5692e791cfb 100644 ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -39,6 +39,7 @@ - * be concurrently added to the mainline kernel - */ - #define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) -+#define FBIODMACOPY _IOW('z', 0x22, struct fb_dmacopy) - - #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ - #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -@@ -351,6 +352,12 @@ struct fb_copyarea { - __u32 sy; - }; - -+struct fb_dmacopy { -+ dma_addr_t dst; -+ dma_addr_t src; -+ __u32 length; ++static struct platform_driver rpi_backlight_driver = { ++ .driver = { ++ .name = "rpi-backlight", ++ .of_match_table = of_match_ptr(rpi_backlight_of_match), ++ }, ++ .probe = rpi_backlight_probe, +}; + - struct fb_fillrect { - __u32 dx; /* screen-relative */ - __u32 dy; ++module_platform_driver(rpi_backlight_driver); ++ ++MODULE_AUTHOR("Gordon Hollingworth "); ++MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); ++MODULE_LICENSE("GPL"); -From 209d010a894c60b2d1d520b156ee388e7a1fcc9d Mon Sep 17 00:00:00 2001 +From 0d43b57dd46045cd251343c1ad168de2db528c01 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Fri, 11 Nov 2016 19:32:54 +0000 -Subject: [PATCH 157/208] rpi-ft5406: Create coherent buffer and push to - firmware +Date: Tue, 23 Feb 2016 19:56:04 +0000 +Subject: [PATCH 086/111] bcm2835-virtgpio: Virtual GPIO driver +Add a virtual GPIO driver that uses the firmware mailbox interface to +request that the VPU toggles LEDs. --- - drivers/input/touchscreen/rpi-ft5406.c | 152 +++++++++++++++++++---------- + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-bcm-virt.c | 214 +++++++++++++++++++++++++++++ include/soc/bcm2835/raspberrypi-firmware.h | 1 + - 2 files changed, 101 insertions(+), 52 deletions(-) + 4 files changed, 222 insertions(+) + create mode 100644 drivers/gpio/gpio-bcm-virt.c -diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c -index b27dbee8f56773dbd2a5503dc864747d0bebdddc..c5e31978c85a4ffd6839952ce0de50c001c7b875 100644 ---- a/drivers/input/touchscreen/rpi-ft5406.c -+++ b/drivers/input/touchscreen/rpi-ft5406.c -@@ -21,6 +21,7 @@ - #include - #include - #include +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index ed37e5908b910cd51cb378ffc171fe2a9104c082..edcb49f9051b703ce35fd1687a6cef8a31bf3627 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -134,6 +134,12 @@ config GPIO_BCM_KONA + help + Turn on GPIO support for Broadcom "Kona" chips. + ++config GPIO_BCM_VIRT ++ bool "Broadcom Virt GPIO" ++ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) ++ help ++ Turn on virtual GPIO support for Broadcom BCM283X chips. ++ + config GPIO_BRCMSTB + tristate "BRCMSTB GPIO support" + default y if (ARCH_BRCMSTB || BMIPS_GENERIC) +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index d074c2299393dc9cef3456b0068ff2d229677c27..cfb8d4bad6b0b20bed56643b0870fcff311c12c5 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -31,6 +31,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o + obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o + obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o + obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o ++obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o +diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c +new file mode 100644 +index 0000000000000000000000000000000000000000..c3725546def9d4a6264fbb1f6b9814d02b50e34e +--- /dev/null ++++ b/drivers/gpio/gpio-bcm-virt.c +@@ -0,0 +1,214 @@ ++/* ++ * brcmvirt GPIO driver ++ * ++ * Copyright (C) 2012,2013 Dom Cobley ++ * Based on gpio-clps711x.c by Alexander Shiyan ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include +#include - #include - - #define MAXIMUM_SUPPORTED_POINTS 10 -@@ -45,6 +46,7 @@ struct ft5406 { - struct platform_device * pdev; - struct input_dev * input_dev; - void __iomem * ts_base; -+ dma_addr_t bus_addr; - struct ft5406_regs * regs; - struct task_struct * thread; - }; -@@ -117,18 +119,19 @@ static int ft5406_thread(void *arg) - - static int ft5406_probe(struct platform_device *pdev) - { -- int ret; -- struct input_dev * input_dev = input_allocate_device(); ++#include ++ ++#define MODULE_NAME "brcmvirt-gpio" ++#define NUM_GPIO 2 ++ ++struct brcmvirt_gpio { ++ struct gpio_chip gc; ++ u32 __iomem *ts_base; ++ /* two packed 16-bit counts of enabled and disables ++ Allows host to detect a brief enable that was missed */ ++ u32 enables_disables[NUM_GPIO]; ++ dma_addr_t bus_addr; ++}; ++ ++static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return -EINVAL; ++} ++ ++static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return 0; ++} ++ ++static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ unsigned v; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ v = readl(gpio->ts_base + off); ++ return (v >> off) & 1; ++} ++ ++static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ u16 enables, disables; ++ s16 diff; ++ bool lit; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ enables = gpio->enables_disables[off] >> 16; ++ disables = gpio->enables_disables[off] >> 0; ++ diff = (s16)(enables - disables); ++ lit = diff > 0; ++ if ((val && lit) || (!val && !lit)) ++ return; ++ if (val) ++ enables++; ++ else ++ disables++; ++ diff = (s16)(enables - disables); ++ BUG_ON(diff != 0 && diff != 1); ++ gpio->enables_disables[off] = (enables << 16) | (disables << 0); ++ writel(gpio->enables_disables[off], gpio->ts_base + off); ++} ++ ++static int brcmvirt_gpio_probe(struct platform_device *pdev) ++{ + int err = 0; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; - struct ft5406 * ts; - struct device_node *fw_node; - struct rpi_firmware *fw; - u32 touchbuf; - -- dev_info(&pdev->dev, "Probing device\n"); -+ dev_info(dev, "Probing device\n"); - -- fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct brcmvirt_gpio *ucb; ++ u32 gpiovirtbuf; ++ + fw_node = of_parse_phandle(np, "firmware", 0); - if (!fw_node) { -- dev_err(&pdev->dev, "Missing firmware node\n"); ++ if (!fw_node) { + dev_err(dev, "Missing firmware node\n"); - return -ENOENT; - } - -@@ -136,62 +139,88 @@ static int ft5406_probe(struct platform_device *pdev) - if (!fw) - return -EPROBE_DEFER; - -- ret = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, -- &touchbuf, sizeof(touchbuf)); -- if (ret) { -- dev_err(&pdev->dev, "Failed to get touch buffer\n"); -- return ret; -+ ts = devm_kzalloc(dev, sizeof(struct ft5406), GFP_KERNEL); -+ if (!ts) { -+ dev_err(dev, "Failed to allocate memory\n"); -+ return -ENOMEM; - } - -- if (!touchbuf) { -- dev_err(&pdev->dev, "Touchscreen not detected\n"); -- return -ENODEV; -+ ts->input_dev = input_allocate_device(); -+ if (!ts->input_dev) { -+ dev_err(dev, "Failed to allocate input device\n"); -+ return -ENOMEM; - } - -- dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", touchbuf); -+ ts->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->bus_addr, GFP_KERNEL); -+ if (!ts->ts_base) { -+ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", -+ __func__, PAGE_SIZE); -+ err = -ENOMEM; -+ goto out; -+ } - -- ts = kzalloc(sizeof(struct ft5406), GFP_KERNEL); -+ touchbuf = (u32)ts->bus_addr; -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, -+ &touchbuf, sizeof(touchbuf)); - -- if (!ts || !input_dev) { -- ret = -ENOMEM; -- dev_err(&pdev->dev, "Failed to allocate memory\n"); -- return ret; -+ if (err || touchbuf != 0) { -+ dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n", err); -+ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); -+ ts->ts_base = 0; -+ ts->bus_addr = 0; ++ return -ENOENT; + } + -+ if (!ts->ts_base) { -+ dev_warn(dev, "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n", err, touchbuf, ts->ts_base, ts->bus_addr); ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; + -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, -+ &touchbuf, sizeof(touchbuf)); -+ if (err) { -+ dev_err(dev, "Failed to get touch buffer\n"); -+ goto out; -+ } -+ -+ if (!touchbuf) { -+ dev_err(dev, "Touchscreen not detected\n"); -+ err = -ENODEV; -+ goto out; -+ } -+ -+ dev_dbg(dev, "Got TS buffer 0x%x\n", touchbuf); -+ -+ // mmap the physical memory -+ touchbuf &= ~0xc0000000; -+ ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -+ if (ts->ts_base == NULL) -+ { -+ dev_err(dev, "Failed to map physical address\n"); -+ err = -ENOMEM; -+ goto out; -+ } - } -- ts->input_dev = input_dev; - platform_set_drvdata(pdev, ts); - ts->pdev = pdev; - -- input_dev->name = "FT5406 memory based driver"; -+ ts->input_dev->name = "FT5406 memory based driver"; - -- __set_bit(EV_KEY, input_dev->evbit); -- __set_bit(EV_SYN, input_dev->evbit); -- __set_bit(EV_ABS, input_dev->evbit); -+ __set_bit(EV_KEY, ts->input_dev->evbit); -+ __set_bit(EV_SYN, ts->input_dev->evbit); -+ __set_bit(EV_ABS, ts->input_dev->evbit); - -- input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, -+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, - SCREEN_WIDTH, 0, 0); -- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, -+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, - SCREEN_HEIGHT, 0, 0); - -- input_mt_init_slots(input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); -+ input_mt_init_slots(ts->input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); - -- input_set_drvdata(input_dev, ts); -+ input_set_drvdata(ts->input_dev, ts); - -- ret = input_register_device(input_dev); -- if (ret) { -- dev_err(&pdev->dev, "could not register input device, %d\n", -- ret); -- return ret; -- } -- -- // mmap the physical memory -- touchbuf &= ~0xc0000000; -- ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -- if(ts->ts_base == NULL) -- { -- dev_err(&pdev->dev, "Failed to map physical address\n"); -- input_unregister_device(input_dev); -- kzfree(ts); -- return -ENOMEM; -+ err = input_register_device(ts->input_dev); -+ if (err) { -+ dev_err(dev, "could not register input device, %d\n", -+ err); ++ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); ++ if (!ucb) { ++ err = -EINVAL; + goto out; - } - - ts->regs = (struct ft5406_regs *) ts->ts_base; -@@ -200,25 +229,44 @@ static int ft5406_probe(struct platform_device *pdev) - ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); - if(ts->thread == NULL) - { -- dev_err(&pdev->dev, "Failed to create kernel thread"); -- iounmap(ts->ts_base); -- input_unregister_device(input_dev); -- kzfree(ts); -+ dev_err(dev, "Failed to create kernel thread"); -+ err = -ENOMEM; -+ goto out; - } - - return 0; -+ -+out: -+ if (ts->bus_addr) { -+ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); -+ ts->bus_addr = 0; -+ ts->ts_base = NULL; -+ } else if (ts->ts_base) { -+ iounmap(ts->ts_base); -+ ts->ts_base = NULL; + } -+ if (ts->input_dev) { -+ input_unregister_device(ts->input_dev); -+ ts->input_dev = NULL; -+ } -+ return err; - } - - static int ft5406_remove(struct platform_device *pdev) - { -+ struct device *dev = &pdev->dev; - struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev); - -- dev_info(&pdev->dev, "Removing rpi-ft5406\n"); -+ dev_info(dev, "Removing rpi-ft5406\n"); - - kthread_stop(ts->thread); -- iounmap(ts->ts_base); -- input_unregister_device(ts->input_dev); -- kzfree(ts); + -+ if (ts->bus_addr) -+ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); -+ else if (ts->ts_base) -+ iounmap(ts->ts_base); -+ if (ts->input_dev) -+ input_unregister_device(ts->input_dev); - - return 0; - } -diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index 227a107214a02deadcca3db202da265eba1fdd21..b0f6e33bd30c35664ceee057f4c3ad32b914291d 100644 ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -115,6 +115,7 @@ enum rpi_firmware_property_tag { - RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, - RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, - RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, - RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, - RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, - - -From e9817038e0442920814b404514373ea9e7838573 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 9 Nov 2016 22:42:39 +0000 -Subject: [PATCH 158/208] brcmvirt_gpio: Create coherent buffer and push to - firmware - ---- - drivers/gpio/gpio-bcm-virt.c | 89 +++++++++++++++++++++--------- - include/soc/bcm2835/raspberrypi-firmware.h | 1 + - 2 files changed, 63 insertions(+), 27 deletions(-) - -diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c -index f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4..c3725546def9d4a6264fbb1f6b9814d02b50e34e 100644 ---- a/drivers/gpio/gpio-bcm-virt.c -+++ b/drivers/gpio/gpio-bcm-virt.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - - #define MODULE_NAME "brcmvirt-gpio" -@@ -25,6 +26,7 @@ struct brcmvirt_gpio { - /* two packed 16-bit counts of enabled and disables - Allows host to detect a brief enable that was missed */ - u32 enables_disables[NUM_GPIO]; -+ dma_addr_t bus_addr; - }; - - static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) -@@ -75,13 +77,13 @@ static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) - - static int brcmvirt_gpio_probe(struct platform_device *pdev) - { -+ int err = 0; - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct device_node *fw_node; - struct rpi_firmware *fw; - struct brcmvirt_gpio *ucb; - u32 gpiovirtbuf; -- int err = 0; - - fw_node = of_parse_phandle(np, "firmware", 0); - if (!fw_node) { -@@ -93,35 +95,56 @@ static int brcmvirt_gpio_probe(struct platform_device *pdev) - if (!fw) - return -EPROBE_DEFER; - -- err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, -- &gpiovirtbuf, sizeof(gpiovirtbuf)); -- -- if (err) { -- dev_err(dev, "Failed to get gpiovirtbuf\n"); -- goto err; -- } -- -- if (!gpiovirtbuf) { -- dev_err(dev, "No virtgpio buffer\n"); -- err = -ENOENT; -- goto err; -- } -- - ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); - if (!ucb) { - err = -EINVAL; -- goto err; -+ goto out; - } - -- // mmap the physical memory -- gpiovirtbuf &= ~0xc0000000; -- ucb->ts_base = ioremap(gpiovirtbuf, 4096); -- if (ucb->ts_base == NULL) { -- dev_err(dev, "Failed to map physical address\n"); -- err = -ENOENT; -- goto err; + ucb->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ucb->bus_addr, GFP_KERNEL); + if (!ucb->ts_base) { + pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", + __func__, PAGE_SIZE); + err = -ENOMEM; + goto out; - } - ++ } ++ + gpiovirtbuf = (u32)ucb->bus_addr; + err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF, + &gpiovirtbuf, sizeof(gpiovirtbuf)); @@ -146408,19 +118119,25 @@ index f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4..c3725546def9d4a6264fbb1f6b9814d0 + } + ucb->bus_addr = 0; + } - ucb->gc.label = MODULE_NAME; - ucb->gc.owner = THIS_MODULE; - //ucb->gc.dev = dev; -@@ -137,22 +160,34 @@ static int brcmvirt_gpio_probe(struct platform_device *pdev) - - err = gpiochip_add(&ucb->gc); - if (err) -- goto err; ++ ucb->gc.label = MODULE_NAME; ++ ucb->gc.owner = THIS_MODULE; ++ //ucb->gc.dev = dev; ++ ucb->gc.of_node = np; ++ ucb->gc.base = 100; ++ ucb->gc.ngpio = NUM_GPIO; ++ ++ ucb->gc.direction_input = brcmvirt_gpio_dir_in; ++ ucb->gc.direction_output = brcmvirt_gpio_dir_out; ++ ucb->gc.get = brcmvirt_gpio_get; ++ ucb->gc.set = brcmvirt_gpio_set; ++ ucb->gc.can_sleep = true; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) + goto out; - - platform_set_drvdata(pdev, ucb); - --err: ++ ++ platform_set_drvdata(pdev, ucb); ++ + return 0; +out: + if (ucb->bus_addr) { @@ -146431,25 +118148,44 @@ index f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4..c3725546def9d4a6264fbb1f6b9814d0 + iounmap(ucb->ts_base); + ucb->ts_base = NULL; + } - return err; -- - } - - static int brcmvirt_gpio_remove(struct platform_device *pdev) - { ++ return err; ++} ++ ++static int brcmvirt_gpio_remove(struct platform_device *pdev) ++{ + struct device *dev = &pdev->dev; - int err = 0; - struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); - - gpiochip_remove(&ucb->gc); -- iounmap(ucb->ts_base); ++ int err = 0; ++ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&ucb->gc); + if (ucb->bus_addr) + dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); + else if (ucb->ts_base) + iounmap(ucb->ts_base); - return err; - } - ++ return err; ++} ++ ++static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { ++ { .compatible = "brcm,bcm2835-virtgpio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); ++ ++static struct platform_driver brcmvirt_gpio_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), ++ }, ++ .probe = brcmvirt_gpio_probe, ++ .remove = brcmvirt_gpio_remove, ++}; ++module_platform_driver(brcmvirt_gpio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Dom Cobley "); ++MODULE_DESCRIPTION("brcmvirt GPIO driver"); ++MODULE_ALIAS("platform:brcmvirt-gpio"); diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h index b0f6e33bd30c35664ceee057f4c3ad32b914291d..e92278968b2b979db2a1f855f70e7aafb224fa98 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h @@ -146463,1369 +118199,5261 @@ index b0f6e33bd30c35664ceee057f4c3ad32b914291d..e92278968b2b979db2a1f855f70e7aaf RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, -From 1dff7d0212f9ac143489397d6da93253d8c79efa Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 14 Nov 2016 22:05:30 +0000 -Subject: [PATCH 159/208] fixup: fb: Use basic types for dma addresses as these - are also included from user code - ---- - include/uapi/linux/fb.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index 289e7c03c1e3308d5a02fc783af4a5692e791cfb..703fa8a70574323abe2fb32599254582cd5d891f 100644 ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -353,8 +353,8 @@ struct fb_copyarea { - }; - - struct fb_dmacopy { -- dma_addr_t dst; -- dma_addr_t src; -+ void *dst; -+ __u32 src; - __u32 length; - }; - - -From 5a82ccf30428b49333f0fcc3ca1729c97cb71592 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 12 Nov 2016 20:28:25 +0100 -Subject: [PATCH 160/208] BCM270x_DT: Drop using ARCH_BCM2708 and ARCH_BCM2709 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Both are based on ARCH_BCM2835 so use that instead. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 25 ++--- - arch/arm/boot/dts/overlays/Makefile | 199 +++++++++++++++++------------------- - 2 files changed, 101 insertions(+), 123 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 0cb86b7a5ab212fee36a34b3672856d27c446593..d59b0f01cdbd7ebe1d660701f47353746faeded6 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -1,23 +1,14 @@ - ifeq ($(CONFIG_OF),y) - --dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b.dtb --dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b-plus.dtb --dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-cm.dtb --dtb-$(CONFIG_ARCH_BCM2709) += bcm2709-rpi-2-b.dtb --dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb --dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb -+dtb-$(CONFIG_ARCH_BCM2835) += \ -+ bcm2708-rpi-b.dtb \ -+ bcm2708-rpi-b-plus.dtb \ -+ bcm2708-rpi-cm.dtb \ -+ bcm2709-rpi-2-b.dtb \ -+ bcm2710-rpi-3-b.dtb \ -+ bcm2710-rpi-cm3.dtb - --# Raspberry Pi --ifeq ($(CONFIG_ARCH_BCM2708),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(CONFIG_ARCH_BCM2709),y) -- RPI_DT_OVERLAYS=y --endif - ifeq ($(CONFIG_ARCH_BCM2835),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(RPI_DT_OVERLAYS),y) - dts-dirs += overlays - endif - -@@ -954,6 +945,6 @@ subdir-y := $(dts-dirs) - clean-files := *.dtb - - # Enable fixups to support overlays on BCM2708 platforms --ifeq ($(RPI_DT_OVERLAYS),y) -+ifeq ($(CONFIG_ARCH_BCM2835),y) - DTC_FLAGS ?= -@ -H epapr - endif -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 7ef449dcfb206f9ab36d63b04bce9f9694c8c697..c940eb3b685d7b9af4340ff184ca736471183e09 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -1,114 +1,101 @@ --ifeq ($(CONFIG_OF),y) -- - # Overlays for the Raspberry Pi platform - --ifeq ($(CONFIG_ARCH_BCM2708),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(CONFIG_ARCH_BCM2709),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(CONFIG_ARCH_BCM2835),y) -- RPI_DT_OVERLAYS=y --endif -- --dtbo-$(RPI_DT_OVERLAYS) += adau1977-adc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += ads1015.dtbo --dtbo-$(RPI_DT_OVERLAYS) += ads7846.dtbo --dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo --dtbo-$(RPI_DT_OVERLAYS) += allo-piano-dac-pcm512x-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo --dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += audremap.dtbo --dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dionaudio-loco.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dpi18.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo --dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo --dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo --dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-amp.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacplus.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi-pro.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-bcm2708.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo --dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo --dtbo-$(RPI_DT_OVERLAYS) += iqaudio-digi-wm8804-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp23s17.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mz61581.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pi3-act-led.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pi3-disable-bt.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pi3-miniuart-bt.dtbo --dtbo-$(RPI_DT_OVERLAYS) += piscreen.dtbo --dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pisound.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft35-resistive.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pps-gpio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pwm.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pwm-2chan.dtbo --dtbo-$(RPI_DT_OVERLAYS) += qca7000.dtbo --dtbo-$(RPI_DT_OVERLAYS) += raspidac3.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-backlight.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-display.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-ft5406.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-proto.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-sense.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rra-digidac1-wm8741-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sc16is750-i2c.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sc16is752-spi1.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi0-hw-cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo --dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo --dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo --dtbo-$(RPI_DT_OVERLAYS) += vga666.dtbo --dtbo-$(RPI_DT_OVERLAYS) += w1-gpio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += w1-gpio-pullup.dtbo --dtbo-$(RPI_DT_OVERLAYS) += wittypi.dtbo -+dtbo-$(CONFIG_ARCH_BCM2835) += \ -+ adau1977-adc.dtbo \ -+ ads1015.dtbo \ -+ ads7846.dtbo \ -+ akkordion-iqdacplus.dtbo \ -+ allo-piano-dac-pcm512x-audio.dtbo \ -+ at86rf233.dtbo \ -+ audioinjector-wm8731-audio.dtbo \ -+ audremap.dtbo \ -+ bmp085_i2c-sensor.dtbo \ -+ dht11.dtbo \ -+ dionaudio-loco.dtbo \ -+ dpi18.dtbo \ -+ dpi24.dtbo \ -+ dwc-otg.dtbo \ -+ dwc2.dtbo \ -+ enc28j60.dtbo \ -+ gpio-ir.dtbo \ -+ gpio-poweroff.dtbo \ -+ hifiberry-amp.dtbo \ -+ hifiberry-dac.dtbo \ -+ hifiberry-dacplus.dtbo \ -+ hifiberry-digi.dtbo \ -+ hifiberry-digi-pro.dtbo \ -+ hy28a.dtbo \ -+ hy28b.dtbo \ -+ i2c-bcm2708.dtbo \ -+ i2c-gpio.dtbo \ -+ i2c-mux.dtbo \ -+ i2c-pwm-pca9685a.dtbo \ -+ i2c-rtc.dtbo \ -+ i2c0-bcm2708.dtbo \ -+ i2c1-bcm2708.dtbo \ -+ i2s-gpio28-31.dtbo \ -+ iqaudio-dac.dtbo \ -+ iqaudio-dacplus.dtbo \ -+ iqaudio-digi-wm8804-audio.dtbo \ -+ justboom-dac.dtbo \ -+ justboom-digi.dtbo \ -+ lirc-rpi.dtbo \ -+ mcp23017.dtbo \ -+ mcp23s17.dtbo \ -+ mcp2515-can0.dtbo \ -+ mcp2515-can1.dtbo \ -+ mmc.dtbo \ -+ mz61581.dtbo \ -+ pi3-act-led.dtbo \ -+ pi3-disable-bt.dtbo \ -+ pi3-miniuart-bt.dtbo \ -+ piscreen.dtbo \ -+ piscreen2r.dtbo \ -+ pisound.dtbo \ -+ pitft22.dtbo \ -+ pitft28-capacitive.dtbo \ -+ pitft28-resistive.dtbo \ -+ pitft35-resistive.dtbo \ -+ pps-gpio.dtbo \ -+ pwm.dtbo \ -+ pwm-2chan.dtbo \ -+ qca7000.dtbo \ -+ raspidac3.dtbo \ -+ rpi-backlight.dtbo \ -+ rpi-dac.dtbo \ -+ rpi-display.dtbo \ -+ rpi-ft5406.dtbo \ -+ rpi-proto.dtbo \ -+ rpi-sense.dtbo \ -+ rra-digidac1-wm8741-audio.dtbo \ -+ sc16is750-i2c.dtbo \ -+ sc16is752-spi1.dtbo \ -+ sdhost.dtbo \ -+ sdio.dtbo \ -+ sdio-1bit.dtbo \ -+ sdtweak.dtbo \ -+ smi.dtbo \ -+ smi-dev.dtbo \ -+ smi-nand.dtbo \ -+ spi-gpio35-39.dtbo \ -+ spi-rtc.dtbo \ -+ spi0-hw-cs.dtbo \ -+ spi1-1cs.dtbo \ -+ spi1-2cs.dtbo \ -+ spi1-3cs.dtbo \ -+ spi2-1cs.dtbo \ -+ spi2-2cs.dtbo \ -+ spi2-3cs.dtbo \ -+ tinylcd35.dtbo \ -+ uart1.dtbo \ -+ vc4-kms-v3d.dtbo \ -+ vga666.dtbo \ -+ w1-gpio.dtbo \ -+ w1-gpio-pullup.dtbo \ -+ wittypi.dtbo - - targets += dtbs dtbs_install - targets += $(dtbo-y) - --endif -- - always := $(dtbo-y) - clean-files := *.dtbo - -From 1c930dafefdf565e34d8e8246702c5dbcbcd6f84 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 12 Nov 2016 20:28:47 +0100 -Subject: [PATCH 161/208] Drop ARCH_BCM2708 and ARCH_BCM2709 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -They are not necessary anymore since both are based on ARCH_BCM2835. -Also use the compatible strings "brcm,bcm2835", "brcm,bcm2836" and "brcm,bcm2837". - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 - - arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 - - arch/arm/boot/dts/bcm2708.dtsi | 3 --- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 - - arch/arm/boot/dts/bcm2709.dtsi | 3 --- - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 1 - - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 1 - - arch/arm/boot/dts/bcm2710.dtsi | 4 ++-- - arch/arm/configs/bcm2709_defconfig | 2 +- - arch/arm/configs/bcmrpi_defconfig | 2 +- - arch/arm/mach-bcm/Kconfig | 19 ++----------------- - arch/arm/mach-bcm/board_bcm2835.c | 28 ---------------------------- - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 4 ++-- - 13 files changed, 8 insertions(+), 62 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 6bd8df44dc9163589074c1dec8a3ec69a47fb458..360da5c928dc5599b0d2a9055728087604c6b189 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -3,7 +3,6 @@ - #include "bcm2708.dtsi" - - / { -- compatible = "brcm,bcm2708"; - model = "Raspberry Pi Model B+"; - }; - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index ba80832726004b1b0719f570a7d8b3a390344d56..9c49659ab246bce0656f3514f3b924bc4826b421 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -3,7 +3,6 @@ - #include "bcm2708.dtsi" - - / { -- compatible = "brcm,bcm2708"; - model = "Raspberry Pi Model B"; - }; - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 663843965027da5dbaefbec1285e275c56746367..0f72bd90c591a2e8752d7437fa7e8c6308bd8c3f 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -3,9 +3,6 @@ - #include "bcm2708-rpi.dtsi" - - / { -- compatible = "brcm,bcm2708"; -- model = "BCM2708"; -- - soc { - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 4f79aaae149abc6f8ebc076d493eb8459e469862..19c83823420fc3cc20a01d07091100cb8720ff4d 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -3,7 +3,6 @@ - #include "bcm2709.dtsi" - - / { -- compatible = "brcm,bcm2709"; - model = "Raspberry Pi 2 Model B"; - }; - -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index b1d82f9026d02e8b5371cbb4d8a144e67207a276..343437db94820bb75a9b81e8bc6ecf6f31d9f04c 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -3,9 +3,6 @@ - #include "bcm2708-rpi.dtsi" - - / { -- compatible = "brcm,bcm2709"; -- model = "BCM2709"; -- - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index 30060663ca712578f6d697fd02a3b31d94301707..cb1694da24b54d4024109fc481aa67f73e15e31f 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -7,7 +7,6 @@ - #include "bcm2710.dtsi" - - / { -- compatible = "brcm,bcm2710","brcm,bcm2709"; - model = "Raspberry Pi 3 Model B"; - }; - -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index d13e3d4dac4e198c8cac451e3f64ef687e2ace1b..41874c25a84226c0e4af92ec4059e0a571fe6123 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -3,7 +3,6 @@ - #include "bcm2710.dtsi" - - / { -- compatible = "brcm,bcm2710","brcm,bcm2709"; - model = "Raspberry Pi Compute Module 3"; - }; - -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index df1a4ce1cd4e570876b7785b357d6c31f66191a4..f6def5d7e5d622cf09e8f87332c7374fe28da08b 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -3,8 +3,8 @@ - #include "bcm2708-rpi.dtsi" - - / { -- compatible = "brcm,bcm2710","brcm,bcm2709"; -- model = "BCM2710"; -+ compatible = "brcm,bcm2837", "brcm,bcm2836"; -+ model = "BCM2837"; - - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index a620bb77fd7934a9977adf3944bb2f3be9d83443..5b7d6177c69eec697a7db2c356263f7770938bd7 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -38,7 +38,7 @@ CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_BCM=y --CONFIG_ARCH_BCM2709=y -+CONFIG_ARCH_BCM2835=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_SMP=y - CONFIG_VMSPLIT_2G=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 43fc0a37f8bf2701aac84962203e7219645d5d7b..1834f3070bcde9dee21482483e95b9313fad6fc4 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -39,7 +39,7 @@ CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_MULTI_V6=y - # CONFIG_ARCH_MULTI_V7 is not set - CONFIG_ARCH_BCM=y --CONFIG_ARCH_BCM2708=y -+CONFIG_ARCH_BCM2835=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y -diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 929a5fa241fa94134993c61a137d1f79b514d64b..3968816e0ee07b813d30ca4bbdbe3f21ea97224e 100644 ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -156,33 +156,18 @@ config ARCH_BCM2835 - select FIQ - select PINCTRL - select PINCTRL_BCM2835 -+ select MFD_SYSCON if ARCH_MULTI_V7 - help - This enables support for the Broadcom BCM2835 and BCM2836 SoCs. - This SoC is used in the Raspberry Pi and Roku 2 devices. - - config MACH_BCM2708 - bool "Enable optimized __copy_to_user and __copy_from_user" -- depends on ARCH_BCM2708 -+ depends on ARCH_BCM2835 && ARCH_MULTI_V6 - default y - help - Optimized versions of __copy_to_user and __copy_from_user for Pi1. - --config ARCH_BCM2708 -- bool "Broadcom BCM2708 family" -- depends on ARCH_MULTI_V6 -- select ARCH_BCM2835 -- help -- This enables support for Broadcom BCM2708 boards. -- --config ARCH_BCM2709 -- bool "Broadcom BCM2709 family" -- depends on ARCH_MULTI_V7 -- select ARCH_BCM2835 -- select HAVE_SMP -- select MFD_SYSCON -- help -- This enables support for Broadcom BCM2709 boards. -- - config ARCH_BCM_63XX - bool "Broadcom BCM63xx DSL SoC" - depends on ARCH_MULTI_V7 -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index efbd18020479c1cab40ce680446a4259c62c83cb..133338f0a21237fda9b7660d2c57a33b991f08ae 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -66,31 +66,3 @@ DT_MACHINE_START(BCM2835, "BCM2835") - .init_early = bcm2835_init_early, - .dt_compat = bcm2835_compat - MACHINE_END -- --#ifdef CONFIG_ARCH_BCM2708 --static const char * const bcm2708_compat[] = { -- "brcm,bcm2708", -- NULL --}; -- --DT_MACHINE_START(BCM2708, "BCM2708") -- .init_machine = bcm2835_init, -- .reserve = bcm2835_board_reserve, -- .init_early = bcm2835_init_early, -- .dt_compat = bcm2708_compat, --MACHINE_END --#endif -- --#ifdef CONFIG_ARCH_BCM2709 --static const char * const bcm2709_compat[] = { -- "brcm,bcm2709", -- NULL --}; -- --DT_MACHINE_START(BCM2709, "BCM2709") -- .init_machine = bcm2835_init, -- .reserve = bcm2835_board_reserve, -- .init_early = bcm2835_init_early, -- .dt_compat = bcm2709_compat, --MACHINE_END --#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -index 85d82f31cb49631f03b23631882d2b6c063b33db..13047c08fb71cc6e44c66096720d4654d3f9e4e1 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -@@ -78,7 +78,7 @@ void notrace _fiq_print(enum fiq_debug_level dbg_lvl, volatile struct fiq_state - * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock - * Must be called with local interrupts and FIQ disabled. - */ --#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) -+#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) - inline void fiq_fsm_spin_lock(fiq_lock_t *lock) - { - unsigned long tmp; -@@ -111,7 +111,7 @@ inline void fiq_fsm_spin_lock(fiq_lock_t *lock) { } - /** - * fiq_fsm_spin_unlock() - ARMv6+ bare bones spinunlock - */ --#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) -+#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) - inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) - { - smp_mb(); - -From 947658a7a79e668f6421a94226e0a39dbbe3abe5 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 15 Nov 2016 15:58:49 +0000 -Subject: [PATCH 162/208] mkknlimg: Retain downstream-kernel detection - -With the death of ARCH_BCM2708 and ARCH_BCM2709, a new way is needed to -determine if this is a "downstream" build that wants the firmware to -load a bcm27xx .dtb. The vc_cma driver is used downstream but not -upstream, making vc_cma_init a suitable predicate symbol. ---- - scripts/mkknlimg | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -index a21f7e31bc904233e980e66ae3e6337e2eab0f1c..60206de7fa9a49bd027c635306674a29a568652f 100755 ---- a/scripts/mkknlimg -+++ b/scripts/mkknlimg -@@ -78,6 +78,7 @@ my $wanted_strings = - 'brcm,bcm2835' => FLAG_PI | FLAG_DTOK | FLAG_283X, - 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, - 'of_cfs_init' => FLAG_DTOK | FLAG_DDTK, -+ 'vc_cma_init' => FLAG_PI | FLAG_270X, - }; - - my $res = try_extract($kernel_file, $tmpfile1); - -From a30274434c39f55c32b179a06fbb57e3d3990294 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 16 Nov 2016 21:17:27 +0000 -Subject: [PATCH 163/208] fixup: fb: Use correct bus address for dest of dma - memcpy - ---- - drivers/video/fbdev/bcm2708_fb.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index a6179186f5a65ebeb99bea34c546f690bb2fd903..0d22e00a0adf2959f94b2f0897888c127062e8d5 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -435,7 +435,7 @@ static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, in - - cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | - BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | -- BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE; -+ BCM2708_DMA_D_INC; - cb->dst = dst; - cb->src = src; - cb->length = size; -@@ -518,7 +518,7 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) - size_t s = min(size, remaining); - unsigned char *p = (unsigned char *)ioparam.src + offset; - unsigned char *q = (unsigned char *)ioparam.dst + offset; -- dma_memcpy(fb, (dma_addr_t)buf, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); -+ dma_memcpy(fb, bus_addr, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); - if (copy_to_user(q, buf, s) != 0) { - pr_err("[%s]: failed to copy-to-user\n", - __func__); - -From b000467a6ec25d6e512ade86b384074608c6289f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 17 Nov 2016 16:49:33 +0000 -Subject: [PATCH 164/208] fixup: fb: Use struct device for dma_alloc_coherent - ---- - drivers/video/fbdev/bcm2708_fb.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 0d22e00a0adf2959f94b2f0897888c127062e8d5..53c5a0bdadb4be9251affdabed66305842a08e72 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -504,7 +504,7 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) - return -EFAULT; - } - -- buf = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &bus_addr, -+ buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr, - GFP_ATOMIC); - if (!buf) { - pr_err("[%s]: failed to dma_alloc_coherent(%d)\n", -@@ -528,7 +528,7 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) - } - out: - if (buf) -- dma_free_coherent(NULL, PAGE_ALIGN(size), buf, bus_addr); -+ dma_free_coherent(fb->fb.device, PAGE_ALIGN(size), buf, bus_addr); - return rc; - } - - -From 805037ddae8a2857a35e5afa5635bcb77fb3534c Mon Sep 17 00:00:00 2001 +From 6e12f2b19d43ee028bfa2a9118585e65bec5c450 Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Fri, 18 Nov 2016 10:52:49 +0000 -Subject: [PATCH 165/208] ARM: dts: Visit overlays subdir unconditionally +Date: Tue, 23 Feb 2016 17:26:48 +0000 +Subject: [PATCH 087/111] amba_pl011: Don't use DT aliases for numbering -make clean processing occurs without loading the configuration, so the -overlays subdir must be added unconditionally. - -See: https://github.com/raspberrypi/linux/issues/1723 +The pl011 driver looks for DT aliases of the form "serial", +and if found uses as the device ID. This can cause +/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the +other serial port is provided by the 8250 driver which doesn't +use the same logic. --- - arch/arm/boot/dts/Makefile | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index d59b0f01cdbd7ebe1d660701f47353746faeded6..c8d3d5ac5b49b4bf2b2fb16078f1c5d56c75ac65 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -8,10 +8,6 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ - bcm2710-rpi-3-b.dtb \ - bcm2710-rpi-cm3.dtb - --ifeq ($(CONFIG_ARCH_BCM2835),y) -- dts-dirs += overlays --endif -- - dtb-$(CONFIG_ARCH_ALPINE) += \ - alpine-db.dtb - dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -941,7 +937,7 @@ dtstree := $(srctree)/$(src) - dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) - - always := $(dtb-y) --subdir-y := $(dts-dirs) -+subdir-y := $(dts-dirs) overlays - clean-files := *.dtb - - # Enable fixups to support overlays on BCM2708 platforms - -From 858b913571ad2b5a9b9f3f91c074b3255a3d18f0 Mon Sep 17 00:00:00 2001 -From: Matt Flax -Date: Sun, 20 Nov 2016 19:15:24 +1100 -Subject: [PATCH 166/208] [Audioinjector] Fix bit offsets for equal volume and - add 8 kHz operation (#1727) - -Applying to the audioinjector sound card only. This patch offsets channel -2 correctly from the LR clock. This ensures that channel 2 doesn't loose -any bits during capture. It also results in both channels 1 and 2 having -the same volume. This commit also adds 8 kHz operation. - -Signed-off-by: Matt Flax ---- - sound/soc/bcm/audioinjector-pi-soundcard.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c -index 5ff0985e07efb96b95634a65995f09f7c68d9e99..ef54e0f07ea03f59e9957b5d98f3e7fdc998e469 100644 ---- a/sound/soc/bcm/audioinjector-pi-soundcard.c -+++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -30,7 +30,7 @@ - #include "../codecs/wm8731.h" - - static const unsigned int bcm2835_rates_12000000[] = { -- 32000, 44100, 48000, 96000, 88200, -+ 8000, 16000, 32000, 44100, 48000, 96000, 88200, - }; - - static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { -@@ -55,19 +55,21 @@ static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *su - - switch (params_rate(params)){ - case 8000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1); -+ case 16000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 750); - case 32000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 375); - case 44100: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 272); - case 48000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 250); - case 88200: - return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); - case 96000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); - default: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); - } - } - - -From 3f01663c3ec2c0ae2a82a46b9484c5726052c295 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Sat, 26 Nov 2016 14:01:52 +0000 -Subject: [PATCH 167/208] ARM: dts: Restore dtbs_install functionality - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/Makefile | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index c8d3d5ac5b49b4bf2b2fb16078f1c5d56c75ac65..950714000b98cf92e60a72d8dde4774a8ef55429 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -937,10 +937,11 @@ dtstree := $(srctree)/$(src) - dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) - - always := $(dtb-y) --subdir-y := $(dts-dirs) overlays -+subdir-y := overlays - clean-files := *.dtb - --# Enable fixups to support overlays on BCM2708 platforms -+# Enable fixups to support overlays on BCM2835 platforms - ifeq ($(CONFIG_ARCH_BCM2835),y) - DTC_FLAGS ?= -@ -H epapr -+ dts-dirs += overlays - endif - -From 8569d7041b8778339e0a4cc6bf49aaf3c1dc4887 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 23 Nov 2016 14:19:40 +0000 -Subject: [PATCH 168/208] config: Add ABX80X RTC driver and overlay - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/README | 12 ++++++++++-- - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 12 +++++++++++- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 4 files changed, 23 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 585f999474ca67155314f2e47d815b081a24d712..180122b381361469ca9e8c4e14f4aa52c1f351dd 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -504,7 +504,11 @@ Params: addr I2C address of PCA9685A (default 0x40) - Name: i2c-rtc - Info: Adds support for a number of I2C Real Time Clock devices - Load: dtoverlay=i2c-rtc,= --Params: ds1307 Select the DS1307 device -+Params: abx80x Select one of the ABx80x family: -+ AB0801, AB0803, AB0804, AB0805, -+ AB1801, AB1803, AB1804, AB1805 -+ -+ ds1307 Select the DS1307 device - - ds1339 Select the DS1339 device - -@@ -520,7 +524,11 @@ Params: ds1307 Select the DS1307 device - - pcf8563 Select the PCF8563 device - -- trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) -+ trickle-diode-type Diode type for trickle charge - "standard" or -+ "schottky" (ABx80x only) -+ -+ trickle-resistor-ohms Resistor value for trickle charge (DS1339, -+ ABx80x) - - wakeup-source Specify that the RTC can be used as a wakeup - source -diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -index 8b6f978155c02409eeb7c83353b8194fa3462435..1efcf0b712c9c5c19210545002ac1f0931db58f5 100644 ---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -12,6 +12,13 @@ - #size-cells = <0>; - status = "okay"; - -+ abx80x: abx80x@69 { -+ compatible = "abracon,abx80x"; -+ reg = <0x69>; -+ abracon,tc-diode = "standard"; -+ abracon,tc-resistor = <0>; -+ status = "disable"; -+ }; - ds1307: ds1307@68 { - compatible = "maxim,ds1307"; - reg = <0x68>; -@@ -56,6 +63,7 @@ - }; - }; - __overrides__ { -+ abx80x = <&abx80x>,"status"; - ds1307 = <&ds1307>,"status"; - ds1339 = <&ds1339>,"status"; - ds3231 = <&ds3231>,"status"; -@@ -64,7 +72,9 @@ - pcf2127 = <&pcf2127>,"status"; - pcf8523 = <&pcf8523>,"status"; - pcf8563 = <&pcf8563>,"status"; -- trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; -+ trickle-diode-type = <&abx80x>,"abracon,tc-diode"; -+ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0", -+ <&abx80x>,"abracon,tc-resistor"; - wakeup-source = <&ds1339>,"wakeup-source?", - <&ds3231>,"wakeup-source?", - <&mcp7940x>,"wakeup-source?", -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 5b7d6177c69eec697a7db2c356263f7770938bd7..10b32a493f244521e6b3a17d54da192e7006db28 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1054,6 +1054,7 @@ CONFIG_LEDS_TRIGGER_INPUT=y - CONFIG_LEDS_TRIGGER_PANIC=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_ABX80X=m - CONFIG_RTC_DRV_DS1307=m - CONFIG_RTC_DRV_DS1374=m - CONFIG_RTC_DRV_DS1672=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 1834f3070bcde9dee21482483e95b9313fad6fc4..2979c31c583cba95096ce449ebc0ccdfa417b838 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1064,6 +1064,7 @@ CONFIG_LEDS_TRIGGER_INPUT=y - CONFIG_LEDS_TRIGGER_PANIC=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_ABX80X=m - CONFIG_RTC_DRV_DS1307=m - CONFIG_RTC_DRV_DS1374=m - CONFIG_RTC_DRV_DS1672=m - -From 17fa71aa67409771c6e323c905d6f07a49c0265b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 25 Nov 2016 15:01:15 +0000 -Subject: [PATCH 169/208] config: Add AK4554 audio codec driver - -See: https://github.com/raspberrypi/linux/issues/1730 - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 10b32a493f244521e6b3a17d54da192e7006db28..48ed6bfe263a6a3fab942d0b52b2f409055f23ad 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -876,6 +876,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 2979c31c583cba95096ce449ebc0ccdfa417b838..ff69cafd7fb706fc0069d59c37974c4ce5d50043 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -871,6 +871,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m - -From d93ed366eb57a05214b58910e6ee763d7bb16bb9 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson <6by9@users.noreply.github.com> -Date: Wed, 30 Nov 2016 20:17:14 +0000 -Subject: [PATCH 170/208] BCM2835-v4l2: Fix a conformance test failure - -Format ioctls: - test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK - warn: v4l2-test-formats.cpp(1195): S_PARM is supported but - doesn't report V4L2_CAP_TIMEPERFRAME. - fail: v4l2-test-formats.cpp(1118): node->has_frmintervals - && !cap->capability ---- - drivers/media/platform/bcm2835/bcm2835-camera.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index cb5bab642eaab2f60d641801dd0afdac45b7698f..4f03949aecf3afbf2e04df38289447195a8847a6 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -1399,6 +1399,7 @@ static int vidioc_s_parm(struct file *file, void *priv, - dev->capture.timeperframe = tpf; - parm->parm.capture.timeperframe = tpf; - parm->parm.capture.readbuffers = 1; -+ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - - fps_param.num = 0; /* Select variable fps, and then use - * FPS_RANGE to select the actual limits. - -From 1b81b02455bce965fbd642bce2eea1370b9461e2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 1 Dec 2016 15:32:23 +0000 -Subject: [PATCH 171/208] hifiberry: Make driver names unique in first 15 - characters - -See: LibreELEC PR1001 ---- - sound/soc/bcm/hifiberry_amp.c | 1 + - sound/soc/bcm/hifiberry_dac.c | 1 + - sound/soc/bcm/hifiberry_dacplus.c | 1 + - sound/soc/bcm/hifiberry_digi.c | 1 + - 4 files changed, 4 insertions(+) - -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -index 0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1..d17c29780507dc31c50f1d567ff5cea7c8241ff5 100644 ---- a/sound/soc/bcm/hifiberry_amp.c -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -61,6 +61,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { - - static struct snd_soc_card snd_rpi_hifiberry_amp = { - .name = "snd_rpi_hifiberry_amp", -+ .driver_name = "HifiberryAmp", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_amp_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -index 29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8..45f2b770ad9e67728ca599a7445d6ae9a01c0c29 100644 ---- a/sound/soc/bcm/hifiberry_dac.c -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -63,6 +63,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_hifiberry_dac = { - .name = "snd_rpi_hifiberry_dac", -+ .driver_name = "HifiberryDac", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_dac_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -index 65600674c286e8a7be8efd352d5a80889221a1d6..bdc35e7e6bc12dc1cf04f5ffad8f9ab49a0b0266 100644 ---- a/sound/soc/bcm/hifiberry_dacplus.c -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -291,6 +291,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_hifiberry_dacplus = { - .name = "snd_rpi_hifiberry_dacplus", -+ .driver_name = "HifiberryDacp", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_dacplus_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 52ab9dea2e724c4238986ca53c59c8492f64e345..19dc953b7227ba86123fc7a2ba654499e0c581c5 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -202,6 +202,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_hifiberry_digi = { - .name = "snd_rpi_hifiberry_digi", -+ .driver_name = "HifiberryDigi", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_digi_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), - -From c0c3bcda197b84fefc31ea5ef4a3c4c71d61d6cf Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 1 Dec 2016 22:58:07 +0000 -Subject: [PATCH 172/208] BCM2835 DT: Add DTC_FLAGS to support overlays - -Signed-off-by: Phil Elwell ---- - arch/arm64/boot/dts/broadcom/Makefile | 5 +++++ + drivers/tty/serial/amba-pl011.c | 5 +++++ 1 file changed, 5 insertions(+) -diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index 2152448c8cf5b22c573642d7ce45e85793f5fc9a..d6a4c2fccf68e4c692973e36b749e3571979ee5e 100644 ---- a/arch/arm64/boot/dts/broadcom/Makefile -+++ b/arch/arm64/boot/dts/broadcom/Makefile -@@ -6,3 +6,8 @@ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb - always := $(dtb-y) - subdir-y := $(dts-dirs) - clean-files := *.dtb -+ -+# Enable fixups to support overlays on BCM2835 platforms -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ DTC_FLAGS ?= -@ -H epapr -+endif +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index e2c33b9528d82ed7a2c27d083d7b1d222da68178..5a11ff833e1fd112ba04df3a427cd94bf6793ec5 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -2441,7 +2441,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, + if (IS_ERR(base)) + return PTR_ERR(base); + ++ /* Don't use DT serial aliases - it causes the device to ++ be renumbered to ttyAMA1 if it is the second serial port in the ++ system, even though the other one is ttyS0. The 8250 driver ++ doesn't use this logic, so always remains ttyS0. + index = pl011_probe_dt_alias(index, dev); ++ */ + + uap->old_cr = 0; + uap->port.dev = dev; -From b220b620b64b4663af9e6c285a9b8a6edb6b93be Mon Sep 17 00:00:00 2001 -From: Gerhard de Clercq -Date: Fri, 2 Dec 2016 12:15:26 +0200 -Subject: [PATCH 173/208] Add overlays symlink and dtbo target for ARM64 - (#1739) +From 71ead171a2d5a1c560884f919ff0c81f2dd07f0c Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Wed, 3 Dec 2014 13:23:28 +0200 +Subject: [PATCH 088/111] OF: DT-Overlay configfs interface -Signed-off-by: Gerhard de Clercq +This is a port of Pantelis Antoniou's v3 port that makes use of the +new upstreamed configfs support for binary attributes. + +Original commit message: + +Add a runtime interface to using configfs for generic device tree overlay +usage. With it its possible to use device tree overlays without having +to use a per-platform overlay manager. + +Please see Documentation/devicetree/configfs-overlays.txt for more info. + +Changes since v2: +- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) +- Created a documentation entry +- Slight rewording in Kconfig + +Changes since v1: +- of_resolve() -> of_resolve_phandles(). + +Originally-signed-off-by: Pantelis Antoniou +Signed-off-by: Phil Elwell + +DT configfs: Fix build errors on other platforms + +Signed-off-by: Phil Elwell + +DT configfs: fix build error + +There is an error when compiling rpi-4.6.y branch: + CC drivers/of/configfs.o +drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] + .default_groups = of_cfs_def_groups, + ^ +drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') + +The .default_groups is linked list since commit +1ae1602de028acaa42a0f6ff18d19756f8e825c6. +This commit uses configfs_add_default_group to fix this problem. + +Signed-off-by: Slawomir Stepien --- - arch/arm64/Makefile | 3 +++ - arch/arm64/boot/dts/Makefile | 1 + - arch/arm64/boot/dts/overlays | 1 + - 3 files changed, 5 insertions(+) - create mode 120000 arch/arm64/boot/dts/overlays + Documentation/devicetree/configfs-overlays.txt | 31 +++ + drivers/of/Kconfig | 7 + + drivers/of/Makefile | 1 + + drivers/of/configfs.c | 311 +++++++++++++++++++++++++ + 4 files changed, 350 insertions(+) + create mode 100644 Documentation/devicetree/configfs-overlays.txt + create mode 100644 drivers/of/configfs.c -diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile -index 5b54f8c021d8332624839e1c7eb8249eff7ba360..64c6bf2b75d1036fc73d43d1ecd2ebb4809f8a62 100644 ---- a/arch/arm64/Makefile -+++ b/arch/arm64/Makefile -@@ -102,6 +102,9 @@ zinstall install: - - %.dtb: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ -+ -+%.dtbo: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ - - PHONY += dtbs dtbs_install - -diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile -index 6e199c90367664a18a50b20372d58cbd57ba3276..4c203fb0be6dffb9057e8066bf21e83cedea92f6 100644 ---- a/arch/arm64/boot/dts/Makefile -+++ b/arch/arm64/boot/dts/Makefile -@@ -19,6 +19,7 @@ dts-dirs += socionext - dts-dirs += sprd - dts-dirs += xilinx - dts-dirs += lg -+dts-dirs += overlays - - subdir-y := $(dts-dirs) - -diff --git a/arch/arm64/boot/dts/overlays b/arch/arm64/boot/dts/overlays -new file mode 120000 -index 0000000000000000000000000000000000000000..413315acbfe83611bb2ae7cbd0da1039f47de34c ---- /dev/null -+++ b/arch/arm64/boot/dts/overlays -@@ -0,0 +1 @@ -+../../../arm/boot/dts/overlays/ -\ No newline at end of file - -From 0edb708d26ed355b63c61db6007b89ae8ce5a2ae Mon Sep 17 00:00:00 2001 -From: Alan Yiding Wang -Date: Sat, 3 Dec 2016 23:22:02 -0500 -Subject: [PATCH 174/208] BCM270X_DT: Add overlay for enc28j60 on SPI2 - -Works on SPI2 for compute module ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 10 ++++- - .../boot/dts/overlays/enc28j60-spi2-overlay.dts | 47 ++++++++++++++++++++++ - 3 files changed, 57 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index c940eb3b685d7b9af4340ff184ca736471183e09..20440abbe9a440d1f748b118f9c0ee3a0dbd039f 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -17,6 +17,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - dwc-otg.dtbo \ - dwc2.dtbo \ - enc28j60.dtbo \ -+ enc28j60-spi2.dtbo \ - gpio-ir.dtbo \ - gpio-poweroff.dtbo \ - hifiberry-amp.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 180122b381361469ca9e8c4e14f4aa52c1f351dd..4be81958d0f8a790c6a725b2367cf3f33ceaaec9 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -344,13 +344,21 @@ Params: dr_mode Dual role mode: "host", "peripheral" or "otg" - - - Name: enc28j60 --Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI0 - Load: dtoverlay=enc28j60,= - Params: int_pin GPIO used for INT (default 25) - - speed SPI bus speed (default 12000000) - - -+Name: enc28j60-spi2 -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI2 -+Load: dtoverlay=enc28j60-spi2,= -+Params: int_pin GPIO used for INT (default 39) -+ -+ speed SPI bus speed (default 12000000) -+ -+ - Name: gpio-ir - Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- - based gpio_ir_recv driver maps received keys directly to a -diff --git a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts +diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt new file mode 100644 -index 0000000000000000000000000000000000000000..946c9d2107a83335b11f094e75945a509595ab7c +index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad --- /dev/null -+++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts -@@ -0,0 +1,47 @@ -+// Overlay for the Microchip ENC28J60 Ethernet Controller - SPI2 Compute Module -+// Interrupt pin: 39 -+/dts-v1/; -+/plugin/; ++++ b/Documentation/devicetree/configfs-overlays.txt +@@ -0,0 +1,31 @@ ++Howto use the configfs overlay interface. + -+/ { -+ compatible = "brcm,bcm2708"; ++A device-tree configfs entry is created in /config/device-tree/overlays ++and and it is manipulated using standard file system I/O. ++Note that this is a debug level interface, for use by developers and ++not necessarily something accessed by normal users due to the ++security implications of having direct access to the kernel's device tree. + -+ fragment@0 { -+ target = <&spi2>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; ++* To create an overlay you mkdir the directory: + -+ status = "okay"; ++ # mkdir /config/device-tree/overlays/foo + -+ eth1: enc28j60@0{ -+ compatible = "microchip,enc28j60"; -+ reg = <0>; /* CE0 */ -+ pinctrl-names = "default"; -+ pinctrl-0 = <ð1_pins>; -+ interrupt-parent = <&gpio>; -+ interrupts = <39 0x2>; /* falling edge */ -+ spi-max-frequency = <12000000>; -+ status = "okay"; -+ }; -+ }; -+ }; ++* Either you echo the overlay firmware file to the path property file. + -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ eth1_pins: eth1_pins { -+ brcm,pins = <39>; -+ brcm,function = <0>; /* in */ -+ brcm,pull = <0>; /* none */ -+ }; -+ }; -+ }; ++ # echo foo.dtbo >/config/device-tree/overlays/foo/path + -+ __overrides__ { -+ int_pin = <ð1>, "interrupts:0", -+ <ð1_pins>, "brcm,pins:0"; -+ speed = <ð1>, "spi-max-frequency:0"; -+ }; ++* Or you cat the contents of the overlay to the dtbo file ++ ++ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo ++ ++The overlay file will be applied, and devices will be created/destroyed ++as required. ++ ++To remove it simply rmdir the directory. ++ ++ # rmdir /config/device-tree/overlays/foo ++ ++The rationalle of the dual interface (firmware & direct copy) is that each is ++better suited to different use patterns. The firmware interface is what's ++intended to be used by hardware managers in the kernel, while the copy interface ++make sense for developers (since it avoids problems with namespaces). +diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig +index ba7b034b2b91c94afb1b7135cdee7fc3d6955828..de0da10d66e6cdc6eedc4d36cf247370627f83f4 100644 +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -112,4 +112,11 @@ config OF_OVERLAY + config OF_NUMA + bool + ++config OF_CONFIGFS ++ bool "Device Tree Overlay ConfigFS interface" ++ select CONFIGFS_FS ++ select OF_OVERLAY ++ help ++ Enable a simple user-space driven DT overlay interface. ++ + endif # OF +diff --git a/drivers/of/Makefile b/drivers/of/Makefile +index d7efd9d458aab4554139e93c72a1688aa0eeef6a..aa5ef9dd1fedc14d4ae2d363818fc160df51bad9 100644 +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,4 +1,5 @@ + obj-y = base.o device.o platform.o ++obj-$(CONFIG_OF_CONFIGFS) += configfs.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o + obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o +diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b6ea6cad7 +--- /dev/null ++++ b/drivers/of/configfs.c +@@ -0,0 +1,311 @@ ++/* ++ * Configfs entries for device-tree ++ * ++ * Copyright (C) 2013 - Pantelis Antoniou ++ * ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "of_private.h" ++ ++struct cfs_overlay_item { ++ struct config_item item; ++ ++ char path[PATH_MAX]; ++ ++ const struct firmware *fw; ++ struct device_node *overlay; ++ int ov_id; ++ ++ void *dtbo; ++ int dtbo_size; +}; ++ ++static int create_overlay(struct cfs_overlay_item *overlay, void *blob) ++{ ++ int err; ++ ++ /* unflatten the tree */ ++ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); ++ if (overlay->overlay == NULL) { ++ pr_err("%s: failed to unflatten tree\n", __func__); ++ err = -EINVAL; ++ goto out_err; ++ } ++ pr_debug("%s: unflattened OK\n", __func__); ++ ++ /* mark it as detached */ ++ of_node_set_flag(overlay->overlay, OF_DETACHED); ++ ++ /* perform resolution */ ++ err = of_resolve_phandles(overlay->overlay); ++ if (err != 0) { ++ pr_err("%s: Failed to resolve tree\n", __func__); ++ goto out_err; ++ } ++ pr_debug("%s: resolved OK\n", __func__); ++ ++ err = of_overlay_create(overlay->overlay); ++ if (err < 0) { ++ pr_err("%s: Failed to create overlay (err=%d)\n", ++ __func__, err); ++ goto out_err; ++ } ++ overlay->ov_id = err; ++ ++out_err: ++ return err; ++} ++ ++static inline struct cfs_overlay_item *to_cfs_overlay_item( ++ struct config_item *item) ++{ ++ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; ++} ++ ++static ssize_t cfs_overlay_item_path_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ return sprintf(page, "%s\n", overlay->path); ++} ++ ++static ssize_t cfs_overlay_item_path_store(struct config_item *item, ++ const char *page, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ const char *p = page; ++ char *s; ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy to path buffer (and make sure it's always zero terminated */ ++ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); ++ overlay->path[sizeof(overlay->path) - 1] = '\0'; ++ ++ /* strip trailing newlines */ ++ s = overlay->path + strlen(overlay->path); ++ while (s > overlay->path && *--s == '\n') ++ *s = '\0'; ++ ++ pr_debug("%s: path is '%s'\n", __func__, overlay->path); ++ ++ err = request_firmware(&overlay->fw, overlay->path, NULL); ++ if (err != 0) ++ goto out_err; ++ ++ err = create_overlay(overlay, (void *)overlay->fw->data); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ ++ release_firmware(overlay->fw); ++ overlay->fw = NULL; ++ ++ overlay->path[0] = '\0'; ++ return err; ++} ++ ++static ssize_t cfs_overlay_item_status_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ return sprintf(page, "%s\n", ++ overlay->ov_id >= 0 ? "applied" : "unapplied"); ++} ++ ++CONFIGFS_ATTR(cfs_overlay_item_, path); ++CONFIGFS_ATTR_RO(cfs_overlay_item_, status); ++ ++static struct configfs_attribute *cfs_overlay_attrs[] = { ++ &cfs_overlay_item_attr_path, ++ &cfs_overlay_item_attr_status, ++ NULL, ++}; ++ ++ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, ++ void *buf, size_t max_count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ pr_debug("%s: buf=%p max_count=%zu\n", __func__, ++ buf, max_count); ++ ++ if (overlay->dtbo == NULL) ++ return 0; ++ ++ /* copy if buffer provided */ ++ if (buf != NULL) { ++ /* the buffer must be large enough */ ++ if (overlay->dtbo_size > max_count) ++ return -ENOSPC; ++ ++ memcpy(buf, overlay->dtbo, overlay->dtbo_size); ++ } ++ ++ return overlay->dtbo_size; ++} ++ ++ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, ++ const void *buf, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy the contents */ ++ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); ++ if (overlay->dtbo == NULL) ++ return -ENOMEM; ++ ++ overlay->dtbo_size = count; ++ ++ err = create_overlay(overlay, overlay->dtbo); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ kfree(overlay->dtbo); ++ overlay->dtbo = NULL; ++ overlay->dtbo_size = 0; ++ ++ return err; ++} ++ ++CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); ++ ++static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { ++ &cfs_overlay_item_attr_dtbo, ++ NULL, ++}; ++ ++static void cfs_overlay_release(struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ if (overlay->ov_id >= 0) ++ of_overlay_destroy(overlay->ov_id); ++ if (overlay->fw) ++ release_firmware(overlay->fw); ++ /* kfree with NULL is safe */ ++ kfree(overlay->dtbo); ++ kfree(overlay); ++} ++ ++static struct configfs_item_operations cfs_overlay_item_ops = { ++ .release = cfs_overlay_release, ++}; ++ ++static struct config_item_type cfs_overlay_type = { ++ .ct_item_ops = &cfs_overlay_item_ops, ++ .ct_attrs = cfs_overlay_attrs, ++ .ct_bin_attrs = cfs_overlay_bin_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_item *cfs_overlay_group_make_item( ++ struct config_group *group, const char *name) ++{ ++ struct cfs_overlay_item *overlay; ++ ++ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); ++ if (!overlay) ++ return ERR_PTR(-ENOMEM); ++ overlay->ov_id = -1; ++ ++ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); ++ return &overlay->item; ++} ++ ++static void cfs_overlay_group_drop_item(struct config_group *group, ++ struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ config_item_put(&overlay->item); ++} ++ ++static struct configfs_group_operations overlays_ops = { ++ .make_item = cfs_overlay_group_make_item, ++ .drop_item = cfs_overlay_group_drop_item, ++}; ++ ++static struct config_item_type overlays_type = { ++ .ct_group_ops = &overlays_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct configfs_group_operations of_cfs_ops = { ++ /* empty - we don't allow anything to be created */ ++}; ++ ++static struct config_item_type of_cfs_type = { ++ .ct_group_ops = &of_cfs_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++struct config_group of_cfs_overlay_group; ++ ++static struct configfs_subsystem of_cfs_subsys = { ++ .su_group = { ++ .cg_item = { ++ .ci_namebuf = "device-tree", ++ .ci_type = &of_cfs_type, ++ }, ++ }, ++ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), ++}; ++ ++static int __init of_cfs_init(void) ++{ ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ config_group_init(&of_cfs_subsys.su_group); ++ config_group_init_type_name(&of_cfs_overlay_group, "overlays", ++ &overlays_type); ++ configfs_add_default_group(&of_cfs_overlay_group, ++ &of_cfs_subsys.su_group); ++ ++ ret = configfs_register_subsystem(&of_cfs_subsys); ++ if (ret != 0) { ++ pr_err("%s: failed to register subsys\n", __func__); ++ goto out; ++ } ++ pr_info("%s: OK\n", __func__); ++out: ++ return ret; ++} ++late_initcall(of_cfs_init); -From 8d454bd4ff18ff2daeeddca6803edb68401c377c Mon Sep 17 00:00:00 2001 -From: Gerhard de Clercq -Date: Fri, 2 Dec 2016 13:45:06 +0200 -Subject: [PATCH 175/208] RPI-FT5406: Enable aarch64 support through explicit - iomem interface +From 2d043fc762bf4cc4aa2595adaad26496dfeb6eb8 Mon Sep 17 00:00:00 2001 +From: Cheong2K +Date: Fri, 26 Feb 2016 18:20:10 +0800 +Subject: [PATCH 089/111] brcm: adds support for BCM43341 wifi -Signed-off-by: Gerhard de Clercq ---- - drivers/input/touchscreen/rpi-ft5406.c | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) +brcmfmac: Disable power management -diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c -index c5e31978c85a4ffd6839952ce0de50c001c7b875..9d7d05482355d168c5c0c42508cd978979ee5f14 100644 ---- a/drivers/input/touchscreen/rpi-ft5406.c -+++ b/drivers/input/touchscreen/rpi-ft5406.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -47,7 +48,6 @@ struct ft5406 { - struct input_dev * input_dev; - void __iomem * ts_base; - dma_addr_t bus_addr; -- struct ft5406_regs * regs; - struct task_struct * thread; - }; - -@@ -68,8 +68,8 @@ static int ft5406_thread(void *arg) - { - // 60fps polling - msleep_interruptible(17); -- memcpy_fromio(®s, ts->regs, sizeof(*ts->regs)); -- writel(99, &ts->regs->num_points); -+ memcpy_fromio(®s, ts->ts_base, sizeof(struct ft5406_regs)); -+ iowrite8(99, ts->ts_base + offsetof(struct ft5406_regs, num_points)); - // Do not output if theres no new information (num_points is 99) - // or we have no touch points and don't need to release any - if(!(regs.num_points == 99 || (regs.num_points == 0 && known_ids == 0))) -@@ -190,7 +190,7 @@ static int ft5406_probe(struct platform_device *pdev) - - // mmap the physical memory - touchbuf &= ~0xc0000000; -- ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -+ ts->ts_base = ioremap(touchbuf, sizeof(struct ft5406_regs)); - if (ts->ts_base == NULL) - { - dev_err(dev, "Failed to map physical address\n"); -@@ -222,8 +222,6 @@ static int ft5406_probe(struct platform_device *pdev) - err); - goto out; - } -- -- ts->regs = (struct ft5406_regs *) ts->ts_base; - - // create thread to poll the touch events - ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); +Disable wireless power saving in the brcmfmac WLAN driver. This is a +temporary measure until the connectivity loss resulting from power +saving is resolved. -From f014240610c93a7e95d58b5869a6d89209685e7b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 6 Dec 2016 17:27:50 +0000 -Subject: [PATCH 176/208] BCM270X_DT: Add midi-uart0 overlay +Signed-off-by: Phil Elwell -MIDI requires 31.25kbaud, a baudrate unsupported by Linux. The -midi-uart0 overlay configures uart0 (ttyAMA0) to use a fake clock -so that requesting 38.4kbaud actually gets 31.25kbaud. +brcmfmac: Use original country code as a fallback + +Commit 73345fd212980d2e28a5c6d83801c903bd773680: + + brcmfmac: Configure country code using device specific settings + +prevents region codes from working on devices that lack a region code +translation table. In the event of an absent table, preserve the old +behaviour of using the provided code as-is. + +Signed-off-by: Phil Elwell + +brcmfmac: Plug memory leak in brcmf_fill_bss_param + +See: https://github.com/raspberrypi/linux/issues/1471 + +Signed-off-by: Phil Elwell + +brcmfmac: do not use internal roaming engine by default + +Some evidence of curing disconnects with this disabled, so make it a default. +Can be overridden with module parameter roamoff=0 +See: http://projectable.me/optimize-my-pi-wi-fi/ + +brcmfmac: Change stop_ap sequence + +Patch from Broadcom/Cypress to resolve a customer error Signed-off-by: Phil Elwell --- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 7 +++++ - arch/arm/boot/dts/overlays/midi-uart0-overlay.dts | 36 +++++++++++++++++++++++ - 3 files changed, 44 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/midi-uart0-overlay.dts + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 31 ++++++++++++++++------ + .../wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ + .../broadcom/brcm80211/include/brcm_hw_ids.h | 1 + + 4 files changed, 27 insertions(+), 9 deletions(-) -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 20440abbe9a440d1f748b118f9c0ee3a0dbd039f..a3ddb4577ce1f671f4c23ebe32c434c97b00781c 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -45,6 +45,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - mcp23s17.dtbo \ - mcp2515-can0.dtbo \ - mcp2515-can1.dtbo \ -+ midi-uart0.dtbo \ - mmc.dtbo \ - mz61581.dtbo \ - pi3-act-led.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 4be81958d0f8a790c6a725b2367cf3f33ceaaec9..496e31db0c7d22934bd381aea5e7227c26a3f034 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -725,6 +725,13 @@ Params: oscillator Clock frequency for the CAN controller (Hz) - interrupt GPIO for interrupt signal +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 78d9966a3957b2b934fe6b21de5cade494ec2839..3fcb1887b2d312e050c02e9fe66ea20f48f0abcb 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2756,6 +2756,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, + * preference in cfg struct to apply this to + * FW later while initializing the dongle + */ ++ pr_info("power management disabled\n"); ++ enabled = false; + cfg->pwr_save = enabled; + if (!check_vif_up(ifp->vif)) { +@@ -4750,12 +4752,15 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); + if (err < 0) + brcmf_err("BRCMF_C_DOWN error %d\n", err); +- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); +- if (err < 0) +- brcmf_err("setting AP mode failed %d\n", err); ++ + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); + if (err < 0) + brcmf_err("setting INFRA mode failed %d\n", err); ++ ++ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); ++ if (err < 0) ++ brcmf_err("setting AP mode failed %d\n", err); ++ + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) + brcmf_fil_iovar_int_set(ifp, "mbss", 0); + brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, +@@ -6737,12 +6742,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + struct brcmfmac_pd_cc *country_codes; + struct brcmfmac_pd_cc_entry *cc; + s32 found_index; ++ char ccode[BRCMF_COUNTRY_BUF_SZ]; ++ int rev; + int i; -+Name: midi-uart0 -+Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets -+ 31.25kbaud, the frequency required for MIDI -+Load: dtoverlay=midi-uart0 -+Params: ++ memcpy(ccode, alpha2, sizeof(ccode)); ++ rev = -1; + + country_codes = drvr->settings->country_codes; + if (!country_codes) { +- brcmf_dbg(TRACE, "No country codes configured for device\n"); +- return -EINVAL; ++ brcmf_dbg(TRACE, "No country codes configured for device" ++ " - use requested value\n"); ++ goto use_input_value; + } + + if ((alpha2[0] == ccreq->country_abbrev[0]) && +@@ -6766,10 +6777,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + brcmf_dbg(TRACE, "No country code match found\n"); + return -EINVAL; + } +- memset(ccreq, 0, sizeof(*ccreq)); +- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); +- memcpy(ccreq->ccode, country_codes->table[found_index].cc, ++ rev = country_codes->table[found_index].rev; ++ memcpy(ccode, country_codes->table[found_index].cc, + BRCMF_COUNTRY_BUF_SZ); + - Name: mmc - Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock - Load: dtoverlay=mmc,= -diff --git a/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts ++use_input_value: ++ memset(ccreq, 0, sizeof(*ccreq)); ++ ccreq->rev = cpu_to_le32(rev); ++ memcpy(ccreq->ccode, ccode, sizeof(ccode)); + ccreq->country_abbrev[0] = alpha2[0]; + ccreq->country_abbrev[1] = alpha2[1]; + ccreq->country_abbrev[2] = 0; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index 3e15d64c64813513bc22202dd9e468588699abb0..4051780f64f44a5ce522babe6c371a1beb79a824 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -69,7 +69,7 @@ static int brcmf_fcmode; + module_param_named(fcmode, brcmf_fcmode, int, 0); + MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); + +-static int brcmf_roamoff; ++static int brcmf_roamoff = 1; + module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); + MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index b892dac70f4b02f76e01a7ccb580c6d8aed4bfe4..db5f8b70b407879f1c006ca4b7ab78d12974609d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -604,6 +604,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); ++BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); +@@ -621,6 +622,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), ++ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index d0407d9ad7827cd756b6311410ffe2d9a7cacc78..f1fb8a3c7a3211e8429585861f2f42e014878654 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -36,6 +36,7 @@ + #define BRCM_CC_4330_CHIP_ID 0x4330 + #define BRCM_CC_4334_CHIP_ID 0x4334 + #define BRCM_CC_43340_CHIP_ID 43340 ++#define BRCM_CC_43341_CHIP_ID 43341 + #define BRCM_CC_43362_CHIP_ID 43362 + #define BRCM_CC_4335_CHIP_ID 0x4335 + #define BRCM_CC_4339_CHIP_ID 0x4339 + +From e8bc1c301166d8273a8ae9f55cc5c41b970c6e53 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 17 Dec 2015 13:37:07 +0000 +Subject: [PATCH 090/111] hci_h5: Don't send conf_req when ACTIVE + +Without this patch, a modem and kernel can continuously bombard each +other with conf_req and conf_rsp messages, in a demented game of tag. +--- + drivers/bluetooth/hci_h5.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) + h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_req, 2) == 0) { + h5_link_control(hu, conf_rsp, 2); +- h5_link_control(hu, conf_req, 3); ++ if (h5->state != H5_ACTIVE) ++ h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_rsp, 2) == 0) { + if (H5_HDR_LEN(hdr) > 2) + h5->tx_win = (data[2] & 0x07); + +From 472db8146235a2a4e9109b9ffe9c80b815b24809 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 13 Apr 2015 17:16:29 +0100 +Subject: [PATCH 091/111] config: Add default configs + +--- + arch/arm/configs/bcm2709_defconfig | 1297 +++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1308 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 2605 insertions(+) + create mode 100644 arch/arm/configs/bcm2709_defconfig + create mode 100644 arch/arm/configs/bcmrpi_defconfig + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig new file mode 100644 -index 0000000000000000000000000000000000000000..565af7cf79d761877be3bd06191f31aabf9e1e9b +index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c1ddf5f7c --- /dev/null -+++ b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts -@@ -0,0 +1,36 @@ -+/dts-v1/; -+/plugin/; -+ -+#include -+ -+/* -+ * Fake a higher clock rate to get a larger divisor, and thereby a lower -+ * baudrate. The real clock is 48MHz, which we scale so that requesting -+ * 38.4kHz results in an actual 31.25kHz. -+ * -+ * 48000000*38400/31250 = 58982400 -+ */ -+ -+/{ -+ compatible = "brcm,bcm2835"; -+ -+ fragment@0 { -+ target-path = "/clocks"; -+ __overlay__ { -+ midi_clk: midi_clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-output-names = "uart0_pclk"; -+ clock-frequency = <58982400>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&uart0>; -+ __overlay__ { -+ clocks = <&midi_clk>, -+ <&clocks BCM2835_CLOCK_VPU>; -+ }; -+ }; -+}; ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -0,0 +1,1297 @@ ++CONFIG_LOCALVERSION="-v7" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_BCM=y ++CONFIG_ARCH_BCM2835=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_SMP=y ++CONFIG_VMSPLIT_2G=y ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_VFP=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_BINFMT_MISC=m ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_CFG80211=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_EKTF2127=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y ++CONFIG_BCM_VC_SM=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_BCM2835AUX=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_BCM2835=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_VIRT=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_BATTERY_DS2760=m ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_INA2XX=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_PISOUND=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_AK4554=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_ABX80X=m ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_HTU21=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM_NEON=m ++CONFIG_CRYPTO_AES_ARM_BS=m ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +new file mode 100644 +index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831cda8d7b51 +--- /dev/null ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -0,0 +1,1308 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_MULTI_V6=y ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_BCM=y ++CONFIG_ARCH_BCM2835=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_VFP=y ++CONFIG_BINFMT_MISC=m ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_CFG80211=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y ++CONFIG_BCM_VC_SM=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_BCM2835AUX=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_BCM2835=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_BATTERY_DS2760=m ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_INA2XX=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_PISOUND=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_AK4554=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_DWC2=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_USB_GADGET=m ++CONFIG_USB_ZERO=m ++CONFIG_USB_AUDIO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++CONFIG_USB_MIDI_GADGET=m ++CONFIG_USB_G_PRINTER=m ++CONFIG_USB_CDC_COMPOSITE=m ++CONFIG_USB_G_ACM_MS=m ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_HID=m ++CONFIG_USB_G_WEBCAM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_ABX80X=m ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_HTU21=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CRYPTD=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_SHA512=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM=m ++CONFIG_CRYPTO_AES_ARM=m ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y -From 2b4dc8b567a7432b754eb86291add0cb2a153ff4 Mon Sep 17 00:00:00 2001 +From f48b75a44a3a1b2fac53aa9e17c8bbb859799b17 Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Wed, 24 Aug 2016 03:35:56 -0700 +Subject: [PATCH 092/111] Add arm64 configuration and device tree differences. + Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing + at the moment. + +ARM64: Modify default config to get raspbian to boot (#1686) + +1. Enable emulation of deprecated instructions. +2. Enable ARM 8.1 and 8.2 features which are not detected at runtime. +3. Switch the default governer to powersave. +4. Include the watchdog timer driver in the kernel image rather then a module. + +Tested with raspbian-jessie 2016-09-23. +--- + arch/arm64/Kconfig.platforms | 22 + + arch/arm64/boot/dts/broadcom/Makefile | 1 + + arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts | 3 + + arch/arm64/configs/bcmrpi3_defconfig | 1334 ++++++++++++++++++++++ + 4 files changed, 1360 insertions(+) + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts + create mode 100644 arch/arm64/configs/bcmrpi3_defconfig + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 101794f5ce1008b7ff007fbfc7fa23d9e63bae67..7d213c2c904271c7a4622b83cd55a750d237bc2e 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -1,5 +1,27 @@ + menu "Platform selection" + ++config MACH_BCM2709 ++ bool ++ ++config ARCH_BCM2709 ++ bool "Broadcom BCM2709 family" ++ select MACH_BCM2709 ++ select HAVE_SMP ++ select ARM_AMBA ++ select COMMON_CLK ++ select ARCH_HAS_CPUFREQ ++ select GENERIC_CLOCKEVENTS ++ select MULTI_IRQ_HANDLER ++ select SPARSE_IRQ ++ select MFD_SYSCON ++ select VC4 ++ select USE_OF ++ select ARCH_REQUIRE_GPIOLIB ++ select PINCTRL ++ select PINCTRL_BCM2835 ++ help ++ This enables support for Broadcom BCM2709 boards. ++ + config ARCH_SUNXI + bool "Allwinner sunxi 64-bit SoC Family" + select GENERIC_IRQ_CHIP +diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile +index 05faf2a8a35ca5ba9049b9038dedb9be88eeb7c5..2152448c8cf5b22c573642d7ce45e85793f5fc9a 100644 +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -1,6 +1,7 @@ + dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb + dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb + dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb ++dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb + + always := $(dtb-y) + subdir-y := $(dts-dirs) +diff --git a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..deb33441da95220db0ed672e41639626fba682a5 +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts +@@ -0,0 +1,3 @@ ++#define RPI364 ++ ++#include "../../../../arm/boot/dts/bcm2710-rpi-3-b.dts" +diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig +new file mode 100644 +index 0000000000000000000000000000000000000000..d7406f5a4620151044b8f716b4d10bb818648e06 +--- /dev/null ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -0,0 +1,1334 @@ ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_PHYS_OFFSET=0 ++CONFIG_LOCALVERSION="-v8" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_64BIT=y ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=n ++CONFIG_ARM64_ERRATUM_827319=n ++CONFIG_ARM64_ERRATUM_824069=n ++CONFIG_ARM64_ERRATUM_819472=n ++CONFIG_ARM64_ERRATUM_832075=n ++CONFIG_ARM64_ERRATUM_845719=n ++CONFIG_ARM64_ERRATUM_843419=n ++CONFIG_CAVIUM_ERRATUM_22375=n ++CONFIG_CAVIUM_ERRATUM_23154=n ++CONFIG_CAVIUM_ERRATUM_27456=n ++CONFIG_ARM64_4K_PAGES=y ++CONFIG_ARM64_VA_BITS_39=y ++CONFIG_ARM64_VA_BITS=39 ++CONFIG_SCHED_MC=y ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++CONFIG_ARMV8_DEPRECATED=y ++CONFIG_SWP_EMULATION=y ++CONFIG_CP15_BARRIER_EMULATION=y ++CONFIG_SETEND_EMULATION=y ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++CONFIG_ARM64_LSE_ATOMICS=y ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=n ++CONFIG_RANDOMIZE_BASE=n ++ ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_TRIM_UNUSED_KSYMS=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_BCM2709=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_SMP=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_2G=y ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_VFP=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_BINFMT_MISC=m ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_IPVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=n ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_FT6236=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=n ++CONFIG_BCM_VC_CMA=n ++CONFIG_BCM_VCIO=n ++CONFIG_BCM_VC_SM=n ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_VIRT=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_BATTERY_DS2760=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=n ++CONFIG_VIDEO_BCM2835_MMAL=n ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_ARM=n ++CONFIG_SND_BCM2835=n ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=n ++CONFIG_USB_DWC2=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_ISL12057=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_R8723AU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++CONFIG_ARM64_CRYPTO=y ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y ++CONFIG_BCM2708_VCHIQ=n + +From 219a6fccb0da0e2e3533110a8871a6a64e11d8bf Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 7 Mar 2016 15:05:11 +0000 +Subject: [PATCH 093/111] vchiq_arm: Tweak the logging output + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 31 +++++++++------------- + 1 file changed, 13 insertions(+), 18 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +index 2c98da4307dff994a00dc246574ef0aaee05d5da..160db24aeea33a8296923501009c1f02bc41e599 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +@@ -891,16 +891,14 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + error_count); + return VCHIQ_ERROR; + } +- if (i == 0) { +- if (SRVTRACE_ENABLED(service, +- VCHIQ_LOG_INFO)) +- vchiq_log_dump_mem("Sent", 0, +- header->data + pos, +- min(64u, +- elements[0].size)); +- } + } + ++ if (SRVTRACE_ENABLED(service, ++ VCHIQ_LOG_INFO)) ++ vchiq_log_dump_mem("Sent", 0, ++ header->data, ++ min(16, pos)); ++ + spin_lock("a_spinlock); + service_quota->message_use_count++; + +@@ -1039,16 +1037,13 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + error_count); + return VCHIQ_ERROR; + } +- if (i == 0) { +- if (vchiq_sync_log_level >= +- VCHIQ_LOG_TRACE) +- vchiq_log_dump_mem("Sent Sync", +- 0, header->data + pos, +- min(64u, +- elements[0].size)); +- } + } + ++ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) ++ vchiq_log_dump_mem("Sent Sync", ++ 0, header->data, ++ min(16, pos)); ++ + VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); + } else { +@@ -1720,7 +1715,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, +- min(64, size)); ++ min(16, size)); + } + + if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) +@@ -2187,7 +2182,7 @@ sync_func(void *v) + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, +- min(64, size)); ++ min(16, size)); + } + + switch (type) { + +From 2ee990fac882706993ff1e41954e3f66329cf902 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 23 Mar 2016 14:16:25 +0000 +Subject: [PATCH 094/111] vchiq_arm: Access the dequeue_pending flag locked + +Reading through this code looking for another problem (now found in userland) +the use of dequeue_pending outside a lock didn't seem safe. + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 7b6cd4d80621e38ff6d47fcd87b45fbe9cd4259b..d8669fa7f39b077877eca1829ba9538bf2e21a82 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -279,6 +279,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + USER_SERVICE_T *user_service; + VCHIQ_SERVICE_T *service; + VCHIQ_INSTANCE_T instance; ++ int skip_completion = 0; + DEBUG_INITIALISE(g_state.local) + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); +@@ -345,9 +346,6 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + user_service->msg_queue[user_service->msg_insert & + (MSG_QUEUE_SIZE - 1)] = header; + user_service->msg_insert++; +- spin_unlock(&msg_queue_spinlock); +- +- up(&user_service->insert_event); + + /* If there is a thread waiting in DEQUEUE_MESSAGE, or if + ** there is a MESSAGE_AVAILABLE in the completion queue then +@@ -356,13 +354,22 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + if (((user_service->message_available_pos - + instance->completion_remove) >= 0) || + user_service->dequeue_pending) { +- DEBUG_TRACE(SERVICE_CALLBACK_LINE); + user_service->dequeue_pending = 0; +- return VCHIQ_SUCCESS; ++ skip_completion = 1; + } + ++ spin_unlock(&msg_queue_spinlock); ++ ++ up(&user_service->insert_event); ++ + header = NULL; + } ++ ++ if (skip_completion) { ++ DEBUG_TRACE(SERVICE_CALLBACK_LINE); ++ return VCHIQ_SUCCESS; ++ } ++ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + + return add_completion(instance, reason, header, user_service, + +From 3116aabedfc03a28116a5d3c5e60bf5ca036b81a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 23 Mar 2016 20:53:47 +0000 +Subject: [PATCH 095/111] vchiq_arm: Service callbacks must not fail + +Service callbacks are not allowed to return an error. The internal callback +that delivers events and messages to user tasks does not enqueue them if +the service is closing, but this is not an error and should not be +reported as such. + +Signed-off-by: Phil Elwell +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index d8669fa7f39b077877eca1829ba9538bf2e21a82..54552c6ce54f413c9781ba279b936f98be4f47b0 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -224,7 +224,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); +- return VCHIQ_ERROR; ++ return VCHIQ_SUCCESS; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + +From e14cabb05cf8aa75df960f82198ed6125c3e4b89 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 21 Apr 2016 13:49:32 +0100 +Subject: [PATCH 096/111] vchiq_arm: Add completion records under the mutex + +An issue was observed when flushing openmax components +which generate a large number of messages returning +buffers to host. + +We occasionally found a duplicate message from 16 +messages prior, resulting in a buffer returned twice. + +While only one thread adds completions, without the +mutex you don't get the protection of the automatic +memory barrier you get with synchronisation objects. + +Signed-off-by: Phil Elwell +--- + .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 54552c6ce54f413c9781ba279b936f98be4f47b0..bde8955b7d8505d73579b77b5b3921549cb9d2fb 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -210,6 +210,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + VCHIQ_COMPLETION_DATA_T *completion; + DEBUG_INITIALISE(g_state.local) + ++ mutex_lock(&instance->completion_mutex); ++ + while (instance->completion_insert == + (instance->completion_remove + MAX_COMPLETIONS)) { + /* Out of space - wait for the client */ +@@ -217,11 +219,17 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); ++ ++ mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; +- } else if (instance->closing) { ++ } ++ ++ mutex_lock(&instance->completion_mutex); ++ if (instance->closing) { ++ mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; +@@ -254,8 +262,11 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + if (reason == VCHIQ_MESSAGE_AVAILABLE) + user_service->message_available_pos = + instance->completion_insert; ++ + instance->completion_insert++; + ++ mutex_unlock(&instance->completion_mutex); ++ + up(&instance->insert_event); + + return VCHIQ_SUCCESS; + +From 720c0f193217c59539e4bd3cbf4c2315caa7fcb2 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Jun 2016 13:51:44 +0100 +Subject: [PATCH 097/111] vchiq_arm: Avoid use of mutex in add_completion + +Claiming the completion_mutex within add_completion did prevent some +messages appearing twice, but provokes a deadlock caused by vcsm using +vchiq within a page fault handler. + +Revert the use of completion_mutex, and instead fix the original +problem using more memory barriers. + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 55 +++++++++++----------- + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 14 ++++-- + 2 files changed, 37 insertions(+), 32 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index bde8955b7d8505d73579b77b5b3921549cb9d2fb..e5cdda12c7e5c35c69eb96991cfdb8326def167f 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -64,10 +64,10 @@ + #define VCHIQ_MINOR 0 + + /* Some per-instance constants */ +-#define MAX_COMPLETIONS 16 ++#define MAX_COMPLETIONS 128 + #define MAX_SERVICES 64 + #define MAX_ELEMENTS 8 +-#define MSG_QUEUE_SIZE 64 ++#define MSG_QUEUE_SIZE 128 + + #define KEEPALIVE_VER 1 + #define KEEPALIVE_VER_MIN KEEPALIVE_VER +@@ -208,28 +208,24 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + void *bulk_userdata) + { + VCHIQ_COMPLETION_DATA_T *completion; ++ int insert; + DEBUG_INITIALISE(g_state.local) + +- mutex_lock(&instance->completion_mutex); +- +- while (instance->completion_insert == +- (instance->completion_remove + MAX_COMPLETIONS)) { ++ insert = instance->completion_insert; ++ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { + /* Out of space - wait for the client */ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); + +- mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; + } + +- mutex_lock(&instance->completion_mutex); + if (instance->closing) { +- mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; +@@ -237,9 +233,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + +- completion = +- &instance->completions[instance->completion_insert & +- (MAX_COMPLETIONS - 1)]; ++ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; + + completion->header = header; + completion->reason = reason; +@@ -260,12 +254,9 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + wmb(); + + if (reason == VCHIQ_MESSAGE_AVAILABLE) +- user_service->message_available_pos = +- instance->completion_insert; ++ user_service->message_available_pos = insert; + +- instance->completion_insert++; +- +- mutex_unlock(&instance->completion_mutex); ++ instance->completion_insert = ++insert; + + up(&instance->insert_event); + +@@ -795,6 +786,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + instance->completion_insert) + && !instance->closing) { + int rc; ++ + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + mutex_unlock(&instance->completion_mutex); + rc = down_interruptible(&instance->insert_event); +@@ -809,24 +801,29 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + } + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + +- /* A read memory barrier is needed to stop prefetch of a stale +- ** completion record +- */ +- rmb(); +- + if (ret == 0) { + int msgbufcount = args.msgbufcount; ++ int remove; ++ ++ remove = instance->completion_remove; ++ + for (ret = 0; ret < args.count; ret++) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; +- if (instance->completion_remove == +- instance->completion_insert) ++ ++ if (remove == instance->completion_insert) + break; ++ + completion = &instance->completions[ +- instance->completion_remove & +- (MAX_COMPLETIONS - 1)]; ++ remove & (MAX_COMPLETIONS - 1)]; ++ ++ ++ /* A read memory barrier is needed to prevent ++ ** the prefetch of a stale completion record ++ */ ++ rmb(); + + service = completion->service_userdata; + user_service = service->base.userdata; +@@ -903,7 +900,11 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + } + +- instance->completion_remove++; ++ /* Ensure that the above copy has completed ++ ** before advancing the remove pointer. */ ++ mb(); ++ ++ instance->completion_remove = ++remove; + } + + if (msgbufcount != args.msgbufcount) { +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +index 160db24aeea33a8296923501009c1f02bc41e599..71a3bedc55314f3b22dbff40c05dedf03b5e7169 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +@@ -610,15 +610,15 @@ process_free_queue(VCHIQ_STATE_T *state) + BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + int slot_queue_available; + +- /* Use a read memory barrier to ensure that any state that may have +- ** been modified by another thread is not masked by stale prefetched +- ** values. */ +- rmb(); +- + /* Find slots which have been freed by the other side, and return them + ** to the available queue. */ + slot_queue_available = state->slot_queue_available; + ++ /* Use a memory barrier to ensure that any state that may have been ++ ** modified by another thread is not masked by stale prefetched ++ ** values. */ ++ mb(); ++ + while (slot_queue_available != local->slot_queue_recycle) { + unsigned int pos; + int slot_index = local->slot_queue[slot_queue_available++ & +@@ -626,6 +626,8 @@ process_free_queue(VCHIQ_STATE_T *state) + char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + int data_found = 0; + ++ rmb(); ++ + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", + state->id, slot_index, (unsigned int)data, + local->slot_queue_recycle, slot_queue_available); +@@ -741,6 +743,8 @@ process_free_queue(VCHIQ_STATE_T *state) + up(&state->data_quota_event); + } + ++ mb(); ++ + state->slot_queue_available = slot_queue_available; + up(&state->slot_available_event); + } + +From 27d47d64fcc3c859c0aa4e586260fe18a4d93ea0 Mon Sep 17 00:00:00 2001 From: Eric Anholt -Date: Wed, 14 Sep 2016 09:18:09 +0100 -Subject: [PATCH 177/208] raspberrypi-firmware: Define the MBOX channel in the - header. +Date: Mon, 3 Oct 2016 10:14:10 -0700 +Subject: [PATCH 098/111] staging/vchi: Convert to current get_user_pages() + arguments. Signed-off-by: Eric Anholt --- - include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ - 1 file changed, 2 insertions(+) + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 +-- + 2 files changed, 2 insertions(+), 3 deletions(-) -diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index e92278968b2b979db2a1f855f70e7aafb224fa98..6f19b27ae24ecfddc880e9b29290238df1f27087 100644 ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -12,6 +12,8 @@ - #include - #include +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +index 1091b9f1dd070e3d27c269402b43b0a09d96bcdc..8c7f31f8d39537e7e1c8135271c5f8eea76ed7a0 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -420,7 +420,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, + *need_release = 0; /* do not try and release vmalloc pages */ + } else { + down_read(&task->mm->mmap_sem); +- actual_pages = get_user_pages(task, task->mm, ++ actual_pages = get_user_pages( + (unsigned long)buf & ~(PAGE_SIZE - 1), + num_pages, + (type == PAGELIST_READ) ? FOLL_WRITE : 0, +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index e5cdda12c7e5c35c69eb96991cfdb8326def167f..085d37588c59198b4e5f00b9249bb8421695854f 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1492,8 +1492,7 @@ dump_phys_mem(void *virt_addr, uint32_t num_bytes) + } -+#define RPI_FIRMWARE_CHAN_FB 1 -+ - struct rpi_firmware; - - enum rpi_firmware_property_status { + down_read(¤t->mm->mmap_sem); +- rc = get_user_pages(current, /* task */ +- current->mm, /* mm */ ++ rc = get_user_pages( + (unsigned long)virt_addr, /* start */ + num_pages, /* len */ + 0, /* gup_flags */ -From 4b1d48bfd89c7a2edfd82be28e7896c9595417f0 Mon Sep 17 00:00:00 2001 +From e1c06a16857ef82b23542476ae90c19f8116759e Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 3 Oct 2016 10:16:03 -0700 +Subject: [PATCH 099/111] staging/vchi: Update for rename of + page_cache_release() to put_page(). + +Signed-off-by: Eric Anholt +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 ++-- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +index 8c7f31f8d39537e7e1c8135271c5f8eea76ed7a0..862fabf5682c7dededc8d7ca6773d5b227b72f3c 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -438,7 +438,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, + while (actual_pages > 0) + { + actual_pages--; +- page_cache_release(pages[actual_pages]); ++ put_page(pages[actual_pages]); + } + kfree(pagelist); + if (actual_pages == 0) +@@ -577,7 +577,7 @@ free_pagelist(PAGELIST_T *pagelist, int actual) + offset = 0; + set_page_dirty(pg); + } +- page_cache_release(pg); ++ put_page(pg); + } + } + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 085d37588c59198b4e5f00b9249bb8421695854f..5a2b8fb459ebe086ec229f37b6381bdbe6f808ca 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1530,7 +1530,7 @@ dump_phys_mem(void *virt_addr, uint32_t num_bytes) + kunmap(page); + + for (page_idx = 0; page_idx < num_pages; page_idx++) +- page_cache_release(pages[page_idx]); ++ put_page(pages[page_idx]); + + kfree(pages); + } + +From d4b6d1d96c30d9d162a96845fb9f6f1da82749d8 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 3 Oct 2016 10:21:17 -0700 +Subject: [PATCH 100/111] drivers/vchi: Remove dependency on CONFIG_BROKEN. + +The driver builds now. + +Signed-off-by: Eric Anholt +--- + drivers/staging/vc04_services/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig +index 9676fb29075a457109e4d4235f086987aec74868..db8e1beb89f9f8c48ea5964016c8285ea82497d8 100644 +--- a/drivers/staging/vc04_services/Kconfig ++++ b/drivers/staging/vc04_services/Kconfig +@@ -1,6 +1,6 @@ + config BCM2708_VCHIQ + tristate "Videocore VCHIQ" +- depends on RASPBERRYPI_FIRMWARE && BROKEN ++ depends on RASPBERRYPI_FIRMWARE + default y + help + Kernel to VideoCore communication interface for the + +From c6b2cd816480eb17449290d989909b8ba892e9a6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 09:16:19 +0100 -Subject: [PATCH 178/208] raspberrypi-firmware: Export the general transaction +Subject: [PATCH 101/111] raspberrypi-firmware: Export the general transaction function. The vc4-firmware-kms module is going to be doing the MBOX FB call. @@ -147858,10 +123486,10 @@ index 3f070bd38a91511c986e3fb114b15bd4ac32634c..f261b64d1657c02290904d841e1f087c /** * rpi_firmware_property_list - Submit firmware property list diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index 6f19b27ae24ecfddc880e9b29290238df1f27087..2859db09e25bb945251e85edb39bc43430857168 100644 +index e92278968b2b979db2a1f855f70e7aafb224fa98..09e3d871d110eb0762ebdb5ea329353738d58661 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -133,5 +133,6 @@ int rpi_firmware_property(struct rpi_firmware *fw, +@@ -131,5 +131,6 @@ int rpi_firmware_property(struct rpi_firmware *fw, int rpi_firmware_property_list(struct rpi_firmware *fw, void *data, size_t tag_size); struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node); @@ -147869,1273 +123497,35 @@ index 6f19b27ae24ecfddc880e9b29290238df1f27087..2859db09e25bb945251e85edb39bc434 #endif /* __SOC_RASPBERRY_FIRMWARE_H__ */ -From 0d1d276c7e42e7e7849ae973bf17d259ae958bc7 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Wed, 10 Aug 2016 18:52:34 +0200 -Subject: [PATCH 179/208] drm/fb-helper: Add a dummy - remove_conflicting_framebuffers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Lots of drivers don't properly compile without this when CONFIG_FB=n. -It's kinda a hack, but since CONFIG_FB doesn't stub any fucntions when -it's disabled I think it makes sense to add it to drm_fb_helper.h. - -Long term we probably need to rethink all the logic to unload firmware -framebuffer drivers, at least if we want to be able to move away from -CONFIG_FB and fbcon. - -v2: Unfortunately just stubbing out remove_conflicting_framebuffers in -drm_fb_helper.h upset gcc about static vs. non-static declarations, so -a new wrapper it needs to be. Means more churn :( - -Cc: Tobias Jakobi -Cc: Noralf Trønnes -Cc: tomi.valkeinen@ti.com -Cc: dh.herrmann@gmail.com -Reviewed-by: Alex Deucher -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1470847958-28465-2-git-send-email-daniel.vetter@ffwll.ch ---- - drivers/gpu/drm/vc4/vc4_drv.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 9ecef93854914579ee74b4d96432d15dfaa1fd6b..eff0530dc713f6ac3cdb5cb3e640abed1cc67492 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -16,6 +16,7 @@ - #include - #include - #include "drm_fb_cma_helper.h" -+#include - - #include "uapi/drm/vc4_drm.h" - #include "vc4_drv.h" -@@ -214,7 +215,7 @@ static void vc4_kick_out_firmware_fb(void) - ap->ranges[0].base = 0; - ap->ranges[0].size = ~0; - -- remove_conflicting_framebuffers(ap, "vc4drmfb", false); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "vc4drmfb", false); - kfree(ap); - } - - -From d970485b895a64a309054dea77693c48332db7fb Mon Sep 17 00:00:00 2001 -From: Laurent Pinchart -Date: Fri, 19 Aug 2016 11:39:29 +0300 -Subject: [PATCH 180/208] drm: Don't implement empty prepare_fb()/cleanup_fb() - -The plane .prepare_fb() and .cleanup_fb() helpers are optional, there's -no need to implement empty stubs, and no need to explicitly set the -function pointers to NULL either. - -Signed-off-by: Laurent Pinchart -[danvet: Resolved conflicts with Chris' patch.] -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/vc4/vc4_plane.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 29e4b400e25e34a63e4710e9edbba62541b9cdc5..881bf489478b01b34e9e4df6013fe608c42215ee 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -735,8 +735,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) - } - - static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { -- .prepare_fb = NULL, -- .cleanup_fb = NULL, - .atomic_check = vc4_plane_atomic_check, - .atomic_update = vc4_plane_atomic_update, - }; - -From 8046f42af8709ad32d6eaf964bc169f6e8e1136b Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:58:57 +0200 -Subject: [PATCH 181/208] drm/vc4: Disallow interlaced modes on DPI. - -We already don't expose such modes to userspace, but make -sure userspace can't sneak some interlaced mode in. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_dpi.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c -index 275fedbdbd9eae420939627e7fcdf9236cfce4fa..1e1f6b8184d058c6e55e092653798f4d75b55b7f 100644 ---- a/drivers/gpu/drm/vc4/vc4_dpi.c -+++ b/drivers/gpu/drm/vc4/vc4_dpi.c -@@ -340,9 +340,20 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) - } - } - -+static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder, -+ const struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) -+ return false; -+ -+ return true; -+} -+ - static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = { - .disable = vc4_dpi_encoder_disable, - .enable = vc4_dpi_encoder_enable, -+ .mode_fixup = vc4_dpi_encoder_mode_fixup, - }; - - static const struct of_device_id vc4_dpi_dt_match[] = { - -From 43e8caa26763825711b0f901d3a0544690363efd Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:58:58 +0200 -Subject: [PATCH 182/208] drm/vc4: Fix handling of interlaced video modes. - -We must not apply CRTC_INTERLACE_HALVE_V to interlaced modes during -mode enumeration, as drm_helper_probe_single_connector_modes -does, so wrap it and reset the effect of CRTC_INTERLACE_HALVE_V -on affected interlaced modes. - -Also mode_fixup interlaced modes passed in from user space. - -This fixes the vblank timestamping constants and entries in -the mode->crtc_xxx fields needed for precise vblank timestamping. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++++++++++ - drivers/gpu/drm/vc4/vc4_hdmi.c | 29 +++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 8fc2b731b59a613fddce5853981e1ab8fd982837..a479d3d840c59257aaf0f411cc9600f4915bb62c 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -532,6 +532,23 @@ static void vc4_crtc_enable(struct drm_crtc *crtc) - CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); - } - -+static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, -+ const struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ /* -+ * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when -+ * coming from user space. We don't want this, as it screws up -+ * vblank timestamping, so fix it up. -+ */ -+ drm_mode_set_crtcinfo(adjusted_mode, 0); -+ -+ DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id); -+ drm_mode_debug_printmodeline(adjusted_mode); -+ -+ return true; -+} -+ - static int vc4_crtc_atomic_check(struct drm_crtc *crtc, - struct drm_crtc_state *state) - { -@@ -819,6 +836,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { - .mode_set_nofb = vc4_crtc_mode_set_nofb, - .disable = vc4_crtc_disable, - .enable = vc4_crtc_enable, -+ .mode_fixup = vc4_crtc_mode_fixup, - .atomic_check = vc4_crtc_atomic_check, - .atomic_flush = vc4_crtc_atomic_flush, - }; -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 4452f3631cacea37bbd5dc8a594367631e308adc..68ad10634b29ec7b716f70f0b5fd9f2046da1fe5 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -208,10 +208,35 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - return ret; - } - -+/* -+ * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to -+ * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it -+ * screws up vblank timestamping for interlaced modes, so fix it up. -+ */ -+static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector, -+ uint32_t maxX, uint32_t maxY) -+{ -+ struct drm_display_mode *mode; -+ int count; -+ -+ count = drm_helper_probe_single_connector_modes(connector, maxX, maxY); -+ if (count == 0) -+ return 0; -+ -+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n", -+ connector->base.id, connector->name); -+ list_for_each_entry(mode, &connector->modes, head) { -+ drm_mode_set_crtcinfo(mode, 0); -+ drm_mode_debug_printmodeline(mode); -+ } -+ -+ return count; -+} -+ - static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .detect = vc4_hdmi_connector_detect, -- .fill_modes = drm_helper_probe_single_connector_modes, -+ .fill_modes = vc4_hdmi_connector_probe_modes, - .destroy = vc4_hdmi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -@@ -246,7 +271,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, - connector->polled = (DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT); - -- connector->interlace_allowed = 0; -+ connector->interlace_allowed = 1; - connector->doublescan_allowed = 0; - - drm_mode_connector_attach_encoder(connector, encoder); - -From 991b87fa61335f5241088165fa667ea2ce5c8f90 Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:58:59 +0200 -Subject: [PATCH 183/208] drm/vc4: Reject doublescan modes. - -We can't handle doublescan modes at the moment, so if -userspace tries to set one, reject the mode set. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index a479d3d840c59257aaf0f411cc9600f4915bb62c..2bfa2470e66b3fb5aa3692c66cb803973985f68f 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -536,6 +536,13 @@ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - { -+ /* Do not allow doublescan modes from user space */ -+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { -+ DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n", -+ crtc->base.id); -+ return false; -+ } -+ - /* - * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when - * coming from user space. We don't want this, as it screws up - -From 503dc975e3a0fde5266a1528ebef09a384b9b1ff Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:59:00 +0200 -Subject: [PATCH 184/208] drm/vc4: Enable precise vblank timestamping for - interlaced modes. - -On top of the interlaced video mode fix and with some additional -adjustments, this now works well. It has almost the same accuracy -as on regular progressive scan modes. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 21 ++++++++------------- - 1 file changed, 8 insertions(+), 13 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 2bfa2470e66b3fb5aa3692c66cb803973985f68f..7ffdad543ed2cbb588ad8f2037620bde7bb25e95 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -163,14 +163,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - int vblank_lines; - int ret = 0; - -- /* -- * XXX Doesn't work well in interlaced mode yet, partially due -- * to problems in vc4 kms or drm core interlaced mode handling, -- * so disable for now in interlaced mode. -- */ -- if (mode->flags & DRM_MODE_FLAG_INTERLACE) -- return ret; -- - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ -@@ -191,10 +183,15 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - - /* Vertical position of hvs composed scanline. */ - *vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE); -+ *hpos = 0; -+ -+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) { -+ *vpos /= 2; - -- /* No hpos info available. */ -- if (hpos) -- *hpos = 0; -+ /* Use hpos to correct for field offset in interlaced mode. */ -+ if (VC4_GET_FIELD(val, SCALER_DISPSTATX_FRAME_COUNT) % 2) -+ *hpos += mode->crtc_htotal / 2; -+ } - - /* This is the offset we need for translating hvs -> pv scanout pos. */ - fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay; -@@ -217,8 +214,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - * position of the PV. - */ - *vpos -= fifo_lines + 1; -- if (mode->flags & DRM_MODE_FLAG_INTERLACE) -- *vpos /= 2; - - ret |= DRM_SCANOUTPOS_ACCURATE; - return ret; - -From ce12fad8b5a7bbe64cba4fea965cd9b9b3d3552b Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:59:01 +0200 -Subject: [PATCH 185/208] drm/vc4: Enable/Disable vblanks properly in crtc - en/disable. - -Add missing drm_crtc_vblank_on/off() calls so vblank irq -handling/updating/timestamping never runs with a crtc shut down -or during its shutdown/startup, as that causes large jumps in -vblank count and trouble for compositors. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 7ffdad543ed2cbb588ad8f2037620bde7bb25e95..2682f07d8f1e6d3dc89ad0858f136c511040b517 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -475,6 +475,9 @@ static void vc4_crtc_disable(struct drm_crtc *crtc) - int ret; - require_hvs_enabled(dev); - -+ /* Disable vblank irq handling before crtc is disabled. */ -+ drm_crtc_vblank_off(crtc); -+ - CRTC_WRITE(PV_V_CONTROL, - CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN); - ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); -@@ -525,6 +528,9 @@ static void vc4_crtc_enable(struct drm_crtc *crtc) - /* Turn on the pixel valve, which will emit the vstart signal. */ - CRTC_WRITE(PV_V_CONTROL, - CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); -+ -+ /* Enable vblank irq handling after crtc is started. */ -+ drm_crtc_vblank_on(crtc); - } - - static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - -From fec57b3556993256fc654768dba939342ca25dc8 Mon Sep 17 00:00:00 2001 +From b3704dd955494e84e7ec6d7d07c8cdad72927139 Mon Sep 17 00:00:00 2001 From: Eric Anholt -Date: Tue, 2 Aug 2016 17:17:52 -0700 -Subject: [PATCH 186/208] drm/vc4: Don't force new binner overflow allocation - per draw. - -This came from the initial bringup code, which always idled the GPU -and always reset the overflow. That massively increases the size of -the working set when you're doing lots of small draws, though, as is -common on X desktops or piglit. +Date: Wed, 14 Sep 2016 09:18:09 +0100 +Subject: [PATCH 102/111] raspberrypi-firmware: Define the MBOX channel in the + header. Signed-off-by: Eric Anholt --- - drivers/gpu/drm/vc4/vc4_gem.c | 4 ---- - 1 file changed, 4 deletions(-) + include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ + 1 file changed, 2 insertions(+) -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index ae1609e739ef424d99207f830cd2bac41ce71557..47a095f392f8a7b5443227933c78b500a4c7137f 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -419,10 +419,6 @@ again: +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +index 09e3d871d110eb0762ebdb5ea329353738d58661..2859db09e25bb945251e85edb39bc43430857168 100644 +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -12,6 +12,8 @@ + #include + #include - vc4_flush_caches(dev); - -- /* Disable the binner's pre-loaded overflow memory address */ -- V3D_WRITE(V3D_BPOA, 0); -- V3D_WRITE(V3D_BPOS, 0); -- - /* Either put the job in the binner if it uses the binner, or - * immediately move it to the to-be-rendered queue. - */ - -From 3560e2aca2425e2b4ea5f5bdb0fa9589ecc125c3 Mon Sep 17 00:00:00 2001 -From: Liu Ying -Date: Mon, 29 Aug 2016 17:12:03 +0800 -Subject: [PATCH 187/208] drm/atomic-helper: Add NO_DISABLE_AFTER_MODESET flag - support for plane commit - -Drivers may set the NO_DISABLE_AFTER_MODESET flag in the 'flags' parameter -of the helper drm_atomic_helper_commit_planes() if the relevant display -controllers(e.g., IPUv3 for imx-drm) require to disable a CRTC's planes -when the CRTC is disabled. The helper would skip the ->atomic_disable -call for a plane if the CRTC of the old plane state needs a modesetting -operation. Of course, the drivers need to disable the planes in their CRTC -disable callbacks since no one else would do that. - -Suggested-by: Daniel Vetter -Cc: Philipp Zabel -Cc: David Airlie -Cc: Russell King -Cc: Peter Senna Tschudin -Cc: Lucas Stach -Signed-off-by: Liu Ying -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1472461923-14364-1-git-send-email-gnuiyl@gmail.com ---- - drivers/gpu/drm/vc4/vc4_kms.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 4ac894d993cd80472777b2a3bacc2fcf0dd52810..c1f65c6c8e601e9331768ca040a5609cad686b2e 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -44,7 +44,7 @@ vc4_atomic_complete_commit(struct vc4_commit *c) - - drm_atomic_helper_commit_modeset_disables(dev, state); - -- drm_atomic_helper_commit_planes(dev, state, false); -+ drm_atomic_helper_commit_planes(dev, state, 0); - - drm_atomic_helper_commit_modeset_enables(dev, state); - - -From 32db4f1829e5531aa6e60ca3020b2c487c945920 Mon Sep 17 00:00:00 2001 -From: Tom Gundersen -Date: Wed, 21 Sep 2016 16:59:19 +0200 -Subject: [PATCH 188/208] drm: Don't swallow error codes in drm_dev_alloc() - -There are many reasons other than ENOMEM that drm_dev_init() can -fail. Return ERR_PTR rather than NULL to be able to distinguish -these in the caller. - -Signed-off-by: Tom Gundersen -Signed-off-by: Sean Paul -Link: http://patchwork.freedesktop.org/patch/msgid/20160921145919.13754-2-teg@jklm.no ---- - drivers/gpu/drm/vc4/vc4_drv.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index eff0530dc713f6ac3cdb5cb3e640abed1cc67492..8703f56b794774ac4130a7b487472e293ebe7cdf 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -233,8 +233,8 @@ static int vc4_drm_bind(struct device *dev) - return -ENOMEM; - - drm = drm_dev_alloc(&vc4_drm_driver, dev); -- if (!drm) -- return -ENOMEM; -+ if (IS_ERR(drm)) -+ return PTR_ERR(drm); - platform_set_drvdata(pdev, drm); - vc4->dev = drm; - drm->dev_private = vc4; - -From 7f1274b2b1e0fe40b2965bad8853cbe3035a3fbe Mon Sep 17 00:00:00 2001 -From: Masahiro Yamada -Date: Tue, 13 Sep 2016 03:35:20 +0900 -Subject: [PATCH 189/208] drm/vc4: cleanup with list_first_entry_or_null() - -The combo of list_empty() check and return list_first_entry() -can be replaced with list_first_entry_or_null(). - -Signed-off-by: Masahiro Yamada -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_drv.h | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index f696b752886b153c4654c0b8acca3fe46c9136cb..7c1e4d97486fb57d9ce7002c30a23138519761ae 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -324,18 +324,15 @@ struct vc4_exec_info { - static inline struct vc4_exec_info * - vc4_first_bin_job(struct vc4_dev *vc4) - { -- if (list_empty(&vc4->bin_job_list)) -- return NULL; -- return list_first_entry(&vc4->bin_job_list, struct vc4_exec_info, head); -+ return list_first_entry_or_null(&vc4->bin_job_list, -+ struct vc4_exec_info, head); - } - - static inline struct vc4_exec_info * - vc4_first_render_job(struct vc4_dev *vc4) - { -- if (list_empty(&vc4->render_job_list)) -- return NULL; -- return list_first_entry(&vc4->render_job_list, -- struct vc4_exec_info, head); -+ return list_first_entry_or_null(&vc4->render_job_list, -+ struct vc4_exec_info, head); - } - - static inline struct vc4_exec_info * - -From ec746edb504c5ac7db80f613e52a0c0dbfc866fa Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 16 Sep 2016 10:59:45 +0100 -Subject: [PATCH 190/208] drm/vc4: Enable limited range RGB output on HDMI with - CEA modes. - -Fixes broken grayscale ramps on many HDMI monitors, where large areas -at the ends of the ramp would all appear as black or white. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 31 +++++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_regs.h | 9 ++++++++- - 2 files changed, 37 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 68ad10634b29ec7b716f70f0b5fd9f2046da1fe5..29be7b7273df5b2c75d3162d72097efe62ec93df 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -298,6 +298,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *unadjusted_mode, - struct drm_display_mode *mode) - { -+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - bool debug_dump_regs = false; -@@ -313,6 +314,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | - VC4_SET_FIELD(mode->vtotal - mode->vsync_end, - VC4_HDMI_VERTB_VBP)); -+ u32 csc_ctl; - - if (debug_dump_regs) { - DRM_INFO("HDMI regs before:\n"); -@@ -351,9 +353,34 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); - -+ csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, -+ VC4_HD_CSC_CTL_ORDER); ++#define RPI_FIRMWARE_CHAN_FB 1 + -+ if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) { -+ /* CEA VICs other than #1 requre limited range RGB -+ * output. Apply a colorspace conversion to squash -+ * 0-255 down to 16-235. The matrix here is: -+ * -+ * [ 0 0 0.8594 16] -+ * [ 0 0.8594 0 16] -+ * [ 0.8594 0 0 16] -+ * [ 0 0 0 1] -+ */ -+ csc_ctl |= VC4_HD_CSC_CTL_ENABLE; -+ csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC; -+ csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, -+ VC4_HD_CSC_CTL_MODE); -+ -+ HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000); -+ HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0); -+ HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000); -+ HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000); -+ HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0); -+ HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000); -+ } -+ - /* The RGB order applies even when CSC is disabled. */ -- HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, -- VC4_HD_CSC_CTL_ORDER)); -+ HD_WRITE(VC4_HD_CSC_CTL, csc_ctl); + struct rpi_firmware; - HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); - -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 160942a9180e716e6c6d890214f0fc6e0e081ecd..9ecd6ff3d493ffca5249256ce99dc2de2b21e0ee 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -528,10 +528,17 @@ - # define VC4_HD_CSC_CTL_MODE_SHIFT 2 - # define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0 - # define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1 --# define VC4_HD_CSC_CTL_MODE_CUSTOM 2 -+# define VC4_HD_CSC_CTL_MODE_CUSTOM 3 - # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) - # define VC4_HD_CSC_CTL_ENABLE BIT(0) - -+#define VC4_HD_CSC_12_11 0x044 -+#define VC4_HD_CSC_14_13 0x048 -+#define VC4_HD_CSC_22_21 0x04c -+#define VC4_HD_CSC_24_23 0x050 -+#define VC4_HD_CSC_32_31 0x054 -+#define VC4_HD_CSC_34_33 0x058 -+ - #define VC4_HD_FRAME_COUNT 0x068 - - /* HVS display list information. */ + enum rpi_firmware_property_status { -From 9bad67df07b8552d61731c2f0e5a5fe0f9d46849 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 19:21:29 +0100 -Subject: [PATCH 191/208] drm/vc4: Fall back to using an EDID probe in the - absence of a GPIO. - -On Pi0/1/2, we use an external GPIO line for hotplug detection, since -the HDMI_HOTPLUG register isn't connected to anything. However, with -the Pi3 the HPD GPIO line has moved off to a GPIO expander that will -be tricky to get to (the firmware is constantly polling the expander -using i2c0, so we'll need to coordinate with it). - -As a stop-gap, if we don't have a GPIO line, use an EDID probe to -detect connection. Fixes HDMI display on the pi3. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 29be7b7273df5b2c75d3162d72097efe62ec93df..1e61931846d3f10cdb7f914e54c260f8b9731cd7 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -174,6 +174,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - return connector_status_disconnected; - } - -+ if (drm_probe_ddc(vc4->hdmi->ddc)) -+ return connector_status_connected; -+ - if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) - return connector_status_connected; - else - -From 45f5d55e2e3214d8e8e0514b1fe7c32ec632357e Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 28 Sep 2016 17:21:05 -0700 -Subject: [PATCH 192/208] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL - changes. - -Fixes occasional debug spew at boot when connected directly through -HDMI, and probably confusing the HDMI state machine when we go trying -to poke registers for the enable sequence too soon. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 1e61931846d3f10cdb7f914e54c260f8b9731cd7..fe1c4e35e68142839756df10ed9b9e56c028d04e 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -424,7 +424,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - - ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & -- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1); -+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000); - WARN_ONCE(ret, "Timeout waiting for " - "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); - } else { -@@ -436,7 +436,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - - ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & -- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1); -+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000); - WARN_ONCE(ret, "Timeout waiting for " - "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); - } - -From 0ec96f64a32dc31a9f1bcbcb367d932622fd9cee Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 28 Sep 2016 17:30:25 -0700 -Subject: [PATCH 193/208] drm/vc4: Fix support for interlaced modes on HDMI. - -We really do need to be using the halved V fields. I had been -confused by the code I was using as a reference because it stored -halved vsync fields but not halved vdisplay, so it looked like I only -needed to divide vdisplay by 2. - -This reverts part of Mario's timestamping fixes that prevented -CRTC_HALVE_V from applying, and instead adjusts the timestamping code -to not use the crtc field in that case. - -Fixes locking of 1920x1080x60i on my Dell 2408WFP. There are black -bars on the top and bottom, but I suspect that might be an -under/overscan flags problem as opposed to video timings. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 49 ++++++++++++++++++++++-------------------- - drivers/gpu/drm/vc4/vc4_hdmi.c | 45 +++++++++++--------------------------- - drivers/gpu/drm/vc4/vc4_regs.h | 3 +++ - 3 files changed, 41 insertions(+), 56 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 2682f07d8f1e6d3dc89ad0858f136c511040b517..83cafea03eff720f9f7b80f484dedf22ac7f283f 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -229,7 +229,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - * and need to make things up in a approximative but consistent way. - */ - ret |= DRM_SCANOUTPOS_IN_VBLANK; -- vblank_lines = mode->crtc_vtotal - mode->crtc_vdisplay; -+ vblank_lines = mode->vtotal - mode->vdisplay; - - if (flags & DRM_CALLED_FROM_VBLIRQ) { - /* -@@ -378,7 +378,6 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - struct drm_crtc_state *state = crtc->state; - struct drm_display_mode *mode = &state->adjusted_mode; - bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; -- u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0)); - u32 format = PV_CONTROL_FORMAT_24; - bool debug_dump_regs = false; - int clock_select = vc4_get_clock_select(crtc); -@@ -404,32 +403,46 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); - - CRTC_WRITE(PV_VERTA, -- VC4_SET_FIELD(mode->vtotal - mode->vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, - PV_VERTA_VBP) | -- VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, -+ VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, - PV_VERTA_VSYNC)); - CRTC_WRITE(PV_VERTB, -- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, -+ VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, - PV_VERTB_VFP) | -- VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); -+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); - - if (interlace) { - CRTC_WRITE(PV_VERTA_EVEN, -- VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1, -+ VC4_SET_FIELD(mode->crtc_vtotal - -+ mode->crtc_vsync_end - 1, - PV_VERTA_VBP) | -- VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, -+ VC4_SET_FIELD(mode->crtc_vsync_end - -+ mode->crtc_vsync_start, - PV_VERTA_VSYNC)); - CRTC_WRITE(PV_VERTB_EVEN, -- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, -+ VC4_SET_FIELD(mode->crtc_vsync_start - -+ mode->crtc_vdisplay, - PV_VERTB_VFP) | -- VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); -+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); -+ -+ /* We set up first field even mode for HDMI. VEC's -+ * NTSC mode would want first field odd instead, once -+ * we support it (to do so, set ODD_FIRST and put the -+ * delay in VSYNCD_EVEN instead). -+ */ -+ CRTC_WRITE(PV_V_CONTROL, -+ PV_VCONTROL_CONTINUOUS | -+ PV_VCONTROL_INTERLACE | -+ VC4_SET_FIELD(mode->htotal / 2, -+ PV_VCONTROL_ODD_DELAY)); -+ CRTC_WRITE(PV_VSYNCD_EVEN, 0); -+ } else { -+ CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); - } - - CRTC_WRITE(PV_HACT_ACT, mode->hdisplay); - -- CRTC_WRITE(PV_V_CONTROL, -- PV_VCONTROL_CONTINUOUS | -- (interlace ? PV_VCONTROL_INTERLACE : 0)); - - CRTC_WRITE(PV_CONTROL, - VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | -@@ -544,16 +557,6 @@ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - return false; - } - -- /* -- * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when -- * coming from user space. We don't want this, as it screws up -- * vblank timestamping, so fix it up. -- */ -- drm_mode_set_crtcinfo(adjusted_mode, 0); -- -- DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id); -- drm_mode_debug_printmodeline(adjusted_mode); -- - return true; - } - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index fe1c4e35e68142839756df10ed9b9e56c028d04e..d94108ca961dac9278d2e38813d089b78acbc8ad 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -211,35 +211,10 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - return ret; - } - --/* -- * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to -- * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it -- * screws up vblank timestamping for interlaced modes, so fix it up. -- */ --static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector, -- uint32_t maxX, uint32_t maxY) --{ -- struct drm_display_mode *mode; -- int count; -- -- count = drm_helper_probe_single_connector_modes(connector, maxX, maxY); -- if (count == 0) -- return 0; -- -- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n", -- connector->base.id, connector->name); -- list_for_each_entry(mode, &connector->modes, head) { -- drm_mode_set_crtcinfo(mode, 0); -- drm_mode_debug_printmodeline(mode); -- } -- -- return count; --} -- - static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .detect = vc4_hdmi_connector_detect, -- .fill_modes = vc4_hdmi_connector_probe_modes, -+ .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_hdmi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -@@ -307,16 +282,20 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - bool debug_dump_regs = false; - bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; - bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; -- u32 vactive = (mode->vdisplay >> -- ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0)); -- u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, -+ bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; -+ u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, - VC4_HDMI_VERTA_VSP) | -- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, -+ VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, - VC4_HDMI_VERTA_VFP) | -- VC4_SET_FIELD(vactive, VC4_HDMI_VERTA_VAL)); -+ VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); - u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | -- VC4_SET_FIELD(mode->vtotal - mode->vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, - VC4_HDMI_VERTB_VBP)); -+ u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | -+ VC4_SET_FIELD(mode->crtc_vtotal - -+ mode->crtc_vsync_end - -+ interlaced, -+ VC4_HDMI_VERTB_VBP)); - u32 csc_ctl; - - if (debug_dump_regs) { -@@ -349,7 +328,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - HDMI_WRITE(VC4_HDMI_VERTA0, verta); - HDMI_WRITE(VC4_HDMI_VERTA1, verta); - -- HDMI_WRITE(VC4_HDMI_VERTB0, vertb); -+ HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even); - HDMI_WRITE(VC4_HDMI_VERTB1, vertb); - - HD_WRITE(VC4_HD_VID_CTL, -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 9ecd6ff3d493ffca5249256ce99dc2de2b21e0ee..c5a423ead86ffdd1ce2abada24f628b19c1ebc08 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -183,6 +183,9 @@ - # define PV_CONTROL_EN BIT(0) - - #define PV_V_CONTROL 0x04 -+# define PV_VCONTROL_ODD_DELAY_MASK VC4_MASK(22, 6) -+# define PV_VCONTROL_ODD_DELAY_SHIFT 6 -+# define PV_VCONTROL_ODD_FIRST BIT(5) - # define PV_VCONTROL_INTERLACE BIT(4) - # define PV_VCONTROL_CONTINUOUS BIT(1) - # define PV_VCONTROL_VIDEN BIT(0) - -From d1475342b1f4cf8f9a51428a64f04ae50c45c9c8 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 29 Sep 2016 15:34:43 -0700 -Subject: [PATCH 194/208] drm/vc4: Set up the AVI and SPD infoframes. - -Fixes a purple bar on the left side of the screen with my Dell -2408WFP. It will also be required for supporting the double-clocked -video modes. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 136 +++++++++++++++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_regs.h | 5 ++ - 2 files changed, 136 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index d94108ca961dac9278d2e38813d089b78acbc8ad..d6b54b905beeec33eee8a763969ffa9568cfa745 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -62,6 +62,8 @@ struct vc4_hdmi { - struct vc4_hdmi_encoder { - struct vc4_encoder base; - bool hdmi_monitor; -+ bool limited_rgb_range; -+ bool rgb_range_selectable; - }; - - static inline struct vc4_hdmi_encoder * -@@ -205,6 +207,12 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - return -ENODEV; - - vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); -+ -+ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { -+ vc4_encoder->rgb_range_selectable = -+ drm_rgb_quant_range_selectable(edid); -+ } -+ - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - -@@ -272,6 +280,117 @@ static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = { - .destroy = vc4_hdmi_encoder_destroy, - }; - -+static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, -+ enum hdmi_infoframe_type type) -+{ -+ struct drm_device *dev = encoder->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ u32 packet_id = type - 0x80; -+ -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, -+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); -+ -+ return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & -+ BIT(packet_id)), 100); -+} -+ -+static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, -+ union hdmi_infoframe *frame) -+{ -+ struct drm_device *dev = encoder->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ u32 packet_id = frame->any.type - 0x80; -+ u32 packet_reg = VC4_HDMI_GCP_0 + VC4_HDMI_PACKET_STRIDE * packet_id; -+ uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; -+ ssize_t len, i; -+ int ret; -+ -+ WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & -+ VC4_HDMI_RAM_PACKET_ENABLE), -+ "Packet RAM has to be on to store the packet."); -+ -+ len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); -+ if (len < 0) -+ return; -+ -+ ret = vc4_hdmi_stop_packet(encoder, frame->any.type); -+ if (ret) { -+ DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret); -+ return; -+ } -+ -+ for (i = 0; i < len; i += 7) { -+ HDMI_WRITE(packet_reg, -+ buffer[i + 0] << 0 | -+ buffer[i + 1] << 8 | -+ buffer[i + 2] << 16); -+ packet_reg += 4; -+ -+ HDMI_WRITE(packet_reg, -+ buffer[i + 3] << 0 | -+ buffer[i + 4] << 8 | -+ buffer[i + 5] << 16 | -+ buffer[i + 6] << 24); -+ packet_reg += 4; -+ } -+ -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, -+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); -+ ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & -+ BIT(packet_id)), 100); -+ if (ret) -+ DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); -+} -+ -+static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) -+{ -+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); -+ struct drm_crtc *crtc = encoder->crtc; -+ const struct drm_display_mode *mode = &crtc->state->adjusted_mode; -+ union hdmi_infoframe frame; -+ int ret; -+ -+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); -+ if (ret < 0) { -+ DRM_ERROR("couldn't fill AVI infoframe\n"); -+ return; -+ } -+ -+ if (vc4_encoder->rgb_range_selectable) { -+ if (vc4_encoder->limited_rgb_range) { -+ frame.avi.quantization_range = -+ HDMI_QUANTIZATION_RANGE_LIMITED; -+ } else { -+ frame.avi.quantization_range = -+ HDMI_QUANTIZATION_RANGE_FULL; -+ } -+ } -+ -+ vc4_hdmi_write_infoframe(encoder, &frame); -+} -+ -+static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) -+{ -+ union hdmi_infoframe frame; -+ int ret; -+ -+ ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore"); -+ if (ret < 0) { -+ DRM_ERROR("couldn't fill SPD infoframe\n"); -+ return; -+ } -+ -+ frame.spd.sdi = HDMI_SPD_SDI_PC; -+ -+ vc4_hdmi_write_infoframe(encoder, &frame); -+} -+ -+static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) -+{ -+ vc4_hdmi_set_avi_infoframe(encoder); -+ vc4_hdmi_set_spd_infoframe(encoder); -+} -+ - static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *unadjusted_mode, - struct drm_display_mode *mode) -@@ -340,8 +459,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - - if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) { - /* CEA VICs other than #1 requre limited range RGB -- * output. Apply a colorspace conversion to squash -- * 0-255 down to 16-235. The matrix here is: -+ * output unless overridden by an AVI infoframe. -+ * Apply a colorspace conversion to squash 0-255 down -+ * to 16-235. The matrix here is: - * - * [ 0 0 0.8594 16] - * [ 0 0.8594 0 16] -@@ -359,6 +479,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000); - HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0); - HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000); -+ vc4_encoder->limited_rgb_range = true; -+ } else { -+ vc4_encoder->limited_rgb_range = false; - } - - /* The RGB order applies even when CSC is disabled. */ -@@ -377,6 +500,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0); -+ - HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); - HD_WRITE(VC4_HD_VID_CTL, - HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); -@@ -429,9 +554,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | - VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT); - -- /* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set -- * up the infoframe. -- */ -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, -+ VC4_HDMI_RAM_PACKET_ENABLE); -+ -+ vc4_hdmi_set_infoframes(encoder); - - drift = HDMI_READ(VC4_HDMI_FIFO_CTL); - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index c5a423ead86ffdd1ce2abada24f628b19c1ebc08..0b868aafa8db69b0a08fe9cbf293263a0a7c5bed 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -441,6 +441,8 @@ - #define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0 - # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16) - -+#define VC4_HDMI_RAM_PACKET_STATUS 0x0a4 -+ - #define VC4_HDMI_HORZA 0x0c4 - # define VC4_HDMI_HORZA_VPOS BIT(14) - # define VC4_HDMI_HORZA_HPOS BIT(13) -@@ -502,6 +504,9 @@ - - #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 - -+#define VC4_HDMI_GCP_0 0x400 -+#define VC4_HDMI_PACKET_STRIDE 0x24 -+ - #define VC4_HD_M_CTL 0x00c - # define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6) - # define VC4_HD_M_RAM_STANDBY (3 << 4) - -From d06d8d96a9423f1a5268377bddbd93a3a3fc20af Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 29 Sep 2016 15:34:44 -0700 -Subject: [PATCH 195/208] drm/vc4: Add support for double-clocked modes. - -Now that we have infoframes to report the pixel repeat flag, we can -start using it. Fixes locking the 720x480i and 720x576i modes on my -Dell 2408WFP. Like the 1920x1080i case, they don't fit properly on -the screen, though. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++------ - drivers/gpu/drm/vc4/vc4_hdmi.c | 16 +++++++++++----- - drivers/gpu/drm/vc4/vc4_regs.h | 2 ++ - 3 files changed, 24 insertions(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 83cafea03eff720f9f7b80f484dedf22ac7f283f..7f08d681a74b4e37529f6c09ae1d2c1a944dcabd 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -378,6 +378,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - struct drm_crtc_state *state = crtc->state; - struct drm_display_mode *mode = &state->adjusted_mode; - bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; -+ u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; - u32 format = PV_CONTROL_FORMAT_24; - bool debug_dump_regs = false; - int clock_select = vc4_get_clock_select(crtc); -@@ -393,14 +394,17 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - CRTC_WRITE(PV_CONTROL, 0); - - CRTC_WRITE(PV_HORZA, -- VC4_SET_FIELD(mode->htotal - mode->hsync_end, -+ VC4_SET_FIELD((mode->htotal - -+ mode->hsync_end) * pixel_rep, - PV_HORZA_HBP) | -- VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, -+ VC4_SET_FIELD((mode->hsync_end - -+ mode->hsync_start) * pixel_rep, - PV_HORZA_HSYNC)); - CRTC_WRITE(PV_HORZB, -- VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, -+ VC4_SET_FIELD((mode->hsync_start - -+ mode->hdisplay) * pixel_rep, - PV_HORZB_HFP) | -- VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); -+ VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE)); - - CRTC_WRITE(PV_VERTA, - VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, -@@ -434,20 +438,21 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - CRTC_WRITE(PV_V_CONTROL, - PV_VCONTROL_CONTINUOUS | - PV_VCONTROL_INTERLACE | -- VC4_SET_FIELD(mode->htotal / 2, -+ VC4_SET_FIELD(mode->htotal * pixel_rep / 2, - PV_VCONTROL_ODD_DELAY)); - CRTC_WRITE(PV_VSYNCD_EVEN, 0); - } else { - CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); - } - -- CRTC_WRITE(PV_HACT_ACT, mode->hdisplay); -+ CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); - - - CRTC_WRITE(PV_CONTROL, - VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | - VC4_SET_FIELD(vc4_get_fifo_full_level(format), - PV_CONTROL_FIFO_LEVEL) | -+ VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) | - PV_CONTROL_CLR_AT_START | - PV_CONTROL_TRIGGER_UNDERFLOW | - PV_CONTROL_WAIT_HSTART | -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index d6b54b905beeec33eee8a763969ffa9568cfa745..c4cb2e26de32f06db0abf3fd94b3117c3292eed5 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -402,6 +402,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; - bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; - bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; -+ u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; - u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, - VC4_HDMI_VERTA_VSP) | - VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, -@@ -424,7 +425,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - - HD_WRITE(VC4_HD_VID_CTL, 0); - -- clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000); -+ clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000 * -+ ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1)); - - HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | -@@ -434,14 +436,18 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - HDMI_WRITE(VC4_HDMI_HORZA, - (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | - (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | -- VC4_SET_FIELD(mode->hdisplay, VC4_HDMI_HORZA_HAP)); -+ VC4_SET_FIELD(mode->hdisplay * pixel_rep, -+ VC4_HDMI_HORZA_HAP)); - - HDMI_WRITE(VC4_HDMI_HORZB, -- VC4_SET_FIELD(mode->htotal - mode->hsync_end, -+ VC4_SET_FIELD((mode->htotal - -+ mode->hsync_end) * pixel_rep, - VC4_HDMI_HORZB_HBP) | -- VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, -+ VC4_SET_FIELD((mode->hsync_end - -+ mode->hsync_start) * pixel_rep, - VC4_HDMI_HORZB_HSP) | -- VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, -+ VC4_SET_FIELD((mode->hsync_start - -+ mode->hdisplay) * pixel_rep, - VC4_HDMI_HORZB_HFP)); - - HDMI_WRITE(VC4_HDMI_VERTA0, verta); -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 0b868aafa8db69b0a08fe9cbf293263a0a7c5bed..1aa44c2db5565ba126d2ceb65495a6c98c555860 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -175,6 +175,8 @@ - # define PV_CONTROL_CLR_AT_START BIT(14) - # define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13) - # define PV_CONTROL_WAIT_HSTART BIT(12) -+# define PV_CONTROL_PIXEL_REP_MASK VC4_MASK(5, 4) -+# define PV_CONTROL_PIXEL_REP_SHIFT 4 - # define PV_CONTROL_CLK_SELECT_DSI_VEC 0 - # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 - # define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2) - -From 68dde0cad20ec7f9c40100cbcfd744d61bdc298a Mon Sep 17 00:00:00 2001 +From ea0597439af226851168bcee2b9e122c17e22567 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 08:39:33 +0100 -Subject: [PATCH 196/208] drm/vc4: Add a mode for using the closed firmware for +Subject: [PATCH 103/111] drm/vc4: Add a mode for using the closed firmware for display. Signed-off-by: Eric Anholt @@ -149902,1253 +124292,841 @@ index 0000000000000000000000000000000000000000..d18a1dae51a2275846c9826b5bf1ba57 + }, +}; -From 1e7e72efacf0401c04fe4295b8c615350a41d6d0 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Wed, 10 Aug 2016 18:52:34 +0200 -Subject: [PATCH 197/208] drm/fb-helper: Add a dummy - remove_conflicting_framebuffers +From d9f0d5cad9768b3b249cf0e45d45f31c0e941f26 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Sat, 17 Sep 2016 15:07:10 +0200 +Subject: [PATCH 104/111] i2c: bcm2835: Fix hang for writing messages larger + than 16 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Lots of drivers don't properly compile without this when CONFIG_FB=n. -It's kinda a hack, but since CONFIG_FB doesn't stub any fucntions when -it's disabled I think it makes sense to add it to drm_fb_helper.h. +Writing messages larger than the FIFO size results in a hang, rendering +the machine unusable. This is because the RXD status flag is set on the +first interrupt which results in bcm2835_drain_rxfifo() stealing bytes +from the buffer. The controller continues to trigger interrupts waiting +for the missing bytes, but bcm2835_fill_txfifo() has none to give. +In this situation wait_for_completion_timeout() apparently is unable to +stop the madness. -Long term we probably need to rethink all the logic to unload firmware -framebuffer drivers, at least if we want to be able to move away from -CONFIG_FB and fbcon. +The BCM2835 ARM Peripherals datasheet has this to say about the flags: + TXD: is set when the FIFO has space for at least one byte of data. + RXD: is set when the FIFO contains at least one byte of data. + TXW: is set during a write transfer and the FIFO is less than full. + RXR: is set during a read transfer and the FIFO is or more full. -v2: Unfortunately just stubbing out remove_conflicting_framebuffers in -drm_fb_helper.h upset gcc about static vs. non-static declarations, so -a new wrapper it needs to be. Means more churn :( +Implementing the logic from the downstream i2c-bcm2708 driver solved +the hang problem. -Cc: Tobias Jakobi -Cc: Noralf Trønnes -Cc: tomi.valkeinen@ti.com -Cc: dh.herrmann@gmail.com -Reviewed-by: Alex Deucher -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1470847958-28465-2-git-send-email-daniel.vetter@ffwll.ch ---- - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- - drivers/gpu/drm/bochs/bochs_drv.c | 3 ++- - drivers/gpu/drm/cirrus/cirrus_drv.c | 2 +- - drivers/gpu/drm/i915/i915_drv.c | 2 +- - drivers/gpu/drm/mgag200/mgag200_drv.c | 2 +- - drivers/gpu/drm/mgag200/mgag200_main.c | 2 +- - drivers/gpu/drm/nouveau/nouveau_drm.c | 2 +- - drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- - drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++- - drivers/gpu/drm/virtio/virtgpu_drm_bus.c | 3 ++- - include/drm/drm_fb_helper.h | 14 ++++++++++++++ - 11 files changed, 28 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -index 414a1600da54b5a108638d86246429d5796562db..6e37e8b7c0f2fc67ecb7e3b98515217d17808e22 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -@@ -341,7 +341,7 @@ static int amdgpu_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "amdgpudrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "amdgpudrmfb", primary); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c -index abace82de6eac2de22b747ff54a5612443f69647..277654abe0f79e768c525380623dc1896749b4cb 100644 ---- a/drivers/gpu/drm/bochs/bochs_drv.c -+++ b/drivers/gpu/drm/bochs/bochs_drv.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - #include "bochs.h" - -@@ -153,7 +154,7 @@ static int bochs_kick_out_firmware_fb(struct pci_dev *pdev) - - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); -- remove_conflicting_framebuffers(ap, "bochsdrmfb", false); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "bochsdrmfb", false); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c -index b05f7eae32ce756e39f656adcbadc2ddfb55893c..6c76d125995bef3f20b566292aeeb7ad9122c86d 100644 ---- a/drivers/gpu/drm/cirrus/cirrus_drv.c -+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c -@@ -57,7 +57,7 @@ static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c -index d46fa2206722855856920de5e6d3817fe75679ab..71d8859aa32d424f86d63f4df5e4b5240d6e0906 100644 ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -706,7 +706,7 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) - primary = - pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - -- ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary); -+ ret = drm_fb_helper_remove_conflicting_framebuffers(ap, "inteldrmfb", primary); - - kfree(ap); - -diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c -index 2b4b125eebc3ef9e5987d3bcc32d429f5b15ff8e..1443b3a34775cbcaca50532482cfa32fd3052671 100644 ---- a/drivers/gpu/drm/mgag200/mgag200_drv.c -+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c -@@ -56,7 +56,7 @@ static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "mgag200drmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "mgag200drmfb", primary); - kfree(ap); - } - -diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c -index 13798b3e6bebbf0b8a62b39c60b9494659d5264d..e79cbc25ae3c54048b21c6293ea340b91b0750fc 100644 ---- a/drivers/gpu/drm/mgag200/mgag200_main.c -+++ b/drivers/gpu/drm/mgag200/mgag200_main.c -@@ -135,7 +135,7 @@ static int mga_vram_init(struct mga_device *mdev) - aper->ranges[0].base = mdev->mc.vram_base; - aper->ranges[0].size = mdev->mc.vram_window; - -- remove_conflicting_framebuffers(aper, "mgafb", true); -+ drm_fb_helper_remove_conflicting_framebuffers(aper, "mgafb", true); - kfree(aper); - - if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window, -diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c -index 66c1280c0f1f2854aa501f810c50a11e6149eaaa..652ab111dd74d899cc9aac867e05791e0a64229f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c -@@ -351,7 +351,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev, - boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif - if (nouveau_modeset != 2) -- remove_conflicting_framebuffers(aper, "nouveaufb", boot); -+ drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot); - kfree(aper); - - ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug, -diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c -index c01a7c6abb491c4227ad02fd6525813a7a9d3d55..90f2ff217b3123e70ed17b6d0ed34c17eadd527e 100644 ---- a/drivers/gpu/drm/radeon/radeon_drv.c -+++ b/drivers/gpu/drm/radeon/radeon_drv.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - - #include "drm_crtc_helper.h" - #include "radeon_kfd.h" -@@ -324,7 +325,7 @@ static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "radeondrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "radeondrmfb", primary); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c -index 7092daaf6c432b8fa8d2bb93bda63785cf307f01..8913c151b37f475acdbee1f41074188c4430a00d 100644 ---- a/drivers/gpu/drm/sun4i/sun4i_drv.c -+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "sun4i_crtc.h" - #include "sun4i_drv.h" -@@ -109,7 +110,7 @@ static void sun4i_remove_framebuffers(void) - ap->ranges[0].base = 0; - ap->ranges[0].size = ~0; - -- remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false); - kfree(ap); - } - -diff --git a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c -index 88a39165edd50705d561ca8c5d23df2ac628f9a1..cf142737a1667227240c9c88d0c6864df39003de 100644 ---- a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c -+++ b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c -@@ -24,6 +24,7 @@ - */ - - #include -+#include - - #include "virtgpu_drv.h" - -@@ -52,7 +53,7 @@ static void virtio_pci_kick_out_firmware_fb(struct pci_dev *pci_dev) - primary = pci_dev->resource[PCI_ROM_RESOURCE].flags - & IORESOURCE_ROM_SHADOW; - -- remove_conflicting_framebuffers(ap, "virtiodrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "virtiodrmfb", primary); - - kfree(ap); - } -diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h -index db8d4780eaa27607baf7857111c72b50bbae5fd4..130c324f1aeeddd25c996a766baaf3d8e26ac110 100644 ---- a/include/drm/drm_fb_helper.h -+++ b/include/drm/drm_fb_helper.h -@@ -32,6 +32,7 @@ - - struct drm_fb_helper; - -+#include - #include - - enum mode_set_atomic { -@@ -282,6 +283,12 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, - int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); - int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector); -+static inline int -+drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, -+ const char *name, bool primary) -+{ -+ return remove_conflicting_framebuffers(a, name, primary); -+} - #else - static inline int drm_fb_helper_modinit(void) - { -@@ -475,5 +482,12 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - { - return 0; - } -+ -+static inline int -+drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, -+ const char *name, bool primary) -+{ -+ return 0; -+} - #endif - #endif - -From c5b9aa24bc98cb757a296d6d26cd27a1728a48cd Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 08:52:26 +0100 -Subject: [PATCH 198/208] BCM270X: Add an overlay for enabling the vc4 driver - in firmware-KMS mode. - -This gets us normal 3D support on top of the existing firmware display -stack. There's no real modesetting support, no async pageflips -(hurting performance), etc., but it means that the desktop can at -least run until we get full native modesetting. - -Signed-off-by: Eric Anholt ---- - arch/arm/boot/dts/bcm270x.dtsi | 11 +++ - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 11 +++ - .../arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 89 ++++++++++++++++++++++ - 4 files changed, 112 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts - -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -index 514b481d4f4095dc8b55a216ac7335934973e145..a46cb4a8b1419edd95e0e07c18b0f373222dc2bf 100644 ---- a/arch/arm/boot/dts/bcm270x.dtsi -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -1,4 +1,5 @@ - /* Downstream bcm283x.dtsi diff */ -+#include "dt-bindings/power/raspberrypi-power.h" - - / { - chosen { -@@ -88,6 +89,15 @@ - status = "disabled"; - }; - -+ firmwarekms: firmwarekms@7e600000 { -+ compatible = "raspberrypi,rpi-firmware-kms"; -+ /* SMI interrupt reg */ -+ reg = <0x7e600000 0x100>; -+ interrupts = <2 16>; -+ brcm,firmware = <&firmware>; -+ status = "disabled"; -+ }; -+ - smi: smi@7e600000 { - compatible = "brcm,bcm2835-smi"; - reg = <0x7e600000 0x100>; -@@ -119,6 +129,7 @@ - - v3d@7ec00000 { /* vd3 */ - compatible = "brcm,vc4-v3d"; -+ power-domains = <&power RPI_POWER_DOMAIN_V3D>; - status = "disabled"; - }; - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index a3ddb4577ce1f671f4c23ebe32c434c97b00781c..7624812d0cdc74728f3556159871c7a299f9f6b7 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -90,6 +90,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - spi2-3cs.dtbo \ - tinylcd35.dtbo \ - uart1.dtbo \ -+ vc4-fkms-v3d.dtbo \ - vc4-kms-v3d.dtbo \ - vga666.dtbo \ - w1-gpio.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 496e31db0c7d22934bd381aea5e7227c26a3f034..c0290531a61fedfe23e820ca4d9693a0acd3e876 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -1276,6 +1276,17 @@ Params: txd1_pin GPIO pin for TXD1 (14, 32 or 40 - default 14) - rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15) - - -+Name: vc4-fkms-v3d -+Info: Enable Eric Anholt's DRM VC4 V3D driver on top of the dispmanx -+ display stack. -+Load: dtoverlay=vc4-fkms-v3d, -+Params: cma-256 CMA is 256MB, 256MB-aligned (needs 1GB) -+ cma-192 CMA is 192MB, 256MB-aligned (needs 1GB) -+ cma-128 CMA is 128MB, 128MB-aligned -+ cma-96 CMA is 96MB, 128MB-aligned -+ cma-64 CMA is 64MB, 64MB-aligned -+ -+ - Name: vc4-kms-v3d - Info: Enable Eric Anholt's DRM VC4 HDMI/HVS/V3D driver. Running startx or - booting to GUI while this overlay is in use will cause interesting -diff --git a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..95a595a35cb4fbb707bf4b18161f6a46860aa4ae ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts -@@ -0,0 +1,89 @@ -+/* -+ * vc4-fkms-v3d-overlay.dts -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target-path = "/chosen"; -+ __overlay__ { -+ bootargs = "cma=256M@256M"; -+ }; -+ }; -+ -+ fragment@1 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=192M@256M"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=128M@128M"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=96M@128M"; -+ }; -+ }; -+ -+ fragment@4 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=64M@64M"; -+ }; -+ }; -+ -+ fragment@5 { -+ target = <&fb>; -+ __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@6 { -+ target = <&firmwarekms>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@7 { -+ target = <&v3d>; -+ __overlay__ { -+ interrupts = <1 10>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@8 { -+ target = <&gpu>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@9 { -+ target-path = "/soc/dma"; -+ __overlay__ { -+ brcm,dma-channel-mask = <0x7f35>; -+ }; -+ }; -+ -+ __overrides__ { -+ cma-256 = <0>,"+0-1-2-3-4"; -+ cma-192 = <0>,"-0+1-2-3-4"; -+ cma-128 = <0>,"-0-1+2-3-4"; -+ cma-96 = <0>,"-0-1-2+3-4"; -+ cma-64 = <0>,"-0-1-2-3+4"; -+ }; -+}; - -From 23f34d57b322879bdba8291a9b41818fc9001d53 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Thu, 13 Oct 2016 11:54:31 +0300 -Subject: [PATCH 199/208] drm/vc4: Fix a couple error codes in - vc4_cl_lookup_bos() - -If the allocation fails the current code returns success. If -copy_from_user() fails it returns the number of bytes remaining instead -of -EFAULT. - -Fixes: d5b1a78a772f ("drm/vc4: Add support for drawing 3D frames.") -Signed-off-by: Dan Carpenter +Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt -(cherry picked from commit b2cdeb19f16ad984eb5bb9193f793d05a8101511) +Reviewed-by: Martin Sperl --- - drivers/gpu/drm/vc4/vc4_gem.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) + drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index 47a095f392f8a7b5443227933c78b500a4c7137f..303f23c962206836d8c95786ad835d7625e10ee8 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -544,14 +544,15 @@ vc4_cl_lookup_bos(struct drm_device *dev, - - handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t)); - if (!handles) { -+ ret = -ENOMEM; - DRM_ERROR("Failed to allocate incoming GEM handles\n"); - goto fail; +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index d4f3239b56865919e1b781b20a7c5ebcd76b4eb9..f283b714aa79e2e4685ed95b04b6b289f7e9eee7 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { + int irq; + struct i2c_adapter adapter; + struct completion completion; ++ struct i2c_msg *curr_msg; + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; +@@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + return IRQ_HANDLED; } -- ret = copy_from_user(handles, -- (void __user *)(uintptr_t)args->bo_handles, -- exec->bo_count * sizeof(uint32_t)); -- if (ret) { -+ if (copy_from_user(handles, -+ (void __user *)(uintptr_t)args->bo_handles, -+ exec->bo_count * sizeof(uint32_t))) { -+ ret = -EFAULT; - DRM_ERROR("Failed to copy in GEM handles\n"); - goto fail; - } - -From 46096f860ad1bbc61716e6b83b08c8e469da213b Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 20 Oct 2016 16:48:12 -0700 -Subject: [PATCH 200/208] drm/vc4: Fix termination of the initial scan for - branch targets. - -The loop is scanning until the original max_ip (size of the BO), but -we want to not examine any code after the PROG_END's delay slots. -There was a block trying to do that, except that we had some early -continue statements if the signal wasn't a PROG_END or a BRANCH. - -The failure mode would be that a valid shader is rejected because some -undefined memory after the PROG_END slots is parsed as a branch and -the rest of its setup is illegal. I haven't seen this in the wild, -but valgrind was complaining when about this up in the userland -simulator mode. - -Signed-off-by: Eric Anholt -(cherry picked from commit 457e67a728696c4f8e6423c64e93def50530db9a) ---- - drivers/gpu/drm/vc4/vc4_validate_shaders.c | 19 ++++++++----------- - 1 file changed, 8 insertions(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -index 2543cf5b8b51869d51b72a5db5017dded38761be..917321ce832ffda9d3e8ca20d987437eea9a1765 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c -+++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -@@ -608,9 +608,7 @@ static bool - vc4_validate_branches(struct vc4_shader_validation_state *validation_state) - { - uint32_t max_branch_target = 0; -- bool found_shader_end = false; - int ip; -- int shader_end_ip = 0; - int last_branch = -2; - - for (ip = 0; ip < validation_state->max_ip; ip++) { -@@ -621,8 +619,13 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state) - uint32_t branch_target_ip; - - if (sig == QPU_SIG_PROG_END) { -- shader_end_ip = ip; -- found_shader_end = true; -+ /* There are two delay slots after program end is -+ * signaled that are still executed, then we're -+ * finished. validation_state->max_ip is the -+ * instruction after the last valid instruction in the -+ * program. -+ */ -+ validation_state->max_ip = ip + 3; - continue; - } - -@@ -676,15 +679,9 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state) - } - set_bit(after_delay_ip, validation_state->branch_targets); - max_branch_target = max(max_branch_target, after_delay_ip); -- -- /* There are two delay slots after program end is signaled -- * that are still executed, then we're finished. -- */ -- if (found_shader_end && ip == shader_end_ip + 2) -- break; - } - -- if (max_branch_target > shader_end_ip) { -+ if (max_branch_target > validation_state->max_ip - 3) { - DRM_ERROR("Branch landed after QPU_SIG_PROG_END"); - return false; - } - -From 1d26463c7b768495482c7883e08685ade635c9c2 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 3 Nov 2016 18:53:10 -0700 -Subject: [PATCH 201/208] drm/vc4: Add support for rendering with ETC1 - textures. - -The validation for it ends up being quite simple, but I hadn't got -around to it before merging the driver. For backwards compatibility, -we also need to add a flag so that the userspace GL driver can easily -tell if the kernel will allow ETC1 textures (on an old kernel, it will -continue to convert to RGBA8) - -Signed-off-by: Eric Anholt -(cherry picked from commit 7154d76fedf549607afbc0d13db9aaf02da5cebf) ---- - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - drivers/gpu/drm/vc4/vc4_validate.c | 7 +++++++ - include/uapi/drm/vc4_drm.h | 1 + - 3 files changed, 9 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 6c4a4fbc86d0a30a6977b2081bca4372e693b817..157e08ab27771854ffbad101f61ce81e27001e1a 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -78,6 +78,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, - pm_runtime_put(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_SUPPORTS_BRANCHES: -+ case DRM_VC4_PARAM_SUPPORTS_ETC1: - args->value = true; - break; - default: -diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c -index 26503e307438a34fe526222c8c15be158eb332a2..e18f88203d32f828b7256a05c653586c14095ef3 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate.c -+++ b/drivers/gpu/drm/vc4/vc4_validate.c -@@ -644,6 +644,13 @@ reloc_tex(struct vc4_exec_info *exec, - cpp = 1; - break; - case VC4_TEXTURE_TYPE_ETC1: -+ /* ETC1 is arranged as 64-bit blocks, where each block is 4x4 -+ * pixels. -+ */ -+ cpp = 8; -+ width = (width + 3) >> 2; -+ height = (height + 3) >> 2; -+ break; - case VC4_TEXTURE_TYPE_BW1: - case VC4_TEXTURE_TYPE_A4: - case VC4_TEXTURE_TYPE_A1: -diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h -index ad7edc3edf7ca1d653a0bc025a5eda6692b74370..69caa21f0cb23c9439238f6239c0041b178d5669 100644 ---- a/include/uapi/drm/vc4_drm.h -+++ b/include/uapi/drm/vc4_drm.h -@@ -286,6 +286,7 @@ struct drm_vc4_get_hang_state { - #define DRM_VC4_PARAM_V3D_IDENT1 1 - #define DRM_VC4_PARAM_V3D_IDENT2 2 - #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 -+#define DRM_VC4_PARAM_SUPPORTS_ETC1 4 - - struct drm_vc4_get_param { - __u32 param; - -From 574fbee0c80641a4f2bcc24f30c8c14a54544d1d Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 4 Nov 2016 15:58:38 -0700 -Subject: [PATCH 202/208] drm/vc4: Use runtime autosuspend to avoid thrashing - V3D power state. - -The pm_runtime_put() we were using immediately released power on the -device, which meant that we were generally turning the device off and -on once per frame. In many profiles I've looked at, that added up to -about 1% of CPU time, but this could get worse in the case of frequent -rendering and readback (as may happen in X rendering). By keeping the -device on until we've been idle for a couple of frames, we drop the -overhead of runtime PM down to sub-.1%. - -Signed-off-by: Eric Anholt -(cherry picked from commit 3a62234680d86efa0239665ed8a0e908f1aef147) ---- - drivers/gpu/drm/vc4/vc4_drv.c | 9 ++++++--- - drivers/gpu/drm/vc4/vc4_gem.c | 6 ++++-- - drivers/gpu/drm/vc4/vc4_v3d.c | 2 ++ - 3 files changed, 12 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 157e08ab27771854ffbad101f61ce81e27001e1a..8302bd788be470fd61a7382b8c3ef16e26f6861d 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -61,21 +61,24 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, - if (ret < 0) - return ret; - args->value = V3D_READ(V3D_IDENT0); -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_V3D_IDENT1: - ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); - if (ret < 0) - return ret; - args->value = V3D_READ(V3D_IDENT1); -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_V3D_IDENT2: - ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); - if (ret < 0) - return ret; - args->value = V3D_READ(V3D_IDENT2); -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_SUPPORTS_BRANCHES: - case DRM_VC4_PARAM_SUPPORTS_ETC1: -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index 303f23c962206836d8c95786ad835d7625e10ee8..db920771bfb5641c9d5d8e53a8f73cf7ee501bb7 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -709,8 +709,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) - } - - mutex_lock(&vc4->power_lock); -- if (--vc4->power_refcount == 0) -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ if (--vc4->power_refcount == 0) { -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); -+ } - mutex_unlock(&vc4->power_lock); - - kfree(exec); -diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c -index e6d3c6028341e447df293cab525713ac10d8ee5e..7cc346ad9b0baed63701d1fae8f0306aa7713129 100644 ---- a/drivers/gpu/drm/vc4/vc4_v3d.c -+++ b/drivers/gpu/drm/vc4/vc4_v3d.c -@@ -222,6 +222,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) - return ret; - } - -+ pm_runtime_use_autosuspend(dev); -+ pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ - pm_runtime_enable(dev); - - return 0; - -From d90a754daaeb289afe12b1991c3cf08fe9bb423d Mon Sep 17 00:00:00 2001 -From: Jonas Pfeil -Date: Tue, 8 Nov 2016 00:18:39 +0100 -Subject: [PATCH 203/208] drm/vc4: Add fragment shader threading support - -FS threading brings performance improvements of 0-20% in glmark2. - -The validation code checks for thread switch signals and ensures that -the registers of the other thread are not touched, and that our clamps -are not live across thread switches. It also checks that the -threading and branching instructions do not interfere. - -(Original patch by Jonas, changes by anholt for style cleanup, -removing validation the kernel doesn't need to do, and adding the flag -for userspace). - -v2: Minor style fixes from checkpatch. - -Signed-off-by: Jonas Pfeil -Signed-off-by: Eric Anholt -(cherry picked from commit c778cc5df944291dcdb1ca7a6bb781fbc22550c5) ---- - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.h | 2 + - drivers/gpu/drm/vc4/vc4_validate.c | 17 +++++--- - drivers/gpu/drm/vc4/vc4_validate_shaders.c | 63 ++++++++++++++++++++++++++++++ - include/uapi/drm/vc4_drm.h | 1 + - 5 files changed, 79 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 8302bd788be470fd61a7382b8c3ef16e26f6861d..3abaa0f85da194016c65f46509d4c64f8e2c8de2 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -82,6 +82,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, - break; - case DRM_VC4_PARAM_SUPPORTS_BRANCHES: - case DRM_VC4_PARAM_SUPPORTS_ETC1: -+ case DRM_VC4_PARAM_SUPPORTS_THREADED_FS: - args->value = true; - break; - default: -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index e1f6ab747f36dd412e00a1e7ea772f13c2fc32d5..e15eb37ca6191e0eae3d4947751437d2646c996d 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -384,6 +384,8 @@ struct vc4_validated_shader_info { - - uint32_t num_uniform_addr_offsets; - uint32_t *uniform_addr_offsets; -+ -+ bool is_threaded; - }; - - /** -diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c -index e18f88203d32f828b7256a05c653586c14095ef3..9fd171c361c23b52a4d507919ec7e26fd1e87aac 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate.c -+++ b/drivers/gpu/drm/vc4/vc4_validate.c -@@ -789,11 +789,6 @@ validate_gl_shader_rec(struct drm_device *dev, - exec->shader_rec_v += roundup(packet_size, 16); - exec->shader_rec_size -= packet_size; - -- if (!(*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD)) { -- DRM_ERROR("Multi-threaded fragment shaders not supported.\n"); -- return -EINVAL; +- if (val & BCM2835_I2C_S_RXD) { +- bcm2835_drain_rxfifo(i2c_dev); +- if (!(val & BCM2835_I2C_S_DONE)) +- return IRQ_HANDLED; - } - - for (i = 0; i < shader_reloc_count; i++) { - if (src_handles[i] > exec->bo_count) { - DRM_ERROR("Shader handle %d too big\n", src_handles[i]); -@@ -810,6 +805,18 @@ validate_gl_shader_rec(struct drm_device *dev, - return -EINVAL; - } - -+ if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) != -+ to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) { -+ DRM_ERROR("Thread mode of CL and FS do not match\n"); -+ return -EINVAL; -+ } -+ -+ if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded || -+ to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) { -+ DRM_ERROR("cs and vs cannot be threaded\n"); -+ return -EINVAL; -+ } -+ - for (i = 0; i < shader_reloc_count; i++) { - struct vc4_validated_shader_info *validated_shader; - uint32_t o = shader_reloc_offsets[i]; -diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -index 917321ce832ffda9d3e8ca20d987437eea9a1765..5dba13dd1e9b600b43a769d086d6eb428547ab66 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c -+++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -@@ -83,6 +83,13 @@ struct vc4_shader_validation_state { - * basic blocks. - */ - bool needs_uniform_address_for_loop; -+ -+ /* Set when we find an instruction writing the top half of the -+ * register files. If we allowed writing the unusable regs in -+ * a threaded shader, then the other shader running on our -+ * QPU's clamp validation would be invalid. -+ */ -+ bool all_registers_used; - }; - - static uint32_t -@@ -119,6 +126,13 @@ raddr_add_a_to_live_reg_index(uint64_t inst) - } - - static bool -+live_reg_is_upper_half(uint32_t lri) -+{ -+ return (lri >= 16 && lri < 32) || -+ (lri >= 32 + 16 && lri < 32 + 32); -+} -+ -+static bool - is_tmu_submit(uint32_t waddr) - { - return (waddr == QPU_W_TMU0_S || -@@ -390,6 +404,9 @@ check_reg_write(struct vc4_validated_shader_info *validated_shader, - } else { - validation_state->live_immediates[lri] = ~0; - } -+ -+ if (live_reg_is_upper_half(lri)) -+ validation_state->all_registers_used = true; - } - - switch (waddr) { -@@ -598,6 +615,11 @@ check_instruction_reads(struct vc4_validated_shader_info *validated_shader, - } - } - -+ if ((raddr_a >= 16 && raddr_a < 32) || -+ (raddr_b >= 16 && raddr_b < 32 && sig != QPU_SIG_SMALL_IMM)) { -+ validation_state->all_registers_used = true; -+ } -+ - return true; - } - -@@ -753,6 +775,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - { - bool found_shader_end = false; - int shader_end_ip = 0; -+ uint32_t last_thread_switch_ip = -3; - uint32_t ip; - struct vc4_validated_shader_info *validated_shader = NULL; - struct vc4_shader_validation_state validation_state; -@@ -785,6 +808,17 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - if (!vc4_handle_branch_target(&validation_state)) - goto fail; - -+ if (ip == last_thread_switch_ip + 3) { -+ /* Reset r0-r3 live clamp data */ -+ int i; -+ -+ for (i = 64; i < LIVE_REG_COUNT; i++) { -+ validation_state.live_min_clamp_offsets[i] = ~0; -+ validation_state.live_max_clamp_regs[i] = false; -+ validation_state.live_immediates[i] = ~0; -+ } + if (val & BCM2835_I2C_S_DONE) { +- if (i2c_dev->msg_buf_remaining) ++ if (i2c_dev->curr_msg->flags & I2C_M_RD) { ++ bcm2835_drain_rxfifo(i2c_dev); ++ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); + } + - switch (sig) { - case QPU_SIG_NONE: - case QPU_SIG_WAIT_FOR_SCOREBOARD: -@@ -794,6 +828,8 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - case QPU_SIG_LOAD_TMU1: - case QPU_SIG_PROG_END: - case QPU_SIG_SMALL_IMM: -+ case QPU_SIG_THREAD_SWITCH: -+ case QPU_SIG_LAST_THREAD_SWITCH: - if (!check_instruction_writes(validated_shader, - &validation_state)) { - DRM_ERROR("Bad write at ip %d\n", ip); -@@ -809,6 +845,18 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - shader_end_ip = ip; - } - -+ if (sig == QPU_SIG_THREAD_SWITCH || -+ sig == QPU_SIG_LAST_THREAD_SWITCH) { -+ validated_shader->is_threaded = true; -+ -+ if (ip < last_thread_switch_ip + 3) { -+ DRM_ERROR("Thread switch too soon after " -+ "last switch at ip %d\n", ip); -+ goto fail; -+ } -+ last_thread_switch_ip = ip; -+ } -+ - break; - - case QPU_SIG_LOAD_IMM: -@@ -823,6 +871,13 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - if (!check_branch(inst, validated_shader, - &validation_state, ip)) - goto fail; -+ -+ if (ip < last_thread_switch_ip + 3) { -+ DRM_ERROR("Branch in thread switch at ip %d", -+ ip); -+ goto fail; -+ } -+ - break; - default: - DRM_ERROR("Unsupported QPU signal %d at " -@@ -844,6 +899,14 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - goto fail; ++ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) + i2c_dev->msg_err = BCM2835_I2C_S_LEN; + else + i2c_dev->msg_err = 0; +@@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + return IRQ_HANDLED; } -+ /* Might corrupt other thread */ -+ if (validated_shader->is_threaded && -+ validation_state.all_registers_used) { -+ DRM_ERROR("Shader uses threading, but uses the upper " -+ "half of the registers, too\n"); -+ goto fail; +- if (val & BCM2835_I2C_S_TXD) { ++ if (val & BCM2835_I2C_S_TXW) { + bcm2835_fill_txfifo(i2c_dev); + return IRQ_HANDLED; + } + ++ if (val & BCM2835_I2C_S_RXR) { ++ bcm2835_drain_rxfifo(i2c_dev); ++ return IRQ_HANDLED; + } + - /* If we did a backwards branch and we haven't emitted a uniforms - * reset since then, we still need the uniforms stream to have the - * uniforms address available so that the backwards branch can do its -diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h -index 69caa21f0cb23c9439238f6239c0041b178d5669..f07a090167261131076438960c1dec175d7d376e 100644 ---- a/include/uapi/drm/vc4_drm.h -+++ b/include/uapi/drm/vc4_drm.h -@@ -287,6 +287,7 @@ struct drm_vc4_get_hang_state { - #define DRM_VC4_PARAM_V3D_IDENT2 2 - #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 - #define DRM_VC4_PARAM_SUPPORTS_ETC1 4 -+#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 + return IRQ_NONE; + } - struct drm_vc4_get_param { - __u32 param; +@@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + u32 c; + unsigned long time_left; + ++ i2c_dev->curr_msg = msg; + i2c_dev->msg_buf = msg->buf; + i2c_dev->msg_buf_remaining = msg->len; + reinit_completion(&i2c_dev->completion); -From 963f20f2caa0018ef7fbb756852fcd6226cde43a Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 6 Dec 2016 18:54:24 +0000 -Subject: [PATCH 204/208] config: fixup +From ee341c5b195116a5edb761bfeba927f926b888cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 18:24:38 +0200 +Subject: [PATCH 105/111] i2c: bcm2835: Protect against unexpected TXW/RXR + interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), +the driver has no way to fill/drain the FIFO to stop the interrupts. +In this case the controller has to be disabled and the transfer +completed to avoid hang. + +(CLKT | ERR) and DONE interrupts are completed in their own paths, and +the controller is disabled in the transfer function after completion. +Unite the code paths and do disabling inside the interrupt routine. + +Clear interrupt status bits in the united completion path instead of +trying to do it on every interrupt which isn't necessary. +Only CLKT, ERR and DONE can be cleared that way. + +Add the status value to the error value in case of TXW/RXR errors to +distinguish them from the other S_LEN error. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt --- - arch/arm/configs/bcm2709_defconfig | 3 ++- - arch/arm/configs/bcmrpi_defconfig | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) + drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 9 deletions(-) -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 48ed6bfe263a6a3fab942d0b52b2f409055f23ad..6757f597213cb029ef5a7ded516848685b89fe4c 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -44,7 +44,6 @@ CONFIG_SMP=y - CONFIG_VMSPLIT_2G=y - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y --CONFIG_OABI_COMPAT=y - # CONFIG_CPU_SW_DOMAIN_PAN is not set - CONFIG_CLEANCACHE=y - CONFIG_FRONTSWAP=y -@@ -58,6 +57,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=y - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y -@@ -1271,6 +1271,7 @@ CONFIG_BOOT_PRINTK_DELAY=y - CONFIG_DEBUG_MEMORY_INIT=y - CONFIG_DETECT_HUNG_TASK=y - CONFIG_TIMER_STATS=y -+CONFIG_LATENCYTOP=y - CONFIG_IRQSOFF_TRACER=y - CONFIG_SCHED_TRACER=y - CONFIG_STACK_TRACER=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index ff69cafd7fb706fc0069d59c37974c4ce5d50043..e683fe6eb803fefaee137f7e6da6cf346ddd5a14 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -43,7 +43,6 @@ CONFIG_ARCH_BCM2835=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y --CONFIG_OABI_COMPAT=y - # CONFIG_CPU_SW_DOMAIN_PAN is not set - CONFIG_CLEANCACHE=y - CONFIG_FRONTSWAP=y -@@ -57,11 +56,13 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=y - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y - CONFIG_VFP=y - CONFIG_BINFMT_MISC=m - # CONFIG_SUSPEND is not set +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index f283b714aa79e2e4685ed95b04b6b289f7e9eee7..d2ba1a4de36af512e8e3c97251bd3537ae61591a 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -50,8 +50,6 @@ + #define BCM2835_I2C_S_CLKT BIT(9) + #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ + +-#define BCM2835_I2C_BITMSK_S 0x03FF +- + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + +@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) + } + } + ++/* ++ * Note about I2C_C_CLEAR on error: ++ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in ++ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through ++ * the state machine to send a NACK and a STOP. Since we're setting CLEAR ++ * without I2CEN, that NACK will be hanging around queued up for next time ++ * we start the engine. ++ */ ++ + static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + { + struct bcm2835_i2c_dev *i2c_dev = data; + u32 val, err; + + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); +- val &= BCM2835_I2C_BITMSK_S; +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); + + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); + if (err) { + i2c_dev->msg_err = err; +- complete(&i2c_dev->completion); +- return IRQ_HANDLED; ++ goto complete; + } + + if (val & BCM2835_I2C_S_DONE) { +@@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + i2c_dev->msg_err = BCM2835_I2C_S_LEN; + else + i2c_dev->msg_err = 0; +- complete(&i2c_dev->completion); +- return IRQ_HANDLED; ++ goto complete; + } + + if (val & BCM2835_I2C_S_TXW) { ++ if (!i2c_dev->msg_buf_remaining) { ++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; ++ goto complete; ++ } ++ + bcm2835_fill_txfifo(i2c_dev); + return IRQ_HANDLED; + } + + if (val & BCM2835_I2C_S_RXR) { ++ if (!i2c_dev->msg_buf_remaining) { ++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; ++ goto complete; ++ } ++ + bcm2835_drain_rxfifo(i2c_dev); + return IRQ_HANDLED; + } + + return IRQ_NONE; ++ ++complete: ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT | ++ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE); ++ complete(&i2c_dev->completion); ++ ++ return IRQ_HANDLED; + } + + static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, +@@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + BCM2835_I2C_TIMEOUT); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); + if (!time_left) { ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, ++ BCM2835_I2C_C_CLEAR); + dev_err(i2c_dev->dev, "i2c transfer timed out\n"); + return -ETIMEDOUT; + } -From d6a316e01480a79073f6baf8b89b5cfcb4900f25 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 5 Dec 2016 17:10:44 +0000 -Subject: [PATCH 205/208] BCM270X_DT: Add i2c-sensor overlay +From 8cf47e3091e11ac5db049059d99c6358365eeafb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Mon, 19 Sep 2016 17:19:41 +0200 +Subject: [PATCH 106/111] i2c: bcm2835: Use dev_dbg logging on transfer errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit -The i2c-sensor overlay is a container for various pressure and -temperature sensors, currently bmp085 and bmp280. The standalone -bmp085_i2c-sensor overlay is now deprecated. +Writing to an AT24C32 generates on average 2x i2c transfer errors per +32-byte page write. Which amounts to a lot for a 4k write. This is due +to the fact that the chip doesn't respond during it's internal write +cycle when the at24 driver tries and retries the next write. +Only a handful drivers use dev_err() on transfer error, so switch to +dev_dbg() instead. -Signed-off-by: Phil Elwell +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt --- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 12 ++++++-- - arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 34 +++++++++++++++++++++++ - 3 files changed, 45 insertions(+), 2 deletions(-) - create mode 100644 arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 7624812d0cdc74728f3556159871c7a299f9f6b7..11dba31712840a9e4b91acd4565c2d6266315273 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -32,6 +32,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - i2c-mux.dtbo \ - i2c-pwm-pca9685a.dtbo \ - i2c-rtc.dtbo \ -+ i2c-sensor.dtbo \ - i2c0-bcm2708.dtbo \ - i2c1-bcm2708.dtbo \ - i2s-gpio28-31.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index c0290531a61fedfe23e820ca4d9693a0acd3e876..4ef35f4ac1622be08066dc74a80d907ae6c164b7 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -283,8 +283,7 @@ Params: swap_lr Reverse the channel allocation, which will also - - - Name: bmp085_i2c-sensor --Info: Configures the BMP085/BMP180 digital barometric pressure and temperature -- sensors from Bosch Sensortec -+Info: This overlay is now deprecated - see i2c-sensor - Load: dtoverlay=bmp085_i2c-sensor - Params: - -@@ -542,6 +541,15 @@ Params: abx80x Select one of the ABx80x family: - source - - -+Name: i2c-sensor -+Info: Adds support for a number of I2C barometric pressure and temperature -+ sensors on i2c_arm -+Load: dtoverlay=i2c-sensor,= -+Params: bmp085 Select the Bosch sensortronic BMP085 -+ -+ bmp280 Select the Bosch sensortronic BMP280 -+ -+ - Name: i2c0-bcm2708 - Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations - are usable on all platforms. -diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..f6d134c095af2398fc55ae7d2b0e86456c30627c ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for a few digital barometric pressure and temperature sensors -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ bmp085: bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "disable"; -+ }; -+ -+ bmp280: bmp280@76 { -+ compatible = "bosch,bmp280"; -+ reg = <0x76>; -+ status = "disable"; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ bmp085 = <&bmp085>,"status"; -+ bmp280 = <&bmp280>,"status"; -+ }; -+}; - -From 9265a25166962ef139810f8c1ca51366da98e6d1 Mon Sep 17 00:00:00 2001 -From: Georgii Staroselskii -Date: Wed, 7 Dec 2016 15:10:27 +0300 -Subject: [PATCH 206/208] BCM270X_DT: overlays/*-overlay.dtb -> overlays/*.dtbo - (#1752) - -We now create overlays as .dtbo files. ---- - arch/arm/boot/dts/overlays/README | 2 +- + drivers/i2c/busses/i2c-bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 4ef35f4ac1622be08066dc74a80d907ae6c164b7..81d991803be335e5a1bc3bb0a8c7a2c9f5c392bd 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -61,7 +61,7 @@ this becomes a line in config.txt: +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index d2ba1a4de36af512e8e3c97251bd3537ae61591a..54d510abd46a117c9238fc6d7edec84019d1f60d 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + (msg->flags & I2C_M_IGNORE_NAK)) + return 0; - dtoverlay=lirc-rpi - --This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By -+This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By - default it will use GPIOs 17 (out) and 18 (in), but this can be modified using - DT parameters: +- dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); ++ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; -From 366621f36df68f06589b2813a8fd715cf8f898a7 Mon Sep 17 00:00:00 2001 -From: Ioan-Adrian Ratiu -Date: Tue, 27 Sep 2016 21:41:37 +0300 -Subject: [PATCH 207/208] Revert "HID: dragonrise: fix HID Descriptor for - 0x0006 PID" +From ddda57262c214495254890c94e598b8fca25dfc9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Thu, 22 Sep 2016 22:05:50 +0200 +Subject: [PATCH 107/111] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit -[ Upstream commit 1bcaa05ebee115213e34f1806cc6a4f7a6175a88 ] +The controller can't support this flag, so remove it. -This reverts commit 18339f59c3a6 ("HID: dragonrise: fix HID...") because it -breaks certain dragonrise 0079:0006 gamepads. While it may fix a breakage -caused by commit 79346d620e9d ("HID: input: force generic axis to be mapped -to their user space axis"), it is probable that the manufacturer released -different hardware with the same PID so this fix works for only a subset -and breaks the other gamepads sharing the PID. +Documentation/i2c/i2c-protocol states that all of the message is sent: -What is needed is another more generic solution which fixes 79346d620e9d -("HID: input: force generic axis ...") breakage for this controller: we -need to add an exception for this driver to make it keep the old behaviour -previous to the initial breakage (this is done in patch 2 of this series). +I2C_M_IGNORE_NAK: + Normally message is interrupted immediately if there is [NA] from the + client. Setting this flag treats any [NA] as [A], and all of + message is sent. -Signed-off-by: Ioan-Adrian Ratiu -Reviewed-by: Benjamin Tissoires -Signed-off-by: Jiri Kosina +From the BCM2835 ARM Peripherals datasheet: + + The ERR field is set when the slave fails to acknowledge either + its address or a data byte written to it. + +So when the controller doesn't receive an ack, it sets ERR and raises +an interrupt. In other words, the whole message is not sent. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt --- - drivers/hid/hid-dr.c | 58 ---------------------------------------------------- - 1 file changed, 58 deletions(-) + drivers/i2c/busses/i2c-bcm2835.c | 4 ---- + 1 file changed, 4 deletions(-) -diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c -index 8fd4bf77f264940ec04631252062e06aafe148c8..2523f8a4b7de9fb3152d1268ba7f79c24208c4c9 100644 ---- a/drivers/hid/hid-dr.c -+++ b/drivers/hid/hid-dr.c -@@ -234,58 +234,6 @@ static __u8 pid0011_rdesc_fixed[] = { - 0xC0 /* End Collection */ +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index 54d510abd46a117c9238fc6d7edec84019d1f60d..565ef69ce61423544dc0558c85ef318b0ae9c324 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + if (likely(!i2c_dev->msg_err)) + return 0; + +- if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && +- (msg->flags & I2C_M_IGNORE_NAK)) +- return 0; +- + dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + +From eaf51d9298d9dde20bded52c63eda7f4e536b992 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 04:54:27 +0200 +Subject: [PATCH 108/111] i2c: bcm2835: Add support for Repeated Start + Condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Documentation/i2c/i2c-protocol states that Combined transactions should +separate messages with a Start bit and end the whole transaction with a +Stop bit. This patch adds support for issuing only a Start between +messages instead of a Stop followed by a Start. + +This implementation differs from downstream i2c-bcm2708 in 2 respects: +- it uses an interrupt to detect that the transfer is active instead + of using polling. There is no interrupt for Transfer Active, but by + not prefilling the FIFO it's possible to use the TXW interrupt. +- when resetting/disabling the controller between transfers it writes + CLEAR to the control register instead of just zero. + Using just zero gave many errors. This might be the reason why + downstream had to disable this feature and make it available with a + module parameter. + +I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) +and AT24C32 (eeprom) in parallel without problems. + +Signed-off-by: Noralf Trønnes +Acked-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++--------------- + 1 file changed, 63 insertions(+), 38 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index 565ef69ce61423544dc0558c85ef318b0ae9c324..241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev { + struct i2c_adapter adapter; + struct completion completion; + struct i2c_msg *curr_msg; ++ int num_msgs; + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; +@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) + } + + /* ++ * Repeated Start Condition (Sr) ++ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it ++ * talks about reading from a slave with 10 bit address. This is achieved by ++ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then ++ * issue a read. ++ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the ++ * firmware actually does it using polling and says that it's a workaround for ++ * a problem in the state machine. ++ * It turns out that it is possible to use the TXW interrupt to know when the ++ * transfer is active, provided the FIFO has not been prefilled. ++ */ ++ ++static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN; ++ struct i2c_msg *msg = i2c_dev->curr_msg; ++ bool last_msg = (i2c_dev->num_msgs == 1); ++ ++ if (!i2c_dev->num_msgs) ++ return; ++ ++ i2c_dev->num_msgs--; ++ i2c_dev->msg_buf = msg->buf; ++ i2c_dev->msg_buf_remaining = msg->len; ++ ++ if (msg->flags & I2C_M_RD) ++ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; ++ else ++ c |= BCM2835_I2C_C_INTT; ++ ++ if (last_msg) ++ c |= BCM2835_I2C_C_INTD; ++ ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++} ++ ++/* + * Note about I2C_C_CLEAR on error: + * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in + * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through +@@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + } + + bcm2835_fill_txfifo(i2c_dev); ++ ++ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { ++ i2c_dev->curr_msg++; ++ bcm2835_i2c_start_transfer(i2c_dev); ++ } ++ + return IRQ_HANDLED; + } + +@@ -175,30 +221,25 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + return IRQ_HANDLED; + } + +-static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, +- struct i2c_msg *msg) ++static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ++ int num) + { +- u32 c; ++ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + unsigned long time_left; ++ int i; + +- i2c_dev->curr_msg = msg; +- i2c_dev->msg_buf = msg->buf; +- i2c_dev->msg_buf_remaining = msg->len; +- reinit_completion(&i2c_dev->completion); +- +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); ++ for (i = 0; i < (num - 1); i++) ++ if (msgs[i].flags & I2C_M_RD) { ++ dev_warn_once(i2c_dev->dev, ++ "only one read message supported, has to be last\n"); ++ return -EOPNOTSUPP; ++ } + +- if (msg->flags & I2C_M_RD) { +- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; +- } else { +- c = BCM2835_I2C_C_INTT; +- bcm2835_fill_txfifo(i2c_dev); +- } +- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; ++ i2c_dev->curr_msg = msgs; ++ i2c_dev->num_msgs = num; ++ reinit_completion(&i2c_dev->completion); + +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++ bcm2835_i2c_start_transfer(i2c_dev); + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + BCM2835_I2C_TIMEOUT); +@@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + return -ETIMEDOUT; + } + +- if (likely(!i2c_dev->msg_err)) +- return 0; ++ if (!i2c_dev->msg_err) ++ return num; + + dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; +- else +- return -EIO; +-} +- +-static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], +- int num) +-{ +- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); +- int i; +- int ret = 0; +- +- for (i = 0; i < num; i++) { +- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); +- if (ret) +- break; +- } + +- return ret ?: i; ++ return -EIO; + } + + static u32 bcm2835_i2c_func(struct i2c_adapter *adap) + +From f7b9050bbbf5e15b9f4c5af03d9a9bd9edc39049 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 04:57:17 +0200 +Subject: [PATCH 109/111] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use i2c_adapter->timeout for the completion timeout value. The core +default is 1 second. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index 241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f..d2085dd3742eabebc537621968088261f8dc7ea8 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -53,8 +53,6 @@ + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + +-#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) +- + struct bcm2835_i2c_dev { + struct device *dev; + void __iomem *regs; +@@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + bcm2835_i2c_start_transfer(i2c_dev); + + time_left = wait_for_completion_timeout(&i2c_dev->completion, +- BCM2835_I2C_TIMEOUT); ++ adap->timeout); + if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); + +From 8b97b2301e5e691828b2ea1210cabd55fa930b5e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Tue, 27 Sep 2016 01:00:08 +0200 +Subject: [PATCH 110/111] i2c: bcm2835: Add support for dynamic clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Support a dynamic clock by reading the frequency and setting the +divisor in the transfer function instead of during probe. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Martin Sperl +--- + drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 19 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index d2085dd3742eabebc537621968088261f8dc7ea8..c3436f627028477f7e21b47e079fd5ab06ec188a 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev { + void __iomem *regs; + struct clk *clk; + int irq; ++ u32 bus_clk_rate; + struct i2c_adapter adapter; + struct completion completion; + struct i2c_msg *curr_msg; +@@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) + return readl(i2c_dev->regs + reg); + } + ++static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ u32 divider; ++ ++ divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), ++ i2c_dev->bus_clk_rate); ++ /* ++ * Per the datasheet, the register is always interpreted as an even ++ * number, by rounding down. In other words, the LSB is ignored. So, ++ * if the LSB is set, increment the divider to avoid any issue. ++ */ ++ if (divider & 1) ++ divider++; ++ if ((divider < BCM2835_I2C_CDIV_MIN) || ++ (divider > BCM2835_I2C_CDIV_MAX)) { ++ dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); ++ return -EINVAL; ++ } ++ ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); ++ ++ return 0; ++} ++ + static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) + { + u32 val; +@@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + { + struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + unsigned long time_left; +- int i; ++ int i, ret; + + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { +@@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + return -EOPNOTSUPP; + } + ++ ret = bcm2835_i2c_set_divider(i2c_dev); ++ if (ret) ++ return ret; ++ + i2c_dev->curr_msg = msgs; + i2c_dev->num_msgs = num; + reinit_completion(&i2c_dev->completion); +@@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) + { + struct bcm2835_i2c_dev *i2c_dev; + struct resource *mem, *irq; +- u32 bus_clk_rate, divider; + int ret; + struct i2c_adapter *adap; + +@@ -306,27 +334,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) + } + + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", +- &bus_clk_rate); ++ &i2c_dev->bus_clk_rate); + if (ret < 0) { + dev_warn(&pdev->dev, + "Could not read clock-frequency property\n"); +- bus_clk_rate = 100000; +- } +- +- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); +- /* +- * Per the datasheet, the register is always interpreted as an even +- * number, by rounding down. In other words, the LSB is ignored. So, +- * if the LSB is set, increment the divider to avoid any issue. +- */ +- if (divider & 1) +- divider++; +- if ((divider < BCM2835_I2C_CDIV_MIN) || +- (divider > BCM2835_I2C_CDIV_MAX)) { +- dev_err(&pdev->dev, "Invalid clock-frequency\n"); +- return -ENODEV; ++ i2c_dev->bus_clk_rate = 100000; + } +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) { + +From 5c14442e251ac2c6f434c914beb3f09ed6573821 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Tue, 1 Nov 2016 15:15:41 +0100 +Subject: [PATCH 111/111] i2c: bcm2835: Add debug support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds a debug module parameter to aid in debugging transfer issues +by printing info to the kernel log. When enabled, status values are +collected in the interrupt routine and msg info in +bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid +affecting timing. Having printk in the isr can mask issues. + +debug values (additive): +1: Print info on error +2: Print info on all transfers +3: Print messages before transfer is started + +The value can be changed at runtime: +/sys/module/i2c_bcm2835/parameters/debug + +Example output, debug=3: +[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] +[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] + +Signed-off-by: Noralf Trønnes +--- + drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 98 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index c3436f627028477f7e21b47e079fd5ab06ec188a..8642f580ce41803bd22c76a0fa80d083d0747be1 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -53,6 +53,18 @@ + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + ++static unsigned int debug; ++module_param(debug, uint, 0644); ++MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); ++ ++#define BCM2835_DEBUG_MAX 512 ++struct bcm2835_debug { ++ struct i2c_msg *msg; ++ int msg_idx; ++ size_t remain; ++ u32 status; ++}; ++ + struct bcm2835_i2c_dev { + struct device *dev; + void __iomem *regs; +@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; ++ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; ++ unsigned int debug_num; ++ unsigned int debug_num_msgs; }; --static __u8 pid0006_rdesc_fixed[] = { -- 0x05, 0x01, /* Usage Page (Generic Desktop) */ -- 0x09, 0x04, /* Usage (Joystick) */ -- 0xA1, 0x01, /* Collection (Application) */ -- 0xA1, 0x02, /* Collection (Logical) */ -- 0x75, 0x08, /* Report Size (8) */ -- 0x95, 0x05, /* Report Count (5) */ -- 0x15, 0x00, /* Logical Minimum (0) */ -- 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ -- 0x35, 0x00, /* Physical Minimum (0) */ -- 0x46, 0xFF, 0x00, /* Physical Maximum (255) */ -- 0x09, 0x30, /* Usage (X) */ -- 0x09, 0x33, /* Usage (Ry) */ -- 0x09, 0x32, /* Usage (Z) */ -- 0x09, 0x31, /* Usage (Y) */ -- 0x09, 0x34, /* Usage (Ry) */ -- 0x81, 0x02, /* Input (Variable) */ -- 0x75, 0x04, /* Report Size (4) */ -- 0x95, 0x01, /* Report Count (1) */ -- 0x25, 0x07, /* Logical Maximum (7) */ -- 0x46, 0x3B, 0x01, /* Physical Maximum (315) */ -- 0x65, 0x14, /* Unit (Centimeter) */ -- 0x09, 0x39, /* Usage (Hat switch) */ -- 0x81, 0x42, /* Input (Variable) */ -- 0x65, 0x00, /* Unit (None) */ -- 0x75, 0x01, /* Report Size (1) */ -- 0x95, 0x0C, /* Report Count (12) */ -- 0x25, 0x01, /* Logical Maximum (1) */ -- 0x45, 0x01, /* Physical Maximum (1) */ -- 0x05, 0x09, /* Usage Page (Button) */ -- 0x19, 0x01, /* Usage Minimum (0x01) */ -- 0x29, 0x0C, /* Usage Maximum (0x0C) */ -- 0x81, 0x02, /* Input (Variable) */ -- 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ -- 0x75, 0x01, /* Report Size (1) */ -- 0x95, 0x08, /* Report Count (8) */ -- 0x25, 0x01, /* Logical Maximum (1) */ -- 0x45, 0x01, /* Physical Maximum (1) */ -- 0x09, 0x01, /* Usage (0x01) */ -- 0x81, 0x02, /* Input (Variable) */ -- 0xC0, /* End Collection */ -- 0xA1, 0x02, /* Collection (Logical) */ -- 0x75, 0x08, /* Report Size (8) */ -- 0x95, 0x07, /* Report Count (7) */ -- 0x46, 0xFF, 0x00, /* Physical Maximum (255) */ -- 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ -- 0x09, 0x02, /* Usage (0x02) */ -- 0x91, 0x02, /* Output (Variable) */ -- 0xC0, /* End Collection */ -- 0xC0 /* End Collection */ --}; -- - static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) - { -@@ -296,12 +244,6 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - *rsize = sizeof(pid0011_rdesc_fixed); - } - break; -- case 0x0006: -- if (*rsize == sizeof(pid0006_rdesc_fixed)) { -- rdesc = pid0006_rdesc_fixed; -- *rsize = sizeof(pid0006_rdesc_fixed); -- } -- break; - } - return rdesc; - } - -From 822b0eb3dac2230ec04d71eeccea28b2528eb4a2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 6 Dec 2016 17:05:39 +0000 -Subject: [PATCH 208/208] bcm2835-rng: Avoid initialising if already enabled - -Avoids the 0x40000 cycles of warmup again if firmware has already used it ---- - drivers/char/hw_random/bcm2835-rng.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c -index af2149273fe049b075d0953034cda0aab1525f23..e5b5222314b1677d989f7e7ea7085cacde8ff1b6 100644 ---- a/drivers/char/hw_random/bcm2835-rng.c -+++ b/drivers/char/hw_random/bcm2835-rng.c -@@ -101,9 +101,10 @@ static int bcm2835_rng_probe(struct platform_device *pdev) - rng_setup(rng_base); - - /* set warm-up count & enable */ -- __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); -- __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); -- -+ if (!(__raw_readl(rng_base + RNG_CTRL) & RNG_RBGEN)) { -+ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); -+ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); ++static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) ++{ ++ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ return; ++ ++ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; ++ i2c_dev->debug[i2c_dev->debug_num].msg_idx = ++ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; ++ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; ++ i2c_dev->debug[i2c_dev->debug_num].status = s; ++ i2c_dev->debug_num++; ++} ++ ++static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, ++ struct bcm2835_debug *d) ++{ ++ u32 s = d->status; ++ ++ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", ++ d->remain, s, ++ s & BCM2835_I2C_S_TA ? "TA " : "", ++ s & BCM2835_I2C_S_DONE ? "DONE " : "", ++ s & BCM2835_I2C_S_TXW ? "TXW " : "", ++ s & BCM2835_I2C_S_RXR ? "RXR " : "", ++ s & BCM2835_I2C_S_TXD ? "TXD " : "", ++ s & BCM2835_I2C_S_RXD ? "RXD " : "", ++ s & BCM2835_I2C_S_TXE ? "TXE " : "", ++ s & BCM2835_I2C_S_RXF ? "RXF " : "", ++ s & BCM2835_I2C_S_ERR ? "ERR " : "", ++ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, ++ struct i2c_msg *msg, int i, int total, ++ const char *fname) ++{ ++ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", ++ fname, i, total, ++ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, ++ msg->flags & I2C_M_TEN ? "TEN" : "", ++ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", ++ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", ++ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", ++ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", ++ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", ++ msg->flags & I2C_M_STOP ? "STOP" : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ struct bcm2835_debug *d; ++ unsigned int i; ++ ++ for (i = 0; i < i2c_dev->debug_num; i++) { ++ d = &i2c_dev->debug[i]; ++ if (d->status == ~0) ++ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, ++ i2c_dev->debug_num_msgs, "start_transfer"); ++ else ++ bcm2835_debug_print_status(i2c_dev, d); + } - /* register driver */ - err = hwrng_register(&bcm2835_rng_ops); ++ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ pr_info("BCM2835_DEBUG_MAX reached\n"); ++} ++ + static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, + u32 reg, u32 val) + { +@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++ bcm2835_debug_add(i2c_dev, ~0); + } + + /* +@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + u32 val, err; + + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); ++ bcm2835_debug_add(i2c_dev, val); + + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); if (err) { +@@ -251,6 +335,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + unsigned long time_left; + int i, ret; + ++ if (debug) ++ i2c_dev->debug_num_msgs = num; ++ ++ if (debug > 2) ++ for (i = 0; i < num; i++) ++ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); ++ + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { + dev_warn_once(i2c_dev->dev, +@@ -270,6 +361,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + adap->timeout); ++ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) ++ bcm2835_debug_print(i2c_dev); ++ i2c_dev->debug_num_msgs = 0; ++ i2c_dev->debug_num = 0; + if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); +@@ -280,7 +375,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + if (!i2c_dev->msg_err) + return num; + +- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); ++ if (debug) ++ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", ++ i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; diff --git a/projects/RPi2/linux/linux.arm.conf b/projects/RPi2/linux/linux.arm.conf index 6279f2192d..abb64893fe 100644 --- a/projects/RPi2/linux/linux.arm.conf +++ b/projects/RPi2/linux/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.8.11 Kernel Configuration +# Linux/arm 4.9.0 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -67,6 +67,7 @@ CONFIG_HANDLE_DOMAIN_IRQ=y # CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_ARCH_HAS_TICK_BROADCAST=y @@ -244,6 +245,7 @@ CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y # CONFIG_CPU_NO_EFFICIENT_FFS is not set +# CONFIG_HAVE_ARCH_VMAP_STACK is not set # # GCOV-based kernel profiling @@ -379,6 +381,7 @@ CONFIG_ARCH_BCM=y # Other Architectures # CONFIG_ARCH_BCM2835=y +# CONFIG_ARCH_BCM_53573 is not set # CONFIG_ARCH_BCM_63XX is not set # CONFIG_ARCH_BRCMSTB is not set # CONFIG_ARCH_BERLIN is not set @@ -586,7 +589,8 @@ CONFIG_AUTO_ZRELADDR=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_ATTR_SET=y CONFIG_CPU_FREQ_GOV_COMMON=y -# CONFIG_CPU_FREQ_STAT is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set @@ -641,6 +645,7 @@ CONFIG_BINFMT_ELF=y CONFIG_ELFCORE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y +# CONFIG_BINFMT_FLAT is not set # CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set CONFIG_COREDUMP=y @@ -1002,6 +1007,7 @@ CONFIG_BT_HCIUART_3WIRE=y CONFIG_BT_HCIUART_BCM=y # CONFIG_BT_HCIUART_QCA is not set # CONFIG_BT_HCIUART_AG6XX is not set +# CONFIG_BT_HCIUART_MRVL is not set CONFIG_BT_HCIBCM203X=m # CONFIG_BT_HCIBPA10X is not set CONFIG_BT_HCIBFUSB=m @@ -1010,6 +1016,7 @@ CONFIG_BT_HCIBFUSB=m CONFIG_BT_ATH3K=m # CONFIG_AF_RXRPC is not set # CONFIG_AF_KCM is not set +# CONFIG_STREAM_PARSER is not set CONFIG_WIRELESS=y CONFIG_WIRELESS_EXT=y CONFIG_WEXT_CORE=y @@ -1070,6 +1077,7 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_ALLOW_DEV_COREDUMP is not set # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set CONFIG_REGMAP=y @@ -1149,8 +1157,6 @@ CONFIG_BCM2835_SMI=m # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085_I2C is not set -# CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set # CONFIG_SRAM is not set @@ -1177,7 +1183,6 @@ CONFIG_EEPROM_93CX6=m # Altera FPGA firmware download module # # CONFIG_ALTERA_STAPL is not set -CONFIG_BCM2708_VCHIQ=y # # Intel MIC Bus Driver @@ -1267,7 +1272,6 @@ CONFIG_NET_CORE=y # CONFIG_NET_TEAM is not set CONFIG_MACVLAN=m # CONFIG_MACVTAP is not set -# CONFIG_IPVLAN is not set # CONFIG_VXLAN is not set # CONFIG_MACSEC is not set CONFIG_NETCONSOLE=y @@ -1291,38 +1295,44 @@ CONFIG_PHYLIB=y CONFIG_SWPHY=y # -# MII PHY device drivers +# MDIO bus device drivers # -# CONFIG_AQUANTIA_PHY is not set -# CONFIG_AT803X_PHY is not set -# CONFIG_AMD_PHY is not set -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_TERANETICS_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_BCM7XXX_PHY is not set -# CONFIG_BCM87XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_DP83848_PHY is not set -# CONFIG_DP83867_PHY is not set -# CONFIG_MICROCHIP_PHY is not set -CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BCM_UNIMAC is not set # CONFIG_MDIO_BITBANG is not set # CONFIG_MDIO_BUS_MUX_GPIO is not set # CONFIG_MDIO_BUS_MUX_MMIOREG is not set -# CONFIG_MDIO_BCM_UNIMAC is not set -# CONFIG_INTEL_XWAY_PHY is not set # CONFIG_MDIO_HISI_FEMAC is not set + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_ICPLUS_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set # CONFIG_MICREL_KS8995MA is not set CONFIG_PPP=m CONFIG_PPP_BSDCOMP=m @@ -1560,11 +1570,11 @@ CONFIG_TOUCHSCREEN_ADS7846=m # CONFIG_TOUCHSCREEN_EETI is not set CONFIG_TOUCHSCREEN_EGALAX=m # CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set -# CONFIG_TOUCHSCREEN_FT6236 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GOODIX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set # CONFIG_TOUCHSCREEN_ELAN is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set @@ -1630,6 +1640,7 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_BEEPER is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_GPIO_DECODER is not set # CONFIG_INPUT_ATI_REMOTE2 is not set # CONFIG_INPUT_KEYSPAN_REMOTE is not set # CONFIG_INPUT_KXTJ9 is not set @@ -1802,6 +1813,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_AXI_SPI_ENGINE is not set CONFIG_SPI_BCM2835=m CONFIG_SPI_BCM2835AUX=m +# CONFIG_SPI_BCM_QSPI is not set # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_CADENCE is not set # CONFIG_SPI_DESIGNWARE is not set @@ -1855,7 +1867,6 @@ CONFIG_PINCONF=y CONFIG_PINCTRL_BCM2835=y CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_GPIOLIB=y -CONFIG_GPIO_DEVRES=y CONFIG_OF_GPIO=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y @@ -1870,6 +1881,7 @@ CONFIG_GPIO_BCM_VIRT=y # CONFIG_GPIO_EM is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_MOCKUP is not set # CONFIG_GPIO_MPC8XXX is not set # CONFIG_GPIO_PL061 is not set # CONFIG_GPIO_SYSCON is not set @@ -1888,11 +1900,13 @@ CONFIG_GPIO_BCM_VIRT=y # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set # CONFIG_GPIO_TPIC2810 is not set +# CONFIG_GPIO_TS4900 is not set # # MFD GPIO expanders # CONFIG_GPIO_ARIZONA=m +# CONFIG_HTC_EGPIO is not set # # SPI GPIO expanders @@ -1936,6 +1950,18 @@ CONFIG_W1_SLAVE_THERM=m # CONFIG_W1_SLAVE_DS2781 is not set # CONFIG_W1_SLAVE_DS28E04 is not set # CONFIG_W1_SLAVE_BQ27000 is not set +# CONFIG_POWER_AVS is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMKONA is not set +# CONFIG_POWER_RESET_BRCMSTB is not set +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_RESTART=y +# CONFIG_POWER_RESET_VERSATILE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_SYSCON_REBOOT_MODE is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set @@ -1958,18 +1984,6 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set # CONFIG_CHARGER_RT9455 is not set -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_BRCMKONA is not set -# CONFIG_POWER_RESET_BRCMSTB is not set -CONFIG_POWER_RESET_GPIO=y -CONFIG_POWER_RESET_GPIO_RESTART=y -# CONFIG_POWER_RESET_LTC2952 is not set -CONFIG_POWER_RESET_RESTART=y -# CONFIG_POWER_RESET_VERSATILE is not set -# CONFIG_POWER_RESET_SYSCON is not set -# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set -# CONFIG_SYSCON_REBOOT_MODE is not set -# CONFIG_POWER_AVS is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -2110,6 +2124,7 @@ CONFIG_THERMAL_GOV_STEP_WISE=y # CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set # CONFIG_CPU_THERMAL is not set # CONFIG_THERMAL_EMULATION is not set +# CONFIG_QORIQ_THERMAL is not set CONFIG_THERMAL_BCM2835=y # @@ -2138,6 +2153,11 @@ CONFIG_BCM2835_WDT=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set + +# +# Watchdog Pretimeout Governors +# +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set CONFIG_SSB_POSSIBLE=y # @@ -2186,10 +2206,10 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_DA9063 is not set # CONFIG_MFD_DA9150 is not set # CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_EXYNOS_LPASS is not set # CONFIG_MFD_MC13XXX_SPI is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_MFD_HI6421_PMIC is not set -# CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set # CONFIG_INTEL_SOC_PMIC is not set @@ -2237,6 +2257,7 @@ CONFIG_MFD_SYSCON=y # CONFIG_MFD_TPS65086 is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set # CONFIG_MFD_TPS65218 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set @@ -2371,6 +2392,7 @@ CONFIG_VIDEO_TM6000_DVB=m # CONFIG_DVB_USB=m # CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB3000MC=m # CONFIG_DVB_USB_A800 is not set CONFIG_DVB_USB_DIBUSB_MB=m CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y @@ -2396,6 +2418,18 @@ CONFIG_DVB_USB_DTV5100=m # CONFIG_DVB_USB_FRIIO is not set CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_TBSQBOX=m +CONFIG_DVB_USB_TBSQBOX2=m +CONFIG_DVB_USB_TBSQBOX22=m +CONFIG_DVB_USB_TBS5922SE=m +CONFIG_DVB_USB_TBSQBOXS2=m +CONFIG_DVB_USB_TBSQBOX2CI=m +CONFIG_DVB_USB_TBS5925=m +CONFIG_DVB_USB_TBS5880=m +CONFIG_DVB_USB_TBS5220=m +CONFIG_DVB_USB_TBS5881=m +CONFIG_DVB_USB_TBS5520=m +CONFIG_DVB_USB_TBS5927=m CONFIG_DVB_USB_V2=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m @@ -2446,7 +2480,7 @@ CONFIG_SMS_SIANO_RC=y # CONFIG_SMS_SIANO_DEBUGFS is not set # -# Media ancillary drivers (tuners, sensors, i2c, frontends) +# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_MEDIA_ATTACH=y @@ -2532,6 +2566,9 @@ CONFIG_MEDIA_TUNER_SI2157=m CONFIG_MEDIA_TUNER_IT913X=m CONFIG_MEDIA_TUNER_R820T=m CONFIG_MEDIA_TUNER_QM1D1C0042=m +CONFIG_MEDIA_TUNER_AV201X=m +CONFIG_MEDIA_TUNER_STV6120=m +CONFIG_MEDIA_TUNER_R848=m # # Multistandard (satellite) frontends @@ -2593,6 +2630,7 @@ CONFIG_DVB_RTL2830=m CONFIG_DVB_RTL2832=m CONFIG_DVB_SI2168=m CONFIG_DVB_AS102_FE=m +# CONFIG_DVB_GP8PSK_FE is not set # # DVB-C (cable) frontends @@ -2648,10 +2686,13 @@ CONFIG_DVB_ATBM8830=m CONFIG_DVB_IX2505V=m CONFIG_DVB_M88RS2000=m CONFIG_DVB_AF9033=m +CONFIG_DVB_TAS2101=m # # Tools to develop new frontends # +CONFIG_DVB_STV0910=m +CONFIG_DVB_AVL6882=m # CONFIG_DVB_DUMMY_FE is not set # @@ -2800,7 +2841,6 @@ CONFIG_SND_BCM2835_SOC_I2S=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m CONFIG_SND_BCM2708_SOC_RPI_DAC=m CONFIG_SND_BCM2708_SOC_RPI_PROTO=m CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m @@ -2830,13 +2870,6 @@ CONFIG_SND_PISOUND=m # CONFIG_SND_SOC_FSL_ESAI is not set # CONFIG_SND_SOC_IMX_AUDMUX is not set # CONFIG_SND_SOC_IMG is not set - -# -# Allwinner SoC Audio support -# -# CONFIG_SND_SUN4I_CODEC is not set -# CONFIG_SND_SUN4I_I2S is not set -# CONFIG_SND_SUN4I_SPDIF is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=m @@ -2900,7 +2933,6 @@ CONFIG_SND_SOC_STA32X=m # CONFIG_SND_SOC_TAS571X is not set # CONFIG_SND_SOC_TAS5720 is not set # CONFIG_SND_SOC_TFA9879 is not set -CONFIG_SND_SOC_TAS5713=m # CONFIG_SND_SOC_TLV320AIC23_I2C is not set # CONFIG_SND_SOC_TLV320AIC23_SPI is not set # CONFIG_SND_SOC_TLV320AIC31XX is not set @@ -2927,8 +2959,10 @@ CONFIG_SND_SOC_WM8804_I2C=m # CONFIG_SND_SOC_WM8974 is not set # CONFIG_SND_SOC_WM8978 is not set # CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_NAU8810 is not set CONFIG_SND_SOC_TPA6130A2=m # CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SND_SIMPLE_SCU_CARD is not set # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=m @@ -3051,7 +3085,7 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set CONFIG_USB_MON=m # CONFIG_USB_WUSB_CBAF is not set @@ -3196,6 +3230,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set @@ -3209,6 +3244,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_ULPI is not set # CONFIG_USB_GADGET is not set # CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_ULPI_BUS is not set # CONFIG_UWB is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set @@ -3275,6 +3311,7 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_TLC591XX is not set # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_KTD2692 is not set +# CONFIG_LEDS_IS31FL319X is not set # CONFIG_LEDS_IS31FL32XX is not set # @@ -3329,6 +3366,7 @@ CONFIG_RTC_INTF_DEV=y CONFIG_RTC_DRV_ABX80X=m CONFIG_RTC_DRV_DS1307=m CONFIG_RTC_DRV_DS1307_HWMON=y +# CONFIG_RTC_DRV_DS1307_CENTURY is not set # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_HYM8563 is not set @@ -3336,7 +3374,6 @@ CONFIG_RTC_DRV_DS1307_HWMON=y # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_ISL12057 is not set # CONFIG_RTC_DRV_X1205 is not set CONFIG_RTC_DRV_PCF8523=m # CONFIG_RTC_DRV_PCF85063 is not set @@ -3488,6 +3525,8 @@ CONFIG_LIRC_RPI=m # CONFIG_WILC1000_SPI is not set # CONFIG_MOST is not set # CONFIG_KS7010 is not set +# CONFIG_GREYBUS is not set +CONFIG_BCM2708_VCHIQ=y # CONFIG_GOLDFISH is not set # CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y @@ -3507,7 +3546,6 @@ CONFIG_COMMON_CLK=y # CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_PIC32 is not set -# CONFIG_SUNXI_CCU is not set # # Hardware Spinlock drivers @@ -3530,6 +3568,7 @@ CONFIG_ARM_TIMER_SP804=y # CONFIG_EM_TIMER_STI is not set CONFIG_MAILBOX=y # CONFIG_ARM_MHU is not set +# CONFIG_PLATFORM_MHU is not set # CONFIG_PL320_MBOX is not set # CONFIG_ALTERA_MBOX is not set CONFIG_BCM2835_MBOX=y @@ -3565,6 +3604,7 @@ CONFIG_EXTCON=m CONFIG_EXTCON_ARIZONA=m # CONFIG_EXTCON_GPIO is not set # CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_QCOM_SPMI_MISC is not set # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set # CONFIG_EXTCON_USB_GPIO is not set @@ -3575,7 +3615,16 @@ CONFIG_IRQCHIP=y CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_IPACK_BUS is not set CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_ATH79 is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_LPC18XX is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_STM32 is not set +# CONFIG_RESET_SUNXI is not set # CONFIG_TI_SYSCON_RESET is not set +# CONFIG_RESET_ZYNQ is not set # CONFIG_FMC is not set # @@ -3990,6 +4039,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set # CONFIG_UBSAN is not set CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y # CONFIG_STRICT_DEVMEM is not set @@ -4220,7 +4270,6 @@ CONFIG_HAS_DMA=y CONFIG_CPU_RMAP=y CONFIG_DQL=y CONFIG_NLATTR=y -CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set # CONFIG_IRQ_POLL is not set @@ -4233,4 +4282,5 @@ CONFIG_FONT_8x16=y # CONFIG_SG_SPLIT is not set CONFIG_SG_POOL=y CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y # CONFIG_VIRTUALIZATION is not set diff --git a/projects/RPi2/patches/linux/linux-01-RPi_support.patch b/projects/RPi2/patches/linux/linux-01-RPi_support.patch index 1c3a98131a..4369261e5c 100644 --- a/projects/RPi2/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi2/patches/linux/linux-01-RPi_support.patch @@ -1,104 +1,7 @@ -From 7d5fc6dc9e80848e3fb1dc99bf93e3fc6251aed4 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 27 Apr 2016 17:43:28 +0100 -Subject: [PATCH 001/208] Revert "SUNRPC: Make NFS swap work with multipath" - -This reverts commit 15001e5a7e1e207b6bd258cd8f187814cd15b6dc. ---- - net/sunrpc/clnt.c | 66 +++++++++++++++++++++++++++++++++++-------------------- - 1 file changed, 42 insertions(+), 24 deletions(-) - -diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c -index 66f23b376fa04a91134eddf6d8ee22a2f5de5808..f55fe2b0137e8fbefcd20c336b28ad48a7a105c1 100644 ---- a/net/sunrpc/clnt.c -+++ b/net/sunrpc/clnt.c -@@ -2743,39 +2743,57 @@ void rpc_show_tasks(struct net *net) - #endif - - #if IS_ENABLED(CONFIG_SUNRPC_SWAP) --static int --rpc_clnt_swap_activate_callback(struct rpc_clnt *clnt, -- struct rpc_xprt *xprt, -- void *dummy) --{ -- return xprt_enable_swap(xprt); --} -- - int - rpc_clnt_swap_activate(struct rpc_clnt *clnt) - { -- if (atomic_inc_return(&clnt->cl_swapper) == 1) -- return rpc_clnt_iterate_for_each_xprt(clnt, -- rpc_clnt_swap_activate_callback, NULL); -- return 0; --} --EXPORT_SYMBOL_GPL(rpc_clnt_swap_activate); -+ int ret = 0; -+ struct rpc_xprt *xprt; - --static int --rpc_clnt_swap_deactivate_callback(struct rpc_clnt *clnt, -- struct rpc_xprt *xprt, -- void *dummy) --{ -- xprt_disable_swap(xprt); -- return 0; -+ if (atomic_inc_return(&clnt->cl_swapper) == 1) { -+retry: -+ rcu_read_lock(); -+ xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); -+ rcu_read_unlock(); -+ if (!xprt) { -+ /* -+ * If we didn't get a reference, then we likely are -+ * racing with a migration event. Wait for a grace -+ * period and try again. -+ */ -+ synchronize_rcu(); -+ goto retry; -+ } -+ -+ ret = xprt_enable_swap(xprt); -+ xprt_put(xprt); -+ } -+ return ret; - } -+EXPORT_SYMBOL_GPL(rpc_clnt_swap_activate); - - void - rpc_clnt_swap_deactivate(struct rpc_clnt *clnt) - { -- if (atomic_dec_if_positive(&clnt->cl_swapper) == 0) -- rpc_clnt_iterate_for_each_xprt(clnt, -- rpc_clnt_swap_deactivate_callback, NULL); -+ struct rpc_xprt *xprt; -+ -+ if (atomic_dec_if_positive(&clnt->cl_swapper) == 0) { -+retry: -+ rcu_read_lock(); -+ xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); -+ rcu_read_unlock(); -+ if (!xprt) { -+ /* -+ * If we didn't get a reference, then we likely are -+ * racing with a migration event. Wait for a grace -+ * period and try again. -+ */ -+ synchronize_rcu(); -+ goto retry; -+ } -+ -+ xprt_disable_swap(xprt); -+ xprt_put(xprt); -+ } - } - EXPORT_SYMBOL_GPL(rpc_clnt_swap_deactivate); - #endif /* CONFIG_SUNRPC_SWAP */ - -From a076f856510da92d7b277dd9ad19b624ce02a559 Mon Sep 17 00:00:00 2001 +From 187d14c75091ecf91914e7273ea75a94649f5715 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 002/208] smsx95xx: fix crimes against truesize +Subject: [PATCH 001/111] smsx95xx: fix crimes against truesize smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings. @@ -110,10 +13,10 @@ Signed-off-by: Steve Glendinning 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62cb78cc1bb 100644 +index 831aa33d078ae7d2dd57fdded5de71d1eb915f99..b77935bded8c0ff7808b00f170ff10e594300ad0 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -80,6 +80,10 @@ static bool turbo_mode = true; +@@ -82,6 +82,10 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); @@ -124,7 +27,7 @@ index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62c static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -1848,7 +1852,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1951,7 +1955,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(skb); skb_trim(skb, skb->len - 4); /* remove fcs */ @@ -134,7 +37,7 @@ index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62c return 1; } -@@ -1866,7 +1871,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1969,7 +1974,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(ax_skb); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ @@ -145,55 +48,33 @@ index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62c usbnet_skb_return(dev, ax_skb); } -From 1a57f996e9d7b4b9698abf85d2665f32c03a2ded Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 003/208] smsc95xx: Disable turbo mode by default - ---- - drivers/net/usb/smsc95xx.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 116680e3089f16e1e3e9113a3b93e62cb78cc1bb..aa4cb43dcd9ba83b042332bc15a4dce68affce28 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -76,7 +76,7 @@ struct smsc95xx_priv { - struct usbnet *dev; - }; - --static bool turbo_mode = true; -+static bool turbo_mode = false; - module_param(turbo_mode, bool, 0644); - MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); - - -From e256c71277d74a1115d9bd9844fcfb5860fec9b2 Mon Sep 17 00:00:00 2001 +From 584529ad0dc510e6e870aa9141ed889edf2dbbbd Mon Sep 17 00:00:00 2001 From: Sam Nazarko Date: Fri, 1 Apr 2016 17:27:21 +0100 -Subject: [PATCH 004/208] add smsc95xx packetsize module_param +Subject: [PATCH 002/111] smsc95xx: Experimental: Enable turbo_mode and + packetsize=2560 by default -Signed-off-by: Sam Nazarko +See: http://forum.kodi.tv/showthread.php?tid=285288 --- drivers/net/usb/smsc95xx.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index aa4cb43dcd9ba83b042332bc15a4dce68affce28..889bdabd9dea6cebccc361aa4ac569d73681396b 100644 +index b77935bded8c0ff7808b00f170ff10e594300ad0..693f163684de921404738e33244881e0aab92ec9 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -84,6 +84,10 @@ static bool truesize_mode = false; +@@ -86,6 +86,10 @@ static bool truesize_mode = false; module_param(truesize_mode, bool, 0644); MODULE_PARM_DESC(truesize_mode, "Report larger truesize value"); -+static int packetsize = 0; ++static int packetsize = 2560; +module_param(packetsize, int, 0644); +MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); + static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -1005,13 +1009,13 @@ static int smsc95xx_reset(struct usbnet *dev) +@@ -1106,13 +1110,13 @@ static int smsc95xx_reset(struct usbnet *dev) if (!turbo_mode) { burst_cap = 0; @@ -213,10 +94,10 @@ index aa4cb43dcd9ba83b042332bc15a4dce68affce28..889bdabd9dea6cebccc361aa4ac569d7 netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", -From 919b66093359eca7e24223ecbba9e788111c841f Mon Sep 17 00:00:00 2001 +From 2bf8ca86c5944a4f05a715a9a6b137bce58e7a59 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 005/208] Allow mac address to be set in smsc95xx +Subject: [PATCH 003/111] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -224,7 +105,7 @@ Signed-off-by: popcornmix 1 file changed, 56 insertions(+) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9f72bebe3 100644 +index 693f163684de921404738e33244881e0aab92ec9..df60c989fc229bf0aab3c27e95ccd45323367840 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -60,6 +60,7 @@ @@ -235,7 +116,7 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 #define CARRIER_CHECK_DELAY (2 * HZ) -@@ -88,6 +89,10 @@ static int packetsize = 0; +@@ -90,6 +91,10 @@ static int packetsize = 2560; module_param(packetsize, int, 0644); MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); @@ -246,7 +127,7 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -817,6 +822,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +@@ -918,6 +923,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } @@ -300,7 +181,7 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 static void smsc95xx_init_mac_address(struct usbnet *dev) { const u8 *mac_addr; -@@ -838,6 +890,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) +@@ -939,6 +991,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) } } @@ -312,75 +193,10 @@ index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9 eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); -From 6885eab792b8feb8c2329f2981453074fae14527 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 9 Aug 2016 22:19:28 +0100 -Subject: [PATCH 006/208] smsc95xx: Experimental: Enable turbo_mode and - packetsize=2560 by default - -See: http://forum.kodi.tv/showthread.php?tid=285288 ---- - drivers/net/usb/smsc95xx.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index d22a2324085fbf61fbd8920362bfc7b9f72bebe3..c846c55075387398d9bcb0957e31f5c82fd7d58d 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -77,7 +77,7 @@ struct smsc95xx_priv { - struct usbnet *dev; - }; - --static bool turbo_mode = false; -+static bool turbo_mode = true; - module_param(turbo_mode, bool, 0644); - MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); - -@@ -85,7 +85,7 @@ static bool truesize_mode = false; - module_param(truesize_mode, bool, 0644); - MODULE_PARM_DESC(truesize_mode, "Report larger truesize value"); - --static int packetsize = 0; -+static int packetsize = 2560; - module_param(packetsize, int, 0644); - MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); - - -From f0bec5372fdc974676a90c5828dc73ac8df18bb9 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 9 Mar 2016 13:28:24 +0000 -Subject: [PATCH 007/208] serial: Take care starting a hung-up tty's port - -tty_port_hangup sets a port's tty field to NULL (holding the port lock), -but uart_tx_stopped, called from __uart_start (with the port lock), -uses the tty field without checking for NULL. - -Change uart_tx_stopped to treat a NULL tty field as another stopped -indication. - -Signed-off-by: Phil Elwell ---- - include/linux/serial_core.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h -index 2f44e20136545162d15ee9a39c2eae38352580d1..6b0518ce13ad210b888b73dd6c02a5558798b38f 100644 ---- a/include/linux/serial_core.h -+++ b/include/linux/serial_core.h -@@ -412,7 +412,7 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); - static inline int uart_tx_stopped(struct uart_port *port) - { - struct tty_struct *tty = port->state->port.tty; -- if (tty->stopped || port->hw_stopped) -+ if (!tty || tty->stopped || port->hw_stopped) - return 1; - return 0; - } - -From 7a4314314fefb3d4288ba4a245f08abd83334c9d Mon Sep 17 00:00:00 2001 +From 481e18fc6c63b56179f93596c5393e5638fab295 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 12:43:36 +0000 -Subject: [PATCH 008/208] Protect __release_resource against resources without +Subject: [PATCH 004/111] Protect __release_resource against resources without parents Without this patch, removing a device tree overlay can crash here. @@ -408,10 +224,10 @@ index 9b5f04404152c296af3a96132f27cfc80ffa9af9..f8a9af6e6b915812be2ba2c1c2b40106 for (;;) { tmp = *p; -From b67c49a019770ea73d250e046faabd79df373fa9 Mon Sep 17 00:00:00 2001 +From 1b2be2671cee28c79160329883028029c2b0c857 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Dec 2014 16:07:15 -0800 -Subject: [PATCH 009/208] mm: Remove the PFN busy warning +Subject: [PATCH 005/111] mm: Remove the PFN busy warning See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is expected sometimes when using CMA. However, that commit still spams @@ -423,10 +239,10 @@ Signed-off-by: Eric Anholt 1 file changed, 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 7401e996009afa14cb6c3834b62ce8780e6e958a..7f48cd9228cd1c7c4fb9451729f7826d2ca3d6eb 100644 +index 6de9440e3ae2d995b28577dc4a000fc23f4182c0..bea7204c14a5e24e018218b3d3eaef7c1ac5fd4f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -7318,8 +7318,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, +@@ -7289,8 +7289,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, /* Make sure the range is really isolated. */ if (test_pages_isolated(outer_start, end, false)) { @@ -436,51 +252,10 @@ index 7401e996009afa14cb6c3834b62ce8780e6e958a..7f48cd9228cd1c7c4fb9451729f7826d goto done; } -From 606896cbfc13f4e43c502c30e9d07acaa77f80c3 Mon Sep 17 00:00:00 2001 -From: Robert Tiemann -Date: Mon, 20 Jul 2015 11:01:25 +0200 -Subject: [PATCH 010/208] BCM2835_DT: Fix I2S register map - ---- - Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- - Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -index baf9b34d20bfb5b5493e0a69841362530c900a77..11c052acf65e74f032ae77bfd2749db860762b2d 100644 ---- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -+++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -@@ -74,8 +74,8 @@ Example: - - bcm2835_i2s: i2s@7e203000 { - compatible = "brcm,bcm2835-i2s"; -- reg = < 0x7e203000 0x20>, -- < 0x7e101098 0x02>; -+ reg = < 0x7e203000 0x24>, -+ < 0x7e101098 0x08>; - - dmas = <&dma 2>, - <&dma 3>; -diff --git a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt -index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554427118a2 100644 ---- a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt -+++ b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt -@@ -16,8 +16,8 @@ Example: - - bcm2835_i2s: i2s@7e203000 { - compatible = "brcm,bcm2835-i2s"; -- reg = <0x7e203000 0x20>, -- <0x7e101098 0x02>; -+ reg = <0x7e203000 0x24>, -+ <0x7e101098 0x08>; - - dmas = <&dma 2>, - <&dma 3>; - -From 59ffae373ced5b44abaa948286cb2e1b69fe9cf3 Mon Sep 17 00:00:00 2001 +From 5d1f384994be88b18a6dfb189687c32204c5b827 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 4 Dec 2015 17:41:50 +0000 -Subject: [PATCH 011/208] irq-bcm2836: Prevent spurious interrupts, and trap +Subject: [PATCH 006/111] irq-bcm2836: Prevent spurious interrupts, and trap them early The old arch-specific IRQ macros included a dsb to ensure the @@ -507,10 +282,10 @@ index d96b2c947e74e3edab3917551c64fbd1ced0f34c..93e3f7660c4230c9f1dd3b195958cb49 #endif } else if (stat) { -From 64abf4863e38961cfdc3c2b1680e3b7751cd7dee Mon Sep 17 00:00:00 2001 +From 62120b5cc0bcdf3a2d243ae8d32dc6033eb0a616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 12 Jun 2015 19:01:05 +0200 -Subject: [PATCH 012/208] irqchip: bcm2835: Add FIQ support +Subject: [PATCH 007/111] irqchip: bcm2835: Add FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -528,10 +303,10 @@ Acked-by: Stephen Warren 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 34f0fca0b8472720cd107946e8f5a99d4cfa542a..5f6ab16792a93b2dd2e3f9e647f8ac4062d4fa6d 100644 +index a0e66d8200c5cf8f2ea592abf870a32800213fa2..4ff30d5278a7ce093c9629d4c25d37e3bbbda752 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig -@@ -153,6 +153,7 @@ config ARCH_BCM2835 +@@ -152,6 +152,7 @@ config ARCH_BCM2835 select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7 select CLKSRC_OF select BCM2835_TIMER @@ -639,10 +414,10 @@ index 44d7c38dde479d771f3552e914bf8c1c1f5019f7..42ff5e6a8e0d532f5b60a1e7af7cc4d9 } -From 86a5fcd1b51a616ae46047631553503ad2b096c8 Mon Sep 17 00:00:00 2001 +From 2a1701f404bdbf47c8864d62551626d60d022d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 23 Oct 2015 16:26:55 +0200 -Subject: [PATCH 013/208] irqchip: irq-bcm2835: Add 2836 FIQ support +Subject: [PATCH 008/111] irqchip: irq-bcm2835: Add 2836 FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -741,10 +516,10 @@ index 42ff5e6a8e0d532f5b60a1e7af7cc4d941bd5008..eccf6ed025299cb480884f5bcbe77abf for (b = 0; b < NR_BANKS; b++) { for (i = 0; i < bank_irqs[b]; i++) { -From dec587cf518f9b967b7ce5faa5fa2944a6e6c0cd Mon Sep 17 00:00:00 2001 +From 573c26f692a511b5850d94ce07a7ae8d27aeb87b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 10:26:09 +0100 -Subject: [PATCH 014/208] spidev: Add "spidev" compatible string to silence +Subject: [PATCH 009/111] spidev: Add "spidev" compatible string to silence warning See: https://github.com/raspberrypi/linux/issues/1054 @@ -765,17 +540,17 @@ index 2e05046f866bd01bf87edcdeff0d5b76d4d0aea7..d780491b8013a4e97fa843958964454e }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -From c142337d3ab8a9fbceb6d611e32b3a621d577cb5 Mon Sep 17 00:00:00 2001 +From 49007260438ac25b031a5f426336b4a3c2f79164 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 30 Jun 2015 14:12:42 +0100 -Subject: [PATCH 015/208] serial: 8250: Don't crash when nr_uarts is 0 +Subject: [PATCH 010/111] serial: 8250: Don't crash when nr_uarts is 0 --- drivers/tty/serial/8250/8250_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c -index dcf43f66404f12d2bd290a30adfe494dd056162e..0fba189c676ded310b92a09c4e7e8f768d753895 100644 +index 240a361b674fe72ce657067e5303156b7add6a6f..14f6cdfd744209482056d206dc476d9427cba9ba 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -509,6 +509,8 @@ static void __init serial8250_isa_init_ports(void) @@ -788,10 +563,10 @@ index dcf43f66404f12d2bd290a30adfe494dd056162e..0fba189c676ded310b92a09c4e7e8f76 for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; -From 967fd972c6351fed9598396aa68071d3699023d2 Mon Sep 17 00:00:00 2001 +From 8dd1e9defb5253e50db90363693595d980b9f89e Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 016/208] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 011/111] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -813,10 +588,10 @@ index fa77165fab2c1348163979da507df17e7168c49b..d11e2e4ea189466e686d762cb6c6fef9 .can_sleep = false, }; -From c5d54043c247044a8ecdd7451b7a2fbc5650f114 Mon Sep 17 00:00:00 2001 +From 1ea344b8d6146e5ddb11d0b8cef5d9c5f1fc76c9 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 017/208] pinctrl-bcm2835: Fix interrupt handling for GPIOs +Subject: [PATCH 012/111] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -962,10 +737,10 @@ index d11e2e4ea189466e686d762cb6c6fef9111ecf8e..107ad7d58de8f8a7f55e09c9cdcf7d66 }, }; -From f12b7d81a1109e470185f3392099dc89552e1545 Mon Sep 17 00:00:00 2001 +From 1a70bcb135aba08029a4a527d94611eea7b14fbe Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 018/208] pinctrl-bcm2835: Only request the interrupts listed +Subject: [PATCH 013/111] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -992,10 +767,10 @@ index 107ad7d58de8f8a7f55e09c9cdcf7d66fa7ab66b..644bdecbcfcb79d3b84a33769265fca5 pc->irq_data[i].irqgroup = i; -From 28c879d001bb5ab3fd6dbacdf0df76518b41dce1 Mon Sep 17 00:00:00 2001 +From 7198cc8ee9b058e09ea92f672ed183abd622aa9b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 May 2016 12:32:47 +0100 -Subject: [PATCH 019/208] pinctrl-bcm2835: Return pins to inputs when freed +Subject: [PATCH 014/111] pinctrl-bcm2835: Return pins to inputs when freed When dynamically unloading overlays, it is important that freed pins are restored to being inputs to prevent functions from being enabled in @@ -1036,10 +811,10 @@ index 644bdecbcfcb79d3b84a33769265fca5d3d0c9e5..81a66cba2ab0f7e3ae179de7edd10122 .get_function_name = bcm2835_pmx_get_function_name, .get_function_groups = bcm2835_pmx_get_function_groups, -From 34a7ed67a97641610545f768e1fac116fb09f129 Mon Sep 17 00:00:00 2001 +From 2f3c0a3e933104ad100b1c28e957c72d7d083de6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 -Subject: [PATCH 020/208] spi-bcm2835: Support pin groups other than 7-11 +Subject: [PATCH 015/111] spi-bcm2835: Support pin groups other than 7-11 The spi-bcm2835 driver automatically uses GPIO chip-selects due to some unreliability of the native ones. In doing so it chooses the @@ -1120,10 +895,10 @@ index f35cc10772f6670397ea923ad30158270dd68578..5dfe20ffc2866fa6789825016c585175 /* and set up the "mode" and level */ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -From 164780791396998dfdc84cdd11ac0a57acb88c8d Mon Sep 17 00:00:00 2001 +From 2f97bbd1ddafb4209b88897b2f6cc1267bc1f247 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 1 Jul 2016 22:09:24 +0100 -Subject: [PATCH 021/208] spi-bcm2835: Disable forced software CS +Subject: [PATCH 016/111] spi-bcm2835: Disable forced software CS Select software CS in bcm2708_common.dtsi, and disable the automatic conversion in the driver to allow hardware CS to be re-enabled with an @@ -1157,10 +932,101 @@ index 5dfe20ffc2866fa6789825016c585175a29705b6..8493474d286f7a1ac6454a22c61c8c2c return 0; } -From 8f9c99a7bb5105f249f22244ee7c11c9491909d2 Mon Sep 17 00:00:00 2001 +From 4a119ff4ae732e4220dba5262ad4d800d1af7dde Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 8 Nov 2016 21:35:38 +0000 +Subject: [PATCH 017/111] spi-bcm2835: Remove unused code + +--- + drivers/spi/spi-bcm2835.c | 61 ----------------------------------------------- + 1 file changed, 61 deletions(-) + +diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c +index 8493474d286f7a1ac6454a22c61c8c2cef9121bf..33d75ad38a7f77d085321ace9101900a83bebcac 100644 +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -679,17 +679,8 @@ static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) + bcm2835_wr(bs, BCM2835_SPI_CS, cs); + } + +-static int chip_match_name(struct gpio_chip *chip, void *data) +-{ +- return !strcmp(chip->label, data); +-} +- + static int bcm2835_spi_setup(struct spi_device *spi) + { +- int err; +- struct gpio_chip *chip; +- struct device_node *pins; +- u32 pingroup_index; + /* + * sanity checking the native-chipselects + */ +@@ -707,58 +698,6 @@ static int bcm2835_spi_setup(struct spi_device *spi) + return -EINVAL; + } + +-#if 0 +- /* now translate native cs to GPIO */ +- /* first look for chip select pins in the devices pin groups */ +- for (pingroup_index = 0; +- (pins = of_parse_phandle(spi->master->dev.of_node, +- "pinctrl-0", +- pingroup_index)) != 0; +- pingroup_index++) { +- u32 pin; +- u32 pin_index; +- for (pin_index = 0; +- of_property_read_u32_index(pins, +- "brcm,pins", +- pin_index, +- &pin) == 0; +- pin_index++) { +- if (((spi->chip_select == 0) && +- ((pin == 8) || (pin == 36) || (pin == 46))) || +- ((spi->chip_select == 1) && +- ((pin == 7) || (pin == 35)))) { +- spi->cs_gpio = pin; +- break; +- } +- } +- of_node_put(pins); +- } +- /* if that fails, assume GPIOs 7-11 are used */ +- if (!gpio_is_valid(spi->cs_gpio) ) { +- /* get the gpio chip for the base */ +- chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); +- if (!chip) +- return 0; +- +- /* and calculate the real CS */ +- spi->cs_gpio = chip->base + 8 - spi->chip_select; +- } +- +- /* and set up the "mode" and level */ +- dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", +- spi->chip_select, spi->cs_gpio); +- +- /* set up GPIO as output and pull to the correct level */ +- err = gpio_direction_output(spi->cs_gpio, +- (spi->mode & SPI_CS_HIGH) ? 0 : 1); +- if (err) { +- dev_err(&spi->dev, +- "could not set CS%i gpio %i as output: %i", +- spi->chip_select, spi->cs_gpio, err); +- return err; +- } +-#endif +- + return 0; + } + + +From de1125b3a2d6229dc168c35ad82f6ef8a202c459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 3 Jun 2015 12:26:13 +0200 -Subject: [PATCH 022/208] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 018/111] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1213,10 +1079,10 @@ index 0c1edfc98696da0e0bb7f4a18cdfbcdd27a9795d..8f152266ba9b470df2eaaed9ebcf158e static const char * const bcm2835_compat[] = { -From 0dcea622ab242228d2ac5492166f6cc83499596b Mon Sep 17 00:00:00 2001 +From 64d21030cae9fb9718296e2657c9881cd74e18fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 3 Oct 2015 22:22:55 +0200 -Subject: [PATCH 023/208] dmaengine: bcm2835: Load driver early and support +Subject: [PATCH 019/111] dmaengine: bcm2835: Load driver early and support legacy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -1234,7 +1100,7 @@ Signed-off-by: Noralf Trønnes 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 739f797b40d9843b7d75261e955439866c7aaa83..f7b3ac574968b35aeb1fb6b3ba8d4f1bf61599f9 100644 +index 141aefbe37ec93d1f4f38d1be5e2cf8d93266725..9c931d36c6a499a02f4f215f8cd77d3f2254a3b9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -108,7 +108,7 @@ config COH901318 @@ -1319,10 +1185,10 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); -From c4d9aa87d6bf7e07bcaa8559af6ad15ab0d2ed95 Mon Sep 17 00:00:00 2001 +From 9300f525a49182536af3efc15a3a274962504e47 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jan 2016 17:25:12 +0000 -Subject: [PATCH 024/208] firmware: Updated mailbox header +Subject: [PATCH 020/111] firmware: Updated mailbox header --- include/soc/bcm2835/raspberrypi-firmware.h | 11 +++++++++++ @@ -1385,59 +1251,10 @@ index 3fb357193f09914fe21f8555a4b8613f74f22bc3..227a107214a02deadcca3db202da265e RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, -From 13a01898fca61986f9fbb5fb2e55477248b2037f Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 26 Apr 2016 11:44:59 -0700 -Subject: [PATCH 025/208] clk: bcm2835: Mark the VPU clock as critical - -The VPU clock is also the clock for our AXI bus, so we really can't -disable it. This might have happened during boot if, for example, -uart1 (aux_uart clock) probed and was then disabled before the other -consumers of the VPU clock had probed. - -v2: Rewrite to use a .flags in bcm2835_clock_data, since other clocks - will need this too. - -Signed-off-by: Eric Anholt ---- - drivers/clk/bcm/clk-bcm2835.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 0fc71cbaa4404bddc1ca603a28a43425a7e5a341..085e5217d3b9f73c312dc7fd510ef55cddb4a27c 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -443,6 +443,8 @@ struct bcm2835_clock_data { - /* Number of fractional bits in the divider */ - u32 frac_bits; - -+ u32 flags; -+ - bool is_vpu_clock; - bool is_mash_clock; - }; -@@ -1253,7 +1255,7 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, - init.parent_names = parents; - init.num_parents = data->num_mux_parents; - init.name = data->name; -- init.flags = CLK_IGNORE_UNUSED; -+ init.flags = data->flags | CLK_IGNORE_UNUSED; - - if (data->is_vpu_clock) { - init.ops = &bcm2835_vpu_clock_clk_ops; -@@ -1672,6 +1674,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .div_reg = CM_VPUDIV, - .int_bits = 12, - .frac_bits = 8, -+ .flags = CLK_IS_CRITICAL, - .is_vpu_clock = true), - - /* clocks with per parent mux */ - -From a136d9a40644e151876c7aa36e971aad4b0dc799 Mon Sep 17 00:00:00 2001 +From 9de63dc57340cb047969dedcfdfd8b51c3779083 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 May 2016 17:28:18 -0700 -Subject: [PATCH 026/208] clk: bcm2835: Mark GPIO clocks enabled at boot as +Subject: [PATCH 021/111] clk: bcm2835: Mark GPIO clocks enabled at boot as critical. These divide off of PLLD_PER and are used for the ethernet and wifi @@ -1451,14 +1268,14 @@ v2: Skip marking as critical if they aren't on at boot. Signed-off-by: Eric Anholt --- - drivers/clk/bcm/clk-bcm2835.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) + drivers/clk/bcm/clk-bcm2835.c | 9 +++++++++ + 1 file changed, 9 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 085e5217d3b9f73c312dc7fd510ef55cddb4a27c..e527649ee5e32d20cebd762f4badbfca06657a84 100644 +index 8c7763fd9efc52b30f02d9ebcd4fdb10d2876465..a73f0873b7b8f78bc4a70f01e17eb287eec1d9e3 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1257,6 +1257,15 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, +@@ -1260,6 +1260,15 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, init.name = data->name; init.flags = data->flags | CLK_IGNORE_UNUSED; @@ -1474,128 +1291,11 @@ index 085e5217d3b9f73c312dc7fd510ef55cddb4a27c..e527649ee5e32d20cebd762f4badbfca if (data->is_vpu_clock) { init.ops = &bcm2835_vpu_clock_clk_ops; } else { -@@ -1731,13 +1740,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .div_reg = CM_GP1DIV, - .int_bits = 12, - .frac_bits = 12, -+ .flags = CLK_IS_CRITICAL, - .is_mash_clock = true), - [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK( - .name = "gp2", - .ctl_reg = CM_GP2CTL, - .div_reg = CM_GP2DIV, - .int_bits = 12, -- .frac_bits = 12), -+ .frac_bits = 12, -+ .flags = CLK_IS_CRITICAL), - - /* HDMI state machine */ - [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK( -From 8c1cbf01341c3f78a107af5dc9b3190932a6c7b2 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 1 Jun 2016 12:05:35 -0700 -Subject: [PATCH 027/208] clk: bcm2835: Mark the CM SDRAM clock's parent as - critical - -While the SDRAM is being driven by its dedicated PLL most of the time, -there is a little loop running in the firmware that periodically turns -on the CM SDRAM clock (using its pre-initialized parent) and switches -SDRAM to using the CM clock to do PVT recalibration. - -This avoids system hangs if we choose SDRAM's parent for some other -clock, then disable that clock. - -Signed-off-by: Eric Anholt ---- - drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index e527649ee5e32d20cebd762f4badbfca06657a84..fbf616021704178a9d007219a0ea2a9f1704f0a6 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -36,6 +36,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -1827,6 +1828,25 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_PERIICTL), - }; - -+/* -+ * Permanently take a reference on the parent of the SDRAM clock. -+ * -+ * While the SDRAM is being driven by its dedicated PLL most of the -+ * time, there is a little loop running in the firmware that -+ * periodically switches the SDRAM to using our CM clock to do PVT -+ * recalibration, with the assumption that the previously configured -+ * SDRAM parent is still enabled and running. -+ */ -+static int bcm2835_mark_sdc_parent_critical(struct clk *sdc) -+{ -+ struct clk *parent = clk_get_parent(sdc); -+ -+ if (IS_ERR(parent)) -+ return PTR_ERR(parent); -+ -+ return clk_prepare_enable(parent); -+} -+ - static int bcm2835_clk_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -1836,6 +1856,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - const struct bcm2835_clk_desc *desc; - const size_t asize = ARRAY_SIZE(clk_desc_array); - size_t i; -+ int ret; - - cprman = devm_kzalloc(dev, - sizeof(*cprman) + asize * sizeof(*clks), -@@ -1866,6 +1887,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - clks[i] = desc->clk_register(cprman, desc->data); - } - -+ ret = bcm2835_mark_sdc_parent_critical(clks[BCM2835_CLOCK_SDRAM]); -+ if (ret) -+ return ret; -+ - return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, - &cprman->onecell); - } - -From 8fabd4b2587c362117ced1337e5ade069e9a2955 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 3 Oct 2016 13:58:40 +0100 -Subject: [PATCH 028/208] Enable upstream BCM2835 auxiliar mini UART support - ---- - drivers/tty/serial/8250/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig -index 7c6f7afca5ddeed7b25fa6272246fc539bf31b04..748098f900d3474b5d535b24da76ad06e9690335 100644 ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -291,7 +291,7 @@ config SERIAL_8250_ACORN - - config SERIAL_8250_BCM2835AUX - tristate "BCM2835 auxiliar mini UART support" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835 || COMPILE_TEST - depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ - help - Support for the BCM2835 auxiliar mini UART. - -From 9f7ddb4f7342c03f3d921e48515f8c89a08efe27 Mon Sep 17 00:00:00 2001 +From 448de2edc0f549ce252e0a0dc8089100c80184c3 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 15 Jun 2016 16:48:41 +0100 -Subject: [PATCH 029/208] rtc: Add SPI alias for pcf2123 driver +Subject: [PATCH 022/111] rtc: Add SPI alias for pcf2123 driver Without this alias, Device Tree won't cause the driver to be loaded. @@ -1615,2442 +1315,419 @@ index 8895f77726e8da5444afcd602dceff8f25a9b3fd..1833b8853ceb0e6147cceb93a00e558c MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:rtc-pcf2123"); -From ca0a284e86c89410ce033ce4abaa0581465665eb Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 19 Apr 2016 15:55:02 -0700 -Subject: [PATCH 030/208] ARM: bcm2708: Enable building power domain driver. +From 2e36db73f1fa2356e1561d09305294e4cf91e3bd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 7 Oct 2016 16:50:59 +0200 +Subject: [PATCH 023/111] watchdog: bcm2835: Support setting reboot partition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit -Signed-off-by: Eric Anholt +The Raspberry Pi firmware looks at the RSTS register to know which +partition to boot from. The reboot syscall command +LINUX_REBOOT_CMD_RESTART2 supports passing in a string argument. + +Add support for passing in a partition number 0..63 to boot from. +Partition 63 is a special partiton indicating halt. +If the partition doesn't exist, the firmware falls back to partition 0. + +Signed-off-by: Noralf Trønnes --- - drivers/soc/bcm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + drivers/watchdog/bcm2835_wdt.c | 61 +++++++++++++++++++++++++----------------- + 1 file changed, 36 insertions(+), 25 deletions(-) + +diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c +index 4dddd8298a227d64862f2e92954a465f2e44b3f6..1f545e024422f59280932713e6a1b05150b39b22 100644 +--- a/drivers/watchdog/bcm2835_wdt.c ++++ b/drivers/watchdog/bcm2835_wdt.c +@@ -35,13 +35,7 @@ + #define PM_RSTC_WRCFG_SET 0x00000030 + #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 + #define PM_RSTC_RESET 0x00000102 +- +-/* +- * The Raspberry Pi firmware uses the RSTS register to know which partiton +- * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. +- * Partiton 63 is a special partition used by the firmware to indicate halt. +- */ +-#define PM_RSTS_RASPBERRYPI_HALT 0x555 ++#define PM_RSTS_PARTITION_CLR 0xfffffaaa + + #define SECS_TO_WDOG_TICKS(x) ((x) << 16) + #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) +@@ -111,15 +105,28 @@ static struct watchdog_device bcm2835_wdt_wdd = { + .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), + }; + +-static int +-bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) ++/* ++ * The Raspberry Pi firmware uses the RSTS register to know which partiton ++ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. ++ * Partiton 63 is a special partition used by the firmware to indicate halt. ++ */ ++ ++static void bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition) + { +- struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, +- restart_handler); +- u32 val; ++ u32 val, rsts; ++ ++ rsts = (partition & BIT(0)) | ((partition & BIT(1)) << 1) | ++ ((partition & BIT(2)) << 2) | ((partition & BIT(3)) << 3) | ++ ((partition & BIT(4)) << 4) | ((partition & BIT(5)) << 5); ++ ++ val = readl_relaxed(wdt->base + PM_RSTS); ++ val &= PM_RSTS_PARTITION_CLR; ++ val |= PM_PASSWORD | rsts; ++ writel_relaxed(val, wdt->base + PM_RSTS); + + /* use a timeout of 10 ticks (~150us) */ + writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG); ++ + val = readl_relaxed(wdt->base + PM_RSTC); + val &= PM_RSTC_WRCFG_CLR; + val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; +@@ -127,6 +134,20 @@ bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) + + /* No sleeping, possibly atomic. */ + mdelay(1); ++} ++ ++static int bcm2835_restart_notifier_call(struct notifier_block *this, ++ unsigned long mode, void *cmd) ++{ ++ struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, ++ restart_handler); ++ unsigned long long val; ++ u8 partition = 0; ++ ++ if (cmd && !kstrtoull(cmd, 0, &val) && val <= 63) ++ partition = val; ++ ++ bcm2835_restart(wdt, partition); + + return 0; + } +@@ -142,19 +163,9 @@ static void bcm2835_power_off(void) + of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt"); + struct platform_device *pdev = of_find_device_by_node(np); + struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); +- u32 val; +- +- /* +- * We set the watchdog hard reset bit here to distinguish this reset +- * from the normal (full) reset. bootcode.bin will not reboot after a +- * hard reset. +- */ +- val = readl_relaxed(wdt->base + PM_RSTS); +- val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT; +- writel_relaxed(val, wdt->base + PM_RSTS); + +- /* Continue with normal reset mechanism */ +- bcm2835_restart(&wdt->restart_handler, REBOOT_HARD, NULL); ++ /* Partition 63 tells the firmware that this is a halt */ ++ bcm2835_restart(wdt, 63); + } + + static int bcm2835_wdt_probe(struct platform_device *pdev) +@@ -188,7 +199,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) + return err; + } + +- wdt->restart_handler.notifier_call = bcm2835_restart; ++ wdt->restart_handler.notifier_call = bcm2835_restart_notifier_call; + wdt->restart_handler.priority = 128; + register_restart_handler(&wdt->restart_handler); + if (pm_power_off == NULL) + +From 126d1c9c30b84709d3df1c9ee6951925ef86e561 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 5 Apr 2016 19:40:12 +0100 +Subject: [PATCH 024/111] reboot: Use power off rather than busy spinning when + halt is requested + +--- + arch/arm/kernel/reboot.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c +index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e00fb59a19 100644 +--- a/arch/arm/kernel/reboot.c ++++ b/arch/arm/kernel/reboot.c +@@ -102,9 +102,7 @@ void machine_shutdown(void) + */ + void machine_halt(void) + { +- local_irq_disable(); +- smp_send_stop(); +- while (1); ++ machine_power_off(); + } + + /* + +From 369132293cbf3404c2f12567f36c72745442d1a7 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 9 Nov 2016 13:02:52 +0000 +Subject: [PATCH 025/111] bcm: Make RASPBERRYPI_POWER depend on PM + +--- + drivers/soc/bcm/Kconfig | 1 + + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig -index a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226..7d11a44f36d2e6f8697773cd49a72e53bca3a5a0 100644 +index a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226..e037a6dd79d1881a09e3ca911578270917888846 100644 --- a/drivers/soc/bcm/Kconfig +++ b/drivers/soc/bcm/Kconfig -@@ -2,7 +2,7 @@ menu "Broadcom SoC drivers" - - config RASPBERRYPI_POWER +@@ -4,6 +4,7 @@ config RASPBERRYPI_POWER bool "Raspberry Pi power domain driver" -- depends on ARCH_BCM2835 || (COMPILE_TEST && OF) -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || (COMPILE_TEST && OF) + depends on ARCH_BCM2835 || (COMPILE_TEST && OF) depends on RASPBERRYPI_FIRMWARE=y ++ depends on PM select PM_GENERIC_DOMAINS if PM help + This enables support for the RPi power domains which can be enabled -From d2a8c66431d4a830d84aa61337e7cf75f7263e7a Mon Sep 17 00:00:00 2001 +From 4f1f33c99707022e920996b81d2394e8a67d72cc Mon Sep 17 00:00:00 2001 +From: Martin Sperl +Date: Fri, 2 Sep 2016 16:45:27 +0100 +Subject: [PATCH 026/111] Register the clocks early during the boot process, so + that special/critical clocks can get enabled early on in the boot process + avoiding the risk of disabling a clock, pll_divider or pll when a claiming + driver fails to install propperly - maybe it needs to defer. + +Signed-off-by: Martin Sperl +--- + drivers/clk/bcm/clk-bcm2835.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index a73f0873b7b8f78bc4a70f01e17eb287eec1d9e3..56fd47891e50dddcf83e687f1d53aeb46d85a7b2 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1901,8 +1901,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + if (ret) + return ret; + +- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, ++ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + &cprman->onecell); ++ if (ret) ++ return ret; ++ ++ /* note that we have registered all the clocks */ ++ dev_dbg(dev, "registered %d clocks\n", asize); ++ ++ return 0; + } + + static const struct of_device_id bcm2835_clk_of_match[] = { +@@ -1919,7 +1926,11 @@ static struct platform_driver bcm2835_clk_driver = { + .probe = bcm2835_clk_probe, + }; + +-builtin_platform_driver(bcm2835_clk_driver); ++static int __init __bcm2835_clk_driver_init(void) ++{ ++ return platform_driver_register(&bcm2835_clk_driver); ++} ++core_initcall(__bcm2835_clk_driver_init); + + MODULE_AUTHOR("Eric Anholt "); + MODULE_DESCRIPTION("BCM2835 clock driver"); + +From 007bca50057b289594959c0b3a40f697042de092 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 6 Dec 2016 17:05:39 +0000 +Subject: [PATCH 027/111] bcm2835-rng: Avoid initialising if already enabled + +Avoids the 0x40000 cycles of warmup again if firmware has already used it +--- + drivers/char/hw_random/bcm2835-rng.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c +index 574211a495491d9d6021dcaefe4274a63ed02055..e66c0fca8c6090e32f72796c0877a1cf1d499fb6 100644 +--- a/drivers/char/hw_random/bcm2835-rng.c ++++ b/drivers/char/hw_random/bcm2835-rng.c +@@ -102,9 +102,10 @@ static int bcm2835_rng_probe(struct platform_device *pdev) + rng_setup(rng_base); + + /* set warm-up count & enable */ +- __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); +- __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); +- ++ if (!(__raw_readl(rng_base + RNG_CTRL) & RNG_RBGEN)) { ++ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); ++ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); ++ } + /* register driver */ + err = hwrng_register(&bcm2835_rng_ops); + if (err) { + +From ea730ebfa6c5a592f2085c3ed4b5ba73b65344e0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 24 Aug 2016 16:28:44 +0100 +Subject: [PATCH 028/111] kbuild: Ignore dtco targets when filtering symbols + +--- + scripts/Kbuild.include | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include +index 179219845dfcdfbeb586d12c5ec1296095d9fbf4..e0743e44f84188667a0c322e8c3d36f18385dcd3 100644 +--- a/scripts/Kbuild.include ++++ b/scripts/Kbuild.include +@@ -284,7 +284,7 @@ ksym_dep_filter = \ + $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ + as_*_S|cpp_s_S) \ + $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ +- boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ ++ boot*|build*|*cpp_lds_S|dtc*|host*|vdso*) : ;; \ + *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ + esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' + + +From bacce62ef301d1ac7882ecdfeaa3289a597c65cc Mon Sep 17 00:00:00 2001 +From: Robert Tiemann +Date: Mon, 20 Jul 2015 11:01:25 +0200 +Subject: [PATCH 029/111] BCM2835_DT: Fix I2S register map + +--- + Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- + Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +index baf9b34d20bfb5b5493e0a69841362530c900a77..11c052acf65e74f032ae77bfd2749db860762b2d 100644 +--- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt ++++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +@@ -74,8 +74,8 @@ Example: + + bcm2835_i2s: i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; +- reg = < 0x7e203000 0x20>, +- < 0x7e101098 0x02>; ++ reg = < 0x7e203000 0x24>, ++ < 0x7e101098 0x08>; + + dmas = <&dma 2>, + <&dma 3>; +diff --git a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt +index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554427118a2 100644 +--- a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt ++++ b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt +@@ -16,8 +16,8 @@ Example: + + bcm2835_i2s: i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; +- reg = <0x7e203000 0x20>, +- <0x7e101098 0x02>; ++ reg = <0x7e203000 0x24>, ++ <0x7e101098 0x08>; + + dmas = <&dma 2>, + <&dma 3>; + +From 83e431a4170b965b12737d9fd9828b224f0b5dc3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 031/208] Main bcm2708/bcm2709 linux port +Subject: [PATCH 030/111] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 49 +++ - arch/arm/Kconfig.debug | 8 + - arch/arm/Makefile | 2 + - arch/arm/kernel/head.S | 8 + - arch/arm/kernel/process.c | 10 + - arch/arm/mach-bcm2708/Kconfig | 23 ++ - arch/arm/mach-bcm2708/Makefile | 5 + - arch/arm/mach-bcm2708/Makefile.boot | 3 + - arch/arm/mach-bcm2708/bcm2708.c | 231 ++++++++++++ - arch/arm/mach-bcm2708/include/mach/debug-macro.S | 22 ++ - arch/arm/mach-bcm2708/include/mach/io.h | 27 ++ - arch/arm/mach-bcm2708/include/mach/memory.h | 57 +++ - arch/arm/mach-bcm2708/include/mach/platform.h | 112 ++++++ - arch/arm/mach-bcm2708/include/mach/system.h | 37 ++ - arch/arm/mach-bcm2708/include/mach/uncompress.h | 84 +++++ - arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 ++ - arch/arm/mach-bcm2709/Kconfig | 16 + - arch/arm/mach-bcm2709/Makefile | 5 + - arch/arm/mach-bcm2709/Makefile.boot | 3 + - arch/arm/mach-bcm2709/bcm2709.c | 380 ++++++++++++++++++++ - arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 ++ - arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 +++++++ - arch/arm/mach-bcm2709/include/mach/io.h | 27 ++ - arch/arm/mach-bcm2709/include/mach/memory.h | 57 +++ - arch/arm/mach-bcm2709/include/mach/platform.h | 188 ++++++++++ - arch/arm/mach-bcm2709/include/mach/system.h | 37 ++ - arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 +++++ - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 ++ - arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 ++ - arch/arm/mach-bcm2709/vc_mem.c | 431 +++++++++++++++++++++++ - arch/arm/mm/proc-v6.S | 15 +- - arch/arm/tools/mach-types | 2 + - drivers/clocksource/Makefile | 2 +- - drivers/irqchip/Makefile | 3 + - drivers/irqchip/irq-bcm2835.c | 7 +- - include/linux/mmc/host.h | 1 + - 36 files changed, 2151 insertions(+), 5 deletions(-) - create mode 100644 arch/arm/mach-bcm2708/Kconfig - create mode 100644 arch/arm/mach-bcm2708/Makefile - create mode 100644 arch/arm/mach-bcm2708/Makefile.boot - create mode 100644 arch/arm/mach-bcm2708/bcm2708.c - create mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2708/include/mach/io.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/system.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2709/Kconfig - create mode 100644 arch/arm/mach-bcm2709/Makefile - create mode 100644 arch/arm/mach-bcm2709/Makefile.boot - create mode 100644 arch/arm/mach-bcm2709/bcm2709.c - create mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/io.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/system.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2709/vc_mem.c -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index a9c4e48bb7ec997bec394066914d26f337a2fec4..018ee76322d9e013598887c50ebea9628ecb9ee3 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -326,6 +326,52 @@ choice - default ARM_SINGLE_ARMV7M if !MMU - default ARCH_MULTIPLATFORM if MMU +bcm2709: Drop platform smp and timer init code + +irq-bcm2836 handles this through these functions: +bcm2835_init_local_timer_frequency() +bcm2836_arm_irqchip_smp_init() + +Signed-off-by: Noralf Trønnes + +bcm270x: Use watchdog for reboot/poweroff + +The watchdog driver already has support for reboot/poweroff. +Make use of this and remove the code from the platform files. + +Signed-off-by: Noralf Trønnes +--- + arch/arm/mach-bcm/Kconfig | 1 + + arch/arm/mach-bcm/board_bcm2835.c | 17 +++++++++++++++++ + arch/arm/mm/proc-v6.S | 15 ++++++++++++--- + drivers/irqchip/irq-bcm2835.c | 7 ++++++- + drivers/mailbox/bcm2835-mailbox.c | 18 ++++++++++++++++-- + 5 files changed, 52 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig +index 4ff30d5278a7ce093c9629d4c25d37e3bbbda752..333dc3c2e5ffbb2c5ab8fcfb6115b6162643cf20 100644 +--- a/arch/arm/mach-bcm/Kconfig ++++ b/arch/arm/mach-bcm/Kconfig +@@ -155,6 +155,7 @@ config ARCH_BCM2835 + select FIQ + select PINCTRL + select PINCTRL_BCM2835 ++ select MFD_SYSCON if ARCH_MULTI_V7 + help + This enables support for the Broadcom BCM2835 and BCM2836 SoCs. + This SoC is used in the Raspberry Pi and Roku 2 devices. +diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c +index 8f152266ba9b470df2eaaed9ebcf158ed2079834..133338f0a21237fda9b7660d2c57a33b991f08ae 100644 +--- a/arch/arm/mach-bcm/board_bcm2835.c ++++ b/arch/arm/mach-bcm/board_bcm2835.c +@@ -16,17 +16,21 @@ + #include + #include + #include ++#include + #include -+config ARCH_BCM2708 -+ bool "Broadcom BCM2708 family" -+ select CPU_V6 -+ select ARM_AMBA -+ select CLKSRC_MMIO -+ select CLKSRC_OF if OF -+ select HAVE_SCHED_CLOCK -+ select NEED_MACH_GPIO_H -+ select NEED_MACH_MEMORY_H -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select ARM_ERRATA_411920 -+ select MACH_BCM2708 -+ select MULTI_IRQ_HANDLER -+ select SPARSE_IRQ -+ select VC4 -+ select FIQ -+ help -+ This enables support for Broadcom BCM2708 boards. + #include + #include + ++#include + -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ select CPU_V7 -+ select HAVE_SMP -+ select ARM_AMBA -+ select MIGHT_HAVE_CACHE_L2X0 -+ select HAVE_SCHED_CLOCK -+ select NEED_MACH_MEMORY_H -+ select NEED_MACH_IO_H -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select MACH_BCM2709 -+ select MULTI_IRQ_HANDLER -+ select SPARSE_IRQ -+ select MFD_SYSCON -+ select VC4 -+ select FIQ -+ select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - config ARCH_MULTIPLATFORM - bool "Allow multiple platforms to be selected" - depends on MMU -@@ -711,6 +757,9 @@ config ARCH_VIRT - # Kconfigs may be included either alphabetically (according to the - # plat- suffix) or along side the corresponding mach-* source. - # -+source "arch/arm/mach-bcm2708/Kconfig" -+source "arch/arm/mach-bcm2709/Kconfig" -+ - source "arch/arm/mach-mvebu/Kconfig" + static void __init bcm2835_init(void) + { + struct device_node *np = of_find_node_by_path("/system"); + u32 val; + u64 val64; - source "arch/arm/mach-alpine/Kconfig" -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index a9693b6987a6e41c69702f1003d0d8bd2279530e..f47f4e70395635fafeacd680c4392cc51660ea8e 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -1312,6 +1312,14 @@ choice - options; the platform specific options are deprecated - and will be soon removed. ++ vc_cma_early_init(); + bcm2835_init_clocks(); -+ config DEBUG_BCM2708_UART0 -+ bool "Broadcom BCM270X UART0 (PL011)" -+ depends on ARCH_BCM2708 || ARCH_BCM2709 -+ help -+ Say Y here if you want the debug print routines to direct -+ their output to UART 0. The port must have been initialised -+ by the boot-loader before use. -+ - endchoice - - config DEBUG_AT91_UART -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 61f6ccc19cfa94364e777cc68d10ce5a24093c0f..d1e45094ab4338f95dab09e81d358cd723f5eb3d 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -152,6 +152,8 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 - - # Machine directory name. This list is sorted alphanumerically - # by CONFIG_* macro name. -+machine-$(CONFIG_ARCH_BCM2708) += bcm2708 -+machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_ALPINE) += alpine - machine-$(CONFIG_ARCH_ARTPEC) += artpec - machine-$(CONFIG_ARCH_AT91) += at91 -diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S -index 04286fd9e09ce7a27259c4d375a05a965e3be0ea..ed826280e744828ebb1c5ae6b7a62d70f28c1429 100644 ---- a/arch/arm/kernel/head.S -+++ b/arch/arm/kernel/head.S -@@ -700,6 +700,14 @@ ARM_BE8(rev16 ip, ip) - ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 1b - ret lr -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop - #endif - ENDPROC(__fixup_a_pv_table) - -diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 612eb530f33fcd19bc4539facb26fc30a2583979..0a0332cb13a7475ee0c4d75a97685b7de6475c95 100644 ---- a/arch/arm/kernel/process.c -+++ b/arch/arm/kernel/process.c -@@ -91,6 +91,16 @@ void arch_cpu_idle_exit(void) - ledtrig_cpu(CPU_LED_IDLE_END); + if (!of_property_read_u32(np, "linux,revision", &val)) +@@ -35,6 +39,17 @@ static void __init bcm2835_init(void) + system_serial_low = val64; } -+char bcm2708_reboot_mode = 'h'; -+ -+int __init reboot_setup(char *str) ++static void __init bcm2835_init_early(void) +{ -+ bcm2708_reboot_mode = str[0]; -+ return 1; ++ /* dwc_otg needs this for bounce buffers on non-aligned transfers */ ++ init_dma_coherent_pool_size(SZ_1M); +} + -+__setup("reboot=", reboot_setup); -+ - void __show_regs(struct pt_regs *regs) - { - unsigned long flags; -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..6eabe844767f7fa9bdc09a897bab83e5149fc0dd ---- /dev/null -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -0,0 +1,23 @@ -+menu "Broadcom BCM2708 Implementations" -+ depends on ARCH_BCM2708 -+ -+config MACH_BCM2708 -+ bool "Broadcom BCM2708 Development Platform" -+ select NEED_MACH_MEMORY_H -+ select NEED_MACH_IO_H -+ select CPU_V6 -+ select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 -+ help -+ Include support for the Broadcom(R) BCM2708 platform. -+ -+config BCM2708_NOL2CACHE -+ bool "Videocore L2 cache disable" -+ depends on MACH_BCM2708 -+ default n -+ help -+ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -+ -+endmenu -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..3da1a1b4ea1fb04ae0b535b2915ea9f386f5701c ---- /dev/null -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -0,0 +1,5 @@ -+# -+# Makefile for the linux kernel. -+# -+ -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o -diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot -new file mode 100644 -index 0000000000000000000000000000000000000000..67039c3e0c48fa6b94f1147b3316f74afcecba9e ---- /dev/null -+++ b/arch/arm/mach-bcm2708/Makefile.boot -@@ -0,0 +1,3 @@ -+ zreladdr-y := 0x00008000 -+params_phys-y := 0x00000100 -+initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -new file mode 100644 -index 0000000000000000000000000000000000000000..280628ba8907d2a4323fc86dfc6db7fc684aeabc ---- /dev/null -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -0,0 +1,231 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/bcm2708.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -+ * give us IO access only to 64Mbytes of physical memory (26 bits). We could -+ * represent this window by setting our dmamasks to 26 bits but, in fact -+ * we're not going to use addresses outside this range (they're not in real -+ * memory) so we don't bother. -+ * -+ * In the future we might include code to use this IOMMU to remap other -+ * physical addresses onto VideoCore memory then the use of 32-bits would be -+ * more legitimate. -+ */ -+ -+/* command line parameters */ -+static unsigned boardrev, serial; -+static unsigned reboot_part = 0; -+ -+static struct map_desc bcm2708_io_desc[] __initdata = { -+ { -+ .virtual = IO_ADDRESS(ARMCTRL_BASE), -+ .pfn = __phys_to_pfn(ARMCTRL_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART0_BASE), -+ .pfn = __phys_to_pfn(UART0_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART1_BASE), -+ .pfn = __phys_to_pfn(UART1_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(DMA_BASE), -+ .pfn = __phys_to_pfn(DMA_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(MCORE_BASE), -+ .pfn = __phys_to_pfn(MCORE_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(ST_BASE), -+ .pfn = __phys_to_pfn(ST_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(USB_BASE), -+ .pfn = __phys_to_pfn(USB_BASE), -+ .length = SZ_128K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(PM_BASE), -+ .pfn = __phys_to_pfn(PM_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(GPIO_BASE), -+ .pfn = __phys_to_pfn(GPIO_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE} -+}; -+ -+void __init bcm2708_map_io(void) -+{ -+ iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); -+} -+ -+int calc_rsts(int partition) -+{ -+ return PM_PASSWORD | -+ ((partition & (1 << 0)) << 0) | -+ ((partition & (1 << 1)) << 1) | -+ ((partition & (1 << 2)) << 2) | -+ ((partition & (1 << 3)) << 3) | -+ ((partition & (1 << 4)) << 4) | -+ ((partition & (1 << 5)) << 5); -+} -+ -+static void bcm2708_restart(enum reboot_mode mode, const char *cmd) -+{ -+ extern char bcm2708_reboot_mode; -+ uint32_t pm_rstc, pm_wdog; -+ uint32_t timeout = 10; -+ uint32_t pm_rsts = 0; -+ -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < 1.3 booting with reboot=q -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -+ } -+ else if(bcm2708_reboot_mode == 'p') -+ { -+ // NOOBS < 1.3 halting -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -+ } -+ else -+ { -+ pm_rsts = calc_rsts(reboot_part); -+ } -+ -+ writel(pm_rsts, __io_address(PM_RSTS)); -+ -+ /* Setup watchdog for reset */ -+ pm_rstc = readl(__io_address(PM_RSTC)); -+ -+ pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -+ pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -+ -+ writel(pm_wdog, __io_address(PM_WDOG)); -+ writel(pm_rstc, __io_address(PM_RSTC)); -+} -+ -+/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ -+static void bcm2708_power_off(void) -+{ -+ extern char bcm2708_reboot_mode; -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < v1.3 -+ bcm2708_restart('p', ""); -+ } -+ else -+ { -+ /* partition 63 is special code for HALT the bootloader knows not to boot*/ -+ reboot_part = 63; -+ /* continue with normal reset mechanism */ -+ bcm2708_restart(0, ""); -+ } -+} -+ -+static void __init bcm2708_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2708: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ -+void __init bcm2708_init(void) -+{ -+ int ret; -+ -+ vc_cma_early_init(); -+ -+ pm_power_off = bcm2708_power_off; -+ -+ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -+ NULL); -+ if (ret) { -+ pr_err("of_platform_populate failed: %d\n", ret); -+ BUG(); -+ } -+ -+ bcm2708_init_uart1(); -+ -+ system_rev = boardrev; -+ system_serial_low = serial; -+} -+ -+void __init bcm2708_init_early(void) -+{ -+ /* -+ * Some devices allocate their coherent buffers from atomic -+ * context. Increase size of atomic coherent pool to make sure such -+ * the allocations won't fail. -+ */ -+ init_dma_coherent_pool_size(SZ_4M); -+} -+ -+static void __init board_reserve(void) ++static void __init bcm2835_board_reserve(void) +{ + vc_cma_reserve(); +} + -+static const char * const bcm2708_compat[] = { -+ "brcm,bcm2708", -+ NULL -+}; -+ -+MACHINE_START(BCM2708, "BCM2708") -+ /* Maintainer: Broadcom Europe Ltd. */ -+ .map_io = bcm2708_map_io, -+ .init_machine = bcm2708_init, -+ .init_early = bcm2708_init_early, -+ .reserve = board_reserve, -+ .restart = bcm2708_restart, -+ .dt_compat = bcm2708_compat, -+MACHINE_END -+ -+module_param(boardrev, uint, 0644); -+module_param(serial, uint, 0644); -+module_param(reboot_part, uint, 0644); -diff --git a/arch/arm/mach-bcm2708/include/mach/debug-macro.S b/arch/arm/mach-bcm2708/include/mach/debug-macro.S -new file mode 100644 -index 0000000000000000000000000000000000000000..b24304a6755e965b8a28eb048b7f4e2d868820f9 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/debug-macro.S -@@ -0,0 +1,22 @@ -+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -+ * -+ * Debugging macro include header -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 1994-1999 Russell King -+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+*/ -+ -+#include -+ -+ .macro addruart, rp, rv, tmp -+ ldr \rp, =UART0_BASE -+ ldr \rv, =IO_ADDRESS(UART0_BASE) -+ .endm -+ -+#include -diff --git a/arch/arm/mach-bcm2708/include/mach/io.h b/arch/arm/mach-bcm2708/include/mach/io.h -new file mode 100644 -index 0000000000000000000000000000000000000000..e6eb84d71006db417dbd0afc4d08d3b19b09a619 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/io.h -@@ -0,0 +1,27 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/io.h -+ * -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARM_ARCH_IO_H -+#define __ASM_ARM_ARCH_IO_H -+ -+#define IO_SPACE_LIMIT 0xffffffff -+ -+#define __io(a) __typesafe_io(a) -+ -+#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/memory.h b/arch/arm/mach-bcm2708/include/mach/memory.h -new file mode 100644 -index 0000000000000000000000000000000000000000..7548a52dcf84affa4d1b0667e5e2f89f591891b8 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/memory.h -@@ -0,0 +1,57 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/memory.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_MEMORY_H -+#define __ASM_ARCH_MEMORY_H -+ -+/* Memory overview: -+ -+ [ARMcore] <--virtual addr--> -+ [ARMmmu] <--physical addr--> -+ [GERTmap] <--bus add--> -+ [VCperiph] -+ -+*/ -+ -+/* -+ * Physical DRAM offset. -+ */ -+#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) -+#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -+ -+#ifdef CONFIG_BCM2708_NOL2CACHE -+ #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ -+#else -+ #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ -+#endif -+ -+/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -+ * will provide the offset into this area as well as setting the bits that -+ * stop the L1 and L2 cache from being used -+ * -+ * WARNING: this only works because the ARM is given memory at a fixed location -+ * (ARMMEM_OFFSET) -+ */ -+#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) -+#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) -+#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) -+#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+ -+#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4fb43cf391e50e702d0a0588ceff397c79c501d7 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -0,0 +1,112 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/platform.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _BCM2708_PLATFORM_H -+#define _BCM2708_PLATFORM_H -+ -+ -+/* macros to get at IO space when running virtually */ -+#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -+ -+#define __io_address(n) IOMEM(IO_ADDRESS(n)) -+ -+ -+/* -+ * SDRAM -+ */ -+#define BCM2708_SDRAM_BASE 0x00000000 -+ -+/* -+ * Logic expansion modules -+ * -+ */ -+ -+ -+/* ------------------------------------------------------------------------ -+ * BCM2708 ARMCTRL Registers -+ * ------------------------------------------------------------------------ -+ */ -+ -+#define HW_REGISTER_RW(addr) (addr) -+#define HW_REGISTER_RO(addr) (addr) -+ -+/* -+ * Definitions and addresses for the ARM CONTROL logic -+ * This file is manually generated. -+ */ -+ -+#define BCM2708_PERI_BASE 0x20000000 -+#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) -+#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ -+#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ -+#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ -+#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ -+#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ -+#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ -+#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ -+#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ -+#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ -+#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ -+#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ -+#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ -+#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ -+#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ -+#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ -+#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ -+#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ -+#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ -+#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -+ -+#define ARMCTRL_BASE (ARM_BASE + 0x000) -+#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ -+#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ -+#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+ -+/* -+ * Watchdog -+ */ -+#define PM_RSTC (PM_BASE+0x1c) -+#define PM_RSTS (PM_BASE+0x20) -+#define PM_WDOG (PM_BASE+0x24) -+ -+#define PM_WDOG_RESET 0000000000 -+#define PM_PASSWORD 0x5a000000 -+#define PM_WDOG_TIME_SET 0x000fffff -+#define PM_RSTC_WRCFG_CLR 0xffffffcf -+#define PM_RSTC_WRCFG_SET 0x00000030 -+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -+#define PM_RSTC_RESET 0x00000102 -+ -+#define PM_RSTS_HADPOR_SET 0x00001000 -+#define PM_RSTS_HADSRH_SET 0x00000400 -+#define PM_RSTS_HADSRF_SET 0x00000200 -+#define PM_RSTS_HADSRQ_SET 0x00000100 -+#define PM_RSTS_HADWRH_SET 0x00000040 -+#define PM_RSTS_HADWRF_SET 0x00000020 -+#define PM_RSTS_HADWRQ_SET 0x00000010 -+#define PM_RSTS_HADDRH_SET 0x00000004 -+#define PM_RSTS_HADDRF_SET 0x00000002 -+#define PM_RSTS_HADDRQ_SET 0x00000001 -+ -+#define UART0_CLOCK 3000000 -+ -+#endif -+ -+/* END */ -diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h -new file mode 100644 -index 0000000000000000000000000000000000000000..c9a9c9a881102c5354971d15203a746906761a70 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/system.h -@@ -0,0 +1,37 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/system.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * Copyright (C) 2000 Deep Blue Solutions Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_SYSTEM_H -+#define __ASM_ARCH_SYSTEM_H -+ -+#include -+#include -+ -+static inline void arch_idle(void) -+{ -+ /* -+ * This should do all the clock switching -+ * and wait for interrupt tricks -+ */ -+ cpu_do_idle(); -+} -+ -+#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/uncompress.h b/arch/arm/mach-bcm2708/include/mach/uncompress.h -new file mode 100644 -index 0000000000000000000000000000000000000000..de7504bfc20ba24be8707861b8389783860adb77 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/uncompress.h -@@ -0,0 +1,84 @@ -+/* -+ * arch/arm/mach-bcn2708/include/mach/uncompress.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+ -+#define UART_BAUD 115200 -+ -+#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) -+#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) -+#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) -+#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) -+#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) -+#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -+ -+/* -+ * This does not append a newline -+ */ -+static inline void putc(int c) -+{ -+ while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -+ barrier(); -+ -+ __raw_writel(c, BCM2708_UART_DR); -+} -+ -+static inline void flush(void) -+{ -+ int fr; -+ -+ do { -+ fr = __raw_readl(BCM2708_UART_FR); -+ barrier(); -+ } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); -+} -+ -+static inline void arch_decomp_setup(void) -+{ -+ int temp, div, rem, frac; -+ -+ temp = 16 * UART_BAUD; -+ div = UART0_CLOCK / temp; -+ rem = UART0_CLOCK % temp; -+ temp = (8 * rem) / UART_BAUD; -+ frac = (temp >> 1) + (temp & 1); -+ -+ /* Make sure the UART is disabled before we start */ -+ __raw_writel(0, BCM2708_UART_CR); -+ -+ /* Set the baud rate */ -+ __raw_writel(div, BCM2708_UART_IBRD); -+ __raw_writel(frac, BCM2708_UART_FBRD); -+ -+ /* Set the UART to 8n1, FIFO enabled */ -+ __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -+ -+ /* Enable the UART */ -+ __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -+ BCM2708_UART_CR); -+} -+ -+/* -+ * nothing to do -+ */ -+#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h -new file mode 100644 -index 0000000000000000000000000000000000000000..502c6178101be60b10c9eb31afec938b5534c33f ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/vmalloc.h -@@ -0,0 +1,20 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vmalloc.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#define VMALLOC_END (0xe8000000) -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..643b4b984512a5f2ae33cee9beffa70a53e005ff ---- /dev/null -+++ b/arch/arm/mach-bcm2709/Kconfig -@@ -0,0 +1,16 @@ -+menu "Broadcom BCM2709 Implementations" -+ depends on ARCH_BCM2709 -+ -+config MACH_BCM2709 -+ bool "Broadcom BCM2709 Development Platform" -+ help -+ Include support for the Broadcom(R) BCM2709 platform. -+ -+config BCM2708_NOL2CACHE -+ bool "Videocore L2 cache disable" -+ depends on MACH_BCM2709 -+ default y -+ help -+ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -+ -+endmenu -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..26cd67d3dc343dbd250fa97855a82c28bbd95af0 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -0,0 +1,5 @@ -+# -+# Makefile for the linux kernel. -+# -+ -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o -diff --git a/arch/arm/mach-bcm2709/Makefile.boot b/arch/arm/mach-bcm2709/Makefile.boot -new file mode 100644 -index 0000000000000000000000000000000000000000..67039c3e0c48fa6b94f1147b3316f74afcecba9e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/Makefile.boot -@@ -0,0 +1,3 @@ -+ zreladdr-y := 0x00008000 -+params_phys-y := 0x00000100 -+initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -new file mode 100644 -index 0000000000000000000000000000000000000000..90773a30b87abbfda1615326c6faf59b9db6d68e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -0,0 +1,380 @@ -+/* -+ * linux/arch/arm/mach-bcm2709/bcm2709.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+ -+/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -+ * give us IO access only to 64Mbytes of physical memory (26 bits). We could -+ * represent this window by setting our dmamasks to 26 bits but, in fact -+ * we're not going to use addresses outside this range (they're not in real -+ * memory) so we don't bother. -+ * -+ * In the future we might include code to use this IOMMU to remap other -+ * physical addresses onto VideoCore memory then the use of 32-bits would be -+ * more legitimate. -+ */ -+ -+/* command line parameters */ -+static unsigned boardrev, serial; -+static unsigned reboot_part = 0; -+ -+static struct map_desc bcm2709_io_desc[] __initdata = { -+ { -+ .virtual = IO_ADDRESS(ARMCTRL_BASE), -+ .pfn = __phys_to_pfn(ARMCTRL_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART0_BASE), -+ .pfn = __phys_to_pfn(UART0_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(UART1_BASE), -+ .pfn = __phys_to_pfn(UART1_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(DMA_BASE), -+ .pfn = __phys_to_pfn(DMA_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(MCORE_BASE), -+ .pfn = __phys_to_pfn(MCORE_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(ST_BASE), -+ .pfn = __phys_to_pfn(ST_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(USB_BASE), -+ .pfn = __phys_to_pfn(USB_BASE), -+ .length = SZ_128K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(PM_BASE), -+ .pfn = __phys_to_pfn(PM_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(GPIO_BASE), -+ .pfn = __phys_to_pfn(GPIO_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+ { -+ .virtual = IO_ADDRESS(ARM_LOCAL_BASE), -+ .pfn = __phys_to_pfn(ARM_LOCAL_BASE), -+ .length = SZ_4K, -+ .type = MT_DEVICE}, -+}; -+ -+void __init bcm2709_map_io(void) -+{ -+ iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); -+} -+ -+int calc_rsts(int partition) -+{ -+ return PM_PASSWORD | -+ ((partition & (1 << 0)) << 0) | -+ ((partition & (1 << 1)) << 1) | -+ ((partition & (1 << 2)) << 2) | -+ ((partition & (1 << 3)) << 3) | -+ ((partition & (1 << 4)) << 4) | -+ ((partition & (1 << 5)) << 5); -+} -+ -+static void bcm2709_restart(enum reboot_mode mode, const char *cmd) -+{ -+ extern char bcm2708_reboot_mode; -+ uint32_t pm_rstc, pm_wdog; -+ uint32_t timeout = 10; -+ uint32_t pm_rsts = 0; -+ -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < 1.3 booting with reboot=q -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -+ } -+ else if(bcm2708_reboot_mode == 'p') -+ { -+ // NOOBS < 1.3 halting -+ pm_rsts = readl(__io_address(PM_RSTS)); -+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -+ } -+ else -+ { -+ pm_rsts = calc_rsts(reboot_part); -+ } -+ -+ writel(pm_rsts, __io_address(PM_RSTS)); -+ -+ /* Setup watchdog for reset */ -+ pm_rstc = readl(__io_address(PM_RSTC)); -+ -+ pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -+ pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -+ -+ writel(pm_wdog, __io_address(PM_WDOG)); -+ writel(pm_rstc, __io_address(PM_RSTC)); -+} -+ -+/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ -+static void bcm2709_power_off(void) -+{ -+ extern char bcm2708_reboot_mode; -+ if(bcm2708_reboot_mode == 'q') -+ { -+ // NOOBS < v1.3 -+ bcm2709_restart('p', ""); -+ } -+ else -+ { -+ /* partition 63 is special code for HALT the bootloader knows not to boot*/ -+ reboot_part = 63; -+ /* continue with normal reset mechanism */ -+ bcm2709_restart(0, ""); -+ } -+} -+ -+static void __init bcm2709_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2709: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ -+void __init bcm2709_init(void) -+{ -+ int ret; -+ -+ vc_cma_early_init(); -+ -+ pm_power_off = bcm2709_power_off; -+ -+ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -+ NULL); -+ if (ret) { -+ pr_err("of_platform_populate failed: %d\n", ret); -+ BUG(); -+ } -+ -+ bcm2709_init_uart1(); -+ -+ system_rev = boardrev; -+ system_serial_low = serial; -+} -+ -+static void __init bcm2709_timer_init(void) -+{ -+ // timer control -+ writel(0, __io_address(ARM_LOCAL_CONTROL)); -+ // timer pre_scaler -+ writel(0x80000000, __io_address(ARM_LOCAL_PRESCALER)); // 19.2MHz -+ //writel(0x06AAAAAB, __io_address(ARM_LOCAL_PRESCALER)); // 1MHz -+ -+ of_clk_init(NULL); -+ clocksource_probe(); -+} -+ -+ -+void __init bcm2709_init_early(void) -+{ -+ /* -+ * Some devices allocate their coherent buffers from atomic -+ * context. Increase size of atomic coherent pool to make sure such -+ * the allocations won't fail. -+ */ -+ init_dma_coherent_pool_size(SZ_4M); -+} -+ -+static void __init board_reserve(void) -+{ -+ vc_cma_reserve(); -+} -+ -+ -+#ifdef CONFIG_SMP -+#include -+ -+#include -+#include -+int dc4=0; -+//void dc4_log(unsigned x) { if (dc4) writel((x), __io_address(ST_BASE+10 + raw_smp_processor_id()*4)); } -+void dc4_log_dead(unsigned x) { if (dc4) writel((readl(__io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)) & 0xffff) | ((x)<<16), __io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)); } -+ -+static void bcm2835_send_doorbell(const struct cpumask *mask, unsigned int irq) -+{ -+ int cpu; -+ /* -+ * Ensure that stores to Normal memory are visible to the -+ * other CPUs before issuing the IPI. -+ */ -+ dsb(); -+ -+ /* Convert our logical CPU mask into a physical one. */ -+ for_each_cpu(cpu, mask) -+ { -+ /* submit softirq */ -+ writel(1<%x)\n", __FUNCTION__, (unsigned)virt_to_phys((void *)secondary_startup), (unsigned)__io_address(ST_BASE + 0x10)); -+ printk("[%s] ncores=%d\n", __FUNCTION__, ncores); -+ -+ for (i = 0; i < ncores; i++) { -+ set_cpu_possible(i, true); -+ /* enable IRQ (not FIQ) */ -+ writel(0x1, __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 0x4 * i)); -+ //writel(0xf, __io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 0x4 * i)); -+ } -+ set_smp_cross_call(bcm2835_send_doorbell); -+} -+ -+/* -+ * for arch/arm/kernel/smp.c:smp_prepare_cpus(unsigned int max_cpus) -+ */ -+void __init bcm2709_smp_prepare_cpus(unsigned int max_cpus) -+{ -+ //void __iomem *scu_base; -+ -+ printk("[%s] enter\n", __FUNCTION__); -+ //scu_base = scu_base_addr(); -+ //scu_enable(scu_base); -+} -+ -+/* -+ * for linux/arch/arm/kernel/smp.c:secondary_start_kernel(void) -+ */ -+void __init bcm2709_secondary_init(unsigned int cpu) -+{ -+ printk("[%s] enter cpu:%d\n", __FUNCTION__, cpu); -+ //gic_secondary_init(0); -+} -+ -+/* -+ * for linux/arch/arm/kernel/smp.c:__cpu_up(..) -+ */ -+int __init bcm2709_boot_secondary(unsigned int cpu, struct task_struct *idle) -+{ -+ void secondary_startup(void); -+ void *mbox_set = __io_address(ARM_LOCAL_MAILBOX3_SET0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -+ void *mbox_clr = __io_address(ARM_LOCAL_MAILBOX3_CLR0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -+ unsigned secondary_boot = (unsigned)virt_to_phys((void *)secondary_startup); -+ int timeout=20; -+ unsigned t = -1; -+ //printk("[%s] enter cpu:%d (%x->%p) %x\n", __FUNCTION__, cpu, secondary_boot, wake, readl(wake)); -+ -+ dsb(); -+ BUG_ON(readl(mbox_clr) != 0); -+ writel(secondary_boot, mbox_set); -+ -+ while (--timeout > 0) { -+ t = readl(mbox_clr); -+ if (t == 0) break; -+ cpu_relax(); -+ } -+ if (timeout==0) -+ printk("[%s] cpu:%d failed to start (%x)\n", __FUNCTION__, cpu, t); -+ else -+ printk("[%s] cpu:%d started (%x) %d\n", __FUNCTION__, cpu, t, timeout); -+ -+ return 0; -+} -+ -+ -+struct smp_operations bcm2709_smp_ops __initdata = { -+ .smp_init_cpus = bcm2709_smp_init_cpus, -+ .smp_prepare_cpus = bcm2709_smp_prepare_cpus, -+ .smp_secondary_init = bcm2709_secondary_init, -+ .smp_boot_secondary = bcm2709_boot_secondary, -+}; -+#endif -+ -+static const char * const bcm2709_compat[] = { -+ "brcm,bcm2709", -+ "brcm,bcm2708", /* Could use bcm2708 in a pinch */ -+ NULL -+}; -+ -+MACHINE_START(BCM2709, "BCM2709") -+ /* Maintainer: Broadcom Europe Ltd. */ -+#ifdef CONFIG_SMP -+ .smp = smp_ops(bcm2709_smp_ops), -+#endif -+ .map_io = bcm2709_map_io, -+ .init_time = bcm2709_timer_init, -+ .init_machine = bcm2709_init, -+ .init_early = bcm2709_init_early, -+ .reserve = board_reserve, -+ .restart = bcm2709_restart, -+ .dt_compat = bcm2709_compat, -+MACHINE_END -+ -+MACHINE_START(BCM2708, "BCM2709") -+ /* Maintainer: Broadcom Europe Ltd. */ -+#ifdef CONFIG_SMP -+ .smp = smp_ops(bcm2709_smp_ops), -+#endif -+ .map_io = bcm2709_map_io, -+ .init_time = bcm2709_timer_init, -+ .init_machine = bcm2709_init, -+ .init_early = bcm2709_init_early, -+ .reserve = board_reserve, -+ .restart = bcm2709_restart, -+ .dt_compat = bcm2709_compat, -+MACHINE_END -+ -+module_param(boardrev, uint, 0644); -+module_param(serial, uint, 0644); -+module_param(reboot_part, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/include/mach/debug-macro.S b/arch/arm/mach-bcm2709/include/mach/debug-macro.S -new file mode 100644 -index 0000000000000000000000000000000000000000..b24304a6755e965b8a28eb048b7f4e2d868820f9 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/debug-macro.S -@@ -0,0 +1,22 @@ -+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -+ * -+ * Debugging macro include header -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 1994-1999 Russell King -+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+*/ -+ -+#include -+ -+ .macro addruart, rp, rv, tmp -+ ldr \rp, =UART0_BASE -+ ldr \rv, =IO_ADDRESS(UART0_BASE) -+ .endm -+ -+#include -diff --git a/arch/arm/mach-bcm2709/include/mach/entry-macro.S b/arch/arm/mach-bcm2709/include/mach/entry-macro.S -new file mode 100644 -index 0000000000000000000000000000000000000000..d08591b63c1a1710c40350d343d3eddc97ae74c1 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/entry-macro.S -@@ -0,0 +1,123 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/entry-macro.S -+ * -+ * Low-level IRQ helper macros for BCM2708 platforms -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#include -+#include -+ -+ .macro disable_fiq -+ .endm -+ -+ .macro get_irqnr_preamble, base, tmp -+ ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) -+ .endm -+ -+ .macro arch_ret_to_user, tmp1, tmp2 -+ .endm -+ -+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -+ /* get core number */ -+ mrc p15, 0, \tmp, c0, c0, 5 -+ ubfx \tmp, \tmp, #0, #2 -+ -+ /* get core's local interrupt controller */ -+ ldr \irqstat, = __io_address(ARM_LOCAL_IRQ_PENDING0) @ local interrupt source -+ add \irqstat, \irqstat, \tmp, lsl #2 -+ ldr \tmp, [\irqstat] -+ /* ignore gpu interrupt */ -+ bic \tmp, #0x100 -+ /* ignore mailbox interrupts */ -+ bics \tmp, #0xf0 -+ beq 1005f -+ -+ @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -+ @ N.B. CLZ is an ARM5 instruction. -+ mov \irqnr, #(ARM_IRQ_LOCAL_BASE + 31) -+ sub \irqstat, \tmp, #1 -+ eor \irqstat, \irqstat, \tmp -+ clz \tmp, \irqstat -+ sub \irqnr, \tmp -+ b 1020f -+1005: -+ /* get core number */ -+ mrc p15, 0, \tmp, c0, c0, 5 -+ ubfx \tmp, \tmp, #0, #2 -+ -+ cmp \tmp, #1 -+ beq 1020f -+ cmp \tmp, #2 -+ beq 1020f -+ cmp \tmp, #3 -+ beq 1020f -+ -+ /* get masked status */ -+ ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] -+ mov \irqnr, #(ARM_IRQ0_BASE + 31) -+ and \tmp, \irqstat, #0x300 @ save bits 8 and 9 -+ /* clear bits 8 and 9, and test */ -+ bics \irqstat, \irqstat, #0x300 -+ bne 1010f -+ -+ tst \tmp, #0x100 -+ ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] -+ movne \irqnr, #(ARM_IRQ1_BASE + 31) -+ @ Mask out the interrupts also present in PEND0 - see SW-5809 -+ bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) -+ bicne \irqstat, #((1<<18) | (1<<19)) -+ bne 1010f -+ -+ tst \tmp, #0x200 -+ ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] -+ movne \irqnr, #(ARM_IRQ2_BASE + 31) -+ @ Mask out the interrupts also present in PEND0 - see SW-5809 -+ bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) -+ bicne \irqstat, #((1<<30)) -+ beq 1020f -+ -+1010: -+ @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -+ @ N.B. CLZ is an ARM5 instruction. -+ sub \tmp, \irqstat, #1 -+ eor \irqstat, \irqstat, \tmp -+ clz \tmp, \irqstat -+ sub \irqnr, \tmp -+ -+1020: @ EQ will be set if no irqs pending -+ -+ .endm -+ -+ .macro test_for_ipi, irqnr, irqstat, base, tmp -+ /* get core number */ -+ mrc p15, 0, \tmp, c0, c0, 5 -+ ubfx \tmp, \tmp, #0, #2 -+ /* get core's mailbox interrupt control */ -+ ldr \irqstat, = __io_address(ARM_LOCAL_MAILBOX0_CLR0) @ mbox_clr -+ add \irqstat, \irqstat, \tmp, lsl #4 -+ ldr \tmp, [\irqstat] -+ cmp \tmp, #0 -+ beq 1030f -+ clz \tmp, \tmp -+ rsb \irqnr, \tmp, #31 -+ mov \tmp, #1 -+ lsl \tmp, \irqnr -+ str \tmp, [\irqstat] @ clear interrupt source -+ dsb -+1030: @ EQ will be set if no irqs pending -+ .endm -diff --git a/arch/arm/mach-bcm2709/include/mach/io.h b/arch/arm/mach-bcm2709/include/mach/io.h -new file mode 100644 -index 0000000000000000000000000000000000000000..e6eb84d71006db417dbd0afc4d08d3b19b09a619 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/io.h -@@ -0,0 +1,27 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/io.h -+ * -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARM_ARCH_IO_H -+#define __ASM_ARM_ARCH_IO_H -+ -+#define IO_SPACE_LIMIT 0xffffffff -+ -+#define __io(a) __typesafe_io(a) -+ -+#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/memory.h b/arch/arm/mach-bcm2709/include/mach/memory.h -new file mode 100644 -index 0000000000000000000000000000000000000000..7548a52dcf84affa4d1b0667e5e2f89f591891b8 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/memory.h -@@ -0,0 +1,57 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/memory.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_MEMORY_H -+#define __ASM_ARCH_MEMORY_H -+ -+/* Memory overview: -+ -+ [ARMcore] <--virtual addr--> -+ [ARMmmu] <--physical addr--> -+ [GERTmap] <--bus add--> -+ [VCperiph] -+ -+*/ -+ -+/* -+ * Physical DRAM offset. -+ */ -+#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) -+#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -+ -+#ifdef CONFIG_BCM2708_NOL2CACHE -+ #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ -+#else -+ #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ -+#endif -+ -+/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -+ * will provide the offset into this area as well as setting the bits that -+ * stop the L1 and L2 cache from being used -+ * -+ * WARNING: this only works because the ARM is given memory at a fixed location -+ * (ARMMEM_OFFSET) -+ */ -+#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) -+#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) -+#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) -+#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -+ -+#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -new file mode 100644 -index 0000000000000000000000000000000000000000..311b9f26fab7dd770bdcd684c7691442b0872d55 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -0,0 +1,188 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/platform.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _BCM2708_PLATFORM_H -+#define _BCM2708_PLATFORM_H -+ -+ -+/* macros to get at IO space when running virtually */ -+#define IO_ADDRESS(x) (((x) & 0x00ffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -+ -+#define __io_address(n) IOMEM(IO_ADDRESS(n)) -+ -+ -+/* -+ * SDRAM -+ */ -+#define BCM2708_SDRAM_BASE 0x00000000 -+ -+/* -+ * Logic expansion modules -+ * -+ */ -+ -+ -+/* ------------------------------------------------------------------------ -+ * BCM2708 ARMCTRL Registers -+ * ------------------------------------------------------------------------ -+ */ -+ -+#define HW_REGISTER_RW(addr) (addr) -+#define HW_REGISTER_RO(addr) (addr) -+ -+/* -+ * Definitions and addresses for the ARM CONTROL logic -+ * This file is manually generated. -+ */ -+ -+#define BCM2708_PERI_BASE 0x3F000000 -+#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) -+#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ -+#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ -+#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ -+#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ -+#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ -+#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ -+#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ -+#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ -+#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ -+#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ -+#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ -+#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ -+#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ -+#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ -+#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ -+#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ -+#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ -+#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ -+#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -+ -+#define ARMCTRL_BASE (ARM_BASE + 0x000) -+#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ -+#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ -+#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+ -+/* -+ * Watchdog -+ */ -+#define PM_RSTC (PM_BASE+0x1c) -+#define PM_RSTS (PM_BASE+0x20) -+#define PM_WDOG (PM_BASE+0x24) -+ -+#define PM_WDOG_RESET 0000000000 -+#define PM_PASSWORD 0x5a000000 -+#define PM_WDOG_TIME_SET 0x000fffff -+#define PM_RSTC_WRCFG_CLR 0xffffffcf -+#define PM_RSTC_WRCFG_SET 0x00000030 -+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -+#define PM_RSTC_RESET 0x00000102 -+ -+#define PM_RSTS_HADPOR_SET 0x00001000 -+#define PM_RSTS_HADSRH_SET 0x00000400 -+#define PM_RSTS_HADSRF_SET 0x00000200 -+#define PM_RSTS_HADSRQ_SET 0x00000100 -+#define PM_RSTS_HADWRH_SET 0x00000040 -+#define PM_RSTS_HADWRF_SET 0x00000020 -+#define PM_RSTS_HADWRQ_SET 0x00000010 -+#define PM_RSTS_HADDRH_SET 0x00000004 -+#define PM_RSTS_HADDRF_SET 0x00000002 -+#define PM_RSTS_HADDRQ_SET 0x00000001 -+ -+#define UART0_CLOCK 3000000 -+ -+#define ARM_LOCAL_BASE 0x40000000 -+#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) -+ -+#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) -+#define ARM_LOCAL_PRESCALER HW_REGISTER_RW(ARM_LOCAL_BASE+0x008) -+#define ARM_LOCAL_GPU_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x00C) -+#define ARM_LOCAL_PM_ROUTING_SET HW_REGISTER_RW(ARM_LOCAL_BASE+0x010) -+#define ARM_LOCAL_PM_ROUTING_CLR HW_REGISTER_RW(ARM_LOCAL_BASE+0x014) -+#define ARM_LOCAL_TIMER_LS HW_REGISTER_RW(ARM_LOCAL_BASE+0x01C) -+#define ARM_LOCAL_TIMER_MS HW_REGISTER_RW(ARM_LOCAL_BASE+0x020) -+#define ARM_LOCAL_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x024) -+#define ARM_LOCAL_AXI_COUNT HW_REGISTER_RW(ARM_LOCAL_BASE+0x02C) -+#define ARM_LOCAL_AXI_IRQ HW_REGISTER_RW(ARM_LOCAL_BASE+0x030) -+#define ARM_LOCAL_TIMER_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x034) -+#define ARM_LOCAL_TIMER_WRITE HW_REGISTER_RW(ARM_LOCAL_BASE+0x038) -+ -+#define ARM_LOCAL_TIMER_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x040) -+#define ARM_LOCAL_TIMER_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x044) -+#define ARM_LOCAL_TIMER_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x048) -+#define ARM_LOCAL_TIMER_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x04C) -+ -+#define ARM_LOCAL_MAILBOX_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x050) -+#define ARM_LOCAL_MAILBOX_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x054) -+#define ARM_LOCAL_MAILBOX_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x058) -+#define ARM_LOCAL_MAILBOX_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x05C) -+ -+#define ARM_LOCAL_IRQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x060) -+#define ARM_LOCAL_IRQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x064) -+#define ARM_LOCAL_IRQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x068) -+#define ARM_LOCAL_IRQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x06C) -+ -+#define ARM_LOCAL_FIQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x070) -+#define ARM_LOCAL_FIQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x074) -+#define ARM_LOCAL_FIQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x078) -+#define ARM_LOCAL_FIQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x07C) -+ -+#define ARM_LOCAL_MAILBOX0_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x080) -+#define ARM_LOCAL_MAILBOX1_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x084) -+#define ARM_LOCAL_MAILBOX2_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x088) -+#define ARM_LOCAL_MAILBOX3_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x08C) -+ -+#define ARM_LOCAL_MAILBOX0_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x090) -+#define ARM_LOCAL_MAILBOX1_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x094) -+#define ARM_LOCAL_MAILBOX2_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x098) -+#define ARM_LOCAL_MAILBOX3_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x09C) -+ -+#define ARM_LOCAL_MAILBOX0_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A0) -+#define ARM_LOCAL_MAILBOX1_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A4) -+#define ARM_LOCAL_MAILBOX2_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A8) -+#define ARM_LOCAL_MAILBOX3_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0AC) -+ -+#define ARM_LOCAL_MAILBOX0_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B0) -+#define ARM_LOCAL_MAILBOX1_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B4) -+#define ARM_LOCAL_MAILBOX2_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B8) -+#define ARM_LOCAL_MAILBOX3_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0BC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C0) -+#define ARM_LOCAL_MAILBOX1_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C4) -+#define ARM_LOCAL_MAILBOX2_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C8) -+#define ARM_LOCAL_MAILBOX3_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0CC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D0) -+#define ARM_LOCAL_MAILBOX1_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D4) -+#define ARM_LOCAL_MAILBOX2_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D8) -+#define ARM_LOCAL_MAILBOX3_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0DC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E0) -+#define ARM_LOCAL_MAILBOX1_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E4) -+#define ARM_LOCAL_MAILBOX2_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E8) -+#define ARM_LOCAL_MAILBOX3_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0EC) -+ -+#define ARM_LOCAL_MAILBOX0_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F0) -+#define ARM_LOCAL_MAILBOX1_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F4) -+#define ARM_LOCAL_MAILBOX2_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F8) -+#define ARM_LOCAL_MAILBOX3_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0FC) -+ -+#endif -+ -+/* END */ -diff --git a/arch/arm/mach-bcm2709/include/mach/system.h b/arch/arm/mach-bcm2709/include/mach/system.h -new file mode 100644 -index 0000000000000000000000000000000000000000..c9a9c9a881102c5354971d15203a746906761a70 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/system.h -@@ -0,0 +1,37 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/system.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * Copyright (C) 2000 Deep Blue Solutions Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ASM_ARCH_SYSTEM_H -+#define __ASM_ARCH_SYSTEM_H -+ -+#include -+#include -+ -+static inline void arch_idle(void) -+{ -+ /* -+ * This should do all the clock switching -+ * and wait for interrupt tricks -+ */ -+ cpu_do_idle(); -+} -+ -+#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/uncompress.h b/arch/arm/mach-bcm2709/include/mach/uncompress.h -new file mode 100644 -index 0000000000000000000000000000000000000000..de7504bfc20ba24be8707861b8389783860adb77 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/uncompress.h -@@ -0,0 +1,84 @@ -+/* -+ * arch/arm/mach-bcn2708/include/mach/uncompress.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * Copyright (C) 2003 ARM Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+ -+#define UART_BAUD 115200 -+ -+#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) -+#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) -+#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) -+#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) -+#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) -+#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -+ -+/* -+ * This does not append a newline -+ */ -+static inline void putc(int c) -+{ -+ while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -+ barrier(); -+ -+ __raw_writel(c, BCM2708_UART_DR); -+} -+ -+static inline void flush(void) -+{ -+ int fr; -+ -+ do { -+ fr = __raw_readl(BCM2708_UART_FR); -+ barrier(); -+ } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); -+} -+ -+static inline void arch_decomp_setup(void) -+{ -+ int temp, div, rem, frac; -+ -+ temp = 16 * UART_BAUD; -+ div = UART0_CLOCK / temp; -+ rem = UART0_CLOCK % temp; -+ temp = (8 * rem) / UART_BAUD; -+ frac = (temp >> 1) + (temp & 1); -+ -+ /* Make sure the UART is disabled before we start */ -+ __raw_writel(0, BCM2708_UART_CR); -+ -+ /* Set the baud rate */ -+ __raw_writel(div, BCM2708_UART_IBRD); -+ __raw_writel(frac, BCM2708_UART_FBRD); -+ -+ /* Set the UART to 8n1, FIFO enabled */ -+ __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -+ -+ /* Enable the UART */ -+ __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -+ BCM2708_UART_CR); -+} -+ -+/* -+ * nothing to do -+ */ -+#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4a4a33845cbc02f0e0d5368fed3609f6ba9ff92b ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -@@ -0,0 +1,35 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#if !defined( VC_MEM_H ) -+#define VC_MEM_H -+ -+#include -+ -+#define VC_MEM_IOC_MAGIC 'v' -+ -+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) -+#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) -+#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) -+#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -+ -+#if defined( __KERNEL__ ) -+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -+ -+extern unsigned long mm_vc_mem_phys_addr; -+extern unsigned int mm_vc_mem_size; -+extern int vc_mem_get_current_size( void ); -+#endif -+ -+#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2709/include/mach/vmalloc.h b/arch/arm/mach-bcm2709/include/mach/vmalloc.h -new file mode 100644 -index 0000000000000000000000000000000000000000..6aa68260dd866c83527dffece8de483913231fb3 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/vmalloc.h -@@ -0,0 +1,20 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vmalloc.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#define VMALLOC_END (0xff000000) -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -new file mode 100644 -index 0000000000000000000000000000000000000000..d2adfd1db2421984ea8ab8fb809d1adb0765714e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/vc_mem.c -@@ -0,0 +1,431 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_ARCH_KONA -+#include -+#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) -+#else -+#include -+#endif -+ -+#include "mach/vc_mem.h" -+ -+#define DRIVER_NAME "vc-mem" -+ -+// Device (/dev) related variables -+static dev_t vc_mem_devnum = 0; -+static struct class *vc_mem_class = NULL; -+static struct cdev vc_mem_cdev; -+static int vc_mem_inited = 0; -+ -+#ifdef CONFIG_DEBUG_FS -+static struct dentry *vc_mem_debugfs_entry; -+#endif -+ -+/* -+ * Videocore memory addresses and size -+ * -+ * Drivers that wish to know the videocore memory addresses and sizes should -+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -+ * headers. This allows the other drivers to not be tied down to a a certain -+ * address/size at compile time. -+ * -+ * In the future, the goal is to have the videocore memory virtual address and -+ * size be calculated at boot time rather than at compile time. The decision of -+ * where the videocore memory resides and its size would be in the hands of the -+ * bootloader (and/or kernel). When that happens, the values of these variables -+ * would be calculated and assigned in the init function. -+ */ -+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space -+unsigned long mm_vc_mem_phys_addr = 0x00000000; -+unsigned int mm_vc_mem_size = 0; -+unsigned int mm_vc_mem_base = 0; -+ -+EXPORT_SYMBOL(mm_vc_mem_phys_addr); -+EXPORT_SYMBOL(mm_vc_mem_size); -+EXPORT_SYMBOL(mm_vc_mem_base); -+ -+static uint phys_addr = 0; -+static uint mem_size = 0; -+static uint mem_base = 0; -+ -+ -+/**************************************************************************** -+* -+* vc_mem_open -+* -+***************************************************************************/ -+ -+static int -+vc_mem_open(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_release -+* -+***************************************************************************/ -+ -+static int -+vc_mem_release(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_size -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_size(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_base -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_base(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_current_size -+* -+***************************************************************************/ -+ -+int -+vc_mem_get_current_size(void) -+{ -+ return mm_vc_mem_size; -+} -+ -+EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -+ -+/**************************************************************************** -+* -+* vc_mem_ioctl -+* -+***************************************************************************/ -+ -+static long -+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int rc = 0; -+ -+ (void) cmd; -+ (void) arg; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ switch (cmd) { -+ case VC_MEM_IOC_MEM_PHYS_ADDR: -+ { -+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -+ __func__, (void *) mm_vc_mem_phys_addr); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -+ sizeof (mm_vc_mem_phys_addr)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_SIZE: -+ { -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -+ mm_vc_mem_size); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_size, -+ sizeof (mm_vc_mem_size)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_BASE: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_LOAD: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ default: -+ { -+ return -ENOTTY; -+ } -+ } -+ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_mmap -+* -+***************************************************************************/ -+ -+static int -+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ int rc = 0; -+ unsigned long length = vma->vm_end - vma->vm_start; -+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -+ -+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -+ __func__, (long) vma->vm_start, (long) vma->vm_end, -+ (long) vma->vm_pgoff); -+ -+ if (offset + length > mm_vc_mem_size) { -+ pr_err("%s: length %ld is too big\n", __func__, length); -+ return -EINVAL; -+ } -+ // Do not cache the memory map -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ rc = remap_pfn_range(vma, vma->vm_start, -+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -+ vma->vm_pgoff, length, vma->vm_page_prot); -+ if (rc != 0) { -+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -+ } -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for the driver. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_mem_fops = { -+ .owner = THIS_MODULE, -+ .open = vc_mem_open, -+ .release = vc_mem_release, -+ .unlocked_ioctl = vc_mem_ioctl, -+ .mmap = vc_mem_mmap, -+}; -+ -+#ifdef CONFIG_DEBUG_FS -+static void vc_mem_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vc_mem_debugfs_entry); -+ vc_mem_debugfs_entry = NULL; -+} -+ -+ -+static int vc_mem_debugfs_init( -+ struct device *dev) -+{ -+ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -+ if (!vc_mem_debugfs_entry) { -+ dev_warn(dev, "could not create debugfs entry\n"); -+ return -EFAULT; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_phys_addr", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_phys_addr)) { -+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_size", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_size)) { -+ dev_warn(dev, "%s:could not create vc_mem_size entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_base", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_base)) { -+ dev_warn(dev, "%s:could not create vc_mem_base entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ vc_mem_debugfs_deinit(); -+ return -EFAULT; -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -+ -+ -+/**************************************************************************** -+* -+* vc_mem_init -+* -+***************************************************************************/ -+ -+static int __init -+vc_mem_init(void) -+{ -+ int rc = -EFAULT; -+ struct device *dev; -+ -+ pr_debug("%s: called\n", __func__); -+ -+ mm_vc_mem_phys_addr = phys_addr; -+ mm_vc_mem_size = mem_size; -+ mm_vc_mem_base = mem_base; -+ -+ vc_mem_get_size(); -+ -+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -+ -+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -+ __func__, rc); -+ goto out_err; -+ } -+ -+ cdev_init(&vc_mem_cdev, &vc_mem_fops); -+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -+ goto out_unregister; -+ } -+ -+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vc_mem_class)) { -+ rc = PTR_ERR(vc_mem_class); -+ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -+ goto out_cdev_del; -+ } -+ -+ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -+ DRIVER_NAME); -+ if (IS_ERR(dev)) { -+ rc = PTR_ERR(dev); -+ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -+ goto out_class_destroy; -+ } -+ -+#ifdef CONFIG_DEBUG_FS -+ /* don't fail if the debug entries cannot be created */ -+ vc_mem_debugfs_init(dev); -+#endif -+ -+ vc_mem_inited = 1; -+ return 0; -+ -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ -+ out_class_destroy: -+ class_destroy(vc_mem_class); -+ vc_mem_class = NULL; -+ -+ out_cdev_del: -+ cdev_del(&vc_mem_cdev); -+ -+ out_unregister: -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ -+ out_err: -+ return -1; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_exit -+* -+***************************************************************************/ -+ -+static void __exit -+vc_mem_exit(void) -+{ -+ pr_debug("%s: called\n", __func__); -+ -+ if (vc_mem_inited) { -+#if CONFIG_DEBUG_FS -+ vc_mem_debugfs_deinit(); -+#endif -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ class_destroy(vc_mem_class); -+ cdev_del(&vc_mem_cdev); -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ } -+} -+ -+module_init(vc_mem_init); -+module_exit(vc_mem_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -+ -+module_param(phys_addr, uint, 0644); -+module_param(mem_size, uint, 0644); -+module_param(mem_base, uint, 0644); + static const char * const bcm2835_compat[] = { + #ifdef CONFIG_ARCH_MULTI_V6 + "brcm,bcm2835", +@@ -47,5 +62,7 @@ static const char * const bcm2835_compat[] = { + + DT_MACHINE_START(BCM2835, "BCM2835") + .init_machine = bcm2835_init, ++ .reserve = bcm2835_board_reserve, ++ .init_early = bcm2835_init_early, + .dt_compat = bcm2835_compat + MACHINE_END diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 06d890a2342b1600e2eae6e350994ad59f5c3a08..30d96e81c0e052c725bdb00bb3df56194023ab9f 100644 --- a/arch/arm/mm/proc-v6.S @@ -4078,46 +1755,6 @@ index 06d890a2342b1600e2eae6e350994ad59f5c3a08..30d96e81c0e052c725bdb00bb3df5619 ret lr ENTRY(cpu_v6_dcache_clean_area) -diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index 2ed1b8a922ed02b9e3545991873af77b4c1bf871..b52d949ee91d96eb7672fbbb4969bfa1e7afc376 100644 ---- a/arch/arm/tools/mach-types -+++ b/arch/arm/tools/mach-types -@@ -522,6 +522,8 @@ torbreck MACH_TORBRECK TORBRECK 3090 - prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 - paz00 MACH_PAZ00 PAZ00 3128 - acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 -+bcm2708 MACH_BCM2708 BCM2708 3138 -+bcm2709 MACH_BCM2709 BCM2709 3139 - ag5evm MACH_AG5EVM AG5EVM 3189 - ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 - wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 -diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile -index fd9d6df0bbc0993c3b7862a08f89dc3a9725be9d..a60aa840b28f0fa73c496a2e0d5c816eed6f771a 100644 ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -19,7 +19,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o - obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o - obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o - obj-$(CONFIG_ORION_TIMER) += time-orion.o --obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o -+obj-$(CONFIG_BCM2835_TIMER)$(CONFIG_ARCH_BCM2708) += bcm2835_timer.o - obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o - obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o - obj-$(CONFIG_MOXART_TIMER) += moxart_timer.o -diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index 4c203b6b816357dce8d7a768ac81feaba91d431b..75da978fac0e06819d8a9740b95ee3d7035c1059 100644 ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -5,6 +5,9 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o - obj-$(CONFIG_ATH79) += irq-ath79-misc.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o -+obj-$(CONFIG_ARCH_BCM2708) += irq-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o - obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o - obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index eccf6ed025299cb480884f5bcbe77abf55a6bbb1..8ed457fd74bd23bee27b64a2c9e3828ce0e4fb87 100644 --- a/drivers/irqchip/irq-bcm2835.c @@ -4154,102 +1791,6 @@ index eccf6ed025299cb480884f5bcbe77abf55a6bbb1..8ed457fd74bd23bee27b64a2c9e3828c return 0; } -diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index aa4bfbf129e4585ebb89b25fca4b03c928925022..89f7a3a539b5a1b84ddcf0a1548160c000103fbb 100644 ---- a/include/linux/mmc/host.h -+++ b/include/linux/mmc/host.h -@@ -311,6 +311,7 @@ struct mmc_host { - #define MMC_CAP2_HS400_ES (1 << 20) /* Host supports enhanced strobe */ - #define MMC_CAP2_NO_SD (1 << 21) /* Do not send SD commands during initialization */ - #define MMC_CAP2_NO_MMC (1 << 22) /* Do not send (e)MMC commands during initialization */ -+#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31) /* Always use multiblock transfers */ - - mmc_pm_flag_t pm_caps; /* supported pm features */ - - -From 7a75212664e74d790360674f0e9d589f967149cf Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 5 Apr 2016 19:40:12 +0100 -Subject: [PATCH 032/208] reboot: Use power off rather than busy spinning when - halt is requested - ---- - arch/arm/kernel/reboot.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c -index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e00fb59a19 100644 ---- a/arch/arm/kernel/reboot.c -+++ b/arch/arm/kernel/reboot.c -@@ -102,9 +102,7 @@ void machine_shutdown(void) - */ - void machine_halt(void) - { -- local_irq_disable(); -- smp_send_stop(); -- while (1); -+ machine_power_off(); - } - - /* - -From f80a468706132177faffe0708b0cd0976ad6bf80 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 11 Nov 2015 21:01:15 +0000 -Subject: [PATCH 033/208] squash: include ARCH_BCM2708 / ARCH_BCM2709 - ---- - drivers/char/hw_random/Kconfig | 2 +- - drivers/clk/bcm/Makefile | 4 ++-- - drivers/mailbox/Kconfig | 2 +- - drivers/mailbox/bcm2835-mailbox.c | 18 ++++++++++++++++-- - drivers/pwm/Kconfig | 2 +- - drivers/spi/Kconfig | 4 ++-- - drivers/watchdog/Kconfig | 2 +- - sound/soc/bcm/Kconfig | 2 +- - 8 files changed, 25 insertions(+), 11 deletions(-) - -diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 8c0770bf8881351c1d956d310c5d670684090770..205b6b34d32c660d34c885e8391032d682c8870e 100644 ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX - - config HW_RANDOM_BCM2835 - tristate "Broadcom BCM2835 Random Number Generator support" -- depends on ARCH_BCM2835 || ARCH_BCM_NSP || ARCH_BCM_5301X -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM_NSP || ARCH_BCM_5301X - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number -diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile -index 1d79bd2c36f004669d1dcf78fa681025c3f074e2..fcf1bb5d792111a31226c33dec6b1da309a36e0d 100644 ---- a/drivers/clk/bcm/Makefile -+++ b/drivers/clk/bcm/Makefile -@@ -4,8 +4,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o --obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o --obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o - obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o - obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o -diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index 7817d40d81e74ad282b1760b1dc50d090d10670d..dc46b41705af8ea405dc961d9230058c7086db7d 100644 ---- a/drivers/mailbox/Kconfig -+++ b/drivers/mailbox/Kconfig -@@ -74,7 +74,7 @@ config ALTERA_MBOX - - config BCM2835_MBOX - tristate "BCM2835 Mailbox" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - An implementation of the BCM2385 Mailbox. It is used to invoke - the services of the Videocore. Say Y here if you want to use the diff --git a/drivers/mailbox/bcm2835-mailbox.c b/drivers/mailbox/bcm2835-mailbox.c index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f27006f4edd15 100644 --- a/drivers/mailbox/bcm2835-mailbox.c @@ -4299,71 +1840,11 @@ index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f2700 MODULE_AUTHOR("Lubomir Rintel "); MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); -diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig -index 80a566a00d0437dcc8fca7715c1109e7c2d35f67..549cf7a786e27e19863ec0ad53a8b2836afd0c2a 100644 ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -95,7 +95,7 @@ config PWM_BCM_KONA - - config PWM_BCM2835 - tristate "BCM2835 PWM support" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - PWM framework driver for BCM2835 controller (Raspberry Pi) - -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index d6fb8d4b778672fd006446c0eab710d35f6e6e3a..4b09be74af155c2a6e0590a6380242db40e6f914 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -94,7 +94,7 @@ config SPI_AXI_SPI_ENGINE - config SPI_BCM2835 - tristate "BCM2835 SPI controller" - depends on GPIOLIB -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI master. - -@@ -105,7 +105,7 @@ config SPI_BCM2835 - - config SPI_BCM2835AUX - tristate "BCM2835 SPI auxiliary controller" -- depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST -+ depends on ((ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709) && GPIOLIB) || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI aux master. - -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index 1bffe006ca9a843e2e71bc1a461a2d67e97480c0..9a28f1fdf93a79104049c03ed51abc31d34165d5 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1440,7 +1440,7 @@ config BCM63XX_WDT - - config BCM2835_WDT - tristate "Broadcom BCM2835 hardware watchdog" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - select WATCHDOG_CORE - help - Watchdog driver for the built in watchdog hardware in Broadcom -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index d528aaceaad95bc6bae2147ebe66249629d2512e..03a303e52d5fe57bbdd8769d24bca59067c54c65 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -1,6 +1,6 @@ - config SND_BCM2835_SOC_I2S - tristate "SoC Audio support for the Broadcom BCM2835 I2S module" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || MACH_BCM2708 || MACH_BCM2709 || COMPILE_TEST - select SND_SOC_GENERIC_DMAENGINE_PCM - select REGMAP_MMIO - help -From 719e241414d5c0c769e3cec0a36701f43665032e Mon Sep 17 00:00:00 2001 +From 4c8bdb873c0c0b35a8dfbff881bf15d64df34ddc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 034/208] Add dwc_otg driver +Subject: [PATCH 031/111] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -4857,6 +2338,12 @@ See: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=70437 Signed-off-by: popcornmix dwc_otg: Use kzalloc when suitable + +dwc_otg: Pass struct device to dma_alloc*() + +This makes it possible to get the bus address from Device Tree. + +Signed-off-by: Noralf Trønnes --- arch/arm/include/asm/irqflags.h | 16 +- arch/arm/kernel/fiqasm.S | 4 + @@ -4876,7 +2363,7 @@ dwc_otg: Use kzalloc when suitable drivers/usb/host/dwc_common_port/dwc_cc.c | 532 ++ drivers/usb/host/dwc_common_port/dwc_cc.h | 224 + drivers/usb/host/dwc_common_port/dwc_common_fbsd.c | 1308 ++++ - .../usb/host/dwc_common_port/dwc_common_linux.c | 1433 ++++ + .../usb/host/dwc_common_port/dwc_common_linux.c | 1418 ++++ drivers/usb/host/dwc_common_port/dwc_common_nbsd.c | 1275 ++++ drivers/usb/host/dwc_common_port/dwc_crypto.c | 308 + drivers/usb/host/dwc_common_port/dwc_crypto.h | 111 + @@ -4910,25 +2397,25 @@ dwc_otg: Use kzalloc when suitable drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 1355 ++++ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 370 + drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S | 80 + - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4257 ++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 862 +++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1132 ++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4260 ++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 868 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1139 ++++ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 417 ++ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2727 ++++++++ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 1005 +++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 962 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 963 +++ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 188 + - drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2712 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 266 + - drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 360 + - drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 5147 ++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1279 ++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2725 ++++++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 273 + + drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 361 + + drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 5148 ++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1280 ++++ drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2550 +++++++ drivers/usb/host/dwc_otg/test/Makefile | 16 + drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 + drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 + drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + - 70 files changed, 59883 insertions(+), 16 deletions(-) + 70 files changed, 59908 insertions(+), 16 deletions(-) create mode 100644 drivers/usb/gadget/file_storage.c create mode 100644 drivers/usb/host/dwc_common_port/Makefile create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd @@ -5059,10 +2546,10 @@ index 358ca8dd784fe43700ae070764fa783500a792fe..abaac7c7142d8887c1516957fc52162c return i; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 1d5fc32d06d007a6f64526a531da8ae69e8e6950..ce881480114d0f444f4b1099c713c2568b725162 100644 +index cbb146736f577da8a060d49b17052af78881adfa..7b07ce5dbdc5cffa36fb7e8dda07dd2a4102e1c5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -5041,7 +5041,7 @@ static void port_event(struct usb_hub *hub, int port1) +@@ -5039,7 +5039,7 @@ static void port_event(struct usb_hub *hub, int port1) if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0, unused; @@ -5072,10 +2559,10 @@ index 1d5fc32d06d007a6f64526a531da8ae69e8e6950..ce881480114d0f444f4b1099c713c256 USB_PORT_FEAT_C_OVER_CURRENT); msleep(100); /* Cool down */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c -index 0406a59f05510cb1dee98ffbf22b55c0ccd65750..8c3401f7c1ca80e0eedc7aec6cca5d593cf16718 100644 +index 3a47077461578f2af47af8d551353c2c7cb12f0e..85b7ff6f24b8023e1b589aa1a3557885c48d7a13 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c -@@ -1906,6 +1906,85 @@ free_interfaces: +@@ -1908,6 +1908,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); @@ -5162,7 +2649,7 @@ index 0406a59f05510cb1dee98ffbf22b55c0ccd65750..8c3401f7c1ca80e0eedc7aec6cca5d59 /* Now that the interfaces are installed, re-enable LPM. */ usb_unlocked_enable_lpm(dev); diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h -index a95b0c989c216eca774abd0709451096fda19792..17b605f5e1a3219b2c878e2aeeb45cec8e56ff3a 100644 +index 085049d37d7a5b23ff8dbf44b02afc1837fe3b68..63a461a21cc14b9c6f14db7c1d03c7a2ebcdba65 100644 --- a/drivers/usb/core/otg_whitelist.h +++ b/drivers/usb/core/otg_whitelist.h @@ -19,33 +19,82 @@ @@ -5199,7 +2686,7 @@ index a95b0c989c216eca774abd0709451096fda19792..17b605f5e1a3219b2c878e2aeeb45cec +//{ USB_DEVICE(0x0525, 0xa4a2), }, #endif - #if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE) + #if IS_ENABLED(CONFIG_USB_TEST) /* gadget zero, for testing */ -{ USB_DEVICE(0x0525, 0xa4a0), }, +//{ USB_DEVICE(0x0525, 0xa4a0), }, @@ -9001,7 +6488,7 @@ index 0000000000000000000000000000000000000000..a896d73f7a9336f5a34015c44ea5a6b0 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index 2e710a4cca525915991bf2b2a884dd2cec844281..a94354d1c7574c5cf1fdb7c47165459a5378c2c0 100644 +index 0b80cee30da4740e8c28c6ea7a4cc700163a12ee..f17b939c149562527937f49d90e23c7ab8b72328 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -762,6 +762,19 @@ config USB_HWA_HCD @@ -11719,10 +9206,10 @@ index 0000000000000000000000000000000000000000..6dd04b58f8f6c6d5ddad3b0b0148ff5d +} diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c new file mode 100644 -index 0000000000000000000000000000000000000000..46646841dda96fb2bed01152de552ccac5f0e5e4 +index 0000000000000000000000000000000000000000..0d641e6da24beeb07109e23847d1d6e81dc7d4ea --- /dev/null +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -@@ -0,0 +1,1433 @@ +@@ -0,0 +1,1418 @@ +#include +#include +#include @@ -12062,27 +9549,12 @@ index 0000000000000000000000000000000000000000..46646841dda96fb2bed01152de552cca + +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) +{ -+#ifdef xxCOSIM /* Only works for 32-bit cosim */ -+ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); -+#else -+ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); -+#endif -+ if (!buf) { -+ return NULL; -+ } -+ -+ memset(buf, 0, (size_t)size); -+ return buf; ++ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_KERNEL | GFP_DMA32); +} + +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) +{ -+ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); -+ if (!buf) { -+ return NULL; -+ } -+ memset(buf, 0, (size_t)size); -+ return buf; ++ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_ATOMIC); +} + +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) @@ -17265,7 +14737,7 @@ index 0000000000000000000000000000000000000000..4a8cdfe565b1fcefb400706dc7bc13cf +#endif /* __DWC_NOTIFIER_H__ */ diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h new file mode 100644 -index 0000000000000000000000000000000000000000..a2bbe232ffc3b58001d026864c3019792cdf5efa +index 0000000000000000000000000000000000000000..9a86d299403bd1dfdcdb6532fad702b2b65138d7 --- /dev/null +++ b/drivers/usb/host/dwc_common_port/dwc_os.h @@ -0,0 +1,1276 @@ @@ -17946,9 +15418,9 @@ index 0000000000000000000000000000000000000000..a2bbe232ffc3b58001d026864c301979 +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) + +# ifdef DWC_LINUX -+#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) ++#define DWC_DMA_ALLOC(_dev, _size_, _dma_) __DWC_DMA_ALLOC(_dev, _size_, _dma_) ++#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) __DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) ++#define DWC_DMA_FREE(_dev, _size_,_virt_, _dma_) __DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) +# endif + +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) @@ -17979,12 +15451,12 @@ index 0000000000000000000000000000000000000000..a2bbe232ffc3b58001d026864c301979 +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) + +# ifdef DWC_LINUX -+#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ -+ _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ -+ _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ -+ _virt_, _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC(_dev, _size_, _dma_) \ ++ dwc_dma_alloc_debug(_dev, _size_, _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) \ ++ dwc_dma_alloc_atomic_debug(_dev, _size_, _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) \ ++ dwc_dma_free_debug(_dev, _size_, _virt_, _dma_, __func__, __LINE__) +# endif + +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) @@ -38916,7 +36388,7 @@ index 0000000000000000000000000000000000000000..6a8be63a0ab20f4e1c56251b85648aa2 +#endif diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c new file mode 100644 -index 0000000000000000000000000000000000000000..85d82f31cb49631f03b23631882d2b6c063b33db +index 0000000000000000000000000000000000000000..13047c08fb71cc6e44c66096720d4654d3f9e4e1 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c @@ -0,0 +1,1355 @@ @@ -39000,7 +36472,7 @@ index 0000000000000000000000000000000000000000..85d82f31cb49631f03b23631882d2b6c + * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock + * Must be called with local interrupts and FIQ disabled. + */ -+#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) ++#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) +inline void fiq_fsm_spin_lock(fiq_lock_t *lock) +{ + unsigned long tmp; @@ -39033,7 +36505,7 @@ index 0000000000000000000000000000000000000000..85d82f31cb49631f03b23631882d2b6c +/** + * fiq_fsm_spin_unlock() - ARMv6+ bare bones spinunlock + */ -+#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) ++#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) +inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) +{ + smp_mb(); @@ -40739,10 +38211,10 @@ index 0000000000000000000000000000000000000000..ffa8d21bc61e893fee86ba04955587e7 +END(_dwc_otg_fiq_stub) diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c new file mode 100644 -index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6b13113fc +index 0000000000000000000000000000000000000000..027414bb2bf9fc3f3652407724187f3c6dc5ff68 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -0,0 +1,4257 @@ +@@ -0,0 +1,4260 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ @@ -41629,6 +39101,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + */ +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(dwc_otg_hcd); + int i; + + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); @@ -41661,7 +39134,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + + if (dwc_otg_hcd->core_if->dma_enable) { + if (dwc_otg_hcd->status_buf_dma) { -+ DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ DWC_DMA_FREE(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, + dwc_otg_hcd->status_buf, + dwc_otg_hcd->status_buf_dma); + } @@ -41691,6 +39164,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + int retval = 0; + int num_channels; + int i; @@ -41786,7 +39260,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + * for use as transaction bounce buffers in a 2-D array. Our access into this chunk is done by some + * moderately readable array casts. + */ -+ hcd->fiq_dmab = DWC_DMA_ALLOC((sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); ++ hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); + DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d", + (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base, + sizeof(struct fiq_dma_channel) * num_channels); @@ -41837,7 +39311,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + */ + if (hcd->core_if->dma_enable) { + hcd->status_buf = -+ DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ DWC_DMA_ALLOC(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, + &hcd->status_buf_dma); + } else { + hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); @@ -41932,6 +39406,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + uint32_t intr_enable; + unsigned long flags; + gintmsk_data_t gintmsk = { .d32 = 0, }; ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); + @@ -42126,7 +39601,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + buf_size = 4096; + } + if (!qh->dw_align_buf) { -+ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, ++ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(dev, buf_size, + &qh->dw_align_buf_dma); + if (!qh->dw_align_buf) { + DWC_ERROR @@ -42177,7 +39652,7 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 + fiq_fsm_spin_unlock(&hcd->fiq_state->lock); + local_fiq_enable(); + } -+ ++ + local_irq_restore(flags); + hc->qh = qh; +} @@ -45002,10 +42477,10 @@ index 0000000000000000000000000000000000000000..135b611abe08e141c937612ab7baada6 +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h new file mode 100644 -index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99ca8dce7dc +index 0000000000000000000000000000000000000000..4539cd7b802d3e49ac9a6cb3f1d88b475a1ace16 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -0,0 +1,862 @@ +@@ -0,0 +1,868 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ + * $Revision: #58 $ @@ -45049,6 +42524,7 @@ index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99c +#include "dwc_list.h" +#include "dwc_otg_cil.h" +#include "dwc_otg_fiq_fsm.h" ++#include "dwc_otg_driver.h" + + +/** @@ -45621,6 +43097,11 @@ index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99c +#endif +}; + ++static inline struct device *dwc_otg_hcd_to_dev(struct dwc_otg_hcd *hcd) ++{ ++ return &hcd->otg_dev->os_dep.platformdev->dev; ++} ++ +/** @name Transaction Execution Functions */ +/** @{ */ +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t @@ -45870,10 +43351,10 @@ index 0000000000000000000000000000000000000000..43dbed9fddbf5491bab33cc6e551b99c +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c new file mode 100644 -index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d809fec4e70 +index 0000000000000000000000000000000000000000..126e99ab2fc43f11d89a08ff0476181ead84029f --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -0,0 +1,1132 @@ +@@ -0,0 +1,1139 @@ +/*========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ + * $Revision: #10 $ @@ -45951,12 +43432,12 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + : qh->interval); +} + -+static int desc_list_alloc(dwc_otg_qh_t * qh) ++static int desc_list_alloc(struct device *dev, dwc_otg_qh_t * qh) +{ + int retval = 0; + + qh->desc_list = (dwc_otg_host_dma_desc_t *) -+ DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), ++ DWC_DMA_ALLOC(dev, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), + &qh->desc_list_dma); + + if (!qh->desc_list) { @@ -45982,10 +43463,10 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + +} + -+static void desc_list_free(dwc_otg_qh_t * qh) ++static void desc_list_free(struct device *dev, dwc_otg_qh_t * qh) +{ + if (qh->desc_list) { -+ DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, ++ DWC_DMA_FREE(dev, max_desc_num(qh), qh->desc_list, + qh->desc_list_dma); + qh->desc_list = NULL; + } @@ -45998,11 +43479,13 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + +static int frame_list_alloc(dwc_otg_hcd_t * hcd) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + int retval = 0; ++ + if (hcd->frame_list) + return 0; + -+ hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, ++ hcd->frame_list = DWC_DMA_ALLOC(dev, 4 * MAX_FRLIST_EN_NUM, + &hcd->frame_list_dma); + if (!hcd->frame_list) { + retval = -DWC_E_NO_MEMORY; @@ -46016,10 +43499,12 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + +static void frame_list_free(dwc_otg_hcd_t * hcd) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); ++ + if (!hcd->frame_list) + return; + -+ DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); ++ DWC_DMA_FREE(dev, 4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); + hcd->frame_list = NULL; +} + @@ -46197,6 +43682,7 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + */ +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + int retval = 0; + + if (qh->do_split) { @@ -46204,7 +43690,7 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + return -1; + } + -+ retval = desc_list_alloc(qh); ++ retval = desc_list_alloc(dev, qh); + + if ((retval == 0) + && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { @@ -46231,7 +43717,9 @@ index 0000000000000000000000000000000000000000..ee920c4d8f4a2980e4406cb878b81d80 + */ +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ -+ desc_list_free(qh); ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); ++ ++ desc_list_free(dev, qh); + + /* + * Channel still assigned due to some reasons. @@ -50164,7 +47652,7 @@ index 0000000000000000000000000000000000000000..e6b38ac330b72152204c2a6879c20f0c +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c new file mode 100644 -index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e83aee1443 +index 0000000000000000000000000000000000000000..74cd5fa54aed5241b61371477ef67d706477fd30 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c @@ -0,0 +1,1005 @@ @@ -50687,6 +48175,7 @@ index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e8 + ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = + dwc_otg_hcd; + otg_dev->hcd = dwc_otg_hcd; ++ otg_dev->hcd->otg_dev = otg_dev; + + if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { + goto error2; @@ -50701,7 +48190,6 @@ index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e8 + } + } + -+ otg_dev->hcd->otg_dev = otg_dev; + hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later @@ -51175,10 +48663,10 @@ index 0000000000000000000000000000000000000000..2ceed4212980f04ad082e78851c6a7e8 +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c new file mode 100644 -index 0000000000000000000000000000000000000000..3b2a60763b92fb2e9261a8ade3d4b33e3896cd62 +index 0000000000000000000000000000000000000000..c2dff94e8e6edd22e4427aaa1eac7aad972cb6bd --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -0,0 +1,962 @@ +@@ -0,0 +1,963 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ + * $Revision: #44 $ @@ -51240,6 +48728,7 @@ index 0000000000000000000000000000000000000000..3b2a60763b92fb2e9261a8ade3d4b33e + uint32_t buf_size = 0; + uint8_t *align_buf_virt = NULL; + dwc_dma_t align_buf_dma; ++ struct device *dev = dwc_otg_hcd_to_dev(hcd); + + /* Free each QTD in the QTD list */ + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); @@ -51263,7 +48752,7 @@ index 0000000000000000000000000000000000000000..3b2a60763b92fb2e9261a8ade3d4b33e + DWC_FREE(qh); + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + if (align_buf_virt) -+ DWC_DMA_FREE(buf_size, align_buf_virt, align_buf_dma); ++ DWC_DMA_FREE(dev, buf_size, align_buf_virt, align_buf_dma); + return; +} + @@ -52337,10 +49826,10 @@ index 0000000000000000000000000000000000000000..6b2c7d0c93f36a63863ff4b0ecc1f3ea +#endif /* _DWC_OS_DEP_H_ */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c new file mode 100644 -index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3d7ef86b8 +index 0000000000000000000000000000000000000000..9dabbe5c9791c5296d1cc7b663afa6ec462173cb --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -@@ -0,0 +1,2712 @@ +@@ -0,0 +1,2725 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ + * $Revision: #101 $ @@ -52580,20 +50069,22 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + * This function allocates a DMA Descriptor chain for the Endpoint + * buffer to be used for a transfer to/from the specified endpoint. + */ -+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, ++dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(struct device *dev, ++ dwc_dma_t * dma_desc_addr, + uint32_t count) +{ -+ return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), ++ return DWC_DMA_ALLOC_ATOMIC(dev, count * sizeof(dwc_otg_dev_dma_desc_t), + dma_desc_addr); +} + +/** + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. + */ -+void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, ++void dwc_otg_ep_free_desc_chain(struct device *dev, ++ dwc_otg_dev_dma_desc_t * desc_addr, + uint32_t dma_desc_addr, uint32_t count) +{ -+ DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, ++ DWC_DMA_FREE(dev, count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, + dma_desc_addr); +} + @@ -53448,8 +50939,10 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + * This function initialized the PCD portion of the driver. + * + */ -+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) ++dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev) +{ ++ struct device *dev = &otg_dev->os_dep.platformdev->dev; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; + dwc_otg_pcd_t *pcd = NULL; + dwc_otg_dev_if_t *dev_if; + int i; @@ -53506,7 +50999,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + */ + if (GET_CORE_IF(pcd)->dma_enable) { + pcd->setup_pkt = -+ DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_ALLOC(dev, sizeof(*pcd->setup_pkt) * 5, + &pcd->setup_pkt_dma_handle); + if (pcd->setup_pkt == NULL) { + DWC_FREE(pcd); @@ -53514,10 +51007,10 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + } + + pcd->status_buf = -+ DWC_DMA_ALLOC(sizeof(uint16_t), ++ DWC_DMA_ALLOC(dev, sizeof(uint16_t), + &pcd->status_buf_dma_handle); + if (pcd->status_buf == NULL) { -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, + pcd->setup_pkt, pcd->setup_pkt_dma_handle); + DWC_FREE(pcd); + return NULL; @@ -53525,17 +51018,17 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + + if (GET_CORE_IF(pcd)->dma_desc_enable) { + dev_if->setup_desc_addr[0] = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_setup_desc_addr[0], 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_setup_desc_addr[0], 1); + dev_if->setup_desc_addr[1] = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_setup_desc_addr[1], 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_setup_desc_addr[1], 1); + dev_if->in_desc_addr = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_in_desc_addr, 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_in_desc_addr, 1); + dev_if->out_desc_addr = -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_out_desc_addr, 1); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &dev_if->dma_out_desc_addr, 1); + pcd->data_terminated = 0; + + if (dev_if->setup_desc_addr[0] == 0 @@ -53544,26 +51037,26 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + || dev_if->out_desc_addr == 0) { + + if (dev_if->out_desc_addr) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->out_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->out_desc_addr, + dev_if->dma_out_desc_addr, 1); + if (dev_if->in_desc_addr) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->in_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->in_desc_addr, + dev_if->dma_in_desc_addr, 1); + if (dev_if->setup_desc_addr[1]) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->setup_desc_addr[1], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[1], + dev_if->dma_setup_desc_addr[1], 1); + if (dev_if->setup_desc_addr[0]) -+ dwc_otg_ep_free_desc_chain -+ (dev_if->setup_desc_addr[0], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[0], + dev_if->dma_setup_desc_addr[0], 1); + -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, + pcd->setup_pkt, + pcd->setup_pkt_dma_handle); -+ DWC_DMA_FREE(sizeof(*pcd->status_buf), ++ DWC_DMA_FREE(dev, sizeof(*pcd->status_buf), + pcd->status_buf, + pcd->status_buf_dma_handle); + @@ -53645,7 +51138,9 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) +{ + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + int i; ++ + if (pcd->core_if->core_params->dev_out_nak) { + for (i = 0; i < MAX_EPS_CHANNELS; i++) { + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); @@ -53654,20 +51149,24 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + } + + if (GET_CORE_IF(pcd)->dma_enable) { -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, ++ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, + pcd->setup_pkt_dma_handle); -+ DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, ++ DWC_DMA_FREE(dev, sizeof(uint16_t), pcd->status_buf, + pcd->status_buf_dma_handle); + if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[0], + dev_if->dma_setup_desc_addr + [0], 1); -+ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->setup_desc_addr[1], + dev_if->dma_setup_desc_addr + [1], 1); -+ dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->in_desc_addr, + dev_if->dma_in_desc_addr, 1); -+ dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, ++ dev_if->out_desc_addr, + dev_if->dma_out_desc_addr, + 1); + } @@ -53806,6 +51305,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; + int retval = 0; + int i, epcount; ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + + desc = (const usb_endpoint_descriptor_t *)ep_desc; + @@ -53914,9 +51414,9 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + if (ep->dwc_ep.type != UE_ISOCHRONOUS) { +#endif + ep->dwc_ep.desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&ep-> -+ dwc_ep.dma_desc_addr, -+ MAX_DMA_DESC_CNT); ++ dwc_otg_ep_alloc_desc_chain(dev, ++ &ep->dwc_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT); + if (!ep->dwc_ep.desc_addr) { + DWC_WARN("%s, can't allocate DMA descriptor\n", + __func__); @@ -53967,6 +51467,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; + gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; + fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + + ep = get_ep_from_handle(pcd, ep_handle); + @@ -54021,7 +51522,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + + /* Cannot call dma_free_coherent() with IRQs disabled */ + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ dwc_otg_ep_free_desc_chain(dev, desc_addr, dma_desc_addr, + MAX_DMA_DESC_CNT); + + goto out_unlocked; @@ -54422,6 +51923,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, + int zero, void *req_handle, int atomic_alloc) +{ ++ struct device *dev = dwc_otg_pcd_to_dev(pcd); + dwc_irqflags_t flags; + dwc_otg_pcd_request_t *req; + dwc_otg_pcd_ep_t *ep; @@ -54458,7 +51960,7 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 + req->dw_align_buf = NULL; + if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable + && !GET_CORE_IF(pcd)->dma_desc_enable) -+ req->dw_align_buf = DWC_DMA_ALLOC(buflen, ++ req->dw_align_buf = DWC_DMA_ALLOC(dev, buflen, + &req->dw_align_buf_dma); + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); + @@ -55055,10 +52557,10 @@ index 0000000000000000000000000000000000000000..ae0c72d02d007d5e7ce0f2dfb79b35d3 +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h new file mode 100644 -index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c2837ddcfa8 +index 0000000000000000000000000000000000000000..a70ebd049d2cca3bf988a1f809832eebede14f96 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -@@ -0,0 +1,266 @@ +@@ -0,0 +1,273 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ + * $Revision: #48 $ @@ -55099,6 +52601,8 @@ index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c28 +#include "usb.h" +#include "dwc_otg_cil.h" +#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_driver.h" ++ +struct cfiobject; + +/** @@ -55314,6 +52818,11 @@ index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c28 + +}; + ++static inline struct device *dwc_otg_pcd_to_dev(struct dwc_otg_pcd *pcd) ++{ ++ return &pcd->otg_dev->os_dep.platformdev->dev; ++} ++ +//FIXME this functions should be static, and this prototypes should be removed +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, @@ -55327,10 +52836,10 @@ index 0000000000000000000000000000000000000000..8ef7ba648ad92b9b7e141f22db2a0c28 +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h new file mode 100644 -index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c64b496b4 +index 0000000000000000000000000000000000000000..4c1d591fbc098b2f4a745669e4f243e068735b20 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -@@ -0,0 +1,360 @@ +@@ -0,0 +1,361 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ + * $Revision: #11 $ @@ -55370,6 +52879,7 @@ index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c + +//#include "dwc_os.h" +#include "dwc_otg_core_if.h" ++#include "dwc_otg_driver.h" + +/** @file + * This file defines DWC_OTG PCD Core API. @@ -55472,7 +52982,7 @@ index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c + * + * @param core_if The DWC_OTG Core + */ -+extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); ++extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev); + +/** Frees PCD allocated by dwc_otg_pcd_init + * @@ -55693,10 +53203,10 @@ index 0000000000000000000000000000000000000000..c8d2e0e0c99486558a4964a8c82de80c +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c new file mode 100644 -index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c34226d094f84 +index 0000000000000000000000000000000000000000..e55ea9c74be46167a41dc14a2d88a1228878b1bb --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -@@ -0,0 +1,5147 @@ +@@ -0,0 +1,5148 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ + * $Revision: #116 $ @@ -57843,6 +55353,7 @@ index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c3422 +static void complete_ep(dwc_otg_pcd_ep_t * ep) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ struct device *dev = dwc_otg_pcd_to_dev(ep->pcd); + dwc_otg_dev_if_t *dev_if = core_if->dev_if; + dwc_otg_dev_in_ep_regs_t *in_ep_regs = + dev_if->in_ep_regs[ep->dwc_ep.num]; @@ -58183,7 +55694,7 @@ index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c3422 + if (!ep->dwc_ep.is_in) { + dwc_memcpy(req->buf, req->dw_align_buf, req->length); + } -+ DWC_DMA_FREE(req->length, req->dw_align_buf, ++ DWC_DMA_FREE(dev, req->length, req->dw_align_buf, + req->dw_align_buf_dma); + } + @@ -60846,10 +58357,10 @@ index 0000000000000000000000000000000000000000..c8590b527110753b8064d35fab4c3422 +#endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c new file mode 100644 -index 0000000000000000000000000000000000000000..5624f32c9ea9117599df451af29fca2e3bca36de +index 0000000000000000000000000000000000000000..e799f15f294706ad7ac328dcb9ce68fbd0e71d38 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -0,0 +1,1279 @@ +@@ -0,0 +1,1280 @@ + /* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ + * $Revision: #21 $ @@ -61122,6 +58633,7 @@ index 0000000000000000000000000000000000000000..5624f32c9ea9117599df451af29fca2e + } + + buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); ++ WARN_ON(!buf); + + /* Check dword alignment */ + if (((int)buf & 0x3UL) != 0) { @@ -62058,7 +59570,7 @@ index 0000000000000000000000000000000000000000..5624f32c9ea9117599df451af29fca2e + + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); + -+ otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); ++ otg_dev->pcd = dwc_otg_pcd_init(otg_dev); + + if (!otg_dev->pcd) { + DWC_ERROR("dwc_otg_pcd_init failed\n"); @@ -65389,10 +62901,10 @@ index 0000000000000000000000000000000000000000..cdc9963176e5a4a0d5250613b61e26c5 +test_main(); +0; -From 8e1c17d3d0343deb70fe8cd422d6d3dc19a770fa Mon Sep 17 00:00:00 2001 +From 37fd2725a8d6b6f18331ba65f01ef63aa9fa3f7c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 035/208] bcm2708 framebuffer driver +Subject: [PATCH 032/111] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -65474,7 +62986,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/video/fbdev/bcm2708_fb.c diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index 88b008fb8a4ec9f4f4458b8b65a5e7d4ccef57e5..78a9e6119fa13437862080d815e84d68f7010d1f 100644 +index 5d3b0db5ce0af34997a3aa748292b6bd8d48c191..0ff4f80531e013f028ca4d05559c5464f8cfa5ef 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -228,6 +228,20 @@ config FB_TILEBLITTING @@ -65499,10 +63011,10 @@ index 88b008fb8a4ec9f4f4458b8b65a5e7d4ccef57e5..78a9e6119fa13437862080d815e84d68 tristate "Aeroflex Gaisler framebuffer support" depends on FB && SPARC diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index f6731867dd26dfc4318799e5204cd583a5d27670..ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2 100644 +index ee8c81405a7f9af1f190c98ddcfa53666ad97b0f..8cd1193b98690b9c4f49098ab14389504d65af3a 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o +@@ -10,6 +10,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o # Hardware specific drivers go first @@ -68851,10 +66363,10 @@ index 3c14e43b82fefe1d32f591d1b2f61d2cd28d0fa8..7626beb6a5bb8df601ddf0f6e6909d1f +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 -From 153d404162b1f45c70ea0113ab3057c534cd9532 Mon Sep 17 00:00:00 2001 +From 9a807a8f74d42575774841b923e278774777f81a Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 036/208] dmaengine: Add support for BCM2708 +Subject: [PATCH 033/111] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69004,19 +66516,28 @@ Signed-off-by: Noralf Trønnes bcm2708-dmaengine - Fix arm64 portability/build issues --- - drivers/dma/Kconfig | 4 + + drivers/dma/Kconfig | 6 +- drivers/dma/Makefile | 1 + drivers/dma/bcm2708-dmaengine.c | 281 ++++++++++++++++++++++++++++++ include/linux/platform_data/dma-bcm2708.h | 143 +++++++++++++++ - 4 files changed, 429 insertions(+) + 4 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/bcm2708-dmaengine.c create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index f7b3ac574968b35aeb1fb6b3ba8d4f1bf61599f9..2a2108062687ff33ff540c987f6367fa3b8aad9d 100644 +index 9c931d36c6a499a02f4f215f8cd77d3f2254a3b9..9ccee1058e4c5c208a196d6d89e700d09754f977 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig -@@ -502,6 +502,10 @@ config TIMB_DMA +@@ -108,7 +108,7 @@ config COH901318 + + config DMA_BCM2835 + tristate "BCM2835 DMA engine support" +- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 ++ depends on ARCH_BCM2835 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + +@@ -499,6 +499,10 @@ config TIMB_DMA help Enable support for the Timberdale FPGA DMA engine. @@ -69476,10 +66997,10 @@ index 0000000000000000000000000000000000000000..c5bfff2765be4606077e6c8af73040ec + +#endif /* _PLAT_BCM2708_DMA_H */ -From 7c69e53eea36e2bc92fb5d1e7e631aa0d4691a68 Mon Sep 17 00:00:00 2001 +From 74ba2b578d504eaed03b226d2945433cc1e2999b Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 037/208] MMC: added alternative MMC driver +Subject: [PATCH 034/111] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69565,8 +67086,8 @@ Signed-off-by: Phil Elwell drivers/mmc/core/quirks.c | 10 + drivers/mmc/host/Kconfig | 29 + drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-mmc.c | 1571 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 1611 insertions(+) + drivers/mmc/host/bcm2835-mmc.c | 1574 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 1614 insertions(+) create mode 100644 drivers/mmc/host/bcm2835-mmc.c diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c @@ -69650,10 +67171,10 @@ index e2bdaaf431841535b936600af56b8e38f52f9845..5133b680970c93fbb9695f83296f0f70 obj-$(CONFIG_MMC_MTK) += mtk-sd.o diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c new file mode 100644 -index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad098eec9a19 +index 0000000000000000000000000000000000000000..4fe8d1fe44578fbefcd48f8c327ba3d03f3d0a2a --- /dev/null +++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -0,0 +1,1571 @@ +@@ -0,0 +1,1574 @@ +/* + * BCM2835 MMC host driver. + * @@ -71115,8 +68636,11 @@ index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad09 +#endif + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { -+ dev_err(dev, "could not get clk\n"); + ret = PTR_ERR(clk); ++ if (ret == -EPROBE_DEFER) ++ dev_info(dev, "could not get clk, deferring probe\n"); ++ else ++ dev_err(dev, "could not get clk\n"); + goto err; + } + @@ -71226,10 +68750,10 @@ index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad09 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 4acaf78a70bd0f9c2fd25d5c9cc229a397eafe06 Mon Sep 17 00:00:00 2001 +From d8a2f68ba20a9bed7751795dda754f7861c71073 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 038/208] Adding bcm2835-sdhost driver, and an overlay to +Subject: [PATCH 035/111] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -71390,23 +68914,32 @@ See: https://github.com/raspberrypi/linux/pull/1492 Signed-off-by: Phil Elwell --- - drivers/mmc/host/Kconfig | 10 + + drivers/mmc/host/Kconfig | 12 +- drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-sdhost.c | 2185 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 2196 insertions(+) + drivers/mmc/host/bcm2835-sdhost.c | 2189 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 2201 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/host/bcm2835-sdhost.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 405d62909dd6ac5351684c002414cc02135d98ba..205d836b52e3bbcf8956fec98072c6ee7804a403 100644 +index 405d62909dd6ac5351684c002414cc02135d98ba..87d251e93913b216359383812cae196e91bf6cfb 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig +@@ -6,7 +6,7 @@ comment "MMC/SD/SDIO Host Controller Drivers" + + config MMC_BCM2835 + tristate "MMC support on BCM2835" +- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + help + This selects the MMC Interface on BCM2835. + @@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER If unsure, say 2 here. +config MMC_BCM2835_SDHOST + tristate "Support for the SDHost controller on BCM2708/9" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + help + This selects the SDHost controller on BCM2835/6. + @@ -71431,10 +68964,10 @@ index 5133b680970c93fbb9695f83296f0f70b4977240..adbc4586fec94aa8bd70f5ca3e2c90d1 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c new file mode 100644 -index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5da69c0d33 +index 0000000000000000000000000000000000000000..a9bc79bfdbb71807819dfe2d8f1651445997f92a --- /dev/null +++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -0,0 +1,2185 @@ +@@ -0,0 +1,2189 @@ +/* + * BCM2835 SD host driver. + * @@ -71672,10 +69205,10 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d +#define LOG_ENTRIES (256*1) +#define LOG_SIZE (sizeof(LOG_ENTRY_T)*LOG_ENTRIES) + -+static void log_init(u32 bus_to_phys) ++static void log_init(struct device *dev, u32 bus_to_phys) +{ + spin_lock_init(&log_lock); -+ sdhost_log_buf = dma_zalloc_coherent(NULL, LOG_SIZE, &sdhost_log_addr, ++ sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr, + GFP_KERNEL); + if (sdhost_log_buf) { + pr_info("sdhost: log_buf @ %p (%x)\n", @@ -73474,7 +71007,6 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d + return -ENODEV; + } + host->bus_addr = be32_to_cpup(addr); -+ log_init(iomem->start - host->bus_addr); + pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n", + (unsigned long)host->ioaddr, + (unsigned long)iomem->start, @@ -73526,8 +71058,11 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { -+ dev_err(dev, "could not get clk\n"); + ret = PTR_ERR(clk); ++ if (ret == -EPROBE_DEFER) ++ dev_info(dev, "could not get clk, deferring probe\n"); ++ else ++ dev_err(dev, "could not get clk\n"); + goto err; + } + @@ -73544,6 +71079,8 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d + (unsigned long)host->max_clk, + (int)host->irq); + ++ log_init(dev, iomem->start - host->bus_addr); ++ + if (node) + mmc_of_parse(mmc); + else @@ -73621,10 +71158,10 @@ index 0000000000000000000000000000000000000000..23dea422182534e248435aeaee3ecb5d +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From a93caaa8ea2e62422122b1a66434e42b56328838 Mon Sep 17 00:00:00 2001 +From 89171c41359e357f80ccc5b5c463f8bd3ee0b001 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 11 May 2016 12:50:33 +0100 -Subject: [PATCH 039/208] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards +Subject: [PATCH 036/111] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards Some SD cards have been found that corrupt data when small blocks are erased. Add a quirk to indicate that ERASE should not be used, @@ -73653,10 +71190,10 @@ Signed-off-by: Phil Elwell 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index 17891f17f39d88941990177b21d05479ec708037..c0163b8bdd20c33f65d952f6446d9bd2ca7bb3a6 100644 +index 709a872ed484a9da1ce620238c3222190c612f86..894c105be9ce7f83147a62c433c787b90a5e7c17 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c -@@ -134,6 +134,13 @@ enum { +@@ -135,6 +135,13 @@ enum { module_param(perdev_minors, int, 0444); MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); @@ -73732,10 +71269,10 @@ index 17891f17f39d88941990177b21d05479ec708037..c0163b8bdd20c33f65d952f6446d9bd2 if (mmc_blk_alloc_parts(card, md)) goto out; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index e55cde6d436dddae261c69ef36ca4de93eaa01ac..48e341b6ba6dde26605e7f9e8b9aa84c7ea268fa 100644 +index 2553d903a82b9eaa8577c1269bc9f63e18b00085..59a4044ea4c2e1283b1cad8afc7e67efaf8653fb 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c -@@ -2289,7 +2289,8 @@ EXPORT_SYMBOL(mmc_erase); +@@ -2409,7 +2409,8 @@ EXPORT_SYMBOL(mmc_erase); int mmc_can_erase(struct mmc_card *card) { if ((card->host->caps & MMC_CAP_ERASE) && @@ -73746,7 +71283,7 @@ index e55cde6d436dddae261c69ef36ca4de93eaa01ac..48e341b6ba6dde26605e7f9e8b9aa84c return 0; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h -index d8673ca968ba2d65fb3da39680583ca5152641e4..510c3872929b3267fb6665bb69d26f5aca740a28 100644 +index 73fad83acbcb6a157587180516f9ffe7c61eb7d7..e7c9d3098ac06e3c6554fa3373a311f937cd6f96 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -283,6 +283,9 @@ struct mmc_card { @@ -73760,10 +71297,10 @@ index d8673ca968ba2d65fb3da39680583ca5152641e4..510c3872929b3267fb6665bb69d26f5a unsigned int erase_shift; /* if erase unit is power 2 */ unsigned int pref_erase; /* in sectors */ -From a27a20db497c1caeba48369323b1821981851d35 Mon Sep 17 00:00:00 2001 +From 9fdd0d7cfa05e00b524b177adabf050922e57afb Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 040/208] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 037/111] cma: Add vc_cma driver to enable use of CMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -73784,10 +71321,10 @@ Signed-off-by: Noralf Trønnes drivers/char/Makefile | 1 + drivers/char/broadcom/Kconfig | 15 + drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_cma/Makefile | 14 + + drivers/char/broadcom/vc_cma/Makefile | 7 + drivers/char/broadcom/vc_cma/vc_cma.c | 1193 +++++++++++++++++++++++++++++++++ include/linux/broadcom/vc_cma.h | 36 + - 7 files changed, 1262 insertions(+) + 7 files changed, 1255 insertions(+) create mode 100644 drivers/char/broadcom/Kconfig create mode 100644 drivers/char/broadcom/Makefile create mode 100644 drivers/char/broadcom/vc_cma/Makefile @@ -73846,20 +71383,13 @@ index 0000000000000000000000000000000000000000..13c5bca291ccc0df090c4e61169ace8f +obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ diff --git a/drivers/char/broadcom/vc_cma/Makefile b/drivers/char/broadcom/vc_cma/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..6a94de4a7576f7c608f5bd01eb9f21a1a852120f +index 0000000000000000000000000000000000000000..d222313e28995bb54e9448192f5c99a352dde2e8 --- /dev/null +++ b/drivers/char/broadcom/vc_cma/Makefile -@@ -0,0 +1,14 @@ -+ccflags-y += -Wall -Wstrict-prototypes -Wno-trigraphs -+ccflags-y += -Werror -+ccflags-y += -Iinclude/linux/broadcom -+ccflags-y += -Idrivers/misc/vc04_services -+ccflags-y += -Idrivers/misc/vc04_services/interface/vchi -+ccflags-y += -Idrivers/misc/vc04_services/interface/vchiq_arm -+ -+ccflags-y += -D__KERNEL__ -+ccflags-y += -D__linux__ -+ccflags-y += -Werror +@@ -0,0 +1,7 @@ ++ccflags-$(CONFIG_BCM_VC_CMA) += -Wall -Wstrict-prototypes -Wno-trigraphs -Werror ++ccflags-$(CONFIG_BCM_VC_CMA) += -Iinclude/linux/broadcom -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vchi -Idrivers/staging/vc04_services/interface/vchiq_arm ++ccflags-$(CONFIG_BCM_VC_CMA) += -D__KERNEL__ -D__linux__ + +obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o + @@ -75106,10 +72636,10 @@ index 0000000000000000000000000000000000000000..be2819d5d41f9d5ed65daf8eedb94c9e + +#endif /* VC_CMA_H */ -From 81396ee5aaaa0cdc1c4c7fadd11dd1d7a3e88fae Mon Sep 17 00:00:00 2001 +From 193d82ddc048edea6b73997a51324a5078d17206 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 041/208] bcm2708: alsa sound driver +Subject: [PATCH 038/111] bcm2708: alsa sound driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -75164,7 +72694,7 @@ See: https://github.com/raspberrypi/linux/issues/1560 snd-bcm2835: Use bcm2835_hw params in preallocate --- - sound/arm/Kconfig | 8 + + sound/arm/Kconfig | 7 + sound/arm/Makefile | 5 + sound/arm/bcm2835-ctl.c | 350 +++++++++++++++ sound/arm/bcm2835-pcm.c | 563 +++++++++++++++++++++++ @@ -75172,7 +72702,7 @@ snd-bcm2835: Use bcm2835_hw params in preallocate sound/arm/bcm2835.c | 511 +++++++++++++++++++++ sound/arm/bcm2835.h | 167 +++++++ sound/arm/vc_vchi_audioserv_defs.h | 116 +++++ - 8 files changed, 2609 insertions(+) + 8 files changed, 2608 insertions(+) create mode 100755 sound/arm/bcm2835-ctl.c create mode 100755 sound/arm/bcm2835-pcm.c create mode 100755 sound/arm/bcm2835-vchiq.c @@ -75181,17 +72711,16 @@ snd-bcm2835: Use bcm2835_hw params in preallocate create mode 100644 sound/arm/vc_vchi_audioserv_defs.h diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 65171f6657a2984ccc14ce907a4c7c87d77d196b..8883c2f3a3269742e2bf6fc995643fb282f3509a 100644 +index 65171f6657a2984ccc14ce907a4c7c87d77d196b..02b6d263035ca18c9ce53229369dfb00915c260b 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig -@@ -32,6 +32,14 @@ config SND_PXA2XX_AC97 +@@ -32,6 +32,13 @@ config SND_PXA2XX_AC97 Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. +config SND_BCM2835 + tristate "BCM2835 ALSA driver" -+ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ -+ && BCM2708_VCHIQ && SND ++ depends on ARCH_BCM2835 && BCM2708_VCHIQ && SND + select SND_PCM + help + Say Y or M if you want to support BCM2835 Alsa pcm card driver @@ -75200,7 +72729,7 @@ index 65171f6657a2984ccc14ce907a4c7c87d77d196b..8883c2f3a3269742e2bf6fc995643fb2 config SND_PXA2XX_LIB diff --git a/sound/arm/Makefile b/sound/arm/Makefile -index 8c0c851d464109819beb296c2624bbec7af131e9..6796d7f5c7803ccfdaadbe56b2520c5454678686 100644 +index 8c0c851d464109819beb296c2624bbec7af131e9..26aabea79a0b5f141f7644a96684470d9b72f681 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -14,3 +14,8 @@ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o @@ -75211,7 +72740,7 @@ index 8c0c851d464109819beb296c2624bbec7af131e9..6796d7f5c7803ccfdaadbe56b2520c54 +obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o +snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o + -+ccflags-y += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 ++ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 diff --git a/sound/arm/bcm2835-ctl.c b/sound/arm/bcm2835-ctl.c new file mode 100755 index 0000000000000000000000000000000000000000..75dc3224be7ce8353378e9676ad2c6847dd0750b @@ -77845,13378 +75374,11 @@ index 0000000000000000000000000000000000000000..af3e6eb690113fc32ce9e06bd2f0f294 + +#endif // _VC_AUDIO_DEFS_H_ -From 5c7989bc7855400db08a481fef1a9caf9e32be2a Mon Sep 17 00:00:00 2001 +From 28996ccfaf3ff7a0873b2d895cab663cce800fdd Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 042/208] bcm2708 vchiq driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: popcornmix - -vchiq: create_pagelist copes with vmalloc memory - -Signed-off-by: Daniel Stone - -vchiq: fix the shim message release - -Signed-off-by: Daniel Stone - -vchiq: export additional symbols - -Signed-off-by: Daniel Stone - -VCHIQ: Make service closure fully synchronous (drv) - -This is one half of a two-part patch, the other half of which is to -the vchiq_lib user library. With these patches, calls to -vchiq_close_service and vchiq_remove_service won't return until any -associated callbacks have been delivered to the callback thread. - -VCHIQ: Add per-service tracing - -The new service option VCHIQ_SERVICE_OPTION_TRACE is a boolean that -toggles tracing for the specified service. - -This commit also introduces vchi_service_set_option and the associated -option VCHI_SERVICE_OPTION_TRACE. - -vchiq: Make the synchronous-CLOSE logic more tolerant - -vchiq: Move logging control into debugfs - -vchiq: Take care of a corner case tickled by VCSM - -Closing a connection that isn't fully open requires care, since one -side does not know the other side's port number. Code was present to -handle the case where a CLOSE is sent immediately after an OPEN, i.e. -before the OPENACK has been received, but this was incorrectly being -used when an OPEN from a client using port 0 was rejected. - -(In the observed failure, the host was attempting to use the VCSM -service, which isn't present in the 'cutdown' firmware. The failure -was intermittent because sometimes the keepalive service would -grab port 0.) - -This case can be distinguished because the client's remoteport will -still be VCHIQ_PORT_FREE, and the srvstate will be OPENING. Either -condition is sufficient to differentiate it from the special case -described above. - -vchiq: Avoid high load when blocked and unkillable - -vchiq: Include SIGSTOP and SIGCONT in list of signals not-masked by vchiq to allow gdb to work - -vchiq_arm: Complete support for SYNCHRONOUS mode - -vchiq: Remove inline from suspend/resume - -vchiq: Allocation does not need to be atomic - -vchiq: Fix wrong condition check - -The log level is checked from within the log call. Remove the check in the call. - -Signed-off-by: Pranith Kumar - -BCM270x: Add vchiq device to platform file and Device Tree - -Prepare to turn the vchiq module into a driver. - -Signed-off-by: Noralf Trønnes - -bcm2708: vchiq: Add Device Tree support - -Turn vchiq into a driver and stop hardcoding resources. -Use devm_* functions in probe path to simplify cleanup. -A global variable is used to hold the register address. This is done -to keep this patch as small as possible. -Also make available on ARCH_BCM2835. -Based on work by Lubomir Rintel. - -Signed-off-by: Noralf Trønnes - -vchiq: Change logging level for inbound data - -vchiq_arm: Two cacheing fixes - -1) Make fragment size vary with cache line size -Without this patch, non-cache-line-aligned transfers may corrupt -(or be corrupted by) adjacent data structures. - -Both ARM and VC need to be updated to enable this feature. This is -ensured by having the loader apply a new DT parameter - -cache-line-size. The existence of this parameter guarantees that the -kernel is capable, and the parameter will only be modified from the -safe default if the loader is capable. - -2) Flush/invalidate vmalloc'd memory, and invalidate after reads - -vchiq: fix NULL pointer dereference when closing driver - -The following code run as root will cause a null pointer dereference oops: - - int fd = open("/dev/vc-cma", O_RDONLY); - if (fd < 0) - err(1, "open failed"); - (void)close(fd); - -[ 1704.877721] Unable to handle kernel NULL pointer dereference at virtual address 00000000 -[ 1704.877725] pgd = b899c000 -[ 1704.877736] [00000000] *pgd=37fab831, *pte=00000000, *ppte=00000000 -[ 1704.877748] Internal error: Oops: 817 [#1] PREEMPT SMP ARM -[ 1704.877765] Modules linked in: evdev i2c_bcm2708 uio_pdrv_genirq uio -[ 1704.877774] CPU: 2 PID: 3656 Comm: stress-ng-fstat Not tainted 3.19.1-12-generic-bcm2709 #12-Ubuntu -[ 1704.877777] Hardware name: BCM2709 -[ 1704.877783] task: b8ab9b00 ti: b7e68000 task.ti: b7e68000 -[ 1704.877798] PC is at __down_interruptible+0x50/0xec -[ 1704.877806] LR is at down_interruptible+0x5c/0x68 -[ 1704.877813] pc : [<80630ee8>] lr : [<800704b0>] psr: 60080093 -sp : b7e69e50 ip : b7e69e88 fp : b7e69e84 -[ 1704.877817] r10: b88123c8 r9 : 00000010 r8 : 00000001 -[ 1704.877822] r7 : b8ab9b00 r6 : 7fffffff r5 : 80a1cc34 r4 : 80a1cc34 -[ 1704.877826] r3 : b7e69e50 r2 : 00000000 r1 : 00000000 r0 : 80a1cc34 -[ 1704.877833] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user -[ 1704.877838] Control: 10c5387d Table: 3899c06a DAC: 00000015 -[ 1704.877843] Process do-oops (pid: 3656, stack limit = 0xb7e68238) -[ 1704.877848] Stack: (0xb7e69e50 to 0xb7e6a000) -[ 1704.877856] 9e40: 80a1cc3c 00000000 00000010 b88123c8 -[ 1704.877865] 9e60: b7e69e84 80a1cc34 fff9fee9 ffffffff b7e68000 00000009 b7e69ea4 b7e69e88 -[ 1704.877874] 9e80: 800704b0 80630ea4 fff9fee9 60080013 80a1cc28 fff9fee9 b7e69edc b7e69ea8 -[ 1704.877884] 9ea0: 8040f558 80070460 fff9fee9 ffffffff 00000000 00000000 00000009 80a1cb7c -[ 1704.877893] 9ec0: 00000000 80a1cb7c 00000000 00000010 b7e69ef4 b7e69ee0 803e1ba4 8040f514 -[ 1704.877902] 9ee0: 00000e48 80a1cb7c b7e69f14 b7e69ef8 803e1c9c 803e1b74 b88123c0 b92acb18 -[ 1704.877911] 9f00: b8812790 b8d815d8 b7e69f24 b7e69f18 803e2250 803e1bc8 b7e69f5c b7e69f28 -[ 1704.877921] 9f20: 80167bac 803e222c 00000000 00000000 b7e69f54 b8ab9ffc 00000000 8098c794 -[ 1704.877930] 9f40: b8ab9b00 8000efc4 b7e68000 00000000 b7e69f6c b7e69f60 80167d6c 80167b28 -[ 1704.877939] 9f60: b7e69f8c b7e69f70 80047d38 80167d60 b7e68000 b7e68010 8000efc4 b7e69fb0 -[ 1704.877949] 9f80: b7e69fac b7e69f90 80012820 80047c84 01155490 011549a8 00000001 00000006 -[ 1704.877957] 9fa0: 00000000 b7e69fb0 8000ee5c 80012790 00000000 353d8c0f 7efc4308 00000000 -[ 1704.877966] 9fc0: 01155490 011549a8 00000001 00000006 00000000 00000000 76cf3ba0 00000003 -[ 1704.877975] 9fe0: 00000000 7efc42e4 0002272f 76e2ed66 60080030 00000003 00000000 00000000 -[ 1704.877998] [<80630ee8>] (__down_interruptible) from [<800704b0>] (down_interruptible+0x5c/0x68) -[ 1704.878015] [<800704b0>] (down_interruptible) from [<8040f558>] (vchiu_queue_push+0x50/0xd8) -[ 1704.878032] [<8040f558>] (vchiu_queue_push) from [<803e1ba4>] (send_worker_msg+0x3c/0x54) -[ 1704.878045] [<803e1ba4>] (send_worker_msg) from [<803e1c9c>] (vc_cma_set_reserve+0xe0/0x1c4) -[ 1704.878057] [<803e1c9c>] (vc_cma_set_reserve) from [<803e2250>] (vc_cma_release+0x30/0x38) -[ 1704.878069] [<803e2250>] (vc_cma_release) from [<80167bac>] (__fput+0x90/0x1e0) -[ 1704.878082] [<80167bac>] (__fput) from [<80167d6c>] (____fput+0x18/0x1c) -[ 1704.878094] [<80167d6c>] (____fput) from [<80047d38>] (task_work_run+0xc0/0xf8) -[ 1704.878109] [<80047d38>] (task_work_run) from [<80012820>] (do_work_pending+0x9c/0xc4) -[ 1704.878123] [<80012820>] (do_work_pending) from [<8000ee5c>] (work_pending+0xc/0x20) -[ 1704.878133] Code: e50b1034 e3a01000 e50b2030 e580300c (e5823000) - -..the fix is to ensure that we have actually initialized the queue before we attempt -to push any items onto it. This occurs if we do an open() followed by a close() without -any activity in between. - -Signed-off-by: Colin Ian King - -vchiq_arm: Sort out the vmalloc case - -See: https://github.com/raspberrypi/linux/issues/1055 - -vchiq: hack: Add include depecated dma include file - -vchiq_arm: Tweak the logging output - -Signed-off-by: Phil Elwell - -vchiq_arm: Access the dequeue_pending flag locked - -Reading through this code looking for another problem (now found in userland) -the use of dequeue_pending outside a lock didn't seem safe. - -Signed-off-by: Phil Elwell - -vchiq_arm: Service callbacks must not fail - -Service callbacks are not allowed to return an error. The internal callback -that delivers events and messages to user tasks does not enqueue them if -the service is closing, but this is not an error and should not be -reported as such. - -Signed-off-by: Phil Elwell - -vchiq_arm: do not use page_cache_release(page) macro (#1403) - -This macro is gone since 1fa64f198b9f8d6ec0f7aec7c18dc94684391140. - -Signed-off-by: Slawomir Stepien - -vchiq: Upate to match get_user_pages prototype - -vchiq_arm: Add completion records under the mutex - -An issue was observed when flushing openmax components -which generate a large number of messages returning -buffers to host. - -We occasionally found a duplicate message from 16 -messages prior, resulting in a buffer returned twice. - -While only one thread adds completions, without the -mutex you don't get the protection of the automatic -memory barrier you get with synchronisation objects. - -Signed-off-by: Phil Elwell ---- - arch/arm/mach-bcm2708/include/mach/platform.h | 2 + - arch/arm/mach-bcm2709/include/mach/platform.h | 2 + - drivers/misc/Kconfig | 1 + - drivers/misc/Makefile | 1 + - drivers/misc/vc04_services/Kconfig | 9 + - drivers/misc/vc04_services/Makefile | 14 + - .../interface/vchi/connections/connection.h | 328 ++ - .../interface/vchi/message_drivers/message.h | 204 + - drivers/misc/vc04_services/interface/vchi/vchi.h | 378 ++ - .../misc/vc04_services/interface/vchi/vchi_cfg.h | 224 ++ - .../interface/vchi/vchi_cfg_internal.h | 71 + - .../vc04_services/interface/vchi/vchi_common.h | 175 + - .../misc/vc04_services/interface/vchi/vchi_mh.h | 42 + - .../misc/vc04_services/interface/vchiq_arm/vchiq.h | 40 + - .../vc04_services/interface/vchiq_arm/vchiq_2835.h | 42 + - .../interface/vchiq_arm/vchiq_2835_arm.c | 586 +++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2921 +++++++++++++++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 220 ++ - .../interface/vchiq_arm/vchiq_build_info.h | 37 + - .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 69 + - .../interface/vchiq_arm/vchiq_connected.c | 120 + - .../interface/vchiq_arm/vchiq_connected.h | 50 + - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 3933 ++++++++++++++++++++ - .../vc04_services/interface/vchiq_arm/vchiq_core.h | 712 ++++ - .../interface/vchiq_arm/vchiq_debugfs.c | 383 ++ - .../interface/vchiq_arm/vchiq_debugfs.h | 52 + - .../interface/vchiq_arm/vchiq_genversion | 87 + - .../vc04_services/interface/vchiq_arm/vchiq_if.h | 189 + - .../interface/vchiq_arm/vchiq_ioctl.h | 131 + - .../interface/vchiq_arm/vchiq_kern_lib.c | 458 +++ - .../interface/vchiq_arm/vchiq_killable.h | 69 + - .../interface/vchiq_arm/vchiq_memdrv.h | 71 + - .../interface/vchiq_arm/vchiq_pagelist.h | 58 + - .../vc04_services/interface/vchiq_arm/vchiq_shim.c | 860 +++++ - .../vc04_services/interface/vchiq_arm/vchiq_util.c | 156 + - .../vc04_services/interface/vchiq_arm/vchiq_util.h | 82 + - .../interface/vchiq_arm/vchiq_version.c | 59 + - 37 files changed, 12836 insertions(+) - create mode 100644 drivers/misc/vc04_services/Kconfig - create mode 100644 drivers/misc/vc04_services/Makefile - create mode 100644 drivers/misc/vc04_services/interface/vchi/connections/connection.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/message_drivers/message.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_cfg.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_common.h - create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_mh.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h - create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c - -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -index 4fb43cf391e50e702d0a0588ceff397c79c501d7..e98ec5acc70ba9eb2bc7ff560ed3c92e21518b73 100644 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -78,6 +78,8 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - /* - * Watchdog -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -index 311b9f26fab7dd770bdcd684c7691442b0872d55..9a638f528fcebc9206419a2cc68f3c9856dda3c3 100644 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -78,6 +78,8 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - /* - * Watchdog -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index d002528289667732e9032f68aa0dba6624abfd9c..dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -802,6 +802,7 @@ source "drivers/misc/lis3lv02d/Kconfig" - source "drivers/misc/altera-stapl/Kconfig" - source "drivers/misc/mei/Kconfig" - source "drivers/misc/vmw_vmci/Kconfig" -+source "drivers/misc/vc04_services/Kconfig" - source "drivers/misc/mic/Kconfig" - source "drivers/misc/genwqe/Kconfig" - source "drivers/misc/echo/Kconfig" -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index fb32516ddfe2e4f8112beee9e831bcc4eb729667..bdf0f5fe7be52b16e12e0bbc79ebfe58a084794d 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_INTEL_MEI) += mei/ - obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ - obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o - obj-$(CONFIG_SRAM) += sram.o -+obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ - obj-y += mic/ - obj-$(CONFIG_GENWQE) += genwqe/ - obj-$(CONFIG_ECHO) += echo/ -diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..db8e1beb89f9f8c48ea5964016c8285ea82497d8 ---- /dev/null -+++ b/drivers/misc/vc04_services/Kconfig -@@ -0,0 +1,9 @@ -+config BCM2708_VCHIQ -+ tristate "Videocore VCHIQ" -+ depends on RASPBERRYPI_FIRMWARE -+ default y -+ help -+ Kernel to VideoCore communication interface for the -+ BCM2708 family of products. -+ Defaults to Y when the Broadcom Videocore services -+ are included in the build, N otherwise. -diff --git a/drivers/misc/vc04_services/Makefile b/drivers/misc/vc04_services/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..8d038feb42105cb2cad688690086ba69379b12e1 ---- /dev/null -+++ b/drivers/misc/vc04_services/Makefile -@@ -0,0 +1,14 @@ -+obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o -+ -+vchiq-objs := \ -+ interface/vchiq_arm/vchiq_core.o \ -+ interface/vchiq_arm/vchiq_arm.o \ -+ interface/vchiq_arm/vchiq_kern_lib.o \ -+ interface/vchiq_arm/vchiq_2835_arm.o \ -+ interface/vchiq_arm/vchiq_debugfs.o \ -+ interface/vchiq_arm/vchiq_shim.o \ -+ interface/vchiq_arm/vchiq_util.o \ -+ interface/vchiq_arm/vchiq_connected.o \ -+ -+ccflags-y += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -+ -diff --git a/drivers/misc/vc04_services/interface/vchi/connections/connection.h b/drivers/misc/vc04_services/interface/vchi/connections/connection.h -new file mode 100644 -index 0000000000000000000000000000000000000000..fef6ac34c6d2c04dfdba66f33850e72c24c613c2 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/connections/connection.h -@@ -0,0 +1,328 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef CONNECTION_H_ -+#define CONNECTION_H_ -+ -+#include -+#include -+#include -+ -+#include "interface/vchi/vchi_cfg_internal.h" -+#include "interface/vchi/vchi_common.h" -+#include "interface/vchi/message_drivers/message.h" -+ -+/****************************************************************************** -+ Global defs -+ *****************************************************************************/ -+ -+// Opaque handle for a connection / service pair -+typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T; -+ -+// opaque handle to the connection state information -+typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T; -+ -+typedef struct vchi_connection_t VCHI_CONNECTION_T; -+ -+ -+/****************************************************************************** -+ API -+ *****************************************************************************/ -+ -+// Routine to init a connection with a particular low level driver -+typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection, -+ const VCHI_MESSAGE_DRIVER_T * driver ); -+ -+// Routine to control CRC enabling at a connection level -+typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle, -+ VCHI_CRC_CONTROL_T control ); -+ -+// Routine to create a service -+typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle, -+ int32_t service_id, -+ uint32_t rx_fifo_size, -+ uint32_t tx_fifo_size, -+ int server, -+ VCHI_CALLBACK_T callback, -+ void *callback_param, -+ int32_t want_crc, -+ int32_t want_unaligned_bulk_rx, -+ int32_t want_unaligned_bulk_tx, -+ VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle ); -+ -+// Routine to close a service -+typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle ); -+ -+// Routine to queue a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// scatter-gather (vector) message queueing -+typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// Routine to dequeue a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *data, -+ uint32_t max_data_size_to_read, -+ uint32_t *actual_msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to peek at a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to hold a message -+typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags, -+ void **message_handle ); -+ -+// Routine to initialise a received message iterator -+typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ VCHI_MSG_ITER_T *iter, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to release a held message -+typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *message_handle ); -+ -+// Routine to get info on a held message -+typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *message_handle, -+ void **data, -+ int32_t *msg_size, -+ uint32_t *tx_timestamp, -+ uint32_t *rx_timestamp ); -+ -+// Routine to check whether the iterator has a next message -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ const VCHI_MSG_ITER_T *iter ); -+ -+// Routine to advance the iterator -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ VCHI_MSG_ITER_T *iter, -+ void **data, -+ uint32_t *msg_size ); -+ -+// Routine to remove the last message returned by the iterator -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ VCHI_MSG_ITER_T *iter ); -+ -+// Routine to hold the last message returned by the iterator -+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, -+ VCHI_MSG_ITER_T *iter, -+ void **msg_handle ); -+ -+// Routine to transmit bulk data -+typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ const void *data_src, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle ); -+ -+// Routine to receive data -+typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, -+ void *data_dst, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle ); -+ -+// Routine to report if a server is available -+typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t peer_flags ); -+ -+// Routine to report the number of RX slots available -+typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state ); -+ -+// Routine to report the RX slot size -+typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state ); -+ -+// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO -+typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state, -+ int32_t service, -+ uint32_t length, -+ MESSAGE_TX_CHANNEL_T channel, -+ uint32_t channel_params, -+ uint32_t data_length, -+ uint32_t data_offset); -+ -+// Callback to inform a service that a Xon or Xoff message has been received -+typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t xoff); -+ -+// Callback to inform a service that a server available reply message has been received -+typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, uint32_t flags); -+ -+// Callback to indicate that bulk auxiliary messages have arrived -+typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state); -+ -+// Callback to indicate that bulk auxiliary messages have arrived -+typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle); -+ -+// Callback with all the connection info you require -+typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size); -+ -+// Callback to inform of a disconnect -+typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags); -+ -+// Callback to inform of a power control request -+typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, int32_t enable); -+ -+// allocate memory suitably aligned for this connection -+typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length); -+ -+// free memory allocated by buffer_allocate -+typedef void (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address); -+ -+ -+/****************************************************************************** -+ System driver struct -+ *****************************************************************************/ -+ -+struct opaque_vchi_connection_api_t -+{ -+ // Routine to init the connection -+ VCHI_CONNECTION_INIT_T init; -+ -+ // Connection-level CRC control -+ VCHI_CONNECTION_CRC_CONTROL_T crc_control; -+ -+ // Routine to connect to or create service -+ VCHI_CONNECTION_SERVICE_CONNECT_T service_connect; -+ -+ // Routine to disconnect from a service -+ VCHI_CONNECTION_SERVICE_DISCONNECT_T service_disconnect; -+ -+ // Routine to queue a message -+ VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T service_queue_msg; -+ -+ // scatter-gather (vector) message queue -+ VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T service_queue_msgv; -+ -+ // Routine to dequeue a message -+ VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T service_dequeue_msg; -+ -+ // Routine to peek at a message -+ VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T service_peek_msg; -+ -+ // Routine to hold a message -+ VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T service_hold_msg; -+ -+ // Routine to initialise a received message iterator -+ VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg; -+ -+ // Routine to release a message -+ VCHI_CONNECTION_HELD_MSG_RELEASE_T held_msg_release; -+ -+ // Routine to get information on a held message -+ VCHI_CONNECTION_HELD_MSG_INFO_T held_msg_info; -+ -+ // Routine to check for next message on iterator -+ VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T msg_iter_has_next; -+ -+ // Routine to get next message on iterator -+ VCHI_CONNECTION_MSG_ITER_NEXT_T msg_iter_next; -+ -+ // Routine to remove the last message returned by iterator -+ VCHI_CONNECTION_MSG_ITER_REMOVE_T msg_iter_remove; -+ -+ // Routine to hold the last message returned by iterator -+ VCHI_CONNECTION_MSG_ITER_HOLD_T msg_iter_hold; -+ -+ // Routine to transmit bulk data -+ VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T bulk_queue_transmit; -+ -+ // Routine to receive data -+ VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T bulk_queue_receive; -+ -+ // Routine to report the available servers -+ VCHI_CONNECTION_SERVER_PRESENT server_present; -+ -+ // Routine to report the number of RX slots available -+ VCHI_CONNECTION_RX_SLOTS_AVAILABLE connection_rx_slots_available; -+ -+ // Routine to report the RX slot size -+ VCHI_CONNECTION_RX_SLOT_SIZE connection_rx_slot_size; -+ -+ // Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO -+ VCHI_CONNECTION_RX_BULK_BUFFER_ADDED rx_bulk_buffer_added; -+ -+ // Callback to inform a service that a Xon or Xoff message has been received -+ VCHI_CONNECTION_FLOW_CONTROL flow_control; -+ -+ // Callback to inform a service that a server available reply message has been received -+ VCHI_CONNECTION_SERVER_AVAILABLE_REPLY server_available_reply; -+ -+ // Callback to indicate that bulk auxiliary messages have arrived -+ VCHI_CONNECTION_BULK_AUX_RECEIVED bulk_aux_received; -+ -+ // Callback to indicate that a bulk auxiliary message has been transmitted -+ VCHI_CONNECTION_BULK_AUX_TRANSMITTED bulk_aux_transmitted; -+ -+ // Callback to provide information about the connection -+ VCHI_CONNECTION_INFO connection_info; -+ -+ // Callback to notify that peer has requested disconnect -+ VCHI_CONNECTION_DISCONNECT disconnect; -+ -+ // Callback to notify that peer has requested power change -+ VCHI_CONNECTION_POWER_CONTROL power_control; -+ -+ // allocate memory suitably aligned for this connection -+ VCHI_BUFFER_ALLOCATE buffer_allocate; -+ -+ // free memory allocated by buffer_allocate -+ VCHI_BUFFER_FREE buffer_free; -+ -+}; -+ -+struct vchi_connection_t { -+ const VCHI_CONNECTION_API_T *api; -+ VCHI_CONNECTION_STATE_T *state; -+#ifdef VCHI_COARSE_LOCKING -+ struct semaphore sem; -+#endif -+}; -+ -+ -+#endif /* CONNECTION_H_ */ -+ -+/****************************** End of file **********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h b/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h -new file mode 100644 -index 0000000000000000000000000000000000000000..8b3f76735bd45ab09a12dc6e17e335241fd11755 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h -@@ -0,0 +1,204 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef _VCHI_MESSAGE_H_ -+#define _VCHI_MESSAGE_H_ -+ -+#include -+#include -+#include -+ -+#include "interface/vchi/vchi_cfg_internal.h" -+#include "interface/vchi/vchi_common.h" -+ -+ -+typedef enum message_event_type { -+ MESSAGE_EVENT_NONE, -+ MESSAGE_EVENT_NOP, -+ MESSAGE_EVENT_MESSAGE, -+ MESSAGE_EVENT_SLOT_COMPLETE, -+ MESSAGE_EVENT_RX_BULK_PAUSED, -+ MESSAGE_EVENT_RX_BULK_COMPLETE, -+ MESSAGE_EVENT_TX_COMPLETE, -+ MESSAGE_EVENT_MSG_DISCARDED -+} MESSAGE_EVENT_TYPE_T; -+ -+typedef enum vchi_msg_flags -+{ -+ VCHI_MSG_FLAGS_NONE = 0x0, -+ VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1 -+} VCHI_MSG_FLAGS_T; -+ -+typedef enum message_tx_channel -+{ -+ MESSAGE_TX_CHANNEL_MESSAGE = 0, -+ MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards -+} MESSAGE_TX_CHANNEL_T; -+ -+// Macros used for cycling through bulk channels -+#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) -+#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) -+ -+typedef enum message_rx_channel -+{ -+ MESSAGE_RX_CHANNEL_MESSAGE = 0, -+ MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards -+} MESSAGE_RX_CHANNEL_T; -+ -+// Message receive slot information -+typedef struct rx_msg_slot_info { -+ -+ struct rx_msg_slot_info *next; -+ //struct slot_info *prev; -+#if !defined VCHI_COARSE_LOCKING -+ struct semaphore sem; -+#endif -+ -+ uint8_t *addr; // base address of slot -+ uint32_t len; // length of slot in bytes -+ -+ uint32_t write_ptr; // hardware causes this to advance -+ uint32_t read_ptr; // this module does the reading -+ int active; // is this slot in the hardware dma fifo? -+ uint32_t msgs_parsed; // count how many messages are in this slot -+ uint32_t msgs_released; // how many messages have been released -+ void *state; // connection state information -+ uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services -+} RX_MSG_SLOTINFO_T; -+ -+// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out. -+// In particular, it mustn't use addr and len - they're the client buffer, but the message -+// driver will be tasked with sending the aligned core section. -+typedef struct rx_bulk_slotinfo_t { -+ struct rx_bulk_slotinfo_t *next; -+ -+ struct semaphore *blocking; -+ -+ // needed by DMA -+ void *addr; -+ uint32_t len; -+ -+ // needed for the callback -+ void *service; -+ void *handle; -+ VCHI_FLAGS_T flags; -+} RX_BULK_SLOTINFO_T; -+ -+ -+/* ---------------------------------------------------------------------- -+ * each connection driver will have a pool of the following struct. -+ * -+ * the pool will be managed by vchi_qman_* -+ * this means there will be multiple queues (single linked lists) -+ * a given struct message_info will be on exactly one of these queues -+ * at any one time -+ * -------------------------------------------------------------------- */ -+typedef struct rx_message_info { -+ -+ struct message_info *next; -+ //struct message_info *prev; -+ -+ uint8_t *addr; -+ uint32_t len; -+ RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message -+ uint32_t tx_timestamp; -+ uint32_t rx_timestamp; -+ -+} RX_MESSAGE_INFO_T; -+ -+typedef struct { -+ MESSAGE_EVENT_TYPE_T type; -+ -+ struct { -+ // for messages -+ void *addr; // address of message -+ uint16_t slot_delta; // whether this message indicated slot delta -+ uint32_t len; // length of message -+ RX_MSG_SLOTINFO_T *slot; // slot this message is in -+ int32_t service; // service id this message is destined for -+ uint32_t tx_timestamp; // timestamp from the header -+ uint32_t rx_timestamp; // timestamp when we parsed it -+ } message; -+ -+ // FIXME: cleanup slot reporting... -+ RX_MSG_SLOTINFO_T *rx_msg; -+ RX_BULK_SLOTINFO_T *rx_bulk; -+ void *tx_handle; -+ MESSAGE_TX_CHANNEL_T tx_channel; -+ -+} MESSAGE_EVENT_T; -+ -+ -+// callbacks -+typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state ); -+ -+typedef struct { -+ VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback; -+} VCHI_MESSAGE_DRIVER_OPEN_T; -+ -+ -+// handle to this instance of message driver (as returned by ->open) -+typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T; -+ -+struct opaque_vchi_message_driver_t { -+ VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state ); -+ int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle ); -+ int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle ); -+ int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, int32_t enable ); -+ int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message -+ int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk) -+ int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk) -+ void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver -+ int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle ); -+ int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, int32_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void -+ *address, uint32_t length_avail, uint32_t max_total_length, int32_t pad_to_fill, int32_t allow_partial ); -+ -+ int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count ); -+ int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length ); -+ void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length ); -+ void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address ); -+ int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); -+ int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); -+ -+ int32_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); -+ uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); -+ int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); -+ int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel ); -+ void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len ); -+ void (*debug)( VCHI_MDRIVER_HANDLE_T *handle ); -+}; -+ -+ -+#endif // _VCHI_MESSAGE_H_ -+ -+/****************************** End of file ***********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi.h b/drivers/misc/vc04_services/interface/vchi/vchi.h -new file mode 100644 -index 0000000000000000000000000000000000000000..1b17e98f737979eef19906609bc19ecd19455618 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi.h -@@ -0,0 +1,378 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_H_ -+#define VCHI_H_ -+ -+#include "interface/vchi/vchi_cfg.h" -+#include "interface/vchi/vchi_common.h" -+#include "interface/vchi/connections/connection.h" -+#include "vchi_mh.h" -+ -+ -+/****************************************************************************** -+ Global defs -+ *****************************************************************************/ -+ -+#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1)) -+#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1)) -+#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1)))) -+ -+#ifdef USE_VCHIQ_ARM -+#define VCHI_BULK_ALIGNED(x) 1 -+#else -+#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0) -+#endif -+ -+struct vchi_version { -+ uint32_t version; -+ uint32_t version_min; -+}; -+#define VCHI_VERSION(v_) { v_, v_ } -+#define VCHI_VERSION_EX(v_, m_) { v_, m_ } -+ -+typedef enum -+{ -+ VCHI_VEC_POINTER, -+ VCHI_VEC_HANDLE, -+ VCHI_VEC_LIST -+} VCHI_MSG_VECTOR_TYPE_T; -+ -+typedef struct vchi_msg_vector_ex { -+ -+ VCHI_MSG_VECTOR_TYPE_T type; -+ union -+ { -+ // a memory handle -+ struct -+ { -+ VCHI_MEM_HANDLE_T handle; -+ uint32_t offset; -+ int32_t vec_len; -+ } handle; -+ -+ // an ordinary data pointer -+ struct -+ { -+ const void *vec_base; -+ int32_t vec_len; -+ } ptr; -+ -+ // a nested vector list -+ struct -+ { -+ struct vchi_msg_vector_ex *vec; -+ uint32_t vec_len; -+ } list; -+ } u; -+} VCHI_MSG_VECTOR_EX_T; -+ -+ -+// Construct an entry in a msg vector for a pointer (p) of length (l) -+#define VCHI_VEC_POINTER(p,l) VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } } -+ -+// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l) -+#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE, { { (h), (o), (l) } } -+ -+// Macros to manipulate 'FOURCC' values -+#define MAKE_FOURCC(x) ((int32_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] )) -+#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF -+ -+ -+// Opaque service information -+struct opaque_vchi_service_t; -+ -+// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold, -+// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only. -+typedef struct -+{ -+ struct opaque_vchi_service_t *service; -+ void *message; -+} VCHI_HELD_MSG_T; -+ -+ -+ -+// structure used to provide the information needed to open a server or a client -+typedef struct { -+ struct vchi_version version; -+ int32_t service_id; -+ VCHI_CONNECTION_T *connection; -+ uint32_t rx_fifo_size; -+ uint32_t tx_fifo_size; -+ VCHI_CALLBACK_T callback; -+ void *callback_param; -+ /* client intends to receive bulk transfers of -+ odd lengths or into unaligned buffers */ -+ int32_t want_unaligned_bulk_rx; -+ /* client intends to transmit bulk transfers of -+ odd lengths or out of unaligned buffers */ -+ int32_t want_unaligned_bulk_tx; -+ /* client wants to check CRCs on (bulk) xfers. -+ Only needs to be set at 1 end - will do both directions. */ -+ int32_t want_crc; -+} SERVICE_CREATION_T; -+ -+// Opaque handle for a VCHI instance -+typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T; -+ -+// Opaque handle for a server or client -+typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T; -+ -+// Service registration & startup -+typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections); -+ -+typedef struct service_info_tag { -+ const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */ -+ VCHI_SERVICE_INIT init; /* Service initialisation function */ -+ void *vll_handle; /* VLL handle; NULL when unloaded or a "static VLL" in build */ -+} SERVICE_INFO_T; -+ -+/****************************************************************************** -+ Global funcs - implementation is specific to which side you are on (local / remote) -+ *****************************************************************************/ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table, -+ const VCHI_MESSAGE_DRIVER_T * low_level); -+ -+ -+// Routine used to initialise the vchi on both local + remote connections -+extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle ); -+ -+extern int32_t vchi_exit( void ); -+ -+extern int32_t vchi_connect( VCHI_CONNECTION_T **connections, -+ const uint32_t num_connections, -+ VCHI_INSTANCE_T instance_handle ); -+ -+//When this is called, ensure that all services have no data pending. -+//Bulk transfers can remain 'queued' -+extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle ); -+ -+// Global control over bulk CRC checking -+extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection, -+ VCHI_CRC_CONTROL_T control ); -+ -+// helper functions -+extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length); -+extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address); -+extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle); -+ -+ -+/****************************************************************************** -+ Global service API -+ *****************************************************************************/ -+// Routine to create a named service -+extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle ); -+ -+// Routine to destory a service -+extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to open a named service -+extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle); -+ -+extern int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, -+ short *peer_version ); -+ -+// Routine to close a named service -+extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to increment ref count on a named service -+extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to decrement ref count on a named service -+extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to set a control option for a named service -+extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle, -+ VCHI_SERVICE_OPTION_T option, -+ int value); -+ -+// Routine to send a message across a service -+extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle, -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// scatter-gather (vector) and send message -+int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_EX_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// legacy scatter-gather (vector) and send message, only handles pointers -+int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// Routine to receive a msg from a service -+// Dequeue is equivalent to hold, copy into client buffer, release -+extern int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle, -+ void *data, -+ uint32_t max_data_size_to_read, -+ uint32_t *actual_msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to look at a message in place. -+// The message is not dequeued, so a subsequent call to peek or dequeue -+// will return the same message. -+extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags ); -+ -+// Routine to remove a message after it has been read in place with peek -+// The first message on the queue is dequeued. -+extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle ); -+ -+// Routine to look at a message in place. -+// The message is dequeued, so the caller is left holding it; the descriptor is -+// filled in and must be released when the user has finished with the message. -+extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle, -+ void **data, // } may be NULL, as info can be -+ uint32_t *msg_size, // } obtained from HELD_MSG_T -+ VCHI_FLAGS_T flags, -+ VCHI_HELD_MSG_T *message_descriptor ); -+ -+// Initialise an iterator to look through messages in place -+extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_ITER_T *iter, -+ VCHI_FLAGS_T flags ); -+ -+/****************************************************************************** -+ Global service support API - operations on held messages and message iterators -+ *****************************************************************************/ -+ -+// Routine to get the address of a held message -+extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to get the size of a held message -+extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to get the transmit timestamp as written into the header by the peer -+extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to get the reception timestamp, written as we parsed the header -+extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message ); -+ -+// Routine to release a held message after it has been processed -+extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message ); -+ -+// Indicates whether the iterator has a next message. -+extern int32_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter ); -+ -+// Return the pointer and length for the next message and advance the iterator. -+extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter, -+ void **data, -+ uint32_t *msg_size ); -+ -+// Remove the last message returned by vchi_msg_iter_next. -+// Can only be called once after each call to vchi_msg_iter_next. -+extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter ); -+ -+// Hold the last message returned by vchi_msg_iter_next. -+// Can only be called once after each call to vchi_msg_iter_next. -+extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter, -+ VCHI_HELD_MSG_T *message ); -+ -+// Return information for the next message, and hold it, advancing the iterator. -+extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter, -+ void **data, // } may be NULL -+ uint32_t *msg_size, // } -+ VCHI_HELD_MSG_T *message ); -+ -+ -+/****************************************************************************** -+ Global bulk API -+ *****************************************************************************/ -+ -+// Routine to prepare interface for a transfer from the other side -+extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle, -+ void *data_dst, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *transfer_handle ); -+ -+ -+// Prepare interface for a transfer from the other side into relocatable memory. -+int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T h_dst, -+ uint32_t offset, -+ uint32_t data_size, -+ const VCHI_FLAGS_T flags, -+ void * const bulk_handle ); -+ -+// Routine to queue up data ready for transfer to the other (once they have signalled they are ready) -+extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle, -+ const void *data_src, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *transfer_handle ); -+ -+ -+/****************************************************************************** -+ Configuration plumbing -+ *****************************************************************************/ -+ -+// function prototypes for the different mid layers (the state info gives the different physical connections) -+extern const VCHI_CONNECTION_API_T *single_get_func_table( void ); -+//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void ); -+//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void ); -+ -+// declare all message drivers here -+const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void ); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+extern int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T h_src, -+ uint32_t offset, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *transfer_handle ); -+#endif /* VCHI_H_ */ -+ -+/****************************** End of file **********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h b/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h -new file mode 100644 -index 0000000000000000000000000000000000000000..26bc2d38d725e3c4c24a4cb894da11e65d01625a ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h -@@ -0,0 +1,224 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_CFG_H_ -+#define VCHI_CFG_H_ -+ -+/**************************************************************************************** -+ * Defines in this first section are part of the VCHI API and may be examined by VCHI -+ * services. -+ ***************************************************************************************/ -+ -+/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */ -+/* Really determined by the message driver, and should be available from a run-time call. */ -+#ifndef VCHI_BULK_ALIGN -+# if __VCCOREVER__ >= 0x04000000 -+# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans -+# else -+# define VCHI_BULK_ALIGN 16 -+# endif -+#endif -+ -+/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */ -+/* May be less than or greater than VCHI_BULK_ALIGN */ -+/* Really determined by the message driver, and should be available from a run-time call. */ -+#ifndef VCHI_BULK_GRANULARITY -+# if __VCCOREVER__ >= 0x04000000 -+# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans -+# else -+# define VCHI_BULK_GRANULARITY 16 -+# endif -+#endif -+ -+/* The largest possible message to be queued with vchi_msg_queue. */ -+#ifndef VCHI_MAX_MSG_SIZE -+# if defined VCHI_LOCAL_HOST_PORT -+# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk? -+# else -+# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!! -+# endif -+#endif -+ -+/****************************************************************************************** -+ * Defines below are system configuration options, and should not be used by VCHI services. -+ *****************************************************************************************/ -+ -+/* How many connections can we support? A localhost implementation uses 2 connections, -+ * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW -+ * driver. */ -+#ifndef VCHI_MAX_NUM_CONNECTIONS -+# define VCHI_MAX_NUM_CONNECTIONS 3 -+#endif -+ -+/* How many services can we open per connection? Extending this doesn't cost processing time, just a small -+ * amount of static memory. */ -+#ifndef VCHI_MAX_SERVICES_PER_CONNECTION -+# define VCHI_MAX_SERVICES_PER_CONNECTION 36 -+#endif -+ -+/* Adjust if using a message driver that supports more logical TX channels */ -+#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION -+# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels -+#endif -+ -+/* Adjust if using a message driver that supports more logical RX channels */ -+#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION -+# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI -+#endif -+ -+/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective -+ * receive queue space, less message headers. */ -+#ifndef VCHI_NUM_READ_SLOTS -+# if defined(VCHI_LOCAL_HOST_PORT) -+# define VCHI_NUM_READ_SLOTS 4 -+# else -+# define VCHI_NUM_READ_SLOTS 48 -+# endif -+#endif -+ -+/* Do we utilise overrun facility for receive message slots? Can aid peer transmit -+ * performance. Only define on VideoCore end, talking to host. -+ */ -+//#define VCHI_MSG_RX_OVERRUN -+ -+/* How many transmit slots do we use. Generally don't need many, as the hardware driver -+ * underneath VCHI will usually have its own buffering. */ -+#ifndef VCHI_NUM_WRITE_SLOTS -+# define VCHI_NUM_WRITE_SLOTS 4 -+#endif -+ -+/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots, -+ * then it's taking up too much buffer space, and the peer service will be told to stop -+ * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS -+ * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency -+ * is too high. */ -+#ifndef VCHI_XOFF_THRESHOLD -+# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2) -+#endif -+ -+/* After we've sent an XOFF, the peer will be told to resume transmission once the local -+ * service has dequeued/released enough messages that it's now occupying -+ * VCHI_XON_THRESHOLD slots or fewer. */ -+#ifndef VCHI_XON_THRESHOLD -+# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4) -+#endif -+ -+/* A size below which a bulk transfer omits the handshake completely and always goes -+ * via the message channel, if bulk auxiliary is being sent on that service. (The user -+ * can guarantee this by enabling unaligned transmits). -+ * Not API. */ -+#ifndef VCHI_MIN_BULK_SIZE -+# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 ) -+#endif -+ -+/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between -+ * speed and latency; the smaller the chunk size the better change of messages and other -+ * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not -+ * break transmissions into chunks. -+ */ -+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI -+# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024) -+#endif -+ -+/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode -+ * with multiple-line frames. Only use if the receiver can cope. */ -+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2 -+# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0 -+#endif -+ -+/* How many TX messages can we have pending in our transmit slots. Once exhausted, -+ * vchi_msg_queue will be blocked. */ -+#ifndef VCHI_TX_MSG_QUEUE_SIZE -+# define VCHI_TX_MSG_QUEUE_SIZE 256 -+#endif -+ -+/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing -+ * will be suspended until older messages are dequeued/released. */ -+#ifndef VCHI_RX_MSG_QUEUE_SIZE -+# define VCHI_RX_MSG_QUEUE_SIZE 256 -+#endif -+ -+/* Really should be able to cope if we run out of received message descriptors, by -+ * suspending parsing as the comment above says, but we don't. This sweeps the issue -+ * under the carpet. */ -+#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS -+# undef VCHI_RX_MSG_QUEUE_SIZE -+# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS -+#endif -+ -+/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit -+ * will be blocked. */ -+#ifndef VCHI_TX_BULK_QUEUE_SIZE -+# define VCHI_TX_BULK_QUEUE_SIZE 64 -+#endif -+ -+/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive -+ * will be blocked. */ -+#ifndef VCHI_RX_BULK_QUEUE_SIZE -+# define VCHI_RX_BULK_QUEUE_SIZE 64 -+#endif -+ -+/* A limit on how many outstanding bulk requests we expect the peer to give us. If -+ * the peer asks for more than this, VCHI will fail and assert. The number is determined -+ * by the peer's hardware - it's the number of outstanding requests that can be queued -+ * on all bulk channels. VC3's MPHI peripheral allows 16. */ -+#ifndef VCHI_MAX_PEER_BULK_REQUESTS -+# define VCHI_MAX_PEER_BULK_REQUESTS 32 -+#endif -+ -+/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2 -+ * transmitter on and off. -+ */ -+/*#define VCHI_CCP2TX_MANUAL_POWER*/ -+ -+#ifndef VCHI_CCP2TX_MANUAL_POWER -+ -+/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set -+ * negative for no IDLE. -+ */ -+# ifndef VCHI_CCP2TX_IDLE_TIMEOUT -+# define VCHI_CCP2TX_IDLE_TIMEOUT 5 -+# endif -+ -+/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set -+ * negative for no OFF. -+ */ -+# ifndef VCHI_CCP2TX_OFF_TIMEOUT -+# define VCHI_CCP2TX_OFF_TIMEOUT 1000 -+# endif -+ -+#endif /* VCHI_CCP2TX_MANUAL_POWER */ -+ -+#endif /* VCHI_CFG_H_ */ -+ -+/****************************** End of file **********************************/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h b/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h -new file mode 100644 -index 0000000000000000000000000000000000000000..35dcba4837d492307f3b273acaefa752cdbd6478 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h -@@ -0,0 +1,71 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_CFG_INTERNAL_H_ -+#define VCHI_CFG_INTERNAL_H_ -+ -+/**************************************************************************************** -+ * Control optimisation attempts. -+ ***************************************************************************************/ -+ -+// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second -+#define VCHI_COARSE_LOCKING -+ -+// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx) -+// (only relevant if VCHI_COARSE_LOCKING) -+#define VCHI_ELIDE_BLOCK_EXIT_LOCK -+ -+// Avoid lock on non-blocking peek -+// (only relevant if VCHI_COARSE_LOCKING) -+#define VCHI_AVOID_PEEK_LOCK -+ -+// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation. -+#define VCHI_MULTIPLE_HANDLER_THREADS -+ -+// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash -+// our way through the pool of descriptors. -+#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD -+ -+// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING. -+#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS -+ -+// Don't use message descriptors for TX messages that don't need them -+#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS -+ -+// Nano-locks for multiqueue -+//#define VCHI_MQUEUE_NANOLOCKS -+ -+// Lock-free(er) dequeuing -+//#define VCHI_RX_NANOLOCKS -+ -+#endif /*VCHI_CFG_INTERNAL_H_*/ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_common.h b/drivers/misc/vc04_services/interface/vchi/vchi_common.h -new file mode 100644 -index 0000000000000000000000000000000000000000..d535a72970d3f1ee63d2038550db8f4e43589c72 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_common.h -@@ -0,0 +1,175 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_COMMON_H_ -+#define VCHI_COMMON_H_ -+ -+ -+//flags used when sending messages (must be bitmapped) -+typedef enum -+{ -+ VCHI_FLAGS_NONE = 0x0, -+ VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side) -+ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go -+ VCHI_FLAGS_ALLOW_PARTIAL = 0x8, -+ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10, -+ VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20, -+ -+ VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only -+ VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only -+ VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only -+ VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only -+ VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only -+ VCHI_FLAGS_INTERNAL = 0xFF0000 -+} VCHI_FLAGS_T; -+ -+// constants for vchi_crc_control() -+typedef enum { -+ VCHI_CRC_NOTHING = -1, -+ VCHI_CRC_PER_SERVICE = 0, -+ VCHI_CRC_EVERYTHING = 1, -+} VCHI_CRC_CONTROL_T; -+ -+//callback reasons when an event occurs on a service -+typedef enum -+{ -+ VCHI_CALLBACK_REASON_MIN, -+ -+ //This indicates that there is data available -+ //handle is the msg id that was transmitted with the data -+ // When a message is received and there was no FULL message available previously, send callback -+ // Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails -+ VCHI_CALLBACK_MSG_AVAILABLE, -+ VCHI_CALLBACK_MSG_SENT, -+ VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented -+ -+ // This indicates that a transfer from the other side has completed -+ VCHI_CALLBACK_BULK_RECEIVED, -+ //This indicates that data queued up to be sent has now gone -+ //handle is the msg id that was used when sending the data -+ VCHI_CALLBACK_BULK_SENT, -+ VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented -+ VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented -+ -+ VCHI_CALLBACK_SERVICE_CLOSED, -+ -+ // this side has sent XOFF to peer due to lack of data consumption by service -+ // (suggests the service may need to take some recovery action if it has -+ // been deliberately holding off consuming data) -+ VCHI_CALLBACK_SENT_XOFF, -+ VCHI_CALLBACK_SENT_XON, -+ -+ // indicates that a bulk transfer has finished reading the source buffer -+ VCHI_CALLBACK_BULK_DATA_READ, -+ -+ // power notification events (currently host side only) -+ VCHI_CALLBACK_PEER_OFF, -+ VCHI_CALLBACK_PEER_SUSPENDED, -+ VCHI_CALLBACK_PEER_ON, -+ VCHI_CALLBACK_PEER_RESUMED, -+ VCHI_CALLBACK_FORCED_POWER_OFF, -+ -+#ifdef USE_VCHIQ_ARM -+ // some extra notifications provided by vchiq_arm -+ VCHI_CALLBACK_SERVICE_OPENED, -+ VCHI_CALLBACK_BULK_RECEIVE_ABORTED, -+ VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, -+#endif -+ -+ VCHI_CALLBACK_REASON_MAX -+} VCHI_CALLBACK_REASON_T; -+ -+// service control options -+typedef enum -+{ -+ VCHI_SERVICE_OPTION_MIN, -+ -+ VCHI_SERVICE_OPTION_TRACE, -+ VCHI_SERVICE_OPTION_SYNCHRONOUS, -+ -+ VCHI_SERVICE_OPTION_MAX -+} VCHI_SERVICE_OPTION_T; -+ -+ -+//Callback used by all services / bulk transfers -+typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param -+ VCHI_CALLBACK_REASON_T reason, -+ void *handle ); //for transmitting msg's only -+ -+ -+ -+/* -+ * Define vector struct for scatter-gather (vector) operations -+ * Vectors can be nested - if a vector element has negative length, then -+ * the data pointer is treated as pointing to another vector array, with -+ * '-vec_len' elements. Thus to append a header onto an existing vector, -+ * you can do this: -+ * -+ * void foo(const VCHI_MSG_VECTOR_T *v, int n) -+ * { -+ * VCHI_MSG_VECTOR_T nv[2]; -+ * nv[0].vec_base = my_header; -+ * nv[0].vec_len = sizeof my_header; -+ * nv[1].vec_base = v; -+ * nv[1].vec_len = -n; -+ * ... -+ * -+ */ -+typedef struct vchi_msg_vector { -+ const void *vec_base; -+ int32_t vec_len; -+} VCHI_MSG_VECTOR_T; -+ -+// Opaque type for a connection API -+typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T; -+ -+// Opaque type for a message driver -+typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T; -+ -+ -+// Iterator structure for reading ahead through received message queue. Allocated by client, -+// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only. -+// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead - -+// will not proceed to messages received since. Behaviour is undefined if an iterator -+// is used again after messages for that service are removed/dequeued by any -+// means other than vchi_msg_iter_... calls on the iterator itself. -+typedef struct { -+ struct opaque_vchi_service_t *service; -+ void *last; -+ void *next; -+ void *remove; -+} VCHI_MSG_ITER_T; -+ -+ -+#endif // VCHI_COMMON_H_ -diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_mh.h b/drivers/misc/vc04_services/interface/vchi/vchi_mh.h -new file mode 100644 -index 0000000000000000000000000000000000000000..198bd076b6668d729e0b6619a1f38eb927a2398b ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchi/vchi_mh.h -@@ -0,0 +1,42 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHI_MH_H_ -+#define VCHI_MH_H_ -+ -+#include -+ -+typedef int32_t VCHI_MEM_HANDLE_T; -+#define VCHI_MEM_HANDLE_INVALID 0 -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h -new file mode 100644 -index 0000000000000000000000000000000000000000..ad398bae6ee4c3d64fc1a37808398397a9a0fefe ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h -@@ -0,0 +1,40 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_VCHIQ_H -+#define VCHIQ_VCHIQ_H -+ -+#include "vchiq_if.h" -+#include "vchiq_util.h" -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h -new file mode 100644 -index 0000000000000000000000000000000000000000..7ea5c64d5343d43786903161518ef1ce0287e27d ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h -@@ -0,0 +1,42 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_2835_H -+#define VCHIQ_2835_H -+ -+#include "vchiq_pagelist.h" -+ -+#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0 -+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 -+ -+#endif /* VCHIQ_2835_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -new file mode 100644 -index 0000000000000000000000000000000000000000..4cb5bff237288a4ee80d80ba53a2efe96f2749f3 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -0,0 +1,586 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define dmac_map_area __glue(_CACHE,_dma_map_area) -+#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) -+ -+extern void dmac_map_area(const void *, size_t, int); -+extern void dmac_unmap_area(const void *, size_t, int); -+ -+#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) -+ -+#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) -+ -+#include "vchiq_arm.h" -+#include "vchiq_2835.h" -+#include "vchiq_connected.h" -+#include "vchiq_killable.h" -+ -+#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) -+ -+#define BELL0 0x00 -+#define BELL2 0x08 -+ -+typedef struct vchiq_2835_state_struct { -+ int inited; -+ VCHIQ_ARM_STATE_T arm_state; -+} VCHIQ_2835_ARM_STATE_T; -+ -+static void __iomem *g_regs; -+static unsigned int g_cache_line_size = sizeof(CACHE_LINE_SIZE); -+static unsigned int g_fragments_size; -+static char *g_fragments_base; -+static char *g_free_fragments; -+static struct semaphore g_free_fragments_sema; -+static unsigned long g_virt_to_bus_offset; -+ -+extern int vchiq_arm_log_level; -+ -+static DEFINE_SEMAPHORE(g_free_fragments_mutex); -+ -+static irqreturn_t -+vchiq_doorbell_irq(int irq, void *dev_id); -+ -+static int -+create_pagelist(char __user *buf, size_t count, unsigned short type, -+ struct task_struct *task, PAGELIST_T ** ppagelist); -+ -+static void -+free_pagelist(PAGELIST_T *pagelist, int actual); -+ -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) -+{ -+ struct device *dev = &pdev->dev; -+ struct rpi_firmware *fw = platform_get_drvdata(pdev); -+ VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; -+ struct resource *res; -+ void *slot_mem; -+ dma_addr_t slot_phys; -+ u32 channelbase; -+ int slot_mem_size, frag_mem_size; -+ int err, irq, i; -+ -+ g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); -+ -+ (void)of_property_read_u32(dev->of_node, "cache-line-size", -+ &g_cache_line_size); -+ g_fragments_size = 2 * g_cache_line_size; -+ -+ /* Allocate space for the channels in coherent memory */ -+ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); -+ frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS); -+ -+ slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, -+ &slot_phys, GFP_KERNEL); -+ if (!slot_mem) { -+ dev_err(dev, "could not allocate DMA memory\n"); -+ return -ENOMEM; -+ } -+ -+ WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); -+ -+ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); -+ if (!vchiq_slot_zero) -+ return -EINVAL; -+ -+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = -+ (int)slot_phys + slot_mem_size; -+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = -+ MAX_FRAGMENTS; -+ -+ g_fragments_base = (char *)slot_mem + slot_mem_size; -+ slot_mem_size += frag_mem_size; -+ -+ g_free_fragments = g_fragments_base; -+ for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { -+ *(char **)&g_fragments_base[i*g_fragments_size] = -+ &g_fragments_base[(i + 1)*g_fragments_size]; -+ } -+ *(char **)&g_fragments_base[i * g_fragments_size] = NULL; -+ sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); -+ -+ if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) -+ return -EINVAL; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ g_regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(g_regs)) -+ return PTR_ERR(g_regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "failed to get IRQ\n"); -+ return irq; -+ } -+ -+ err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, -+ "VCHIQ doorbell", state); -+ if (err) { -+ dev_err(dev, "failed to register irq=%d\n", irq); -+ return err; -+ } -+ -+ /* Send the base address of the slots to VideoCore */ -+ channelbase = slot_phys; -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT, -+ &channelbase, sizeof(channelbase)); -+ if (err || channelbase) { -+ dev_err(dev, "failed to set channelbase\n"); -+ return err ? : -ENXIO; -+ } -+ -+ vchiq_log_info(vchiq_arm_log_level, -+ "vchiq_init - done (slots %x, phys %pad)", -+ (unsigned int)vchiq_slot_zero, &slot_phys); -+ -+ vchiq_call_connected_callbacks(); -+ -+ return 0; -+} -+ -+VCHIQ_STATUS_T -+vchiq_platform_init_state(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ state->platform_state = kzalloc(sizeof(VCHIQ_2835_ARM_STATE_T), GFP_KERNEL); -+ ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 1; -+ status = vchiq_arm_init_state(state, &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state); -+ if(status != VCHIQ_SUCCESS) -+ { -+ ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 0; -+ } -+ return status; -+} -+ -+VCHIQ_ARM_STATE_T* -+vchiq_platform_get_arm_state(VCHIQ_STATE_T *state) -+{ -+ if(!((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited) -+ { -+ BUG(); -+ } -+ return &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state; -+} -+ -+void -+remote_event_signal(REMOTE_EVENT_T *event) -+{ -+ wmb(); -+ -+ event->fired = 1; -+ -+ dsb(); /* data barrier operation */ -+ -+ if (event->armed) -+ writel(0, g_regs + BELL2); /* trigger vc interrupt */ -+} -+ -+int -+vchiq_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ((uint32_t)src < TASK_SIZE) { -+ return copy_from_user(dst, src, size); -+ } else { -+ memcpy(dst, src, size); -+ return 0; -+ } -+} -+ -+VCHIQ_STATUS_T -+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, -+ void *offset, int size, int dir) -+{ -+ PAGELIST_T *pagelist; -+ int ret; -+ -+ WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID); -+ -+ ret = create_pagelist((char __user *)offset, size, -+ (dir == VCHIQ_BULK_RECEIVE) -+ ? PAGELIST_READ -+ : PAGELIST_WRITE, -+ current, -+ &pagelist); -+ if (ret != 0) -+ return VCHIQ_ERROR; -+ -+ bulk->handle = memhandle; -+ bulk->data = VCHIQ_ARM_ADDRESS(pagelist); -+ -+ /* Store the pagelist address in remote_data, which isn't used by the -+ slave. */ -+ bulk->remote_data = pagelist; -+ -+ return VCHIQ_SUCCESS; -+} -+ -+void -+vchiq_complete_bulk(VCHIQ_BULK_T *bulk) -+{ -+ if (bulk && bulk->remote_data && bulk->actual) -+ free_pagelist((PAGELIST_T *)bulk->remote_data, bulk->actual); -+} -+ -+void -+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk) -+{ -+ /* -+ * This should only be called on the master (VideoCore) side, but -+ * provide an implementation to avoid the need for ifdefery. -+ */ -+ BUG(); -+} -+ -+void -+vchiq_dump_platform_state(void *dump_context) -+{ -+ char buf[80]; -+ int len; -+ len = snprintf(buf, sizeof(buf), -+ " Platform: 2835 (VC master)"); -+ vchiq_dump(dump_context, buf, len + 1); -+} -+ -+VCHIQ_STATUS_T -+vchiq_platform_suspend(VCHIQ_STATE_T *state) -+{ -+ return VCHIQ_ERROR; -+} -+ -+VCHIQ_STATUS_T -+vchiq_platform_resume(VCHIQ_STATE_T *state) -+{ -+ return VCHIQ_SUCCESS; -+} -+ -+void -+vchiq_platform_paused(VCHIQ_STATE_T *state) -+{ -+} -+ -+void -+vchiq_platform_resumed(VCHIQ_STATE_T *state) -+{ -+} -+ -+int -+vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state) -+{ -+ return 1; // autosuspend not supported - videocore always wanted -+} -+ -+int -+vchiq_platform_use_suspend_timer(void) -+{ -+ return 0; -+} -+void -+vchiq_dump_platform_use_state(VCHIQ_STATE_T *state) -+{ -+ vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use"); -+} -+void -+vchiq_platform_handle_timeout(VCHIQ_STATE_T *state) -+{ -+ (void)state; -+} -+/* -+ * Local functions -+ */ -+ -+static irqreturn_t -+vchiq_doorbell_irq(int irq, void *dev_id) -+{ -+ VCHIQ_STATE_T *state = dev_id; -+ irqreturn_t ret = IRQ_NONE; -+ unsigned int status; -+ -+ /* Read (and clear) the doorbell */ -+ status = readl(g_regs + BELL0); -+ -+ if (status & 0x4) { /* Was the doorbell rung? */ -+ remote_event_pollall(state); -+ ret = IRQ_HANDLED; -+ } -+ -+ return ret; -+} -+ -+/* There is a potential problem with partial cache lines (pages?) -+** at the ends of the block when reading. If the CPU accessed anything in -+** the same line (page?) then it may have pulled old data into the cache, -+** obscuring the new data underneath. We can solve this by transferring the -+** partial cache lines separately, and allowing the ARM to copy into the -+** cached area. -+ -+** N.B. This implementation plays slightly fast and loose with the Linux -+** driver programming rules, e.g. its use of dmac_map_area instead of -+** dma_map_single, but it isn't a multi-platform driver and it benefits -+** from increased speed as a result. -+*/ -+ -+static int -+create_pagelist(char __user *buf, size_t count, unsigned short type, -+ struct task_struct *task, PAGELIST_T ** ppagelist) -+{ -+ PAGELIST_T *pagelist; -+ struct page **pages; -+ unsigned long *addrs; -+ unsigned int num_pages, offset, i; -+ char *addr, *base_addr, *next_addr; -+ int run, addridx, actual_pages; -+ unsigned long *need_release; -+ -+ offset = (unsigned int)buf & (PAGE_SIZE - 1); -+ num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; -+ -+ *ppagelist = NULL; -+ -+ /* Allocate enough storage to hold the page pointers and the page -+ ** list -+ */ -+ pagelist = kmalloc(sizeof(PAGELIST_T) + -+ (num_pages * sizeof(unsigned long)) + -+ sizeof(unsigned long) + -+ (num_pages * sizeof(pages[0])), -+ GFP_KERNEL); -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "create_pagelist - %x", (unsigned int)pagelist); -+ if (!pagelist) -+ return -ENOMEM; -+ -+ addrs = pagelist->addrs; -+ need_release = (unsigned long *)(addrs + num_pages); -+ pages = (struct page **)(addrs + num_pages + 1); -+ -+ if (is_vmalloc_addr(buf)) { -+ int dir = (type == PAGELIST_WRITE) ? -+ DMA_TO_DEVICE : DMA_FROM_DEVICE; -+ unsigned long length = count; -+ unsigned int off = offset; -+ -+ for (actual_pages = 0; actual_pages < num_pages; -+ actual_pages++) { -+ struct page *pg = vmalloc_to_page(buf + (actual_pages * -+ PAGE_SIZE)); -+ size_t bytes = PAGE_SIZE - off; -+ -+ if (bytes > length) -+ bytes = length; -+ pages[actual_pages] = pg; -+ dmac_map_area(page_address(pg) + off, bytes, dir); -+ length -= bytes; -+ off = 0; -+ } -+ *need_release = 0; /* do not try and release vmalloc pages */ -+ } else { -+ down_read(&task->mm->mmap_sem); -+ actual_pages = get_user_pages( -+ (unsigned long)buf & ~(PAGE_SIZE - 1), -+ num_pages, -+ (type == PAGELIST_READ) /*Write */ , -+ 0 /*Force */ , -+ pages, -+ NULL /*vmas */); -+ up_read(&task->mm->mmap_sem); -+ -+ if (actual_pages != num_pages) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "create_pagelist - only %d/%d pages locked", -+ actual_pages, -+ num_pages); -+ -+ /* This is probably due to the process being killed */ -+ while (actual_pages > 0) -+ { -+ actual_pages--; -+ put_page(pages[actual_pages]); -+ } -+ kfree(pagelist); -+ if (actual_pages == 0) -+ actual_pages = -ENOMEM; -+ return actual_pages; -+ } -+ *need_release = 1; /* release user pages */ -+ } -+ -+ pagelist->length = count; -+ pagelist->type = type; -+ pagelist->offset = offset; -+ -+ /* Group the pages into runs of contiguous pages */ -+ -+ base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0])); -+ next_addr = base_addr + PAGE_SIZE; -+ addridx = 0; -+ run = 0; -+ -+ for (i = 1; i < num_pages; i++) { -+ addr = VCHIQ_ARM_ADDRESS(page_address(pages[i])); -+ if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) { -+ next_addr += PAGE_SIZE; -+ run++; -+ } else { -+ addrs[addridx] = (unsigned long)base_addr + run; -+ addridx++; -+ base_addr = addr; -+ next_addr = addr + PAGE_SIZE; -+ run = 0; -+ } -+ } -+ -+ addrs[addridx] = (unsigned long)base_addr + run; -+ addridx++; -+ -+ /* Partial cache lines (fragments) require special measures */ -+ if ((type == PAGELIST_READ) && -+ ((pagelist->offset & (g_cache_line_size - 1)) || -+ ((pagelist->offset + pagelist->length) & -+ (g_cache_line_size - 1)))) { -+ char *fragments; -+ -+ if (down_interruptible(&g_free_fragments_sema) != 0) { -+ kfree(pagelist); -+ return -EINTR; -+ } -+ -+ WARN_ON(g_free_fragments == NULL); -+ -+ down(&g_free_fragments_mutex); -+ fragments = g_free_fragments; -+ WARN_ON(fragments == NULL); -+ g_free_fragments = *(char **) g_free_fragments; -+ up(&g_free_fragments_mutex); -+ pagelist->type = PAGELIST_READ_WITH_FRAGMENTS + -+ (fragments - g_fragments_base) / g_fragments_size; -+ } -+ -+ dmac_flush_range(pagelist, addrs + num_pages); -+ -+ *ppagelist = pagelist; -+ -+ return 0; -+} -+ -+static void -+free_pagelist(PAGELIST_T *pagelist, int actual) -+{ -+ unsigned long *need_release; -+ struct page **pages; -+ unsigned int num_pages, i; -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "free_pagelist - %x, %d", (unsigned int)pagelist, actual); -+ -+ num_pages = -+ (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / -+ PAGE_SIZE; -+ -+ need_release = (unsigned long *)(pagelist->addrs + num_pages); -+ pages = (struct page **)(pagelist->addrs + num_pages + 1); -+ -+ /* Deal with any partial cache lines (fragments) */ -+ if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) { -+ char *fragments = g_fragments_base + -+ (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * -+ g_fragments_size; -+ int head_bytes, tail_bytes; -+ head_bytes = (g_cache_line_size - pagelist->offset) & -+ (g_cache_line_size - 1); -+ tail_bytes = (pagelist->offset + actual) & -+ (g_cache_line_size - 1); -+ -+ if ((actual >= 0) && (head_bytes != 0)) { -+ if (head_bytes > actual) -+ head_bytes = actual; -+ -+ memcpy((char *)page_address(pages[0]) + -+ pagelist->offset, -+ fragments, -+ head_bytes); -+ } -+ if ((actual >= 0) && (head_bytes < actual) && -+ (tail_bytes != 0)) { -+ memcpy((char *)page_address(pages[num_pages - 1]) + -+ ((pagelist->offset + actual) & -+ (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)), -+ fragments + g_cache_line_size, -+ tail_bytes); -+ } -+ -+ down(&g_free_fragments_mutex); -+ *(char **)fragments = g_free_fragments; -+ g_free_fragments = fragments; -+ up(&g_free_fragments_mutex); -+ up(&g_free_fragments_sema); -+ } -+ -+ if (*need_release) { -+ unsigned int length = pagelist->length; -+ unsigned int offset = pagelist->offset; -+ -+ for (i = 0; i < num_pages; i++) { -+ struct page *pg = pages[i]; -+ -+ if (pagelist->type != PAGELIST_WRITE) { -+ unsigned int bytes = PAGE_SIZE - offset; -+ -+ if (bytes > length) -+ bytes = length; -+ dmac_unmap_area(page_address(pg) + offset, -+ bytes, DMA_FROM_DEVICE); -+ length -= bytes; -+ offset = 0; -+ set_page_dirty(pg); -+ } -+ put_page(pg); -+ } -+ } -+ -+ kfree(pagelist); -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -new file mode 100644 -index 0000000000000000000000000000000000000000..2dfccafc765b2211bd7b8ead5e9e52bd8fe13913 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -0,0 +1,2921 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "vchiq_core.h" -+#include "vchiq_ioctl.h" -+#include "vchiq_arm.h" -+#include "vchiq_debugfs.h" -+#include "vchiq_killable.h" -+ -+#define DEVICE_NAME "vchiq" -+ -+/* Override the default prefix, which would be vchiq_arm (from the filename) */ -+#undef MODULE_PARAM_PREFIX -+#define MODULE_PARAM_PREFIX DEVICE_NAME "." -+ -+#define VCHIQ_MINOR 0 -+ -+/* Some per-instance constants */ -+#define MAX_COMPLETIONS 128 -+#define MAX_SERVICES 64 -+#define MAX_ELEMENTS 8 -+#define MSG_QUEUE_SIZE 128 -+ -+#define KEEPALIVE_VER 1 -+#define KEEPALIVE_VER_MIN KEEPALIVE_VER -+ -+/* Run time control of log level, based on KERN_XXX level. */ -+int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT; -+int vchiq_susp_log_level = VCHIQ_LOG_ERROR; -+ -+#define SUSPEND_TIMER_TIMEOUT_MS 100 -+#define SUSPEND_RETRY_TIMER_TIMEOUT_MS 1000 -+ -+#define VC_SUSPEND_NUM_OFFSET 3 /* number of values before idle which are -ve */ -+static const char *const suspend_state_names[] = { -+ "VC_SUSPEND_FORCE_CANCELED", -+ "VC_SUSPEND_REJECTED", -+ "VC_SUSPEND_FAILED", -+ "VC_SUSPEND_IDLE", -+ "VC_SUSPEND_REQUESTED", -+ "VC_SUSPEND_IN_PROGRESS", -+ "VC_SUSPEND_SUSPENDED" -+}; -+#define VC_RESUME_NUM_OFFSET 1 /* number of values before idle which are -ve */ -+static const char *const resume_state_names[] = { -+ "VC_RESUME_FAILED", -+ "VC_RESUME_IDLE", -+ "VC_RESUME_REQUESTED", -+ "VC_RESUME_IN_PROGRESS", -+ "VC_RESUME_RESUMED" -+}; -+/* The number of times we allow force suspend to timeout before actually -+** _forcing_ suspend. This is to cater for SW which fails to release vchiq -+** correctly - we don't want to prevent ARM suspend indefinitely in this case. -+*/ -+#define FORCE_SUSPEND_FAIL_MAX 8 -+ -+/* The time in ms allowed for videocore to go idle when force suspend has been -+ * requested */ -+#define FORCE_SUSPEND_TIMEOUT_MS 200 -+ -+ -+static void suspend_timer_callback(unsigned long context); -+ -+ -+typedef struct user_service_struct { -+ VCHIQ_SERVICE_T *service; -+ void *userdata; -+ VCHIQ_INSTANCE_T instance; -+ char is_vchi; -+ char dequeue_pending; -+ char close_pending; -+ int message_available_pos; -+ int msg_insert; -+ int msg_remove; -+ struct semaphore insert_event; -+ struct semaphore remove_event; -+ struct semaphore close_event; -+ VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE]; -+} USER_SERVICE_T; -+ -+struct bulk_waiter_node { -+ struct bulk_waiter bulk_waiter; -+ int pid; -+ struct list_head list; -+}; -+ -+struct vchiq_instance_struct { -+ VCHIQ_STATE_T *state; -+ VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS]; -+ int completion_insert; -+ int completion_remove; -+ struct semaphore insert_event; -+ struct semaphore remove_event; -+ struct mutex completion_mutex; -+ -+ int connected; -+ int closing; -+ int pid; -+ int mark; -+ int use_close_delivered; -+ int trace; -+ -+ struct list_head bulk_waiter_list; -+ struct mutex bulk_waiter_list_mutex; -+ -+ VCHIQ_DEBUGFS_NODE_T debugfs_node; -+}; -+ -+typedef struct dump_context_struct { -+ char __user *buf; -+ size_t actual; -+ size_t space; -+ loff_t offset; -+} DUMP_CONTEXT_T; -+ -+static struct cdev vchiq_cdev; -+static dev_t vchiq_devid; -+static VCHIQ_STATE_T g_state; -+static struct class *vchiq_class; -+static struct device *vchiq_dev; -+static DEFINE_SPINLOCK(msg_queue_spinlock); -+ -+static const char *const ioctl_names[] = { -+ "CONNECT", -+ "SHUTDOWN", -+ "CREATE_SERVICE", -+ "REMOVE_SERVICE", -+ "QUEUE_MESSAGE", -+ "QUEUE_BULK_TRANSMIT", -+ "QUEUE_BULK_RECEIVE", -+ "AWAIT_COMPLETION", -+ "DEQUEUE_MESSAGE", -+ "GET_CLIENT_ID", -+ "GET_CONFIG", -+ "CLOSE_SERVICE", -+ "USE_SERVICE", -+ "RELEASE_SERVICE", -+ "SET_SERVICE_OPTION", -+ "DUMP_PHYS_MEM", -+ "LIB_VERSION", -+ "CLOSE_DELIVERED" -+}; -+ -+vchiq_static_assert((sizeof(ioctl_names)/sizeof(ioctl_names[0])) == -+ (VCHIQ_IOC_MAX + 1)); -+ -+static void -+dump_phys_mem(void *virt_addr, uint32_t num_bytes); -+ -+/**************************************************************************** -+* -+* add_completion -+* -+***************************************************************************/ -+ -+static VCHIQ_STATUS_T -+add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service, -+ void *bulk_userdata) -+{ -+ VCHIQ_COMPLETION_DATA_T *completion; -+ int insert; -+ DEBUG_INITIALISE(g_state.local) -+ -+ insert = instance->completion_insert; -+ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { -+ /* Out of space - wait for the client */ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ vchiq_log_trace(vchiq_arm_log_level, -+ "add_completion - completion queue full"); -+ DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); -+ -+ if (down_interruptible(&instance->remove_event) != 0) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback interrupted"); -+ return VCHIQ_RETRY; -+ } -+ -+ if (instance->closing) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback closing"); -+ return VCHIQ_SUCCESS; -+ } -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ } -+ -+ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; -+ -+ completion->header = header; -+ completion->reason = reason; -+ /* N.B. service_userdata is updated while processing AWAIT_COMPLETION */ -+ completion->service_userdata = user_service->service; -+ completion->bulk_userdata = bulk_userdata; -+ -+ if (reason == VCHIQ_SERVICE_CLOSED) { -+ /* Take an extra reference, to be held until -+ this CLOSED notification is delivered. */ -+ lock_service(user_service->service); -+ if (instance->use_close_delivered) -+ user_service->close_pending = 1; -+ } -+ -+ /* A write barrier is needed here to ensure that the entire completion -+ record is written out before the insert point. */ -+ wmb(); -+ -+ if (reason == VCHIQ_MESSAGE_AVAILABLE) -+ user_service->message_available_pos = insert; -+ -+ instance->completion_insert = ++insert; -+ -+ up(&instance->insert_event); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+/**************************************************************************** -+* -+* service_callback -+* -+***************************************************************************/ -+ -+static VCHIQ_STATUS_T -+service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, -+ VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) -+{ -+ /* How do we ensure the callback goes to the right client? -+ ** The service_user data points to a USER_SERVICE_T record containing -+ ** the original callback and the user state structure, which contains a -+ ** circular buffer for completion records. -+ */ -+ USER_SERVICE_T *user_service; -+ VCHIQ_SERVICE_T *service; -+ VCHIQ_INSTANCE_T instance; -+ int skip_completion = 0; -+ DEBUG_INITIALISE(g_state.local) -+ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ -+ service = handle_to_service(handle); -+ BUG_ON(!service); -+ user_service = (USER_SERVICE_T *)service->base.userdata; -+ instance = user_service->instance; -+ -+ if (!instance || instance->closing) -+ return VCHIQ_SUCCESS; -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "service_callback - service %lx(%d,%p), reason %d, header %lx, " -+ "instance %lx, bulk_userdata %lx", -+ (unsigned long)user_service, -+ service->localport, user_service->userdata, -+ reason, (unsigned long)header, -+ (unsigned long)instance, (unsigned long)bulk_userdata); -+ -+ if (header && user_service->is_vchi) { -+ spin_lock(&msg_queue_spinlock); -+ while (user_service->msg_insert == -+ (user_service->msg_remove + MSG_QUEUE_SIZE)) { -+ spin_unlock(&msg_queue_spinlock); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ DEBUG_COUNT(MSG_QUEUE_FULL_COUNT); -+ vchiq_log_trace(vchiq_arm_log_level, -+ "service_callback - msg queue full"); -+ /* If there is no MESSAGE_AVAILABLE in the completion -+ ** queue, add one -+ */ -+ if ((user_service->message_available_pos - -+ instance->completion_remove) < 0) { -+ VCHIQ_STATUS_T status; -+ vchiq_log_info(vchiq_arm_log_level, -+ "Inserting extra MESSAGE_AVAILABLE"); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ status = add_completion(instance, reason, -+ NULL, user_service, bulk_userdata); -+ if (status != VCHIQ_SUCCESS) { -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return status; -+ } -+ } -+ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ if (down_interruptible(&user_service->remove_event) -+ != 0) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback interrupted"); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_RETRY; -+ } else if (instance->closing) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "service_callback closing"); -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_ERROR; -+ } -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ spin_lock(&msg_queue_spinlock); -+ } -+ -+ user_service->msg_queue[user_service->msg_insert & -+ (MSG_QUEUE_SIZE - 1)] = header; -+ user_service->msg_insert++; -+ -+ /* If there is a thread waiting in DEQUEUE_MESSAGE, or if -+ ** there is a MESSAGE_AVAILABLE in the completion queue then -+ ** bypass the completion queue. -+ */ -+ if (((user_service->message_available_pos - -+ instance->completion_remove) >= 0) || -+ user_service->dequeue_pending) { -+ user_service->dequeue_pending = 0; -+ skip_completion = 1; -+ } -+ -+ spin_unlock(&msg_queue_spinlock); -+ -+ up(&user_service->insert_event); -+ -+ header = NULL; -+ } -+ -+ if (skip_completion) { -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_SUCCESS; -+ } -+ -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ -+ return add_completion(instance, reason, header, user_service, -+ bulk_userdata); -+} -+ -+/**************************************************************************** -+* -+* user_service_free -+* -+***************************************************************************/ -+static void -+user_service_free(void *userdata) -+{ -+ kfree(userdata); -+} -+ -+/**************************************************************************** -+* -+* close_delivered -+* -+***************************************************************************/ -+static void close_delivered(USER_SERVICE_T *user_service) -+{ -+ vchiq_log_info(vchiq_arm_log_level, -+ "close_delivered(handle=%x)", -+ user_service->service->handle); -+ -+ if (user_service->close_pending) { -+ /* Allow the underlying service to be culled */ -+ unlock_service(user_service->service); -+ -+ /* Wake the user-thread blocked in close_ or remove_service */ -+ up(&user_service->close_event); -+ -+ user_service->close_pending = 0; -+ } -+} -+ -+/**************************************************************************** -+* -+* vchiq_ioctl -+* -+***************************************************************************/ -+static long -+vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ VCHIQ_INSTANCE_T instance = file->private_data; -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ VCHIQ_SERVICE_T *service = NULL; -+ long ret = 0; -+ int i, rc; -+ DEBUG_INITIALISE(g_state.local) -+ -+ vchiq_log_trace(vchiq_arm_log_level, -+ "vchiq_ioctl - instance %x, cmd %s, arg %lx", -+ (unsigned int)instance, -+ ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && -+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ? -+ ioctl_names[_IOC_NR(cmd)] : "", arg); -+ -+ switch (cmd) { -+ case VCHIQ_IOC_SHUTDOWN: -+ if (!instance->connected) -+ break; -+ -+ /* Remove all services */ -+ i = 0; -+ while ((service = next_service_by_instance(instance->state, -+ instance, &i)) != NULL) { -+ status = vchiq_remove_service(service->handle); -+ unlock_service(service); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ service = NULL; -+ -+ if (status == VCHIQ_SUCCESS) { -+ /* Wake the completion thread and ask it to exit */ -+ instance->closing = 1; -+ up(&instance->insert_event); -+ } -+ -+ break; -+ -+ case VCHIQ_IOC_CONNECT: -+ if (instance->connected) { -+ ret = -EINVAL; -+ break; -+ } -+ rc = mutex_lock_interruptible(&instance->state->mutex); -+ if (rc != 0) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "vchiq: connect: could not lock mutex for " -+ "state %d: %d", -+ instance->state->id, rc); -+ ret = -EINTR; -+ break; -+ } -+ status = vchiq_connect_internal(instance->state, instance); -+ mutex_unlock(&instance->state->mutex); -+ -+ if (status == VCHIQ_SUCCESS) -+ instance->connected = 1; -+ else -+ vchiq_log_error(vchiq_arm_log_level, -+ "vchiq: could not connect: %d", status); -+ break; -+ -+ case VCHIQ_IOC_CREATE_SERVICE: { -+ VCHIQ_CREATE_SERVICE_T args; -+ USER_SERVICE_T *user_service = NULL; -+ void *userdata; -+ int srvstate; -+ -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL); -+ if (!user_service) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ if (args.is_open) { -+ if (!instance->connected) { -+ ret = -ENOTCONN; -+ kfree(user_service); -+ break; -+ } -+ srvstate = VCHIQ_SRVSTATE_OPENING; -+ } else { -+ srvstate = -+ instance->connected ? -+ VCHIQ_SRVSTATE_LISTENING : -+ VCHIQ_SRVSTATE_HIDDEN; -+ } -+ -+ userdata = args.params.userdata; -+ args.params.callback = service_callback; -+ args.params.userdata = user_service; -+ service = vchiq_add_service_internal( -+ instance->state, -+ &args.params, srvstate, -+ instance, user_service_free); -+ -+ if (service != NULL) { -+ user_service->service = service; -+ user_service->userdata = userdata; -+ user_service->instance = instance; -+ user_service->is_vchi = (args.is_vchi != 0); -+ user_service->dequeue_pending = 0; -+ user_service->close_pending = 0; -+ user_service->message_available_pos = -+ instance->completion_remove - 1; -+ user_service->msg_insert = 0; -+ user_service->msg_remove = 0; -+ sema_init(&user_service->insert_event, 0); -+ sema_init(&user_service->remove_event, 0); -+ sema_init(&user_service->close_event, 0); -+ -+ if (args.is_open) { -+ status = vchiq_open_service_internal -+ (service, instance->pid); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_remove_service(service->handle); -+ service = NULL; -+ ret = (status == VCHIQ_RETRY) ? -+ -EINTR : -EIO; -+ break; -+ } -+ } -+ -+ if (copy_to_user((void __user *) -+ &(((VCHIQ_CREATE_SERVICE_T __user *) -+ arg)->handle), -+ (const void *)&service->handle, -+ sizeof(service->handle)) != 0) { -+ ret = -EFAULT; -+ vchiq_remove_service(service->handle); -+ } -+ -+ service = NULL; -+ } else { -+ ret = -EEXIST; -+ kfree(user_service); -+ } -+ } break; -+ -+ case VCHIQ_IOC_CLOSE_SERVICE: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_service_for_instance(instance, handle); -+ if (service != NULL) { -+ USER_SERVICE_T *user_service = -+ (USER_SERVICE_T *)service->base.userdata; -+ /* close_pending is false on first entry, and when the -+ wait in vchiq_close_service has been interrupted. */ -+ if (!user_service->close_pending) { -+ status = vchiq_close_service(service->handle); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ -+ /* close_pending is true once the underlying service -+ has been closed until the client library calls the -+ CLOSE_DELIVERED ioctl, signalling close_event. */ -+ if (user_service->close_pending && -+ down_interruptible(&user_service->close_event)) -+ status = VCHIQ_RETRY; -+ } -+ else -+ ret = -EINVAL; -+ } break; -+ -+ case VCHIQ_IOC_REMOVE_SERVICE: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_service_for_instance(instance, handle); -+ if (service != NULL) { -+ USER_SERVICE_T *user_service = -+ (USER_SERVICE_T *)service->base.userdata; -+ /* close_pending is false on first entry, and when the -+ wait in vchiq_close_service has been interrupted. */ -+ if (!user_service->close_pending) { -+ status = vchiq_remove_service(service->handle); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ -+ /* close_pending is true once the underlying service -+ has been closed until the client library calls the -+ CLOSE_DELIVERED ioctl, signalling close_event. */ -+ if (user_service->close_pending && -+ down_interruptible(&user_service->close_event)) -+ status = VCHIQ_RETRY; -+ } -+ else -+ ret = -EINVAL; -+ } break; -+ -+ case VCHIQ_IOC_USE_SERVICE: -+ case VCHIQ_IOC_RELEASE_SERVICE: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_service_for_instance(instance, handle); -+ if (service != NULL) { -+ status = (cmd == VCHIQ_IOC_USE_SERVICE) ? -+ vchiq_use_service_internal(service) : -+ vchiq_release_service_internal(service); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s: cmd %s returned error %d for " -+ "service %c%c%c%c:%03d", -+ __func__, -+ (cmd == VCHIQ_IOC_USE_SERVICE) ? -+ "VCHIQ_IOC_USE_SERVICE" : -+ "VCHIQ_IOC_RELEASE_SERVICE", -+ status, -+ VCHIQ_FOURCC_AS_4CHARS( -+ service->base.fourcc), -+ service->client_id); -+ ret = -EINVAL; -+ } -+ } else -+ ret = -EINVAL; -+ } break; -+ -+ case VCHIQ_IOC_QUEUE_MESSAGE: { -+ VCHIQ_QUEUE_MESSAGE_T args; -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ service = find_service_for_instance(instance, args.handle); -+ -+ if ((service != NULL) && (args.count <= MAX_ELEMENTS)) { -+ /* Copy elements into kernel space */ -+ VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; -+ if (copy_from_user(elements, args.elements, -+ args.count * sizeof(VCHIQ_ELEMENT_T)) == 0) -+ status = vchiq_queue_message -+ (args.handle, -+ elements, args.count); -+ else -+ ret = -EFAULT; -+ } else { -+ ret = -EINVAL; -+ } -+ } break; -+ -+ case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: -+ case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { -+ VCHIQ_QUEUE_BULK_TRANSFER_T args; -+ struct bulk_waiter_node *waiter = NULL; -+ VCHIQ_BULK_DIR_T dir = -+ (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ? -+ VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE; -+ -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ service = find_service_for_instance(instance, args.handle); -+ if (!service) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (args.mode == VCHIQ_BULK_MODE_BLOCKING) { -+ waiter = kzalloc(sizeof(struct bulk_waiter_node), -+ GFP_KERNEL); -+ if (!waiter) { -+ ret = -ENOMEM; -+ break; -+ } -+ args.userdata = &waiter->bulk_waiter; -+ } else if (args.mode == VCHIQ_BULK_MODE_WAITING) { -+ struct list_head *pos; -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_for_each(pos, &instance->bulk_waiter_list) { -+ if (list_entry(pos, struct bulk_waiter_node, -+ list)->pid == current->pid) { -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ break; -+ } -+ -+ } -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ if (!waiter) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "no bulk_waiter found for pid %d", -+ current->pid); -+ ret = -ESRCH; -+ break; -+ } -+ vchiq_log_info(vchiq_arm_log_level, -+ "found bulk_waiter %x for pid %d", -+ (unsigned int)waiter, current->pid); -+ args.userdata = &waiter->bulk_waiter; -+ } -+ status = vchiq_bulk_transfer -+ (args.handle, -+ VCHI_MEM_HANDLE_INVALID, -+ args.data, args.size, -+ args.userdata, args.mode, -+ dir); -+ if (!waiter) -+ break; -+ if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || -+ !waiter->bulk_waiter.bulk) { -+ if (waiter->bulk_waiter.bulk) { -+ /* Cancel the signal when the transfer -+ ** completes. */ -+ spin_lock(&bulk_waiter_spinlock); -+ waiter->bulk_waiter.bulk->userdata = NULL; -+ spin_unlock(&bulk_waiter_spinlock); -+ } -+ kfree(waiter); -+ } else { -+ const VCHIQ_BULK_MODE_T mode_waiting = -+ VCHIQ_BULK_MODE_WAITING; -+ waiter->pid = current->pid; -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_add(&waiter->list, &instance->bulk_waiter_list); -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ vchiq_log_info(vchiq_arm_log_level, -+ "saved bulk_waiter %x for pid %d", -+ (unsigned int)waiter, current->pid); -+ -+ if (copy_to_user((void __user *) -+ &(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *) -+ arg)->mode), -+ (const void *)&mode_waiting, -+ sizeof(mode_waiting)) != 0) -+ ret = -EFAULT; -+ } -+ } break; -+ -+ case VCHIQ_IOC_AWAIT_COMPLETION: { -+ VCHIQ_AWAIT_COMPLETION_T args; -+ -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ if (!instance->connected) { -+ ret = -ENOTCONN; -+ break; -+ } -+ -+ if (copy_from_user(&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ mutex_lock(&instance->completion_mutex); -+ -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ while ((instance->completion_remove == -+ instance->completion_insert) -+ && !instance->closing) { -+ int rc; -+ -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ mutex_unlock(&instance->completion_mutex); -+ rc = down_interruptible(&instance->insert_event); -+ mutex_lock(&instance->completion_mutex); -+ if (rc != 0) { -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ vchiq_log_info(vchiq_arm_log_level, -+ "AWAIT_COMPLETION interrupted"); -+ ret = -EINTR; -+ break; -+ } -+ } -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ -+ if (ret == 0) { -+ int msgbufcount = args.msgbufcount; -+ int remove; -+ -+ remove = instance->completion_remove; -+ -+ for (ret = 0; ret < args.count; ret++) { -+ VCHIQ_COMPLETION_DATA_T *completion; -+ VCHIQ_SERVICE_T *service; -+ USER_SERVICE_T *user_service; -+ VCHIQ_HEADER_T *header; -+ -+ if (remove == instance->completion_insert) -+ break; -+ -+ completion = &instance->completions[ -+ remove & (MAX_COMPLETIONS - 1)]; -+ -+ -+ /* A read memory barrier is needed to prevent -+ ** the prefetch of a stale completion record -+ */ -+ rmb(); -+ -+ service = completion->service_userdata; -+ user_service = service->base.userdata; -+ completion->service_userdata = -+ user_service->userdata; -+ -+ header = completion->header; -+ if (header) { -+ void __user *msgbuf; -+ int msglen; -+ -+ msglen = header->size + -+ sizeof(VCHIQ_HEADER_T); -+ /* This must be a VCHIQ-style service */ -+ if (args.msgbufsize < msglen) { -+ vchiq_log_error( -+ vchiq_arm_log_level, -+ "header %x: msgbufsize" -+ " %x < msglen %x", -+ (unsigned int)header, -+ args.msgbufsize, -+ msglen); -+ WARN(1, "invalid message " -+ "size\n"); -+ if (ret == 0) -+ ret = -EMSGSIZE; -+ break; -+ } -+ if (msgbufcount <= 0) -+ /* Stall here for lack of a -+ ** buffer for the message. */ -+ break; -+ /* Get the pointer from user space */ -+ msgbufcount--; -+ if (copy_from_user(&msgbuf, -+ (const void __user *) -+ &args.msgbufs[msgbufcount], -+ sizeof(msgbuf)) != 0) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ -+ /* Copy the message to user space */ -+ if (copy_to_user(msgbuf, header, -+ msglen) != 0) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ -+ /* Now it has been copied, the message -+ ** can be released. */ -+ vchiq_release_message(service->handle, -+ header); -+ -+ /* The completion must point to the -+ ** msgbuf. */ -+ completion->header = msgbuf; -+ } -+ -+ if ((completion->reason == -+ VCHIQ_SERVICE_CLOSED) && -+ !instance->use_close_delivered) -+ unlock_service(service); -+ -+ if (copy_to_user((void __user *)( -+ (size_t)args.buf + -+ ret * sizeof(VCHIQ_COMPLETION_DATA_T)), -+ completion, -+ sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ -+ /* Ensure that the above copy has completed -+ ** before advancing the remove pointer. */ -+ mb(); -+ -+ instance->completion_remove = ++remove; -+ } -+ -+ if (msgbufcount != args.msgbufcount) { -+ if (copy_to_user((void __user *) -+ &((VCHIQ_AWAIT_COMPLETION_T *)arg)-> -+ msgbufcount, -+ &msgbufcount, -+ sizeof(msgbufcount)) != 0) { -+ ret = -EFAULT; -+ } -+ } -+ } -+ -+ if (ret != 0) -+ up(&instance->remove_event); -+ mutex_unlock(&instance->completion_mutex); -+ DEBUG_TRACE(AWAIT_COMPLETION_LINE); -+ } break; -+ -+ case VCHIQ_IOC_DEQUEUE_MESSAGE: { -+ VCHIQ_DEQUEUE_MESSAGE_T args; -+ USER_SERVICE_T *user_service; -+ VCHIQ_HEADER_T *header; -+ -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ service = find_service_for_instance(instance, args.handle); -+ if (!service) { -+ ret = -EINVAL; -+ break; -+ } -+ user_service = (USER_SERVICE_T *)service->base.userdata; -+ if (user_service->is_vchi == 0) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ spin_lock(&msg_queue_spinlock); -+ if (user_service->msg_remove == user_service->msg_insert) { -+ if (!args.blocking) { -+ spin_unlock(&msg_queue_spinlock); -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ ret = -EWOULDBLOCK; -+ break; -+ } -+ user_service->dequeue_pending = 1; -+ do { -+ spin_unlock(&msg_queue_spinlock); -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ if (down_interruptible( -+ &user_service->insert_event) != 0) { -+ vchiq_log_info(vchiq_arm_log_level, -+ "DEQUEUE_MESSAGE interrupted"); -+ ret = -EINTR; -+ break; -+ } -+ spin_lock(&msg_queue_spinlock); -+ } while (user_service->msg_remove == -+ user_service->msg_insert); -+ -+ if (ret) -+ break; -+ } -+ -+ BUG_ON((int)(user_service->msg_insert - -+ user_service->msg_remove) < 0); -+ -+ header = user_service->msg_queue[user_service->msg_remove & -+ (MSG_QUEUE_SIZE - 1)]; -+ user_service->msg_remove++; -+ spin_unlock(&msg_queue_spinlock); -+ -+ up(&user_service->remove_event); -+ if (header == NULL) -+ ret = -ENOTCONN; -+ else if (header->size <= args.bufsize) { -+ /* Copy to user space if msgbuf is not NULL */ -+ if ((args.buf == NULL) || -+ (copy_to_user((void __user *)args.buf, -+ header->data, -+ header->size) == 0)) { -+ ret = header->size; -+ vchiq_release_message( -+ service->handle, -+ header); -+ } else -+ ret = -EFAULT; -+ } else { -+ vchiq_log_error(vchiq_arm_log_level, -+ "header %x: bufsize %x < size %x", -+ (unsigned int)header, args.bufsize, -+ header->size); -+ WARN(1, "invalid size\n"); -+ ret = -EMSGSIZE; -+ } -+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -+ } break; -+ -+ case VCHIQ_IOC_GET_CLIENT_ID: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ ret = vchiq_get_client_id(handle); -+ } break; -+ -+ case VCHIQ_IOC_GET_CONFIG: { -+ VCHIQ_GET_CONFIG_T args; -+ VCHIQ_CONFIG_T config; -+ -+ if (copy_from_user(&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ if (args.config_size > sizeof(config)) { -+ ret = -EINVAL; -+ break; -+ } -+ status = vchiq_get_config(instance, args.config_size, &config); -+ if (status == VCHIQ_SUCCESS) { -+ if (copy_to_user((void __user *)args.pconfig, -+ &config, args.config_size) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ } -+ } break; -+ -+ case VCHIQ_IOC_SET_SERVICE_OPTION: { -+ VCHIQ_SET_SERVICE_OPTION_T args; -+ -+ if (copy_from_user( -+ &args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ -+ service = find_service_for_instance(instance, args.handle); -+ if (!service) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ status = vchiq_set_service_option( -+ args.handle, args.option, args.value); -+ } break; -+ -+ case VCHIQ_IOC_DUMP_PHYS_MEM: { -+ VCHIQ_DUMP_MEM_T args; -+ -+ if (copy_from_user -+ (&args, (const void __user *)arg, -+ sizeof(args)) != 0) { -+ ret = -EFAULT; -+ break; -+ } -+ dump_phys_mem(args.virt_addr, args.num_bytes); -+ } break; -+ -+ case VCHIQ_IOC_LIB_VERSION: { -+ unsigned int lib_version = (unsigned int)arg; -+ -+ if (lib_version < VCHIQ_VERSION_MIN) -+ ret = -EINVAL; -+ else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED) -+ instance->use_close_delivered = 1; -+ } break; -+ -+ case VCHIQ_IOC_CLOSE_DELIVERED: { -+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; -+ -+ service = find_closed_service_for_instance(instance, handle); -+ if (service != NULL) { -+ USER_SERVICE_T *user_service = -+ (USER_SERVICE_T *)service->base.userdata; -+ close_delivered(user_service); -+ } -+ else -+ ret = -EINVAL; -+ } break; -+ -+ default: -+ ret = -ENOTTY; -+ break; -+ } -+ -+ if (service) -+ unlock_service(service); -+ -+ if (ret == 0) { -+ if (status == VCHIQ_ERROR) -+ ret = -EIO; -+ else if (status == VCHIQ_RETRY) -+ ret = -EINTR; -+ } -+ -+ if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) && -+ (ret != -EWOULDBLOCK)) -+ vchiq_log_info(vchiq_arm_log_level, -+ " ioctl instance %lx, cmd %s -> status %d, %ld", -+ (unsigned long)instance, -+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? -+ ioctl_names[_IOC_NR(cmd)] : -+ "", -+ status, ret); -+ else -+ vchiq_log_trace(vchiq_arm_log_level, -+ " ioctl instance %lx, cmd %s -> status %d, %ld", -+ (unsigned long)instance, -+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? -+ ioctl_names[_IOC_NR(cmd)] : -+ "", -+ status, ret); -+ -+ return ret; -+} -+ -+/**************************************************************************** -+* -+* vchiq_open -+* -+***************************************************************************/ -+ -+static int -+vchiq_open(struct inode *inode, struct file *file) -+{ -+ int dev = iminor(inode) & 0x0f; -+ vchiq_log_info(vchiq_arm_log_level, "vchiq_open"); -+ switch (dev) { -+ case VCHIQ_MINOR: { -+ int ret; -+ VCHIQ_STATE_T *state = vchiq_get_state(); -+ VCHIQ_INSTANCE_T instance; -+ -+ if (!state) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "vchiq has no connection to VideoCore"); -+ return -ENOTCONN; -+ } -+ -+ instance = kzalloc(sizeof(*instance), GFP_KERNEL); -+ if (!instance) -+ return -ENOMEM; -+ -+ instance->state = state; -+ instance->pid = current->tgid; -+ -+ ret = vchiq_debugfs_add_instance(instance); -+ if (ret != 0) { -+ kfree(instance); -+ return ret; -+ } -+ -+ sema_init(&instance->insert_event, 0); -+ sema_init(&instance->remove_event, 0); -+ mutex_init(&instance->completion_mutex); -+ mutex_init(&instance->bulk_waiter_list_mutex); -+ INIT_LIST_HEAD(&instance->bulk_waiter_list); -+ -+ file->private_data = instance; -+ } break; -+ -+ default: -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unknown minor device: %d", dev); -+ return -ENXIO; -+ } -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vchiq_release -+* -+***************************************************************************/ -+ -+static int -+vchiq_release(struct inode *inode, struct file *file) -+{ -+ int dev = iminor(inode) & 0x0f; -+ int ret = 0; -+ switch (dev) { -+ case VCHIQ_MINOR: { -+ VCHIQ_INSTANCE_T instance = file->private_data; -+ VCHIQ_STATE_T *state = vchiq_get_state(); -+ VCHIQ_SERVICE_T *service; -+ int i; -+ -+ vchiq_log_info(vchiq_arm_log_level, -+ "vchiq_release: instance=%lx", -+ (unsigned long)instance); -+ -+ if (!state) { -+ ret = -EPERM; -+ goto out; -+ } -+ -+ /* Ensure videocore is awake to allow termination. */ -+ vchiq_use_internal(instance->state, NULL, -+ USE_TYPE_VCHIQ); -+ -+ mutex_lock(&instance->completion_mutex); -+ -+ /* Wake the completion thread and ask it to exit */ -+ instance->closing = 1; -+ up(&instance->insert_event); -+ -+ mutex_unlock(&instance->completion_mutex); -+ -+ /* Wake the slot handler if the completion queue is full. */ -+ up(&instance->remove_event); -+ -+ /* Mark all services for termination... */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, -+ &i)) != NULL) { -+ USER_SERVICE_T *user_service = service->base.userdata; -+ -+ /* Wake the slot handler if the msg queue is full. */ -+ up(&user_service->remove_event); -+ -+ vchiq_terminate_service_internal(service); -+ unlock_service(service); -+ } -+ -+ /* ...and wait for them to die */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, &i)) -+ != NULL) { -+ USER_SERVICE_T *user_service = service->base.userdata; -+ -+ down(&service->remove_event); -+ -+ BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); -+ -+ spin_lock(&msg_queue_spinlock); -+ -+ while (user_service->msg_remove != -+ user_service->msg_insert) { -+ VCHIQ_HEADER_T *header = user_service-> -+ msg_queue[user_service->msg_remove & -+ (MSG_QUEUE_SIZE - 1)]; -+ user_service->msg_remove++; -+ spin_unlock(&msg_queue_spinlock); -+ -+ if (header) -+ vchiq_release_message( -+ service->handle, -+ header); -+ spin_lock(&msg_queue_spinlock); -+ } -+ -+ spin_unlock(&msg_queue_spinlock); -+ -+ unlock_service(service); -+ } -+ -+ /* Release any closed services */ -+ while (instance->completion_remove != -+ instance->completion_insert) { -+ VCHIQ_COMPLETION_DATA_T *completion; -+ VCHIQ_SERVICE_T *service; -+ completion = &instance->completions[ -+ instance->completion_remove & -+ (MAX_COMPLETIONS - 1)]; -+ service = completion->service_userdata; -+ if (completion->reason == VCHIQ_SERVICE_CLOSED) -+ { -+ USER_SERVICE_T *user_service = -+ service->base.userdata; -+ -+ /* Wake any blocked user-thread */ -+ if (instance->use_close_delivered) -+ up(&user_service->close_event); -+ unlock_service(service); -+ } -+ instance->completion_remove++; -+ } -+ -+ /* Release the PEER service count. */ -+ vchiq_release_internal(instance->state, NULL); -+ -+ { -+ struct list_head *pos, *next; -+ list_for_each_safe(pos, next, -+ &instance->bulk_waiter_list) { -+ struct bulk_waiter_node *waiter; -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ vchiq_log_info(vchiq_arm_log_level, -+ "bulk_waiter - cleaned up %x " -+ "for pid %d", -+ (unsigned int)waiter, waiter->pid); -+ kfree(waiter); -+ } -+ } -+ -+ vchiq_debugfs_remove_instance(instance); -+ -+ kfree(instance); -+ file->private_data = NULL; -+ } break; -+ -+ default: -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unknown minor device: %d", dev); -+ ret = -ENXIO; -+ } -+ -+out: -+ return ret; -+} -+ -+/**************************************************************************** -+* -+* vchiq_dump -+* -+***************************************************************************/ -+ -+void -+vchiq_dump(void *dump_context, const char *str, int len) -+{ -+ DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context; -+ -+ if (context->actual < context->space) { -+ int copy_bytes; -+ if (context->offset > 0) { -+ int skip_bytes = min(len, (int)context->offset); -+ str += skip_bytes; -+ len -= skip_bytes; -+ context->offset -= skip_bytes; -+ if (context->offset > 0) -+ return; -+ } -+ copy_bytes = min(len, (int)(context->space - context->actual)); -+ if (copy_bytes == 0) -+ return; -+ if (copy_to_user(context->buf + context->actual, str, -+ copy_bytes)) -+ context->actual = -EFAULT; -+ context->actual += copy_bytes; -+ len -= copy_bytes; -+ -+ /* If tne terminating NUL is included in the length, then it -+ ** marks the end of a line and should be replaced with a -+ ** carriage return. */ -+ if ((len == 0) && (str[copy_bytes - 1] == '\0')) { -+ char cr = '\n'; -+ if (copy_to_user(context->buf + context->actual - 1, -+ &cr, 1)) -+ context->actual = -EFAULT; -+ } -+ } -+} -+ -+/**************************************************************************** -+* -+* vchiq_dump_platform_instance_state -+* -+***************************************************************************/ -+ -+void -+vchiq_dump_platform_instances(void *dump_context) -+{ -+ VCHIQ_STATE_T *state = vchiq_get_state(); -+ char buf[80]; -+ int len; -+ int i; -+ -+ /* There is no list of instances, so instead scan all services, -+ marking those that have been dumped. */ -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ VCHIQ_INSTANCE_T instance; -+ -+ if (service && (service->base.callback == service_callback)) { -+ instance = service->instance; -+ if (instance) -+ instance->mark = 0; -+ } -+ } -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ VCHIQ_INSTANCE_T instance; -+ -+ if (service && (service->base.callback == service_callback)) { -+ instance = service->instance; -+ if (instance && !instance->mark) { -+ len = snprintf(buf, sizeof(buf), -+ "Instance %x: pid %d,%s completions " -+ "%d/%d", -+ (unsigned int)instance, instance->pid, -+ instance->connected ? " connected, " : -+ "", -+ instance->completion_insert - -+ instance->completion_remove, -+ MAX_COMPLETIONS); -+ -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ instance->mark = 1; -+ } -+ } -+ } -+} -+ -+/**************************************************************************** -+* -+* vchiq_dump_platform_service_state -+* -+***************************************************************************/ -+ -+void -+vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service) -+{ -+ USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata; -+ char buf[80]; -+ int len; -+ -+ len = snprintf(buf, sizeof(buf), " instance %x", -+ (unsigned int)service->instance); -+ -+ if ((service->base.callback == service_callback) && -+ user_service->is_vchi) { -+ len += snprintf(buf + len, sizeof(buf) - len, -+ ", %d/%d messages", -+ user_service->msg_insert - user_service->msg_remove, -+ MSG_QUEUE_SIZE); -+ -+ if (user_service->dequeue_pending) -+ len += snprintf(buf + len, sizeof(buf) - len, -+ " (dequeue pending)"); -+ } -+ -+ vchiq_dump(dump_context, buf, len + 1); -+} -+ -+/**************************************************************************** -+* -+* dump_user_mem -+* -+***************************************************************************/ -+ -+static void -+dump_phys_mem(void *virt_addr, uint32_t num_bytes) -+{ -+ int rc; -+ uint8_t *end_virt_addr = virt_addr + num_bytes; -+ int num_pages; -+ int offset; -+ int end_offset; -+ int page_idx; -+ int prev_idx; -+ struct page *page; -+ struct page **pages; -+ uint8_t *kmapped_virt_ptr; -+ -+ /* Align virtAddr and endVirtAddr to 16 byte boundaries. */ -+ -+ virt_addr = (void *)((unsigned long)virt_addr & ~0x0fuL); -+ end_virt_addr = (void *)(((unsigned long)end_virt_addr + 15uL) & -+ ~0x0fuL); -+ -+ offset = (int)(long)virt_addr & (PAGE_SIZE - 1); -+ end_offset = (int)(long)end_virt_addr & (PAGE_SIZE - 1); -+ -+ num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE; -+ -+ pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL); -+ if (pages == NULL) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to allocation memory for %d pages\n", -+ num_pages); -+ return; -+ } -+ -+ down_read(¤t->mm->mmap_sem); -+ rc = get_user_pages( -+ (unsigned long)virt_addr, /* start */ -+ num_pages, /* len */ -+ 0, /* write */ -+ 0, /* force */ -+ pages, /* pages (array of page pointers) */ -+ NULL); /* vmas */ -+ up_read(¤t->mm->mmap_sem); -+ -+ prev_idx = -1; -+ page = NULL; -+ -+ while (offset < end_offset) { -+ -+ int page_offset = offset % PAGE_SIZE; -+ page_idx = offset / PAGE_SIZE; -+ -+ if (page_idx != prev_idx) { -+ -+ if (page != NULL) -+ kunmap(page); -+ page = pages[page_idx]; -+ kmapped_virt_ptr = kmap(page); -+ -+ prev_idx = page_idx; -+ } -+ -+ if (vchiq_arm_log_level >= VCHIQ_LOG_TRACE) -+ vchiq_log_dump_mem("ph", -+ (uint32_t)(unsigned long)&kmapped_virt_ptr[ -+ page_offset], -+ &kmapped_virt_ptr[page_offset], 16); -+ -+ offset += 16; -+ } -+ if (page != NULL) -+ kunmap(page); -+ -+ for (page_idx = 0; page_idx < num_pages; page_idx++) -+ put_page(pages[page_idx]); -+ -+ kfree(pages); -+} -+ -+/**************************************************************************** -+* -+* vchiq_read -+* -+***************************************************************************/ -+ -+static ssize_t -+vchiq_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ DUMP_CONTEXT_T context; -+ context.buf = buf; -+ context.actual = 0; -+ context.space = count; -+ context.offset = *ppos; -+ -+ vchiq_dump_state(&context, &g_state); -+ -+ *ppos += context.actual; -+ -+ return context.actual; -+} -+ -+VCHIQ_STATE_T * -+vchiq_get_state(void) -+{ -+ -+ if (g_state.remote == NULL) -+ printk(KERN_ERR "%s: g_state.remote == NULL\n", __func__); -+ else if (g_state.remote->initialised != 1) -+ printk(KERN_NOTICE "%s: g_state.remote->initialised != 1 (%d)\n", -+ __func__, g_state.remote->initialised); -+ -+ return ((g_state.remote != NULL) && -+ (g_state.remote->initialised == 1)) ? &g_state : NULL; -+} -+ -+static const struct file_operations -+vchiq_fops = { -+ .owner = THIS_MODULE, -+ .unlocked_ioctl = vchiq_ioctl, -+ .open = vchiq_open, -+ .release = vchiq_release, -+ .read = vchiq_read -+}; -+ -+/* -+ * Autosuspend related functionality -+ */ -+ -+int -+vchiq_videocore_wanted(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ if (!arm_state) -+ /* autosuspend not supported - always return wanted */ -+ return 1; -+ else if (arm_state->blocked_count) -+ return 1; -+ else if (!arm_state->videocore_use_count) -+ /* usage count zero - check for override unless we're forcing */ -+ if (arm_state->resume_blocked) -+ return 0; -+ else -+ return vchiq_platform_videocore_wanted(state); -+ else -+ /* non-zero usage count - videocore still required */ -+ return 1; -+} -+ -+static VCHIQ_STATUS_T -+vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, -+ VCHIQ_SERVICE_HANDLE_T service_user, -+ void *bulk_user) -+{ -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s callback reason %d", __func__, reason); -+ return 0; -+} -+ -+static int -+vchiq_keepalive_thread_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ -+ VCHIQ_STATUS_T status; -+ VCHIQ_INSTANCE_T instance; -+ VCHIQ_SERVICE_HANDLE_T ka_handle; -+ -+ VCHIQ_SERVICE_PARAMS_T params = { -+ .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), -+ .callback = vchiq_keepalive_vchiq_callback, -+ .version = KEEPALIVE_VER, -+ .version_min = KEEPALIVE_VER_MIN -+ }; -+ -+ status = vchiq_initialise(&instance); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_initialise failed %d", __func__, status); -+ goto exit; -+ } -+ -+ status = vchiq_connect(instance); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_connect failed %d", __func__, status); -+ goto shutdown; -+ } -+ -+ status = vchiq_add_service(instance, ¶ms, &ka_handle); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_open_service failed %d", __func__, status); -+ goto shutdown; -+ } -+ -+ while (1) { -+ long rc = 0, uc = 0; -+ if (wait_for_completion_interruptible(&arm_state->ka_evt) -+ != 0) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s interrupted", __func__); -+ flush_signals(current); -+ continue; -+ } -+ -+ /* read and clear counters. Do release_count then use_count to -+ * prevent getting more releases than uses */ -+ rc = atomic_xchg(&arm_state->ka_release_count, 0); -+ uc = atomic_xchg(&arm_state->ka_use_count, 0); -+ -+ /* Call use/release service the requisite number of times. -+ * Process use before release so use counts don't go negative */ -+ while (uc--) { -+ atomic_inc(&arm_state->ka_use_ack_count); -+ status = vchiq_use_service(ka_handle); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_use_service error %d", -+ __func__, status); -+ } -+ } -+ while (rc--) { -+ status = vchiq_release_service(ka_handle); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s vchiq_release_service error %d", -+ __func__, status); -+ } -+ } -+ } -+ -+shutdown: -+ vchiq_shutdown(instance); -+exit: -+ return 0; -+} -+ -+ -+ -+VCHIQ_STATUS_T -+vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (arm_state) { -+ rwlock_init(&arm_state->susp_res_lock); -+ -+ init_completion(&arm_state->ka_evt); -+ atomic_set(&arm_state->ka_use_count, 0); -+ atomic_set(&arm_state->ka_use_ack_count, 0); -+ atomic_set(&arm_state->ka_release_count, 0); -+ -+ init_completion(&arm_state->vc_suspend_complete); -+ -+ init_completion(&arm_state->vc_resume_complete); -+ /* Initialise to 'done' state. We only want to block on resume -+ * completion while videocore is suspended. */ -+ set_resume_state(arm_state, VC_RESUME_RESUMED); -+ -+ init_completion(&arm_state->resume_blocker); -+ /* Initialise to 'done' state. We only want to block on this -+ * completion while resume is blocked */ -+ complete_all(&arm_state->resume_blocker); -+ -+ init_completion(&arm_state->blocked_blocker); -+ /* Initialise to 'done' state. We only want to block on this -+ * completion while things are waiting on the resume blocker */ -+ complete_all(&arm_state->blocked_blocker); -+ -+ arm_state->suspend_timer_timeout = SUSPEND_TIMER_TIMEOUT_MS; -+ arm_state->suspend_timer_running = 0; -+ init_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer.data = (unsigned long)(state); -+ arm_state->suspend_timer.function = suspend_timer_callback; -+ -+ arm_state->first_connect = 0; -+ -+ } -+ return status; -+} -+ -+/* -+** Functions to modify the state variables; -+** set_suspend_state -+** set_resume_state -+** -+** There are more state variables than we might like, so ensure they remain in -+** step. Suspend and resume state are maintained separately, since most of -+** these state machines can operate independently. However, there are a few -+** states where state transitions in one state machine cause a reset to the -+** other state machine. In addition, there are some completion events which -+** need to occur on state machine reset and end-state(s), so these are also -+** dealt with in these functions. -+** -+** In all states we set the state variable according to the input, but in some -+** cases we perform additional steps outlined below; -+** -+** VC_SUSPEND_IDLE - Initialise the suspend completion at the same time. -+** The suspend completion is completed after any suspend -+** attempt. When we reset the state machine we also reset -+** the completion. This reset occurs when videocore is -+** resumed, and also if we initiate suspend after a suspend -+** failure. -+** -+** VC_SUSPEND_IN_PROGRESS - This state is considered the point of no return for -+** suspend - ie from this point on we must try to suspend -+** before resuming can occur. We therefore also reset the -+** resume state machine to VC_RESUME_IDLE in this state. -+** -+** VC_SUSPEND_SUSPENDED - Suspend has completed successfully. Also call -+** complete_all on the suspend completion to notify -+** anything waiting for suspend to happen. -+** -+** VC_SUSPEND_REJECTED - Videocore rejected suspend. Videocore will also -+** initiate resume, so no need to alter resume state. -+** We call complete_all on the suspend completion to notify -+** of suspend rejection. -+** -+** VC_SUSPEND_FAILED - We failed to initiate videocore suspend. We notify the -+** suspend completion and reset the resume state machine. -+** -+** VC_RESUME_IDLE - Initialise the resume completion at the same time. The -+** resume completion is in it's 'done' state whenever -+** videcore is running. Therfore, the VC_RESUME_IDLE state -+** implies that videocore is suspended. -+** Hence, any thread which needs to wait until videocore is -+** running can wait on this completion - it will only block -+** if videocore is suspended. -+** -+** VC_RESUME_RESUMED - Resume has completed successfully. Videocore is running. -+** Call complete_all on the resume completion to unblock -+** any threads waiting for resume. Also reset the suspend -+** state machine to it's idle state. -+** -+** VC_RESUME_FAILED - Currently unused - no mechanism to fail resume exists. -+*/ -+ -+void -+set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_suspend_status new_state) -+{ -+ /* set the state in all cases */ -+ arm_state->vc_suspend_state = new_state; -+ -+ /* state specific additional actions */ -+ switch (new_state) { -+ case VC_SUSPEND_FORCE_CANCELED: -+ complete_all(&arm_state->vc_suspend_complete); -+ break; -+ case VC_SUSPEND_REJECTED: -+ complete_all(&arm_state->vc_suspend_complete); -+ break; -+ case VC_SUSPEND_FAILED: -+ complete_all(&arm_state->vc_suspend_complete); -+ arm_state->vc_resume_state = VC_RESUME_RESUMED; -+ complete_all(&arm_state->vc_resume_complete); -+ break; -+ case VC_SUSPEND_IDLE: -+ reinit_completion(&arm_state->vc_suspend_complete); -+ break; -+ case VC_SUSPEND_REQUESTED: -+ break; -+ case VC_SUSPEND_IN_PROGRESS: -+ set_resume_state(arm_state, VC_RESUME_IDLE); -+ break; -+ case VC_SUSPEND_SUSPENDED: -+ complete_all(&arm_state->vc_suspend_complete); -+ break; -+ default: -+ BUG(); -+ break; -+ } -+} -+ -+void -+set_resume_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_resume_status new_state) -+{ -+ /* set the state in all cases */ -+ arm_state->vc_resume_state = new_state; -+ -+ /* state specific additional actions */ -+ switch (new_state) { -+ case VC_RESUME_FAILED: -+ break; -+ case VC_RESUME_IDLE: -+ reinit_completion(&arm_state->vc_resume_complete); -+ break; -+ case VC_RESUME_REQUESTED: -+ break; -+ case VC_RESUME_IN_PROGRESS: -+ break; -+ case VC_RESUME_RESUMED: -+ complete_all(&arm_state->vc_resume_complete); -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ break; -+ default: -+ BUG(); -+ break; -+ } -+} -+ -+ -+/* should be called with the write lock held */ -+inline void -+start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ del_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer.expires = jiffies + -+ msecs_to_jiffies(arm_state-> -+ suspend_timer_timeout); -+ add_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer_running = 1; -+} -+ -+/* should be called with the write lock held */ -+static inline void -+stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ if (arm_state->suspend_timer_running) { -+ del_timer(&arm_state->suspend_timer); -+ arm_state->suspend_timer_running = 0; -+ } -+} -+ -+static inline int -+need_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && -+ (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && -+ vchiq_videocore_wanted(state); -+} -+ -+static int -+block_resume(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ int status = VCHIQ_SUCCESS; -+ const unsigned long timeout_val = -+ msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS); -+ int resume_count = 0; -+ -+ /* Allow any threads which were blocked by the last force suspend to -+ * complete if they haven't already. Only give this one shot; if -+ * blocked_count is incremented after blocked_blocker is completed -+ * (which only happens when blocked_count hits 0) then those threads -+ * will have to wait until next time around */ -+ if (arm_state->blocked_count) { -+ reinit_completion(&arm_state->blocked_blocker); -+ write_unlock_bh(&arm_state->susp_res_lock); -+ vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " -+ "blocked clients", __func__); -+ if (wait_for_completion_interruptible_timeout( -+ &arm_state->blocked_blocker, timeout_val) -+ <= 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s wait for " -+ "previously blocked clients failed" , __func__); -+ status = VCHIQ_ERROR; -+ write_lock_bh(&arm_state->susp_res_lock); -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s previously blocked " -+ "clients resumed", __func__); -+ write_lock_bh(&arm_state->susp_res_lock); -+ } -+ -+ /* We need to wait for resume to complete if it's in process */ -+ while (arm_state->vc_resume_state != VC_RESUME_RESUMED && -+ arm_state->vc_resume_state > VC_RESUME_IDLE) { -+ if (resume_count > 1) { -+ status = VCHIQ_ERROR; -+ vchiq_log_error(vchiq_susp_log_level, "%s waited too " -+ "many times for resume" , __func__); -+ goto out; -+ } -+ write_unlock_bh(&arm_state->susp_res_lock); -+ vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", -+ __func__); -+ if (wait_for_completion_interruptible_timeout( -+ &arm_state->vc_resume_complete, timeout_val) -+ <= 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s wait for " -+ "resume failed (%s)", __func__, -+ resume_state_names[arm_state->vc_resume_state + -+ VC_RESUME_NUM_OFFSET]); -+ status = VCHIQ_ERROR; -+ write_lock_bh(&arm_state->susp_res_lock); -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s resumed", __func__); -+ write_lock_bh(&arm_state->susp_res_lock); -+ resume_count++; -+ } -+ reinit_completion(&arm_state->resume_blocker); -+ arm_state->resume_blocked = 1; -+ -+out: -+ return status; -+} -+ -+static inline void -+unblock_resume(VCHIQ_ARM_STATE_T *arm_state) -+{ -+ complete_all(&arm_state->resume_blocker); -+ arm_state->resume_blocked = 0; -+} -+ -+/* Initiate suspend via slot handler. Should be called with the write lock -+ * held */ -+VCHIQ_STATUS_T -+vchiq_arm_vcsuspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ status = VCHIQ_SUCCESS; -+ -+ -+ switch (arm_state->vc_suspend_state) { -+ case VC_SUSPEND_REQUESTED: -+ vchiq_log_info(vchiq_susp_log_level, "%s: suspend already " -+ "requested", __func__); -+ break; -+ case VC_SUSPEND_IN_PROGRESS: -+ vchiq_log_info(vchiq_susp_log_level, "%s: suspend already in " -+ "progress", __func__); -+ break; -+ -+ default: -+ /* We don't expect to be in other states, so log but continue -+ * anyway */ -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s unexpected suspend state %s", __func__, -+ suspend_state_names[arm_state->vc_suspend_state + -+ VC_SUSPEND_NUM_OFFSET]); -+ /* fall through */ -+ case VC_SUSPEND_REJECTED: -+ case VC_SUSPEND_FAILED: -+ /* Ensure any idle state actions have been run */ -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ /* fall through */ -+ case VC_SUSPEND_IDLE: -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: suspending", __func__); -+ set_suspend_state(arm_state, VC_SUSPEND_REQUESTED); -+ /* kick the slot handler thread to initiate suspend */ -+ request_poll(state, NULL, 0); -+ break; -+ } -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); -+ return status; -+} -+ -+void -+vchiq_platform_check_suspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int susp = 0; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->vc_suspend_state == VC_SUSPEND_REQUESTED && -+ arm_state->vc_resume_state == VC_RESUME_RESUMED) { -+ set_suspend_state(arm_state, VC_SUSPEND_IN_PROGRESS); -+ susp = 1; -+ } -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (susp) -+ vchiq_platform_suspend(state); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return; -+} -+ -+ -+static void -+output_timeout_error(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ char service_err[50] = ""; -+ int vc_use_count = arm_state->videocore_use_count; -+ int active_services = state->unused_service; -+ int i; -+ -+ if (!arm_state->videocore_use_count) { -+ snprintf(service_err, 50, " Videocore usecount is 0"); -+ goto output_msg; -+ } -+ for (i = 0; i < active_services; i++) { -+ VCHIQ_SERVICE_T *service_ptr = state->services[i]; -+ if (service_ptr && service_ptr->service_use_count && -+ (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) { -+ snprintf(service_err, 50, " %c%c%c%c(%d) service has " -+ "use count %d%s", VCHIQ_FOURCC_AS_4CHARS( -+ service_ptr->base.fourcc), -+ service_ptr->client_id, -+ service_ptr->service_use_count, -+ service_ptr->service_use_count == -+ vc_use_count ? "" : " (+ more)"); -+ break; -+ } -+ } -+ -+output_msg: -+ vchiq_log_error(vchiq_susp_log_level, -+ "timed out waiting for vc suspend (%d).%s", -+ arm_state->autosuspend_override, service_err); -+ -+} -+ -+/* Try to get videocore into suspended state, regardless of autosuspend state. -+** We don't actually force suspend, since videocore may get into a bad state -+** if we force suspend at a bad time. Instead, we wait for autosuspend to -+** determine a good point to suspend. If this doesn't happen within 100ms we -+** report failure. -+** -+** Returns VCHIQ_SUCCESS if videocore suspended successfully, VCHIQ_RETRY if -+** videocore failed to suspend in time or VCHIQ_ERROR if interrupted. -+*/ -+VCHIQ_STATUS_T -+vchiq_arm_force_suspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ long rc = 0; -+ int repeat = -1; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ -+ status = block_resume(arm_state); -+ if (status != VCHIQ_SUCCESS) -+ goto unlock; -+ if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { -+ /* Already suspended - just block resume and exit */ -+ vchiq_log_info(vchiq_susp_log_level, "%s already suspended", -+ __func__); -+ status = VCHIQ_SUCCESS; -+ goto unlock; -+ } else if (arm_state->vc_suspend_state <= VC_SUSPEND_IDLE) { -+ /* initiate suspend immediately in the case that we're waiting -+ * for the timeout */ -+ stop_suspend_timer(arm_state); -+ if (!vchiq_videocore_wanted(state)) { -+ vchiq_log_info(vchiq_susp_log_level, "%s videocore " -+ "idle, initiating suspend", __func__); -+ status = vchiq_arm_vcsuspend(state); -+ } else if (arm_state->autosuspend_override < -+ FORCE_SUSPEND_FAIL_MAX) { -+ vchiq_log_info(vchiq_susp_log_level, "%s letting " -+ "videocore go idle", __func__); -+ status = VCHIQ_SUCCESS; -+ } else { -+ vchiq_log_warning(vchiq_susp_log_level, "%s failed too " -+ "many times - attempting suspend", __func__); -+ status = vchiq_arm_vcsuspend(state); -+ } -+ } else { -+ vchiq_log_info(vchiq_susp_log_level, "%s videocore suspend " -+ "in progress - wait for completion", __func__); -+ status = VCHIQ_SUCCESS; -+ } -+ -+ /* Wait for suspend to happen due to system idle (not forced..) */ -+ if (status != VCHIQ_SUCCESS) -+ goto unblock_resume; -+ -+ do { -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ rc = wait_for_completion_interruptible_timeout( -+ &arm_state->vc_suspend_complete, -+ msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS)); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (rc < 0) { -+ vchiq_log_warning(vchiq_susp_log_level, "%s " -+ "interrupted waiting for suspend", __func__); -+ status = VCHIQ_ERROR; -+ goto unblock_resume; -+ } else if (rc == 0) { -+ if (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) { -+ /* Repeat timeout once if in progress */ -+ if (repeat < 0) { -+ repeat = 1; -+ continue; -+ } -+ } -+ arm_state->autosuspend_override++; -+ output_timeout_error(state); -+ -+ status = VCHIQ_RETRY; -+ goto unblock_resume; -+ } -+ } while (0 < (repeat--)); -+ -+ /* Check and report state in case we need to abort ARM suspend */ -+ if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED) { -+ status = VCHIQ_RETRY; -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s videocore suspend failed (state %s)", __func__, -+ suspend_state_names[arm_state->vc_suspend_state + -+ VC_SUSPEND_NUM_OFFSET]); -+ /* Reset the state only if it's still in an error state. -+ * Something could have already initiated another suspend. */ -+ if (arm_state->vc_suspend_state < VC_SUSPEND_IDLE) -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ -+ goto unblock_resume; -+ } -+ -+ /* successfully suspended - unlock and exit */ -+ goto unlock; -+ -+unblock_resume: -+ /* all error states need to unblock resume before exit */ -+ unblock_resume(arm_state); -+ -+unlock: -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); -+ return status; -+} -+ -+void -+vchiq_check_suspend(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED && -+ arm_state->first_connect && -+ !vchiq_videocore_wanted(state)) { -+ vchiq_arm_vcsuspend(state); -+ } -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return; -+} -+ -+ -+int -+vchiq_arm_allow_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int resume = 0; -+ int ret = -1; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ unblock_resume(arm_state); -+ resume = vchiq_check_resume(state); -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (resume) { -+ if (wait_for_completion_interruptible( -+ &arm_state->vc_resume_complete) < 0) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s interrupted", __func__); -+ /* failed, cannot accurately derive suspend -+ * state, so exit early. */ -+ goto out; -+ } -+ } -+ -+ read_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: Videocore remains suspended", __func__); -+ } else { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: Videocore resumed", __func__); -+ ret = 0; -+ } -+ read_unlock_bh(&arm_state->susp_res_lock); -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); -+ return ret; -+} -+ -+/* This function should be called with the write lock held */ -+int -+vchiq_check_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int resume = 0; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ if (need_resume(state)) { -+ set_resume_state(arm_state, VC_RESUME_REQUESTED); -+ request_poll(state, NULL, 0); -+ resume = 1; -+ } -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return resume; -+} -+ -+void -+vchiq_platform_check_resume(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int res = 0; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->wake_address == 0) { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: already awake", __func__); -+ goto unlock; -+ } -+ if (arm_state->vc_resume_state == VC_RESUME_IN_PROGRESS) { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s: already resuming", __func__); -+ goto unlock; -+ } -+ -+ if (arm_state->vc_resume_state == VC_RESUME_REQUESTED) { -+ set_resume_state(arm_state, VC_RESUME_IN_PROGRESS); -+ res = 1; -+ } else -+ vchiq_log_trace(vchiq_susp_log_level, -+ "%s: not resuming (resume state %s)", __func__, -+ resume_state_names[arm_state->vc_resume_state + -+ VC_RESUME_NUM_OFFSET]); -+ -+unlock: -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (res) -+ vchiq_platform_resume(state); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -+ return; -+ -+} -+ -+ -+ -+VCHIQ_STATUS_T -+vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ enum USE_TYPE_E use_type) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; -+ char entity[16]; -+ int *entity_uc; -+ int local_uc, local_entity_uc; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ if (use_type == USE_TYPE_VCHIQ) { -+ sprintf(entity, "VCHIQ: "); -+ entity_uc = &arm_state->peer_use_count; -+ } else if (service) { -+ sprintf(entity, "%c%c%c%c:%03d", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->client_id); -+ entity_uc = &service->service_use_count; -+ } else { -+ vchiq_log_error(vchiq_susp_log_level, "%s null service " -+ "ptr", __func__); -+ ret = VCHIQ_ERROR; -+ goto out; -+ } -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ while (arm_state->resume_blocked) { -+ /* If we call 'use' while force suspend is waiting for suspend, -+ * then we're about to block the thread which the force is -+ * waiting to complete, so we're bound to just time out. In this -+ * case, set the suspend state such that the wait will be -+ * canceled, so we can complete as quickly as possible. */ -+ if (arm_state->resume_blocked && arm_state->vc_suspend_state == -+ VC_SUSPEND_IDLE) { -+ set_suspend_state(arm_state, VC_SUSPEND_FORCE_CANCELED); -+ break; -+ } -+ /* If suspend is already in progress then we need to block */ -+ if (!try_wait_for_completion(&arm_state->resume_blocker)) { -+ /* Indicate that there are threads waiting on the resume -+ * blocker. These need to be allowed to complete before -+ * a _second_ call to force suspend can complete, -+ * otherwise low priority threads might never actually -+ * continue */ -+ arm_state->blocked_count++; -+ write_unlock_bh(&arm_state->susp_res_lock); -+ vchiq_log_info(vchiq_susp_log_level, "%s %s resume " -+ "blocked - waiting...", __func__, entity); -+ if (wait_for_completion_killable( -+ &arm_state->resume_blocker) != 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s %s " -+ "wait for resume blocker interrupted", -+ __func__, entity); -+ ret = VCHIQ_ERROR; -+ write_lock_bh(&arm_state->susp_res_lock); -+ arm_state->blocked_count--; -+ write_unlock_bh(&arm_state->susp_res_lock); -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s %s resume " -+ "unblocked", __func__, entity); -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (--arm_state->blocked_count == 0) -+ complete_all(&arm_state->blocked_blocker); -+ } -+ } -+ -+ stop_suspend_timer(arm_state); -+ -+ local_uc = ++arm_state->videocore_use_count; -+ local_entity_uc = ++(*entity_uc); -+ -+ /* If there's a pending request which hasn't yet been serviced then -+ * just clear it. If we're past VC_SUSPEND_REQUESTED state then -+ * vc_resume_complete will block until we either resume or fail to -+ * suspend */ -+ if (arm_state->vc_suspend_state <= VC_SUSPEND_REQUESTED) -+ set_suspend_state(arm_state, VC_SUSPEND_IDLE); -+ -+ if ((use_type != USE_TYPE_SERVICE_NO_RESUME) && need_resume(state)) { -+ set_resume_state(arm_state, VC_RESUME_REQUESTED); -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s %s count %d, state count %d", -+ __func__, entity, local_entity_uc, local_uc); -+ request_poll(state, NULL, 0); -+ } else -+ vchiq_log_trace(vchiq_susp_log_level, -+ "%s %s count %d, state count %d", -+ __func__, entity, *entity_uc, local_uc); -+ -+ -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+ /* Completion is in a done state when we're not suspended, so this won't -+ * block for the non-suspended case. */ -+ if (!try_wait_for_completion(&arm_state->vc_resume_complete)) { -+ vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume", -+ __func__, entity); -+ if (wait_for_completion_killable( -+ &arm_state->vc_resume_complete) != 0) { -+ vchiq_log_error(vchiq_susp_log_level, "%s %s wait for " -+ "resume interrupted", __func__, entity); -+ ret = VCHIQ_ERROR; -+ goto out; -+ } -+ vchiq_log_info(vchiq_susp_log_level, "%s %s resumed", __func__, -+ entity); -+ } -+ -+ if (ret == VCHIQ_SUCCESS) { -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); -+ while (ack_cnt && (status == VCHIQ_SUCCESS)) { -+ /* Send the use notify to videocore */ -+ status = vchiq_send_remote_use_active(state); -+ if (status == VCHIQ_SUCCESS) -+ ack_cnt--; -+ else -+ atomic_add(ack_cnt, -+ &arm_state->ka_use_ack_count); -+ } -+ } -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); -+ return ret; -+} -+ -+VCHIQ_STATUS_T -+vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; -+ char entity[16]; -+ int *entity_uc; -+ int local_uc, local_entity_uc; -+ -+ if (!arm_state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ if (service) { -+ sprintf(entity, "%c%c%c%c:%03d", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->client_id); -+ entity_uc = &service->service_use_count; -+ } else { -+ sprintf(entity, "PEER: "); -+ entity_uc = &arm_state->peer_use_count; -+ } -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (!arm_state->videocore_use_count || !(*entity_uc)) { -+ /* Don't use BUG_ON - don't allow user thread to crash kernel */ -+ WARN_ON(!arm_state->videocore_use_count); -+ WARN_ON(!(*entity_uc)); -+ ret = VCHIQ_ERROR; -+ goto unlock; -+ } -+ local_uc = --arm_state->videocore_use_count; -+ local_entity_uc = --(*entity_uc); -+ -+ if (!vchiq_videocore_wanted(state)) { -+ if (vchiq_platform_use_suspend_timer() && -+ !arm_state->resume_blocked) { -+ /* Only use the timer if we're not trying to force -+ * suspend (=> resume_blocked) */ -+ start_suspend_timer(arm_state); -+ } else { -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s %s count %d, state count %d - suspending", -+ __func__, entity, *entity_uc, -+ arm_state->videocore_use_count); -+ vchiq_arm_vcsuspend(state); -+ } -+ } else -+ vchiq_log_trace(vchiq_susp_log_level, -+ "%s %s count %d, state count %d", -+ __func__, entity, *entity_uc, -+ arm_state->videocore_use_count); -+ -+unlock: -+ write_unlock_bh(&arm_state->susp_res_lock); -+ -+out: -+ vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); -+ return ret; -+} -+ -+void -+vchiq_on_remote_use(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ atomic_inc(&arm_state->ka_use_count); -+ complete(&arm_state->ka_evt); -+} -+ -+void -+vchiq_on_remote_release(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ atomic_inc(&arm_state->ka_release_count); -+ complete(&arm_state->ka_evt); -+} -+ -+VCHIQ_STATUS_T -+vchiq_use_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); -+} -+ -+VCHIQ_STATUS_T -+vchiq_release_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ return vchiq_release_internal(service->state, service); -+} -+ -+VCHIQ_DEBUGFS_NODE_T * -+vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) -+{ -+ return &instance->debugfs_node; -+} -+ -+int -+vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_SERVICE_T *service; -+ int use_count = 0, i; -+ i = 0; -+ while ((service = next_service_by_instance(instance->state, -+ instance, &i)) != NULL) { -+ use_count += service->service_use_count; -+ unlock_service(service); -+ } -+ return use_count; -+} -+ -+int -+vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance) -+{ -+ return instance->pid; -+} -+ -+int -+vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance) -+{ -+ return instance->trace; -+} -+ -+void -+vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) -+{ -+ VCHIQ_SERVICE_T *service; -+ int i; -+ i = 0; -+ while ((service = next_service_by_instance(instance->state, -+ instance, &i)) != NULL) { -+ service->trace = trace; -+ unlock_service(service); -+ } -+ instance->trace = (trace != 0); -+} -+ -+static void suspend_timer_callback(unsigned long context) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *)context; -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ if (!arm_state) -+ goto out; -+ vchiq_log_info(vchiq_susp_log_level, -+ "%s - suspend timer expired - check suspend", __func__); -+ vchiq_check_suspend(state); -+out: -+ return; -+} -+ -+VCHIQ_STATUS_T -+vchiq_use_service_no_resume(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ if (service) { -+ ret = vchiq_use_internal(service->state, service, -+ USE_TYPE_SERVICE_NO_RESUME); -+ unlock_service(service); -+ } -+ return ret; -+} -+ -+VCHIQ_STATUS_T -+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ if (service) { -+ ret = vchiq_use_internal(service->state, service, -+ USE_TYPE_SERVICE); -+ unlock_service(service); -+ } -+ return ret; -+} -+ -+VCHIQ_STATUS_T -+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ if (service) { -+ ret = vchiq_release_internal(service->state, service); -+ unlock_service(service); -+ } -+ return ret; -+} -+ -+void -+vchiq_dump_service_use_state(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ int i, j = 0; -+ /* Only dump 64 services */ -+ static const int local_max_services = 64; -+ /* If there's more than 64 services, only dump ones with -+ * non-zero counts */ -+ int only_nonzero = 0; -+ static const char *nz = "<-- preventing suspend"; -+ -+ enum vc_suspend_status vc_suspend_state; -+ enum vc_resume_status vc_resume_state; -+ int peer_count; -+ int vc_use_count; -+ int active_services; -+ struct service_data_struct { -+ int fourcc; -+ int clientid; -+ int use_count; -+ } service_data[local_max_services]; -+ -+ if (!arm_state) -+ return; -+ -+ read_lock_bh(&arm_state->susp_res_lock); -+ vc_suspend_state = arm_state->vc_suspend_state; -+ vc_resume_state = arm_state->vc_resume_state; -+ peer_count = arm_state->peer_use_count; -+ vc_use_count = arm_state->videocore_use_count; -+ active_services = state->unused_service; -+ if (active_services > local_max_services) -+ only_nonzero = 1; -+ -+ for (i = 0; (i < active_services) && (j < local_max_services); i++) { -+ VCHIQ_SERVICE_T *service_ptr = state->services[i]; -+ if (!service_ptr) -+ continue; -+ -+ if (only_nonzero && !service_ptr->service_use_count) -+ continue; -+ -+ if (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE) { -+ service_data[j].fourcc = service_ptr->base.fourcc; -+ service_data[j].clientid = service_ptr->client_id; -+ service_data[j++].use_count = service_ptr-> -+ service_use_count; -+ } -+ } -+ -+ read_unlock_bh(&arm_state->susp_res_lock); -+ -+ vchiq_log_warning(vchiq_susp_log_level, -+ "-- Videcore suspend state: %s --", -+ suspend_state_names[vc_suspend_state + VC_SUSPEND_NUM_OFFSET]); -+ vchiq_log_warning(vchiq_susp_log_level, -+ "-- Videcore resume state: %s --", -+ resume_state_names[vc_resume_state + VC_RESUME_NUM_OFFSET]); -+ -+ if (only_nonzero) -+ vchiq_log_warning(vchiq_susp_log_level, "Too many active " -+ "services (%d). Only dumping up to first %d services " -+ "with non-zero use-count", active_services, -+ local_max_services); -+ -+ for (i = 0; i < j; i++) { -+ vchiq_log_warning(vchiq_susp_log_level, -+ "----- %c%c%c%c:%d service count %d %s", -+ VCHIQ_FOURCC_AS_4CHARS(service_data[i].fourcc), -+ service_data[i].clientid, -+ service_data[i].use_count, -+ service_data[i].use_count ? nz : ""); -+ } -+ vchiq_log_warning(vchiq_susp_log_level, -+ "----- VCHIQ use count count %d", peer_count); -+ vchiq_log_warning(vchiq_susp_log_level, -+ "--- Overall vchiq instance use count %d", vc_use_count); -+ -+ vchiq_dump_platform_use_state(state); -+} -+ -+VCHIQ_STATUS_T -+vchiq_check_service(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_ARM_STATE_T *arm_state; -+ VCHIQ_STATUS_T ret = VCHIQ_ERROR; -+ -+ if (!service || !service->state) -+ goto out; -+ -+ vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); -+ -+ arm_state = vchiq_platform_get_arm_state(service->state); -+ -+ read_lock_bh(&arm_state->susp_res_lock); -+ if (service->service_use_count) -+ ret = VCHIQ_SUCCESS; -+ read_unlock_bh(&arm_state->susp_res_lock); -+ -+ if (ret == VCHIQ_ERROR) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "%s ERROR - %c%c%c%c:%d service count %d, " -+ "state count %d, videocore suspend state %s", __func__, -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->client_id, service->service_use_count, -+ arm_state->videocore_use_count, -+ suspend_state_names[arm_state->vc_suspend_state + -+ VC_SUSPEND_NUM_OFFSET]); -+ vchiq_dump_service_use_state(service->state); -+ } -+out: -+ return ret; -+} -+ -+/* stub functions */ -+void vchiq_on_remote_use_active(VCHIQ_STATE_T *state) -+{ -+ (void)state; -+} -+ -+void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, -+ VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate) -+{ -+ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); -+ vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id, -+ get_conn_state_name(oldstate), get_conn_state_name(newstate)); -+ if (state->conn_state == VCHIQ_CONNSTATE_CONNECTED) { -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (!arm_state->first_connect) { -+ char threadname[10]; -+ arm_state->first_connect = 1; -+ write_unlock_bh(&arm_state->susp_res_lock); -+ snprintf(threadname, sizeof(threadname), "VCHIQka-%d", -+ state->id); -+ arm_state->ka_thread = kthread_create( -+ &vchiq_keepalive_thread_func, -+ (void *)state, -+ threadname); -+ if (arm_state->ka_thread == NULL) { -+ vchiq_log_error(vchiq_susp_log_level, -+ "vchiq: FATAL: couldn't create thread %s", -+ threadname); -+ } else { -+ wake_up_process(arm_state->ka_thread); -+ } -+ } else -+ write_unlock_bh(&arm_state->susp_res_lock); -+ } -+} -+ -+static int vchiq_probe(struct platform_device *pdev) -+{ -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ int err; -+ void *ptr_err; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+/* Remove comment when booting without Device Tree is no longer supported -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+*/ -+ fw = rpi_firmware_get(fw_node); -+ if (!fw) -+ return -EPROBE_DEFER; -+ -+ platform_set_drvdata(pdev, fw); -+ -+ /* create debugfs entries */ -+ err = vchiq_debugfs_init(); -+ if (err != 0) -+ goto failed_debugfs_init; -+ -+ err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME); -+ if (err != 0) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to allocate device number"); -+ goto failed_alloc_chrdev; -+ } -+ cdev_init(&vchiq_cdev, &vchiq_fops); -+ vchiq_cdev.owner = THIS_MODULE; -+ err = cdev_add(&vchiq_cdev, vchiq_devid, 1); -+ if (err != 0) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to register device"); -+ goto failed_cdev_add; -+ } -+ -+ /* create sysfs entries */ -+ vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); -+ ptr_err = vchiq_class; -+ if (IS_ERR(ptr_err)) -+ goto failed_class_create; -+ -+ vchiq_dev = device_create(vchiq_class, NULL, -+ vchiq_devid, NULL, "vchiq"); -+ ptr_err = vchiq_dev; -+ if (IS_ERR(ptr_err)) -+ goto failed_device_create; -+ -+ err = vchiq_platform_init(pdev, &g_state); -+ if (err != 0) -+ goto failed_platform_init; -+ -+ vchiq_log_info(vchiq_arm_log_level, -+ "vchiq: initialised - version %d (min %d), device %d.%d", -+ VCHIQ_VERSION, VCHIQ_VERSION_MIN, -+ MAJOR(vchiq_devid), MINOR(vchiq_devid)); -+ -+ return 0; -+ -+failed_platform_init: -+ device_destroy(vchiq_class, vchiq_devid); -+failed_device_create: -+ class_destroy(vchiq_class); -+failed_class_create: -+ cdev_del(&vchiq_cdev); -+ err = PTR_ERR(ptr_err); -+failed_cdev_add: -+ unregister_chrdev_region(vchiq_devid, 1); -+failed_alloc_chrdev: -+ vchiq_debugfs_deinit(); -+failed_debugfs_init: -+ vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq"); -+ return err; -+} -+ -+static int vchiq_remove(struct platform_device *pdev) -+{ -+ device_destroy(vchiq_class, vchiq_devid); -+ class_destroy(vchiq_class); -+ cdev_del(&vchiq_cdev); -+ unregister_chrdev_region(vchiq_devid, 1); -+ -+ return 0; -+} -+ -+static const struct of_device_id vchiq_of_match[] = { -+ { .compatible = "brcm,bcm2835-vchiq", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, vchiq_of_match); -+ -+static struct platform_driver vchiq_driver = { -+ .driver = { -+ .name = "bcm2835_vchiq", -+ .owner = THIS_MODULE, -+ .of_match_table = vchiq_of_match, -+ }, -+ .probe = vchiq_probe, -+ .remove = vchiq_remove, -+}; -+module_platform_driver(vchiq_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -new file mode 100644 -index 0000000000000000000000000000000000000000..9740e1afbc9dc6223f2fea5106916062a3e783ce ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -@@ -0,0 +1,220 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_ARM_H -+#define VCHIQ_ARM_H -+ -+#include -+#include -+#include -+#include -+#include "vchiq_core.h" -+#include "vchiq_debugfs.h" -+ -+ -+enum vc_suspend_status { -+ VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */ -+ VC_SUSPEND_REJECTED = -2, /* Videocore rejected suspend request */ -+ VC_SUSPEND_FAILED = -1, /* Videocore suspend failed */ -+ VC_SUSPEND_IDLE = 0, /* VC active, no suspend actions */ -+ VC_SUSPEND_REQUESTED, /* User has requested suspend */ -+ VC_SUSPEND_IN_PROGRESS, /* Slot handler has recvd suspend request */ -+ VC_SUSPEND_SUSPENDED /* Videocore suspend succeeded */ -+}; -+ -+enum vc_resume_status { -+ VC_RESUME_FAILED = -1, /* Videocore resume failed */ -+ VC_RESUME_IDLE = 0, /* VC suspended, no resume actions */ -+ VC_RESUME_REQUESTED, /* User has requested resume */ -+ VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */ -+ VC_RESUME_RESUMED /* Videocore resumed successfully (active) */ -+}; -+ -+ -+enum USE_TYPE_E { -+ USE_TYPE_SERVICE, -+ USE_TYPE_SERVICE_NO_RESUME, -+ USE_TYPE_VCHIQ -+}; -+ -+ -+ -+typedef struct vchiq_arm_state_struct { -+ /* Keepalive-related data */ -+ struct task_struct *ka_thread; -+ struct completion ka_evt; -+ atomic_t ka_use_count; -+ atomic_t ka_use_ack_count; -+ atomic_t ka_release_count; -+ -+ struct completion vc_suspend_complete; -+ struct completion vc_resume_complete; -+ -+ rwlock_t susp_res_lock; -+ enum vc_suspend_status vc_suspend_state; -+ enum vc_resume_status vc_resume_state; -+ -+ unsigned int wake_address; -+ -+ struct timer_list suspend_timer; -+ int suspend_timer_timeout; -+ int suspend_timer_running; -+ -+ /* Global use count for videocore. -+ ** This is equal to the sum of the use counts for all services. When -+ ** this hits zero the videocore suspend procedure will be initiated. -+ */ -+ int videocore_use_count; -+ -+ /* Use count to track requests from videocore peer. -+ ** This use count is not associated with a service, so needs to be -+ ** tracked separately with the state. -+ */ -+ int peer_use_count; -+ -+ /* Flag to indicate whether resume is blocked. This happens when the -+ ** ARM is suspending -+ */ -+ struct completion resume_blocker; -+ int resume_blocked; -+ struct completion blocked_blocker; -+ int blocked_count; -+ -+ int autosuspend_override; -+ -+ /* Flag to indicate that the first vchiq connect has made it through. -+ ** This means that both sides should be fully ready, and we should -+ ** be able to suspend after this point. -+ */ -+ int first_connect; -+ -+ unsigned long long suspend_start_time; -+ unsigned long long sleep_start_time; -+ unsigned long long resume_start_time; -+ unsigned long long last_wake_time; -+ -+} VCHIQ_ARM_STATE_T; -+ -+extern int vchiq_arm_log_level; -+extern int vchiq_susp_log_level; -+ -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATE_T * -+vchiq_get_state(void); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_vcsuspend(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_force_suspend(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_arm_allow_resume(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_vcresume(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state); -+ -+extern int -+vchiq_check_resume(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_check_suspend(VCHIQ_STATE_T *state); -+ VCHIQ_STATUS_T -+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_STATUS_T -+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_STATUS_T -+vchiq_check_service(VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_platform_suspend(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_platform_use_suspend_timer(void); -+ -+extern void -+vchiq_dump_platform_use_state(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_dump_service_use_state(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_ARM_STATE_T* -+vchiq_platform_get_arm_state(VCHIQ_STATE_T *state); -+ -+extern int -+vchiq_videocore_wanted(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ enum USE_TYPE_E use_type); -+extern VCHIQ_STATUS_T -+vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_DEBUGFS_NODE_T * -+vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance); -+ -+extern int -+vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance); -+ -+extern int -+vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance); -+ -+extern int -+vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance); -+ -+extern void -+vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace); -+ -+extern void -+set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_suspend_status new_state); -+ -+extern void -+set_resume_state(VCHIQ_ARM_STATE_T *arm_state, -+ enum vc_resume_status new_state); -+ -+extern void -+start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state); -+ -+ -+#endif /* VCHIQ_ARM_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h -new file mode 100644 -index 0000000000000000000000000000000000000000..df645813bdaeb2cd6296154af434ebc1b0c5939a ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h -@@ -0,0 +1,37 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+const char *vchiq_get_build_hostname(void); -+const char *vchiq_get_build_version(void); -+const char *vchiq_get_build_time(void); -+const char *vchiq_get_build_date(void); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h -new file mode 100644 -index 0000000000000000000000000000000000000000..d2797db702f9fd2e35beb3dd2d5ac9323ccedfc6 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h -@@ -0,0 +1,69 @@ -+/** -+ * Copyright (c) 2010-2014 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_CFG_H -+#define VCHIQ_CFG_H -+ -+#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I') -+/* The version of VCHIQ - change with any non-trivial change */ -+#define VCHIQ_VERSION 8 -+/* The minimum compatible version - update to match VCHIQ_VERSION with any -+** incompatible change */ -+#define VCHIQ_VERSION_MIN 3 -+ -+/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */ -+#define VCHIQ_VERSION_LIB_VERSION 7 -+ -+/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */ -+#define VCHIQ_VERSION_CLOSE_DELIVERED 7 -+ -+/* The version that made it safe to use SYNCHRONOUS mode */ -+#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8 -+ -+#define VCHIQ_MAX_STATES 1 -+#define VCHIQ_MAX_SERVICES 4096 -+#define VCHIQ_MAX_SLOTS 128 -+#define VCHIQ_MAX_SLOTS_PER_SIDE 64 -+ -+#define VCHIQ_NUM_CURRENT_BULKS 32 -+#define VCHIQ_NUM_SERVICE_BULKS 4 -+ -+#ifndef VCHIQ_ENABLE_DEBUG -+#define VCHIQ_ENABLE_DEBUG 1 -+#endif -+ -+#ifndef VCHIQ_ENABLE_STATS -+#define VCHIQ_ENABLE_STATS 1 -+#endif -+ -+#endif /* VCHIQ_CFG_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c -new file mode 100644 -index 0000000000000000000000000000000000000000..5efc62ffb2f5e441cb307d0a575565338b407249 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c -@@ -0,0 +1,120 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "vchiq_connected.h" -+#include "vchiq_core.h" -+#include "vchiq_killable.h" -+#include -+#include -+ -+#define MAX_CALLBACKS 10 -+ -+static int g_connected; -+static int g_num_deferred_callbacks; -+static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; -+static int g_once_init; -+static struct mutex g_connected_mutex; -+ -+/**************************************************************************** -+* -+* Function to initialize our lock. -+* -+***************************************************************************/ -+ -+static void connected_init(void) -+{ -+ if (!g_once_init) { -+ mutex_init(&g_connected_mutex); -+ g_once_init = 1; -+ } -+} -+ -+/**************************************************************************** -+* -+* This function is used to defer initialization until the vchiq stack is -+* initialized. If the stack is already initialized, then the callback will -+* be made immediately, otherwise it will be deferred until -+* vchiq_call_connected_callbacks is called. -+* -+***************************************************************************/ -+ -+void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) -+{ -+ connected_init(); -+ -+ if (mutex_lock_interruptible(&g_connected_mutex) != 0) -+ return; -+ -+ if (g_connected) -+ /* We're already connected. Call the callback immediately. */ -+ -+ callback(); -+ else { -+ if (g_num_deferred_callbacks >= MAX_CALLBACKS) -+ vchiq_log_error(vchiq_core_log_level, -+ "There already %d callback registered - " -+ "please increase MAX_CALLBACKS", -+ g_num_deferred_callbacks); -+ else { -+ g_deferred_callback[g_num_deferred_callbacks] = -+ callback; -+ g_num_deferred_callbacks++; -+ } -+ } -+ mutex_unlock(&g_connected_mutex); -+} -+ -+/**************************************************************************** -+* -+* This function is called by the vchiq stack once it has been connected to -+* the videocore and clients can start to use the stack. -+* -+***************************************************************************/ -+ -+void vchiq_call_connected_callbacks(void) -+{ -+ int i; -+ -+ connected_init(); -+ -+ if (mutex_lock_interruptible(&g_connected_mutex) != 0) -+ return; -+ -+ for (i = 0; i < g_num_deferred_callbacks; i++) -+ g_deferred_callback[i](); -+ -+ g_num_deferred_callbacks = 0; -+ g_connected = 1; -+ mutex_unlock(&g_connected_mutex); -+} -+EXPORT_SYMBOL(vchiq_add_connected_callback); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h -new file mode 100644 -index 0000000000000000000000000000000000000000..863b3e335c1aa4bbe7f8652e0e6c3713ea1aed45 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h -@@ -0,0 +1,50 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_CONNECTED_H -+#define VCHIQ_CONNECTED_H -+ -+/* ---- Include Files ----------------------------------------------------- */ -+ -+/* ---- Constants and Types ---------------------------------------------- */ -+ -+typedef void (*VCHIQ_CONNECTED_CALLBACK_T)(void); -+ -+/* ---- Variable Externs ------------------------------------------------- */ -+ -+/* ---- Function Prototypes ---------------------------------------------- */ -+ -+void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback); -+void vchiq_call_connected_callbacks(void); -+ -+#endif /* VCHIQ_CONNECTED_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -new file mode 100644 -index 0000000000000000000000000000000000000000..71a3bedc55314f3b22dbff40c05dedf03b5e7169 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -0,0 +1,3933 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "vchiq_core.h" -+#include "vchiq_killable.h" -+ -+#define VCHIQ_SLOT_HANDLER_STACK 8192 -+ -+#define HANDLE_STATE_SHIFT 12 -+ -+#define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index)) -+#define SLOT_DATA_FROM_INDEX(state, index) (state->slot_data + (index)) -+#define SLOT_INDEX_FROM_DATA(state, data) \ -+ (((unsigned int)((char *)data - (char *)state->slot_data)) / \ -+ VCHIQ_SLOT_SIZE) -+#define SLOT_INDEX_FROM_INFO(state, info) \ -+ ((unsigned int)(info - state->slot_info)) -+#define SLOT_QUEUE_INDEX_FROM_POS(pos) \ -+ ((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE)) -+ -+#define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1)) -+ -+#define SRVTRACE_LEVEL(srv) \ -+ (((srv) && (srv)->trace) ? VCHIQ_LOG_TRACE : vchiq_core_msg_log_level) -+#define SRVTRACE_ENABLED(srv, lev) \ -+ (((srv) && (srv)->trace) || (vchiq_core_msg_log_level >= (lev))) -+ -+struct vchiq_open_payload { -+ int fourcc; -+ int client_id; -+ short version; -+ short version_min; -+}; -+ -+struct vchiq_openack_payload { -+ short version; -+}; -+ -+enum -+{ -+ QMFLAGS_IS_BLOCKING = (1 << 0), -+ QMFLAGS_NO_MUTEX_LOCK = (1 << 1), -+ QMFLAGS_NO_MUTEX_UNLOCK = (1 << 2) -+}; -+ -+/* we require this for consistency between endpoints */ -+vchiq_static_assert(sizeof(VCHIQ_HEADER_T) == 8); -+vchiq_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T))); -+vchiq_static_assert(IS_POW2(VCHIQ_NUM_CURRENT_BULKS)); -+vchiq_static_assert(IS_POW2(VCHIQ_NUM_SERVICE_BULKS)); -+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SERVICES)); -+vchiq_static_assert(VCHIQ_VERSION >= VCHIQ_VERSION_MIN); -+ -+/* Run time control of log level, based on KERN_XXX level. */ -+int vchiq_core_log_level = VCHIQ_LOG_DEFAULT; -+int vchiq_core_msg_log_level = VCHIQ_LOG_DEFAULT; -+int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT; -+ -+static atomic_t pause_bulks_count = ATOMIC_INIT(0); -+ -+static DEFINE_SPINLOCK(service_spinlock); -+DEFINE_SPINLOCK(bulk_waiter_spinlock); -+DEFINE_SPINLOCK(quota_spinlock); -+ -+VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; -+static unsigned int handle_seq; -+ -+static const char *const srvstate_names[] = { -+ "FREE", -+ "HIDDEN", -+ "LISTENING", -+ "OPENING", -+ "OPEN", -+ "OPENSYNC", -+ "CLOSESENT", -+ "CLOSERECVD", -+ "CLOSEWAIT", -+ "CLOSED" -+}; -+ -+static const char *const reason_names[] = { -+ "SERVICE_OPENED", -+ "SERVICE_CLOSED", -+ "MESSAGE_AVAILABLE", -+ "BULK_TRANSMIT_DONE", -+ "BULK_RECEIVE_DONE", -+ "BULK_TRANSMIT_ABORTED", -+ "BULK_RECEIVE_ABORTED" -+}; -+ -+static const char *const conn_state_names[] = { -+ "DISCONNECTED", -+ "CONNECTING", -+ "CONNECTED", -+ "PAUSING", -+ "PAUSE_SENT", -+ "PAUSED", -+ "RESUMING", -+ "PAUSE_TIMEOUT", -+ "RESUME_TIMEOUT" -+}; -+ -+ -+static void -+release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header); -+ -+static const char *msg_type_str(unsigned int msg_type) -+{ -+ switch (msg_type) { -+ case VCHIQ_MSG_PADDING: return "PADDING"; -+ case VCHIQ_MSG_CONNECT: return "CONNECT"; -+ case VCHIQ_MSG_OPEN: return "OPEN"; -+ case VCHIQ_MSG_OPENACK: return "OPENACK"; -+ case VCHIQ_MSG_CLOSE: return "CLOSE"; -+ case VCHIQ_MSG_DATA: return "DATA"; -+ case VCHIQ_MSG_BULK_RX: return "BULK_RX"; -+ case VCHIQ_MSG_BULK_TX: return "BULK_TX"; -+ case VCHIQ_MSG_BULK_RX_DONE: return "BULK_RX_DONE"; -+ case VCHIQ_MSG_BULK_TX_DONE: return "BULK_TX_DONE"; -+ case VCHIQ_MSG_PAUSE: return "PAUSE"; -+ case VCHIQ_MSG_RESUME: return "RESUME"; -+ case VCHIQ_MSG_REMOTE_USE: return "REMOTE_USE"; -+ case VCHIQ_MSG_REMOTE_RELEASE: return "REMOTE_RELEASE"; -+ case VCHIQ_MSG_REMOTE_USE_ACTIVE: return "REMOTE_USE_ACTIVE"; -+ } -+ return "???"; -+} -+ -+static inline void -+vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate) -+{ -+ vchiq_log_info(vchiq_core_log_level, "%d: srv:%d %s->%s", -+ service->state->id, service->localport, -+ srvstate_names[service->srvstate], -+ srvstate_names[newstate]); -+ service->srvstate = newstate; -+} -+ -+VCHIQ_SERVICE_T * -+find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service; -+ -+ spin_lock(&service_spinlock); -+ service = handle_to_service(handle); -+ if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (service->handle == handle)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid service handle 0x%x", handle); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+find_service_by_port(VCHIQ_STATE_T *state, int localport) -+{ -+ VCHIQ_SERVICE_T *service = NULL; -+ if ((unsigned int)localport <= VCHIQ_PORT_MAX) { -+ spin_lock(&service_spinlock); -+ service = state->services[localport]; -+ if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ } -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid port %d", localport); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+find_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle) { -+ VCHIQ_SERVICE_T *service; -+ -+ spin_lock(&service_spinlock); -+ service = handle_to_service(handle); -+ if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (service->handle == handle) && -+ (service->instance == instance)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid service handle 0x%x", handle); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle) { -+ VCHIQ_SERVICE_T *service; -+ -+ spin_lock(&service_spinlock); -+ service = handle_to_service(handle); -+ if (service && -+ ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_CLOSED)) && -+ (service->handle == handle) && -+ (service->instance == instance)) { -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ } else -+ service = NULL; -+ spin_unlock(&service_spinlock); -+ -+ if (!service) -+ vchiq_log_info(vchiq_core_log_level, -+ "Invalid service handle 0x%x", handle); -+ -+ return service; -+} -+ -+VCHIQ_SERVICE_T * -+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, -+ int *pidx) -+{ -+ VCHIQ_SERVICE_T *service = NULL; -+ int idx = *pidx; -+ -+ spin_lock(&service_spinlock); -+ while (idx < state->unused_service) { -+ VCHIQ_SERVICE_T *srv = state->services[idx++]; -+ if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (srv->instance == instance)) { -+ service = srv; -+ BUG_ON(service->ref_count == 0); -+ service->ref_count++; -+ break; -+ } -+ } -+ spin_unlock(&service_spinlock); -+ -+ *pidx = idx; -+ -+ return service; -+} -+ -+void -+lock_service(VCHIQ_SERVICE_T *service) -+{ -+ spin_lock(&service_spinlock); -+ BUG_ON(!service || (service->ref_count == 0)); -+ if (service) -+ service->ref_count++; -+ spin_unlock(&service_spinlock); -+} -+ -+void -+unlock_service(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ spin_lock(&service_spinlock); -+ BUG_ON(!service || (service->ref_count == 0)); -+ if (service && service->ref_count) { -+ service->ref_count--; -+ if (!service->ref_count) { -+ BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); -+ state->services[service->localport] = NULL; -+ } else -+ service = NULL; -+ } -+ spin_unlock(&service_spinlock); -+ -+ if (service && service->userdata_term) -+ service->userdata_term(service->base.userdata); -+ -+ kfree(service); -+} -+ -+int -+vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ int id; -+ -+ id = service ? service->client_id : 0; -+ if (service) -+ unlock_service(service); -+ -+ return id; -+} -+ -+void * -+vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service = handle_to_service(handle); -+ -+ return service ? service->base.userdata : NULL; -+} -+ -+int -+vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_SERVICE_T *service = handle_to_service(handle); -+ -+ return service ? service->base.fourcc : 0; -+} -+ -+static void -+mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ VCHIQ_SERVICE_QUOTA_T *service_quota; -+ -+ service->closing = 1; -+ -+ /* Synchronise with other threads. */ -+ mutex_lock(&state->recycle_mutex); -+ mutex_unlock(&state->recycle_mutex); -+ if (!sh_thread || (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT)) { -+ /* If we're pausing then the slot_mutex is held until resume -+ * by the slot handler. Therefore don't try to acquire this -+ * mutex if we're the slot handler and in the pause sent state. -+ * We don't need to in this case anyway. */ -+ mutex_lock(&state->slot_mutex); -+ mutex_unlock(&state->slot_mutex); -+ } -+ -+ /* Unblock any sending thread. */ -+ service_quota = &state->service_quotas[service->localport]; -+ up(&service_quota->quota_event); -+} -+ -+static void -+mark_service_closing(VCHIQ_SERVICE_T *service) -+{ -+ mark_service_closing_internal(service, 0); -+} -+ -+static inline VCHIQ_STATUS_T -+make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, void *bulk_userdata) -+{ -+ VCHIQ_STATUS_T status; -+ vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %x, %x)", -+ service->state->id, service->localport, reason_names[reason], -+ (unsigned int)header, (unsigned int)bulk_userdata); -+ status = service->base.callback(reason, header, service->handle, -+ bulk_userdata); -+ if (status == VCHIQ_ERROR) { -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: ignoring ERROR from callback to service %x", -+ service->state->id, service->handle); -+ status = VCHIQ_SUCCESS; -+ } -+ return status; -+} -+ -+inline void -+vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate) -+{ -+ VCHIQ_CONNSTATE_T oldstate = state->conn_state; -+ vchiq_log_info(vchiq_core_log_level, "%d: %s->%s", state->id, -+ conn_state_names[oldstate], -+ conn_state_names[newstate]); -+ state->conn_state = newstate; -+ vchiq_platform_conn_state_changed(state, oldstate, newstate); -+} -+ -+static inline void -+remote_event_create(REMOTE_EVENT_T *event) -+{ -+ event->armed = 0; -+ /* Don't clear the 'fired' flag because it may already have been set -+ ** by the other side. */ -+ sema_init(event->event, 0); -+} -+ -+static inline void -+remote_event_destroy(REMOTE_EVENT_T *event) -+{ -+ (void)event; -+} -+ -+static inline int -+remote_event_wait(REMOTE_EVENT_T *event) -+{ -+ if (!event->fired) { -+ event->armed = 1; -+ dsb(); -+ if (!event->fired) { -+ if (down_interruptible(event->event) != 0) { -+ event->armed = 0; -+ return 0; -+ } -+ } -+ event->armed = 0; -+ wmb(); -+ } -+ -+ event->fired = 0; -+ return 1; -+} -+ -+static inline void -+remote_event_signal_local(REMOTE_EVENT_T *event) -+{ -+ event->armed = 0; -+ up(event->event); -+} -+ -+static inline void -+remote_event_poll(REMOTE_EVENT_T *event) -+{ -+ if (event->fired && event->armed) -+ remote_event_signal_local(event); -+} -+ -+void -+remote_event_pollall(VCHIQ_STATE_T *state) -+{ -+ remote_event_poll(&state->local->sync_trigger); -+ remote_event_poll(&state->local->sync_release); -+ remote_event_poll(&state->local->trigger); -+ remote_event_poll(&state->local->recycle); -+} -+ -+/* Round up message sizes so that any space at the end of a slot is always big -+** enough for a header. This relies on header size being a power of two, which -+** has been verified earlier by a static assertion. */ -+ -+static inline unsigned int -+calc_stride(unsigned int size) -+{ -+ /* Allow room for the header */ -+ size += sizeof(VCHIQ_HEADER_T); -+ -+ /* Round up */ -+ return (size + sizeof(VCHIQ_HEADER_T) - 1) & ~(sizeof(VCHIQ_HEADER_T) -+ - 1); -+} -+ -+/* Called by the slot handler thread */ -+static VCHIQ_SERVICE_T * -+get_listening_service(VCHIQ_STATE_T *state, int fourcc) -+{ -+ int i; -+ -+ WARN_ON(fourcc == VCHIQ_FOURCC_INVALID); -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ if (service && -+ (service->public_fourcc == fourcc) && -+ ((service->srvstate == VCHIQ_SRVSTATE_LISTENING) || -+ ((service->srvstate == VCHIQ_SRVSTATE_OPEN) && -+ (service->remoteport == VCHIQ_PORT_FREE)))) { -+ lock_service(service); -+ return service; -+ } -+ } -+ -+ return NULL; -+} -+ -+/* Called by the slot handler thread */ -+static VCHIQ_SERVICE_T * -+get_connected_service(VCHIQ_STATE_T *state, unsigned int port) -+{ -+ int i; -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN) -+ && (service->remoteport == port)) { -+ lock_service(service); -+ return service; -+ } -+ } -+ return NULL; -+} -+ -+inline void -+request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) -+{ -+ uint32_t value; -+ -+ if (service) { -+ do { -+ value = atomic_read(&service->poll_flags); -+ } while (atomic_cmpxchg(&service->poll_flags, value, -+ value | (1 << poll_type)) != value); -+ -+ do { -+ value = atomic_read(&state->poll_services[ -+ service->localport>>5]); -+ } while (atomic_cmpxchg( -+ &state->poll_services[service->localport>>5], -+ value, value | (1 << (service->localport & 0x1f))) -+ != value); -+ } -+ -+ state->poll_needed = 1; -+ wmb(); -+ -+ /* ... and ensure the slot handler runs. */ -+ remote_event_signal_local(&state->local->trigger); -+} -+ -+/* Called from queue_message, by the slot handler and application threads, -+** with slot_mutex held */ -+static VCHIQ_HEADER_T * -+reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking) -+{ -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ int tx_pos = state->local_tx_pos; -+ int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK); -+ -+ if (space > slot_space) { -+ VCHIQ_HEADER_T *header; -+ /* Fill the remaining space with padding */ -+ WARN_ON(state->tx_data == NULL); -+ header = (VCHIQ_HEADER_T *) -+ (state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); -+ header->msgid = VCHIQ_MSGID_PADDING; -+ header->size = slot_space - sizeof(VCHIQ_HEADER_T); -+ -+ tx_pos += slot_space; -+ } -+ -+ /* If necessary, get the next slot. */ -+ if ((tx_pos & VCHIQ_SLOT_MASK) == 0) { -+ int slot_index; -+ -+ /* If there is no free slot... */ -+ -+ if (down_trylock(&state->slot_available_event) != 0) { -+ /* ...wait for one. */ -+ -+ VCHIQ_STATS_INC(state, slot_stalls); -+ -+ /* But first, flush through the last slot. */ -+ state->local_tx_pos = tx_pos; -+ local->tx_pos = tx_pos; -+ remote_event_signal(&state->remote->trigger); -+ -+ if (!is_blocking || -+ (down_interruptible( -+ &state->slot_available_event) != 0)) -+ return NULL; /* No space available */ -+ } -+ -+ BUG_ON(tx_pos == -+ (state->slot_queue_available * VCHIQ_SLOT_SIZE)); -+ -+ slot_index = local->slot_queue[ -+ SLOT_QUEUE_INDEX_FROM_POS(tx_pos) & -+ VCHIQ_SLOT_QUEUE_MASK]; -+ state->tx_data = -+ (char *)SLOT_DATA_FROM_INDEX(state, slot_index); -+ } -+ -+ state->local_tx_pos = tx_pos + space; -+ -+ return (VCHIQ_HEADER_T *)(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); -+} -+ -+/* Called by the recycle thread. */ -+static void -+process_free_queue(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; -+ int slot_queue_available; -+ -+ /* Find slots which have been freed by the other side, and return them -+ ** to the available queue. */ -+ slot_queue_available = state->slot_queue_available; -+ -+ /* Use a memory barrier to ensure that any state that may have been -+ ** modified by another thread is not masked by stale prefetched -+ ** values. */ -+ mb(); -+ -+ while (slot_queue_available != local->slot_queue_recycle) { -+ unsigned int pos; -+ int slot_index = local->slot_queue[slot_queue_available++ & -+ VCHIQ_SLOT_QUEUE_MASK]; -+ char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); -+ int data_found = 0; -+ -+ rmb(); -+ -+ vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", -+ state->id, slot_index, (unsigned int)data, -+ local->slot_queue_recycle, slot_queue_available); -+ -+ /* Initialise the bitmask for services which have used this -+ ** slot */ -+ BITSET_ZERO(service_found); -+ -+ pos = 0; -+ -+ while (pos < VCHIQ_SLOT_SIZE) { -+ VCHIQ_HEADER_T *header = -+ (VCHIQ_HEADER_T *)(data + pos); -+ int msgid = header->msgid; -+ if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) { -+ int port = VCHIQ_MSG_SRCPORT(msgid); -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &state->service_quotas[port]; -+ int count; -+ spin_lock("a_spinlock); -+ count = service_quota->message_use_count; -+ if (count > 0) -+ service_quota->message_use_count = -+ count - 1; -+ spin_unlock("a_spinlock); -+ -+ if (count == service_quota->message_quota) -+ /* Signal the service that it -+ ** has dropped below its quota -+ */ -+ up(&service_quota->quota_event); -+ else if (count == 0) { -+ vchiq_log_error(vchiq_core_log_level, -+ "service %d " -+ "message_use_count=%d " -+ "(header %x, msgid %x, " -+ "header->msgid %x, " -+ "header->size %x)", -+ port, -+ service_quota-> -+ message_use_count, -+ (unsigned int)header, msgid, -+ header->msgid, -+ header->size); -+ WARN(1, "invalid message use count\n"); -+ } -+ if (!BITSET_IS_SET(service_found, port)) { -+ /* Set the found bit for this service */ -+ BITSET_SET(service_found, port); -+ -+ spin_lock("a_spinlock); -+ count = service_quota->slot_use_count; -+ if (count > 0) -+ service_quota->slot_use_count = -+ count - 1; -+ spin_unlock("a_spinlock); -+ -+ if (count > 0) { -+ /* Signal the service in case -+ ** it has dropped below its -+ ** quota */ -+ up(&service_quota->quota_event); -+ vchiq_log_trace( -+ vchiq_core_log_level, -+ "%d: pfq:%d %x@%x - " -+ "slot_use->%d", -+ state->id, port, -+ header->size, -+ (unsigned int)header, -+ count - 1); -+ } else { -+ vchiq_log_error( -+ vchiq_core_log_level, -+ "service %d " -+ "slot_use_count" -+ "=%d (header %x" -+ ", msgid %x, " -+ "header->msgid" -+ " %x, header->" -+ "size %x)", -+ port, count, -+ (unsigned int)header, -+ msgid, -+ header->msgid, -+ header->size); -+ WARN(1, "bad slot use count\n"); -+ } -+ } -+ -+ data_found = 1; -+ } -+ -+ pos += calc_stride(header->size); -+ if (pos > VCHIQ_SLOT_SIZE) { -+ vchiq_log_error(vchiq_core_log_level, -+ "pfq - pos %x: header %x, msgid %x, " -+ "header->msgid %x, header->size %x", -+ pos, (unsigned int)header, msgid, -+ header->msgid, header->size); -+ WARN(1, "invalid slot position\n"); -+ } -+ } -+ -+ if (data_found) { -+ int count; -+ spin_lock("a_spinlock); -+ count = state->data_use_count; -+ if (count > 0) -+ state->data_use_count = -+ count - 1; -+ spin_unlock("a_spinlock); -+ if (count == state->data_quota) -+ up(&state->data_quota_event); -+ } -+ -+ mb(); -+ -+ state->slot_queue_available = slot_queue_available; -+ up(&state->slot_available_event); -+ } -+} -+ -+/* Called by the slot handler and application threads */ -+static VCHIQ_STATUS_T -+queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ int msgid, const VCHIQ_ELEMENT_T *elements, -+ int count, int size, int flags) -+{ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_SERVICE_QUOTA_T *service_quota = NULL; -+ VCHIQ_HEADER_T *header; -+ int type = VCHIQ_MSG_TYPE(msgid); -+ -+ unsigned int stride; -+ -+ local = state->local; -+ -+ stride = calc_stride(size); -+ -+ WARN_ON(!(stride <= VCHIQ_SLOT_SIZE)); -+ -+ if (!(flags & QMFLAGS_NO_MUTEX_LOCK) && -+ (mutex_lock_interruptible(&state->slot_mutex) != 0)) -+ return VCHIQ_RETRY; -+ -+ if (type == VCHIQ_MSG_DATA) { -+ int tx_end_index; -+ -+ BUG_ON(!service); -+ BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | -+ QMFLAGS_NO_MUTEX_UNLOCK)) != 0); -+ -+ if (service->closing) { -+ /* The service has been closed */ -+ mutex_unlock(&state->slot_mutex); -+ return VCHIQ_ERROR; -+ } -+ -+ service_quota = &state->service_quotas[service->localport]; -+ -+ spin_lock("a_spinlock); -+ -+ /* Ensure this service doesn't use more than its quota of -+ ** messages or slots */ -+ tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( -+ state->local_tx_pos + stride - 1); -+ -+ /* Ensure data messages don't use more than their quota of -+ ** slots */ -+ while ((tx_end_index != state->previous_data_index) && -+ (state->data_use_count == state->data_quota)) { -+ VCHIQ_STATS_INC(state, data_stalls); -+ spin_unlock("a_spinlock); -+ mutex_unlock(&state->slot_mutex); -+ -+ if (down_interruptible(&state->data_quota_event) -+ != 0) -+ return VCHIQ_RETRY; -+ -+ mutex_lock(&state->slot_mutex); -+ spin_lock("a_spinlock); -+ tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( -+ state->local_tx_pos + stride - 1); -+ if ((tx_end_index == state->previous_data_index) || -+ (state->data_use_count < state->data_quota)) { -+ /* Pass the signal on to other waiters */ -+ up(&state->data_quota_event); -+ break; -+ } -+ } -+ -+ while ((service_quota->message_use_count == -+ service_quota->message_quota) || -+ ((tx_end_index != service_quota->previous_tx_index) && -+ (service_quota->slot_use_count == -+ service_quota->slot_quota))) { -+ spin_unlock("a_spinlock); -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: qm:%d %s,%x - quota stall " -+ "(msg %d, slot %d)", -+ state->id, service->localport, -+ msg_type_str(type), size, -+ service_quota->message_use_count, -+ service_quota->slot_use_count); -+ VCHIQ_SERVICE_STATS_INC(service, quota_stalls); -+ mutex_unlock(&state->slot_mutex); -+ if (down_interruptible(&service_quota->quota_event) -+ != 0) -+ return VCHIQ_RETRY; -+ if (service->closing) -+ return VCHIQ_ERROR; -+ if (mutex_lock_interruptible(&state->slot_mutex) != 0) -+ return VCHIQ_RETRY; -+ if (service->srvstate != VCHIQ_SRVSTATE_OPEN) { -+ /* The service has been closed */ -+ mutex_unlock(&state->slot_mutex); -+ return VCHIQ_ERROR; -+ } -+ spin_lock("a_spinlock); -+ tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( -+ state->local_tx_pos + stride - 1); -+ } -+ -+ spin_unlock("a_spinlock); -+ } -+ -+ header = reserve_space(state, stride, flags & QMFLAGS_IS_BLOCKING); -+ -+ if (!header) { -+ if (service) -+ VCHIQ_SERVICE_STATS_INC(service, slot_stalls); -+ /* In the event of a failure, return the mutex to the -+ state it was in */ -+ if (!(flags & QMFLAGS_NO_MUTEX_LOCK)) -+ mutex_unlock(&state->slot_mutex); -+ return VCHIQ_RETRY; -+ } -+ -+ if (type == VCHIQ_MSG_DATA) { -+ int i, pos; -+ int tx_end_index; -+ int slot_use_count; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: qm %s@%x,%x (%d->%d)", -+ state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ -+ BUG_ON(!service); -+ BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | -+ QMFLAGS_NO_MUTEX_UNLOCK)) != 0); -+ -+ for (i = 0, pos = 0; i < (unsigned int)count; -+ pos += elements[i++].size) -+ if (elements[i].size) { -+ if (vchiq_copy_from_user -+ (header->data + pos, elements[i].data, -+ (size_t) elements[i].size) != -+ VCHIQ_SUCCESS) { -+ mutex_unlock(&state->slot_mutex); -+ VCHIQ_SERVICE_STATS_INC(service, -+ error_count); -+ return VCHIQ_ERROR; -+ } -+ } -+ -+ if (SRVTRACE_ENABLED(service, -+ VCHIQ_LOG_INFO)) -+ vchiq_log_dump_mem("Sent", 0, -+ header->data, -+ min(16, pos)); -+ -+ spin_lock("a_spinlock); -+ service_quota->message_use_count++; -+ -+ tx_end_index = -+ SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos - 1); -+ -+ /* If this transmission can't fit in the last slot used by any -+ ** service, the data_use_count must be increased. */ -+ if (tx_end_index != state->previous_data_index) { -+ state->previous_data_index = tx_end_index; -+ state->data_use_count++; -+ } -+ -+ /* If this isn't the same slot last used by this service, -+ ** the service's slot_use_count must be increased. */ -+ if (tx_end_index != service_quota->previous_tx_index) { -+ service_quota->previous_tx_index = tx_end_index; -+ slot_use_count = ++service_quota->slot_use_count; -+ } else { -+ slot_use_count = 0; -+ } -+ -+ spin_unlock("a_spinlock); -+ -+ if (slot_use_count) -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: qm:%d %s,%x - slot_use->%d (hdr %p)", -+ state->id, service->localport, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), size, -+ slot_use_count, header); -+ -+ VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); -+ } else { -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: qm %s@%x,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ if (size != 0) { -+ WARN_ON(!((count == 1) && (size == elements[0].size))); -+ memcpy(header->data, elements[0].data, -+ elements[0].size); -+ } -+ VCHIQ_STATS_INC(state, ctrl_tx_count); -+ } -+ -+ header->msgid = msgid; -+ header->size = size; -+ -+ { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ VCHIQ_MSG_TYPE(msgid), -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid), -+ size); -+ } -+ -+ /* Make sure the new header is visible to the peer. */ -+ wmb(); -+ -+ /* Make the new tx_pos visible to the peer. */ -+ local->tx_pos = state->local_tx_pos; -+ wmb(); -+ -+ if (service && (type == VCHIQ_MSG_CLOSE)) -+ vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT); -+ -+ if (!(flags & QMFLAGS_NO_MUTEX_UNLOCK)) -+ mutex_unlock(&state->slot_mutex); -+ -+ remote_event_signal(&state->remote->trigger); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+/* Called by the slot handler and application threads */ -+static VCHIQ_STATUS_T -+queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -+ int msgid, const VCHIQ_ELEMENT_T *elements, -+ int count, int size, int is_blocking) -+{ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_HEADER_T *header; -+ -+ local = state->local; -+ -+ if ((VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME) && -+ (mutex_lock_interruptible(&state->sync_mutex) != 0)) -+ return VCHIQ_RETRY; -+ -+ remote_event_wait(&local->sync_release); -+ -+ rmb(); -+ -+ header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, -+ local->slot_sync); -+ -+ { -+ int oldmsgid = header->msgid; -+ if (oldmsgid != VCHIQ_MSGID_PADDING) -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: qms - msgid %x, not PADDING", -+ state->id, oldmsgid); -+ } -+ -+ if (service) { -+ int i, pos; -+ -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: qms %s@%x,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ -+ for (i = 0, pos = 0; i < (unsigned int)count; -+ pos += elements[i++].size) -+ if (elements[i].size) { -+ if (vchiq_copy_from_user -+ (header->data + pos, elements[i].data, -+ (size_t) elements[i].size) != -+ VCHIQ_SUCCESS) { -+ mutex_unlock(&state->sync_mutex); -+ VCHIQ_SERVICE_STATS_INC(service, -+ error_count); -+ return VCHIQ_ERROR; -+ } -+ } -+ -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) -+ vchiq_log_dump_mem("Sent Sync", -+ 0, header->data, -+ min(16, pos)); -+ -+ VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); -+ } else { -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: qms %s@%x,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ (unsigned int)header, size, -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ if (size != 0) { -+ WARN_ON(!((count == 1) && (size == elements[0].size))); -+ memcpy(header->data, elements[0].data, -+ elements[0].size); -+ } -+ VCHIQ_STATS_INC(state, ctrl_tx_count); -+ } -+ -+ header->size = size; -+ header->msgid = msgid; -+ -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ -+ vchiq_log_trace(vchiq_sync_log_level, -+ "Sent Sync Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ VCHIQ_MSG_TYPE(msgid), -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid), -+ size); -+ } -+ -+ /* Make sure the new header is visible to the peer. */ -+ wmb(); -+ -+ remote_event_signal(&state->remote->sync_trigger); -+ -+ if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE) -+ mutex_unlock(&state->sync_mutex); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+static inline void -+claim_slot(VCHIQ_SLOT_INFO_T *slot) -+{ -+ slot->use_count++; -+} -+ -+static void -+release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info, -+ VCHIQ_HEADER_T *header, VCHIQ_SERVICE_T *service) -+{ -+ int release_count; -+ -+ mutex_lock(&state->recycle_mutex); -+ -+ if (header) { -+ int msgid = header->msgid; -+ if (((msgid & VCHIQ_MSGID_CLAIMED) == 0) || -+ (service && service->closing)) { -+ mutex_unlock(&state->recycle_mutex); -+ return; -+ } -+ -+ /* Rewrite the message header to prevent a double -+ ** release */ -+ header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED; -+ } -+ -+ release_count = slot_info->release_count; -+ slot_info->release_count = ++release_count; -+ -+ if (release_count == slot_info->use_count) { -+ int slot_queue_recycle; -+ /* Add to the freed queue */ -+ -+ /* A read barrier is necessary here to prevent speculative -+ ** fetches of remote->slot_queue_recycle from overtaking the -+ ** mutex. */ -+ rmb(); -+ -+ slot_queue_recycle = state->remote->slot_queue_recycle; -+ state->remote->slot_queue[slot_queue_recycle & -+ VCHIQ_SLOT_QUEUE_MASK] = -+ SLOT_INDEX_FROM_INFO(state, slot_info); -+ state->remote->slot_queue_recycle = slot_queue_recycle + 1; -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: release_slot %d - recycle->%x", -+ state->id, SLOT_INDEX_FROM_INFO(state, slot_info), -+ state->remote->slot_queue_recycle); -+ -+ /* A write barrier is necessary, but remote_event_signal -+ ** contains one. */ -+ remote_event_signal(&state->remote->recycle); -+ } -+ -+ mutex_unlock(&state->recycle_mutex); -+} -+ -+/* Called by the slot handler - don't hold the bulk mutex */ -+static VCHIQ_STATUS_T -+notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, -+ int retry_poll) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: nb:%d %cx - p=%x rn=%x r=%x", -+ service->state->id, service->localport, -+ (queue == &service->bulk_tx) ? 't' : 'r', -+ queue->process, queue->remote_notify, queue->remove); -+ -+ if (service->state->is_master) { -+ while (queue->remote_notify != queue->process) { -+ VCHIQ_BULK_T *bulk = -+ &queue->bulks[BULK_INDEX(queue->remote_notify)]; -+ int msgtype = (bulk->dir == VCHIQ_BULK_TRANSMIT) ? -+ VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE; -+ int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport, -+ service->remoteport); -+ VCHIQ_ELEMENT_T element = { &bulk->actual, 4 }; -+ /* Only reply to non-dummy bulk requests */ -+ if (bulk->remote_data) { -+ status = queue_message(service->state, NULL, -+ msgid, &element, 1, 4, 0); -+ if (status != VCHIQ_SUCCESS) -+ break; -+ } -+ queue->remote_notify++; -+ } -+ } else { -+ queue->remote_notify = queue->process; -+ } -+ -+ if (status == VCHIQ_SUCCESS) { -+ while (queue->remove != queue->remote_notify) { -+ VCHIQ_BULK_T *bulk = -+ &queue->bulks[BULK_INDEX(queue->remove)]; -+ -+ /* Only generate callbacks for non-dummy bulk -+ ** requests, and non-terminated services */ -+ if (bulk->data && service->instance) { -+ if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { -+ if (bulk->dir == VCHIQ_BULK_TRANSMIT) { -+ VCHIQ_SERVICE_STATS_INC(service, -+ bulk_tx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, -+ bulk_tx_bytes, -+ bulk->actual); -+ } else { -+ VCHIQ_SERVICE_STATS_INC(service, -+ bulk_rx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, -+ bulk_rx_bytes, -+ bulk->actual); -+ } -+ } else { -+ VCHIQ_SERVICE_STATS_INC(service, -+ bulk_aborted_count); -+ } -+ if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { -+ struct bulk_waiter *waiter; -+ spin_lock(&bulk_waiter_spinlock); -+ waiter = bulk->userdata; -+ if (waiter) { -+ waiter->actual = bulk->actual; -+ up(&waiter->event); -+ } -+ spin_unlock(&bulk_waiter_spinlock); -+ } else if (bulk->mode == -+ VCHIQ_BULK_MODE_CALLBACK) { -+ VCHIQ_REASON_T reason = (bulk->dir == -+ VCHIQ_BULK_TRANSMIT) ? -+ ((bulk->actual == -+ VCHIQ_BULK_ACTUAL_ABORTED) ? -+ VCHIQ_BULK_TRANSMIT_ABORTED : -+ VCHIQ_BULK_TRANSMIT_DONE) : -+ ((bulk->actual == -+ VCHIQ_BULK_ACTUAL_ABORTED) ? -+ VCHIQ_BULK_RECEIVE_ABORTED : -+ VCHIQ_BULK_RECEIVE_DONE); -+ status = make_service_callback(service, -+ reason, NULL, bulk->userdata); -+ if (status == VCHIQ_RETRY) -+ break; -+ } -+ } -+ -+ queue->remove++; -+ up(&service->bulk_remove_event); -+ } -+ if (!retry_poll) -+ status = VCHIQ_SUCCESS; -+ } -+ -+ if (status == VCHIQ_RETRY) -+ request_poll(service->state, service, -+ (queue == &service->bulk_tx) ? -+ VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); -+ -+ return status; -+} -+ -+/* Called by the slot handler thread */ -+static void -+poll_services(VCHIQ_STATE_T *state) -+{ -+ int group, i; -+ -+ for (group = 0; group < BITSET_SIZE(state->unused_service); group++) { -+ uint32_t flags; -+ flags = atomic_xchg(&state->poll_services[group], 0); -+ for (i = 0; flags; i++) { -+ if (flags & (1 << i)) { -+ VCHIQ_SERVICE_T *service = -+ find_service_by_port(state, -+ (group<<5) + i); -+ uint32_t service_flags; -+ flags &= ~(1 << i); -+ if (!service) -+ continue; -+ service_flags = -+ atomic_xchg(&service->poll_flags, 0); -+ if (service_flags & -+ (1 << VCHIQ_POLL_REMOVE)) { -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: ps - remove %d<->%d", -+ state->id, service->localport, -+ service->remoteport); -+ -+ /* Make it look like a client, because -+ it must be removed and not left in -+ the LISTENING state. */ -+ service->public_fourcc = -+ VCHIQ_FOURCC_INVALID; -+ -+ if (vchiq_close_service_internal( -+ service, 0/*!close_recvd*/) != -+ VCHIQ_SUCCESS) -+ request_poll(state, service, -+ VCHIQ_POLL_REMOVE); -+ } else if (service_flags & -+ (1 << VCHIQ_POLL_TERMINATE)) { -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: ps - terminate %d<->%d", -+ state->id, service->localport, -+ service->remoteport); -+ if (vchiq_close_service_internal( -+ service, 0/*!close_recvd*/) != -+ VCHIQ_SUCCESS) -+ request_poll(state, service, -+ VCHIQ_POLL_TERMINATE); -+ } -+ if (service_flags & (1 << VCHIQ_POLL_TXNOTIFY)) -+ notify_bulks(service, -+ &service->bulk_tx, -+ 1/*retry_poll*/); -+ if (service_flags & (1 << VCHIQ_POLL_RXNOTIFY)) -+ notify_bulks(service, -+ &service->bulk_rx, -+ 1/*retry_poll*/); -+ unlock_service(service); -+ } -+ } -+ } -+} -+ -+/* Called by the slot handler or application threads, holding the bulk mutex. */ -+static int -+resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ int resolved = 0; -+ int rc; -+ -+ while ((queue->process != queue->local_insert) && -+ (queue->process != queue->remote_insert)) { -+ VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: rb:%d %cx - li=%x ri=%x p=%x", -+ state->id, service->localport, -+ (queue == &service->bulk_tx) ? 't' : 'r', -+ queue->local_insert, queue->remote_insert, -+ queue->process); -+ -+ WARN_ON(!((int)(queue->local_insert - queue->process) > 0)); -+ WARN_ON(!((int)(queue->remote_insert - queue->process) > 0)); -+ -+ rc = mutex_lock_interruptible(&state->bulk_transfer_mutex); -+ if (rc != 0) -+ break; -+ -+ vchiq_transfer_bulk(bulk); -+ mutex_unlock(&state->bulk_transfer_mutex); -+ -+ if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { -+ const char *header = (queue == &service->bulk_tx) ? -+ "Send Bulk to" : "Recv Bulk from"; -+ if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "%s %c%c%c%c d:%d len:%d %x<->%x", -+ header, -+ VCHIQ_FOURCC_AS_4CHARS( -+ service->base.fourcc), -+ service->remoteport, -+ bulk->size, -+ (unsigned int)bulk->data, -+ (unsigned int)bulk->remote_data); -+ else -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "%s %c%c%c%c d:%d ABORTED - tx len:%d," -+ " rx len:%d %x<->%x", -+ header, -+ VCHIQ_FOURCC_AS_4CHARS( -+ service->base.fourcc), -+ service->remoteport, -+ bulk->size, -+ bulk->remote_size, -+ (unsigned int)bulk->data, -+ (unsigned int)bulk->remote_data); -+ } -+ -+ vchiq_complete_bulk(bulk); -+ queue->process++; -+ resolved++; -+ } -+ return resolved; -+} -+ -+/* Called with the bulk_mutex held */ -+static void -+abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) -+{ -+ int is_tx = (queue == &service->bulk_tx); -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: aob:%d %cx - li=%x ri=%x p=%x", -+ service->state->id, service->localport, is_tx ? 't' : 'r', -+ queue->local_insert, queue->remote_insert, queue->process); -+ -+ WARN_ON(!((int)(queue->local_insert - queue->process) >= 0)); -+ WARN_ON(!((int)(queue->remote_insert - queue->process) >= 0)); -+ -+ while ((queue->process != queue->local_insert) || -+ (queue->process != queue->remote_insert)) { -+ VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; -+ -+ if (queue->process == queue->remote_insert) { -+ /* fabricate a matching dummy bulk */ -+ bulk->remote_data = NULL; -+ bulk->remote_size = 0; -+ queue->remote_insert++; -+ } -+ -+ if (queue->process != queue->local_insert) { -+ vchiq_complete_bulk(bulk); -+ -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "%s %c%c%c%c d:%d ABORTED - tx len:%d, " -+ "rx len:%d", -+ is_tx ? "Send Bulk to" : "Recv Bulk from", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->remoteport, -+ bulk->size, -+ bulk->remote_size); -+ } else { -+ /* fabricate a matching dummy bulk */ -+ bulk->data = NULL; -+ bulk->size = 0; -+ bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; -+ bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT : -+ VCHIQ_BULK_RECEIVE; -+ queue->local_insert++; -+ } -+ -+ queue->process++; -+ } -+} -+ -+/* Called from the slot handler thread */ -+static void -+pause_bulks(VCHIQ_STATE_T *state) -+{ -+ if (unlikely(atomic_inc_return(&pause_bulks_count) != 1)) { -+ WARN_ON_ONCE(1); -+ atomic_set(&pause_bulks_count, 1); -+ return; -+ } -+ -+ /* Block bulk transfers from all services */ -+ mutex_lock(&state->bulk_transfer_mutex); -+} -+ -+/* Called from the slot handler thread */ -+static void -+resume_bulks(VCHIQ_STATE_T *state) -+{ -+ int i; -+ if (unlikely(atomic_dec_return(&pause_bulks_count) != 0)) { -+ WARN_ON_ONCE(1); -+ atomic_set(&pause_bulks_count, 0); -+ return; -+ } -+ -+ /* Allow bulk transfers from all services */ -+ mutex_unlock(&state->bulk_transfer_mutex); -+ -+ if (state->deferred_bulks == 0) -+ return; -+ -+ /* Deal with any bulks which had to be deferred due to being in -+ * paused state. Don't try to match up to number of deferred bulks -+ * in case we've had something come and close the service in the -+ * interim - just process all bulk queues for all services */ -+ vchiq_log_info(vchiq_core_log_level, "%s: processing %d deferred bulks", -+ __func__, state->deferred_bulks); -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = state->services[i]; -+ int resolved_rx = 0; -+ int resolved_tx = 0; -+ if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN)) -+ continue; -+ -+ mutex_lock(&service->bulk_mutex); -+ resolved_rx = resolve_bulks(service, &service->bulk_rx); -+ resolved_tx = resolve_bulks(service, &service->bulk_tx); -+ mutex_unlock(&service->bulk_mutex); -+ if (resolved_rx) -+ notify_bulks(service, &service->bulk_rx, 1); -+ if (resolved_tx) -+ notify_bulks(service, &service->bulk_tx, 1); -+ } -+ state->deferred_bulks = 0; -+} -+ -+static int -+parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) -+{ -+ VCHIQ_SERVICE_T *service = NULL; -+ int msgid, size; -+ int type; -+ unsigned int localport, remoteport; -+ -+ msgid = header->msgid; -+ size = header->size; -+ type = VCHIQ_MSG_TYPE(msgid); -+ localport = VCHIQ_MSG_DSTPORT(msgid); -+ remoteport = VCHIQ_MSG_SRCPORT(msgid); -+ if (size >= sizeof(struct vchiq_open_payload)) { -+ const struct vchiq_open_payload *payload = -+ (struct vchiq_open_payload *)header->data; -+ unsigned int fourcc; -+ -+ fourcc = payload->fourcc; -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs OPEN@%x (%d->'%c%c%c%c')", -+ state->id, (unsigned int)header, -+ localport, -+ VCHIQ_FOURCC_AS_4CHARS(fourcc)); -+ -+ service = get_listening_service(state, fourcc); -+ -+ if (service) { -+ /* A matching service exists */ -+ short version = payload->version; -+ short version_min = payload->version_min; -+ if ((service->version < version_min) || -+ (version < service->version_min)) { -+ /* Version mismatch */ -+ vchiq_loud_error_header(); -+ vchiq_loud_error("%d: service %d (%c%c%c%c) " -+ "version mismatch - local (%d, min %d)" -+ " vs. remote (%d, min %d)", -+ state->id, service->localport, -+ VCHIQ_FOURCC_AS_4CHARS(fourcc), -+ service->version, service->version_min, -+ version, version_min); -+ vchiq_loud_error_footer(); -+ unlock_service(service); -+ service = NULL; -+ goto fail_open; -+ } -+ service->peer_version = version; -+ -+ if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { -+ struct vchiq_openack_payload ack_payload = { -+ service->version -+ }; -+ VCHIQ_ELEMENT_T body = { -+ &ack_payload, -+ sizeof(ack_payload) -+ }; -+ -+ if (state->version_common < -+ VCHIQ_VERSION_SYNCHRONOUS_MODE) -+ service->sync = 0; -+ -+ /* Acknowledge the OPEN */ -+ if (service->sync && -+ (state->version_common >= -+ VCHIQ_VERSION_SYNCHRONOUS_MODE)) { -+ if (queue_message_sync(state, NULL, -+ VCHIQ_MAKE_MSG( -+ VCHIQ_MSG_OPENACK, -+ service->localport, -+ remoteport), -+ &body, 1, sizeof(ack_payload), -+ 0) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ } else { -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG( -+ VCHIQ_MSG_OPENACK, -+ service->localport, -+ remoteport), -+ &body, 1, sizeof(ack_payload), -+ 0) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ } -+ -+ /* The service is now open */ -+ vchiq_set_service_state(service, -+ service->sync ? VCHIQ_SRVSTATE_OPENSYNC -+ : VCHIQ_SRVSTATE_OPEN); -+ } -+ -+ service->remoteport = remoteport; -+ service->client_id = ((int *)header->data)[1]; -+ if (make_service_callback(service, VCHIQ_SERVICE_OPENED, -+ NULL, NULL) == VCHIQ_RETRY) { -+ /* Bail out if not ready */ -+ service->remoteport = VCHIQ_PORT_FREE; -+ goto bail_not_ready; -+ } -+ -+ /* Success - the message has been dealt with */ -+ unlock_service(service); -+ return 1; -+ } -+ } -+ -+fail_open: -+ /* No available service, or an invalid request - send a CLOSE */ -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, VCHIQ_MSG_SRCPORT(msgid)), -+ NULL, 0, 0, 0) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ -+ return 1; -+ -+bail_not_ready: -+ if (service) -+ unlock_service(service); -+ -+ return 0; -+} -+ -+/* Called by the slot handler thread */ -+static void -+parse_rx_slots(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_SHARED_STATE_T *remote = state->remote; -+ VCHIQ_SERVICE_T *service = NULL; -+ int tx_pos; -+ DEBUG_INITIALISE(state->local) -+ -+ tx_pos = remote->tx_pos; -+ -+ while (state->rx_pos != tx_pos) { -+ VCHIQ_HEADER_T *header; -+ int msgid, size; -+ int type; -+ unsigned int localport, remoteport; -+ -+ DEBUG_TRACE(PARSE_LINE); -+ if (!state->rx_data) { -+ int rx_index; -+ WARN_ON(!((state->rx_pos & VCHIQ_SLOT_MASK) == 0)); -+ rx_index = remote->slot_queue[ -+ SLOT_QUEUE_INDEX_FROM_POS(state->rx_pos) & -+ VCHIQ_SLOT_QUEUE_MASK]; -+ state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state, -+ rx_index); -+ state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index); -+ -+ /* Initialise use_count to one, and increment -+ ** release_count at the end of the slot to avoid -+ ** releasing the slot prematurely. */ -+ state->rx_info->use_count = 1; -+ state->rx_info->release_count = 0; -+ } -+ -+ header = (VCHIQ_HEADER_T *)(state->rx_data + -+ (state->rx_pos & VCHIQ_SLOT_MASK)); -+ DEBUG_VALUE(PARSE_HEADER, (int)header); -+ msgid = header->msgid; -+ DEBUG_VALUE(PARSE_MSGID, msgid); -+ size = header->size; -+ type = VCHIQ_MSG_TYPE(msgid); -+ localport = VCHIQ_MSG_DSTPORT(msgid); -+ remoteport = VCHIQ_MSG_SRCPORT(msgid); -+ -+ if (type != VCHIQ_MSG_DATA) -+ VCHIQ_STATS_INC(state, ctrl_rx_count); -+ -+ switch (type) { -+ case VCHIQ_MSG_OPENACK: -+ case VCHIQ_MSG_CLOSE: -+ case VCHIQ_MSG_DATA: -+ case VCHIQ_MSG_BULK_RX: -+ case VCHIQ_MSG_BULK_TX: -+ case VCHIQ_MSG_BULK_RX_DONE: -+ case VCHIQ_MSG_BULK_TX_DONE: -+ service = find_service_by_port(state, localport); -+ if ((!service || -+ ((service->remoteport != remoteport) && -+ (service->remoteport != VCHIQ_PORT_FREE))) && -+ (localport == 0) && -+ (type == VCHIQ_MSG_CLOSE)) { -+ /* This could be a CLOSE from a client which -+ hadn't yet received the OPENACK - look for -+ the connected service */ -+ if (service) -+ unlock_service(service); -+ service = get_connected_service(state, -+ remoteport); -+ if (service) -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) - " -+ "found connected service %d", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ service->localport); -+ } -+ -+ if (!service) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) - " -+ "invalid/closed service %d", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, localport); -+ goto skip_message; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ vchiq_log_info(SRVTRACE_LEVEL(service), -+ "Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d " -+ "len:%d", -+ msg_type_str(type), type, -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ remoteport, localport, size); -+ if (size > 0) -+ vchiq_log_dump_mem("Rcvd", 0, header->data, -+ min(16, size)); -+ } -+ -+ if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) -+ > VCHIQ_SLOT_SIZE) { -+ vchiq_log_error(vchiq_core_log_level, -+ "header %x (msgid %x) - size %x too big for " -+ "slot", -+ (unsigned int)header, (unsigned int)msgid, -+ (unsigned int)size); -+ WARN(1, "oversized for slot\n"); -+ } -+ -+ switch (type) { -+ case VCHIQ_MSG_OPEN: -+ WARN_ON(!(VCHIQ_MSG_DSTPORT(msgid) == 0)); -+ if (!parse_open(state, header)) -+ goto bail_not_ready; -+ break; -+ case VCHIQ_MSG_OPENACK: -+ if (size >= sizeof(struct vchiq_openack_payload)) { -+ const struct vchiq_openack_payload *payload = -+ (struct vchiq_openack_payload *) -+ header->data; -+ service->peer_version = payload->version; -+ } -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs OPENACK@%x,%x (%d->%d) v:%d", -+ state->id, (unsigned int)header, size, -+ remoteport, localport, service->peer_version); -+ if (service->srvstate == -+ VCHIQ_SRVSTATE_OPENING) { -+ service->remoteport = remoteport; -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_OPEN); -+ up(&service->remove_event); -+ } else -+ vchiq_log_error(vchiq_core_log_level, -+ "OPENACK received in state %s", -+ srvstate_names[service->srvstate]); -+ break; -+ case VCHIQ_MSG_CLOSE: -+ WARN_ON(size != 0); /* There should be no data */ -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs CLOSE@%x (%d->%d)", -+ state->id, (unsigned int)header, -+ remoteport, localport); -+ -+ mark_service_closing_internal(service, 1); -+ -+ if (vchiq_close_service_internal(service, -+ 1/*close_recvd*/) == VCHIQ_RETRY) -+ goto bail_not_ready; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "Close Service %c%c%c%c s:%u d:%d", -+ VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), -+ service->localport, -+ service->remoteport); -+ break; -+ case VCHIQ_MSG_DATA: -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs DATA@%x,%x (%d->%d)", -+ state->id, (unsigned int)header, size, -+ remoteport, localport); -+ -+ if ((service->remoteport == remoteport) -+ && (service->srvstate == -+ VCHIQ_SRVSTATE_OPEN)) { -+ header->msgid = msgid | VCHIQ_MSGID_CLAIMED; -+ claim_slot(state->rx_info); -+ DEBUG_TRACE(PARSE_LINE); -+ if (make_service_callback(service, -+ VCHIQ_MESSAGE_AVAILABLE, header, -+ NULL) == VCHIQ_RETRY) { -+ DEBUG_TRACE(PARSE_LINE); -+ goto bail_not_ready; -+ } -+ VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count); -+ VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes, -+ size); -+ } else { -+ VCHIQ_STATS_INC(state, error_count); -+ } -+ break; -+ case VCHIQ_MSG_CONNECT: -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs CONNECT@%x", -+ state->id, (unsigned int)header); -+ state->version_common = ((VCHIQ_SLOT_ZERO_T *) -+ state->slot_data)->version; -+ up(&state->connect); -+ break; -+ case VCHIQ_MSG_BULK_RX: -+ case VCHIQ_MSG_BULK_TX: { -+ VCHIQ_BULK_QUEUE_T *queue; -+ WARN_ON(!state->is_master); -+ queue = (type == VCHIQ_MSG_BULK_RX) ? -+ &service->bulk_tx : &service->bulk_rx; -+ if ((service->remoteport == remoteport) -+ && (service->srvstate == -+ VCHIQ_SRVSTATE_OPEN)) { -+ VCHIQ_BULK_T *bulk; -+ int resolved = 0; -+ -+ DEBUG_TRACE(PARSE_LINE); -+ if (mutex_lock_interruptible( -+ &service->bulk_mutex) != 0) { -+ DEBUG_TRACE(PARSE_LINE); -+ goto bail_not_ready; -+ } -+ -+ WARN_ON(!(queue->remote_insert < queue->remove + -+ VCHIQ_NUM_SERVICE_BULKS)); -+ bulk = &queue->bulks[ -+ BULK_INDEX(queue->remote_insert)]; -+ bulk->remote_data = -+ (void *)((int *)header->data)[0]; -+ bulk->remote_size = ((int *)header->data)[1]; -+ wmb(); -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) %x@%x", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ bulk->remote_size, -+ (unsigned int)bulk->remote_data); -+ -+ queue->remote_insert++; -+ -+ if (atomic_read(&pause_bulks_count)) { -+ state->deferred_bulks++; -+ vchiq_log_info(vchiq_core_log_level, -+ "%s: deferring bulk (%d)", -+ __func__, -+ state->deferred_bulks); -+ if (state->conn_state != -+ VCHIQ_CONNSTATE_PAUSE_SENT) -+ vchiq_log_error( -+ vchiq_core_log_level, -+ "%s: bulks paused in " -+ "unexpected state %s", -+ __func__, -+ conn_state_names[ -+ state->conn_state]); -+ } else if (state->conn_state == -+ VCHIQ_CONNSTATE_CONNECTED) { -+ DEBUG_TRACE(PARSE_LINE); -+ resolved = resolve_bulks(service, -+ queue); -+ } -+ -+ mutex_unlock(&service->bulk_mutex); -+ if (resolved) -+ notify_bulks(service, queue, -+ 1/*retry_poll*/); -+ } -+ } break; -+ case VCHIQ_MSG_BULK_RX_DONE: -+ case VCHIQ_MSG_BULK_TX_DONE: -+ WARN_ON(state->is_master); -+ if ((service->remoteport == remoteport) -+ && (service->srvstate != -+ VCHIQ_SRVSTATE_FREE)) { -+ VCHIQ_BULK_QUEUE_T *queue; -+ VCHIQ_BULK_T *bulk; -+ -+ queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? -+ &service->bulk_rx : &service->bulk_tx; -+ -+ DEBUG_TRACE(PARSE_LINE); -+ if (mutex_lock_interruptible( -+ &service->bulk_mutex) != 0) { -+ DEBUG_TRACE(PARSE_LINE); -+ goto bail_not_ready; -+ } -+ if ((int)(queue->remote_insert - -+ queue->local_insert) >= 0) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) " -+ "unexpected (ri=%d,li=%d)", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ queue->remote_insert, -+ queue->local_insert); -+ mutex_unlock(&service->bulk_mutex); -+ break; -+ } -+ -+ BUG_ON(queue->process == queue->local_insert); -+ BUG_ON(queue->process != queue->remote_insert); -+ -+ bulk = &queue->bulks[ -+ BULK_INDEX(queue->remote_insert)]; -+ bulk->actual = *(int *)header->data; -+ queue->remote_insert++; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: prs %s@%x (%d->%d) %x@%x", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, -+ bulk->actual, (unsigned int)bulk->data); -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs:%d %cx li=%x ri=%x p=%x", -+ state->id, localport, -+ (type == VCHIQ_MSG_BULK_RX_DONE) ? -+ 'r' : 't', -+ queue->local_insert, -+ queue->remote_insert, queue->process); -+ -+ DEBUG_TRACE(PARSE_LINE); -+ WARN_ON(queue->process == queue->local_insert); -+ vchiq_complete_bulk(bulk); -+ queue->process++; -+ mutex_unlock(&service->bulk_mutex); -+ DEBUG_TRACE(PARSE_LINE); -+ notify_bulks(service, queue, 1/*retry_poll*/); -+ DEBUG_TRACE(PARSE_LINE); -+ } -+ break; -+ case VCHIQ_MSG_PADDING: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs PADDING@%x,%x", -+ state->id, (unsigned int)header, size); -+ break; -+ case VCHIQ_MSG_PAUSE: -+ /* If initiated, signal the application thread */ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs PAUSE@%x,%x", -+ state->id, (unsigned int)header, size); -+ if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: PAUSE received in state PAUSED", -+ state->id); -+ break; -+ } -+ if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) { -+ /* Send a PAUSE in response */ -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), -+ NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK) -+ == VCHIQ_RETRY) -+ goto bail_not_ready; -+ if (state->is_master) -+ pause_bulks(state); -+ } -+ /* At this point slot_mutex is held */ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); -+ vchiq_platform_paused(state); -+ break; -+ case VCHIQ_MSG_RESUME: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: prs RESUME@%x,%x", -+ state->id, (unsigned int)header, size); -+ /* Release the slot mutex */ -+ mutex_unlock(&state->slot_mutex); -+ if (state->is_master) -+ resume_bulks(state); -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); -+ vchiq_platform_resumed(state); -+ break; -+ -+ case VCHIQ_MSG_REMOTE_USE: -+ vchiq_on_remote_use(state); -+ break; -+ case VCHIQ_MSG_REMOTE_RELEASE: -+ vchiq_on_remote_release(state); -+ break; -+ case VCHIQ_MSG_REMOTE_USE_ACTIVE: -+ vchiq_on_remote_use_active(state); -+ break; -+ -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: prs invalid msgid %x@%x,%x", -+ state->id, msgid, (unsigned int)header, size); -+ WARN(1, "invalid message\n"); -+ break; -+ } -+ -+skip_message: -+ if (service) { -+ unlock_service(service); -+ service = NULL; -+ } -+ -+ state->rx_pos += calc_stride(size); -+ -+ DEBUG_TRACE(PARSE_LINE); -+ /* Perform some housekeeping when the end of the slot is -+ ** reached. */ -+ if ((state->rx_pos & VCHIQ_SLOT_MASK) == 0) { -+ /* Remove the extra reference count. */ -+ release_slot(state, state->rx_info, NULL, NULL); -+ state->rx_data = NULL; -+ } -+ } -+ -+bail_not_ready: -+ if (service) -+ unlock_service(service); -+} -+ -+/* Called by the slot handler thread */ -+static int -+slot_handler_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ DEBUG_INITIALISE(local) -+ -+ while (1) { -+ DEBUG_COUNT(SLOT_HANDLER_COUNT); -+ DEBUG_TRACE(SLOT_HANDLER_LINE); -+ remote_event_wait(&local->trigger); -+ -+ rmb(); -+ -+ DEBUG_TRACE(SLOT_HANDLER_LINE); -+ if (state->poll_needed) { -+ /* Check if we need to suspend - may change our -+ * conn_state */ -+ vchiq_platform_check_suspend(state); -+ -+ state->poll_needed = 0; -+ -+ /* Handle service polling and other rare conditions here -+ ** out of the mainline code */ -+ switch (state->conn_state) { -+ case VCHIQ_CONNSTATE_CONNECTED: -+ /* Poll the services as requested */ -+ poll_services(state); -+ break; -+ -+ case VCHIQ_CONNSTATE_PAUSING: -+ if (state->is_master) -+ pause_bulks(state); -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), -+ NULL, 0, 0, -+ QMFLAGS_NO_MUTEX_UNLOCK) -+ != VCHIQ_RETRY) { -+ vchiq_set_conn_state(state, -+ VCHIQ_CONNSTATE_PAUSE_SENT); -+ } else { -+ if (state->is_master) -+ resume_bulks(state); -+ /* Retry later */ -+ state->poll_needed = 1; -+ } -+ break; -+ -+ case VCHIQ_CONNSTATE_PAUSED: -+ vchiq_platform_resume(state); -+ break; -+ -+ case VCHIQ_CONNSTATE_RESUMING: -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), -+ NULL, 0, 0, QMFLAGS_NO_MUTEX_LOCK) -+ != VCHIQ_RETRY) { -+ if (state->is_master) -+ resume_bulks(state); -+ vchiq_set_conn_state(state, -+ VCHIQ_CONNSTATE_CONNECTED); -+ vchiq_platform_resumed(state); -+ } else { -+ /* This should really be impossible, -+ ** since the PAUSE should have flushed -+ ** through outstanding messages. */ -+ vchiq_log_error(vchiq_core_log_level, -+ "Failed to send RESUME " -+ "message"); -+ BUG(); -+ } -+ break; -+ -+ case VCHIQ_CONNSTATE_PAUSE_TIMEOUT: -+ case VCHIQ_CONNSTATE_RESUME_TIMEOUT: -+ vchiq_platform_handle_timeout(state); -+ break; -+ default: -+ break; -+ } -+ -+ -+ } -+ -+ DEBUG_TRACE(SLOT_HANDLER_LINE); -+ parse_rx_slots(state); -+ } -+ return 0; -+} -+ -+ -+/* Called by the recycle thread */ -+static int -+recycle_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ -+ while (1) { -+ remote_event_wait(&local->recycle); -+ -+ process_free_queue(state); -+ } -+ return 0; -+} -+ -+ -+/* Called by the sync thread */ -+static int -+sync_func(void *v) -+{ -+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; -+ VCHIQ_SHARED_STATE_T *local = state->local; -+ VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, -+ state->remote->slot_sync); -+ -+ while (1) { -+ VCHIQ_SERVICE_T *service; -+ int msgid, size; -+ int type; -+ unsigned int localport, remoteport; -+ -+ remote_event_wait(&local->sync_trigger); -+ -+ rmb(); -+ -+ msgid = header->msgid; -+ size = header->size; -+ type = VCHIQ_MSG_TYPE(msgid); -+ localport = VCHIQ_MSG_DSTPORT(msgid); -+ remoteport = VCHIQ_MSG_SRCPORT(msgid); -+ -+ service = find_service_by_port(state, localport); -+ -+ if (!service) { -+ vchiq_log_error(vchiq_sync_log_level, -+ "%d: sf %s@%x (%d->%d) - " -+ "invalid/closed service %d", -+ state->id, msg_type_str(type), -+ (unsigned int)header, -+ remoteport, localport, localport); -+ release_message_sync(state, header); -+ continue; -+ } -+ -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { -+ int svc_fourcc; -+ -+ svc_fourcc = service -+ ? service->base.fourcc -+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); -+ vchiq_log_trace(vchiq_sync_log_level, -+ "Rcvd Msg %s from %c%c%c%c s:%d d:%d len:%d", -+ msg_type_str(type), -+ VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), -+ remoteport, localport, size); -+ if (size > 0) -+ vchiq_log_dump_mem("Rcvd", 0, header->data, -+ min(16, size)); -+ } -+ -+ switch (type) { -+ case VCHIQ_MSG_OPENACK: -+ if (size >= sizeof(struct vchiq_openack_payload)) { -+ const struct vchiq_openack_payload *payload = -+ (struct vchiq_openack_payload *) -+ header->data; -+ service->peer_version = payload->version; -+ } -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: sf OPENACK@%x,%x (%d->%d) v:%d", -+ state->id, (unsigned int)header, size, -+ remoteport, localport, service->peer_version); -+ if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { -+ service->remoteport = remoteport; -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_OPENSYNC); -+ service->sync = 1; -+ up(&service->remove_event); -+ } -+ release_message_sync(state, header); -+ break; -+ -+ case VCHIQ_MSG_DATA: -+ vchiq_log_trace(vchiq_sync_log_level, -+ "%d: sf DATA@%x,%x (%d->%d)", -+ state->id, (unsigned int)header, size, -+ remoteport, localport); -+ -+ if ((service->remoteport == remoteport) && -+ (service->srvstate == -+ VCHIQ_SRVSTATE_OPENSYNC)) { -+ if (make_service_callback(service, -+ VCHIQ_MESSAGE_AVAILABLE, header, -+ NULL) == VCHIQ_RETRY) -+ vchiq_log_error(vchiq_sync_log_level, -+ "synchronous callback to " -+ "service %d returns " -+ "VCHIQ_RETRY", -+ localport); -+ } -+ break; -+ -+ default: -+ vchiq_log_error(vchiq_sync_log_level, -+ "%d: sf unexpected msgid %x@%x,%x", -+ state->id, msgid, (unsigned int)header, size); -+ release_message_sync(state, header); -+ break; -+ } -+ -+ unlock_service(service); -+ } -+ -+ return 0; -+} -+ -+ -+static void -+init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue) -+{ -+ queue->local_insert = 0; -+ queue->remote_insert = 0; -+ queue->process = 0; -+ queue->remote_notify = 0; -+ queue->remove = 0; -+} -+ -+ -+inline const char * -+get_conn_state_name(VCHIQ_CONNSTATE_T conn_state) -+{ -+ return conn_state_names[conn_state]; -+} -+ -+ -+VCHIQ_SLOT_ZERO_T * -+vchiq_init_slots(void *mem_base, int mem_size) -+{ -+ int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK; -+ VCHIQ_SLOT_ZERO_T *slot_zero = -+ (VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align); -+ int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE; -+ int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS; -+ -+ /* Ensure there is enough memory to run an absolutely minimum system */ -+ num_slots -= first_data_slot; -+ -+ if (num_slots < 4) { -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_init_slots - insufficient memory %x bytes", -+ mem_size); -+ return NULL; -+ } -+ -+ memset(slot_zero, 0, sizeof(VCHIQ_SLOT_ZERO_T)); -+ -+ slot_zero->magic = VCHIQ_MAGIC; -+ slot_zero->version = VCHIQ_VERSION; -+ slot_zero->version_min = VCHIQ_VERSION_MIN; -+ slot_zero->slot_zero_size = sizeof(VCHIQ_SLOT_ZERO_T); -+ slot_zero->slot_size = VCHIQ_SLOT_SIZE; -+ slot_zero->max_slots = VCHIQ_MAX_SLOTS; -+ slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE; -+ -+ slot_zero->master.slot_sync = first_data_slot; -+ slot_zero->master.slot_first = first_data_slot + 1; -+ slot_zero->master.slot_last = first_data_slot + (num_slots/2) - 1; -+ slot_zero->slave.slot_sync = first_data_slot + (num_slots/2); -+ slot_zero->slave.slot_first = first_data_slot + (num_slots/2) + 1; -+ slot_zero->slave.slot_last = first_data_slot + num_slots - 1; -+ -+ return slot_zero; -+} -+ -+VCHIQ_STATUS_T -+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, -+ int is_master) -+{ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_SHARED_STATE_T *remote; -+ VCHIQ_STATUS_T status; -+ char threadname[10]; -+ static int id; -+ int i; -+ -+ vchiq_log_warning(vchiq_core_log_level, -+ "%s: slot_zero = 0x%08lx, is_master = %d", -+ __func__, (unsigned long)slot_zero, is_master); -+ -+ /* Check the input configuration */ -+ -+ if (slot_zero->magic != VCHIQ_MAGIC) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("Invalid VCHIQ magic value found."); -+ vchiq_loud_error("slot_zero=%x: magic=%x (expected %x)", -+ (unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if (slot_zero->version < VCHIQ_VERSION_MIN) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("Incompatible VCHIQ versions found."); -+ vchiq_loud_error("slot_zero=%x: VideoCore version=%d " -+ "(minimum %d)", -+ (unsigned int)slot_zero, slot_zero->version, -+ VCHIQ_VERSION_MIN); -+ vchiq_loud_error("Restart with a newer VideoCore image."); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if (VCHIQ_VERSION < slot_zero->version_min) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("Incompatible VCHIQ versions found."); -+ vchiq_loud_error("slot_zero=%x: version=%d (VideoCore " -+ "minimum %d)", -+ (unsigned int)slot_zero, VCHIQ_VERSION, -+ slot_zero->version_min); -+ vchiq_loud_error("Restart with a newer kernel."); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if ((slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) || -+ (slot_zero->slot_size != VCHIQ_SLOT_SIZE) || -+ (slot_zero->max_slots != VCHIQ_MAX_SLOTS) || -+ (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) { -+ vchiq_loud_error_header(); -+ if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) -+ vchiq_loud_error("slot_zero=%x: slot_zero_size=%x " -+ "(expected %x)", -+ (unsigned int)slot_zero, -+ slot_zero->slot_zero_size, -+ sizeof(VCHIQ_SLOT_ZERO_T)); -+ if (slot_zero->slot_size != VCHIQ_SLOT_SIZE) -+ vchiq_loud_error("slot_zero=%x: slot_size=%d " -+ "(expected %d", -+ (unsigned int)slot_zero, slot_zero->slot_size, -+ VCHIQ_SLOT_SIZE); -+ if (slot_zero->max_slots != VCHIQ_MAX_SLOTS) -+ vchiq_loud_error("slot_zero=%x: max_slots=%d " -+ "(expected %d)", -+ (unsigned int)slot_zero, slot_zero->max_slots, -+ VCHIQ_MAX_SLOTS); -+ if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE) -+ vchiq_loud_error("slot_zero=%x: max_slots_per_side=%d " -+ "(expected %d)", -+ (unsigned int)slot_zero, -+ slot_zero->max_slots_per_side, -+ VCHIQ_MAX_SLOTS_PER_SIDE); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ if (VCHIQ_VERSION < slot_zero->version) -+ slot_zero->version = VCHIQ_VERSION; -+ -+ if (is_master) { -+ local = &slot_zero->master; -+ remote = &slot_zero->slave; -+ } else { -+ local = &slot_zero->slave; -+ remote = &slot_zero->master; -+ } -+ -+ if (local->initialised) { -+ vchiq_loud_error_header(); -+ if (remote->initialised) -+ vchiq_loud_error("local state has already been " -+ "initialised"); -+ else -+ vchiq_loud_error("master/slave mismatch - two %ss", -+ is_master ? "master" : "slave"); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ -+ memset(state, 0, sizeof(VCHIQ_STATE_T)); -+ -+ state->id = id++; -+ state->is_master = is_master; -+ -+ /* -+ initialize shared state pointers -+ */ -+ -+ state->local = local; -+ state->remote = remote; -+ state->slot_data = (VCHIQ_SLOT_T *)slot_zero; -+ -+ /* -+ initialize events and mutexes -+ */ -+ -+ sema_init(&state->connect, 0); -+ mutex_init(&state->mutex); -+ sema_init(&state->trigger_event, 0); -+ sema_init(&state->recycle_event, 0); -+ sema_init(&state->sync_trigger_event, 0); -+ sema_init(&state->sync_release_event, 0); -+ -+ mutex_init(&state->slot_mutex); -+ mutex_init(&state->recycle_mutex); -+ mutex_init(&state->sync_mutex); -+ mutex_init(&state->bulk_transfer_mutex); -+ -+ sema_init(&state->slot_available_event, 0); -+ sema_init(&state->slot_remove_event, 0); -+ sema_init(&state->data_quota_event, 0); -+ -+ state->slot_queue_available = 0; -+ -+ for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &state->service_quotas[i]; -+ sema_init(&service_quota->quota_event, 0); -+ } -+ -+ for (i = local->slot_first; i <= local->slot_last; i++) { -+ local->slot_queue[state->slot_queue_available++] = i; -+ up(&state->slot_available_event); -+ } -+ -+ state->default_slot_quota = state->slot_queue_available/2; -+ state->default_message_quota = -+ min((unsigned short)(state->default_slot_quota * 256), -+ (unsigned short)~0); -+ -+ state->previous_data_index = -1; -+ state->data_use_count = 0; -+ state->data_quota = state->slot_queue_available - 1; -+ -+ local->trigger.event = &state->trigger_event; -+ remote_event_create(&local->trigger); -+ local->tx_pos = 0; -+ -+ local->recycle.event = &state->recycle_event; -+ remote_event_create(&local->recycle); -+ local->slot_queue_recycle = state->slot_queue_available; -+ -+ local->sync_trigger.event = &state->sync_trigger_event; -+ remote_event_create(&local->sync_trigger); -+ -+ local->sync_release.event = &state->sync_release_event; -+ remote_event_create(&local->sync_release); -+ -+ /* At start-of-day, the slot is empty and available */ -+ ((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid -+ = VCHIQ_MSGID_PADDING; -+ remote_event_signal_local(&local->sync_release); -+ -+ local->debug[DEBUG_ENTRIES] = DEBUG_MAX; -+ -+ status = vchiq_platform_init_state(state); -+ -+ /* -+ bring up slot handler thread -+ */ -+ snprintf(threadname, sizeof(threadname), "VCHIQ-%d", state->id); -+ state->slot_handler_thread = kthread_create(&slot_handler_func, -+ (void *)state, -+ threadname); -+ -+ if (state->slot_handler_thread == NULL) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("couldn't create thread %s", threadname); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ set_user_nice(state->slot_handler_thread, -19); -+ wake_up_process(state->slot_handler_thread); -+ -+ snprintf(threadname, sizeof(threadname), "VCHIQr-%d", state->id); -+ state->recycle_thread = kthread_create(&recycle_func, -+ (void *)state, -+ threadname); -+ if (state->recycle_thread == NULL) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("couldn't create thread %s", threadname); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ set_user_nice(state->recycle_thread, -19); -+ wake_up_process(state->recycle_thread); -+ -+ snprintf(threadname, sizeof(threadname), "VCHIQs-%d", state->id); -+ state->sync_thread = kthread_create(&sync_func, -+ (void *)state, -+ threadname); -+ if (state->sync_thread == NULL) { -+ vchiq_loud_error_header(); -+ vchiq_loud_error("couldn't create thread %s", threadname); -+ vchiq_loud_error_footer(); -+ return VCHIQ_ERROR; -+ } -+ set_user_nice(state->sync_thread, -20); -+ wake_up_process(state->sync_thread); -+ -+ BUG_ON(state->id >= VCHIQ_MAX_STATES); -+ vchiq_states[state->id] = state; -+ -+ /* Indicate readiness to the other side */ -+ local->initialised = 1; -+ -+ return status; -+} -+ -+/* Called from application thread when a client or server service is created. */ -+VCHIQ_SERVICE_T * -+vchiq_add_service_internal(VCHIQ_STATE_T *state, -+ const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, -+ VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term) -+{ -+ VCHIQ_SERVICE_T *service; -+ -+ service = kmalloc(sizeof(VCHIQ_SERVICE_T), GFP_KERNEL); -+ if (service) { -+ service->base.fourcc = params->fourcc; -+ service->base.callback = params->callback; -+ service->base.userdata = params->userdata; -+ service->handle = VCHIQ_SERVICE_HANDLE_INVALID; -+ service->ref_count = 1; -+ service->srvstate = VCHIQ_SRVSTATE_FREE; -+ service->userdata_term = userdata_term; -+ service->localport = VCHIQ_PORT_FREE; -+ service->remoteport = VCHIQ_PORT_FREE; -+ -+ service->public_fourcc = (srvstate == VCHIQ_SRVSTATE_OPENING) ? -+ VCHIQ_FOURCC_INVALID : params->fourcc; -+ service->client_id = 0; -+ service->auto_close = 1; -+ service->sync = 0; -+ service->closing = 0; -+ service->trace = 0; -+ atomic_set(&service->poll_flags, 0); -+ service->version = params->version; -+ service->version_min = params->version_min; -+ service->state = state; -+ service->instance = instance; -+ service->service_use_count = 0; -+ init_bulk_queue(&service->bulk_tx); -+ init_bulk_queue(&service->bulk_rx); -+ sema_init(&service->remove_event, 0); -+ sema_init(&service->bulk_remove_event, 0); -+ mutex_init(&service->bulk_mutex); -+ memset(&service->stats, 0, sizeof(service->stats)); -+ } else { -+ vchiq_log_error(vchiq_core_log_level, -+ "Out of memory"); -+ } -+ -+ if (service) { -+ VCHIQ_SERVICE_T **pservice = NULL; -+ int i; -+ -+ /* Although it is perfectly possible to use service_spinlock -+ ** to protect the creation of services, it is overkill as it -+ ** disables interrupts while the array is searched. -+ ** The only danger is of another thread trying to create a -+ ** service - service deletion is safe. -+ ** Therefore it is preferable to use state->mutex which, -+ ** although slower to claim, doesn't block interrupts while -+ ** it is held. -+ */ -+ -+ mutex_lock(&state->mutex); -+ -+ /* Prepare to use a previously unused service */ -+ if (state->unused_service < VCHIQ_MAX_SERVICES) -+ pservice = &state->services[state->unused_service]; -+ -+ if (srvstate == VCHIQ_SRVSTATE_OPENING) { -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *srv = state->services[i]; -+ if (!srv) { -+ pservice = &state->services[i]; -+ break; -+ } -+ } -+ } else { -+ for (i = (state->unused_service - 1); i >= 0; i--) { -+ VCHIQ_SERVICE_T *srv = state->services[i]; -+ if (!srv) -+ pservice = &state->services[i]; -+ else if ((srv->public_fourcc == params->fourcc) -+ && ((srv->instance != instance) || -+ (srv->base.callback != -+ params->callback))) { -+ /* There is another server using this -+ ** fourcc which doesn't match. */ -+ pservice = NULL; -+ break; -+ } -+ } -+ } -+ -+ if (pservice) { -+ service->localport = (pservice - state->services); -+ if (!handle_seq) -+ handle_seq = VCHIQ_MAX_STATES * -+ VCHIQ_MAX_SERVICES; -+ service->handle = handle_seq | -+ (state->id * VCHIQ_MAX_SERVICES) | -+ service->localport; -+ handle_seq += VCHIQ_MAX_STATES * VCHIQ_MAX_SERVICES; -+ *pservice = service; -+ if (pservice == &state->services[state->unused_service]) -+ state->unused_service++; -+ } -+ -+ mutex_unlock(&state->mutex); -+ -+ if (!pservice) { -+ kfree(service); -+ service = NULL; -+ } -+ } -+ -+ if (service) { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &state->service_quotas[service->localport]; -+ service_quota->slot_quota = state->default_slot_quota; -+ service_quota->message_quota = state->default_message_quota; -+ if (service_quota->slot_use_count == 0) -+ service_quota->previous_tx_index = -+ SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos) -+ - 1; -+ -+ /* Bring this service online */ -+ vchiq_set_service_state(service, srvstate); -+ -+ vchiq_log_info(vchiq_core_msg_log_level, -+ "%s Service %c%c%c%c SrcPort:%d", -+ (srvstate == VCHIQ_SRVSTATE_OPENING) -+ ? "Open" : "Add", -+ VCHIQ_FOURCC_AS_4CHARS(params->fourcc), -+ service->localport); -+ } -+ -+ /* Don't unlock the service - leave it with a ref_count of 1. */ -+ -+ return service; -+} -+ -+VCHIQ_STATUS_T -+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) -+{ -+ struct vchiq_open_payload payload = { -+ service->base.fourcc, -+ client_id, -+ service->version, -+ service->version_min -+ }; -+ VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) }; -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ service->client_id = client_id; -+ vchiq_use_service_internal(service); -+ status = queue_message(service->state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0), -+ &body, 1, sizeof(payload), QMFLAGS_IS_BLOCKING); -+ if (status == VCHIQ_SUCCESS) { -+ /* Wait for the ACK/NAK */ -+ if (down_interruptible(&service->remove_event) != 0) { -+ status = VCHIQ_RETRY; -+ vchiq_release_service_internal(service); -+ } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && -+ (service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) { -+ if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: osi - srvstate = %s (ref %d)", -+ service->state->id, -+ srvstate_names[service->srvstate], -+ service->ref_count); -+ status = VCHIQ_ERROR; -+ VCHIQ_SERVICE_STATS_INC(service, error_count); -+ vchiq_release_service_internal(service); -+ } -+ } -+ return status; -+} -+ -+static void -+release_service_messages(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ int slot_last = state->remote->slot_last; -+ int i; -+ -+ /* Release any claimed messages aimed at this service */ -+ -+ if (service->sync) { -+ VCHIQ_HEADER_T *header = -+ (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, -+ state->remote->slot_sync); -+ if (VCHIQ_MSG_DSTPORT(header->msgid) == service->localport) -+ release_message_sync(state, header); -+ -+ return; -+ } -+ -+ for (i = state->remote->slot_first; i <= slot_last; i++) { -+ VCHIQ_SLOT_INFO_T *slot_info = -+ SLOT_INFO_FROM_INDEX(state, i); -+ if (slot_info->release_count != slot_info->use_count) { -+ char *data = -+ (char *)SLOT_DATA_FROM_INDEX(state, i); -+ unsigned int pos, end; -+ -+ end = VCHIQ_SLOT_SIZE; -+ if (data == state->rx_data) -+ /* This buffer is still being read from - stop -+ ** at the current read position */ -+ end = state->rx_pos & VCHIQ_SLOT_MASK; -+ -+ pos = 0; -+ -+ while (pos < end) { -+ VCHIQ_HEADER_T *header = -+ (VCHIQ_HEADER_T *)(data + pos); -+ int msgid = header->msgid; -+ int port = VCHIQ_MSG_DSTPORT(msgid); -+ if ((port == service->localport) && -+ (msgid & VCHIQ_MSGID_CLAIMED)) { -+ vchiq_log_info(vchiq_core_log_level, -+ " fsi - hdr %x", -+ (unsigned int)header); -+ release_slot(state, slot_info, header, -+ NULL); -+ } -+ pos += calc_stride(header->size); -+ if (pos > VCHIQ_SLOT_SIZE) { -+ vchiq_log_error(vchiq_core_log_level, -+ "fsi - pos %x: header %x, " -+ "msgid %x, header->msgid %x, " -+ "header->size %x", -+ pos, (unsigned int)header, -+ msgid, header->msgid, -+ header->size); -+ WARN(1, "invalid slot position\n"); -+ } -+ } -+ } -+ } -+} -+ -+static int -+do_abort_bulks(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATUS_T status; -+ -+ /* Abort any outstanding bulk transfers */ -+ if (mutex_lock_interruptible(&service->bulk_mutex) != 0) -+ return 0; -+ abort_outstanding_bulks(service, &service->bulk_tx); -+ abort_outstanding_bulks(service, &service->bulk_rx); -+ mutex_unlock(&service->bulk_mutex); -+ -+ status = notify_bulks(service, &service->bulk_tx, 0/*!retry_poll*/); -+ if (status == VCHIQ_SUCCESS) -+ status = notify_bulks(service, &service->bulk_rx, -+ 0/*!retry_poll*/); -+ return (status == VCHIQ_SUCCESS); -+} -+ -+static VCHIQ_STATUS_T -+close_service_complete(VCHIQ_SERVICE_T *service, int failstate) -+{ -+ VCHIQ_STATUS_T status; -+ int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); -+ int newstate; -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_OPEN: -+ case VCHIQ_SRVSTATE_CLOSESENT: -+ case VCHIQ_SRVSTATE_CLOSERECVD: -+ if (is_server) { -+ if (service->auto_close) { -+ service->client_id = 0; -+ service->remoteport = VCHIQ_PORT_FREE; -+ newstate = VCHIQ_SRVSTATE_LISTENING; -+ } else -+ newstate = VCHIQ_SRVSTATE_CLOSEWAIT; -+ } else -+ newstate = VCHIQ_SRVSTATE_CLOSED; -+ vchiq_set_service_state(service, newstate); -+ break; -+ case VCHIQ_SRVSTATE_LISTENING: -+ break; -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "close_service_complete(%x) called in state %s", -+ service->handle, srvstate_names[service->srvstate]); -+ WARN(1, "close_service_complete in unexpected state\n"); -+ return VCHIQ_ERROR; -+ } -+ -+ status = make_service_callback(service, -+ VCHIQ_SERVICE_CLOSED, NULL, NULL); -+ -+ if (status != VCHIQ_RETRY) { -+ int uc = service->service_use_count; -+ int i; -+ /* Complete the close process */ -+ for (i = 0; i < uc; i++) -+ /* cater for cases where close is forced and the -+ ** client may not close all it's handles */ -+ vchiq_release_service_internal(service); -+ -+ service->client_id = 0; -+ service->remoteport = VCHIQ_PORT_FREE; -+ -+ if (service->srvstate == VCHIQ_SRVSTATE_CLOSED) -+ vchiq_free_service_internal(service); -+ else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) { -+ if (is_server) -+ service->closing = 0; -+ -+ up(&service->remove_event); -+ } -+ } else -+ vchiq_set_service_state(service, failstate); -+ -+ return status; -+} -+ -+/* Called by the slot handler */ -+VCHIQ_STATUS_T -+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); -+ -+ vchiq_log_info(vchiq_core_log_level, "%d: csi:%d,%d (%s)", -+ service->state->id, service->localport, close_recvd, -+ srvstate_names[service->srvstate]); -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_CLOSED: -+ case VCHIQ_SRVSTATE_HIDDEN: -+ case VCHIQ_SRVSTATE_LISTENING: -+ case VCHIQ_SRVSTATE_CLOSEWAIT: -+ if (close_recvd) -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_close_service_internal(1) called " -+ "in state %s", -+ srvstate_names[service->srvstate]); -+ else if (is_server) { -+ if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { -+ status = VCHIQ_ERROR; -+ } else { -+ service->client_id = 0; -+ service->remoteport = VCHIQ_PORT_FREE; -+ if (service->srvstate == -+ VCHIQ_SRVSTATE_CLOSEWAIT) -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_LISTENING); -+ } -+ up(&service->remove_event); -+ } else -+ vchiq_free_service_internal(service); -+ break; -+ case VCHIQ_SRVSTATE_OPENING: -+ if (close_recvd) { -+ /* The open was rejected - tell the user */ -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_CLOSEWAIT); -+ up(&service->remove_event); -+ } else { -+ /* Shutdown mid-open - let the other side know */ -+ status = queue_message(state, service, -+ VCHIQ_MAKE_MSG -+ (VCHIQ_MSG_CLOSE, -+ service->localport, -+ VCHIQ_MSG_DSTPORT(service->remoteport)), -+ NULL, 0, 0, 0); -+ } -+ break; -+ -+ case VCHIQ_SRVSTATE_OPENSYNC: -+ mutex_lock(&state->sync_mutex); -+ /* Drop through */ -+ -+ case VCHIQ_SRVSTATE_OPEN: -+ if (state->is_master || close_recvd) { -+ if (!do_abort_bulks(service)) -+ status = VCHIQ_RETRY; -+ } -+ -+ release_service_messages(service); -+ -+ if (status == VCHIQ_SUCCESS) -+ status = queue_message(state, service, -+ VCHIQ_MAKE_MSG -+ (VCHIQ_MSG_CLOSE, -+ service->localport, -+ VCHIQ_MSG_DSTPORT(service->remoteport)), -+ NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK); -+ -+ if (status == VCHIQ_SUCCESS) { -+ if (!close_recvd) { -+ /* Change the state while the mutex is -+ still held */ -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_CLOSESENT); -+ mutex_unlock(&state->slot_mutex); -+ if (service->sync) -+ mutex_unlock(&state->sync_mutex); -+ break; -+ } -+ } else if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) { -+ mutex_unlock(&state->sync_mutex); -+ break; -+ } else -+ break; -+ -+ /* Change the state while the mutex is still held */ -+ vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD); -+ mutex_unlock(&state->slot_mutex); -+ if (service->sync) -+ mutex_unlock(&state->sync_mutex); -+ -+ status = close_service_complete(service, -+ VCHIQ_SRVSTATE_CLOSERECVD); -+ break; -+ -+ case VCHIQ_SRVSTATE_CLOSESENT: -+ if (!close_recvd) -+ /* This happens when a process is killed mid-close */ -+ break; -+ -+ if (!state->is_master) { -+ if (!do_abort_bulks(service)) { -+ status = VCHIQ_RETRY; -+ break; -+ } -+ } -+ -+ if (status == VCHIQ_SUCCESS) -+ status = close_service_complete(service, -+ VCHIQ_SRVSTATE_CLOSERECVD); -+ break; -+ -+ case VCHIQ_SRVSTATE_CLOSERECVD: -+ if (!close_recvd && is_server) -+ /* Force into LISTENING mode */ -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_LISTENING); -+ status = close_service_complete(service, -+ VCHIQ_SRVSTATE_CLOSERECVD); -+ break; -+ -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_close_service_internal(%d) called in state %s", -+ close_recvd, srvstate_names[service->srvstate]); -+ break; -+ } -+ -+ return status; -+} -+ -+/* Called from the application process upon process death */ -+void -+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ -+ vchiq_log_info(vchiq_core_log_level, "%d: tsi - (%d<->%d)", -+ state->id, service->localport, service->remoteport); -+ -+ mark_service_closing(service); -+ -+ /* Mark the service for removal by the slot handler */ -+ request_poll(state, service, VCHIQ_POLL_REMOVE); -+} -+ -+/* Called from the slot handler */ -+void -+vchiq_free_service_internal(VCHIQ_SERVICE_T *service) -+{ -+ VCHIQ_STATE_T *state = service->state; -+ -+ vchiq_log_info(vchiq_core_log_level, "%d: fsi - (%d)", -+ state->id, service->localport); -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_OPENING: -+ case VCHIQ_SRVSTATE_CLOSED: -+ case VCHIQ_SRVSTATE_HIDDEN: -+ case VCHIQ_SRVSTATE_LISTENING: -+ case VCHIQ_SRVSTATE_CLOSEWAIT: -+ break; -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "%d: fsi - (%d) in state %s", -+ state->id, service->localport, -+ srvstate_names[service->srvstate]); -+ return; -+ } -+ -+ vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE); -+ -+ up(&service->remove_event); -+ -+ /* Release the initial lock */ -+ unlock_service(service); -+} -+ -+VCHIQ_STATUS_T -+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_SERVICE_T *service; -+ int i; -+ -+ /* Find all services registered to this client and enable them. */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, -+ &i)) != NULL) { -+ if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN) -+ vchiq_set_service_state(service, -+ VCHIQ_SRVSTATE_LISTENING); -+ unlock_service(service); -+ } -+ -+ if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) { -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0, -+ 0, QMFLAGS_IS_BLOCKING) == VCHIQ_RETRY) -+ return VCHIQ_RETRY; -+ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING); -+ } -+ -+ if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) { -+ if (down_interruptible(&state->connect) != 0) -+ return VCHIQ_RETRY; -+ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); -+ up(&state->connect); -+ } -+ -+ return VCHIQ_SUCCESS; -+} -+ -+VCHIQ_STATUS_T -+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_SERVICE_T *service; -+ int i; -+ -+ /* Find all services registered to this client and enable them. */ -+ i = 0; -+ while ((service = next_service_by_instance(state, instance, -+ &i)) != NULL) { -+ (void)vchiq_remove_service(service->handle); -+ unlock_service(service); -+ } -+ -+ return VCHIQ_SUCCESS; -+} -+ -+VCHIQ_STATUS_T -+vchiq_pause_internal(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ switch (state->conn_state) { -+ case VCHIQ_CONNSTATE_CONNECTED: -+ /* Request a pause */ -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSING); -+ request_poll(state, NULL, 0); -+ break; -+ default: -+ vchiq_log_error(vchiq_core_log_level, -+ "vchiq_pause_internal in state %s\n", -+ conn_state_names[state->conn_state]); -+ status = VCHIQ_ERROR; -+ VCHIQ_STATS_INC(state, error_count); -+ break; -+ } -+ -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_resume_internal(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { -+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_RESUMING); -+ request_poll(state, NULL, 0); -+ } else { -+ status = VCHIQ_ERROR; -+ VCHIQ_STATS_INC(state, error_count); -+ } -+ -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ /* Unregister the service */ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (!service) -+ return VCHIQ_ERROR; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: close_service:%d", -+ service->state->id, service->localport); -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || -+ (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)) { -+ unlock_service(service); -+ return VCHIQ_ERROR; -+ } -+ -+ mark_service_closing(service); -+ -+ if (current == service->state->slot_handler_thread) { -+ status = vchiq_close_service_internal(service, -+ 0/*!close_recvd*/); -+ BUG_ON(status == VCHIQ_RETRY); -+ } else { -+ /* Mark the service for termination by the slot handler */ -+ request_poll(service->state, service, VCHIQ_POLL_TERMINATE); -+ } -+ -+ while (1) { -+ if (down_interruptible(&service->remove_event) != 0) { -+ status = VCHIQ_RETRY; -+ break; -+ } -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || -+ (service->srvstate == VCHIQ_SRVSTATE_OPEN)) -+ break; -+ -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: close_service:%d - waiting in state %s", -+ service->state->id, service->localport, -+ srvstate_names[service->srvstate]); -+ } -+ -+ if ((status == VCHIQ_SUCCESS) && -+ (service->srvstate != VCHIQ_SRVSTATE_FREE) && -+ (service->srvstate != VCHIQ_SRVSTATE_LISTENING)) -+ status = VCHIQ_ERROR; -+ -+ unlock_service(service); -+ -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ /* Unregister the service */ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS; -+ -+ if (!service) -+ return VCHIQ_ERROR; -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: remove_service:%d", -+ service->state->id, service->localport); -+ -+ if (service->srvstate == VCHIQ_SRVSTATE_FREE) { -+ unlock_service(service); -+ return VCHIQ_ERROR; -+ } -+ -+ mark_service_closing(service); -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || -+ (current == service->state->slot_handler_thread)) { -+ /* Make it look like a client, because it must be removed and -+ not left in the LISTENING state. */ -+ service->public_fourcc = VCHIQ_FOURCC_INVALID; -+ -+ status = vchiq_close_service_internal(service, -+ 0/*!close_recvd*/); -+ BUG_ON(status == VCHIQ_RETRY); -+ } else { -+ /* Mark the service for removal by the slot handler */ -+ request_poll(service->state, service, VCHIQ_POLL_REMOVE); -+ } -+ while (1) { -+ if (down_interruptible(&service->remove_event) != 0) { -+ status = VCHIQ_RETRY; -+ break; -+ } -+ -+ if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || -+ (service->srvstate == VCHIQ_SRVSTATE_OPEN)) -+ break; -+ -+ vchiq_log_warning(vchiq_core_log_level, -+ "%d: remove_service:%d - waiting in state %s", -+ service->state->id, service->localport, -+ srvstate_names[service->srvstate]); -+ } -+ -+ if ((status == VCHIQ_SUCCESS) && -+ (service->srvstate != VCHIQ_SRVSTATE_FREE)) -+ status = VCHIQ_ERROR; -+ -+ unlock_service(service); -+ -+ return status; -+} -+ -+ -+/* This function may be called by kernel threads or user threads. -+ * User threads may receive VCHIQ_RETRY to indicate that a signal has been -+ * received and the call should be retried after being returned to user -+ * context. -+ * When called in blocking mode, the userdata field points to a bulk_waiter -+ * structure. -+ */ -+VCHIQ_STATUS_T -+vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_BULK_QUEUE_T *queue; -+ VCHIQ_BULK_T *bulk; -+ VCHIQ_STATE_T *state; -+ struct bulk_waiter *bulk_waiter = NULL; -+ const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; -+ const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? -+ VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX; -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ -+ if (!service || -+ (service->srvstate != VCHIQ_SRVSTATE_OPEN) || -+ ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) || -+ (vchiq_check_service(service) != VCHIQ_SUCCESS)) -+ goto error_exit; -+ -+ switch (mode) { -+ case VCHIQ_BULK_MODE_NOCALLBACK: -+ case VCHIQ_BULK_MODE_CALLBACK: -+ break; -+ case VCHIQ_BULK_MODE_BLOCKING: -+ bulk_waiter = (struct bulk_waiter *)userdata; -+ sema_init(&bulk_waiter->event, 0); -+ bulk_waiter->actual = 0; -+ bulk_waiter->bulk = NULL; -+ break; -+ case VCHIQ_BULK_MODE_WAITING: -+ bulk_waiter = (struct bulk_waiter *)userdata; -+ bulk = bulk_waiter->bulk; -+ goto waiting; -+ default: -+ goto error_exit; -+ } -+ -+ state = service->state; -+ -+ queue = (dir == VCHIQ_BULK_TRANSMIT) ? -+ &service->bulk_tx : &service->bulk_rx; -+ -+ if (mutex_lock_interruptible(&service->bulk_mutex) != 0) { -+ status = VCHIQ_RETRY; -+ goto error_exit; -+ } -+ -+ if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) { -+ VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); -+ do { -+ mutex_unlock(&service->bulk_mutex); -+ if (down_interruptible(&service->bulk_remove_event) -+ != 0) { -+ status = VCHIQ_RETRY; -+ goto error_exit; -+ } -+ if (mutex_lock_interruptible(&service->bulk_mutex) -+ != 0) { -+ status = VCHIQ_RETRY; -+ goto error_exit; -+ } -+ } while (queue->local_insert == queue->remove + -+ VCHIQ_NUM_SERVICE_BULKS); -+ } -+ -+ bulk = &queue->bulks[BULK_INDEX(queue->local_insert)]; -+ -+ bulk->mode = mode; -+ bulk->dir = dir; -+ bulk->userdata = userdata; -+ bulk->size = size; -+ bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; -+ -+ if (vchiq_prepare_bulk_data(bulk, memhandle, offset, size, dir) != -+ VCHIQ_SUCCESS) -+ goto unlock_error_exit; -+ -+ wmb(); -+ -+ vchiq_log_info(vchiq_core_log_level, -+ "%d: bt (%d->%d) %cx %x@%x %x", -+ state->id, -+ service->localport, service->remoteport, dir_char, -+ size, (unsigned int)bulk->data, (unsigned int)userdata); -+ -+ /* The slot mutex must be held when the service is being closed, so -+ claim it here to ensure that isn't happening */ -+ if (mutex_lock_interruptible(&state->slot_mutex) != 0) { -+ status = VCHIQ_RETRY; -+ goto cancel_bulk_error_exit; -+ } -+ -+ if (service->srvstate != VCHIQ_SRVSTATE_OPEN) -+ goto unlock_both_error_exit; -+ -+ if (state->is_master) { -+ queue->local_insert++; -+ if (resolve_bulks(service, queue)) -+ request_poll(state, service, -+ (dir == VCHIQ_BULK_TRANSMIT) ? -+ VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); -+ } else { -+ int payload[2] = { (int)bulk->data, bulk->size }; -+ VCHIQ_ELEMENT_T element = { payload, sizeof(payload) }; -+ -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(dir_msgtype, -+ service->localport, service->remoteport), -+ &element, 1, sizeof(payload), -+ QMFLAGS_IS_BLOCKING | -+ QMFLAGS_NO_MUTEX_LOCK | -+ QMFLAGS_NO_MUTEX_UNLOCK); -+ if (status != VCHIQ_SUCCESS) { -+ goto unlock_both_error_exit; -+ } -+ queue->local_insert++; -+ } -+ -+ mutex_unlock(&state->slot_mutex); -+ mutex_unlock(&service->bulk_mutex); -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%d: bt:%d %cx li=%x ri=%x p=%x", -+ state->id, -+ service->localport, dir_char, -+ queue->local_insert, queue->remote_insert, queue->process); -+ -+waiting: -+ unlock_service(service); -+ -+ status = VCHIQ_SUCCESS; -+ -+ if (bulk_waiter) { -+ bulk_waiter->bulk = bulk; -+ if (down_interruptible(&bulk_waiter->event) != 0) -+ status = VCHIQ_RETRY; -+ else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) -+ status = VCHIQ_ERROR; -+ } -+ -+ return status; -+ -+unlock_both_error_exit: -+ mutex_unlock(&state->slot_mutex); -+cancel_bulk_error_exit: -+ vchiq_complete_bulk(bulk); -+unlock_error_exit: -+ mutex_unlock(&service->bulk_mutex); -+ -+error_exit: -+ if (service) -+ unlock_service(service); -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, -+ const VCHIQ_ELEMENT_T *elements, unsigned int count) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ -+ unsigned int size = 0; -+ unsigned int i; -+ -+ if (!service || -+ (vchiq_check_service(service) != VCHIQ_SUCCESS)) -+ goto error_exit; -+ -+ for (i = 0; i < (unsigned int)count; i++) { -+ if (elements[i].size) { -+ if (elements[i].data == NULL) { -+ VCHIQ_SERVICE_STATS_INC(service, error_count); -+ goto error_exit; -+ } -+ size += elements[i].size; -+ } -+ } -+ -+ if (size > VCHIQ_MAX_MSG_SIZE) { -+ VCHIQ_SERVICE_STATS_INC(service, error_count); -+ goto error_exit; -+ } -+ -+ switch (service->srvstate) { -+ case VCHIQ_SRVSTATE_OPEN: -+ status = queue_message(service->state, service, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, -+ service->localport, -+ service->remoteport), -+ elements, count, size, 1); -+ break; -+ case VCHIQ_SRVSTATE_OPENSYNC: -+ status = queue_message_sync(service->state, service, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, -+ service->localport, -+ service->remoteport), -+ elements, count, size, 1); -+ break; -+ default: -+ status = VCHIQ_ERROR; -+ break; -+ } -+ -+error_exit: -+ if (service) -+ unlock_service(service); -+ -+ return status; -+} -+ -+void -+vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_SHARED_STATE_T *remote; -+ VCHIQ_STATE_T *state; -+ int slot_index; -+ -+ if (!service) -+ return; -+ -+ state = service->state; -+ remote = state->remote; -+ -+ slot_index = SLOT_INDEX_FROM_DATA(state, (void *)header); -+ -+ if ((slot_index >= remote->slot_first) && -+ (slot_index <= remote->slot_last)) { -+ int msgid = header->msgid; -+ if (msgid & VCHIQ_MSGID_CLAIMED) { -+ VCHIQ_SLOT_INFO_T *slot_info = -+ SLOT_INFO_FROM_INDEX(state, slot_index); -+ -+ release_slot(state, slot_info, header, service); -+ } -+ } else if (slot_index == remote->slot_sync) -+ release_message_sync(state, header); -+ -+ unlock_service(service); -+} -+ -+static void -+release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) -+{ -+ header->msgid = VCHIQ_MSGID_PADDING; -+ wmb(); -+ remote_event_signal(&state->remote->sync_release); -+} -+ -+VCHIQ_STATUS_T -+vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, short *peer_version) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ -+ if (!service || -+ (vchiq_check_service(service) != VCHIQ_SUCCESS) || -+ !peer_version) -+ goto exit; -+ *peer_version = service->peer_version; -+ status = VCHIQ_SUCCESS; -+ -+exit: -+ if (service) -+ unlock_service(service); -+ return status; -+} -+ -+VCHIQ_STATUS_T -+vchiq_get_config(VCHIQ_INSTANCE_T instance, -+ int config_size, VCHIQ_CONFIG_T *pconfig) -+{ -+ VCHIQ_CONFIG_T config; -+ -+ (void)instance; -+ -+ config.max_msg_size = VCHIQ_MAX_MSG_SIZE; -+ config.bulk_threshold = VCHIQ_MAX_MSG_SIZE; -+ config.max_outstanding_bulks = VCHIQ_NUM_SERVICE_BULKS; -+ config.max_services = VCHIQ_MAX_SERVICES; -+ config.version = VCHIQ_VERSION; -+ config.version_min = VCHIQ_VERSION_MIN; -+ -+ if (config_size > sizeof(VCHIQ_CONFIG_T)) -+ return VCHIQ_ERROR; -+ -+ memcpy(pconfig, &config, -+ min(config_size, (int)(sizeof(VCHIQ_CONFIG_T)))); -+ -+ return VCHIQ_SUCCESS; -+} -+ -+VCHIQ_STATUS_T -+vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, -+ VCHIQ_SERVICE_OPTION_T option, int value) -+{ -+ VCHIQ_SERVICE_T *service = find_service_by_handle(handle); -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ -+ if (service) { -+ switch (option) { -+ case VCHIQ_SERVICE_OPTION_AUTOCLOSE: -+ service->auto_close = value; -+ status = VCHIQ_SUCCESS; -+ break; -+ -+ case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &service->state->service_quotas[ -+ service->localport]; -+ if (value == 0) -+ value = service->state->default_slot_quota; -+ if ((value >= service_quota->slot_use_count) && -+ (value < (unsigned short)~0)) { -+ service_quota->slot_quota = value; -+ if ((value >= service_quota->slot_use_count) && -+ (service_quota->message_quota >= -+ service_quota->message_use_count)) { -+ /* Signal the service that it may have -+ ** dropped below its quota */ -+ up(&service_quota->quota_event); -+ } -+ status = VCHIQ_SUCCESS; -+ } -+ } break; -+ -+ case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA: { -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &service->state->service_quotas[ -+ service->localport]; -+ if (value == 0) -+ value = service->state->default_message_quota; -+ if ((value >= service_quota->message_use_count) && -+ (value < (unsigned short)~0)) { -+ service_quota->message_quota = value; -+ if ((value >= -+ service_quota->message_use_count) && -+ (service_quota->slot_quota >= -+ service_quota->slot_use_count)) -+ /* Signal the service that it may have -+ ** dropped below its quota */ -+ up(&service_quota->quota_event); -+ status = VCHIQ_SUCCESS; -+ } -+ } break; -+ -+ case VCHIQ_SERVICE_OPTION_SYNCHRONOUS: -+ if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || -+ (service->srvstate == -+ VCHIQ_SRVSTATE_LISTENING)) { -+ service->sync = value; -+ status = VCHIQ_SUCCESS; -+ } -+ break; -+ -+ case VCHIQ_SERVICE_OPTION_TRACE: -+ service->trace = value; -+ status = VCHIQ_SUCCESS; -+ break; -+ -+ default: -+ break; -+ } -+ unlock_service(service); -+ } -+ -+ return status; -+} -+ -+void -+vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state, -+ VCHIQ_SHARED_STATE_T *shared, const char *label) -+{ -+ static const char *const debug_names[] = { -+ "", -+ "SLOT_HANDLER_COUNT", -+ "SLOT_HANDLER_LINE", -+ "PARSE_LINE", -+ "PARSE_HEADER", -+ "PARSE_MSGID", -+ "AWAIT_COMPLETION_LINE", -+ "DEQUEUE_MESSAGE_LINE", -+ "SERVICE_CALLBACK_LINE", -+ "MSG_QUEUE_FULL_COUNT", -+ "COMPLETION_QUEUE_FULL_COUNT" -+ }; -+ int i; -+ -+ char buf[80]; -+ int len; -+ len = snprintf(buf, sizeof(buf), -+ " %s: slots %d-%d tx_pos=%x recycle=%x", -+ label, shared->slot_first, shared->slot_last, -+ shared->tx_pos, shared->slot_queue_recycle); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Slots claimed:"); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ for (i = shared->slot_first; i <= shared->slot_last; i++) { -+ VCHIQ_SLOT_INFO_T slot_info = *SLOT_INFO_FROM_INDEX(state, i); -+ if (slot_info.use_count != slot_info.release_count) { -+ len = snprintf(buf, sizeof(buf), -+ " %d: %d/%d", i, slot_info.use_count, -+ slot_info.release_count); -+ vchiq_dump(dump_context, buf, len + 1); -+ } -+ } -+ -+ for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { -+ len = snprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", -+ debug_names[i], shared->debug[i], shared->debug[i]); -+ vchiq_dump(dump_context, buf, len + 1); -+ } -+} -+ -+void -+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) -+{ -+ char buf[80]; -+ int len; -+ int i; -+ -+ len = snprintf(buf, sizeof(buf), "State %d: %s", state->id, -+ conn_state_names[state->conn_state]); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " tx_pos=%x(@%x), rx_pos=%x(@%x)", -+ state->local->tx_pos, -+ (uint32_t)state->tx_data + -+ (state->local_tx_pos & VCHIQ_SLOT_MASK), -+ state->rx_pos, -+ (uint32_t)state->rx_data + -+ (state->rx_pos & VCHIQ_SLOT_MASK)); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Version: %d (min %d)", -+ VCHIQ_VERSION, VCHIQ_VERSION_MIN); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ if (VCHIQ_ENABLE_STATS) { -+ len = snprintf(buf, sizeof(buf), -+ " Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, " -+ "error_count=%d", -+ state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, -+ state->stats.error_count); -+ vchiq_dump(dump_context, buf, len + 1); -+ } -+ -+ len = snprintf(buf, sizeof(buf), -+ " Slots: %d available (%d data), %d recyclable, %d stalls " -+ "(%d data)", -+ ((state->slot_queue_available * VCHIQ_SLOT_SIZE) - -+ state->local_tx_pos) / VCHIQ_SLOT_SIZE, -+ state->data_quota - state->data_use_count, -+ state->local->slot_queue_recycle - state->slot_queue_available, -+ state->stats.slot_stalls, state->stats.data_stalls); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ vchiq_dump_platform_state(dump_context); -+ -+ vchiq_dump_shared_state(dump_context, state, state->local, "Local"); -+ vchiq_dump_shared_state(dump_context, state, state->remote, "Remote"); -+ -+ vchiq_dump_platform_instances(dump_context); -+ -+ for (i = 0; i < state->unused_service; i++) { -+ VCHIQ_SERVICE_T *service = find_service_by_port(state, i); -+ -+ if (service) { -+ vchiq_dump_service_state(dump_context, service); -+ unlock_service(service); -+ } -+ } -+} -+ -+void -+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service) -+{ -+ char buf[80]; -+ int len; -+ -+ len = snprintf(buf, sizeof(buf), "Service %d: %s (ref %u)", -+ service->localport, srvstate_names[service->srvstate], -+ service->ref_count - 1); /*Don't include the lock just taken*/ -+ -+ if (service->srvstate != VCHIQ_SRVSTATE_FREE) { -+ char remoteport[30]; -+ VCHIQ_SERVICE_QUOTA_T *service_quota = -+ &service->state->service_quotas[service->localport]; -+ int fourcc = service->base.fourcc; -+ int tx_pending, rx_pending; -+ if (service->remoteport != VCHIQ_PORT_FREE) { -+ int len2 = snprintf(remoteport, sizeof(remoteport), -+ "%d", service->remoteport); -+ if (service->public_fourcc != VCHIQ_FOURCC_INVALID) -+ snprintf(remoteport + len2, -+ sizeof(remoteport) - len2, -+ " (client %x)", service->client_id); -+ } else -+ strcpy(remoteport, "n/a"); -+ -+ len += snprintf(buf + len, sizeof(buf) - len, -+ " '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)", -+ VCHIQ_FOURCC_AS_4CHARS(fourcc), -+ remoteport, -+ service_quota->message_use_count, -+ service_quota->message_quota, -+ service_quota->slot_use_count, -+ service_quota->slot_quota); -+ -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ tx_pending = service->bulk_tx.local_insert - -+ service->bulk_tx.remote_insert; -+ -+ rx_pending = service->bulk_rx.local_insert - -+ service->bulk_rx.remote_insert; -+ -+ len = snprintf(buf, sizeof(buf), -+ " Bulk: tx_pending=%d (size %d)," -+ " rx_pending=%d (size %d)", -+ tx_pending, -+ tx_pending ? service->bulk_tx.bulks[ -+ BULK_INDEX(service->bulk_tx.remove)].size : 0, -+ rx_pending, -+ rx_pending ? service->bulk_rx.bulks[ -+ BULK_INDEX(service->bulk_rx.remove)].size : 0); -+ -+ if (VCHIQ_ENABLE_STATS) { -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Ctrl: tx_count=%d, tx_bytes=%llu, " -+ "rx_count=%d, rx_bytes=%llu", -+ service->stats.ctrl_tx_count, -+ service->stats.ctrl_tx_bytes, -+ service->stats.ctrl_rx_count, -+ service->stats.ctrl_rx_bytes); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " Bulk: tx_count=%d, tx_bytes=%llu, " -+ "rx_count=%d, rx_bytes=%llu", -+ service->stats.bulk_tx_count, -+ service->stats.bulk_tx_bytes, -+ service->stats.bulk_rx_count, -+ service->stats.bulk_rx_bytes); -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ len = snprintf(buf, sizeof(buf), -+ " %d quota stalls, %d slot stalls, " -+ "%d bulk stalls, %d aborted, %d errors", -+ service->stats.quota_stalls, -+ service->stats.slot_stalls, -+ service->stats.bulk_stalls, -+ service->stats.bulk_aborted_count, -+ service->stats.error_count); -+ } -+ } -+ -+ vchiq_dump(dump_context, buf, len + 1); -+ -+ if (service->srvstate != VCHIQ_SRVSTATE_FREE) -+ vchiq_dump_platform_service_state(dump_context, service); -+} -+ -+ -+void -+vchiq_loud_error_header(void) -+{ -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+ vchiq_log_error(vchiq_core_log_level, "====="); -+} -+ -+void -+vchiq_loud_error_footer(void) -+{ -+ vchiq_log_error(vchiq_core_log_level, "====="); -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+ vchiq_log_error(vchiq_core_log_level, -+ "============================================================" -+ "================"); -+} -+ -+ -+VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_RETRY; -+ if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE, 0, 0), -+ NULL, 0, 0, 0); -+ return status; -+} -+ -+VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_RETRY; -+ if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_RELEASE, 0, 0), -+ NULL, 0, 0, 0); -+ return status; -+} -+ -+VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T *state) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_RETRY; -+ if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE_ACTIVE, 0, 0), -+ NULL, 0, 0, 0); -+ return status; -+} -+ -+void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, -+ size_t numBytes) -+{ -+ const uint8_t *mem = (const uint8_t *)voidMem; -+ size_t offset; -+ char lineBuf[100]; -+ char *s; -+ -+ while (numBytes > 0) { -+ s = lineBuf; -+ -+ for (offset = 0; offset < 16; offset++) { -+ if (offset < numBytes) -+ s += snprintf(s, 4, "%02x ", mem[offset]); -+ else -+ s += snprintf(s, 4, " "); -+ } -+ -+ for (offset = 0; offset < 16; offset++) { -+ if (offset < numBytes) { -+ uint8_t ch = mem[offset]; -+ -+ if ((ch < ' ') || (ch > '~')) -+ ch = '.'; -+ *s++ = (char)ch; -+ } -+ } -+ *s++ = '\0'; -+ -+ if ((label != NULL) && (*label != '\0')) -+ vchiq_log_trace(VCHIQ_LOG_TRACE, -+ "%s: %08x: %s", label, addr, lineBuf); -+ else -+ vchiq_log_trace(VCHIQ_LOG_TRACE, -+ "%08x: %s", addr, lineBuf); -+ -+ addr += 16; -+ mem += 16; -+ if (numBytes > 16) -+ numBytes -= 16; -+ else -+ numBytes = 0; -+ } -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h -new file mode 100644 -index 0000000000000000000000000000000000000000..9be484c776d044a51bb3904c6a1e2cd11a852e35 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h -@@ -0,0 +1,712 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_CORE_H -+#define VCHIQ_CORE_H -+ -+#include -+#include -+#include -+ -+#include "vchiq_cfg.h" -+ -+#include "vchiq.h" -+ -+/* Run time control of log level, based on KERN_XXX level. */ -+#define VCHIQ_LOG_DEFAULT 4 -+#define VCHIQ_LOG_ERROR 3 -+#define VCHIQ_LOG_WARNING 4 -+#define VCHIQ_LOG_INFO 6 -+#define VCHIQ_LOG_TRACE 7 -+ -+#define VCHIQ_LOG_PREFIX KERN_INFO "vchiq: " -+ -+#ifndef vchiq_log_error -+#define vchiq_log_error(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_ERROR) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+#ifndef vchiq_log_warning -+#define vchiq_log_warning(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_WARNING) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+#ifndef vchiq_log_info -+#define vchiq_log_info(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_INFO) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+#ifndef vchiq_log_trace -+#define vchiq_log_trace(cat, fmt, ...) \ -+ do { if (cat >= VCHIQ_LOG_TRACE) \ -+ printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) -+#endif -+ -+#define vchiq_loud_error(...) \ -+ vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__) -+ -+#ifndef vchiq_static_assert -+#define vchiq_static_assert(cond) __attribute__((unused)) \ -+ extern int vchiq_static_assert[(cond) ? 1 : -1] -+#endif -+ -+#define IS_POW2(x) (x && ((x & (x - 1)) == 0)) -+ -+/* Ensure that the slot size and maximum number of slots are powers of 2 */ -+vchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE)); -+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS)); -+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE)); -+ -+#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) -+#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) -+#define VCHIQ_SLOT_ZERO_SLOTS ((sizeof(VCHIQ_SLOT_ZERO_T) + \ -+ VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE) -+ -+#define VCHIQ_MSG_PADDING 0 /* - */ -+#define VCHIQ_MSG_CONNECT 1 /* - */ -+#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */ -+#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */ -+#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */ -+#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */ -+#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */ -+#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */ -+#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */ -+#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */ -+#define VCHIQ_MSG_PAUSE 10 /* - */ -+#define VCHIQ_MSG_RESUME 11 /* - */ -+#define VCHIQ_MSG_REMOTE_USE 12 /* - */ -+#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */ -+#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */ -+ -+#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1) -+#define VCHIQ_PORT_FREE 0x1000 -+#define VCHIQ_PORT_IS_VALID(port) (port < VCHIQ_PORT_FREE) -+#define VCHIQ_MAKE_MSG(type, srcport, dstport) \ -+ ((type<<24) | (srcport<<12) | (dstport<<0)) -+#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)msgid >> 24) -+#define VCHIQ_MSG_SRCPORT(msgid) \ -+ (unsigned short)(((unsigned int)msgid >> 12) & 0xfff) -+#define VCHIQ_MSG_DSTPORT(msgid) \ -+ ((unsigned short)msgid & 0xfff) -+ -+#define VCHIQ_FOURCC_AS_4CHARS(fourcc) \ -+ ((fourcc) >> 24) & 0xff, \ -+ ((fourcc) >> 16) & 0xff, \ -+ ((fourcc) >> 8) & 0xff, \ -+ (fourcc) & 0xff -+ -+/* Ensure the fields are wide enough */ -+vchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) -+ == 0); -+vchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); -+vchiq_static_assert((unsigned int)VCHIQ_PORT_MAX < -+ (unsigned int)VCHIQ_PORT_FREE); -+ -+#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) -+#define VCHIQ_MSGID_CLAIMED 0x40000000 -+ -+#define VCHIQ_FOURCC_INVALID 0x00000000 -+#define VCHIQ_FOURCC_IS_LEGAL(fourcc) (fourcc != VCHIQ_FOURCC_INVALID) -+ -+#define VCHIQ_BULK_ACTUAL_ABORTED -1 -+ -+typedef uint32_t BITSET_T; -+ -+vchiq_static_assert((sizeof(BITSET_T) * 8) == 32); -+ -+#define BITSET_SIZE(b) ((b + 31) >> 5) -+#define BITSET_WORD(b) (b >> 5) -+#define BITSET_BIT(b) (1 << (b & 31)) -+#define BITSET_ZERO(bs) memset(bs, 0, sizeof(bs)) -+#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) -+#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) -+#define BITSET_CLR(bs, b) (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b)) -+ -+#if VCHIQ_ENABLE_STATS -+#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++) -+#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++) -+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \ -+ (service->stats. stat += addend) -+#else -+#define VCHIQ_STATS_INC(state, stat) ((void)0) -+#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0) -+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0) -+#endif -+ -+enum { -+ DEBUG_ENTRIES, -+#if VCHIQ_ENABLE_DEBUG -+ DEBUG_SLOT_HANDLER_COUNT, -+ DEBUG_SLOT_HANDLER_LINE, -+ DEBUG_PARSE_LINE, -+ DEBUG_PARSE_HEADER, -+ DEBUG_PARSE_MSGID, -+ DEBUG_AWAIT_COMPLETION_LINE, -+ DEBUG_DEQUEUE_MESSAGE_LINE, -+ DEBUG_SERVICE_CALLBACK_LINE, -+ DEBUG_MSG_QUEUE_FULL_COUNT, -+ DEBUG_COMPLETION_QUEUE_FULL_COUNT, -+#endif -+ DEBUG_MAX -+}; -+ -+#if VCHIQ_ENABLE_DEBUG -+ -+#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug; -+#define DEBUG_TRACE(d) \ -+ do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0) -+#define DEBUG_VALUE(d, v) \ -+ do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0) -+#define DEBUG_COUNT(d) \ -+ do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0) -+ -+#else /* VCHIQ_ENABLE_DEBUG */ -+ -+#define DEBUG_INITIALISE(local) -+#define DEBUG_TRACE(d) -+#define DEBUG_VALUE(d, v) -+#define DEBUG_COUNT(d) -+ -+#endif /* VCHIQ_ENABLE_DEBUG */ -+ -+typedef enum { -+ VCHIQ_CONNSTATE_DISCONNECTED, -+ VCHIQ_CONNSTATE_CONNECTING, -+ VCHIQ_CONNSTATE_CONNECTED, -+ VCHIQ_CONNSTATE_PAUSING, -+ VCHIQ_CONNSTATE_PAUSE_SENT, -+ VCHIQ_CONNSTATE_PAUSED, -+ VCHIQ_CONNSTATE_RESUMING, -+ VCHIQ_CONNSTATE_PAUSE_TIMEOUT, -+ VCHIQ_CONNSTATE_RESUME_TIMEOUT -+} VCHIQ_CONNSTATE_T; -+ -+enum { -+ VCHIQ_SRVSTATE_FREE, -+ VCHIQ_SRVSTATE_HIDDEN, -+ VCHIQ_SRVSTATE_LISTENING, -+ VCHIQ_SRVSTATE_OPENING, -+ VCHIQ_SRVSTATE_OPEN, -+ VCHIQ_SRVSTATE_OPENSYNC, -+ VCHIQ_SRVSTATE_CLOSESENT, -+ VCHIQ_SRVSTATE_CLOSERECVD, -+ VCHIQ_SRVSTATE_CLOSEWAIT, -+ VCHIQ_SRVSTATE_CLOSED -+}; -+ -+enum { -+ VCHIQ_POLL_TERMINATE, -+ VCHIQ_POLL_REMOVE, -+ VCHIQ_POLL_TXNOTIFY, -+ VCHIQ_POLL_RXNOTIFY, -+ VCHIQ_POLL_COUNT -+}; -+ -+typedef enum { -+ VCHIQ_BULK_TRANSMIT, -+ VCHIQ_BULK_RECEIVE -+} VCHIQ_BULK_DIR_T; -+ -+typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata); -+ -+typedef struct vchiq_bulk_struct { -+ short mode; -+ short dir; -+ void *userdata; -+ VCHI_MEM_HANDLE_T handle; -+ void *data; -+ int size; -+ void *remote_data; -+ int remote_size; -+ int actual; -+} VCHIQ_BULK_T; -+ -+typedef struct vchiq_bulk_queue_struct { -+ int local_insert; /* Where to insert the next local bulk */ -+ int remote_insert; /* Where to insert the next remote bulk (master) */ -+ int process; /* Bulk to transfer next */ -+ int remote_notify; /* Bulk to notify the remote client of next (mstr) */ -+ int remove; /* Bulk to notify the local client of, and remove, -+ ** next */ -+ VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS]; -+} VCHIQ_BULK_QUEUE_T; -+ -+typedef struct remote_event_struct { -+ int armed; -+ int fired; -+ struct semaphore *event; -+} REMOTE_EVENT_T; -+ -+typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T; -+ -+typedef struct vchiq_state_struct VCHIQ_STATE_T; -+ -+typedef struct vchiq_slot_struct { -+ char data[VCHIQ_SLOT_SIZE]; -+} VCHIQ_SLOT_T; -+ -+typedef struct vchiq_slot_info_struct { -+ /* Use two counters rather than one to avoid the need for a mutex. */ -+ short use_count; -+ short release_count; -+} VCHIQ_SLOT_INFO_T; -+ -+typedef struct vchiq_service_struct { -+ VCHIQ_SERVICE_BASE_T base; -+ VCHIQ_SERVICE_HANDLE_T handle; -+ unsigned int ref_count; -+ int srvstate; -+ VCHIQ_USERDATA_TERM_T userdata_term; -+ unsigned int localport; -+ unsigned int remoteport; -+ int public_fourcc; -+ int client_id; -+ char auto_close; -+ char sync; -+ char closing; -+ char trace; -+ atomic_t poll_flags; -+ short version; -+ short version_min; -+ short peer_version; -+ -+ VCHIQ_STATE_T *state; -+ VCHIQ_INSTANCE_T instance; -+ -+ int service_use_count; -+ -+ VCHIQ_BULK_QUEUE_T bulk_tx; -+ VCHIQ_BULK_QUEUE_T bulk_rx; -+ -+ struct semaphore remove_event; -+ struct semaphore bulk_remove_event; -+ struct mutex bulk_mutex; -+ -+ struct service_stats_struct { -+ int quota_stalls; -+ int slot_stalls; -+ int bulk_stalls; -+ int error_count; -+ int ctrl_tx_count; -+ int ctrl_rx_count; -+ int bulk_tx_count; -+ int bulk_rx_count; -+ int bulk_aborted_count; -+ uint64_t ctrl_tx_bytes; -+ uint64_t ctrl_rx_bytes; -+ uint64_t bulk_tx_bytes; -+ uint64_t bulk_rx_bytes; -+ } stats; -+} VCHIQ_SERVICE_T; -+ -+/* The quota information is outside VCHIQ_SERVICE_T so that it can be -+ statically allocated, since for accounting reasons a service's slot -+ usage is carried over between users of the same port number. -+ */ -+typedef struct vchiq_service_quota_struct { -+ unsigned short slot_quota; -+ unsigned short slot_use_count; -+ unsigned short message_quota; -+ unsigned short message_use_count; -+ struct semaphore quota_event; -+ int previous_tx_index; -+} VCHIQ_SERVICE_QUOTA_T; -+ -+typedef struct vchiq_shared_state_struct { -+ -+ /* A non-zero value here indicates that the content is valid. */ -+ int initialised; -+ -+ /* The first and last (inclusive) slots allocated to the owner. */ -+ int slot_first; -+ int slot_last; -+ -+ /* The slot allocated to synchronous messages from the owner. */ -+ int slot_sync; -+ -+ /* Signalling this event indicates that owner's slot handler thread -+ ** should run. */ -+ REMOTE_EVENT_T trigger; -+ -+ /* Indicates the byte position within the stream where the next message -+ ** will be written. The least significant bits are an index into the -+ ** slot. The next bits are the index of the slot in slot_queue. */ -+ int tx_pos; -+ -+ /* This event should be signalled when a slot is recycled. */ -+ REMOTE_EVENT_T recycle; -+ -+ /* The slot_queue index where the next recycled slot will be written. */ -+ int slot_queue_recycle; -+ -+ /* This event should be signalled when a synchronous message is sent. */ -+ REMOTE_EVENT_T sync_trigger; -+ -+ /* This event should be signalled when a synchronous message has been -+ ** released. */ -+ REMOTE_EVENT_T sync_release; -+ -+ /* A circular buffer of slot indexes. */ -+ int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; -+ -+ /* Debugging state */ -+ int debug[DEBUG_MAX]; -+} VCHIQ_SHARED_STATE_T; -+ -+typedef struct vchiq_slot_zero_struct { -+ int magic; -+ short version; -+ short version_min; -+ int slot_zero_size; -+ int slot_size; -+ int max_slots; -+ int max_slots_per_side; -+ int platform_data[2]; -+ VCHIQ_SHARED_STATE_T master; -+ VCHIQ_SHARED_STATE_T slave; -+ VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS]; -+} VCHIQ_SLOT_ZERO_T; -+ -+struct vchiq_state_struct { -+ int id; -+ int initialised; -+ VCHIQ_CONNSTATE_T conn_state; -+ int is_master; -+ short version_common; -+ -+ VCHIQ_SHARED_STATE_T *local; -+ VCHIQ_SHARED_STATE_T *remote; -+ VCHIQ_SLOT_T *slot_data; -+ -+ unsigned short default_slot_quota; -+ unsigned short default_message_quota; -+ -+ /* Event indicating connect message received */ -+ struct semaphore connect; -+ -+ /* Mutex protecting services */ -+ struct mutex mutex; -+ VCHIQ_INSTANCE_T *instance; -+ -+ /* Processes incoming messages */ -+ struct task_struct *slot_handler_thread; -+ -+ /* Processes recycled slots */ -+ struct task_struct *recycle_thread; -+ -+ /* Processes synchronous messages */ -+ struct task_struct *sync_thread; -+ -+ /* Local implementation of the trigger remote event */ -+ struct semaphore trigger_event; -+ -+ /* Local implementation of the recycle remote event */ -+ struct semaphore recycle_event; -+ -+ /* Local implementation of the sync trigger remote event */ -+ struct semaphore sync_trigger_event; -+ -+ /* Local implementation of the sync release remote event */ -+ struct semaphore sync_release_event; -+ -+ char *tx_data; -+ char *rx_data; -+ VCHIQ_SLOT_INFO_T *rx_info; -+ -+ struct mutex slot_mutex; -+ -+ struct mutex recycle_mutex; -+ -+ struct mutex sync_mutex; -+ -+ struct mutex bulk_transfer_mutex; -+ -+ /* Indicates the byte position within the stream from where the next -+ ** message will be read. The least significant bits are an index into -+ ** the slot.The next bits are the index of the slot in -+ ** remote->slot_queue. */ -+ int rx_pos; -+ -+ /* A cached copy of local->tx_pos. Only write to local->tx_pos, and read -+ from remote->tx_pos. */ -+ int local_tx_pos; -+ -+ /* The slot_queue index of the slot to become available next. */ -+ int slot_queue_available; -+ -+ /* A flag to indicate if any poll has been requested */ -+ int poll_needed; -+ -+ /* Ths index of the previous slot used for data messages. */ -+ int previous_data_index; -+ -+ /* The number of slots occupied by data messages. */ -+ unsigned short data_use_count; -+ -+ /* The maximum number of slots to be occupied by data messages. */ -+ unsigned short data_quota; -+ -+ /* An array of bit sets indicating which services must be polled. */ -+ atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; -+ -+ /* The number of the first unused service */ -+ int unused_service; -+ -+ /* Signalled when a free slot becomes available. */ -+ struct semaphore slot_available_event; -+ -+ struct semaphore slot_remove_event; -+ -+ /* Signalled when a free data slot becomes available. */ -+ struct semaphore data_quota_event; -+ -+ /* Incremented when there are bulk transfers which cannot be processed -+ * whilst paused and must be processed on resume */ -+ int deferred_bulks; -+ -+ struct state_stats_struct { -+ int slot_stalls; -+ int data_stalls; -+ int ctrl_tx_count; -+ int ctrl_rx_count; -+ int error_count; -+ } stats; -+ -+ VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES]; -+ VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES]; -+ VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS]; -+ -+ VCHIQ_PLATFORM_STATE_T platform_state; -+}; -+ -+struct bulk_waiter { -+ VCHIQ_BULK_T *bulk; -+ struct semaphore event; -+ int actual; -+}; -+ -+extern spinlock_t bulk_waiter_spinlock; -+ -+extern int vchiq_core_log_level; -+extern int vchiq_core_msg_log_level; -+extern int vchiq_sync_log_level; -+ -+extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; -+ -+extern const char * -+get_conn_state_name(VCHIQ_CONNSTATE_T conn_state); -+ -+extern VCHIQ_SLOT_ZERO_T * -+vchiq_init_slots(void *mem_base, int mem_size); -+ -+extern VCHIQ_STATUS_T -+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, -+ int is_master); -+ -+extern VCHIQ_STATUS_T -+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); -+ -+extern VCHIQ_SERVICE_T * -+vchiq_add_service_internal(VCHIQ_STATE_T *state, -+ const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, -+ VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term); -+ -+extern VCHIQ_STATUS_T -+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id); -+ -+extern VCHIQ_STATUS_T -+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd); -+ -+extern void -+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_free_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); -+ -+extern VCHIQ_STATUS_T -+vchiq_pause_internal(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_resume_internal(VCHIQ_STATE_T *state); -+ -+extern void -+remote_event_pollall(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, -+ VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir); -+ -+extern void -+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_loud_error_header(void); -+ -+extern void -+vchiq_loud_error_footer(void); -+ -+extern void -+request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type); -+ -+static inline VCHIQ_SERVICE_T * -+handle_to_service(VCHIQ_SERVICE_HANDLE_T handle) -+{ -+ VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & -+ (VCHIQ_MAX_STATES - 1)]; -+ if (!state) -+ return NULL; -+ -+ return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; -+} -+ -+extern VCHIQ_SERVICE_T * -+find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_SERVICE_T * -+find_service_by_port(VCHIQ_STATE_T *state, int localport); -+ -+extern VCHIQ_SERVICE_T * -+find_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_SERVICE_T * -+find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, -+ VCHIQ_SERVICE_HANDLE_T handle); -+ -+extern VCHIQ_SERVICE_T * -+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, -+ int *pidx); -+ -+extern void -+lock_service(VCHIQ_SERVICE_T *service); -+ -+extern void -+unlock_service(VCHIQ_SERVICE_T *service); -+ -+/* The following functions are called from vchiq_core, and external -+** implementations must be provided. */ -+ -+extern VCHIQ_STATUS_T -+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, -+ VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir); -+ -+extern void -+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk); -+ -+extern void -+vchiq_complete_bulk(VCHIQ_BULK_T *bulk); -+ -+extern VCHIQ_STATUS_T -+vchiq_copy_from_user(void *dst, const void *src, int size); -+ -+extern void -+remote_event_signal(REMOTE_EVENT_T *event); -+ -+void -+vchiq_platform_check_suspend(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_platform_paused(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_platform_resume(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_platform_resumed(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_dump(void *dump_context, const char *str, int len); -+ -+extern void -+vchiq_dump_platform_state(void *dump_context); -+ -+extern void -+vchiq_dump_platform_instances(void *dump_context); -+ -+extern void -+vchiq_dump_platform_service_state(void *dump_context, -+ VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_use_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern VCHIQ_STATUS_T -+vchiq_release_service_internal(VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_on_remote_use(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_on_remote_release(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_platform_init_state(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_check_service(VCHIQ_SERVICE_T *service); -+ -+extern void -+vchiq_on_remote_use_active(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_send_remote_use(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_send_remote_release(VCHIQ_STATE_T *state); -+ -+extern VCHIQ_STATUS_T -+vchiq_send_remote_use_active(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, -+ VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); -+ -+extern void -+vchiq_platform_handle_timeout(VCHIQ_STATE_T *state); -+ -+extern void -+vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate); -+ -+ -+extern void -+vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, -+ size_t numBytes); -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c -new file mode 100644 -index 0000000000000000000000000000000000000000..7e032130d967a69384926ddbe614e9af4be8f22e ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c -@@ -0,0 +1,383 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+ -+#include -+#include "vchiq_core.h" -+#include "vchiq_arm.h" -+#include "vchiq_debugfs.h" -+ -+#ifdef CONFIG_DEBUG_FS -+ -+/**************************************************************************** -+* -+* log category entries -+* -+***************************************************************************/ -+#define DEBUGFS_WRITE_BUF_SIZE 256 -+ -+#define VCHIQ_LOG_ERROR_STR "error" -+#define VCHIQ_LOG_WARNING_STR "warning" -+#define VCHIQ_LOG_INFO_STR "info" -+#define VCHIQ_LOG_TRACE_STR "trace" -+ -+ -+/* Top-level debug info */ -+struct vchiq_debugfs_info { -+ /* Global 'vchiq' debugfs entry used by all instances */ -+ struct dentry *vchiq_cfg_dir; -+ -+ /* one entry per client process */ -+ struct dentry *clients; -+ -+ /* log categories */ -+ struct dentry *log_categories; -+}; -+ -+static struct vchiq_debugfs_info debugfs_info; -+ -+/* Log category debugfs entries */ -+struct vchiq_debugfs_log_entry { -+ const char *name; -+ int *plevel; -+ struct dentry *dir; -+}; -+ -+static struct vchiq_debugfs_log_entry vchiq_debugfs_log_entries[] = { -+ { "core", &vchiq_core_log_level }, -+ { "msg", &vchiq_core_msg_log_level }, -+ { "sync", &vchiq_sync_log_level }, -+ { "susp", &vchiq_susp_log_level }, -+ { "arm", &vchiq_arm_log_level }, -+}; -+static int n_log_entries = -+ sizeof(vchiq_debugfs_log_entries)/sizeof(vchiq_debugfs_log_entries[0]); -+ -+ -+static struct dentry *vchiq_clients_top(void); -+static struct dentry *vchiq_debugfs_top(void); -+ -+static int debugfs_log_show(struct seq_file *f, void *offset) -+{ -+ int *levp = f->private; -+ char *log_value = NULL; -+ -+ switch (*levp) { -+ case VCHIQ_LOG_ERROR: -+ log_value = VCHIQ_LOG_ERROR_STR; -+ break; -+ case VCHIQ_LOG_WARNING: -+ log_value = VCHIQ_LOG_WARNING_STR; -+ break; -+ case VCHIQ_LOG_INFO: -+ log_value = VCHIQ_LOG_INFO_STR; -+ break; -+ case VCHIQ_LOG_TRACE: -+ log_value = VCHIQ_LOG_TRACE_STR; -+ break; -+ default: -+ break; -+ } -+ -+ seq_printf(f, "%s\n", log_value ? log_value : "(null)"); -+ -+ return 0; -+} -+ -+static int debugfs_log_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, debugfs_log_show, inode->i_private); -+} -+ -+static int debugfs_log_write(struct file *file, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct seq_file *f = (struct seq_file *)file->private_data; -+ int *levp = f->private; -+ char kbuf[DEBUGFS_WRITE_BUF_SIZE + 1]; -+ -+ memset(kbuf, 0, DEBUGFS_WRITE_BUF_SIZE + 1); -+ if (count >= DEBUGFS_WRITE_BUF_SIZE) -+ count = DEBUGFS_WRITE_BUF_SIZE; -+ -+ if (copy_from_user(kbuf, buffer, count) != 0) -+ return -EFAULT; -+ kbuf[count - 1] = 0; -+ -+ if (strncmp("error", kbuf, strlen("error")) == 0) -+ *levp = VCHIQ_LOG_ERROR; -+ else if (strncmp("warning", kbuf, strlen("warning")) == 0) -+ *levp = VCHIQ_LOG_WARNING; -+ else if (strncmp("info", kbuf, strlen("info")) == 0) -+ *levp = VCHIQ_LOG_INFO; -+ else if (strncmp("trace", kbuf, strlen("trace")) == 0) -+ *levp = VCHIQ_LOG_TRACE; -+ else -+ *levp = VCHIQ_LOG_DEFAULT; -+ -+ *ppos += count; -+ -+ return count; -+} -+ -+static const struct file_operations debugfs_log_fops = { -+ .owner = THIS_MODULE, -+ .open = debugfs_log_open, -+ .write = debugfs_log_write, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+/* create an entry under /vchiq/log for each log category */ -+static int vchiq_debugfs_create_log_entries(struct dentry *top) -+{ -+ struct dentry *dir; -+ size_t i; -+ int ret = 0; -+ dir = debugfs_create_dir("log", vchiq_debugfs_top()); -+ if (!dir) -+ return -ENOMEM; -+ debugfs_info.log_categories = dir; -+ -+ for (i = 0; i < n_log_entries; i++) { -+ void *levp = (void *)vchiq_debugfs_log_entries[i].plevel; -+ dir = debugfs_create_file(vchiq_debugfs_log_entries[i].name, -+ 0644, -+ debugfs_info.log_categories, -+ levp, -+ &debugfs_log_fops); -+ if (!dir) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ vchiq_debugfs_log_entries[i].dir = dir; -+ } -+ return ret; -+} -+ -+static int debugfs_usecount_show(struct seq_file *f, void *offset) -+{ -+ VCHIQ_INSTANCE_T instance = f->private; -+ int use_count; -+ -+ use_count = vchiq_instance_get_use_count(instance); -+ seq_printf(f, "%d\n", use_count); -+ -+ return 0; -+} -+ -+static int debugfs_usecount_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, debugfs_usecount_show, inode->i_private); -+} -+ -+static const struct file_operations debugfs_usecount_fops = { -+ .owner = THIS_MODULE, -+ .open = debugfs_usecount_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static int debugfs_trace_show(struct seq_file *f, void *offset) -+{ -+ VCHIQ_INSTANCE_T instance = f->private; -+ int trace; -+ -+ trace = vchiq_instance_get_trace(instance); -+ seq_printf(f, "%s\n", trace ? "Y" : "N"); -+ -+ return 0; -+} -+ -+static int debugfs_trace_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, debugfs_trace_show, inode->i_private); -+} -+ -+static int debugfs_trace_write(struct file *file, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct seq_file *f = (struct seq_file *)file->private_data; -+ VCHIQ_INSTANCE_T instance = f->private; -+ char firstchar; -+ -+ if (copy_from_user(&firstchar, buffer, 1) != 0) -+ return -EFAULT; -+ -+ switch (firstchar) { -+ case 'Y': -+ case 'y': -+ case '1': -+ vchiq_instance_set_trace(instance, 1); -+ break; -+ case 'N': -+ case 'n': -+ case '0': -+ vchiq_instance_set_trace(instance, 0); -+ break; -+ default: -+ break; -+ } -+ -+ *ppos += count; -+ -+ return count; -+} -+ -+static const struct file_operations debugfs_trace_fops = { -+ .owner = THIS_MODULE, -+ .open = debugfs_trace_open, -+ .write = debugfs_trace_write, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+/* add an instance (process) to the debugfs entries */ -+int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) -+{ -+ char pidstr[16]; -+ struct dentry *top, *use_count, *trace; -+ struct dentry *clients = vchiq_clients_top(); -+ -+ snprintf(pidstr, sizeof(pidstr), "%d", -+ vchiq_instance_get_pid(instance)); -+ -+ top = debugfs_create_dir(pidstr, clients); -+ if (!top) -+ goto fail_top; -+ -+ use_count = debugfs_create_file("use_count", -+ 0444, top, -+ instance, -+ &debugfs_usecount_fops); -+ if (!use_count) -+ goto fail_use_count; -+ -+ trace = debugfs_create_file("trace", -+ 0644, top, -+ instance, -+ &debugfs_trace_fops); -+ if (!trace) -+ goto fail_trace; -+ -+ vchiq_instance_get_debugfs_node(instance)->dentry = top; -+ -+ return 0; -+ -+fail_trace: -+ debugfs_remove(use_count); -+fail_use_count: -+ debugfs_remove(top); -+fail_top: -+ return -ENOMEM; -+} -+ -+void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_DEBUGFS_NODE_T *node = vchiq_instance_get_debugfs_node(instance); -+ debugfs_remove_recursive(node->dentry); -+} -+ -+ -+int vchiq_debugfs_init(void) -+{ -+ BUG_ON(debugfs_info.vchiq_cfg_dir != NULL); -+ -+ debugfs_info.vchiq_cfg_dir = debugfs_create_dir("vchiq", NULL); -+ if (debugfs_info.vchiq_cfg_dir == NULL) -+ goto fail; -+ -+ debugfs_info.clients = debugfs_create_dir("clients", -+ vchiq_debugfs_top()); -+ if (!debugfs_info.clients) -+ goto fail; -+ -+ if (vchiq_debugfs_create_log_entries(vchiq_debugfs_top()) != 0) -+ goto fail; -+ -+ return 0; -+ -+fail: -+ vchiq_debugfs_deinit(); -+ vchiq_log_error(vchiq_arm_log_level, -+ "%s: failed to create debugfs directory", -+ __func__); -+ -+ return -ENOMEM; -+} -+ -+/* remove all the debugfs entries */ -+void vchiq_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vchiq_debugfs_top()); -+} -+ -+static struct dentry *vchiq_clients_top(void) -+{ -+ return debugfs_info.clients; -+} -+ -+static struct dentry *vchiq_debugfs_top(void) -+{ -+ BUG_ON(debugfs_info.vchiq_cfg_dir == NULL); -+ return debugfs_info.vchiq_cfg_dir; -+} -+ -+#else /* CONFIG_DEBUG_FS */ -+ -+int vchiq_debugfs_init(void) -+{ -+ return 0; -+} -+ -+void vchiq_debugfs_deinit(void) -+{ -+} -+ -+int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) -+{ -+ return 0; -+} -+ -+void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) -+{ -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4d6a3788e9c508c9eb1379980c4f3a67791e428e ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h -@@ -0,0 +1,52 @@ -+/** -+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_DEBUGFS_H -+#define VCHIQ_DEBUGFS_H -+ -+#include "vchiq_core.h" -+ -+typedef struct vchiq_debugfs_node_struct -+{ -+ struct dentry *dentry; -+} VCHIQ_DEBUGFS_NODE_T; -+ -+int vchiq_debugfs_init(void); -+ -+void vchiq_debugfs_deinit(void); -+ -+int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance); -+ -+void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance); -+ -+#endif /* VCHIQ_DEBUGFS_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion -new file mode 100644 -index 0000000000000000000000000000000000000000..9f5b6344b9b77f72ebd4ff6621c90fd0ac47efb1 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion -@@ -0,0 +1,87 @@ -+#!/usr/bin/perl -w -+ -+use strict; -+ -+# -+# Generate a version from available information -+# -+ -+my $prefix = shift @ARGV; -+my $root = shift @ARGV; -+ -+ -+if ( not defined $root ) { -+ die "usage: $0 prefix root-dir\n"; -+} -+ -+if ( ! -d $root ) { -+ die "root directory $root not found\n"; -+} -+ -+my $version = "unknown"; -+my $tainted = ""; -+ -+if ( -d "$root/.git" ) { -+ # attempt to work out git version. only do so -+ # on a linux build host, as cygwin builds are -+ # already slow enough -+ -+ if ( -f "/usr/bin/git" || -f "/usr/local/bin/git" ) { -+ if (not open(F, "git --git-dir $root/.git rev-parse --verify HEAD|")) { -+ $version = "no git version"; -+ } -+ else { -+ $version = ; -+ $version =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). -+ $version =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). -+ } -+ -+ if (open(G, "git --git-dir $root/.git status --porcelain|")) { -+ $tainted = ; -+ $tainted =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). -+ $tainted =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). -+ if (length $tainted) { -+ $version = join ' ', $version, "(tainted)"; -+ } -+ else { -+ $version = join ' ', $version, "(clean)"; -+ } -+ } -+ } -+} -+ -+my $hostname = `hostname`; -+$hostname =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). -+$hostname =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). -+ -+ -+print STDERR "Version $version\n"; -+print < -+ -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_hostname, "$hostname" ); -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_version, "$version" ); -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_time, __TIME__ ); -+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_date, __DATE__ ); -+ -+const char *vchiq_get_build_hostname( void ) -+{ -+ return vchiq_build_hostname; -+} -+ -+const char *vchiq_get_build_version( void ) -+{ -+ return vchiq_build_version; -+} -+ -+const char *vchiq_get_build_date( void ) -+{ -+ return vchiq_build_date; -+} -+ -+const char *vchiq_get_build_time( void ) -+{ -+ return vchiq_build_time; -+} -+EOF -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h -new file mode 100644 -index 0000000000000000000000000000000000000000..8067bbe7ce8d70c41b2e6e0466d20a4612e39d93 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h -@@ -0,0 +1,189 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_IF_H -+#define VCHIQ_IF_H -+ -+#include "interface/vchi/vchi_mh.h" -+ -+#define VCHIQ_SERVICE_HANDLE_INVALID 0 -+ -+#define VCHIQ_SLOT_SIZE 4096 -+#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T)) -+#define VCHIQ_CHANNEL_SIZE VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */ -+ -+#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ -+ (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) -+#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service) -+#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service) -+ -+typedef enum { -+ VCHIQ_SERVICE_OPENED, /* service, -, - */ -+ VCHIQ_SERVICE_CLOSED, /* service, -, - */ -+ VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */ -+ VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */ -+ VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */ -+ VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */ -+ VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */ -+} VCHIQ_REASON_T; -+ -+typedef enum { -+ VCHIQ_ERROR = -1, -+ VCHIQ_SUCCESS = 0, -+ VCHIQ_RETRY = 1 -+} VCHIQ_STATUS_T; -+ -+typedef enum { -+ VCHIQ_BULK_MODE_CALLBACK, -+ VCHIQ_BULK_MODE_BLOCKING, -+ VCHIQ_BULK_MODE_NOCALLBACK, -+ VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */ -+} VCHIQ_BULK_MODE_T; -+ -+typedef enum { -+ VCHIQ_SERVICE_OPTION_AUTOCLOSE, -+ VCHIQ_SERVICE_OPTION_SLOT_QUOTA, -+ VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, -+ VCHIQ_SERVICE_OPTION_SYNCHRONOUS, -+ VCHIQ_SERVICE_OPTION_TRACE -+} VCHIQ_SERVICE_OPTION_T; -+ -+typedef struct vchiq_header_struct { -+ /* The message identifier - opaque to applications. */ -+ int msgid; -+ -+ /* Size of message data. */ -+ unsigned int size; -+ -+ char data[0]; /* message */ -+} VCHIQ_HEADER_T; -+ -+typedef struct { -+ const void *data; -+ unsigned int size; -+} VCHIQ_ELEMENT_T; -+ -+typedef unsigned int VCHIQ_SERVICE_HANDLE_T; -+ -+typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *, -+ VCHIQ_SERVICE_HANDLE_T, void *); -+ -+typedef struct vchiq_service_base_struct { -+ int fourcc; -+ VCHIQ_CALLBACK_T callback; -+ void *userdata; -+} VCHIQ_SERVICE_BASE_T; -+ -+typedef struct vchiq_service_params_struct { -+ int fourcc; -+ VCHIQ_CALLBACK_T callback; -+ void *userdata; -+ short version; /* Increment for non-trivial changes */ -+ short version_min; /* Update for incompatible changes */ -+} VCHIQ_SERVICE_PARAMS_T; -+ -+typedef struct vchiq_config_struct { -+ unsigned int max_msg_size; -+ unsigned int bulk_threshold; /* The message size above which it -+ is better to use a bulk transfer -+ (<= max_msg_size) */ -+ unsigned int max_outstanding_bulks; -+ unsigned int max_services; -+ short version; /* The version of VCHIQ */ -+ short version_min; /* The minimum compatible version of VCHIQ */ -+} VCHIQ_CONFIG_T; -+ -+typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T; -+typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg); -+ -+extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance); -+extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance); -+extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance); -+extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *pservice); -+extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *pservice); -+extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_use_service_no_resume( -+ VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service); -+ -+extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service, -+ const VCHIQ_ELEMENT_T *elements, unsigned int count); -+extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service, -+ VCHIQ_HEADER_T *header); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, -+ const void *data, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, -+ void *data, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit_handle( -+ VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, -+ const void *offset, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive_handle( -+ VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, -+ void *offset, unsigned int size, void *userdata); -+extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, -+ const void *data, unsigned int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode); -+extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, -+ void *data, unsigned int size, void *userdata, -+ VCHIQ_BULK_MODE_T mode); -+extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service, -+ VCHI_MEM_HANDLE_T handle, const void *offset, unsigned int size, -+ void *userdata, VCHIQ_BULK_MODE_T mode); -+extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service, -+ VCHI_MEM_HANDLE_T handle, void *offset, unsigned int size, -+ void *userdata, VCHIQ_BULK_MODE_T mode); -+extern int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service); -+extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service); -+extern int vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T service); -+extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance, -+ int config_size, VCHIQ_CONFIG_T *pconfig); -+extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service, -+ VCHIQ_SERVICE_OPTION_T option, int value); -+ -+extern VCHIQ_STATUS_T vchiq_remote_use(VCHIQ_INSTANCE_T instance, -+ VCHIQ_REMOTE_USE_CALLBACK_T callback, void *cb_arg); -+extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance); -+ -+extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service, -+ void *ptr, size_t num_bytes); -+ -+extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, -+ short *peer_version); -+ -+#endif /* VCHIQ_IF_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h -new file mode 100644 -index 0000000000000000000000000000000000000000..6137ae9de1c19cb0ffc486dc60505061a10aea6c ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h -@@ -0,0 +1,131 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_IOCTLS_H -+#define VCHIQ_IOCTLS_H -+ -+#include -+#include "vchiq_if.h" -+ -+#define VCHIQ_IOC_MAGIC 0xc4 -+#define VCHIQ_INVALID_HANDLE (~0) -+ -+typedef struct { -+ VCHIQ_SERVICE_PARAMS_T params; -+ int is_open; -+ int is_vchi; -+ unsigned int handle; /* OUT */ -+} VCHIQ_CREATE_SERVICE_T; -+ -+typedef struct { -+ unsigned int handle; -+ unsigned int count; -+ const VCHIQ_ELEMENT_T *elements; -+} VCHIQ_QUEUE_MESSAGE_T; -+ -+typedef struct { -+ unsigned int handle; -+ void *data; -+ unsigned int size; -+ void *userdata; -+ VCHIQ_BULK_MODE_T mode; -+} VCHIQ_QUEUE_BULK_TRANSFER_T; -+ -+typedef struct { -+ VCHIQ_REASON_T reason; -+ VCHIQ_HEADER_T *header; -+ void *service_userdata; -+ void *bulk_userdata; -+} VCHIQ_COMPLETION_DATA_T; -+ -+typedef struct { -+ unsigned int count; -+ VCHIQ_COMPLETION_DATA_T *buf; -+ unsigned int msgbufsize; -+ unsigned int msgbufcount; /* IN/OUT */ -+ void **msgbufs; -+} VCHIQ_AWAIT_COMPLETION_T; -+ -+typedef struct { -+ unsigned int handle; -+ int blocking; -+ unsigned int bufsize; -+ void *buf; -+} VCHIQ_DEQUEUE_MESSAGE_T; -+ -+typedef struct { -+ unsigned int config_size; -+ VCHIQ_CONFIG_T *pconfig; -+} VCHIQ_GET_CONFIG_T; -+ -+typedef struct { -+ unsigned int handle; -+ VCHIQ_SERVICE_OPTION_T option; -+ int value; -+} VCHIQ_SET_SERVICE_OPTION_T; -+ -+typedef struct { -+ void *virt_addr; -+ size_t num_bytes; -+} VCHIQ_DUMP_MEM_T; -+ -+#define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0) -+#define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1) -+#define VCHIQ_IOC_CREATE_SERVICE \ -+ _IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T) -+#define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3) -+#define VCHIQ_IOC_QUEUE_MESSAGE \ -+ _IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T) -+#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \ -+ _IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T) -+#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \ -+ _IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T) -+#define VCHIQ_IOC_AWAIT_COMPLETION \ -+ _IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T) -+#define VCHIQ_IOC_DEQUEUE_MESSAGE \ -+ _IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T) -+#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9) -+#define VCHIQ_IOC_GET_CONFIG \ -+ _IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T) -+#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11) -+#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12) -+#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13) -+#define VCHIQ_IOC_SET_SERVICE_OPTION \ -+ _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T) -+#define VCHIQ_IOC_DUMP_PHYS_MEM \ -+ _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T) -+#define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16) -+#define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17) -+#define VCHIQ_IOC_MAX 17 -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c -new file mode 100644 -index 0000000000000000000000000000000000000000..25e7011edc5094372919d7e3be482f3bbd7b6155 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c -@@ -0,0 +1,458 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+ -+#include -+#include -+#include -+ -+#include "vchiq_core.h" -+#include "vchiq_arm.h" -+#include "vchiq_killable.h" -+ -+/* ---- Public Variables ------------------------------------------------- */ -+ -+/* ---- Private Constants and Types -------------------------------------- */ -+ -+struct bulk_waiter_node { -+ struct bulk_waiter bulk_waiter; -+ int pid; -+ struct list_head list; -+}; -+ -+struct vchiq_instance_struct { -+ VCHIQ_STATE_T *state; -+ -+ int connected; -+ -+ struct list_head bulk_waiter_list; -+ struct mutex bulk_waiter_list_mutex; -+}; -+ -+static VCHIQ_STATUS_T -+vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, VCHIQ_BULK_DIR_T dir); -+ -+/**************************************************************************** -+* -+* vchiq_initialise -+* -+***************************************************************************/ -+#define VCHIQ_INIT_RETRIES 10 -+VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_STATE_T *state; -+ VCHIQ_INSTANCE_T instance = NULL; -+ int i; -+ -+ vchiq_log_trace(vchiq_core_log_level, "%s called", __func__); -+ -+ /* VideoCore may not be ready due to boot up timing. -+ It may never be ready if kernel and firmware are mismatched, so don't block forever. */ -+ for (i=0; i0) { -+ vchiq_log_warning(vchiq_core_log_level, -+ "%s: videocore initialized after %d retries\n", __func__, i); -+ } -+ -+ instance = kzalloc(sizeof(*instance), GFP_KERNEL); -+ if (!instance) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%s: error allocating vchiq instance\n", __func__); -+ goto failed; -+ } -+ -+ instance->connected = 0; -+ instance->state = state; -+ mutex_init(&instance->bulk_waiter_list_mutex); -+ INIT_LIST_HEAD(&instance->bulk_waiter_list); -+ -+ *instanceOut = instance; -+ -+ status = VCHIQ_SUCCESS; -+ -+failed: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_initialise); -+ -+/**************************************************************************** -+* -+* vchiq_shutdown -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_STATUS_T status; -+ VCHIQ_STATE_T *state = instance->state; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ if (mutex_lock_interruptible(&state->mutex) != 0) -+ return VCHIQ_RETRY; -+ -+ /* Remove all services */ -+ status = vchiq_shutdown_internal(state, instance); -+ -+ mutex_unlock(&state->mutex); -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ if (status == VCHIQ_SUCCESS) { -+ struct list_head *pos, *next; -+ list_for_each_safe(pos, next, -+ &instance->bulk_waiter_list) { -+ struct bulk_waiter_node *waiter; -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ vchiq_log_info(vchiq_arm_log_level, -+ "bulk_waiter - cleaned up %x " -+ "for pid %d", -+ (unsigned int)waiter, waiter->pid); -+ kfree(waiter); -+ } -+ kfree(instance); -+ } -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_shutdown); -+ -+/**************************************************************************** -+* -+* vchiq_is_connected -+* -+***************************************************************************/ -+ -+int vchiq_is_connected(VCHIQ_INSTANCE_T instance) -+{ -+ return instance->connected; -+} -+ -+/**************************************************************************** -+* -+* vchiq_connect -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance) -+{ -+ VCHIQ_STATUS_T status; -+ VCHIQ_STATE_T *state = instance->state; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ if (mutex_lock_interruptible(&state->mutex) != 0) { -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s: call to mutex_lock failed", __func__); -+ status = VCHIQ_RETRY; -+ goto failed; -+ } -+ status = vchiq_connect_internal(state, instance); -+ -+ if (status == VCHIQ_SUCCESS) -+ instance->connected = 1; -+ -+ mutex_unlock(&state->mutex); -+ -+failed: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_connect); -+ -+/**************************************************************************** -+* -+* vchiq_add_service -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_add_service( -+ VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *phandle) -+{ -+ VCHIQ_STATUS_T status; -+ VCHIQ_STATE_T *state = instance->state; -+ VCHIQ_SERVICE_T *service = NULL; -+ int srvstate; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ *phandle = VCHIQ_SERVICE_HANDLE_INVALID; -+ -+ srvstate = vchiq_is_connected(instance) -+ ? VCHIQ_SRVSTATE_LISTENING -+ : VCHIQ_SRVSTATE_HIDDEN; -+ -+ service = vchiq_add_service_internal( -+ state, -+ params, -+ srvstate, -+ instance, -+ NULL); -+ -+ if (service) { -+ *phandle = service->handle; -+ status = VCHIQ_SUCCESS; -+ } else -+ status = VCHIQ_ERROR; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_add_service); -+ -+/**************************************************************************** -+* -+* vchiq_open_service -+* -+***************************************************************************/ -+ -+VCHIQ_STATUS_T vchiq_open_service( -+ VCHIQ_INSTANCE_T instance, -+ const VCHIQ_SERVICE_PARAMS_T *params, -+ VCHIQ_SERVICE_HANDLE_T *phandle) -+{ -+ VCHIQ_STATUS_T status = VCHIQ_ERROR; -+ VCHIQ_STATE_T *state = instance->state; -+ VCHIQ_SERVICE_T *service = NULL; -+ -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p) called", __func__, instance); -+ -+ *phandle = VCHIQ_SERVICE_HANDLE_INVALID; -+ -+ if (!vchiq_is_connected(instance)) -+ goto failed; -+ -+ service = vchiq_add_service_internal(state, -+ params, -+ VCHIQ_SRVSTATE_OPENING, -+ instance, -+ NULL); -+ -+ if (service) { -+ *phandle = service->handle; -+ status = vchiq_open_service_internal(service, current->pid); -+ if (status != VCHIQ_SUCCESS) { -+ vchiq_remove_service(service->handle); -+ *phandle = VCHIQ_SERVICE_HANDLE_INVALID; -+ } -+ } -+ -+failed: -+ vchiq_log_trace(vchiq_core_log_level, -+ "%s(%p): returning %d", __func__, instance, status); -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_open_service); -+ -+VCHIQ_STATUS_T -+vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, -+ const void *data, unsigned int size, void *userdata) -+{ -+ return vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, -+ VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT); -+} -+EXPORT_SYMBOL(vchiq_queue_bulk_transmit); -+ -+VCHIQ_STATUS_T -+vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, void *userdata) -+{ -+ return vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, data, size, userdata, -+ VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE); -+} -+EXPORT_SYMBOL(vchiq_queue_bulk_receive); -+ -+VCHIQ_STATUS_T -+vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data, -+ unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) -+{ -+ VCHIQ_STATUS_T status; -+ -+ switch (mode) { -+ case VCHIQ_BULK_MODE_NOCALLBACK: -+ case VCHIQ_BULK_MODE_CALLBACK: -+ status = vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, -+ mode, VCHIQ_BULK_TRANSMIT); -+ break; -+ case VCHIQ_BULK_MODE_BLOCKING: -+ status = vchiq_blocking_bulk_transfer(handle, -+ (void *)data, size, VCHIQ_BULK_TRANSMIT); -+ break; -+ default: -+ return VCHIQ_ERROR; -+ } -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_bulk_transmit); -+ -+VCHIQ_STATUS_T -+vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) -+{ -+ VCHIQ_STATUS_T status; -+ -+ switch (mode) { -+ case VCHIQ_BULK_MODE_NOCALLBACK: -+ case VCHIQ_BULK_MODE_CALLBACK: -+ status = vchiq_bulk_transfer(handle, -+ VCHI_MEM_HANDLE_INVALID, data, size, userdata, -+ mode, VCHIQ_BULK_RECEIVE); -+ break; -+ case VCHIQ_BULK_MODE_BLOCKING: -+ status = vchiq_blocking_bulk_transfer(handle, -+ (void *)data, size, VCHIQ_BULK_RECEIVE); -+ break; -+ default: -+ return VCHIQ_ERROR; -+ } -+ -+ return status; -+} -+EXPORT_SYMBOL(vchiq_bulk_receive); -+ -+static VCHIQ_STATUS_T -+vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, -+ unsigned int size, VCHIQ_BULK_DIR_T dir) -+{ -+ VCHIQ_INSTANCE_T instance; -+ VCHIQ_SERVICE_T *service; -+ VCHIQ_STATUS_T status; -+ struct bulk_waiter_node *waiter = NULL; -+ struct list_head *pos; -+ -+ service = find_service_by_handle(handle); -+ if (!service) -+ return VCHIQ_ERROR; -+ -+ instance = service->instance; -+ -+ unlock_service(service); -+ -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_for_each(pos, &instance->bulk_waiter_list) { -+ if (list_entry(pos, struct bulk_waiter_node, -+ list)->pid == current->pid) { -+ waiter = list_entry(pos, -+ struct bulk_waiter_node, -+ list); -+ list_del(pos); -+ break; -+ } -+ } -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ -+ if (waiter) { -+ VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; -+ if (bulk) { -+ /* This thread has an outstanding bulk transfer. */ -+ if ((bulk->data != data) || -+ (bulk->size != size)) { -+ /* This is not a retry of the previous one. -+ ** Cancel the signal when the transfer -+ ** completes. */ -+ spin_lock(&bulk_waiter_spinlock); -+ bulk->userdata = NULL; -+ spin_unlock(&bulk_waiter_spinlock); -+ } -+ } -+ } -+ -+ if (!waiter) { -+ waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL); -+ if (!waiter) { -+ vchiq_log_error(vchiq_core_log_level, -+ "%s - out of memory", __func__); -+ return VCHIQ_ERROR; -+ } -+ } -+ -+ status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID, -+ data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING, -+ dir); -+ if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || -+ !waiter->bulk_waiter.bulk) { -+ VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; -+ if (bulk) { -+ /* Cancel the signal when the transfer -+ ** completes. */ -+ spin_lock(&bulk_waiter_spinlock); -+ bulk->userdata = NULL; -+ spin_unlock(&bulk_waiter_spinlock); -+ } -+ kfree(waiter); -+ } else { -+ waiter->pid = current->pid; -+ mutex_lock(&instance->bulk_waiter_list_mutex); -+ list_add(&waiter->list, &instance->bulk_waiter_list); -+ mutex_unlock(&instance->bulk_waiter_list_mutex); -+ vchiq_log_info(vchiq_arm_log_level, -+ "saved bulk_waiter %x for pid %d", -+ (unsigned int)waiter, current->pid); -+ } -+ -+ return status; -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h -new file mode 100644 -index 0000000000000000000000000000000000000000..335446e05476c3dbb905a69e45b37a2702566bf6 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h -@@ -0,0 +1,69 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_KILLABLE_H -+#define VCHIQ_KILLABLE_H -+ -+#include -+#include -+ -+#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTRAP) | sigmask(SIGSTOP) | sigmask(SIGCONT)) -+ -+static inline int __must_check down_interruptible_killable(struct semaphore *sem) -+{ -+ /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ -+ int ret; -+ sigset_t blocked, oldset; -+ siginitsetinv(&blocked, SHUTDOWN_SIGS); -+ sigprocmask(SIG_SETMASK, &blocked, &oldset); -+ ret = down_interruptible(sem); -+ sigprocmask(SIG_SETMASK, &oldset, NULL); -+ return ret; -+} -+#define down_interruptible down_interruptible_killable -+ -+ -+static inline int __must_check mutex_lock_interruptible_killable(struct mutex *lock) -+{ -+ /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ -+ int ret; -+ sigset_t blocked, oldset; -+ siginitsetinv(&blocked, SHUTDOWN_SIGS); -+ sigprocmask(SIG_SETMASK, &blocked, &oldset); -+ ret = mutex_lock_interruptible(lock); -+ sigprocmask(SIG_SETMASK, &oldset, NULL); -+ return ret; -+} -+#define mutex_lock_interruptible mutex_lock_interruptible_killable -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h -new file mode 100644 -index 0000000000000000000000000000000000000000..d02e7764bd0d8721453d2e0a4900c26c12634c8b ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h -@@ -0,0 +1,71 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_MEMDRV_H -+#define VCHIQ_MEMDRV_H -+ -+/* ---- Include Files ----------------------------------------------------- */ -+ -+#include -+#include "vchiq_if.h" -+ -+/* ---- Constants and Types ---------------------------------------------- */ -+ -+typedef struct { -+ void *armSharedMemVirt; -+ dma_addr_t armSharedMemPhys; -+ size_t armSharedMemSize; -+ -+ void *vcSharedMemVirt; -+ dma_addr_t vcSharedMemPhys; -+ size_t vcSharedMemSize; -+} VCHIQ_SHARED_MEM_INFO_T; -+ -+/* ---- Variable Externs ------------------------------------------------- */ -+ -+/* ---- Function Prototypes ---------------------------------------------- */ -+ -+void vchiq_get_shared_mem_info(VCHIQ_SHARED_MEM_INFO_T *info); -+ -+VCHIQ_STATUS_T vchiq_memdrv_initialise(void); -+ -+VCHIQ_STATUS_T vchiq_userdrv_create_instance( -+ const VCHIQ_PLATFORM_DATA_T * platform_data); -+ -+VCHIQ_STATUS_T vchiq_userdrv_suspend( -+ const VCHIQ_PLATFORM_DATA_T * platform_data); -+ -+VCHIQ_STATUS_T vchiq_userdrv_resume( -+ const VCHIQ_PLATFORM_DATA_T * platform_data); -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h -new file mode 100644 -index 0000000000000000000000000000000000000000..54a3ecec69ef6702c382a7af339d21b87ec8a346 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h -@@ -0,0 +1,58 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_PAGELIST_H -+#define VCHIQ_PAGELIST_H -+ -+#ifndef PAGE_SIZE -+#define PAGE_SIZE 4096 -+#endif -+#define CACHE_LINE_SIZE 32 -+#define PAGELIST_WRITE 0 -+#define PAGELIST_READ 1 -+#define PAGELIST_READ_WITH_FRAGMENTS 2 -+ -+typedef struct pagelist_struct { -+ unsigned long length; -+ unsigned short type; -+ unsigned short offset; -+ unsigned long addrs[1]; /* N.B. 12 LSBs hold the number of following -+ pages at consecutive addresses. */ -+} PAGELIST_T; -+ -+typedef struct fragments_struct { -+ char headbuf[CACHE_LINE_SIZE]; -+ char tailbuf[CACHE_LINE_SIZE]; -+} FRAGMENTS_T; -+ -+#endif /* VCHIQ_PAGELIST_H */ -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c -new file mode 100644 -index 0000000000000000000000000000000000000000..8072ff613636121d50293693d0bd2aaf0b6e07b5 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c -@@ -0,0 +1,860 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+#include -+#include -+ -+#include "interface/vchi/vchi.h" -+#include "vchiq.h" -+#include "vchiq_core.h" -+ -+#include "vchiq_util.h" -+ -+#include -+ -+#define vchiq_status_to_vchi(status) ((int32_t)status) -+ -+typedef struct { -+ VCHIQ_SERVICE_HANDLE_T handle; -+ -+ VCHIU_QUEUE_T queue; -+ -+ VCHI_CALLBACK_T callback; -+ void *callback_param; -+} SHIM_SERVICE_T; -+ -+/* ---------------------------------------------------------------------- -+ * return pointer to the mphi message driver function table -+ * -------------------------------------------------------------------- */ -+const VCHI_MESSAGE_DRIVER_T * -+vchi_mphi_message_driver_func_table(void) -+{ -+ return NULL; -+} -+ -+/* ---------------------------------------------------------------------- -+ * return a pointer to the 'single' connection driver fops -+ * -------------------------------------------------------------------- */ -+const VCHI_CONNECTION_API_T * -+single_get_func_table(void) -+{ -+ return NULL; -+} -+ -+VCHI_CONNECTION_T *vchi_create_connection( -+ const VCHI_CONNECTION_API_T *function_table, -+ const VCHI_MESSAGE_DRIVER_T *low_level) -+{ -+ (void)function_table; -+ (void)low_level; -+ return NULL; -+} -+ -+/*********************************************************** -+ * Name: vchi_msg_peek -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle, -+ * void **data, -+ * uint32_t *msg_size, -+ -+ -+ * VCHI_FLAGS_T flags -+ * -+ * Description: Routine to return a pointer to the current message (to allow in -+ * place processing). The message can be removed using -+ * vchi_msg_remove when you're finished -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ WARN_ON((flags != VCHI_FLAGS_NONE) && -+ (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); -+ -+ if (flags == VCHI_FLAGS_NONE) -+ if (vchiu_queue_is_empty(&service->queue)) -+ return -1; -+ -+ header = vchiu_queue_peek(&service->queue); -+ -+ *data = header->data; -+ *msg_size = header->size; -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_peek); -+ -+/*********************************************************** -+ * Name: vchi_msg_remove -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle, -+ * -+ * Description: Routine to remove a message (after it has been read with -+ * vchi_msg_peek) -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ header = vchiu_queue_pop(&service->queue); -+ -+ vchiq_release_message(service->handle, header); -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_remove); -+ -+/*********************************************************** -+ * Name: vchi_msg_queue -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * const void *data, -+ * uint32_t data_size, -+ * VCHI_FLAGS_T flags, -+ * void *msg_handle, -+ * -+ * Description: Thin wrapper to queue a message onto a connection -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_ELEMENT_T element = {data, data_size}; -+ VCHIQ_STATUS_T status; -+ -+ (void)msg_handle; -+ -+ WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); -+ -+ status = vchiq_queue_message(service->handle, &element, 1); -+ -+ /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to -+ ** implement a retry mechanism since this function is supposed -+ ** to block until queued -+ */ -+ while (status == VCHIQ_RETRY) { -+ msleep(1); -+ status = vchiq_queue_message(service->handle, &element, 1); -+ } -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_msg_queue); -+ -+/*********************************************************** -+ * Name: vchi_bulk_queue_receive -+ * -+ * Arguments: VCHI_BULK_HANDLE_T handle, -+ * void *data_dst, -+ * const uint32_t data_size, -+ * VCHI_FLAGS_T flags -+ * void *bulk_handle -+ * -+ * Description: Routine to setup a rcv buffer -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, -+ void *data_dst, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_BULK_MODE_T mode; -+ VCHIQ_STATUS_T status; -+ -+ switch ((int)flags) { -+ case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE -+ | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ WARN_ON(!service->callback); -+ mode = VCHIQ_BULK_MODE_CALLBACK; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: -+ mode = VCHIQ_BULK_MODE_BLOCKING; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ case VCHI_FLAGS_NONE: -+ mode = VCHIQ_BULK_MODE_NOCALLBACK; -+ break; -+ default: -+ WARN(1, "unsupported message\n"); -+ return vchiq_status_to_vchi(VCHIQ_ERROR); -+ } -+ -+ status = vchiq_bulk_receive(service->handle, data_dst, data_size, -+ bulk_handle, mode); -+ -+ /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to -+ ** implement a retry mechanism since this function is supposed -+ ** to block until queued -+ */ -+ while (status == VCHIQ_RETRY) { -+ msleep(1); -+ status = vchiq_bulk_receive(service->handle, data_dst, -+ data_size, bulk_handle, mode); -+ } -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_bulk_queue_receive); -+ -+/*********************************************************** -+ * Name: vchi_bulk_queue_transmit -+ * -+ * Arguments: VCHI_BULK_HANDLE_T handle, -+ * const void *data_src, -+ * uint32_t data_size, -+ * VCHI_FLAGS_T flags, -+ * void *bulk_handle -+ * -+ * Description: Routine to transmit some data -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, -+ const void *data_src, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *bulk_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_BULK_MODE_T mode; -+ VCHIQ_STATUS_T status; -+ -+ switch ((int)flags) { -+ case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE -+ | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ WARN_ON(!service->callback); -+ mode = VCHIQ_BULK_MODE_CALLBACK; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: -+ case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: -+ mode = VCHIQ_BULK_MODE_BLOCKING; -+ break; -+ case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: -+ case VCHI_FLAGS_NONE: -+ mode = VCHIQ_BULK_MODE_NOCALLBACK; -+ break; -+ default: -+ WARN(1, "unsupported message\n"); -+ return vchiq_status_to_vchi(VCHIQ_ERROR); -+ } -+ -+ status = vchiq_bulk_transmit(service->handle, data_src, data_size, -+ bulk_handle, mode); -+ -+ /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to -+ ** implement a retry mechanism since this function is supposed -+ ** to block until queued -+ */ -+ while (status == VCHIQ_RETRY) { -+ msleep(1); -+ status = vchiq_bulk_transmit(service->handle, data_src, -+ data_size, bulk_handle, mode); -+ } -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_bulk_queue_transmit); -+ -+/*********************************************************** -+ * Name: vchi_msg_dequeue -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * void *data, -+ * uint32_t max_data_size_to_read, -+ * uint32_t *actual_msg_size -+ * VCHI_FLAGS_T flags -+ * -+ * Description: Routine to dequeue a message into the supplied buffer -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, -+ void *data, -+ uint32_t max_data_size_to_read, -+ uint32_t *actual_msg_size, -+ VCHI_FLAGS_T flags) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ WARN_ON((flags != VCHI_FLAGS_NONE) && -+ (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); -+ -+ if (flags == VCHI_FLAGS_NONE) -+ if (vchiu_queue_is_empty(&service->queue)) -+ return -1; -+ -+ header = vchiu_queue_pop(&service->queue); -+ -+ memcpy(data, header->data, header->size < max_data_size_to_read ? -+ header->size : max_data_size_to_read); -+ -+ *actual_msg_size = header->size; -+ -+ vchiq_release_message(service->handle, header); -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_dequeue); -+ -+/*********************************************************** -+ * Name: vchi_msg_queuev -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * VCHI_MSG_VECTOR_T *vector, -+ * uint32_t count, -+ * VCHI_FLAGS_T flags, -+ * void *msg_handle -+ * -+ * Description: Thin wrapper to queue a message onto a connection -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+ -+vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); -+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == -+ offsetof(VCHIQ_ELEMENT_T, data)); -+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == -+ offsetof(VCHIQ_ELEMENT_T, size)); -+ -+int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ -+ (void)msg_handle; -+ -+ WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); -+ -+ return vchiq_status_to_vchi(vchiq_queue_message(service->handle, -+ (const VCHIQ_ELEMENT_T *)vector, count)); -+} -+EXPORT_SYMBOL(vchi_msg_queuev); -+ -+/*********************************************************** -+ * Name: vchi_held_msg_release -+ * -+ * Arguments: VCHI_HELD_MSG_T *message -+ * -+ * Description: Routine to release a held message (after it has been read with -+ * vchi_msg_hold) -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) -+{ -+ vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, -+ (VCHIQ_HEADER_T *)message->message); -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_held_msg_release); -+ -+/*********************************************************** -+ * Name: vchi_msg_hold -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * void **data, -+ * uint32_t *msg_size, -+ * VCHI_FLAGS_T flags, -+ * VCHI_HELD_MSG_T *message_handle -+ * -+ * Description: Routine to return a pointer to the current message (to allow -+ * in place processing). The message is dequeued - don't forget -+ * to release the message using vchi_held_msg_release when you're -+ * finished. -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, -+ void **data, -+ uint32_t *msg_size, -+ VCHI_FLAGS_T flags, -+ VCHI_HELD_MSG_T *message_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_HEADER_T *header; -+ -+ WARN_ON((flags != VCHI_FLAGS_NONE) && -+ (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); -+ -+ if (flags == VCHI_FLAGS_NONE) -+ if (vchiu_queue_is_empty(&service->queue)) -+ return -1; -+ -+ header = vchiu_queue_pop(&service->queue); -+ -+ *data = header->data; -+ *msg_size = header->size; -+ -+ message_handle->service = -+ (struct opaque_vchi_service_t *)service->handle; -+ message_handle->message = header; -+ -+ return 0; -+} -+EXPORT_SYMBOL(vchi_msg_hold); -+ -+/*********************************************************** -+ * Name: vchi_initialise -+ * -+ * Arguments: VCHI_INSTANCE_T *instance_handle -+ * -+ * Description: Initialises the hardware but does not transmit anything -+ * When run as a Host App this will be called twice hence the need -+ * to malloc the state information -+ * -+ * Returns: 0 if successful, failure otherwise -+ * -+ ***********************************************************/ -+ -+int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle) -+{ -+ VCHIQ_INSTANCE_T instance; -+ VCHIQ_STATUS_T status; -+ -+ status = vchiq_initialise(&instance); -+ -+ *instance_handle = (VCHI_INSTANCE_T)instance; -+ -+ return vchiq_status_to_vchi(status); -+} -+EXPORT_SYMBOL(vchi_initialise); -+ -+/*********************************************************** -+ * Name: vchi_connect -+ * -+ * Arguments: VCHI_CONNECTION_T **connections -+ * const uint32_t num_connections -+ * VCHI_INSTANCE_T instance_handle) -+ * -+ * Description: Starts the command service on each connection, -+ * causing INIT messages to be pinged back and forth -+ * -+ * Returns: 0 if successful, failure otherwise -+ * -+ ***********************************************************/ -+int32_t vchi_connect(VCHI_CONNECTION_T **connections, -+ const uint32_t num_connections, -+ VCHI_INSTANCE_T instance_handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ -+ (void)connections; -+ (void)num_connections; -+ -+ return vchiq_connect(instance); -+} -+EXPORT_SYMBOL(vchi_connect); -+ -+ -+/*********************************************************** -+ * Name: vchi_disconnect -+ * -+ * Arguments: VCHI_INSTANCE_T instance_handle -+ * -+ * Description: Stops the command service on each connection, -+ * causing DE-INIT messages to be pinged back and forth -+ * -+ * Returns: 0 if successful, failure otherwise -+ * -+ ***********************************************************/ -+int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ return vchiq_status_to_vchi(vchiq_shutdown(instance)); -+} -+EXPORT_SYMBOL(vchi_disconnect); -+ -+ -+/*********************************************************** -+ * Name: vchi_service_open -+ * Name: vchi_service_create -+ * -+ * Arguments: VCHI_INSTANCE_T *instance_handle -+ * SERVICE_CREATION_T *setup, -+ * VCHI_SERVICE_HANDLE_T *handle -+ * -+ * Description: Routine to open a service -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+ -+static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) -+{ -+ SHIM_SERVICE_T *service = -+ (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle); -+ -+ if (!service->callback) -+ goto release; -+ -+ switch (reason) { -+ case VCHIQ_MESSAGE_AVAILABLE: -+ vchiu_queue_push(&service->queue, header); -+ -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_MSG_AVAILABLE, NULL); -+ -+ goto done; -+ break; -+ -+ case VCHIQ_BULK_TRANSMIT_DONE: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_SENT, bulk_user); -+ break; -+ -+ case VCHIQ_BULK_RECEIVE_DONE: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_RECEIVED, bulk_user); -+ break; -+ -+ case VCHIQ_SERVICE_CLOSED: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_SERVICE_CLOSED, NULL); -+ break; -+ -+ case VCHIQ_SERVICE_OPENED: -+ /* No equivalent VCHI reason */ -+ break; -+ -+ case VCHIQ_BULK_TRANSMIT_ABORTED: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, -+ bulk_user); -+ break; -+ -+ case VCHIQ_BULK_RECEIVE_ABORTED: -+ service->callback(service->callback_param, -+ VCHI_CALLBACK_BULK_RECEIVE_ABORTED, -+ bulk_user); -+ break; -+ -+ default: -+ WARN(1, "not supported\n"); -+ break; -+ } -+ -+release: -+ vchiq_release_message(service->handle, header); -+done: -+ return VCHIQ_SUCCESS; -+} -+ -+static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance, -+ SERVICE_CREATION_T *setup) -+{ -+ SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL); -+ -+ (void)instance; -+ -+ if (service) { -+ if (vchiu_queue_init(&service->queue, 64)) { -+ service->callback = setup->callback; -+ service->callback_param = setup->callback_param; -+ } else { -+ kfree(service); -+ service = NULL; -+ } -+ } -+ -+ return service; -+} -+ -+static void service_free(SHIM_SERVICE_T *service) -+{ -+ if (service) { -+ vchiu_queue_delete(&service->queue); -+ kfree(service); -+ } -+} -+ -+int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ SHIM_SERVICE_T *service = service_alloc(instance, setup); -+ -+ *handle = (VCHI_SERVICE_HANDLE_T)service; -+ -+ if (service) { -+ VCHIQ_SERVICE_PARAMS_T params; -+ VCHIQ_STATUS_T status; -+ -+ memset(¶ms, 0, sizeof(params)); -+ params.fourcc = setup->service_id; -+ params.callback = shim_callback; -+ params.userdata = service; -+ params.version = setup->version.version; -+ params.version_min = setup->version.version_min; -+ -+ status = vchiq_open_service(instance, ¶ms, -+ &service->handle); -+ if (status != VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ *handle = NULL; -+ } -+ } -+ -+ return (service != NULL) ? 0 : -1; -+} -+EXPORT_SYMBOL(vchi_service_open); -+ -+int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, -+ SERVICE_CREATION_T *setup, -+ VCHI_SERVICE_HANDLE_T *handle) -+{ -+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; -+ SHIM_SERVICE_T *service = service_alloc(instance, setup); -+ -+ *handle = (VCHI_SERVICE_HANDLE_T)service; -+ -+ if (service) { -+ VCHIQ_SERVICE_PARAMS_T params; -+ VCHIQ_STATUS_T status; -+ -+ memset(¶ms, 0, sizeof(params)); -+ params.fourcc = setup->service_id; -+ params.callback = shim_callback; -+ params.userdata = service; -+ params.version = setup->version.version; -+ params.version_min = setup->version.version_min; -+ status = vchiq_add_service(instance, ¶ms, &service->handle); -+ -+ if (status != VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ *handle = NULL; -+ } -+ } -+ -+ return (service != NULL) ? 0 : -1; -+} -+EXPORT_SYMBOL(vchi_service_create); -+ -+int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) { -+ VCHIQ_STATUS_T status = vchiq_close_service(service->handle); -+ if (status == VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ } -+ -+ ret = vchiq_status_to_vchi(status); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_close); -+ -+int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) { -+ VCHIQ_STATUS_T status = vchiq_remove_service(service->handle); -+ if (status == VCHIQ_SUCCESS) { -+ service_free(service); -+ service = NULL; -+ } -+ -+ ret = vchiq_status_to_vchi(status); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_destroy); -+ -+int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle, -+ VCHI_SERVICE_OPTION_T option, -+ int value) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_SERVICE_OPTION_T vchiq_option; -+ switch (option) { -+ case VCHI_SERVICE_OPTION_TRACE: -+ vchiq_option = VCHIQ_SERVICE_OPTION_TRACE; -+ break; -+ case VCHI_SERVICE_OPTION_SYNCHRONOUS: -+ vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS; -+ break; -+ default: -+ service = NULL; -+ break; -+ } -+ if (service) { -+ VCHIQ_STATUS_T status = -+ vchiq_set_service_option(service->handle, -+ vchiq_option, -+ value); -+ -+ ret = vchiq_status_to_vchi(status); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_set_option); -+ -+int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version ) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if(service) -+ { -+ VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version); -+ ret = vchiq_status_to_vchi( status ); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(vchi_get_peer_version); -+ -+/* ---------------------------------------------------------------------- -+ * read a uint32_t from buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+uint32_t -+vchi_readbuf_uint32(const void *_ptr) -+{ -+ const unsigned char *ptr = _ptr; -+ return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); -+} -+ -+/* ---------------------------------------------------------------------- -+ * write a uint32_t to buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+void -+vchi_writebuf_uint32(void *_ptr, uint32_t value) -+{ -+ unsigned char *ptr = _ptr; -+ ptr[0] = (unsigned char)((value >> 0) & 0xFF); -+ ptr[1] = (unsigned char)((value >> 8) & 0xFF); -+ ptr[2] = (unsigned char)((value >> 16) & 0xFF); -+ ptr[3] = (unsigned char)((value >> 24) & 0xFF); -+} -+ -+/* ---------------------------------------------------------------------- -+ * read a uint16_t from buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+uint16_t -+vchi_readbuf_uint16(const void *_ptr) -+{ -+ const unsigned char *ptr = _ptr; -+ return ptr[0] | (ptr[1] << 8); -+} -+ -+/* ---------------------------------------------------------------------- -+ * write a uint16_t into the buffer. -+ * network format is defined to be little endian -+ * -------------------------------------------------------------------- */ -+void -+vchi_writebuf_uint16(void *_ptr, uint16_t value) -+{ -+ unsigned char *ptr = _ptr; -+ ptr[0] = (value >> 0) & 0xFF; -+ ptr[1] = (value >> 8) & 0xFF; -+} -+ -+/*********************************************************** -+ * Name: vchi_service_use -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle -+ * -+ * Description: Routine to increment refcount on a service -+ * -+ * Returns: void -+ * -+ ***********************************************************/ -+int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) -+ ret = vchiq_status_to_vchi(vchiq_use_service(service->handle)); -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_use); -+ -+/*********************************************************** -+ * Name: vchi_service_release -+ * -+ * Arguments: const VCHI_SERVICE_HANDLE_T handle -+ * -+ * Description: Routine to decrement refcount on a service -+ * -+ * Returns: void -+ * -+ ***********************************************************/ -+int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle) -+{ -+ int32_t ret = -1; -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ if (service) -+ ret = vchiq_status_to_vchi( -+ vchiq_release_service(service->handle)); -+ return ret; -+} -+EXPORT_SYMBOL(vchi_service_release); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c -new file mode 100644 -index 0000000000000000000000000000000000000000..384acb8d2eae12eca8aa955c274467f120e8824f ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c -@@ -0,0 +1,156 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "vchiq_util.h" -+#include "vchiq_killable.h" -+ -+static inline int is_pow2(int i) -+{ -+ return i && !(i & (i - 1)); -+} -+ -+int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) -+{ -+ WARN_ON(!is_pow2(size)); -+ -+ queue->size = size; -+ queue->read = 0; -+ queue->write = 0; -+ queue->initialized = 1; -+ -+ sema_init(&queue->pop, 0); -+ sema_init(&queue->push, 0); -+ -+ queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL); -+ if (queue->storage == NULL) { -+ vchiu_queue_delete(queue); -+ return 0; -+ } -+ return 1; -+} -+ -+void vchiu_queue_delete(VCHIU_QUEUE_T *queue) -+{ -+ if (queue->storage != NULL) -+ kfree(queue->storage); -+} -+ -+int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue) -+{ -+ return queue->read == queue->write; -+} -+ -+int vchiu_queue_is_full(VCHIU_QUEUE_T *queue) -+{ -+ return queue->write == queue->read + queue->size; -+} -+ -+void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header) -+{ -+ if (!queue->initialized) -+ return; -+ -+ while (queue->write == queue->read + queue->size) { -+ if (down_interruptible(&queue->pop) != 0) { -+ flush_signals(current); -+ } -+ } -+ -+ /* -+ * Write to queue->storage must be visible after read from -+ * queue->read -+ */ -+ smp_mb(); -+ -+ queue->storage[queue->write & (queue->size - 1)] = header; -+ -+ /* -+ * Write to queue->storage must be visible before write to -+ * queue->write -+ */ -+ smp_wmb(); -+ -+ queue->write++; -+ -+ up(&queue->push); -+} -+ -+VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue) -+{ -+ while (queue->write == queue->read) { -+ if (down_interruptible(&queue->push) != 0) { -+ flush_signals(current); -+ } -+ } -+ -+ up(&queue->push); // We haven't removed anything from the queue. -+ -+ /* -+ * Read from queue->storage must be visible after read from -+ * queue->write -+ */ -+ smp_rmb(); -+ -+ return queue->storage[queue->read & (queue->size - 1)]; -+} -+ -+VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue) -+{ -+ VCHIQ_HEADER_T *header; -+ -+ while (queue->write == queue->read) { -+ if (down_interruptible(&queue->push) != 0) { -+ flush_signals(current); -+ } -+ } -+ -+ /* -+ * Read from queue->storage must be visible after read from -+ * queue->write -+ */ -+ smp_rmb(); -+ -+ header = queue->storage[queue->read & (queue->size - 1)]; -+ -+ /* -+ * Read from queue->storage must be visible before write to -+ * queue->read -+ */ -+ smp_mb(); -+ -+ queue->read++; -+ -+ up(&queue->pop); -+ -+ return header; -+} -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4055d4bf9f740ab9f10a7e44673b9795681981f7 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h -@@ -0,0 +1,82 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef VCHIQ_UTIL_H -+#define VCHIQ_UTIL_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for time_t */ -+#include -+#include -+ -+#include "vchiq_if.h" -+ -+typedef struct { -+ int size; -+ int read; -+ int write; -+ int initialized; -+ -+ struct semaphore pop; -+ struct semaphore push; -+ -+ VCHIQ_HEADER_T **storage; -+} VCHIU_QUEUE_T; -+ -+extern int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size); -+extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue); -+ -+extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue); -+extern int vchiu_queue_is_full(VCHIU_QUEUE_T *queue); -+ -+extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header); -+ -+extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue); -+extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue); -+ -+#endif -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c -new file mode 100644 -index 0000000000000000000000000000000000000000..b6bfa21155e431e93bfb2c149d32437184c2b6e3 ---- /dev/null -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c -@@ -0,0 +1,59 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+#include "vchiq_build_info.h" -+#include -+ -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_hostname, "dc4-arm-01" ); -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_version, "9245b4c35b99b3870e1f7dc598c5692b3c66a6f0 (tainted)" ); -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_time, __TIME__ ); -+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_date, __DATE__ ); -+ -+const char *vchiq_get_build_hostname( void ) -+{ -+ return vchiq_build_hostname; -+} -+ -+const char *vchiq_get_build_version( void ) -+{ -+ return vchiq_build_version; -+} -+ -+const char *vchiq_get_build_date( void ) -+{ -+ return vchiq_build_date; -+} -+ -+const char *vchiq_get_build_time( void ) -+{ -+ return vchiq_build_time; -+} - -From 566c5c2c2ff0ad35cccf0ad61a4ebd9f9dfb2e4b Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 17 Jun 2015 16:07:06 +0100 -Subject: [PATCH 043/208] vc_mem: Add vc_mem driver +Date: Fri, 28 Oct 2016 15:36:43 +0100 +Subject: [PATCH 039/111] vc_mem: Add vc_mem driver for querying firmware + memory addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -91229,496 +75391,14 @@ Make the vc_mem module available for ARCH_BCM2835 by moving it. Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 --- - arch/arm/mach-bcm2709/vc_mem.c | 431 ---------------------------- - drivers/char/broadcom/Kconfig | 12 +- - drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_mem.c | 422 +++++++++++++++++++++++++++ - include/linux/broadcom/vc_mem.h | 35 +++ - 6 files changed, 469 insertions(+), 467 deletions(-) - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - delete mode 100644 arch/arm/mach-bcm2709/vc_mem.c + drivers/char/broadcom/Kconfig | 12 +- + drivers/char/broadcom/Makefile | 1 + + drivers/char/broadcom/vc_mem.c | 422 ++++++++++++++++++++++++++++++++++++++++ + include/linux/broadcom/vc_mem.h | 35 ++++ + 4 files changed, 469 insertions(+), 1 deletion(-) create mode 100644 drivers/char/broadcom/vc_mem.c create mode 100644 include/linux/broadcom/vc_mem.h -diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -deleted file mode 100644 -index 4a4a33845cbc02f0e0d5368fed3609f6ba9ff92b..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/vc_mem.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#if !defined( VC_MEM_H ) --#define VC_MEM_H -- --#include -- --#define VC_MEM_IOC_MAGIC 'v' -- --#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) --#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) --#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) --#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -- --#if defined( __KERNEL__ ) --#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -- --extern unsigned long mm_vc_mem_phys_addr; --extern unsigned int mm_vc_mem_size; --extern int vc_mem_get_current_size( void ); --#endif -- --#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -deleted file mode 100644 -index d2adfd1db2421984ea8ab8fb809d1adb0765714e..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/vc_mem.c -+++ /dev/null -@@ -1,431 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_ARCH_KONA --#include --#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) --#else --#include --#endif -- --#include "mach/vc_mem.h" -- --#define DRIVER_NAME "vc-mem" -- --// Device (/dev) related variables --static dev_t vc_mem_devnum = 0; --static struct class *vc_mem_class = NULL; --static struct cdev vc_mem_cdev; --static int vc_mem_inited = 0; -- --#ifdef CONFIG_DEBUG_FS --static struct dentry *vc_mem_debugfs_entry; --#endif -- --/* -- * Videocore memory addresses and size -- * -- * Drivers that wish to know the videocore memory addresses and sizes should -- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -- * headers. This allows the other drivers to not be tied down to a a certain -- * address/size at compile time. -- * -- * In the future, the goal is to have the videocore memory virtual address and -- * size be calculated at boot time rather than at compile time. The decision of -- * where the videocore memory resides and its size would be in the hands of the -- * bootloader (and/or kernel). When that happens, the values of these variables -- * would be calculated and assigned in the init function. -- */ --// in the 2835 VC in mapped above ARM, but ARM has full access to VC space --unsigned long mm_vc_mem_phys_addr = 0x00000000; --unsigned int mm_vc_mem_size = 0; --unsigned int mm_vc_mem_base = 0; -- --EXPORT_SYMBOL(mm_vc_mem_phys_addr); --EXPORT_SYMBOL(mm_vc_mem_size); --EXPORT_SYMBOL(mm_vc_mem_base); -- --static uint phys_addr = 0; --static uint mem_size = 0; --static uint mem_base = 0; -- -- --/**************************************************************************** --* --* vc_mem_open --* --***************************************************************************/ -- --static int --vc_mem_open(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_release --* --***************************************************************************/ -- --static int --vc_mem_release(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_get_size --* --***************************************************************************/ -- --static void --vc_mem_get_size(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_base --* --***************************************************************************/ -- --static void --vc_mem_get_base(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_current_size --* --***************************************************************************/ -- --int --vc_mem_get_current_size(void) --{ -- return mm_vc_mem_size; --} -- --EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -- --/**************************************************************************** --* --* vc_mem_ioctl --* --***************************************************************************/ -- --static long --vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) --{ -- int rc = 0; -- -- (void) cmd; -- (void) arg; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- switch (cmd) { -- case VC_MEM_IOC_MEM_PHYS_ADDR: -- { -- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -- __func__, (void *) mm_vc_mem_phys_addr); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -- sizeof (mm_vc_mem_phys_addr)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_SIZE: -- { -- // Get the videocore memory size first -- vc_mem_get_size(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -- mm_vc_mem_size); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_size, -- sizeof (mm_vc_mem_size)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_BASE: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_LOAD: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- default: -- { -- return -ENOTTY; -- } -- } -- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -- -- return rc; --} -- --/**************************************************************************** --* --* vc_mem_mmap --* --***************************************************************************/ -- --static int --vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) --{ -- int rc = 0; -- unsigned long length = vma->vm_end - vma->vm_start; -- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -- -- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -- __func__, (long) vma->vm_start, (long) vma->vm_end, -- (long) vma->vm_pgoff); -- -- if (offset + length > mm_vc_mem_size) { -- pr_err("%s: length %ld is too big\n", __func__, length); -- return -EINVAL; -- } -- // Do not cache the memory map -- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- -- rc = remap_pfn_range(vma, vma->vm_start, -- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -- vma->vm_pgoff, length, vma->vm_page_prot); -- if (rc != 0) { -- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -- } -- -- return rc; --} -- --/**************************************************************************** --* --* File Operations for the driver. --* --***************************************************************************/ -- --static const struct file_operations vc_mem_fops = { -- .owner = THIS_MODULE, -- .open = vc_mem_open, -- .release = vc_mem_release, -- .unlocked_ioctl = vc_mem_ioctl, -- .mmap = vc_mem_mmap, --}; -- --#ifdef CONFIG_DEBUG_FS --static void vc_mem_debugfs_deinit(void) --{ -- debugfs_remove_recursive(vc_mem_debugfs_entry); -- vc_mem_debugfs_entry = NULL; --} -- -- --static int vc_mem_debugfs_init( -- struct device *dev) --{ -- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -- if (!vc_mem_debugfs_entry) { -- dev_warn(dev, "could not create debugfs entry\n"); -- return -EFAULT; -- } -- -- if (!debugfs_create_x32("vc_mem_phys_addr", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_phys_addr)) { -- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_size", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_size)) { -- dev_warn(dev, "%s:could not create vc_mem_size entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_base", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_base)) { -- dev_warn(dev, "%s:could not create vc_mem_base entry\n", -- __func__); -- goto fail; -- } -- -- return 0; -- --fail: -- vc_mem_debugfs_deinit(); -- return -EFAULT; --} -- --#endif /* CONFIG_DEBUG_FS */ -- -- --/**************************************************************************** --* --* vc_mem_init --* --***************************************************************************/ -- --static int __init --vc_mem_init(void) --{ -- int rc = -EFAULT; -- struct device *dev; -- -- pr_debug("%s: called\n", __func__); -- -- mm_vc_mem_phys_addr = phys_addr; -- mm_vc_mem_size = mem_size; -- mm_vc_mem_base = mem_base; -- -- vc_mem_get_size(); -- -- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -- -- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -- __func__, rc); -- goto out_err; -- } -- -- cdev_init(&vc_mem_cdev, &vc_mem_fops); -- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -- goto out_unregister; -- } -- -- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vc_mem_class)) { -- rc = PTR_ERR(vc_mem_class); -- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -- goto out_cdev_del; -- } -- -- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -- DRIVER_NAME); -- if (IS_ERR(dev)) { -- rc = PTR_ERR(dev); -- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -- goto out_class_destroy; -- } -- --#ifdef CONFIG_DEBUG_FS -- /* don't fail if the debug entries cannot be created */ -- vc_mem_debugfs_init(dev); --#endif -- -- vc_mem_inited = 1; -- return 0; -- -- device_destroy(vc_mem_class, vc_mem_devnum); -- -- out_class_destroy: -- class_destroy(vc_mem_class); -- vc_mem_class = NULL; -- -- out_cdev_del: -- cdev_del(&vc_mem_cdev); -- -- out_unregister: -- unregister_chrdev_region(vc_mem_devnum, 1); -- -- out_err: -- return -1; --} -- --/**************************************************************************** --* --* vc_mem_exit --* --***************************************************************************/ -- --static void __exit --vc_mem_exit(void) --{ -- pr_debug("%s: called\n", __func__); -- -- if (vc_mem_inited) { --#if CONFIG_DEBUG_FS -- vc_mem_debugfs_deinit(); --#endif -- device_destroy(vc_mem_class, vc_mem_devnum); -- class_destroy(vc_mem_class); -- cdev_del(&vc_mem_cdev); -- unregister_chrdev_region(vc_mem_devnum, 1); -- } --} -- --module_init(vc_mem_init); --module_exit(vc_mem_exit); --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Broadcom Corporation"); -- --module_param(phys_addr, uint, 0644); --module_param(mem_size, uint, 0644); --module_param(mem_base, uint, 0644); diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig index 2d8bd6e5016aab7340636c1f5dc4dd0cbacae6c0..70379287f6261fd833202ac47de1bcca8b84959a 100644 --- a/drivers/char/broadcom/Kconfig @@ -92221,10 +75901,10 @@ index 0000000000000000000000000000000000000000..20a475377eb3078ea1ecaef2b24efc35 + +#endif /* _VC_MEM_H */ -From 1a374ac5d04091feae0ddeca584c67ca348fcfae Mon Sep 17 00:00:00 2001 +From 81ba2928873a89c6233776e594f2a001d87cc11b Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 044/208] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 040/111] vcsm: VideoCore shared memory service for BCM2835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -92267,14 +75947,14 @@ Signed-off-by: Noralf Trønnes --- drivers/char/broadcom/Kconfig | 9 + drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_sm/Makefile | 20 + + drivers/char/broadcom/vc_sm/Makefile | 9 + drivers/char/broadcom/vc_sm/vc_sm_defs.h | 181 ++ drivers/char/broadcom/vc_sm/vc_sm_knl.h | 55 + drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 492 +++++ drivers/char/broadcom/vc_sm/vc_vchi_sm.h | 82 + drivers/char/broadcom/vc_sm/vmcs_sm.c | 3213 ++++++++++++++++++++++++++++++ include/linux/broadcom/vmcs_sm_ioctl.h | 248 +++ - 9 files changed, 4301 insertions(+) + 9 files changed, 4290 insertions(+) create mode 100644 drivers/char/broadcom/vc_sm/Makefile create mode 100644 drivers/char/broadcom/vc_sm/vc_sm_defs.h create mode 100644 drivers/char/broadcom/vc_sm/vc_sm_knl.h @@ -92310,24 +75990,13 @@ index fce918c369f7a9430136fea3ab098350339f1b01..de8feb98c63ff1e6437d80a6db85a8d3 +obj-$(CONFIG_BCM_VC_SM) += vc_sm/ diff --git a/drivers/char/broadcom/vc_sm/Makefile b/drivers/char/broadcom/vc_sm/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..68fa2aa7f725d3587c47c22489efc3418e48dce8 +index 0000000000000000000000000000000000000000..19ce263bc273dcdb24ea2b4431e4cafcf4ca4a2b --- /dev/null +++ b/drivers/char/broadcom/vc_sm/Makefile -@@ -0,0 +1,20 @@ -+EXTRA_CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -+ -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services" -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchi" -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchiq_arm" -+EXTRA_CFLAGS += -I"$(srctree)/fs/" -+ -+EXTRA_CFLAGS += -DOS_ASSERT_FAILURE -+EXTRA_CFLAGS += -D__STDC_VERSION=199901L -+EXTRA_CFLAGS += -D__STDC_VERSION__=199901L -+EXTRA_CFLAGS += -D__VCCOREVER__=0 -+EXTRA_CFLAGS += -D__KERNEL__ -+EXTRA_CFLAGS += -D__linux__ -+EXTRA_CFLAGS += -Werror +@@ -0,0 +1,9 @@ ++ccflags-$(CONFIG_BCM_VC_SM) += -Werror -Wall -Wstrict-prototypes -Wno-trigraphs -O2 ++ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"$(srctree)/fs/" ++ccflags-$(CONFIG_BCM_VC_SM) += -DOS_ASSERT_FAILURE -D__STDC_VERSION=199901L -D__STDC_VERSION__=199901L -D__VCCOREVER__=0 -D__KERNEL__ -D__linux__ + +obj-$(CONFIG_BCM_VC_SM) := vc-sm.o + @@ -96642,10 +80311,10 @@ index 0000000000000000000000000000000000000000..334f36d0d697b047df2922b5f2db67f3 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ -From 9a1ccb17b43b5109f5490c1d6bf5bacbf4e11a1b Mon Sep 17 00:00:00 2001 +From c79d4c54a6a03c79b998430d2d08afbc63c6d110 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 21 Aug 2015 23:14:48 +0100 -Subject: [PATCH 045/208] Add /dev/gpiomem device for rootless user GPIO access +Subject: [PATCH 041/111] Add /dev/gpiomem device for rootless user GPIO access Signed-off-by: Luke Wren @@ -96956,10 +80625,10 @@ index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae64 +MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +MODULE_AUTHOR("Luke Wren "); -From f4db6af82e4cb6535fa14fdf29b90769f2ce3f05 Mon Sep 17 00:00:00 2001 +From d89f74a85fef14e7b1661b2252fa2b08a859eb94 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:14:45 +0100 -Subject: [PATCH 046/208] Add SMI driver +Subject: [PATCH 042/111] Add SMI driver Signed-off-by: Luke Wren --- @@ -97057,7 +80726,7 @@ index 0000000000000000000000000000000000000000..b76dc694f1ac0b8044000ae54d312c80 +}; + diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index b75c9b2639fb0e63dd2623ddc1dcaac5759c132b..2292ed2ac9f457a7d491110e673666136faa5a5e 100644 +index b75c9b2639fb0e63dd2623ddc1dcaac5759c132b..f7885466f5bf9c0cf45f2057d07a0d24151f10c3 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig @@ -41,3 +41,11 @@ config BCM2835_DEVGPIOMEM @@ -97066,7 +80735,7 @@ index b75c9b2639fb0e63dd2623ddc1dcaac5759c132b..2292ed2ac9f457a7d491110e67366613 +config BCM2835_SMI_DEV + tristate "Character device driver for BCM2835 Secondary Memory Interface" -+ depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI ++ depends on BCM2835_SMI + default m + help + This driver provides a character device interface (ioctl + read/write) to @@ -97491,7 +81160,7 @@ index 0000000000000000000000000000000000000000..d6efd92fdfe46df5cfe219d2123e0dff + "Character device driver for BCM2835's secondary memory interface"); +MODULE_AUTHOR("Luke Wren "); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2..cff8c3df50c4b13d40fd1143eb86a66756bc097c 100644 +index 64971baf11faebaff879c58067d23fd9bf29895a..779f7d61a1779decd4dcbba3bc0e6b330e47f335 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -10,6 +10,14 @@ config SENSORS_LIS3LV02D @@ -97500,7 +81169,7 @@ index dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2..cff8c3df50c4b13d40fd1143eb86a667 +config BCM2835_SMI + tristate "Broadcom 283x Secondary Memory Interface driver" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + default m + help + Driver for enabling and using Broadcom's Secondary/Slow Memory Interface. @@ -97510,7 +81179,7 @@ index dc9a6ae02c2aebd934cb5ff66c7db9eaccb4c0d2..cff8c3df50c4b13d40fd1143eb86a667 tristate "Analog Devices Digital Potentiometers" depends on (I2C || SPI) && SYSFS diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index bdf0f5fe7be52b16e12e0bbc79ebfe58a084794d..d31dd62a64dfb98f07d1cae048b31961600d79f9 100644 +index 31983366090a781441a3235cac5883d6fbb27fa4..6c400f0fb92f5af49e04911b7f103ce1a60af093 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o @@ -97518,9 +81187,9 @@ index bdf0f5fe7be52b16e12e0bbc79ebfe58a084794d..d31dd62a64dfb98f07d1cae048b31961 obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o +obj-$(CONFIG_BCM2835_SMI) += bcm2835_smi.o - obj-$(CONFIG_BMP085) += bmp085.o - obj-$(CONFIG_BMP085_I2C) += bmp085-i2c.o - obj-$(CONFIG_BMP085_SPI) += bmp085-spi.o + obj-$(CONFIG_DUMMY_IRQ) += dummy-irq.o + obj-$(CONFIG_ICS932S401) += ics932s401.o + obj-$(CONFIG_LKDTM) += lkdtm.o diff --git a/drivers/misc/bcm2835_smi.c b/drivers/misc/bcm2835_smi.c new file mode 100644 index 0000000000000000000000000000000000000000..63a4ea08b9930a3a31a985f0a1d969b488ed49ec @@ -98910,10 +82579,10 @@ index 0000000000000000000000000000000000000000..ee3a75edfc033eeb0d90a687ffb68b10 + +#endif /* BCM2835_SMI_H */ -From 5b3d8d4688eb4eeaea69a189323e9c5fc0354e69 Mon Sep 17 00:00:00 2001 +From 5c4de9dbae5990f716e77e360a6367588597c2d6 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 26 Apr 2016 14:59:21 +0000 -Subject: [PATCH 047/208] MISC: bcm2835: smi: use clock manager and fix reload +Subject: [PATCH 043/111] MISC: bcm2835: smi: use clock manager and fix reload issues Use clock manager instead of self-made clockmanager. @@ -99083,10 +82752,10 @@ index 63a4ea08b9930a3a31a985f0a1d969b488ed49ec..1261540703127d1d63b9f3c87042c6e5 return 0; } -From c6d205f0fe1e94bc2f07fd3c0891c79719fb4acb Mon Sep 17 00:00:00 2001 +From 0b8fd06e2579f9d9fca4c995c99567e29d4f9ffe Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:16:10 +0100 -Subject: [PATCH 048/208] Add SMI NAND driver +Subject: [PATCH 044/111] Add SMI NAND driver Signed-off-by: Luke Wren --- @@ -99148,7 +82817,7 @@ index 0000000000000000000000000000000000000000..159544d6579070d376d146bd24a86653 +}; \ No newline at end of file diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig -index 21ff58099f3bfd5c042040d2ee7e4bbcbdb6a074..b6a0529b2c15f37983169e3429b67bedb71fb14e 100644 +index 7b7a887b4709f0122f32b60833d8c2e36bc4dead..2db503816a8d5d763bef1b08e3f458d1a2e87751 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -41,6 +41,13 @@ config MTD_SM_COMMON @@ -99157,7 +82826,7 @@ index 21ff58099f3bfd5c042040d2ee7e4bbcbdb6a074..b6a0529b2c15f37983169e3429b67bed +config MTD_NAND_BCM2835_SMI + tristate "Use Broadcom's Secondary Memory Interface as a NAND controller (BCM283x)" -+ depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI && MTD_NAND ++ depends on BCM2835_SMI + default m + help + Uses the BCM2835's SMI peripheral as a NAND controller. @@ -99451,10 +83120,10 @@ index 0000000000000000000000000000000000000000..02adda6da18bd0ba9ab19a104975b79d + ("Driver for NAND chips using Broadcom Secondary Memory Interface"); +MODULE_AUTHOR("Luke Wren "); -From feab27c42b831d89424f2efc1c5eb7a98972712d Mon Sep 17 00:00:00 2001 +From 81a230faec239611f15b7854b0536575b4fec75d Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 049/208] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 045/111] lirc: added support for RaspberryPi GPIO lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others See: https://github.com/raspberrypi/linux/issues/525 @@ -100317,17 +83986,17 @@ index 0000000000000000000000000000000000000000..fb69624ccef00ddbdccf8256d6baf1b1 + +#endif -From fff2289d895dbfc79c794d5a1cd1d8d24435c926 Mon Sep 17 00:00:00 2001 +From f983fc96a1764f6e1de49aa0190ec988bf9ae29d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 050/208] Add cpufreq driver +Subject: [PATCH 046/111] Add cpufreq driver Signed-off-by: popcornmix --- drivers/cpufreq/Kconfig.arm | 9 ++ drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/bcm2835-cpufreq.c | 213 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 223 insertions(+) + drivers/cpufreq/bcm2835-cpufreq.c | 218 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 228 insertions(+) create mode 100644 drivers/cpufreq/bcm2835-cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm @@ -100364,10 +84033,10 @@ index 0a9b6a093646bd1dd60ee092e362b24527f0ef1e..92a628a670c12c39c2be73fc91f65da5 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c new file mode 100644 -index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245c71cf868 +index 0000000000000000000000000000000000000000..414fbdc10dfbfc6e4bb47870a7af3fd5780f9c9a --- /dev/null +++ b/drivers/cpufreq/bcm2835-cpufreq.c -@@ -0,0 +1,213 @@ +@@ -0,0 +1,218 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -100415,12 +84084,8 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 + +/* ---------- GLOBALS ---------- */ +static struct cpufreq_driver bcm2835_cpufreq_driver; /* the cpufreq driver global */ -+ -+static struct cpufreq_frequency_table bcm2835_freq_table[] = { -+ {0, 0, 0}, -+ {0, 0, 0}, -+ {0, 0, CPUFREQ_TABLE_END}, -+}; ++static unsigned int min_frequency, max_frequency; ++static struct cpufreq_frequency_table bcm2835_freq_table[3]; + +/* + =============================================== @@ -100525,10 +84190,19 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 + } + + /* now find out what the maximum and minimum frequencies are */ -+ bcm2835_freq_table[0].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); -+ bcm2835_freq_table[1].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); ++ min_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); ++ max_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); + -+ print_info("min=%d max=%d\n", bcm2835_freq_table[0].frequency, bcm2835_freq_table[1].frequency); ++ if (min_frequency == max_frequency) { ++ bcm2835_freq_table[0].frequency = min_frequency; ++ bcm2835_freq_table[1].frequency = CPUFREQ_TABLE_END; ++ } else { ++ bcm2835_freq_table[0].frequency = min_frequency; ++ bcm2835_freq_table[1].frequency = max_frequency; ++ bcm2835_freq_table[2].frequency = CPUFREQ_TABLE_END; ++ } ++ ++ print_info("min=%d max=%d\n", min_frequency, max_frequency); + return cpufreq_generic_init(policy, bcm2835_freq_table, transition_latency); +} + @@ -100540,7 +84214,7 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 + +static int bcm2835_cpufreq_driver_target_index(struct cpufreq_policy *policy, unsigned int state) +{ -+ unsigned int target_freq = bcm2835_freq_table[state].frequency; ++ unsigned int target_freq = state == 0 ? min_frequency : max_frequency; + unsigned int cur = bcm2835_cpufreq_set_clock(policy->cur, target_freq); + + if (!cur) @@ -100562,7 +84236,7 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 +{ + unsigned int actual_rate = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_CLOCK_RATE); + print_debug("cpu%d: freq=%d\n", cpu, actual_rate); -+ return actual_rate <= bcm2835_freq_table[0].frequency ? bcm2835_freq_table[0].frequency : bcm2835_freq_table[1].frequency; ++ return actual_rate <= min_frequency ? min_frequency : max_frequency; +} + +/* the CPUFreq driver */ @@ -100582,10 +84256,10 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From 37aa96d5731f2657672c71c63c1e1a196b62be02 Mon Sep 17 00:00:00 2001 +From e15412c1981d5de69b4d6e4b4eae8b99c2f4980d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 051/208] Added hwmon/thermal driver for reporting core +Subject: [PATCH 047/111] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -100606,10 +84280,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index 2d702ca6556f5b6185a95ec007ada7b124226272..32ab74bb842d658b6b937e38fa69b8abd31de94b 100644 +index a13541bdc726899807dd8723c92c21312fbc6439..de45ea51555e5f47498c18a969751ea6dc52d6b9 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -282,6 +282,13 @@ config INTEL_POWERCLAMP +@@ -302,6 +302,13 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. @@ -100624,11 +84298,11 @@ index 2d702ca6556f5b6185a95ec007ada7b124226272..32ab74bb842d658b6b937e38fa69b8ab tristate "X86 package temperature thermal driver" depends on X86_THERMAL_VECTOR diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile -index 10b07c14f8a9f75363323d0c69542606d8dfed96..ac19930164fdcc773035a95af8136ec2f36fc8b7 100644 +index c92eb22a41ff89f3f1c61c61977de7eb9ba516ae..bcf9e7503c940821ca260774ba9e1cebf185cd3e 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o - obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o +@@ -41,6 +41,7 @@ obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o + obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o +obj-$(CONFIG_THERMAL_BCM2835) += bcm2835-thermal.o @@ -100751,10 +84425,10 @@ index 0000000000000000000000000000000000000000..c63fb9f9d143e19612a18fe530c7b2b3 +MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); +MODULE_LICENSE("GPL"); -From e92628a6bd90876e0ccea0ac20eaa0ac2445c14c Mon Sep 17 00:00:00 2001 +From 38c98a91730d6c9d0fb64287a0094611e80b74ee Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 052/208] Add Chris Boot's i2c driver +Subject: [PATCH 048/111] Add Chris Boot's i2c driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -100851,14 +84525,14 @@ Check if FIFO can accept data before writing. To avoid a peripheral read on the last iteration of a loop, both bcm2708_bsc_fifo_fill and ~drain are changed as well. --- - drivers/i2c/busses/Kconfig | 21 +- + drivers/i2c/busses/Kconfig | 19 ++ drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-bcm2708.c | 512 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 534 insertions(+), 1 deletion(-) + 3 files changed, 533 insertions(+) create mode 100644 drivers/i2c/busses/i2c-bcm2708.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 5c3993b261298ef3c9571e76307fe912548b9538..37f463232d6db91940763345600b095dbd8b5c58 100644 +index d252276feadf6b0b05cbe370330ed7cef5a16857..b81d8133639a34dcec85df50f064d8e9a9ba22fa 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" @@ -100867,7 +84541,7 @@ index 5c3993b261298ef3c9571e76307fe912548b9538..37f463232d6db91940763345600b095d +config I2C_BCM2708 + tristate "BCM2708 BSC" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on ARCH_BCM2835 + help + Enabling this option will add BSC (Broadcom Serial Controller) + support for the BCM2708. BSC is a Broadcom proprietary bus compatible @@ -100887,17 +84561,8 @@ index 5c3993b261298ef3c9571e76307fe912548b9538..37f463232d6db91940763345600b095d config I2C_ALI1535 tristate "ALI 1535" depends on PCI -@@ -366,7 +385,7 @@ config I2C_AXXIA - - config I2C_BCM2835 - tristate "Broadcom BCM2835 I2C controller" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - If you say yes to this option, support will be included for the - BCM2835 I2C controller. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index 37f2819b4560b0e0947b74c214f5c5a0952bc0ae..e309579e691599031f25bd9b9b36430753f004a7 100644 +index 29764cc20a440752841272ddfed3993048ecd105..26ae016a15e72cbb2e742aa89238636e3b846b8e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -2,6 +2,8 @@ @@ -101428,10 +85093,10 @@ index 0000000000000000000000000000000000000000..962f2e5c7455d91bf32925d785f5f16b +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 10a9053f8e51e5f87b5e3b772c5785ea42971dd7 Mon Sep 17 00:00:00 2001 +From 2580b23fea5c030382c691631a510744f7b9e839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:27:06 +0200 -Subject: [PATCH 053/208] char: broadcom: Add vcio module +Subject: [PATCH 049/111] char: broadcom: Add vcio module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101448,7 +85113,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/char/broadcom/vcio.c diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 2292ed2ac9f457a7d491110e673666136faa5a5e..5489f19f05c620a30541e1a222d77b6ee4356d97 100644 +index f7885466f5bf9c0cf45f2057d07a0d24151f10c3..032164919350db25c586c36f0e05d3e4891fb835 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig @@ -22,6 +22,12 @@ config BCM2708_VCMEM @@ -101657,10 +85322,10 @@ index 0000000000000000000000000000000000000000..c19bc2075c77879563ef5e59038b5a14 +MODULE_DESCRIPTION("Mailbox userspace access"); +MODULE_LICENSE("GPL"); -From d583497e3d8d54010157aed484835a06a45572e7 Mon Sep 17 00:00:00 2001 +From 3802654fe78a70cf73b7b50064ae12b3ad7352a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:25:01 +0200 -Subject: [PATCH 054/208] firmware: bcm2835: Support ARCH_BCM270x +Subject: [PATCH 050/111] firmware: bcm2835: Support ARCH_BCM270x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101670,13 +85335,22 @@ Turn on USB power. Load driver early because of lacking support for deferred probing in many drivers. +Signed-off-by: Noralf Trønnes + +firmware: bcm2835: Don't turn on USB power + +The raspberrypi-power driver is now used to turn on USB power. + +This partly reverts commit: +firmware: bcm2835: Support ARCH_BCM270x + Signed-off-by: Noralf Trønnes --- - drivers/firmware/raspberrypi.c | 41 +++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 39 insertions(+), 2 deletions(-) + drivers/firmware/raspberrypi.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c -index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b868a85f2b5 100644 +index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..3f070bd38a91511c986e3fb114b15bd4ac32634c 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c @@ -28,6 +28,8 @@ struct rpi_firmware { @@ -101688,33 +85362,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 static DEFINE_MUTEX(transaction_lock); static void response_callback(struct mbox_client *cl, void *msg) -@@ -183,6 +185,25 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) - } - } - -+static int raspberrypi_firmware_set_power(struct rpi_firmware *fw, -+ u32 domain, bool on) -+{ -+ struct { -+ u32 domain; -+ u32 on; -+ } packet; -+ int ret; -+ -+ packet.domain = domain; -+ packet.on = on; -+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POWER_STATE, -+ &packet, sizeof(packet)); -+ if (!ret && packet.on != on) -+ ret = -EINVAL; -+ -+ return ret; -+} -+ - static int rpi_firmware_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -207,9 +228,13 @@ static int rpi_firmware_probe(struct platform_device *pdev) +@@ -207,6 +209,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) init_completion(&fw->c); platform_set_drvdata(pdev, fw); @@ -101722,13 +85370,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 rpi_firmware_print_firmware_revision(fw); -+ if (raspberrypi_firmware_set_power(fw, 3, true)) -+ dev_err(dev, "failed to turn on USB power\n"); -+ - return 0; - } - -@@ -218,6 +243,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) +@@ -218,6 +221,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) struct rpi_firmware *fw = platform_get_drvdata(pdev); mbox_free_channel(fw->chan); @@ -101736,7 +85378,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 return 0; } -@@ -230,7 +256,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) +@@ -230,7 +234,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) */ struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) { @@ -101745,7 +85387,7 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 if (!pdev) return NULL; -@@ -253,7 +279,18 @@ static struct platform_driver rpi_firmware_driver = { +@@ -253,7 +257,18 @@ static struct platform_driver rpi_firmware_driver = { .probe = rpi_firmware_probe, .remove = rpi_firmware_remove, }; @@ -101766,10 +85408,10 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Raspberry Pi firmware driver"); -From 9296e7af762cee3eaeae26c298130bb2cffe4dae Mon Sep 17 00:00:00 2001 +From 722c4b9747c8488a8e9b037948b44085646e874a Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 055/208] bcm2835: add v4l2 camera device +Subject: [PATCH 051/111] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -102149,13 +85791,22 @@ two formats. Detect the old firmware, and reverse the formats if necessary. Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> + +BCM2835-v4l2: Fix a conformance test failure + +Format ioctls: + test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK + warn: v4l2-test-formats.cpp(1195): S_PARM is supported but + doesn't report V4L2_CAP_TIMEPERFRAME. + fail: v4l2-test-formats.cpp(1118): node->has_frmintervals + && !cap->capability --- Documentation/video4linux/bcm2835-v4l2.txt | 60 + drivers/media/platform/Kconfig | 2 + drivers/media/platform/Makefile | 2 + drivers/media/platform/bcm2835/Kconfig | 25 + drivers/media/platform/bcm2835/Makefile | 5 + - drivers/media/platform/bcm2835/bcm2835-camera.c | 2015 ++++++++++++++++++++++ + drivers/media/platform/bcm2835/bcm2835-camera.c | 2016 ++++++++++++++++++++++ drivers/media/platform/bcm2835/bcm2835-camera.h | 145 ++ drivers/media/platform/bcm2835/controls.c | 1345 +++++++++++++++ drivers/media/platform/bcm2835/mmal-common.h | 53 + @@ -102167,7 +85818,7 @@ Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> drivers/media/platform/bcm2835/mmal-parameters.h | 689 ++++++++ drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 ++++++++++++++++++++ drivers/media/platform/bcm2835/mmal-vchiq.h | 178 ++ - 17 files changed, 7204 insertions(+) + 17 files changed, 7205 insertions(+) create mode 100644 Documentation/video4linux/bcm2835-v4l2.txt create mode 100644 drivers/media/platform/bcm2835/Kconfig create mode 100644 drivers/media/platform/bcm2835/Makefile @@ -102251,7 +85902,7 @@ index 0000000000000000000000000000000000000000..c585a8fadf91c5a04453e442fc29ed89 + +$ v4l2-ctl --list-formats diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 552b635cfce7f02b4f3e65d1d641e9e39903ec43..d22e5d5dd939451aa62988f69c6a80ae545011d4 100644 +index ce4a96fccc433c69269a14455ba94e053b515d91..0ea7ea95d824bf95747678e83ee7a61dea6f55cd 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -11,6 +11,8 @@ menuconfig V4L_PLATFORM_DRIVERS @@ -102264,7 +85915,7 @@ index 552b635cfce7f02b4f3e65d1d641e9e39903ec43..d22e5d5dd939451aa62988f69c6a80ae config VIDEO_VIA_CAMERA diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 21771c1a13fbcf9460900826ae2ecb8e2dbaa469..a7a0df8ab6e7672c2e44714a95c95790f55abeb4 100644 +index 40b18d12726ec52d0acfd15894337366eb420e89..b9f01f61c500a9b502d976b4c595be5013610aec 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -2,6 +2,8 @@ @@ -102278,7 +85929,7 @@ index 21771c1a13fbcf9460900826ae2ecb8e2dbaa469..a7a0df8ab6e7672c2e44714a95c95790 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig new file mode 100644 -index 0000000000000000000000000000000000000000..99a5cbccf0f3fa66ad5190ec0942b0c232c3e824 +index 0000000000000000000000000000000000000000..58d5f9600d726cb20e6d04c54c58c53ac3a586d2 --- /dev/null +++ b/drivers/media/platform/bcm2835/Kconfig @@ -0,0 +1,25 @@ @@ -102286,7 +85937,7 @@ index 0000000000000000000000000000000000000000..99a5cbccf0f3fa66ad5190ec0942b0c2 + +config VIDEO_BCM2835 + bool "Broadcom BCM2835 camera interface driver" -+ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) ++ depends on VIDEO_V4L2 && ARCH_BCM2835 + ---help--- + Say Y here to enable camera host interface devices for + Broadcom BCM2835 SoC. This operates over the VCHIQ interface @@ -102309,7 +85960,7 @@ index 0000000000000000000000000000000000000000..99a5cbccf0f3fa66ad5190ec0942b0c2 +endif # VIDEO_BM2835 diff --git a/drivers/media/platform/bcm2835/Makefile b/drivers/media/platform/bcm2835/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..f17c79c33e4a07a2294907d3c748b4d62fc55e21 +index 0000000000000000000000000000000000000000..b14ea91ac79c60f83bc63156436ef8cbcc893e9b --- /dev/null +++ b/drivers/media/platform/bcm2835/Makefile @@ -0,0 +1,5 @@ @@ -102317,13 +85968,13 @@ index 0000000000000000000000000000000000000000..f17c79c33e4a07a2294907d3c748b4d6 + +obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o + -+ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 ++ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c new file mode 100644 -index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478809eb161 +index 0000000000000000000000000000000000000000..4f03949aecf3afbf2e04df38289447195a8847a6 --- /dev/null +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -0,0 +1,2015 @@ +@@ -0,0 +1,2016 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -102570,7 +86221,7 @@ index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478 + +static int queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, -+ unsigned int sizes[], void *alloc_ctxs[]) ++ unsigned int sizes[], struct device *alloc_ctxs[]) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); + unsigned long size; @@ -103725,6 +87376,7 @@ index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478 + dev->capture.timeperframe = tpf; + parm->parm.capture.timeperframe = tpf; + parm->parm.capture.readbuffers = 1; ++ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + + fps_param.num = 0; /* Select variable fps, and then use + * FPS_RANGE to select the actual limits. @@ -109501,10 +93153,10 @@ index 0000000000000000000000000000000000000000..9d1d11e4a53e510c04a416d92d195a7d + +#endif /* MMAL_VCHIQ_H */ -From 11b448942d10a35fb98c8b1f91c78b8ede600c37 Mon Sep 17 00:00:00 2001 +From badabbef8c2ed82582e881b667ff7fe28f7180e0 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 056/208] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 052/111] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -109562,10 +93214,17 @@ scripts/knlinfo: Decode DDTK atom Show the DDTK atom as being a boolean. Signed-off-by: Phil Elwell + +mkknlimg: Retain downstream-kernel detection + +With the death of ARCH_BCM2708 and ARCH_BCM2709, a new way is needed to +determine if this is a "downstream" build that wants the firmware to +load a bcm27xx .dtb. The vc_cma driver is used downstream but not +upstream, making vc_cma_init a suitable predicate symbol. --- - scripts/knlinfo | 171 ++++++++++++++++++++++++++++++++++++ - scripts/mkknlimg | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 434 insertions(+) + scripts/knlinfo | 171 +++++++++++++++++++++++++++++++++++ + scripts/mkknlimg | 264 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 435 insertions(+) create mode 100755 scripts/knlinfo create mode 100755 scripts/mkknlimg @@ -109748,10 +93407,10 @@ index 0000000000000000000000000000000000000000..263ec937eaa70b4fd00bff18599db7f2 +} diff --git a/scripts/mkknlimg b/scripts/mkknlimg new file mode 100755 -index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa60624f87f98 +index 0000000000000000000000000000000000000000..60206de7fa9a49bd027c635306674a29a568652f --- /dev/null +++ b/scripts/mkknlimg -@@ -0,0 +1,263 @@ +@@ -0,0 +1,264 @@ +#!/usr/bin/env perl +# ---------------------------------------------------------------------- +# mkknlimg by Phil Elwell for Raspberry Pi @@ -109831,7 +93490,8 @@ index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa606 + 'brcm,bcm2709' => FLAG_PI | FLAG_DTOK | FLAG_270X, + 'brcm,bcm2835' => FLAG_PI | FLAG_DTOK | FLAG_283X, + 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, -+ 'of_overlay_apply' => FLAG_DTOK | FLAG_DDTK, ++ 'of_cfs_init' => FLAG_DTOK | FLAG_DDTK, ++ 'vc_cma_init' => FLAG_PI | FLAG_270X, +}; + +my $res = try_extract($kernel_file, $tmpfile1); @@ -110016,10 +93676,10 @@ index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa606 + return $trailer; +} -From 804f05236652ec5169092c4b102faa5979b92b27 Mon Sep 17 00:00:00 2001 +From 5588e71a027a865ad341fe3d30dd47c2c1772d57 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 10 Aug 2015 09:49:15 +0100 -Subject: [PATCH 057/208] scripts/dtc: Update to upstream version 1.4.1 +Subject: [PATCH 053/111] scripts/dtc: Update to upstream version 1.4.1 Includes the new localfixups format. @@ -112870,10 +96530,13 @@ index ad9b05ae698b0495ecbda42ffcf4743555313a27..2595dfda020fd9e03f0beff5006f229d -#define DTC_VERSION "DTC 1.4.1-g53bf130b" +#define DTC_VERSION "DTC 1.4.1-g25efc119" -From 87dc2c03954f71140aa60b8e5a2f35ad8236cd08 Mon Sep 17 00:00:00 2001 +From c5c6e46a51b163e9a3faf7422693f14b7bdb94d8 Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 058/208] BCM2708: Add core Device Tree support +Subject: [PATCH 054/111] BCM2708: Add core Device Tree support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Add the bare minimum needed to boot BCM2708 from a Device Tree. @@ -112938,23 +96601,137 @@ The "mmc" overlay reverts to using the other controller. squash: Add cprman to dt BCM270X_DT: Use clk_core for I2C interfaces + +BCM270X_DT: Use bcm283x.dtsi, bcm2835.dtsi and bcm2836.dtsi + +The mainline Device Tree files are quite close to downstream now. +Let's use bcm283x.dtsi, bcm2835.dtsi and bcm2836.dtsi as base files +for our dts files. + +Mainline dts files are based on these files: + + bcm2835-rpi.dtsi + bcm2835.dtsi bcm2836.dtsi + bcm283x.dtsi + +Current downstream are based on these: + + bcm2708.dtsi bcm2709.dtsi bcm2710.dtsi + bcm2708_common.dtsi + +This patch introduces this dependency: + + bcm2708.dtsi bcm2709.dtsi + bcm2708-rpi.dtsi + bcm270x.dtsi + bcm2835.dtsi bcm2836.dtsi + bcm283x.dtsi + +And: + bcm2710.dtsi + bcm2708-rpi.dtsi + bcm270x.dtsi + bcm283x.dtsi + +bcm270x.dtsi contains the downstream bcm283x.dtsi diff. +bcm2708-rpi.dtsi is the downstream version of bcm2835-rpi.dtsi. + +Other changes: +- The led node has moved from /soc/leds to /leds. This is not a problem + since the label is used to reference it. +- The clk_osc reg property changes from 6 to 3. +- The gpu nodes has their interrupt property set in the base file. +- the clocks label does not point to the /clocks node anymore, but + points to the cprman node. This is not a problem since the overlays + that use the clock node refer to it directly: target-path = "/clocks"; +- some nodes now have 2 labels since mainline and downstream differs in + this respect: cprman/clocks, spi0/spi, gpu/vc4. +- some nodes doesn't have an explicit status = "okay" since they're not + disabled in the base file: watchdog and random. +- gpiomem doesn't need an explicit status = "okay". +- bcm2708-rpi-cm.dts got the hpd-gpios property from bcm2708_common.dtsi, + it's now set directly in that file. +- bcm2709-rpi-2-b.dts has the timer node moved from /soc/timer to /timer. +- Removed clock-frequency property on the bcm{2709,2710}.dtsi timer nodes. + +Signed-off-by: Noralf Trønnes + +BCM270X_DT: Use raspberrypi-power to turn on USB power + +Use the raspberrypi-power driver to turn on USB power. + +Signed-off-by: Noralf Trønnes + +BCM270X_DT: Add a .dtbo target, use for overlays + +Change the filenames and extensions to keep the pre-DDT style of +overlay (-overlay.dtb) distinct from new ones that use a +different style of local fixups (.dtbo), and to match other +platforms. + +The RPi firmware uses the DDTK trailer atom to choose which type of +overlay to use for each kernel. + +Signed-off-by: Phil Elwell + +BCM270X_DT: Don't generate "linux,phandle" props + +The EPAPR standard says to use "phandle" properties to store phandles, +rather than the deprecated "linux,phandle" version. By default, dtc +generates both, but adding "-H epapr" causes it to only generate +"phandle"s, saving some space and clutter. + +Signed-off-by: Phil Elwell + +BCM270X_DT: Add overlay for enc28j60 on SPI2 + +Works on SPI2 for compute module + +BCM270X_DT: Add midi-uart0 overlay + +MIDI requires 31.25kbaud, a baudrate unsupported by Linux. The +midi-uart0 overlay configures uart0 (ttyAMA0) to use a fake clock +so that requesting 38.4kbaud actually gets 31.25kbaud. + +Signed-off-by: Phil Elwell + +BCM270X_DT: Add i2c-sensor overlay + +The i2c-sensor overlay is a container for various pressure and +temperature sensors, currently bmp085 and bmp280. The standalone +bmp085_i2c-sensor overlay is now deprecated. + +Signed-off-by: Phil Elwell + +BCM270X_DT: overlays/*-overlay.dtb -> overlays/*.dtbo (#1752) + +We now create overlays as .dtbo files. + +build: support for .dtbo files for dtb overlays + +Kernel 4.4.6+ on RaspberryPi support .dtbo files for overlays, instead of .dtb. +Patch the kernel, which has faulty rules to generate .dtbo the way yocto does + +Signed-off-by: Herve Jourdain +Signed-off-by: Khem Raj --- - arch/arm/boot/dts/Makefile | 32 + - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 162 +++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 152 +++ - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 106 ++ + arch/arm/Makefile | 2 + + arch/arm/boot/.gitignore | 2 +- + arch/arm/boot/dts/Makefile | 19 + + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 156 +++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 146 +++ + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 105 ++ arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 50 + - arch/arm/boot/dts/bcm2708.dtsi | 40 + - arch/arm/boot/dts/bcm2708_common.dtsi | 436 +++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 162 +++ - arch/arm/boot/dts/bcm2709.dtsi | 102 ++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 213 ++++ - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 162 +++ - arch/arm/boot/dts/bcm2710.dtsi | 165 +++ - arch/arm/boot/dts/bcm2835-rpi-cm.dts | 93 ++ - arch/arm/boot/dts/bcm2835-rpi-cm.dtsi | 30 + - arch/arm/boot/dts/overlays/Makefile | 111 ++ - arch/arm/boot/dts/overlays/README | 1302 ++++++++++++++++++++ + arch/arm/boot/dts/bcm2708-rpi.dtsi | 109 ++ + arch/arm/boot/dts/bcm2708.dtsi | 16 + + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 156 +++ + arch/arm/boot/dts/bcm2709.dtsi | 22 + + arch/arm/boot/dts/bcm270x.dtsi | 141 ++ + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 203 +++ + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 155 +++ + arch/arm/boot/dts/bcm2710.dtsi | 155 +++ + arch/arm/boot/dts/overlays/Makefile | 105 ++ + arch/arm/boot/dts/overlays/README | 1368 ++++++++++++++++++++ .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 53 + arch/arm/boot/dts/overlays/ads1015-overlay.dts | 98 ++ arch/arm/boot/dts/overlays/ads7846-overlay.dts | 89 ++ @@ -112971,6 +96748,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 20 + arch/arm/boot/dts/overlays/dwc2-overlay.dts | 29 + arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 53 + + .../boot/dts/overlays/enc28j60-spi2-overlay.dts | 47 + arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 44 + .../boot/dts/overlays/gpio-poweroff-overlay.dts | 34 + .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 + @@ -112980,10 +96758,12 @@ BCM270X_DT: Use clk_core for I2C interfaces .../dts/overlays/hifiberry-digi-pro-overlay.dts | 41 + arch/arm/boot/dts/overlays/hy28a-overlay.dts | 93 ++ arch/arm/boot/dts/overlays/hy28b-overlay.dts | 148 +++ + arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts | 13 + arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 43 + - arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 139 +++ + arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 139 ++ .../boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts | 26 + - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 73 ++ + arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 83 ++ + arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 34 + .../arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts | 61 + .../arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts | 37 + .../boot/dts/overlays/i2s-gpio28-31-overlay.dts | 18 + @@ -112997,6 +96777,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/mcp23s17-overlay.dts | 732 +++++++++++ .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 73 ++ .../arm/boot/dts/overlays/mcp2515-can1-overlay.dts | 73 ++ + arch/arm/boot/dts/overlays/midi-uart0-overlay.dts | 36 + arch/arm/boot/dts/overlays/mmc-overlay.dts | 38 + arch/arm/boot/dts/overlays/mz61581-overlay.dts | 117 ++ arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts | 27 + @@ -113004,9 +96785,11 @@ BCM270X_DT: Use clk_core for I2C interfaces .../boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 64 + arch/arm/boot/dts/overlays/piscreen-overlay.dts | 102 ++ arch/arm/boot/dts/overlays/piscreen2r-overlay.dts | 106 ++ - arch/arm/boot/dts/overlays/pitft22-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/pisound-overlay.dts | 114 ++ + arch/arm/boot/dts/overlays/pitft22-overlay.dts | 69 + .../dts/overlays/pitft28-capacitive-overlay.dts | 91 ++ .../dts/overlays/pitft28-resistive-overlay.dts | 121 ++ + .../dts/overlays/pitft35-resistive-overlay.dts | 121 ++ arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 35 + arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts | 47 + arch/arm/boot/dts/overlays/pwm-overlay.dts | 43 + @@ -113026,38 +96809,40 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/sdio-overlay.dts | 36 + arch/arm/boot/dts/overlays/sdtweak-overlay.dts | 23 + arch/arm/boot/dts/overlays/smi-dev-overlay.dts | 18 + - arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 69 + arch/arm/boot/dts/overlays/smi-overlay.dts | 37 + .../boot/dts/overlays/spi-gpio35-39-overlay.dts | 31 + arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 33 + arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts | 26 + arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts | 57 + - arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 69 + arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts | 81 ++ arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts | 57 + - arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts | 69 + arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts | 81 ++ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 224 ++++ arch/arm/boot/dts/overlays/uart1-overlay.dts | 38 + + .../arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 89 ++ arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 136 ++ arch/arm/boot/dts/overlays/vga666-overlay.dts | 30 + arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 + .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 + arch/arm/boot/dts/overlays/wittypi-overlay.dts | 44 + - 105 files changed, 8906 insertions(+) + scripts/Makefile.dtbinst | 10 +- + scripts/Makefile.lib | 11 + + 115 files changed, 8979 insertions(+), 4 deletions(-) create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts - create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dts create mode 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi + create mode 100644 arch/arm/boot/dts/bcm2708-rpi.dtsi create mode 100644 arch/arm/boot/dts/bcm2708.dtsi - create mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi create mode 100644 arch/arm/boot/dts/bcm2709-rpi-2-b.dts create mode 100644 arch/arm/boot/dts/bcm2709.dtsi + create mode 100644 arch/arm/boot/dts/bcm270x.dtsi create mode 100644 arch/arm/boot/dts/bcm2710-rpi-3-b.dts create mode 100644 arch/arm/boot/dts/bcm2710-rpi-cm3.dts create mode 100644 arch/arm/boot/dts/bcm2710.dtsi - create mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dts - create mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dtsi create mode 100644 arch/arm/boot/dts/overlays/Makefile create mode 100644 arch/arm/boot/dts/overlays/README create mode 100644 arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts @@ -113076,6 +96861,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/dwc-otg-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dwc2-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/gpio-ir-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts @@ -113085,10 +96871,12 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/hy28a-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/hy28b-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-mux-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts @@ -113102,6 +96890,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/mcp23s17-overlay.dts create mode 100755 arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart0-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mmc-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mz61581-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts @@ -113109,9 +96898,11 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/piscreen-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/piscreen2r-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pisound-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pitft22-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pps-gpio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pwm-overlay.dts @@ -113144,45 +96935,55 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/tinylcd35-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/uart1-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vga666-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/wittypi-overlay.dts +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 6be9ee148b78b964004392045199ec8d1540134e..b1c49e2a0c5f5ef2939102625171b26cd5372016 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -334,6 +334,8 @@ $(INSTALL_TARGETS): + + %.dtb: | scripts + $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ ++%.dtbo: | scripts ++ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ + + PHONY += dtbs dtbs_install + +diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore +index 3c79f85975aaa26c7c2e353fefc54d71d89bc5bf..eaaeb17e5986e5f7178b2851169444ac7e45be8d 100644 +--- a/arch/arm/boot/.gitignore ++++ b/arch/arm/boot/.gitignore +@@ -3,4 +3,4 @@ zImage + xipImage + bootpImage + uImage +-*.dtb ++*.dtb* diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index faacd52370d24061e705d4e97785c254cf147f8c..71f794ecc710ac533731854bd95961a6a4175b64 100644 +index c558ba75cbccf909063e0f4f131f7efdfd28867b..ec218dcb67019acacd4a6c73c74d12ef4f4204d8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -1,5 +1,27 @@ +@@ -1,5 +1,13 @@ ifeq ($(CONFIG_OF),y) -+dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b.dtb -+dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b-plus.dtb -+dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-cm.dtb -+dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-cm.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2709-rpi-2-b.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb -+ -+# Raspberry Pi -+ifeq ($(CONFIG_ARCH_BCM2708),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2709),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(RPI_DT_OVERLAYS),y) -+ dts-dirs += overlays -+endif ++dtb-$(CONFIG_ARCH_BCM2835) += \ ++ bcm2708-rpi-b.dtb \ ++ bcm2708-rpi-b-plus.dtb \ ++ bcm2708-rpi-cm.dtb \ ++ bcm2709-rpi-2-b.dtb \ ++ bcm2710-rpi-3-b.dtb \ ++ bcm2710-rpi-cm3.dtb + dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -919,10 +941,20 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ +@@ -954,10 +962,21 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \ aspeed-ast2500-evb.dtb @@ -113196,25 +96997,25 @@ index faacd52370d24061e705d4e97785c254cf147f8c..71f794ecc710ac533731854bd95961a6 dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) always := $(dtb-y) -+subdir-y := $(dts-dirs) ++subdir-y := overlays clean-files := *.dtb + -+# Enable fixups to support overlays on BCM2708 platforms -+ifeq ($(RPI_DT_OVERLAYS),y) ++# Enable fixups to support overlays on BCM2835 platforms ++ifeq ($(CONFIG_ARCH_BCM2835),y) + DTC_FLAGS ?= -@ -H epapr ++ dts-dirs += overlays +endif diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts new file mode 100644 -index 0000000000000000000000000000000000000000..6c16c325cd2887a42c42665273834618c1937918 +index 0000000000000000000000000000000000000000..360da5c928dc5599b0d2a9055728087604c6b189 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,162 @@ +@@ -0,0 +1,156 @@ +/dts-v1/; + +#include "bcm2708.dtsi" + +/ { -+ compatible = "brcm,bcm2708"; + model = "Raspberry Pi Model B+"; +}; + @@ -113309,15 +97110,10 @@ index 0000000000000000000000000000000000000000..6c16c325cd2887a42c42665273834618 +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -113373,16 +97169,15 @@ index 0000000000000000000000000000000000000000..6c16c325cd2887a42c42665273834618 +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..7c132437671d43e76445a4bf1184cc9a316b0965 +index 0000000000000000000000000000000000000000..9c49659ab246bce0656f3514f3b924bc4826b421 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,152 @@ +@@ -0,0 +1,146 @@ +/dts-v1/; + +#include "bcm2708.dtsi" + +/ { -+ compatible = "brcm,bcm2708"; + model = "Raspberry Pi Model B"; +}; + @@ -113477,15 +97272,10 @@ index 0000000000000000000000000000000000000000..7c132437671d43e76445a4bf1184cc9a +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -113530,11 +97320,11 @@ index 0000000000000000000000000000000000000000..7c132437671d43e76445a4bf1184cc9a + }; +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -new file mode 100755 -index 0000000000000000000000000000000000000000..ce9f54ff7e4ce76ad25ad0a19cf2ad48ba9df01a +new file mode 100644 +index 0000000000000000000000000000000000000000..eb8662f0d222b4c0a9a2bcb8bccb13e86a0006b3 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -0,0 +1,106 @@ +@@ -0,0 +1,105 @@ +/dts-v1/; + +#include "bcm2708-rpi-cm.dtsi" @@ -113618,13 +97408,12 @@ index 0000000000000000000000000000000000000000..ce9f54ff7e4ce76ad25ad0a19cf2ad48 +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; +}; + +/ { @@ -113697,67 +97486,22 @@ index 0000000000000000000000000000000000000000..d33d462b4090e4a4f967a37212918b9c + sd_overclock = <&mmc>,"brcm,overclock-50:0"; + }; +}; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi +diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..f5a44cd4fef0ee221ed6ae1c43ca81dabffa110d +index 0000000000000000000000000000000000000000..46cf8602c3b96e477b05b57dbfe5e349930c9d9a --- /dev/null -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -0,0 +1,40 @@ -+#include "bcm2708_common.dtsi" ++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi +@@ -0,0 +1,109 @@ ++/* Downstream version of bcm2835-rpi.dtsi */ ++ ++#include + +/ { -+ compatible = "brcm,bcm2708"; -+ model = "BCM2708"; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; ++ memory { ++ device_type = "memory"; ++ reg = <0x0 0x0>; + }; + -+ soc { -+ ranges = <0x7e000000 0x20000000 0x01000000>; -+ -+ timer@7e003000 { -+ compatible = "brcm,bcm2835-system-timer"; -+ reg = <0x7e003000 0x1000>; -+ interrupts = <1 0>, <1 1>, <1 2>, <1 3>; -+ clock-frequency = <1000000>; -+ }; -+ -+ arm-pmu { -+ compatible = "arm,arm1176-pmu"; -+ }; -+ -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ status = "okay"; -+ }; -+ }; -+}; -+ -+&intc { -+ compatible = "brcm,bcm2835-armctrl-ic"; -+}; -+ -+&watchdog { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de13b5717ef ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -0,0 +1,436 @@ -+#include "dt-bindings/clock/bcm2835.h" -+#include -+#include "dt-bindings/power/raspberrypi-power.h" -+#include "dt-bindings/gpio/gpio.h" -+#include "skeleton.dtsi" -+ -+/ { -+ interrupt-parent = <&intc>; -+ + aliases { + audio = &audio; + aux = &aux; @@ -113771,7 +97515,7 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + gpio = &gpio; + uart0 = &uart0; + sdhost = &sdhost; -+ i2s = &i2s; ++ i2s = &i2s; + spi0 = &spi0; + i2c0 = &i2c0; + uart1 = &uart1; @@ -113785,333 +97529,16 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + fb = &fb; + vchiq = &vchiq; + thermal = &thermal; -+ clocks = &clocks; + }; + -+ soc: soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; ++ leds: leds { ++ compatible = "gpio-leds"; ++ }; + -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ reg = <0x7e007000 0xf00>; -+ interrupts = <1 16>, -+ <1 17>, -+ <1 18>, -+ <1 19>, -+ <1 20>, -+ <1 21>, -+ <1 22>, -+ <1 23>, -+ <1 24>, -+ <1 25>, -+ <1 26>, -+ /* dma channel 11-14 share one irq */ -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ /* unused shared irq for all channels */ -+ <1 28>; -+ interrupt-names = "dma0", -+ "dma1", -+ "dma2", -+ "dma3", -+ "dma4", -+ "dma5", -+ "dma6", -+ "dma7", -+ "dma8", -+ "dma9", -+ "dma10", -+ "dma11", -+ "dma12", -+ "dma13", -+ "dma14", -+ "dma-shared-all"; -+ -+ #dma-cells = <1>; -+ brcm,dma-channel-mask = <0x7f34>; -+ }; -+ -+ intc: interrupt-controller@7e00b200 { -+#ifdef RPI364 -+ compatible = "brcm,bcm2835-armctrl-ic", "brcm,bcm2708-armctrl-ic"; -+#else -+ compatible = "brcm,bcm2708-armctrl-ic"; -+#endif -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ mailbox: mailbox@7e00b800 { -+ compatible = "brcm,bcm2835-mbox"; -+ reg = <0x7e00b880 0x40>; -+ interrupts = <0 1>; -+ #mbox-cells = <0>; -+ }; -+ -+ watchdog: watchdog@7e100000 { -+ compatible = "brcm,bcm2835-pm-wdt"; -+ reg = <0x7e100000 0x28>; -+ status = "disabled"; -+ }; -+ -+ cprman: cprman@7e101000 { -+ compatible = "brcm,bcm2835-cprman"; -+ #clock-cells = <1>; -+ reg = <0x7e101000 0x2000>; -+ -+ /* CPRMAN derives everything from the platform's -+ * oscillator. -+ */ -+ clocks = <&clk_osc>; -+ }; -+ -+ random: rng@7e104000 { -+ compatible = "brcm,bcm2835-rng"; -+ reg = <0x7e104000 0x10>; -+ status = "disabled"; -+ }; -+ -+ gpio: gpio@7e200000 { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ uart0: serial@7e201000 { -+ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; -+ reg = <0x7e201000 0x1000>; -+ interrupts = <2 25>; -+ clocks = <&cprman BCM2835_CLOCK_UART>, -+ <&cprman BCM2835_CLOCK_VPU>; -+ clock-names = "uartclk","apb_pclk"; -+ arm,primecell-periphid = <0x00241011>; // For an explanation, see -+ // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 -+ status = "disabled"; -+ }; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ interrupts = <2 24>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ dmas = <&dma 13>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ brcm,pio-limit = <1>; -+ status = "disabled"; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2835-i2s"; -+ #sound-dai-cells = <0>; -+ reg = <0x7e203000 0x24>; -+ clocks = <&cprman BCM2835_CLOCK_PCM>; -+ -+ dmas = <&dma 2>, <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2835-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ /* the dma channels */ -+ dmas = <&dma 6>, <&dma 7>; -+ dma-names = "tx", "rx"; -+ /* the chipselects used - <0> means native GPIO -+ * add more gpios if necessary as <&gpio 6 1> -+ * (but do not forget to make them output!) -+ */ -+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pixelvalve0: pixelvalve@7e206000 { -+ compatible = "brcm,bcm2835-pixelvalve0"; -+ reg = <0x7e206000 0x100>; -+ status = "disabled"; -+ }; -+ -+ dpi: dpi@7e208000 { -+ compatible = "brcm,bcm2835-dpi"; -+ reg = <0x7e208000 0x8c>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>, -+ <&cprman BCM2835_CLOCK_DPI>; -+ clock-names = "core", "pixel"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pixelvalve1: pixelvalve@7e207000 { -+ compatible = "brcm,bcm2835-pixelvalve1"; -+ reg = <0x7e207000 0x100>; -+ status = "disabled"; -+ }; -+ -+ pwm: pwm@7e20c000 { -+ compatible = "brcm,bcm2835-pwm"; -+ reg = <0x7e20c000 0x28>; -+ clocks = <&cprman BCM2835_CLOCK_PWM>; -+ assigned-clocks = <&cprman BCM2835_CLOCK_PWM>; -+ assigned-clock-rates = <10000000>; -+ #pwm-cells = <2>; -+ status = "disabled"; -+ }; -+ -+ aux: aux@0x7e215000 { -+ compatible = "brcm,bcm2835-aux"; -+ #clock-cells = <1>; -+ reg = <0x7e215000 0x8>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ }; -+ -+ uart1: serial@7e215040 { -+ compatible = "brcm,bcm2835-aux-uart"; -+ reg = <0x7e215040 0x40>; -+ interrupts = <1 29>; -+ clocks = <&aux BCM2835_AUX_CLOCK_UART>; -+ status = "disabled"; -+ }; -+ -+ spi1: spi@7e215080 { -+ compatible = "brcm,bcm2835-aux-spi"; -+ reg = <0x7e215080 0x40>; -+ interrupts = <1 29>; -+ clocks = <&aux BCM2835_AUX_CLOCK_SPI1>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ spi2: spi@7e2150C0 { -+ compatible = "brcm,bcm2835-aux-spi"; -+ reg = <0x7e2150C0 0x40>; -+ interrupts = <1 29>; -+ clocks = <&aux BCM2835_AUX_CLOCK_SPI2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&cprman BCM2835_CLOCK_EMMC>; -+ dmas = <&dma 11>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ status = "disabled"; -+ }; -+ -+ hvs: hvs@7e400000 { -+ compatible = "brcm,bcm2835-hvs"; -+ reg = <0x7e400000 0x6000>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c2: i2c@7e805000 { -+ // Beware - this is shared with the HDMI module. -+ // Careless use may break (really) your display. -+ // Caveat emptor. -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e805000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&cprman BCM2835_CLOCK_VPU>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ smi: smi@7e600000 { -+ compatible = "brcm,bcm2835-smi"; -+ reg = <0x7e600000 0x100>; -+ interrupts = <2 16>; -+ clocks = <&cprman BCM2835_CLOCK_SMI>; -+ assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; -+ assigned-clock-rates = <125000000>; -+ dmas = <&dma 4>; -+ dma-names = "rx-tx"; -+ status = "disabled"; -+ }; -+ -+ pixelvalve2: pixelvalve@7e807000 { -+ compatible = "brcm,bcm2835-pixelvalve2"; -+ reg = <0x7e807000 0x100>; -+ status = "disabled"; -+ }; -+ -+ hdmi: hdmi@7e902000 { -+ compatible = "brcm,bcm2835-hdmi"; -+ reg = <0x7e902000 0x600>, -+ <0x7e808000 0x100>; -+ ddc = <&i2c2>; -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; -+ clocks = <&cprman BCM2835_PLLH_PIX>, -+ <&cprman BCM2835_CLOCK_HSM>; -+ clock-names = "pixel", "hdmi"; -+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>; -+ status = "disabled"; -+ }; -+ -+#ifdef RPI364 -+ usb: usb@7e980000 { -+ compatible = "brcm,bcm2835-usb"; -+ reg = <0x7e980000 0x10000>; -+ interrupts = <1 9>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+#else -+ usb: usb@7e980000 { -+ compatible = "brcm,bcm2708-usb"; -+ reg = <0x7e980000 0x10000>, -+ <0x7e006000 0x1000>; -+ interrupts = <2 0>, -+ <1 9>; -+ }; -+#endif -+ -+ v3d: v3d@7ec00000 { -+ compatible = "brcm,vc4-v3d"; -+ reg = <0x7ec00000 0x1000>; -+ status = "disabled"; ++ soc { ++ gpiomem { ++ compatible = "brcm,bcm2835-gpiomem"; ++ reg = <0x7e200000 0x1000>; + }; + + firmware: firmware { @@ -114125,10 +97552,6 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + #power-domain-cells = <1>; + }; + -+ leds: leds { -+ compatible = "gpio-leds"; -+ }; -+ + fb: fb { + compatible = "brcm,bcm2708-fb"; + firmware = <&firmware>; @@ -114148,11 +97571,6 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + firmware = <&firmware>; + }; + -+ gpu: gpu { -+ compatible = "brcm,bcm2835-vc4"; -+ status = "disabled"; -+ }; -+ + /* Onboard audio */ + audio: audio { + compatible = "brcm,bcm2835-audio"; @@ -114164,39 +97582,58 @@ index 0000000000000000000000000000000000000000..6081b2aeb7ab1e1821506bcb93d36de1 + sound: sound { + status = "disabled"; + }; -+ }; + -+ clocks: clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* The oscillator is the root of the clock tree. */ -+ clk_osc: clock@6 { -+ compatible = "fixed-clock"; -+ reg = <6>; -+ #clock-cells = <0>; -+ clock-output-names = "osc"; -+ clock-frequency = <19200000>; -+ }; + }; + + __overrides__ { + cache_line_size = <&vchiq>, "cache-line-size:0"; + }; +}; ++ ++&dma { ++ brcm,dma-channel-mask = <0x7f34>; ++}; ++ ++&hdmi { ++ power-domains = <&power RPI_POWER_DOMAIN_HDMI>; ++}; ++ ++&usb { ++ power-domains = <&power RPI_POWER_DOMAIN_USB>; ++}; +diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi +new file mode 100644 +index 0000000000000000000000000000000000000000..0f72bd90c591a2e8752d7437fa7e8c6308bd8c3f +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708.dtsi +@@ -0,0 +1,16 @@ ++#include "bcm2835.dtsi" ++#include "bcm270x.dtsi" ++#include "bcm2708-rpi.dtsi" ++ ++/ { ++ soc { ++ timer@7e003000 { ++ compatible = "brcm,bcm2835-system-timer"; ++ reg = <0x7e003000 0x1000>; ++ interrupts = <1 0>, <1 1>, <1 2>, <1 3>; ++ clock-frequency = <1000000>; ++ }; ++ }; ++ ++ /delete-node/ cpus; ++}; diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..74fe4cc1d667e9508ca860bcc8c837fed0cbb855 +index 0000000000000000000000000000000000000000..19c83823420fc3cc20a01d07091100cb8720ff4d --- /dev/null +++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,162 @@ +@@ -0,0 +1,156 @@ +/dts-v1/; + +#include "bcm2709.dtsi" + +/ { -+ compatible = "brcm,bcm2709"; + model = "Raspberry Pi 2 Model B"; +}; + @@ -114291,15 +97728,10 @@ index 0000000000000000000000000000000000000000..74fe4cc1d667e9508ca860bcc8c837fe +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -114355,118 +97787,185 @@ index 0000000000000000000000000000000000000000..74fe4cc1d667e9508ca860bcc8c837fe +}; diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..a8cfd7c4df5bcf7692d13882833c97852649932d +index 0000000000000000000000000000000000000000..343437db94820bb75a9b81e8bc6ecf6f31d9f04c --- /dev/null +++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -0,0 +1,102 @@ -+#include "bcm2708_common.dtsi" +@@ -0,0 +1,22 @@ ++#include "bcm2836.dtsi" ++#include "bcm270x.dtsi" ++#include "bcm2708-rpi.dtsi" + +/ { -+ compatible = "brcm,bcm2709"; -+ model = "BCM2709"; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; -+ + soc { + ranges = <0x7e000000 0x3f000000 0x01000000>, + <0x40000000 0x40000000 0x00040000>; + -+ local_intc: local_intc { -+ compatible = "brcm,bcm2836-l1-intc"; -+ reg = <0x40000000 0x100>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ interrupt-parent = <&local_intc>; -+ }; -+ -+ arm-pmu { -+ compatible = "arm,cortex-a7-pmu"; -+ interrupt-parent = <&local_intc>; -+ interrupts = <9>; -+ }; -+ -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ status = "okay"; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ clock-frequency = <19200000>; -+ interrupt-parent = <&local_intc>; -+ interrupts = <0>, // PHYS_SECURE_PPI -+ <1>, // PHYS_NONSECURE_PPI -+ <3>, // VIRT_PPI -+ <2>; // HYP_PPI -+ always-on; -+ }; -+ + syscon@40000000 { + compatible = "brcm,bcm2836-arm-local", "syscon"; + reg = <0x40000000 0x100>; + }; + }; + -+ cpus: cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ v7_cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf00>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf01>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf02>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf03>; -+ clock-frequency = <800000000>; -+ }; -+ }; -+ + __overrides__ { + arm_freq = <&v7_cpu0>, "clock-frequency:0", -+ <&v7_cpu1>, "clock-frequency:0", -+ <&v7_cpu2>, "clock-frequency:0", -+ <&v7_cpu3>, "clock-frequency:0"; ++ <&v7_cpu1>, "clock-frequency:0", ++ <&v7_cpu2>, "clock-frequency:0", ++ <&v7_cpu3>, "clock-frequency:0"; + }; +}; +diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi +new file mode 100644 +index 0000000000000000000000000000000000000000..a46cb4a8b1419edd95e0e07c18b0f373222dc2bf +--- /dev/null ++++ b/arch/arm/boot/dts/bcm270x.dtsi +@@ -0,0 +1,141 @@ ++/* Downstream bcm283x.dtsi diff */ ++#include "dt-bindings/power/raspberrypi-power.h" + -+&watchdog { -+ status = "okay"; -+}; ++/ { ++ chosen { ++ bootargs = ""; ++ }; + -+&intc { -+ compatible = "brcm,bcm2836-armctrl-ic"; -+ interrupt-parent = <&local_intc>; -+ interrupts = <8>; ++ soc: soc { ++ ++ /delete-node/ timer@7e003000; ++ ++ watchdog: watchdog@7e100000 { ++ /* Add alias */ ++ }; ++ ++ cprman: cprman@7e101000 { ++ /* Add alias */ ++ }; ++ ++ random: rng@7e104000 { ++ /* Add alias */ ++ }; ++ ++ gpio@7e200000 { /* gpio */ ++ interrupts = <2 17>, <2 18>; ++ }; ++ ++ sdhost: sdhost@7e202000 { ++ compatible = "brcm,bcm2835-sdhost"; ++ reg = <0x7e202000 0x100>; ++ interrupts = <2 24>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>; ++ dmas = <&dma 13>; ++ dma-names = "rx-tx"; ++ brcm,overclock-50 = <0>; ++ brcm,pio-limit = <1>; ++ status = "disabled"; ++ }; ++ ++ i2s@7e203000 { /* i2s */ ++ #sound-dai-cells = <0>; ++ reg = <0x7e203000 0x24>; ++ clocks = <&clocks BCM2835_CLOCK_PCM>; ++ }; ++ ++ spi0: spi@7e204000 { ++ /* Add alias */ ++ dmas = <&dma 6>, <&dma 7>; ++ dma-names = "tx", "rx"; ++ }; ++ ++ pixelvalve0: pixelvalve@7e206000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ pixelvalve1: pixelvalve@7e207000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ dpi: dpi@7e208000 { ++ compatible = "brcm,bcm2835-dpi"; ++ reg = <0x7e208000 0x8c>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>, ++ <&clocks BCM2835_CLOCK_DPI>; ++ clock-names = "core", "pixel"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ /delete-node/ sdhci@7e300000; ++ ++ mmc: mmc@7e300000 { ++ compatible = "brcm,bcm2835-mmc"; ++ reg = <0x7e300000 0x100>; ++ interrupts = <2 30>; ++ clocks = <&clocks BCM2835_CLOCK_EMMC>; ++ dmas = <&dma 11>; ++ dma-names = "rx-tx"; ++ brcm,overclock-50 = <0>; ++ status = "disabled"; ++ }; ++ ++ hvs: hvs@7e400000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ firmwarekms: firmwarekms@7e600000 { ++ compatible = "raspberrypi,rpi-firmware-kms"; ++ /* SMI interrupt reg */ ++ reg = <0x7e600000 0x100>; ++ interrupts = <2 16>; ++ brcm,firmware = <&firmware>; ++ status = "disabled"; ++ }; ++ ++ smi: smi@7e600000 { ++ compatible = "brcm,bcm2835-smi"; ++ reg = <0x7e600000 0x100>; ++ interrupts = <2 16>; ++ clocks = <&clocks BCM2835_CLOCK_SMI>; ++ assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; ++ assigned-clock-rates = <125000000>; ++ dmas = <&dma 4>; ++ dma-names = "rx-tx"; ++ status = "disabled"; ++ }; ++ ++ pixelvalve2: pixelvalve@7e807000 { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ ++ hdmi@7e902000 { /* hdmi */ ++ status = "disabled"; ++ }; ++ ++ usb@7e980000 { /* usb */ ++ compatible = "brcm,bcm2708-usb"; ++ reg = <0x7e980000 0x10000>, ++ <0x7e006000 0x1000>; ++ interrupts = <2 0>, ++ <1 9>; ++ }; ++ ++ v3d@7ec00000 { /* vd3 */ ++ compatible = "brcm,vc4-v3d"; ++ power-domains = <&power RPI_POWER_DOMAIN_V3D>; ++ status = "disabled"; ++ }; ++ ++ gpu: gpu { ++ /* Add alias */ ++ status = "disabled"; ++ }; ++ }; +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc221f99953d +index 0000000000000000000000000000000000000000..12764a3495b2372ffaf47e32ea0d21326ca83686 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -0,0 +1,213 @@ +@@ -0,0 +1,203 @@ +/dts-v1/; + +#ifdef RPI364 @@ -114476,7 +97975,6 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 +#include "bcm2710.dtsi" + +/ { -+ compatible = "brcm,bcm2710","brcm,bcm2709"; + model = "Raspberry Pi 3 Model B"; +}; + @@ -114622,15 +98120,10 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -114639,10 +98132,6 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 + }; +}; + -+&hdmi { -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; -+}; -+ +&audio { + pinctrl-names = "default"; + pinctrl-0 = <&audio_pins>; @@ -114682,24 +98171,22 @@ index 0000000000000000000000000000000000000000..d9ae00f95e6261eea582d7a2c6dfbc22 +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts new file mode 100644 -index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540cfea71886 +index 0000000000000000000000000000000000000000..41874c25a84226c0e4af92ec4059e0a571fe6123 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -0,0 +1,162 @@ +@@ -0,0 +1,155 @@ +/dts-v1/; + +#include "bcm2710.dtsi" + +/ { -+ compatible = "brcm,bcm2710","brcm,bcm2709"; + model = "Raspberry Pi Compute Module 3"; +}; + +&gpio { -+ -+ mmc_pins: mmc_pins { ++ sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; -+ brcm,function = <7>; /* alt3 */ ++ brcm,function = <4>; /* alt0 */ + brcm,pull = <0 2 2 2 2 2>; + }; + @@ -114734,9 +98221,9 @@ index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540c + }; +}; + -+&mmc { ++&sdhost { + pinctrl-names = "default"; -+ pinctrl-0 = <&mmc_pins>; ++ pinctrl-0 = <&sdhost_pins>; + non-removable; + bus-width = <4>; + status = "okay"; @@ -114796,15 +98283,10 @@ index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540c +}; + +&i2s { -+ #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + -+&random { -+ status = "okay"; -+}; -+ +&leds { + act_led: act { + label = "led0"; @@ -114850,27 +98332,22 @@ index 0000000000000000000000000000000000000000..20388084b98cf942529eb60c55dc540c +}; diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..223bd9627b3dcaac5458909dc59c877eed751ce4 +index 0000000000000000000000000000000000000000..f6def5d7e5d622cf09e8f87332c7374fe28da08b --- /dev/null +++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -0,0 +1,165 @@ -+#include "bcm2708_common.dtsi" +@@ -0,0 +1,155 @@ ++#include "bcm283x.dtsi" ++#include "bcm270x.dtsi" ++#include "bcm2708-rpi.dtsi" + +/ { -+ compatible = "brcm,bcm2710","brcm,bcm2709"; -+ model = "BCM2710"; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; ++ compatible = "brcm,bcm2837", "brcm,bcm2836"; ++ model = "BCM2837"; + + soc { + ranges = <0x7e000000 0x3f000000 0x01000000>, + <0x40000000 0x40000000 0x00040000>; -+#ifdef RPI364 + dma-ranges = <0xc0000000 0x00000000 0x3f000000>; -+#endif + + local_intc: local_intc { + compatible = "brcm,bcm2836-l1-intc"; @@ -114890,19 +98367,12 @@ index 0000000000000000000000000000000000000000..223bd9627b3dcaac5458909dc59c877e + interrupts = <9>; + }; + -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ status = "okay"; -+ }; -+ + timer { +#ifdef RPI364 + compatible = "arm,armv8-timer", "arm,armv7-timer"; +#else + compatible = "arm,armv7-timer"; +#endif -+ clock-frequency = <19200000>; + interrupt-parent = <&local_intc>; + interrupts = <0>, // PHYS_SECURE_PPI + <1>, // PHYS_NONSECURE_PPI @@ -115007,276 +98477,137 @@ index 0000000000000000000000000000000000000000..223bd9627b3dcaac5458909dc59c877e +#endif +}; + -+&watchdog { -+ status = "okay"; -+}; -+ +&intc { + compatible = "brcm,bcm2836-armctrl-ic"; -+#ifdef RPI364 + reg = <0x7e00b200 0x200>; -+#endif + interrupt-parent = <&local_intc>; + interrupts = <8>; +}; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dts b/arch/arm/boot/dts/bcm2835-rpi-cm.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..c6e6860a6d4356a613f4f7ab41c6befc76740a15 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2835-rpi-cm.dts -@@ -0,0 +1,93 @@ -+/dts-v1/; + -+#include "bcm2835-rpi-cm.dtsi" -+ -+/ { -+ model = "Raspberry Pi Compute Module"; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&gpio { -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; -+ }; -+ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; -+ }; -+ -+ i2s_pins: i2s { -+ brcm,pins = <18 19 20 21>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -+ -+/ { -+ __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; -+ uart1_clkrate = <&uart1>,"clock-frequency:0"; -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ i2c2_iknowwhatimdoing = <&i2c2>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; -+ i2c2_baudrate = <&i2c2>,"clock-frequency:0"; -+ core_freq = <&clk_core>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..9c4000fc686a9882b9ddde24fdcf937d52b0f86f ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -@@ -0,0 +1,30 @@ -+#include "bcm2835.dtsi" -+ -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 47 0>; -+ }; -+}; -+ -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ -+&fb { -+ status = "okay"; -+}; -+ -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; -+ }; ++#ifdef RPI364 ++&usb { ++ compatible = "brcm,bcm2835-usb"; ++ reg = <0x7e980000 0x10000>; ++ interrupts = <1 9>; +}; ++#endif diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..b6ed1a3c06a7a67d1dd79bb7e55421d8eccba492 +index 0000000000000000000000000000000000000000..11dba31712840a9e4b91acd4565c2d6266315273 --- /dev/null +++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,111 @@ -+ifeq ($(CONFIG_OF),y) -+ +@@ -0,0 +1,105 @@ +# Overlays for the Raspberry Pi platform + -+ifeq ($(CONFIG_ARCH_BCM2708),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2709),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif -+ -+dtbo-$(RPI_DT_OVERLAYS) += adau1977-adc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += ads1015.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += ads7846.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += allo-piano-dac-pcm512x-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += audremap.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dionaudio-loco.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dpi18.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-amp.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacplus.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi-pro.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += iqaudio-digi-wm8804-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp23s17.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mz61581.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pi3-act-led.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pi3-disable-bt.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pi3-miniuart-bt.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += piscreen.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pps-gpio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pwm.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pwm-2chan.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += qca7000.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += raspidac3.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-backlight.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-dac.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-display.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-ft5406.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-proto.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rpi-sense.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += rra-digidac1-wm8741-audio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sc16is750-i2c.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sc16is752-spi1.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi0-hw-cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += vga666.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += w1-gpio.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += w1-gpio-pullup.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += wittypi.dtbo ++dtbo-$(CONFIG_ARCH_BCM2835) += \ ++ adau1977-adc.dtbo \ ++ ads1015.dtbo \ ++ ads7846.dtbo \ ++ akkordion-iqdacplus.dtbo \ ++ allo-piano-dac-pcm512x-audio.dtbo \ ++ at86rf233.dtbo \ ++ audioinjector-wm8731-audio.dtbo \ ++ audremap.dtbo \ ++ bmp085_i2c-sensor.dtbo \ ++ dht11.dtbo \ ++ dionaudio-loco.dtbo \ ++ dpi18.dtbo \ ++ dpi24.dtbo \ ++ dwc-otg.dtbo \ ++ dwc2.dtbo \ ++ enc28j60.dtbo \ ++ enc28j60-spi2.dtbo \ ++ gpio-ir.dtbo \ ++ gpio-poweroff.dtbo \ ++ hifiberry-amp.dtbo \ ++ hifiberry-dac.dtbo \ ++ hifiberry-dacplus.dtbo \ ++ hifiberry-digi.dtbo \ ++ hifiberry-digi-pro.dtbo \ ++ hy28a.dtbo \ ++ hy28b.dtbo \ ++ i2c-bcm2708.dtbo \ ++ i2c-gpio.dtbo \ ++ i2c-mux.dtbo \ ++ i2c-pwm-pca9685a.dtbo \ ++ i2c-rtc.dtbo \ ++ i2c-sensor.dtbo \ ++ i2c0-bcm2708.dtbo \ ++ i2c1-bcm2708.dtbo \ ++ i2s-gpio28-31.dtbo \ ++ iqaudio-dac.dtbo \ ++ iqaudio-dacplus.dtbo \ ++ iqaudio-digi-wm8804-audio.dtbo \ ++ justboom-dac.dtbo \ ++ justboom-digi.dtbo \ ++ lirc-rpi.dtbo \ ++ mcp23017.dtbo \ ++ mcp23s17.dtbo \ ++ mcp2515-can0.dtbo \ ++ mcp2515-can1.dtbo \ ++ midi-uart0.dtbo \ ++ mmc.dtbo \ ++ mz61581.dtbo \ ++ pi3-act-led.dtbo \ ++ pi3-disable-bt.dtbo \ ++ pi3-miniuart-bt.dtbo \ ++ piscreen.dtbo \ ++ piscreen2r.dtbo \ ++ pisound.dtbo \ ++ pitft22.dtbo \ ++ pitft28-capacitive.dtbo \ ++ pitft28-resistive.dtbo \ ++ pitft35-resistive.dtbo \ ++ pps-gpio.dtbo \ ++ pwm.dtbo \ ++ pwm-2chan.dtbo \ ++ qca7000.dtbo \ ++ raspidac3.dtbo \ ++ rpi-backlight.dtbo \ ++ rpi-dac.dtbo \ ++ rpi-display.dtbo \ ++ rpi-ft5406.dtbo \ ++ rpi-proto.dtbo \ ++ rpi-sense.dtbo \ ++ rra-digidac1-wm8741-audio.dtbo \ ++ sc16is750-i2c.dtbo \ ++ sc16is752-spi1.dtbo \ ++ sdhost.dtbo \ ++ sdio.dtbo \ ++ sdio-1bit.dtbo \ ++ sdtweak.dtbo \ ++ smi.dtbo \ ++ smi-dev.dtbo \ ++ smi-nand.dtbo \ ++ spi-gpio35-39.dtbo \ ++ spi-rtc.dtbo \ ++ spi0-hw-cs.dtbo \ ++ spi1-1cs.dtbo \ ++ spi1-2cs.dtbo \ ++ spi1-3cs.dtbo \ ++ spi2-1cs.dtbo \ ++ spi2-2cs.dtbo \ ++ spi2-3cs.dtbo \ ++ tinylcd35.dtbo \ ++ uart1.dtbo \ ++ vc4-fkms-v3d.dtbo \ ++ vc4-kms-v3d.dtbo \ ++ vga666.dtbo \ ++ w1-gpio.dtbo \ ++ w1-gpio-pullup.dtbo \ ++ wittypi.dtbo + +targets += dtbs dtbs_install +targets += $(dtbo-y) + -+endif -+ +always := $(dtbo-y) +clean-files := *.dtbo diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README new file mode 100644 -index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a08679298b26 +index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9f5c392bd --- /dev/null +++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,1302 @@ +@@ -0,0 +1,1368 @@ +Introduction +============ + @@ -115340,7 +98671,7 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + dtoverlay=lirc-rpi + -+This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By ++This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By +default it will use GPIOs 17 (out) and 18 (in), but this can be modified using +DT parameters: + @@ -115562,8 +98893,7 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + +Name: bmp085_i2c-sensor -+Info: Configures the BMP085/BMP180 digital barometric pressure and temperature -+ sensors from Bosch Sensortec ++Info: This overlay is now deprecated - see i2c-sensor +Load: dtoverlay=bmp085_i2c-sensor +Params: + @@ -115623,13 +98953,21 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + +Name: enc28j60 -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) ++Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI0 +Load: dtoverlay=enc28j60,= +Params: int_pin GPIO used for INT (default 25) + + speed SPI bus speed (default 12000000) + + ++Name: enc28j60-spi2 ++Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI2 ++Load: dtoverlay=enc28j60-spi2,= ++Params: int_pin GPIO used for INT (default 39) ++ ++ speed SPI bus speed (default 12000000) ++ ++ +Name: gpio-ir +Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- + based gpio_ir_recv driver maps received keys directly to a @@ -115742,6 +99080,12 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + ledgpio GPIO used to control backlight + + ++Name: i2c-bcm2708 ++Info: Fall back to the i2c_bcm2708 driver for the i2c_arm bus. ++Load: dtoverlay=i2c-bcm2708 ++Params: ++ ++ +Name: i2c-gpio +Info: Adds support for software i2c controller on gpio pins +Load: dtoverlay=i2c-gpio,= @@ -115777,7 +99121,11 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 +Name: i2c-rtc +Info: Adds support for a number of I2C Real Time Clock devices +Load: dtoverlay=i2c-rtc,= -+Params: ds1307 Select the DS1307 device ++Params: abx80x Select one of the ABx80x family: ++ AB0801, AB0803, AB0804, AB0805, ++ AB1801, AB1803, AB1804, AB1805 ++ ++ ds1307 Select the DS1307 device + + ds1339 Select the DS1339 device + @@ -115793,12 +99141,25 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + + pcf8563 Select the PCF8563 device + -+ trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) ++ trickle-diode-type Diode type for trickle charge - "standard" or ++ "schottky" (ABx80x only) ++ ++ trickle-resistor-ohms Resistor value for trickle charge (DS1339, ++ ABx80x) + + wakeup-source Specify that the RTC can be used as a wakeup + source + + ++Name: i2c-sensor ++Info: Adds support for a number of I2C barometric pressure and temperature ++ sensors on i2c_arm ++Load: dtoverlay=i2c-sensor,= ++Params: bmp085 Select the Bosch sensortronic BMP085 ++ ++ bmp280 Select the Bosch sensortronic BMP280 ++ ++ +Name: i2c0-bcm2708 +Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations + are usable on all platforms. @@ -115982,6 +99343,13 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + interrupt GPIO for interrupt signal + + ++Name: midi-uart0 ++Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets ++ 31.25kbaud, the frequency required for MIDI ++Load: dtoverlay=midi-uart0 ++Params: ++ ++ +Name: mmc +Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock +Load: dtoverlay=mmc,= @@ -116081,6 +99449,12 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + xohms Touchpanel sensitivity (X-plate resistance) + + ++Name: pisound ++Info: Configures the Blokas Labs pisound card ++Load: dtoverlay=pisound ++Params: ++ ++ +Name: pitft22 +Info: Adafruit PiTFT 2.2" screen +Load: dtoverlay=pitft22,= @@ -116127,6 +99501,18 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + debug Debug output level {0-7} + + ++Name: pitft35-resistive ++Info: Adafruit PiTFT 3.5" resistive touch screen ++Load: dtoverlay=pitft35-resistive,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ +Name: pps-gpio +Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). +Load: dtoverlay=pps-gpio,= @@ -116508,6 +99894,17 @@ index 0000000000000000000000000000000000000000..1ebb94c005d68b17792f95bd9792a086 + rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15) + + ++Name: vc4-fkms-v3d ++Info: Enable Eric Anholt's DRM VC4 V3D driver on top of the dispmanx ++ display stack. ++Load: dtoverlay=vc4-fkms-v3d, ++Params: cma-256 CMA is 256MB, 256MB-aligned (needs 1GB) ++ cma-192 CMA is 192MB, 256MB-aligned (needs 1GB) ++ cma-128 CMA is 128MB, 128MB-aligned ++ cma-96 CMA is 96MB, 128MB-aligned ++ cma-64 CMA is 64MB, 64MB-aligned ++ ++ +Name: vc4-kms-v3d +Info: Enable Eric Anholt's DRM VC4 HDMI/HVS/V3D driver. Running startx or + booting to GUI while this overlay is in use will cause interesting @@ -117395,6 +100792,59 @@ index 0000000000000000000000000000000000000000..db8a8feed94c010e368065fdd88b0286 + speed = <ð1>, "spi-max-frequency:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..946c9d2107a83335b11f094e75945a509595ab7c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts +@@ -0,0 +1,47 @@ ++// Overlay for the Microchip ENC28J60 Ethernet Controller - SPI2 Compute Module ++// Interrupt pin: 39 ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&spi2>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ ++ eth1: enc28j60@0{ ++ compatible = "microchip,enc28j60"; ++ reg = <0>; /* CE0 */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð1_pins>; ++ interrupt-parent = <&gpio>; ++ interrupts = <39 0x2>; /* falling edge */ ++ spi-max-frequency = <12000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ eth1_pins: eth1_pins { ++ brcm,pins = <39>; ++ brcm,function = <0>; /* in */ ++ brcm,pull = <0>; /* none */ ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ int_pin = <ð1>, "interrupts:0", ++ <ð1_pins>, "brcm,pins:0"; ++ speed = <ð1>, "spi-max-frequency:0"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..af5baf7ddc92be7a59ad3d5f9a9fefba915bed05 @@ -117977,6 +101427,25 @@ index 0000000000000000000000000000000000000000..8018aebde8e557f45ffd63eb86f6c7a1 + <&hy28b_pins>, "brcm,pins:2"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..0afc6b405414c97428278dd3e8836759092aedb5 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ compatible = "brcm,bcm2708-i2c"; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..b72b32e936774d901bc253b06e025c2dd48bdb1b @@ -118205,10 +101674,10 @@ index 0000000000000000000000000000000000000000..d1ffd2326669e46ad68939f94713cc99 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194fa3462435 +index 0000000000000000000000000000000000000000..1efcf0b712c9c5c19210545002ac1f0931db58f5 --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -0,0 +1,73 @@ +@@ -0,0 +1,83 @@ +// Definitions for several I2C based Real Time Clocks +/dts-v1/; +/plugin/; @@ -118223,6 +101692,13 @@ index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194f + #size-cells = <0>; + status = "okay"; + ++ abx80x: abx80x@69 { ++ compatible = "abracon,abx80x"; ++ reg = <0x69>; ++ abracon,tc-diode = "standard"; ++ abracon,tc-resistor = <0>; ++ status = "disable"; ++ }; + ds1307: ds1307@68 { + compatible = "maxim,ds1307"; + reg = <0x68>; @@ -118267,6 +101743,7 @@ index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194f + }; + }; + __overrides__ { ++ abx80x = <&abx80x>,"status"; + ds1307 = <&ds1307>,"status"; + ds1339 = <&ds1339>,"status"; + ds3231 = <&ds3231>,"status"; @@ -118275,13 +101752,55 @@ index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194f + pcf2127 = <&pcf2127>,"status"; + pcf8523 = <&pcf8523>,"status"; + pcf8563 = <&pcf8563>,"status"; -+ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; ++ trickle-diode-type = <&abx80x>,"abracon,tc-diode"; ++ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0", ++ <&abx80x>,"abracon,tc-resistor"; + wakeup-source = <&ds1339>,"wakeup-source?", + <&ds3231>,"wakeup-source?", + <&mcp7940x>,"wakeup-source?", + <&mcp7941x>,"wakeup-source?"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..f6d134c095af2398fc55ae7d2b0e86456c30627c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +@@ -0,0 +1,34 @@ ++// Definitions for a few digital barometric pressure and temperature sensors ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ bmp085: bmp085@77 { ++ compatible = "bosch,bmp085"; ++ reg = <0x77>; ++ default-oversampling = <3>; ++ status = "disable"; ++ }; ++ ++ bmp280: bmp280@76 { ++ compatible = "bosch,bmp280"; ++ reg = <0x76>; ++ status = "disable"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ bmp085 = <&bmp085>,"status"; ++ bmp280 = <&bmp280>,"status"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..1f4fc7b570604a50ff6d3f6d676c3c4642d66b17 @@ -119683,6 +103202,48 @@ index 0000000000000000000000000000000000000000..67bd0d9bdaa2ff767d284010a69ecfe3 + interrupt = <&can1_pins>,"brcm,pins:0",<&can1>,"interrupts:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..565af7cf79d761877be3bd06191f31aabf9e1e9b +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts +@@ -0,0 +1,36 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 48MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 48000000*38400/31250 = 58982400 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target-path = "/clocks"; ++ __overlay__ { ++ midi_clk: midi_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart0_pclk"; ++ clock-frequency = <58982400>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart0>; ++ __overlay__ { ++ clocks = <&midi_clk>, ++ <&clocks BCM2835_CLOCK_VPU>; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/mmc-overlay.dts b/arch/arm/boot/dts/overlays/mmc-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..d32b02ca01ced5ab3de00d66d5412c8fda4bc510 @@ -120225,6 +103786,126 @@ index 0000000000000000000000000000000000000000..9c0bed893057b9129c8f16b0b695b85b + }; +}; + +diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae26019055 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts +@@ -0,0 +1,114 @@ ++/* ++ * pisound Linux kernel module. ++ * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound ++ * ++ * 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; version 2 of the ++ * License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "blokaslabs,pisound"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ ++ pinctrl-0 = <&pisound_button_pins>; ++ ++ osr-gpios = ++ <&gpio 13 GPIO_ACTIVE_HIGH>, ++ <&gpio 26 GPIO_ACTIVE_HIGH>, ++ <&gpio 16 GPIO_ACTIVE_HIGH>; ++ ++ reset-gpios = ++ <&gpio 12 GPIO_ACTIVE_HIGH>, ++ <&gpio 24 GPIO_ACTIVE_HIGH>; ++ ++ data_available-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; ++ ++ button-gpios = <&gpio 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pisound_button_pins>; ++ ++ pisound_button_pins: pisound_button_pins { ++ brcm,pins = <17>; ++ brcm,function = <0>; // Input ++ brcm,pull = <2>; // Pull-Up ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&spi0>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pisound_spi: pisound_spi@0{ ++ compatible = "blokaslabs,pisound-spi"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/pitft22-overlay.dts b/arch/arm/boot/dts/overlays/pitft22-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..894ba2292f6be76356f3ab39376d84ebd72fa29d @@ -120524,6 +104205,133 @@ index 0000000000000000000000000000000000000000..ed2afc2f7fd6528f4e6d75bb2d534307 + debug = <&pitft>,"debug:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..25cb5cc9576dadc3539f4ea3c9507c592ccac9d6 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts +@@ -0,0 +1,121 @@ ++/* ++ * Device Tree overlay for Adafruit PiTFT 3.5" resistive touch screen ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spidev0>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spidev1>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&gpio>; ++ __overlay__ { ++ pitft_pins: pitft_pins { ++ brcm,pins = <24 25>; ++ brcm,function = <0 1>; /* in out */ ++ brcm,pull = <2 0>; /* pullup none */ ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pitft: pitft@0{ ++ compatible = "himax,hx8357d"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pitft_pins>; ++ ++ spi-max-frequency = <32000000>; ++ rotate = <90>; ++ fps = <25>; ++ bgr; ++ buswidth = <8>; ++ dc-gpios = <&gpio 25 0>; ++ debug = <0>; ++ }; ++ ++ pitft_ts@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stmpe610"; ++ reg = <1>; ++ ++ spi-max-frequency = <500000>; ++ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ ++ interrupts = <24 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ interrupt-controller; ++ ++ stmpe_touchscreen { ++ compatible = "st,stmpe-ts"; ++ st,sample-time = <4>; ++ st,mod-12b = <1>; ++ st,ref-sel = <0>; ++ st,adc-freq = <2>; ++ st,ave-ctrl = <3>; ++ st,touch-det-delay = <4>; ++ st,settling = <2>; ++ st,fraction-z = <7>; ++ st,i-drive = <0>; ++ }; ++ ++ stmpe_gpio: stmpe_gpio { ++ #gpio-cells = <2>; ++ compatible = "st,stmpe-gpio"; ++ /* ++ * only GPIO2 is wired/available ++ * and it is wired to the backlight ++ */ ++ st,norequest-mask = <0x7b>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@5 { ++ target-path = "/soc"; ++ __overlay__ { ++ backlight { ++ compatible = "gpio-backlight"; ++ gpios = <&stmpe_gpio 2 0>; ++ default-on; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ speed = <&pitft>,"spi-max-frequency:0"; ++ rotate = <&pitft>,"rotate:0"; ++ fps = <&pitft>,"fps:0"; ++ debug = <&pitft>,"debug:0"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..50143a4bb215807ba0a0d0562f5827fa29a04de4 @@ -122381,6 +106189,101 @@ index 0000000000000000000000000000000000000000..fa73e1feaeb1bf53a6755e81a998e71c + rxd1_pin = <&uart1_pins>,"brcm,pins:4"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..95a595a35cb4fbb707bf4b18161f6a46860aa4ae +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts +@@ -0,0 +1,89 @@ ++/* ++ * vc4-fkms-v3d-overlay.dts ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target-path = "/chosen"; ++ __overlay__ { ++ bootargs = "cma=256M@256M"; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=192M@256M"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=128M@128M"; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=96M@128M"; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "/chosen"; ++ __dormant__ { ++ bootargs = "cma=64M@64M"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&fb>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&firmwarekms>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&v3d>; ++ __overlay__ { ++ interrupts = <1 10>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&gpu>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target-path = "/soc/dma"; ++ __overlay__ { ++ brcm,dma-channel-mask = <0x7f35>; ++ }; ++ }; ++ ++ __overrides__ { ++ cma-256 = <0>,"+0-1-2-3-4"; ++ cma-192 = <0>,"-0+1-2-3-4"; ++ cma-128 = <0>,"-0-1+2-3-4"; ++ cma-96 = <0>,"-0-1-2+3-4"; ++ cma-64 = <0>,"-0-1-2-3+4"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..4f1cc20f90dc6780f74e08ebee00e5a1a6062c85 @@ -122701,60 +106604,6 @@ index 0000000000000000000000000000000000000000..8498134fdbb3912e9ce18282b53084d8 + }; + +}; - -From 65b456a37c0916b6315fec653abcfd712656d6c3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 24 Aug 2016 16:28:44 +0100 -Subject: [PATCH 059/208] kbuild: Ignore dtco targets when filtering symbols - ---- - scripts/Kbuild.include | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include -index 179219845dfcdfbeb586d12c5ec1296095d9fbf4..e0743e44f84188667a0c322e8c3d36f18385dcd3 100644 ---- a/scripts/Kbuild.include -+++ b/scripts/Kbuild.include -@@ -284,7 +284,7 @@ ksym_dep_filter = \ - $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ - as_*_S|cpp_s_S) \ - $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ -- boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ -+ boot*|build*|*cpp_lds_S|dtc*|host*|vdso*) : ;; \ - *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ - esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' - - -From c648634cfedb6adbaf9e793e9fc1ba79dcf4bc9d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 13 Mar 2015 20:00:21 +0000 -Subject: [PATCH 060/208] BCM270X_DT: Add a .dtbo target, use for overlays - -Change the filenames and extensions to keep the pre-DDT style of -overlay (-overlay.dtb) distinct from new ones that use a -different style of local fixups (.dtbo), and to match other -platforms. - -The RPi firmware uses the DDTK trailer atom to choose which type of -overlay to use for each kernel. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/.gitignore | 2 +- - scripts/Makefile.dtbinst | 10 +++++++--- - scripts/Makefile.lib | 10 ++++++++++ - 3 files changed, 18 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore -index 3c79f85975aaa26c7c2e353fefc54d71d89bc5bf..eaaeb17e5986e5f7178b2851169444ac7e45be8d 100644 ---- a/arch/arm/boot/.gitignore -+++ b/arch/arm/boot/.gitignore -@@ -3,4 +3,4 @@ zImage - xipImage - bootpImage - uImage --*.dtb -+*.dtb* diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..ad8dc1c93d04bc929b551c5a47f67d244116c7e7 100644 --- a/scripts/Makefile.dtbinst @@ -122790,16 +106639,17 @@ index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..ad8dc1c93d04bc929b551c5a47f67d24 .PHONY: $(PHONY) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index 0a07f9014944ed92a8e2e42983ae43be60b3e471..b1513a7c175885137034b9f7225788c0a7c35027 100644 +index 0a07f9014944ed92a8e2e42983ae43be60b3e471..1967878a843461c3ff1f473b9a030eb01b7c726e 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -312,6 +312,16 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ +@@ -312,6 +312,17 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep,dtc) +quiet_cmd_dtco = DTCO $@ -+cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -+ $(objtree)/scripts/dtc/dtc -@ -O dtb -o $@ -b 0 \ ++cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \ ++ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ ++ $(DTC) -@ -H epapr -O dtb -o $@ -b 0 \ + -i $(dir $<) $(DTC_FLAGS) \ + -d $(depfile).dtc.tmp $(dtc-tmp) ; \ + cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) @@ -122811,39 +106661,10 @@ index 0a07f9014944ed92a8e2e42983ae43be60b3e471..b1513a7c175885137034b9f7225788c0 # Bzip2 -From c02bd18e6291de77eb37462f47ce78063975157f Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 8 Apr 2016 17:43:27 +0100 -Subject: [PATCH 061/208] BCM270X_DT: Don't generate "linux,phandle" props - -The EPAPR standard says to use "phandle" properties to store phandles, -rather than the deprecated "linux,phandle" version. By default, dtc -generates both, but adding "-H epapr" causes it to only generate -"phandle"s, saving some space and clutter. - -Signed-off-by: Phil Elwell ---- - scripts/Makefile.lib | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index b1513a7c175885137034b9f7225788c0a7c35027..1d949b7410600dd3b04a3acde8c41cfead15bfa4 100644 ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -314,7 +314,7 @@ $(obj)/%.dtb: $(src)/%.dts FORCE - - quiet_cmd_dtco = DTCO $@ - cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -- $(objtree)/scripts/dtc/dtc -@ -O dtb -o $@ -b 0 \ -+ $(objtree)/scripts/dtc/dtc -@ -H epapr -O dtb -o $@ -b 0 \ - -i $(dir $<) $(DTC_FLAGS) \ - -d $(depfile).dtc.tmp $(dtc-tmp) ; \ - cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) - -From 397a180a518dd177c140287c66caf9ae4dcb4a1e Mon Sep 17 00:00:00 2001 +From 26a743327cb9976306f0f31d8badd36f6636a3d4 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 062/208] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 055/111] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -122873,10 +106694,10 @@ See: https://github.com/raspberrypi/linux/issues/1064 create mode 100644 drivers/leds/trigger/ledtrig-input.c diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index 9b991d46ed848a0de40185eef30d9691c7e07e88..f454881346bbf01ea98aa2662e82f8c66dd11318 100644 +index d400dcaf4d296444967065e98812c210c48a192d..6a27a693034825de2897bb7b338b60cc10c9e59f 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c -@@ -46,8 +46,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, +@@ -50,8 +50,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, led_dat->platform_gpio_blink_set(led_dat->gpiod, level, NULL, NULL); led_dat->blinking = 0; @@ -122893,7 +106714,7 @@ index 9b991d46ed848a0de40185eef30d9691c7e07e88..f454881346bbf01ea98aa2662e82f8c6 gpiod_set_value_cansleep(led_dat->gpiod, level); else gpiod_set_value(led_dat->gpiod, level); -@@ -61,6 +68,13 @@ static int gpio_led_set_blocking(struct led_classdev *led_cdev, +@@ -65,6 +72,13 @@ static int gpio_led_set_blocking(struct led_classdev *led_cdev, return 0; } @@ -122907,15 +106728,15 @@ index 9b991d46ed848a0de40185eef30d9691c7e07e88..f454881346bbf01ea98aa2662e82f8c6 static int gpio_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { -@@ -120,6 +134,8 @@ static int create_gpio_led(const struct gpio_led *template, +@@ -122,6 +136,8 @@ static int create_gpio_led(const struct gpio_led *template, led_dat->platform_gpio_blink_set = blink_set; led_dat->cdev.blink_set = gpio_blink_set; } + led_dat->cdev.brightness_set = gpio_led_set; + led_dat->cdev.brightness_get = gpio_led_get; - if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) - state = !!gpiod_get_value_cansleep(led_dat->gpiod); - else + if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) { + state = gpiod_get_value_cansleep(led_dat->gpiod); + if (state < 0) diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 3f9ddb9fafa77f1f1fe5535c5e947838761e4f35..c1b6c83f3b63f993452893f136c5da54d0ada8e7 100644 --- a/drivers/leds/trigger/Kconfig @@ -123005,7 +106826,7 @@ index 0000000000000000000000000000000000000000..27f8ebea43d86fc51c98db5c953da05b +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h -index 8a3b5d29602ffe665cfb26522180f3a696664371..d067976ddc2f34d5476bcd9321856b1c40e17e12 100644 +index ddfcb2df3656cf0ab6aebd1fa3d624a6ec2e94e9..271563eb835f9018712e2076a88f341d2d6db7db 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -52,6 +52,9 @@ struct led_classdev { @@ -123019,10 +106840,10 @@ index 8a3b5d29602ffe665cfb26522180f3a696664371..d067976ddc2f34d5476bcd9321856b1c /* Set LED brightness level * Must not sleep. Use brightness_set_blocking for drivers -From 43ca3a9b4fe3c10f5ce4a65732444c6df4f081f1 Mon Sep 17 00:00:00 2001 +From 1cca88ce52ad46a1096fea51c07a9842c06466f2 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 063/208] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 056/111] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -123031,11 +106852,150 @@ Provide an ioctl for userspace applications, but only if this operation is hardware accelerated (otherwide it does not make any sense). Signed-off-by: Siarhei Siamashka ---- - drivers/video/fbdev/core/fbmem.c | 36 ++++++++++++++++++++++++++++++++++++ - include/uapi/linux/fb.h | 5 +++++ - 2 files changed, 41 insertions(+) +bcm2708_fb: Add ioctl for reading gpu memory through dma +--- + drivers/video/fbdev/bcm2708_fb.c | 109 +++++++++++++++++++++++++++++++++++++++ + drivers/video/fbdev/core/fbmem.c | 36 +++++++++++++ + include/uapi/linux/fb.h | 12 +++++ + 3 files changed, 157 insertions(+) + +diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c +index 37f60813fe1dd95d9f5f725c07ec2e75c09857bf..53c5a0bdadb4be9251affdabed66305842a08e72 100644 +--- a/drivers/video/fbdev/bcm2708_fb.c ++++ b/drivers/video/fbdev/bcm2708_fb.c +@@ -31,8 +31,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + #include + + //#define BCM2708_FB_DEBUG +@@ -426,6 +428,110 @@ static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info + return result; + } + ++static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, int size) ++{ ++ int burst_size = (fb->dma_chan == 0) ? 8 : 2; ++ struct bcm2708_dma_cb *cb = fb->cb_base; ++ ++ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | ++ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | ++ BCM2708_DMA_D_INC; ++ cb->dst = dst; ++ cb->src = src; ++ cb->length = size; ++ cb->stride = 0; ++ cb->pad[0] = 0; ++ cb->pad[1] = 0; ++ cb->next = 0; ++ ++ if (size < dma_busy_wait_threshold) { ++ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); ++ bcm_dma_wait_idle(fb->dma_chan_base); ++ } else { ++ void __iomem *dma_chan = fb->dma_chan_base; ++ cb->info |= BCM2708_DMA_INT_EN; ++ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); ++ while (bcm_dma_is_busy(dma_chan)) { ++ wait_event_interruptible( ++ fb->dma_waitq, ++ !bcm_dma_is_busy(dma_chan)); ++ } ++ fb->stats.dma_irqs++; ++ } ++ fb->stats.dma_copies++; ++} ++ ++#define INTALIAS_NORMAL(x) ((x)&~0xc0000000) // address with no aliases ++#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000) // cache coherent but non-allocating in L1 and L2 ++ ++static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) ++{ ++ struct fb_dmacopy ioparam; ++ size_t size = PAGE_SIZE; ++ u32 *buf = NULL; ++ dma_addr_t bus_addr; ++ long rc = 0; ++ size_t offset; ++ struct { u32 base, length; } gpu = {}; ++ ++ /* restrict this to root user */ ++ if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) ++ { ++ rc = -EFAULT; ++ goto out; ++ } ++ ++ /* Get the parameter data. ++ */ ++ if (copy_from_user ++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { ++ pr_err("[%s]: failed to copy-from-user\n", ++ __func__); ++ rc = -EFAULT; ++ goto out; ++ } ++ ++ rc = rpi_firmware_property(fb->fw, ++ RPI_FIRMWARE_GET_VC_MEMORY, ++ &gpu, sizeof(gpu)); ++ if (rc != 0 || gpu.base == 0 || gpu.length == 0) { ++ pr_err("[%s]: Unable to determine gpu memory %ld,%x,%x)\n", __func__, rc, gpu.base, gpu.length); ++ return -EFAULT; ++ } ++ ++ if (INTALIAS_NORMAL(ioparam.src) < gpu.base || INTALIAS_NORMAL(ioparam.src) >= gpu.base + gpu.length) { ++ pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__, INTALIAS_NORMAL(ioparam.src), gpu.base, gpu.base + gpu.length); ++ return -EFAULT; ++ } ++ ++ buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr, ++ GFP_ATOMIC); ++ if (!buf) { ++ pr_err("[%s]: failed to dma_alloc_coherent(%d)\n", ++ __func__, size); ++ rc = -ENOMEM; ++ goto out; ++ } ++ ++ for (offset = 0; offset < ioparam.length; offset += size) { ++ size_t remaining = ioparam.length - offset; ++ size_t s = min(size, remaining); ++ unsigned char *p = (unsigned char *)ioparam.src + offset; ++ unsigned char *q = (unsigned char *)ioparam.dst + offset; ++ dma_memcpy(fb, bus_addr, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); ++ if (copy_to_user(q, buf, s) != 0) { ++ pr_err("[%s]: failed to copy-to-user\n", ++ __func__); ++ rc = -EFAULT; ++ goto out; ++ } ++ } ++out: ++ if (buf) ++ dma_free_coherent(fb->fb.device, PAGE_ALIGN(size), buf, bus_addr); ++ return rc; ++} ++ + static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) + { + struct bcm2708_fb *fb = to_bcm2708(info); +@@ -438,6 +544,9 @@ static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long a + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, + &dummy, sizeof(dummy)); + break; ++ case FBIODMACOPY: ++ ret = vc_mem_copy(fb, arg); ++ break; + default: + dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd); + return -ENOTTY; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 76c1ad96fb37d4f07bbde6462f54825f566acbac..7bf48e478c056fcd745026902961506d5826615d 100644 --- a/drivers/video/fbdev/core/fbmem.c @@ -123105,10 +107065,10 @@ index 76c1ad96fb37d4f07bbde6462f54825f566acbac..7bf48e478c056fcd745026902961506d case FBIOBLANK: ret = do_fb_ioctl(info, cmd, arg); diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..fa72af0c981710fe80bacf4cf6612f6da19046ee 100644 +index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..703fa8a70574323abe2fb32599254582cd5d891f 100644 --- a/include/uapi/linux/fb.h +++ b/include/uapi/linux/fb.h -@@ -34,6 +34,11 @@ +@@ -34,6 +34,12 @@ #define FBIOPUT_MODEINFO 0x4617 #define FBIOGET_DISPINFO 0x4618 #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) @@ -123117,14 +107077,28 @@ index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..fa72af0c981710fe80bacf4cf6612f6d + * be concurrently added to the mainline kernel + */ +#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) ++#define FBIODMACOPY _IOW('z', 0x22, struct fb_dmacopy) #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ +@@ -346,6 +352,12 @@ struct fb_copyarea { + __u32 sy; + }; + ++struct fb_dmacopy { ++ void *dst; ++ __u32 src; ++ __u32 length; ++}; ++ + struct fb_fillrect { + __u32 dx; /* screen-relative */ + __u32 dy; -From 26923981303957954bcbc91fff432e1ac2633648 Mon Sep 17 00:00:00 2001 +From 8bccd20de5c5a27255761c7b4393f6fdd9730571 Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 064/208] Speed up console framebuffer imageblit function +Subject: [PATCH 057/111] Speed up console framebuffer imageblit function Especially on platforms with a slower CPU but a relatively high framebuffer fill bandwidth, like current ARM devices, the existing @@ -123333,10 +107307,10 @@ index a2bb276a8b2463eee98eb237c4647bc00cd93601..436494fba15abecb400ef28688466faf start_index, pitch_index); } else -From 71619935735369868d063609734855d0bdcc347d Mon Sep 17 00:00:00 2001 +From 10bc9c9562b39ebd10858de412b6336668171a39 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 065/208] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 058/111] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) 1-wire: Add support for configuring pin for w1-gpio kernel module @@ -123586,10 +107560,10 @@ index d58594a3232492e33f1dd4babd3798b03e0f0203..feae94256256316fd9d850c3d83325af unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From d3fec7c3a52ebf2123c4c379f48f349fbef17578 Mon Sep 17 00:00:00 2001 +From b5f0005bf497b78d9b6a40f364f8a6dba5676bbc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 066/208] config: Enable CONFIG_MEMCG, but leave it disabled +Subject: [PATCH 059/111] config: Enable CONFIG_MEMCG, but leave it disabled (due to memory cost). Enable with cgroup_enable=memory. --- @@ -123597,10 +107571,10 @@ Subject: [PATCH 066/208] config: Enable CONFIG_MEMCG, but leave it disabled 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index d6b729beba4930bbb1a1ddc4a6a6b8533bbf94e0..69e8d214f663572319f784fe17032b1ef4c588b4 100644 +index 85bc9beb046d9a6deda2e3564f4d5bd01d6fc27b..4acdbef46a8f0556469b5580a39c18ce0496c69d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c -@@ -5609,7 +5609,7 @@ int __init cgroup_init_early(void) +@@ -5629,7 +5629,7 @@ int __init cgroup_init_early(void) return 0; } @@ -123609,7 +107583,7 @@ index d6b729beba4930bbb1a1ddc4a6a6b8533bbf94e0..69e8d214f663572319f784fe17032b1e /** * cgroup_init - cgroup initialization -@@ -6139,6 +6139,28 @@ static int __init cgroup_no_v1(char *str) +@@ -6166,6 +6166,28 @@ static int __init cgroup_no_v1(char *str) } __setup("cgroup_no_v1=", cgroup_no_v1); @@ -123639,10 +107613,10 @@ index d6b729beba4930bbb1a1ddc4a6a6b8533bbf94e0..69e8d214f663572319f784fe17032b1e * css_tryget_online_from_dir - get corresponding css from a cgroup dentry * @dentry: directory dentry of interest -From 4a63703bb5d6cff1731ed710841ff6b3f62b3434 Mon Sep 17 00:00:00 2001 +From f64e7d0ea8c5f3aba4fdc4833493403bcdf10557 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 067/208] hid: Reduce default mouse polling interval to 60Hz +Subject: [PATCH 060/111] hid: Reduce default mouse polling interval to 60Hz Reduces overhead when using X --- @@ -123678,26 +107652,31 @@ index ae83af649a607f67239f1a64bf45dd4b5770cc7d..4a7af9d0b910f59d17421ce14138400d ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { -From a9b48b08d46cfbfd35b45dc3738412a8d9ecf6d0 Mon Sep 17 00:00:00 2001 +From 06547c09139ecfe3ee97ca218f8fb7b0373a672b Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 068/208] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 061/111] rpi-ft5406: Add touchscreen driver for pi LCD display Fix driver detection failure Check that the buffer response is non-zero meaning the touchscreen was detected rpi-ft5406: Use firmware API + +RPI-FT5406: Enable aarch64 support through explicit iomem interface + +Signed-off-by: Gerhard de Clercq --- - drivers/input/touchscreen/Kconfig | 7 + - drivers/input/touchscreen/Makefile | 1 + - drivers/input/touchscreen/rpi-ft5406.c | 246 +++++++++++++++++++++++++++++++++ - 3 files changed, 254 insertions(+) + drivers/input/touchscreen/Kconfig | 7 + + drivers/input/touchscreen/Makefile | 1 + + drivers/input/touchscreen/rpi-ft5406.c | 292 +++++++++++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 4 files changed, 301 insertions(+) create mode 100644 drivers/input/touchscreen/rpi-ft5406.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig -index 2fb1f430a4318fcddf65a85a813aae96861da09c..f43fc4561170d1649d77e5b4918ca56ec48e95e8 100644 +index efca0133e266b84439bed072f86b6d4c3e147ece..0bf78ff1ae888a1afe3825aab5316f365ef96bfe 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig -@@ -630,6 +630,13 @@ config TOUCHSCREEN_EDT_FT5X06 +@@ -638,6 +638,13 @@ config TOUCHSCREEN_EDT_FT5X06 To compile this driver as a module, choose M here: the module will be called edt-ft5x06. @@ -123712,7 +107691,7 @@ index 2fb1f430a4318fcddf65a85a813aae96861da09c..f43fc4561170d1649d77e5b4918ca56e tristate "Renesas MIGO-R touchscreen" depends on (SH_MIGOR || COMPILE_TEST) && I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile -index b4373d6be4021687c1f4fc4b4bc0faa054141ec0..9665772864cff27a33c0533e5147f29656e791bd 100644 +index 81b86451782d4479147fbb1a8c70cdc0f6f08eac..f720bc30ada9c2b5907228e852e3955ce9f48c12 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o @@ -123725,10 +107704,10 @@ index b4373d6be4021687c1f4fc4b4bc0faa054141ec0..9665772864cff27a33c0533e5147f296 obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c new file mode 100644 -index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d0bebdddc +index 0000000000000000000000000000000000000000..9d7d05482355d168c5c0c42508cd978979ee5f14 --- /dev/null +++ b/drivers/input/touchscreen/rpi-ft5406.c -@@ -0,0 +1,246 @@ +@@ -0,0 +1,292 @@ +/* + * Driver for memory based ft5406 touchscreen + * @@ -123751,7 +107730,9 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d +#include +#include +#include ++#include +#include ++#include +#include + +#define MAXIMUM_SUPPORTED_POINTS 10 @@ -123776,7 +107757,7 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + struct platform_device * pdev; + struct input_dev * input_dev; + void __iomem * ts_base; -+ struct ft5406_regs * regs; ++ dma_addr_t bus_addr; + struct task_struct * thread; +}; + @@ -123797,8 +107778,8 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + { + // 60fps polling + msleep_interruptible(17); -+ memcpy_fromio(®s, ts->regs, sizeof(*ts->regs)); -+ writel(99, &ts->regs->num_points); ++ memcpy_fromio(®s, ts->ts_base, sizeof(struct ft5406_regs)); ++ iowrite8(99, ts->ts_base + offsetof(struct ft5406_regs, num_points)); + // Do not output if theres no new information (num_points is 99) + // or we have no touch points and don't need to release any + if(!(regs.num_points == 99 || (regs.num_points == 0 && known_ids == 0))) @@ -123848,18 +107829,19 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + +static int ft5406_probe(struct platform_device *pdev) +{ -+ int ret; -+ struct input_dev * input_dev = input_allocate_device(); ++ int err = 0; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; + struct ft5406 * ts; + struct device_node *fw_node; + struct rpi_firmware *fw; + u32 touchbuf; + -+ dev_info(&pdev->dev, "Probing device\n"); ++ dev_info(dev, "Probing device\n"); + -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ fw_node = of_parse_phandle(np, "firmware", 0); + if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); ++ dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + @@ -123867,89 +107849,132 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d + if (!fw) + return -EPROBE_DEFER; + -+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, ++ ts = devm_kzalloc(dev, sizeof(struct ft5406), GFP_KERNEL); ++ if (!ts) { ++ dev_err(dev, "Failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ ts->input_dev = input_allocate_device(); ++ if (!ts->input_dev) { ++ dev_err(dev, "Failed to allocate input device\n"); ++ return -ENOMEM; ++ } ++ ++ ts->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->bus_addr, GFP_KERNEL); ++ if (!ts->ts_base) { ++ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", ++ __func__, PAGE_SIZE); ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ touchbuf = (u32)ts->bus_addr; ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, + &touchbuf, sizeof(touchbuf)); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to get touch buffer\n"); -+ return ret; ++ ++ if (err || touchbuf != 0) { ++ dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n", err); ++ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ ts->ts_base = 0; ++ ts->bus_addr = 0; + } + -+ if (!touchbuf) { -+ dev_err(&pdev->dev, "Touchscreen not detected\n"); -+ return -ENODEV; ++ if (!ts->ts_base) { ++ dev_warn(dev, "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n", err, touchbuf, ts->ts_base, ts->bus_addr); ++ ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, ++ &touchbuf, sizeof(touchbuf)); ++ if (err) { ++ dev_err(dev, "Failed to get touch buffer\n"); ++ goto out; ++ } ++ ++ if (!touchbuf) { ++ dev_err(dev, "Touchscreen not detected\n"); ++ err = -ENODEV; ++ goto out; ++ } ++ ++ dev_dbg(dev, "Got TS buffer 0x%x\n", touchbuf); ++ ++ // mmap the physical memory ++ touchbuf &= ~0xc0000000; ++ ts->ts_base = ioremap(touchbuf, sizeof(struct ft5406_regs)); ++ if (ts->ts_base == NULL) ++ { ++ dev_err(dev, "Failed to map physical address\n"); ++ err = -ENOMEM; ++ goto out; ++ } + } -+ -+ dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", touchbuf); -+ -+ ts = kzalloc(sizeof(struct ft5406), GFP_KERNEL); -+ -+ if (!ts || !input_dev) { -+ ret = -ENOMEM; -+ dev_err(&pdev->dev, "Failed to allocate memory\n"); -+ return ret; -+ } -+ ts->input_dev = input_dev; + platform_set_drvdata(pdev, ts); + ts->pdev = pdev; + -+ input_dev->name = "FT5406 memory based driver"; ++ ts->input_dev->name = "FT5406 memory based driver"; + -+ __set_bit(EV_KEY, input_dev->evbit); -+ __set_bit(EV_SYN, input_dev->evbit); -+ __set_bit(EV_ABS, input_dev->evbit); ++ __set_bit(EV_KEY, ts->input_dev->evbit); ++ __set_bit(EV_SYN, ts->input_dev->evbit); ++ __set_bit(EV_ABS, ts->input_dev->evbit); + -+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, + SCREEN_WIDTH, 0, 0); -+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, + SCREEN_HEIGHT, 0, 0); + -+ input_mt_init_slots(input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); ++ input_mt_init_slots(ts->input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); + -+ input_set_drvdata(input_dev, ts); ++ input_set_drvdata(ts->input_dev, ts); + -+ ret = input_register_device(input_dev); -+ if (ret) { -+ dev_err(&pdev->dev, "could not register input device, %d\n", -+ ret); -+ return ret; ++ err = input_register_device(ts->input_dev); ++ if (err) { ++ dev_err(dev, "could not register input device, %d\n", ++ err); ++ goto out; + } -+ -+ // mmap the physical memory -+ touchbuf &= ~0xc0000000; -+ ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -+ if(ts->ts_base == NULL) -+ { -+ dev_err(&pdev->dev, "Failed to map physical address\n"); -+ input_unregister_device(input_dev); -+ kzfree(ts); -+ return -ENOMEM; -+ } -+ -+ ts->regs = (struct ft5406_regs *) ts->ts_base; + + // create thread to poll the touch events + ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); + if(ts->thread == NULL) + { -+ dev_err(&pdev->dev, "Failed to create kernel thread"); -+ iounmap(ts->ts_base); -+ input_unregister_device(input_dev); -+ kzfree(ts); ++ dev_err(dev, "Failed to create kernel thread"); ++ err = -ENOMEM; ++ goto out; + } + + return 0; ++ ++out: ++ if (ts->bus_addr) { ++ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ ts->bus_addr = 0; ++ ts->ts_base = NULL; ++ } else if (ts->ts_base) { ++ iounmap(ts->ts_base); ++ ts->ts_base = NULL; ++ } ++ if (ts->input_dev) { ++ input_unregister_device(ts->input_dev); ++ ts->input_dev = NULL; ++ } ++ return err; +} + +static int ft5406_remove(struct platform_device *pdev) +{ ++ struct device *dev = &pdev->dev; + struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev); + -+ dev_info(&pdev->dev, "Removing rpi-ft5406\n"); ++ dev_info(dev, "Removing rpi-ft5406\n"); + + kthread_stop(ts->thread); -+ iounmap(ts->ts_base); -+ input_unregister_device(ts->input_dev); -+ kzfree(ts); ++ ++ if (ts->bus_addr) ++ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ else if (ts->ts_base) ++ iounmap(ts->ts_base); ++ if (ts->input_dev) ++ input_unregister_device(ts->input_dev); + + return 0; +} @@ -123975,11 +108000,23 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d +MODULE_AUTHOR("Gordon Hollingworth"); +MODULE_DESCRIPTION("Touchscreen driver for memory based FT5406"); +MODULE_LICENSE("GPL"); +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +index 227a107214a02deadcca3db202da265eba1fdd21..b0f6e33bd30c35664ceee057f4c3ad32b914291d 100644 +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -115,6 +115,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + -From 79bd07b796e2fc05512634cc0c80bd3d6e641c6b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 069/208] Improve __copy_to_user and __copy_from_user +From c4de14efbb23ff522c321d5a9220b04560c559a7 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 28 Nov 2016 16:50:04 +0000 +Subject: [PATCH 062/111] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use @@ -124010,7 +108047,8 @@ Signed-off-by: Phil Elwell arch/arm/lib/memmove_rpi.S | 61 +++++ arch/arm/lib/memset_rpi.S | 123 +++++++++ arch/arm/lib/uaccess_with_memcpy.c | 120 ++++++++- - 12 files changed, 1373 insertions(+), 6 deletions(-) + arch/arm/mach-bcm/Kconfig | 7 + + 13 files changed, 1380 insertions(+), 6 deletions(-) create mode 100644 arch/arm/lib/arm-mem.h create mode 100644 arch/arm/lib/exports_rpi.c create mode 100644 arch/arm/lib/memcmp_rpi.S @@ -124020,14 +108058,14 @@ Signed-off-by: Phil Elwell create mode 100644 arch/arm/lib/memset_rpi.S diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h -index cf4f3aad0fc1c2154c6cf3839ff21bb1c46d6499..9fe7780002ce1847b9009ff9b741b56f34e19256 100644 +index cf4f3aad0fc1c2154c6cf3839ff21bb1c46d6499..d69b70a6007dfc647ad164d1ee90d253c0686dee 100644 --- a/arch/arm/include/asm/string.h +++ b/arch/arm/include/asm/string.h @@ -24,6 +24,11 @@ extern void * memchr(const void *, int, __kernel_size_t); #define __HAVE_ARCH_MEMSET extern void * memset(void *, int, __kernel_size_t); -+#ifdef CONFIG_MACH_BCM2708 ++#ifdef CONFIG_BCM2835_FAST_MEMCPY +#define __HAVE_ARCH_MEMCMP +extern int memcmp(const void *, const void *, size_t); +#endif @@ -124036,7 +108074,7 @@ index cf4f3aad0fc1c2154c6cf3839ff21bb1c46d6499..9fe7780002ce1847b9009ff9b741b56f #define memset(p,v,n) \ diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h -index a93c0f99acf7767c680158cf96acef87d1f0da51..cbad0e035c6b8f39463007071539797da586e620 100644 +index 1f59ea051bab814132074b09f55d3a57c800a471..028d151b80a3dfb4253e94b87cc391bdb0b16c49 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -477,6 +477,9 @@ do { \ @@ -124050,7 +108088,7 @@ index a93c0f99acf7767c680158cf96acef87d1f0da51..cbad0e035c6b8f39463007071539797d __copy_from_user(void *to, const void __user *from, unsigned long n) { diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile -index 27f4d96258a2e66193d6a3701bb4cf9a44399aad..5235717443bd221df0b190adeb7d90231a5e5693 100644 +index 27f4d96258a2e66193d6a3701bb4cf9a44399aad..96b390c9301f816d5c83c6ddb76ac74ba7a3b99d 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -6,9 +6,8 @@ @@ -124070,7 +108108,7 @@ index 27f4d96258a2e66193d6a3701bb4cf9a44399aad..5235717443bd221df0b190adeb7d9023 copy_from_user.o copy_to_user.o +# Choose optimised implementations for Raspberry Pi -+ifeq ($(CONFIG_MACH_BCM2708),y) ++ifeq ($(CONFIG_BCM2835_FAST_MEMCPY),y) + CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600 + CFLAGS_uaccess_with_memcpy.o += -DCOPY_TO_USER_THRESHOLD=672 + obj-$(CONFIG_MODULES) += exports_rpi.o @@ -124248,7 +108286,7 @@ index 0000000000000000000000000000000000000000..5d4bda19ad207c65e7b7c6d6d733087f +92: +.endm diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S -index 1512bebfbf1b18ad317648891385a24e93d1f35f..3da60dd2caab0968e2156cf8705ebbe5f2551a8b 100644 +index 7a4b060490012dd29f8a6d9fb8e24dfa58896bd1..fb40a1b3a5b7d42f93ae362e3326b7a72dc290dc 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S @@ -89,11 +89,13 @@ @@ -125440,7 +109478,7 @@ index 6bd1089b07e0960830ed6bd6a8345202b7efd8b0..cd17dd11ebe7bbe00089e70cd2ccea74 __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) { unsigned long ua_flags; -@@ -137,6 +182,57 @@ out: +@@ -137,6 +182,57 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) return n; } @@ -125534,11 +109572,29 @@ index 6bd1089b07e0960830ed6bd6a8345202b7efd8b0..cd17dd11ebe7bbe00089e70cd2ccea74 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) +diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig +index 333dc3c2e5ffbb2c5ab8fcfb6115b6162643cf20..46b787a6474ffa857da9b663948863ecfb46e862 100644 +--- a/arch/arm/mach-bcm/Kconfig ++++ b/arch/arm/mach-bcm/Kconfig +@@ -174,6 +174,13 @@ config ARCH_BCM_53573 + The base chip is BCM53573 and there are some packaging modifications + like BCM47189 and BCM47452. + ++config BCM2835_FAST_MEMCPY ++ bool "Enable optimized __copy_to_user and __copy_from_user" ++ depends on ARCH_BCM2835 && ARCH_MULTI_V6 ++ default y ++ help ++ Optimized versions of __copy_to_user and __copy_from_user for Pi1. ++ + config ARCH_BCM_63XX + bool "Broadcom BCM63xx DSL SoC" + depends on ARCH_MULTI_V7 -From 100203b956cc659d9e65a4086db54f28c304e1e8 Mon Sep 17 00:00:00 2001 +From 1e9511001925124be9b1d3461e87605255c58310 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 25 Jun 2015 12:16:11 +0100 -Subject: [PATCH 070/208] gpio-poweroff: Allow it to work on Raspberry Pi +Subject: [PATCH 063/111] gpio-poweroff: Allow it to work on Raspberry Pi The Raspberry Pi firmware manages the power-down and reboot process. To do this it installs a pm_power_off handler, causing @@ -125573,10 +109629,10 @@ index be3d81ff51cc3f510d85e4eed7a52960e51e7bc1..a030ae9fb1fca325061c093696e82186 "%s: pm_power_off function already registered", __func__); -From 75e0aa61e26876991add914994a59a0ccf3e6e12 Mon Sep 17 00:00:00 2001 +From da2deb13c51f74edf4a4851bf01f03503a208b2a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 14:32:47 +0100 -Subject: [PATCH 071/208] mfd: Add Raspberry Pi Sense HAT core driver +Subject: [PATCH 064/111] mfd: Add Raspberry Pi Sense HAT core driver --- drivers/input/joystick/Kconfig | 8 + @@ -125786,7 +109842,7 @@ index 0000000000000000000000000000000000000000..6a416769065d2198344792eb02d8e38d +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 580f4f280d6b7aebe9a4813acbfaf28ea92a7ba9..87cbe66ad08a2c300079de5772ceaab08db4217f 100644 +index c6df6442ba2b1b378386db03cb530fa6b6e3e723..b220064bd5feba3f9bb5ec198bcf8e5c4b930533 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -10,6 +10,14 @@ config MFD_CORE @@ -125805,10 +109861,10 @@ index 580f4f280d6b7aebe9a4813acbfaf28ea92a7ba9..87cbe66ad08a2c300079de5772ceaab0 tristate "AMD CS5535 and CS5536 southbridge core functions" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 2ba3ba35f745309de62050ab8442cea87a0edb2e..6f2b1d39e4a5c7860dcf971c47096759c578b6fc 100644 +index 9834e669d98573ce8c0b0a15b3f167dbf3485d87..1d8d58fe173c27bdf00daa646f4970e3aeb3ac08 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -207,3 +207,4 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o +@@ -211,3 +211,4 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o @@ -125977,10 +110033,10 @@ index 0000000000000000000000000000000000000000..eea9312dc96a496ce846b0c5a83e6e4f +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index 78a9e6119fa13437862080d815e84d68f7010d1f..ec1a5c27ead7dce18608eb6314f0ae8072fdf9bc 100644 +index 0ff4f80531e013f028ca4d05559c5464f8cfa5ef..2cd45bce38120d076d6a19804443557862978d4b 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig -@@ -2501,3 +2501,16 @@ config FB_SM712 +@@ -2504,3 +2504,16 @@ config FB_SM712 This driver is also available as a module. The module will be called sm712fb. If you want to compile it as a module, say M here and read . @@ -125998,10 +110054,10 @@ index 78a9e6119fa13437862080d815e84d68f7010d1f..ec1a5c27ead7dce18608eb6314f0ae80 + help + This is the framebuffer driver for the Raspberry Pi Sense HAT diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2..459f9d1d4a37bb386c207df0f3aab581b9eb5e9e 100644 +index 8cd1193b98690b9c4f49098ab14389504d65af3a..c9f1754bf2a6796bf5555fabb9e80f8991cb83bc 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile -@@ -148,6 +148,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o +@@ -147,6 +147,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_MXS) += mxsfb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o @@ -126441,10 +110497,10 @@ index 0000000000000000000000000000000000000000..56196dc2af10e464a1e3f98b028dca1c + +#endif -From 396b0f4386372c8b2ca36a812bad656738b82fe2 Mon Sep 17 00:00:00 2001 +From 63fe5b59d57d2cd54bbe96dc5e0743e977b404f5 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 072/208] ASoC: Add support for HifiBerry DAC +Subject: [PATCH 065/111] ASoC: Add support for HifiBerry DAC This adds a machine driver for the HifiBerry DAC. It is a sound card that can @@ -126452,14 +110508,14 @@ be stacked onto the Raspberry Pi. Signed-off-by: Florian Meier --- - sound/soc/bcm/Kconfig | 9 +++- + sound/soc/bcm/Kconfig | 9 ++- sound/soc/bcm/Makefile | 4 ++ - sound/soc/bcm/hifiberry_dac.c | 123 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 135 insertions(+), 1 deletion(-) + sound/soc/bcm/hifiberry_dac.c | 124 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 sound/soc/bcm/hifiberry_dac.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 03a303e52d5fe57bbdd8769d24bca59067c54c65..42e1358aa1e0f67a08912af7ea17b8756ab06b1c 100644 +index d528aaceaad95bc6bae2147ebe66249629d2512e..ad4817f44072bbc0a92d8a5ebd1b6b365fb4ed82 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -15,4 +15,11 @@ config SND_SOC_CYGNUS @@ -126490,10 +110546,10 @@ index fc739d0078842680802389500dea19334da8fb7b..be80079de3cefbd52f4b78db20ee9a5d +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c new file mode 100644 -index 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8 +index 0000000000000000000000000000000000000000..45f2b770ad9e67728ca599a7445d6ae9a01c0c29 --- /dev/null +++ b/sound/soc/bcm/hifiberry_dac.c -@@ -0,0 +1,123 @@ +@@ -0,0 +1,124 @@ +/* + * ASoC Driver for HifiBerry DAC + * @@ -126559,6 +110615,7 @@ index 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21 +/* audio machine driver */ +static struct snd_soc_card snd_rpi_hifiberry_dac = { + .name = "snd_rpi_hifiberry_dac", ++ .driver_name = "HifiberryDac", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_dac_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), @@ -126618,10 +110675,10 @@ index 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); +MODULE_LICENSE("GPL v2"); -From 39db6b2b07cc619b8f31e9698a1a3c6681d5b532 Mon Sep 17 00:00:00 2001 +From e7c31478dde01383847f0150428a449b46893a77 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Mon, 25 Jan 2016 15:48:59 +0000 -Subject: [PATCH 073/208] ASoC: Add support for Rpi-DAC +Subject: [PATCH 066/111] ASoC: Add support for Rpi-DAC --- sound/soc/bcm/Kconfig | 7 +++ @@ -126635,7 +110692,7 @@ Subject: [PATCH 073/208] ASoC: Add support for Rpi-DAC create mode 100644 sound/soc/codecs/pcm1794a.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 42e1358aa1e0f67a08912af7ea17b8756ab06b1c..8c1e353458a3460f2c3fe26991498ee16f19ecd1 100644 +index ad4817f44072bbc0a92d8a5ebd1b6b365fb4ed82..8209fffdc0be3136a99cbab4e5152759aa95594b 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -23,3 +23,10 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC @@ -126787,10 +110844,10 @@ index 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1 +MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 1cd6ab344d67def61db455d956ac2d7075a1f6d8..9a51aad8c267f08ce568b2eb23da0951b1dc246e 100644 +index c67667bb970f1729db65b027dd8e963b9ee95b7b..74a93e52bdc8116df3db08aaf98fffa1e6f6cc1b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -97,6 +97,7 @@ config SND_SOC_ALL_CODECS +@@ -98,6 +98,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM179X_I2C if I2C select SND_SOC_PCM179X_SPI if SPI_MASTER @@ -126798,7 +110855,7 @@ index 1cd6ab344d67def61db455d956ac2d7075a1f6d8..9a51aad8c267f08ce568b2eb23da0951 select SND_SOC_PCM3008 select SND_SOC_PCM3168A_I2C if I2C select SND_SOC_PCM3168A_SPI if SPI_MASTER -@@ -681,6 +682,10 @@ config SND_SOC_RT5616 +@@ -689,6 +690,10 @@ config SND_SOC_RT5616 tristate "Realtek RT5616 CODEC" depends on I2C @@ -126810,10 +110867,10 @@ index 1cd6ab344d67def61db455d956ac2d7075a1f6d8..9a51aad8c267f08ce568b2eb23da0951 tristate "Realtek ALC5631/RT5631 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 58036af2c7d9837b347ea2b6cdccaad72a711a53..d781f6c90383b3865ae2cc6516e7581bde004d9b 100644 +index 958cd4912fbc9820f965c0d2f38692857f410d3a..77786e7f44a7fa22d9b5beed3eb687e2b7a28526 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile -@@ -92,6 +92,7 @@ snd-soc-pcm1681-objs := pcm1681.o +@@ -93,6 +93,7 @@ snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o snd-soc-pcm179x-spi-objs := pcm179x-spi.o @@ -126821,7 +110878,7 @@ index 58036af2c7d9837b347ea2b6cdccaad72a711a53..d781f6c90383b3865ae2cc6516e7581b snd-soc-pcm3008-objs := pcm3008.o snd-soc-pcm3168a-objs := pcm3168a.o snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o -@@ -321,6 +322,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o +@@ -325,6 +326,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o @@ -126905,10 +110962,10 @@ index 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From a17eab5f9fbde48aabcbecad1b4d173aecdd2287 Mon Sep 17 00:00:00 2001 +From e55d838e108b015dba7611659f3fd9926e45aac5 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 074/208] ASoC: wm8804: Implement MCLK configuration options, +Subject: [PATCH 067/111] ASoC: wm8804: Implement MCLK configuration options, add 32bit support WM8804 can run with PLL frequencies of 256xfs and 128xfs for most sample rates. At 192kHz only 128xfs is supported. The existing driver selects 128xfs automatically for some lower samples rates. By using an @@ -126927,7 +110984,7 @@ Signed-off-by: Daniel Matuschek 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801dc0fa1c7b 100644 +index af95d648265b3e92e345101542b332aee35191d4..513f56ba132929662802d15cdc653af3d059a39c 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, @@ -126954,13 +111011,13 @@ index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801d - .idle_bias_off = true, + .idle_bias_off = false, - .dapm_widgets = wm8804_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + .component_driver = { + .dapm_widgets = wm8804_dapm_widgets, -From c4240b894be6cb535c9a3260dc9071eb38ede175 Mon Sep 17 00:00:00 2001 +From 556c9e016c3bdf1c62e3360d52638560bda63501 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 075/208] ASoC: BCM:Add support for HiFiBerry Digi. Driver is +Subject: [PATCH 068/111] ASoC: BCM:Add support for HiFiBerry Digi. Driver is based on the patched WM8804 driver. Signed-off-by: Daniel Matuschek @@ -126978,15 +111035,19 @@ HiFiBerry Digi: set SPDIF status bits for sample rate The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. While this is optional, some DACs and receivers do not accept this signal. This patch adds the sample rate bits in the SPDIF status block. + +Added HiFiBerry Digi+ Pro driver + +Signed-off-by: Daniel Matuschek --- sound/soc/bcm/Kconfig | 7 ++ sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_digi.c | 224 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 233 insertions(+) + sound/soc/bcm/hifiberry_digi.c | 276 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 285 insertions(+) create mode 100644 sound/soc/bcm/hifiberry_digi.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 8c1e353458a3460f2c3fe26991498ee16f19ecd1..ac1fbf74b808789641aa53b0418632bfee858e79 100644 +index 8209fffdc0be3136a99cbab4e5152759aa95594b..3cd4288a1e1c535210b01cd9561128fd4ea3e87f 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -24,6 +24,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC @@ -127019,10 +111080,10 @@ index 09501910f8152b8d516e098433339b5fc2640d0f..862f00fb43bfb0b8dc75d577df47ea4e obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c new file mode 100644 -index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408cc28c333 +index 0000000000000000000000000000000000000000..19dc953b7227ba86123fc7a2ba654499e0c581c5 --- /dev/null +++ b/sound/soc/bcm/hifiberry_digi.c -@@ -0,0 +1,224 @@ +@@ -0,0 +1,276 @@ +/* + * ASoC Driver for HifiBerry Digi + * @@ -127048,6 +111109,7 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +#include +#include +#include ++#include + +#include "../codecs/wm8804.h" + @@ -127055,9 +111117,34 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); + ++#define CLK_44EN_RATE 22579200UL ++#define CLK_48EN_RATE 24576000UL ++ ++static bool snd_rpi_hifiberry_is_digipro; ++static struct gpio_desc *snd_rpi_hifiberry_clk44gpio; ++static struct gpio_desc *snd_rpi_hifiberry_clk48gpio; + +static int samplerate=44100; + ++static uint32_t snd_rpi_hifiberry_digi_enable_clock(int sample_rate) ++{ ++ switch (sample_rate) { ++ case 11025: ++ case 22050: ++ case 44100: ++ case 88200: ++ case 176400: ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 1); ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 0); ++ return CLK_44EN_RATE; ++ default: ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 1); ++ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 0); ++ return CLK_48EN_RATE; ++ } ++} ++ ++ +static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; @@ -127065,6 +111152,14 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + /* enable TX output */ + snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); + ++ /* Initialize Digi+ Pro hardware */ ++ if (snd_rpi_hifiberry_is_digipro) { ++ struct snd_soc_dai_link *dai = rtd->dai_link; ++ ++ dai->name = "HiFiBerry Digi+ Pro"; ++ dai->stream_name = "HiFiBerry Digi+ Pro HiFi"; ++ } ++ + return 0; +} + @@ -127112,6 +111207,9 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + mclk_freq=samplerate*128; + mclk_div=WM8804_MCLKDIV_128FS; + } ++ ++ if (snd_rpi_hifiberry_is_digipro) ++ sysclk = snd_rpi_hifiberry_digi_enable_clock(samplerate); + + switch (samplerate) { + case 32000: @@ -127146,6 +111244,7 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, + sysclk, SND_SOC_CLOCK_OUT); ++ + if (ret < 0) { + dev_err(codec->dev, + "Failed to set WM8804 SYSCLK: %d\n", ret); @@ -127189,6 +111288,7 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +/* audio machine driver */ +static struct snd_soc_card snd_rpi_hifiberry_digi = { + .name = "snd_rpi_hifiberry_digi", ++ .driver_name = "HifiberryDigi", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_digi_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), @@ -127212,6 +111312,19 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 + dai->platform_name = NULL; + dai->platform_of_node = i2s_node; + } ++ ++ snd_rpi_hifiberry_is_digipro = 1; ++ ++ snd_rpi_hifiberry_clk44gpio = ++ devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW); ++ if (IS_ERR(snd_rpi_hifiberry_clk44gpio)) ++ snd_rpi_hifiberry_is_digipro = 0; ++ ++ snd_rpi_hifiberry_clk48gpio = ++ devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW); ++ if (IS_ERR(snd_rpi_hifiberry_clk48gpio)) ++ snd_rpi_hifiberry_is_digipro = 0; ++ + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); @@ -127248,10 +111361,10 @@ index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); +MODULE_LICENSE("GPL v2"); -From d75574658dee579a87b081abf15d7b8f18006156 Mon Sep 17 00:00:00 2001 +From 2cffe8450f73abcb7ccdcef2b0f62e4ac7e064e6 Mon Sep 17 00:00:00 2001 From: Gordon Garrity Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 076/208] Add IQaudIO Sound Card support for Raspberry Pi +Subject: [PATCH 069/111] Add IQaudIO Sound Card support for Raspberry Pi Set a limit of 0dB on Digital Volume Control @@ -127312,7 +111425,7 @@ Signed-off-by: DigitalDreamtime create mode 100644 sound/soc/bcm/iqaudio-dac.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index ac1fbf74b808789641aa53b0418632bfee858e79..fa4a8fd28bb977edc66dd4e9bd5ebc8ce5e47916 100644 +index 3cd4288a1e1c535210b01cd9561128fd4ea3e87f..8272ba5302b1ddbd9c21ee50891d3cb0f0303c58 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -37,3 +37,10 @@ config SND_BCM2708_SOC_RPI_DAC @@ -127581,10 +111694,10 @@ index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); +MODULE_LICENSE("GPL v2"); -From ab9d6e71cd86d0b32c9100e19dd44a075e3e9645 Mon Sep 17 00:00:00 2001 +From 375717ae06cb32b14e2c615798b51d4bc384c0b0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jul 2016 17:06:50 +0100 -Subject: [PATCH 077/208] iqaudio-dac: Compile fix - untested +Subject: [PATCH 070/111] iqaudio-dac: Compile fix - untested --- sound/soc/bcm/iqaudio-dac.c | 6 +++++- @@ -127608,10 +111721,10 @@ index 4e8e6dec14bcf4a1ff286c43742d4097249d6777..aa15bc4b49ca95edec905fddd8fd0a6d if (dapm->dev != codec_dai->dev) return 0; -From 962edd733d593be9f0542a3aeb9a0591ab5ab5c1 Mon Sep 17 00:00:00 2001 +From 8c1655f7ed054fab977e814fa775ba3d0132a71e Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 078/208] Added support for HiFiBerry DAC+ +Subject: [PATCH 071/111] Added support for HiFiBerry DAC+ The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses a different codec chip (PCM5122), therefore a new driver is necessary. @@ -127641,14 +111754,14 @@ Signed-off-by: DigitalDreamtime drivers/clk/clk-hifiberry-dacpro.c | 160 +++++++++++++++++ sound/soc/bcm/Kconfig | 7 + sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_dacplus.c | 358 +++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/hifiberry_dacplus.c | 359 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/pcm512x.c | 3 +- - 6 files changed, 530 insertions(+), 1 deletion(-) + 6 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/clk-hifiberry-dacpro.c create mode 100644 sound/soc/bcm/hifiberry_dacplus.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index 3b6f9cf3464aaddca0a54886aa575a108c21b7ca..698a88576e9d760feaf824683edf4c9adcbe7c49 100644 +index 925081ec14c04935e1eb17bf2709640c7ae3ae10..2b6fcd8abf79da77aa85fdc53512aafd09f836cb 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o @@ -127656,9 +111769,9 @@ index 3b6f9cf3464aaddca0a54886aa575a108c21b7ca..698a88576e9d760feaf824683edf4c9a obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o - obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o - obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o + obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o + obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o diff --git a/drivers/clk/clk-hifiberry-dacpro.c b/drivers/clk/clk-hifiberry-dacpro.c new file mode 100644 index 0000000000000000000000000000000000000000..99cee2b1706c43170b4fc35c0023349b9019606c @@ -127826,7 +111939,7 @@ index 0000000000000000000000000000000000000000..99cee2b1706c43170b4fc35c0023349b +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:clk-hifiberry-dacpro"); diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index fa4a8fd28bb977edc66dd4e9bd5ebc8ce5e47916..3477304b789c87ebe75fde3876cb4a3a572b1bb8 100644 +index 8272ba5302b1ddbd9c21ee50891d3cb0f0303c58..4473cc728097bda0ce9fe68d4a9da348ec41f8b3 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -24,6 +24,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC @@ -127863,10 +111976,10 @@ index fcac518ca9b46ab2074fc859b8d2f1ff850ebc19..203afc03167acbcad15e836209956bc5 obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c new file mode 100644 -index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a80889221a1d6 +index 0000000000000000000000000000000000000000..bdc35e7e6bc12dc1cf04f5ffad8f9ab49a0b0266 --- /dev/null +++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -0,0 +1,358 @@ +@@ -0,0 +1,359 @@ +/* + * ASoC Driver for HiFiBerry DAC+ / DAC Pro + * @@ -128160,6 +112273,7 @@ index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a8088 +/* audio machine driver */ +static struct snd_soc_card snd_rpi_hifiberry_dacplus = { + .name = "snd_rpi_hifiberry_dacplus", ++ .driver_name = "HifiberryDacp", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_dacplus_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), @@ -128226,7 +112340,7 @@ index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a8088 +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c -index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb69f87d693 100644 +index 72b19e62f6267698aea45d2410d616d91c1825cb..c6839ef6e16754ed9de2698507b8986addd822fe 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -854,7 +854,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, @@ -128240,10 +112354,10 @@ index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb6 dev_err(dev, "No LRCLK?\n"); return -EINVAL; -From 291d3872c447b25b51ad03f52787442cec78dd1f Mon Sep 17 00:00:00 2001 +From 1f802ccf0a9e67907572ea2f881975a904ec3bf5 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 079/208] Added driver for HiFiBerry Amp amplifier add-on board +Subject: [PATCH 072/111] Added driver for HiFiBerry Amp amplifier add-on board The driver contains a low-level hardware driver for the TAS5713 and the drivers for the Raspberry Pi I2S subsystem. @@ -128261,18 +112375,18 @@ Some code to load the driver based on device-tree-overlays was missing. This is --- sound/soc/bcm/Kconfig | 7 + sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 128 +++++++++++++++ + sound/soc/bcm/hifiberry_amp.c | 129 +++++++++++++++ sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ - 7 files changed, 722 insertions(+) + 7 files changed, 723 insertions(+) create mode 100644 sound/soc/bcm/hifiberry_amp.c create mode 100644 sound/soc/codecs/tas5713.c create mode 100644 sound/soc/codecs/tas5713.h diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 3477304b789c87ebe75fde3876cb4a3a572b1bb8..f764110b86b790a2b639cc66b965e187d9f52ce3 100644 +index 4473cc728097bda0ce9fe68d4a9da348ec41f8b3..b1d877407dd69c9bd6b2787b0a559f4113bc21f2 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -38,6 +38,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI @@ -128309,10 +112423,10 @@ index 203afc03167acbcad15e836209956bc5ab151157..a4838e2cf8e93c9285836f95f4151dae obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c new file mode 100644 -index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1 +index 0000000000000000000000000000000000000000..d17c29780507dc31c50f1d567ff5cea7c8241ff5 --- /dev/null +++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,128 @@ +@@ -0,0 +1,129 @@ +/* + * ASoC Driver for HifiBerry AMP + * @@ -128376,6 +112490,7 @@ index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7d + +static struct snd_soc_card snd_rpi_hifiberry_amp = { + .name = "snd_rpi_hifiberry_amp", ++ .driver_name = "HifiberryAmp", + .owner = THIS_MODULE, + .dai_link = snd_rpi_hifiberry_amp_dai, + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), @@ -128442,10 +112557,10 @@ index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7d +MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 9a51aad8c267f08ce568b2eb23da0951b1dc246e..37674869e4ef2dc33b59ace8ef36e404d5a809a2 100644 +index 74a93e52bdc8116df3db08aaf98fffa1e6f6cc1b..9824cdd04b0c11c45b8cedd0187a0eba8f1dc2d4 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -136,6 +136,7 @@ config SND_SOC_ALL_CODECS +@@ -139,6 +139,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TFA9879 if I2C select SND_SOC_TLV320AIC23_I2C if I2C select SND_SOC_TLV320AIC23_SPI if SPI_MASTER @@ -128453,7 +112568,7 @@ index 9a51aad8c267f08ce568b2eb23da0951b1dc246e..37674869e4ef2dc33b59ace8ef36e404 select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC31XX if I2C select SND_SOC_TLV320AIC32X4_I2C if I2C -@@ -807,6 +808,9 @@ config SND_SOC_TFA9879 +@@ -821,6 +822,9 @@ config SND_SOC_TFA9879 tristate "NXP Semiconductors TFA9879 amplifier" depends on I2C @@ -128464,10 +112579,10 @@ index 9a51aad8c267f08ce568b2eb23da0951b1dc246e..37674869e4ef2dc33b59ace8ef36e404 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index d781f6c90383b3865ae2cc6516e7581bde004d9b..c21145c8a55a9a25e6a37d6e06c1ab5d37ddf603 100644 +index 77786e7f44a7fa22d9b5beed3eb687e2b7a28526..5a2db0d2fe2f49920eeccfecef62c969ae2e99a1 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile -@@ -141,6 +141,7 @@ snd-soc-tas5086-objs := tas5086.o +@@ -144,6 +144,7 @@ snd-soc-tas5086-objs := tas5086.o snd-soc-tas571x-objs := tas571x.o snd-soc-tas5720-objs := tas5720.o snd-soc-tfa9879-objs := tfa9879.o @@ -128475,7 +112590,7 @@ index d781f6c90383b3865ae2cc6516e7581bde004d9b..c21145c8a55a9a25e6a37d6e06c1ab5d snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -360,6 +361,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o +@@ -366,6 +367,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o @@ -129075,121 +113190,835 @@ index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8 + +#endif /* _TAS5713_H */ -From 11db210348ec63453d86cb144b3f5c17feedfacf Mon Sep 17 00:00:00 2001 -From: "Daniel Matuschek (HiFiBerry)" -Date: Tue, 26 Jul 2016 19:16:25 +0200 -Subject: [PATCH 080/208] Added HiFiBerry Digi+ Pro driver +From 7c0248b02d38aeb82181a3d86d999cc1e8b4e5b3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 12 Dec 2016 16:26:54 +0000 +Subject: [PATCH 073/111] Revert "Added driver for HiFiBerry Amp amplifier + add-on board" -Signed-off-by: Daniel Matuschek +This reverts commit 3e6b00833d92a50cbcc9922deb6e1bc8fcdbb587. --- - sound/soc/bcm/hifiberry_digi.c | 51 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 51 insertions(+) + sound/soc/bcm/Kconfig | 7 - + sound/soc/bcm/Makefile | 2 - + sound/soc/bcm/hifiberry_amp.c | 129 --------------- + sound/soc/codecs/Kconfig | 4 - + sound/soc/codecs/Makefile | 2 - + sound/soc/codecs/tas5713.c | 369 ------------------------------------------ + sound/soc/codecs/tas5713.h | 210 ------------------------ + 7 files changed, 723 deletions(-) + delete mode 100644 sound/soc/bcm/hifiberry_amp.c + delete mode 100644 sound/soc/codecs/tas5713.c + delete mode 100644 sound/soc/codecs/tas5713.h -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 9840e15d3e2be6396bc3ce6e74749408cc28c333..52ab9dea2e724c4238986ca53c59c8492f64e345 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index b1d877407dd69c9bd6b2787b0a559f4113bc21f2..4473cc728097bda0ce9fe68d4a9da348ec41f8b3 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -38,13 +38,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI + help + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - #include "../codecs/wm8804.h" +-config SND_BCM2708_SOC_HIFIBERRY_AMP +- tristate "Support for the HifiBerry Amp" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +- select SND_SOC_TAS5713 +- help +- Say Y or M if you want to add support for the HifiBerry Amp amplifier board. +- + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index a4838e2cf8e93c9285836f95f4151daea33e1bd1..203afc03167acbcad15e836209956bc5ab151157 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -12,13 +12,11 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o +-snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o -@@ -30,9 +31,34 @@ static short int auto_shutdown_output = 0; - module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o +-obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c +deleted file mode 100644 +index d17c29780507dc31c50f1d567ff5cea7c8241ff5..0000000000000000000000000000000000000000 +--- a/sound/soc/bcm/hifiberry_amp.c ++++ /dev/null +@@ -1,129 +0,0 @@ +-/* +- * ASoC Driver for HifiBerry AMP +- * +- * Author: Sebastian Eickhoff +- * Copyright 2014 +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * 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. +- */ +- +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) +-{ +- // ToDo: init of the dsp-registers. +- return 0; +-} +- +-static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params ) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- +- return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); +-} +- +-static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { +- .hw_params = snd_rpi_hifiberry_amp_hw_params, +-}; +- +-static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { +- { +- .name = "HifiBerry AMP", +- .stream_name = "HifiBerry AMP HiFi", +- .cpu_dai_name = "bcm2708-i2s.0", +- .codec_dai_name = "tas5713-hifi", +- .platform_name = "bcm2708-i2s.0", +- .codec_name = "tas5713.1-001b", +- .dai_fmt = SND_SOC_DAIFMT_I2S | +- SND_SOC_DAIFMT_NB_NF | +- SND_SOC_DAIFMT_CBS_CFS, +- .ops = &snd_rpi_hifiberry_amp_ops, +- .init = snd_rpi_hifiberry_amp_init, +- }, +-}; +- +- +-static struct snd_soc_card snd_rpi_hifiberry_amp = { +- .name = "snd_rpi_hifiberry_amp", +- .driver_name = "HifiberryAmp", +- .owner = THIS_MODULE, +- .dai_link = snd_rpi_hifiberry_amp_dai, +- .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), +-}; +- +-static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { +- { .compatible = "hifiberry,hifiberry-amp", }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); +- +- +-static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) +-{ +- int ret = 0; +- +- snd_rpi_hifiberry_amp.dev = &pdev->dev; +- +- if (pdev->dev.of_node) { +- struct device_node *i2s_node; +- struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; +- i2s_node = of_parse_phandle(pdev->dev.of_node, +- "i2s-controller", 0); +- +- if (i2s_node) { +- dai->cpu_dai_name = NULL; +- dai->cpu_of_node = i2s_node; +- dai->platform_name = NULL; +- dai->platform_of_node = i2s_node; +- } +- } +- +- ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); +- +- if (ret != 0) { +- dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); +- } +- +- return ret; +-} +- +- +-static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) +-{ +- return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); +-} +- +- +-static struct platform_driver snd_rpi_hifiberry_amp_driver = { +- .driver = { +- .name = "snd-hifiberry-amp", +- .owner = THIS_MODULE, +- .of_match_table = snd_rpi_hifiberry_amp_of_match, +- }, +- .probe = snd_rpi_hifiberry_amp_probe, +- .remove = snd_rpi_hifiberry_amp_remove, +-}; +- +- +-module_platform_driver(snd_rpi_hifiberry_amp_driver); +- +- +-MODULE_AUTHOR("Sebastian Eickhoff "); +-MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 9824cdd04b0c11c45b8cedd0187a0eba8f1dc2d4..74a93e52bdc8116df3db08aaf98fffa1e6f6cc1b 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -139,7 +139,6 @@ config SND_SOC_ALL_CODECS + select SND_SOC_TFA9879 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER +- select SND_SOC_TAS5713 if I2C + select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C + select SND_SOC_TLV320AIC32X4_I2C if I2C +@@ -822,9 +821,6 @@ config SND_SOC_TFA9879 + tristate "NXP Semiconductors TFA9879 amplifier" + depends on I2C -+#define CLK_44EN_RATE 22579200UL -+#define CLK_48EN_RATE 24576000UL -+ -+static bool snd_rpi_hifiberry_is_digipro; -+static struct gpio_desc *snd_rpi_hifiberry_clk44gpio; -+static struct gpio_desc *snd_rpi_hifiberry_clk48gpio; +-config SND_SOC_TAS5713 +- tristate +- + config SND_SOC_TLV320AIC23 + tristate - static int samplerate=44100; - -+static uint32_t snd_rpi_hifiberry_digi_enable_clock(int sample_rate) -+{ -+ switch (sample_rate) { -+ case 11025: -+ case 22050: -+ case 44100: -+ case 88200: -+ case 176400: -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 1); -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 0); -+ return CLK_44EN_RATE; -+ default: -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk48gpio, 1); -+ gpiod_set_value_cansleep(snd_rpi_hifiberry_clk44gpio, 0); -+ return CLK_48EN_RATE; -+ } -+} -+ -+ - static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) - { - struct snd_soc_codec *codec = rtd->codec; -@@ -40,6 +66,14 @@ static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) - /* enable TX output */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); - -+ /* Initialize Digi+ Pro hardware */ -+ if (snd_rpi_hifiberry_is_digipro) { -+ struct snd_soc_dai_link *dai = rtd->dai_link; -+ -+ dai->name = "HiFiBerry Digi+ Pro"; -+ dai->stream_name = "HiFiBerry Digi+ Pro HiFi"; -+ } -+ - return 0; - } - -@@ -87,6 +121,9 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - mclk_freq=samplerate*128; - mclk_div=WM8804_MCLKDIV_128FS; - } -+ -+ if (snd_rpi_hifiberry_is_digipro) -+ sysclk = snd_rpi_hifiberry_digi_enable_clock(samplerate); - - switch (samplerate) { - case 32000: -@@ -121,6 +158,7 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - - ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, - sysclk, SND_SOC_CLOCK_OUT); -+ - if (ret < 0) { - dev_err(codec->dev, - "Failed to set WM8804 SYSCLK: %d\n", ret); -@@ -187,6 +225,19 @@ static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) - dai->platform_name = NULL; - dai->platform_of_node = i2s_node; - } -+ -+ snd_rpi_hifiberry_is_digipro = 1; -+ -+ snd_rpi_hifiberry_clk44gpio = -+ devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW); -+ if (IS_ERR(snd_rpi_hifiberry_clk44gpio)) -+ snd_rpi_hifiberry_is_digipro = 0; -+ -+ snd_rpi_hifiberry_clk48gpio = -+ devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW); -+ if (IS_ERR(snd_rpi_hifiberry_clk48gpio)) -+ snd_rpi_hifiberry_is_digipro = 0; -+ - } - - ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 5a2db0d2fe2f49920eeccfecef62c969ae2e99a1..77786e7f44a7fa22d9b5beed3eb687e2b7a28526 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -144,7 +144,6 @@ snd-soc-tas5086-objs := tas5086.o + snd-soc-tas571x-objs := tas571x.o + snd-soc-tas5720-objs := tas5720.o + snd-soc-tfa9879-objs := tfa9879.o +-snd-soc-tas5713-objs := tas5713.o + snd-soc-tlv320aic23-objs := tlv320aic23.o + snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o + snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o +@@ -367,7 +366,6 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o + obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o + obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o + obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o +-obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o + obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o +diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c +deleted file mode 100644 +index 9b2713861dcbed751842ca29c88eb1eae5867411..0000000000000000000000000000000000000000 +--- a/sound/soc/codecs/tas5713.c ++++ /dev/null +@@ -1,369 +0,0 @@ +-/* +- * ASoC Driver for TAS5713 +- * +- * Author: Sebastian Eickhoff +- * Copyright 2014 +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * 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. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include "tas5713.h" +- +- +-static struct i2c_client *i2c; +- +-struct tas5713_priv { +- struct regmap *regmap; +- int mclk_div; +- struct snd_soc_codec *codec; +-}; +- +-static struct tas5713_priv *priv_data; +- +- +- +- +-/* +- * _ _ ___ _ ___ _ _ +- * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ +- * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< +- * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ +- * +- */ +- +-static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); +- +- +-static const struct snd_kcontrol_new tas5713_snd_controls[] = { +- SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), +- SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) +-}; +- +- +- +- +-/* +- * __ __ _ _ ___ _ +- * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ +- * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| +- * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| +- * +- */ +- +-static int tas5713_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct snd_soc_dai *dai) +-{ +- u16 blen = 0x00; +- +- struct snd_soc_codec *codec; +- codec = dai->codec; +- priv_data->codec = dai->codec; +- +- switch (params_format(params)) { +- case SNDRV_PCM_FORMAT_S16_LE: +- blen = 0x03; +- break; +- case SNDRV_PCM_FORMAT_S20_3LE: +- blen = 0x1; +- break; +- case SNDRV_PCM_FORMAT_S24_LE: +- blen = 0x04; +- break; +- case SNDRV_PCM_FORMAT_S32_LE: +- blen = 0x05; +- break; +- default: +- dev_err(dai->dev, "Unsupported word length: %u\n", +- params_format(params)); +- return -EINVAL; +- } +- +- // set word length +- snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); +- +- return 0; +-} +- +- +-static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +-{ +- unsigned int val = 0; +- +- struct tas5713_priv *tas5713; +- struct snd_soc_codec *codec = dai->codec; +- tas5713 = snd_soc_codec_get_drvdata(codec); +- +- if (mute) { +- val = TAS5713_SOFT_MUTE_ALL; +- } +- +- return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); +-} +- +- +-static const struct snd_soc_dai_ops tas5713_dai_ops = { +- .hw_params = tas5713_hw_params, +- .mute_stream = tas5713_mute_stream, +-}; +- +- +-static struct snd_soc_dai_driver tas5713_dai = { +- .name = "tas5713-hifi", +- .playback = { +- .stream_name = "Playback", +- .channels_min = 2, +- .channels_max = 2, +- .rates = SNDRV_PCM_RATE_8000_48000, +- .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), +- }, +- .ops = &tas5713_dai_ops, +-}; +- +- +- +- +-/* +- * ___ _ ___ _ +- * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ +- * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| +- * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| +- * +- */ +- +-static int tas5713_remove(struct snd_soc_codec *codec) +-{ +- struct tas5713_priv *tas5713; +- +- tas5713 = snd_soc_codec_get_drvdata(codec); +- +- return 0; +-} +- +- +-static int tas5713_probe(struct snd_soc_codec *codec) +-{ +- struct tas5713_priv *tas5713; +- int i, ret; +- +- i2c = container_of(codec->dev, struct i2c_client, dev); +- +- tas5713 = snd_soc_codec_get_drvdata(codec); +- +- // Reset error +- ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); +- if (ret < 0) return ret; +- +- // Trim oscillator +- ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); +- if (ret < 0) return ret; +- msleep(1000); +- +- // Reset error +- ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); +- if (ret < 0) return ret; +- +- // Clock mode: 44/48kHz, MCLK=64xfs +- ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); +- if (ret < 0) return ret; +- +- // I2S 24bit +- ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); +- if (ret < 0) return ret; +- +- // Unmute +- ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); +- if (ret < 0) return ret; +- ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); +- if (ret < 0) return ret; +- +- // Set volume to 0db +- ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); +- if (ret < 0) return ret; +- +- // Now start programming the default initialization sequence +- for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { +- ret = i2c_master_send(i2c, +- tas5713_init_sequence[i].data, +- tas5713_init_sequence[i].size); +- if (ret < 0) { +- printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); +- } +- } +- +- // Unmute +- ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); +- if (ret < 0) return ret; +- +- return 0; +-} +- +- +-static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { +- .probe = tas5713_probe, +- .remove = tas5713_remove, +- .controls = tas5713_snd_controls, +- .num_controls = ARRAY_SIZE(tas5713_snd_controls), +-}; +- +- +- +- +-/* +- * ___ ___ ___ ___ _ +- * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ +- * | | / / (__ | |) | '_| \ V / -_) '_| +- * |___/___\___| |___/|_| |_|\_/\___|_| +- * +- */ +- +-static const struct reg_default tas5713_reg_defaults[] = { +- { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB +- { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB +- { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB +- { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB +-}; +- +- +-static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) +-{ +- switch (reg) { +- case TAS5713_DEVICE_ID: +- case TAS5713_ERROR_STATUS: +- return true; +- default: +- return false; +- } +-} +- +- +-static const struct of_device_id tas5713_of_match[] = { +- { .compatible = "ti,tas5713", }, +- { } +-}; +-MODULE_DEVICE_TABLE(of, tas5713_of_match); +- +- +-static struct regmap_config tas5713_regmap_config = { +- .reg_bits = 8, +- .val_bits = 8, +- +- .max_register = TAS5713_MAX_REGISTER, +- .volatile_reg = tas5713_reg_volatile, +- +- .cache_type = REGCACHE_RBTREE, +- .reg_defaults = tas5713_reg_defaults, +- .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), +-}; +- +- +-static int tas5713_i2c_probe(struct i2c_client *i2c, +- const struct i2c_device_id *id) +-{ +- int ret; +- +- priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); +- if (!priv_data) +- return -ENOMEM; +- +- priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); +- if (IS_ERR(priv_data->regmap)) { +- ret = PTR_ERR(priv_data->regmap); +- return ret; +- } +- +- i2c_set_clientdata(i2c, priv_data); +- +- ret = snd_soc_register_codec(&i2c->dev, +- &soc_codec_dev_tas5713, &tas5713_dai, 1); +- +- return ret; +-} +- +- +-static int tas5713_i2c_remove(struct i2c_client *i2c) +-{ +- snd_soc_unregister_codec(&i2c->dev); +- i2c_set_clientdata(i2c, NULL); +- +- kfree(priv_data); +- +- return 0; +-} +- +- +-static const struct i2c_device_id tas5713_i2c_id[] = { +- { "tas5713", 0 }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); +- +- +-static struct i2c_driver tas5713_i2c_driver = { +- .driver = { +- .name = "tas5713", +- .owner = THIS_MODULE, +- .of_match_table = tas5713_of_match, +- }, +- .probe = tas5713_i2c_probe, +- .remove = tas5713_i2c_remove, +- .id_table = tas5713_i2c_id +-}; +- +- +-static int __init tas5713_modinit(void) +-{ +- int ret = 0; +- +- ret = i2c_add_driver(&tas5713_i2c_driver); +- if (ret) { +- printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", +- ret); +- } +- +- return ret; +-} +-module_init(tas5713_modinit); +- +- +-static void __exit tas5713_exit(void) +-{ +- i2c_del_driver(&tas5713_i2c_driver); +-} +-module_exit(tas5713_exit); +- +- +-MODULE_AUTHOR("Sebastian Eickhoff "); +-MODULE_DESCRIPTION("ASoC driver for TAS5713"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h +deleted file mode 100644 +index 8f019e04898754d2f87e9630137be9e8f612a342..0000000000000000000000000000000000000000 +--- a/sound/soc/codecs/tas5713.h ++++ /dev/null +@@ -1,210 +0,0 @@ +-/* +- * ASoC Driver for TAS5713 +- * +- * Author: Sebastian Eickhoff +- * Copyright 2014 +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * 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. +- */ +- +-#ifndef _TAS5713_H +-#define _TAS5713_H +- +- +-// TAS5713 I2C-bus register addresses +- +-#define TAS5713_CLOCK_CTRL 0x00 +-#define TAS5713_DEVICE_ID 0x01 +-#define TAS5713_ERROR_STATUS 0x02 +-#define TAS5713_SYSTEM_CTRL1 0x03 +-#define TAS5713_SERIAL_DATA_INTERFACE 0x04 +-#define TAS5713_SYSTEM_CTRL2 0x05 +-#define TAS5713_SOFT_MUTE 0x06 +-#define TAS5713_VOL_MASTER 0x07 +-#define TAS5713_VOL_CH1 0x08 +-#define TAS5713_VOL_CH2 0x09 +-#define TAS5713_VOL_HEADPHONE 0x0A +-#define TAS5713_VOL_CONFIG 0x0E +-#define TAS5713_MODULATION_LIMIT 0x10 +-#define TAS5713_IC_DLY_CH1 0x11 +-#define TAS5713_IC_DLY_CH2 0x12 +-#define TAS5713_IC_DLY_CH3 0x13 +-#define TAS5713_IC_DLY_CH4 0x14 +- +-#define TAS5713_START_STOP_PERIOD 0x1A +-#define TAS5713_OSC_TRIM 0x1B +-#define TAS5713_BKND_ERR 0x1C +- +-#define TAS5713_INPUT_MUX 0x20 +-#define TAS5713_SRC_SELECT_CH4 0x21 +-#define TAS5713_PWM_MUX 0x25 +- +-#define TAS5713_CH1_BQ0 0x29 +-#define TAS5713_CH1_BQ1 0x2A +-#define TAS5713_CH1_BQ2 0x2B +-#define TAS5713_CH1_BQ3 0x2C +-#define TAS5713_CH1_BQ4 0x2D +-#define TAS5713_CH1_BQ5 0x2E +-#define TAS5713_CH1_BQ6 0x2F +-#define TAS5713_CH1_BQ7 0x58 +-#define TAS5713_CH1_BQ8 0x59 +- +-#define TAS5713_CH2_BQ0 0x30 +-#define TAS5713_CH2_BQ1 0x31 +-#define TAS5713_CH2_BQ2 0x32 +-#define TAS5713_CH2_BQ3 0x33 +-#define TAS5713_CH2_BQ4 0x34 +-#define TAS5713_CH2_BQ5 0x35 +-#define TAS5713_CH2_BQ6 0x36 +-#define TAS5713_CH2_BQ7 0x5C +-#define TAS5713_CH2_BQ8 0x5D +- +-#define TAS5713_CH4_BQ0 0x5A +-#define TAS5713_CH4_BQ1 0x5B +-#define TAS5713_CH3_BQ0 0x5E +-#define TAS5713_CH3_BQ1 0x5F +- +-#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B +-#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C +-#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E +-#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F +-#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 +-#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 +-#define TAS5713_DRC_CTRL 0x46 +- +-#define TAS5713_BANK_SW_CTRL 0x50 +-#define TAS5713_CH1_OUTPUT_MIXER 0x51 +-#define TAS5713_CH2_OUTPUT_MIXER 0x52 +-#define TAS5713_CH1_INPUT_MIXER 0x53 +-#define TAS5713_CH2_INPUT_MIXER 0x54 +-#define TAS5713_OUTPUT_POST_SCALE 0x56 +-#define TAS5713_OUTPUT_PRESCALE 0x57 +- +-#define TAS5713_IDF_POST_SCALE 0x62 +- +-#define TAS5713_CH1_INLINE_MIXER 0x70 +-#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 +-#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 +-#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 +-#define TAS5713_CH2_INLINE_MIXER 0x74 +-#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 +-#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 +-#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 +- +-#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 +-#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 +- +-#define TAS5713_REGISTER_COUNT 0x46 +-#define TAS5713_MAX_REGISTER 0xF9 +- +- +-// Bitmasks for registers +-#define TAS5713_SOFT_MUTE_ALL 0x07 +- +- +- +-struct tas5713_init_command { +- const int size; +- const char *const data; +-}; +- +-static const struct tas5713_init_command tas5713_init_sequence[] = { +- +- // Trim oscillator +- { .size = 2, .data = "\x1B\x00" }, +- // System control register 1 (0x03): block DC +- { .size = 2, .data = "\x03\x80" }, +- // Mute everything +- { .size = 2, .data = "\x05\x40" }, +- // Modulation limit register (0x10): 97.7% +- { .size = 2, .data = "\x10\x02" }, +- // Interchannel delay registers +- // (0x11, 0x12, 0x13, and 0x14): BD mode +- { .size = 2, .data = "\x11\xB8" }, +- { .size = 2, .data = "\x12\x60" }, +- { .size = 2, .data = "\x13\xA0" }, +- { .size = 2, .data = "\x14\x48" }, +- // PWM shutdown group register (0x19): no shutdown +- { .size = 2, .data = "\x19\x00" }, +- // Input multiplexer register (0x20): BD mode +- { .size = 2, .data = "\x20\x00\x89\x77\x72" }, +- // PWM output mux register (0x25) +- // Channel 1 --> OUTA, channel 1 neg --> OUTB +- // Channel 2 --> OUTC, channel 2 neg --> OUTD +- { .size = 5, .data = "\x25\x01\x02\x13\x45" }, +- // DRC control (0x46): DRC off +- { .size = 5, .data = "\x46\x00\x00\x00\x00" }, +- // BKND_ERR register (0x1C): 299ms reset period +- { .size = 2, .data = "\x1C\x07" }, +- // Mute channel 3 +- { .size = 2, .data = "\x0A\xFF" }, +- // Volume configuration register (0x0E): volume slew 512 steps +- { .size = 2, .data = "\x0E\x90" }, +- // Clock control register (0x00): 44/48kHz, MCLK=64xfs +- { .size = 2, .data = "\x00\x60" }, +- // Bank switch and eq control (0x50): no bank switching +- { .size = 5, .data = "\x50\x00\x00\x00\x00" }, +- // Volume registers (0x07, 0x08, 0x09, 0x0A) +- { .size = 2, .data = "\x07\x20" }, +- { .size = 2, .data = "\x08\x30" }, +- { .size = 2, .data = "\x09\x30" }, +- { .size = 2, .data = "\x0A\xFF" }, +- // 0x72, 0x73, 0x76, 0x77 input mixer: +- // no intermix between channels +- { .size = 5, .data = "\x72\x00\x00\x00\x00" }, +- { .size = 5, .data = "\x73\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x76\x00\x00\x00\x00" }, +- { .size = 5, .data = "\x77\x00\x80\x00\x00" }, +- // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: +- // no inline DRC inmix +- { .size = 5, .data = "\x70\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x71\x00\x00\x00\x00" }, +- { .size = 5, .data = "\x74\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x75\x00\x00\x00\x00" }, +- // 0x56, 0x57 Output scale +- { .size = 5, .data = "\x56\x00\x80\x00\x00" }, +- { .size = 5, .data = "\x57\x00\x02\x00\x00" }, +- // 0x3B, 0x3c +- { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, +- { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, +- { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, +- // 0x51, 0x52: output mixer +- { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, +- { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, +- // PEQ defaults +- { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +- { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, +-}; +- +- +-#endif /* _TAS5713_H */ -From ca49f7825bbd719ed413c05a07a4c004b598850c Mon Sep 17 00:00:00 2001 +From 3696c3507465b578e9db9edcf2567f9cc4f50ea9 Mon Sep 17 00:00:00 2001 From: Ryan Coe Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 081/208] Update ds1307 driver for device-tree support +Subject: [PATCH 074/111] Update ds1307 driver for device-tree support Signed-off-by: Ryan Coe --- @@ -129197,10 +114026,10 @@ Signed-off-by: Ryan Coe 1 file changed, 8 insertions(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index 8e1c5cb6ece6f60619e5cafcea4271e056d96778..f9536679b270a39a4d9639fdbd3420fecbf1d169 100644 +index 4e31036ee2596dec93accd26f627c5b95591ae9f..b92044cf03e750afa521a93519500e9d128486f4 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c -@@ -1631,6 +1631,14 @@ static int ds1307_remove(struct i2c_client *client) +@@ -1675,6 +1675,14 @@ static int ds1307_remove(struct i2c_client *client) return 0; } @@ -129216,10 +114045,10 @@ index 8e1c5cb6ece6f60619e5cafcea4271e056d96778..f9536679b270a39a4d9639fdbd3420fe .driver = { .name = "rtc-ds1307", -From cbc94ab92e62b8628bd4648e2391ee1582c199ba Mon Sep 17 00:00:00 2001 +From f4ce7691f7e0dd6c047041d87e29876365e6ee27 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 082/208] Add driver for rpi-proto +Subject: [PATCH 075/111] Add driver for rpi-proto Forward port of 3.10.x driver from https://github.com/koalo We are using a custom board and would like to use rpi 3.18.x @@ -129239,10 +114068,10 @@ Signed-off-by: Waldemar Brodkorb create mode 100644 sound/soc/bcm/rpi-proto.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index f764110b86b790a2b639cc66b965e187d9f52ce3..5b08c4dfb71597d6f6381146c4ce79e57f551b9c 100644 +index 4473cc728097bda0ce9fe68d4a9da348ec41f8b3..ac0dbaf29b821c4b21855f22104a986f6e0849ec 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -52,6 +52,13 @@ config SND_BCM2708_SOC_RPI_DAC +@@ -45,6 +45,13 @@ config SND_BCM2708_SOC_RPI_DAC help Say Y or M if you want to add support for RPi-DAC. @@ -129257,20 +114086,19 @@ index f764110b86b790a2b639cc66b965e187d9f52ce3..5b08c4dfb71597d6f6381146c4ce79e5 tristate "Support for IQaudIO-DAC" depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index a4838e2cf8e93c9285836f95f4151daea33e1bd1..680d1b6d5e16819094fbfaa6c42b458267b54819 100644 +index 203afc03167acbcad15e836209956bc5ab151157..3badc43cbe1fcb6972829a6d5eb3143cfa812da9 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -14,6 +14,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o +@@ -13,10 +13,12 @@ snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-hifiberry-amp-objs := hifiberry_amp.o snd-soc-rpi-dac-objs := rpi-dac.o +snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -21,4 +22,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o @@ -129435,10 +114263,10 @@ index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed67 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From e31208717f0fc90e3e5d82e10408540c9272a69e Mon Sep 17 00:00:00 2001 +From 3eaf5ac6549cc9b659ae23f1b02960801ae2b2ca Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:03:47 +0100 -Subject: [PATCH 083/208] RaspiDAC3 support +Subject: [PATCH 076/111] RaspiDAC3 support Signed-off-by: Jan Grulich @@ -129456,10 +114284,10 @@ Signed-off-by: Matthias Reichl create mode 100644 sound/soc/bcm/raspidac3.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 5b08c4dfb71597d6f6381146c4ce79e57f551b9c..e07f8b74497fe3b271290cc4e6a1c49a2e84c29c 100644 +index ac0dbaf29b821c4b21855f22104a986f6e0849ec..c59c835757a51aa8ad72933d35a83b73a889477c 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -65,3 +65,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC +@@ -58,3 +58,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC select SND_SOC_PCM512x_I2C help Say Y or M if you want to add support for IQaudIO-DAC. @@ -129472,10 +114300,10 @@ index 5b08c4dfb71597d6f6381146c4ce79e57f551b9c..e07f8b74497fe3b271290cc4e6a1c49a + help + Say Y or M if you want to add support for RaspiDAC Rev.3x. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 680d1b6d5e16819094fbfaa6c42b458267b54819..18253b39addf831780fefe85578e72007c0d51d9 100644 +index 3badc43cbe1fcb6972829a6d5eb3143cfa812da9..07d2b52376b1d16e427cf6f51cbf4779d6219ce0 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -16,6 +16,7 @@ snd-soc-hifiberry-amp-objs := hifiberry_amp.o +@@ -15,6 +15,7 @@ snd-soc-hifiberry-digi-objs := hifiberry_digi.o snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o @@ -129483,7 +114311,7 @@ index 680d1b6d5e16819094fbfaa6c42b458267b54819..18253b39addf831780fefe85578e7200 obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o -@@ -24,3 +25,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -22,3 +23,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o @@ -129681,10 +114509,10 @@ index 0000000000000000000000000000000000000000..dd9eeea2af0382307f437e6db09d1546 +MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); +MODULE_LICENSE("GPL v2"); -From 0dbf63d7ac2e0f2ccb758b7641bb24d75fa3e99e Mon Sep 17 00:00:00 2001 +From a86f56673950aa0eafca22c4d2c393744d49032d Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Thu, 7 Apr 2016 21:26:21 +0100 -Subject: [PATCH 084/208] Add Support for JustBoom Audio boards +Subject: [PATCH 077/111] Add Support for JustBoom Audio boards justboom-dac: Adjust for ALSA API change @@ -129702,10 +114530,10 @@ Signed-off-by: Phil Elwell create mode 100644 sound/soc/bcm/justboom-digi.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index e07f8b74497fe3b271290cc4e6a1c49a2e84c29c..b8fcd82f1e9ccabaae307b07fa17bdec57c173a1 100644 +index c59c835757a51aa8ad72933d35a83b73a889477c..b2f6339c318cdfe3516d73952a5be1fd32bc1156 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -59,6 +59,20 @@ config SND_BCM2708_SOC_RPI_PROTO +@@ -52,6 +52,20 @@ config SND_BCM2708_SOC_RPI_PROTO help Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). @@ -129727,22 +114555,22 @@ index e07f8b74497fe3b271290cc4e6a1c49a2e84c29c..b8fcd82f1e9ccabaae307b07fa17bdec tristate "Support for IQaudIO-DAC" depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 18253b39addf831780fefe85578e72007c0d51d9..ddffe5d69f29878afb4f286abe69c2c787cf169e 100644 +index 07d2b52376b1d16e427cf6f51cbf4779d6219ce0..cb8ab1901b172bdee0bd9cddd2f2e7ab2f36c16a 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -13,6 +13,8 @@ snd-soc-hifiberry-dac-objs := hifiberry_dac.o +@@ -12,6 +12,8 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-hifiberry-amp-objs := hifiberry_amp.o +snd-soc-justboom-dac-objs := justboom-dac.o +snd-soc-justboom-digi-objs := justboom-digi.o snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o -@@ -22,6 +24,8 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +@@ -20,6 +22,8 @@ snd-soc-raspidac3-objs := raspidac3.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o @@ -130138,10 +114966,10 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); +MODULE_LICENSE("GPL v2"); -From 3c1739ef8bbd37c97af637e792f7dc604eb0dbac Mon Sep 17 00:00:00 2001 +From 14fbb06425bbc30d2d42de634942532006313b58 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 3 May 2016 22:10:59 -0400 -Subject: [PATCH 085/208] ARM: adau1977-adc: Add basic machine driver for +Subject: [PATCH 078/111] ARM: adau1977-adc: Add basic machine driver for adau1977 codec driver. This commit adds basic support for the codec usage including: Device tree overlay, @@ -130157,10 +114985,10 @@ Signed-off-by: Andrey Grodzovsky create mode 100644 sound/soc/bcm/adau1977-adc.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index b8fcd82f1e9ccabaae307b07fa17bdec57c173a1..cacc10431c5b82b000f5b71b1c1256f19073dc16 100644 +index b2f6339c318cdfe3516d73952a5be1fd32bc1156..190a79dffa53a34c2df9b2c9b5160065c759de65 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -87,3 +87,10 @@ config SND_BCM2708_SOC_RASPIDAC3 +@@ -80,3 +80,10 @@ config SND_BCM2708_SOC_RASPIDAC3 select SND_SOC_TPA6130A2 help Say Y or M if you want to add support for RaspiDAC Rev.3x. @@ -130172,7 +115000,7 @@ index b8fcd82f1e9ccabaae307b07fa17bdec57c173a1..cacc10431c5b82b000f5b71b1c1256f1 + help + Say Y or M if you want to add support for ADAU1977 ADC. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index ddffe5d69f29878afb4f286abe69c2c787cf169e..63584bc364ed266b8e9eb30afab0a631b97b145c 100644 +index cb8ab1901b172bdee0bd9cddd2f2e7ab2f36c16a..9dd0785532aae24f3366cc2910d4dbc558cb0e5d 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -9,6 +9,7 @@ snd-soc-cygnus-objs := cygnus-pcm.o cygnus-ssp.o @@ -130183,7 +115011,7 @@ index ddffe5d69f29878afb4f286abe69c2c787cf169e..63584bc364ed266b8e9eb30afab0a631 snd-soc-hifiberry-dac-objs := hifiberry_dac.o snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o -@@ -20,6 +21,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o +@@ -19,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o snd-soc-raspidac3-objs := raspidac3.o @@ -130323,10 +115151,10 @@ index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d +MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); +MODULE_LICENSE("GPL v2"); -From d653d98735f512ced56df4968813e513fd93afdb Mon Sep 17 00:00:00 2001 +From e1215eff5db9d0e68052f3a3e9f87c2d8f5bae1c Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 16 May 2016 21:36:31 +1000 -Subject: [PATCH 086/208] New AudioInjector.net Pi soundcard with low jitter +Subject: [PATCH 079/111] New AudioInjector.net Pi soundcard with low jitter audio in and out. Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile. @@ -130340,15 +115168,15 @@ This patch adds headphone and microphone capability to the Audio Injector sound --- sound/soc/bcm/Kconfig | 7 ++ sound/soc/bcm/Makefile | 3 + - sound/soc/bcm/audioinjector-pi-soundcard.c | 191 +++++++++++++++++++++++++++++ - 3 files changed, 201 insertions(+) + sound/soc/bcm/audioinjector-pi-soundcard.c | 193 +++++++++++++++++++++++++++++ + 3 files changed, 203 insertions(+) create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index cacc10431c5b82b000f5b71b1c1256f19073dc16..214aa1314ef97dff7422a4743024ddb4ae114912 100644 +index 190a79dffa53a34c2df9b2c9b5160065c759de65..eb16c3a7fb316eb5938a54dfa864f66f9b167eb0 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -94,3 +94,10 @@ config SND_BCM2708_SOC_ADAU1977_ADC +@@ -87,3 +87,10 @@ config SND_BCM2708_SOC_ADAU1977_ADC select SND_SOC_ADAU1977_I2C help Say Y or M if you want to add support for ADAU1977 ADC. @@ -130360,10 +115188,10 @@ index cacc10431c5b82b000f5b71b1c1256f19073dc16..214aa1314ef97dff7422a4743024ddb4 + help + Say Y or M if you want to add support for audioinjector.net Pi Hat diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 63584bc364ed266b8e9eb30afab0a631b97b145c..eb21e3baff008959ba41b5c816ecaff4462900ed 100644 +index 9dd0785532aae24f3366cc2910d4dbc558cb0e5d..a68469644535a38305bb5b0f3780e03e0ca4f519 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -20,6 +20,7 @@ snd-soc-rpi-dac-objs := rpi-dac.o +@@ -19,6 +19,7 @@ snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o snd-soc-raspidac3-objs := raspidac3.o @@ -130371,7 +115199,7 @@ index 63584bc364ed266b8e9eb30afab0a631b97b145c..eb21e3baff008959ba41b5c816ecaff4 obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -32,3 +33,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +@@ -30,3 +31,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o @@ -130379,10 +115207,10 @@ index 63584bc364ed266b8e9eb30afab0a631b97b145c..eb21e3baff008959ba41b5c816ecaff4 + diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c new file mode 100644 -index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7c68d9e99 +index 0000000000000000000000000000000000000000..ef54e0f07ea03f59e9957b5d98f3e7fdc998e469 --- /dev/null +++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -0,0 +1,191 @@ +@@ -0,0 +1,193 @@ +/* + * ASoC Driver for AudioInjector Pi add on soundcard + * @@ -130415,7 +115243,7 @@ index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7 +#include "../codecs/wm8731.h" + +static const unsigned int bcm2835_rates_12000000[] = { -+ 32000, 44100, 48000, 96000, 88200, ++ 8000, 16000, 32000, 44100, 48000, 96000, 88200, +}; + +static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { @@ -130440,19 +115268,21 @@ index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7 + + switch (params_rate(params)){ + case 8000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1); ++ case 16000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 750); + case 32000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 375); + case 44100: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 272); + case 48000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 250); + case 88200: + return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); + case 96000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); + default: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); + } +} + @@ -130575,10 +115405,10 @@ index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7 +MODULE_ALIAS("platform:audioinjector-pi-soundcard"); + -From 83acbad0b2688cd44fbb7293d219394a8ff4f435 Mon Sep 17 00:00:00 2001 +From 3abc67377cca7ff4e63ad2496a53a4454b9d1555 Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Thu, 30 Jun 2016 18:38:42 +0100 -Subject: [PATCH 087/208] Add IQAudIO Digi WM8804 board support +Subject: [PATCH 080/111] Add IQAudIO Digi WM8804 board support Support IQAudIO Digi board with iqaudio_digi machine driver and iqaudio-digi-wm8804-audio overlay. @@ -130595,10 +115425,10 @@ Signed-off-by: DigitalDreamtime create mode 100644 sound/soc/bcm/iqaudio_digi.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 214aa1314ef97dff7422a4743024ddb4ae114912..f85c6b1e8835e1a76bfa5be1bee69aaeec631a70 100644 +index eb16c3a7fb316eb5938a54dfa864f66f9b167eb0..9cba69ab877ef73beb2dff2f4f82d1d243f7c604 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -80,6 +80,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC +@@ -73,6 +73,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC help Say Y or M if you want to add support for IQaudIO-DAC. @@ -130613,10 +115443,10 @@ index 214aa1314ef97dff7422a4743024ddb4ae114912..f85c6b1e8835e1a76bfa5be1bee69aae tristate "Support for RaspiDAC Rev.3x" depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index eb21e3baff008959ba41b5c816ecaff4462900ed..0316dcaa3148dc60dfe9d10dabb6b4d0b0eea875 100644 +index a68469644535a38305bb5b0f3780e03e0ca4f519..fa2739206b79a9f9d2e1173b2099e1156e4e08c8 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -19,6 +19,7 @@ snd-soc-justboom-digi-objs := justboom-digi.o +@@ -18,6 +18,7 @@ snd-soc-justboom-digi-objs := justboom-digi.o snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o @@ -130624,7 +115454,7 @@ index eb21e3baff008959ba41b5c816ecaff4462900ed..0316dcaa3148dc60dfe9d10dabb6b4d0 snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o -@@ -32,6 +33,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o +@@ -30,6 +31,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o @@ -130878,10 +115708,10 @@ index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e78163196 +MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); +MODULE_LICENSE("GPL v2"); -From 6004b4aced007bc18f0bf6b2fe006cc23f537e5c Mon Sep 17 00:00:00 2001 +From 8d49dfc240c29fc3296d25559303f72a521f0141 Mon Sep 17 00:00:00 2001 From: escalator2015 Date: Tue, 24 May 2016 16:20:09 +0100 -Subject: [PATCH 088/208] New driver for RRA DigiDAC1 soundcard using WM8741 + +Subject: [PATCH 081/111] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 --- @@ -130892,10 +115722,10 @@ Subject: [PATCH 088/208] New driver for RRA DigiDAC1 soundcard using WM8741 + create mode 100644 sound/soc/bcm/digidac1-soundcard.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index f85c6b1e8835e1a76bfa5be1bee69aaeec631a70..04edcfdbb6ce5910a0704e6f1d1edd6fd97631e3 100644 +index 9cba69ab877ef73beb2dff2f4f82d1d243f7c604..2be5b64fb0d5dcad0d5747626015a6886c3c273b 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -108,3 +108,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD +@@ -101,3 +101,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD select SND_SOC_WM8731 help Say Y or M if you want to add support for audioinjector.net Pi Hat @@ -130908,10 +115738,10 @@ index f85c6b1e8835e1a76bfa5be1bee69aaeec631a70..04edcfdbb6ce5910a0704e6f1d1edd6f + help + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 0316dcaa3148dc60dfe9d10dabb6b4d0b0eea875..b407091a168af15062df7bc6410e48e3f92acd49 100644 +index fa2739206b79a9f9d2e1173b2099e1156e4e08c8..a5c30c0bdacafb2bd09b6ac2f8a3bdc6a85a8404 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -22,6 +22,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o +@@ -21,6 +21,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o snd-soc-iqaudio-digi-objs := iqaudio_digi.o snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o @@ -130919,7 +115749,7 @@ index 0316dcaa3148dc60dfe9d10dabb6b4d0b0eea875..b407091a168af15062df7bc6410e48e3 obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -36,4 +37,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +@@ -34,4 +35,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o @@ -131354,10 +116184,10 @@ index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0 +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); +MODULE_LICENSE("GPL v2"); -From c9186592a8d8b0de5f1b198d154819283b3ff954 Mon Sep 17 00:00:00 2001 +From 9a617cde3a19d6e794a531fc97056d3712acc6d0 Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Sat, 2 Jul 2016 16:26:19 +0100 -Subject: [PATCH 089/208] Add support for Dion Audio LOCO DAC-AMP HAT +Subject: [PATCH 082/111] Add support for Dion Audio LOCO DAC-AMP HAT Using dedicated machine driver and pcm5102a codec driver. @@ -131370,10 +116200,10 @@ Signed-off-by: DigitalDreamtime create mode 100644 sound/soc/bcm/dionaudio_loco.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 04edcfdbb6ce5910a0704e6f1d1edd6fd97631e3..7eafe2c62d716d490df87f9c6fd92bf3b9100124 100644 +index 2be5b64fb0d5dcad0d5747626015a6886c3c273b..b8cb5eb7af9b3e6d8d100926e04bfef629641d1d 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -116,3 +116,10 @@ config SND_DIGIDAC1_SOUNDCARD +@@ -109,3 +109,10 @@ config SND_DIGIDAC1_SOUNDCARD select SND_SOC_WM8741 help Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. @@ -131385,10 +116215,10 @@ index 04edcfdbb6ce5910a0704e6f1d1edd6fd97631e3..7eafe2c62d716d490df87f9c6fd92bf3 + help + Say Y or M if you want to add support for Dion Audio LOCO. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index b407091a168af15062df7bc6410e48e3f92acd49..2c233080c40938c38f11bed79304830fda851ae4 100644 +index a5c30c0bdacafb2bd09b6ac2f8a3bdc6a85a8404..28cdf019dbc7aafda194c83817d260ad1a477666 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -23,6 +23,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_digi.o +@@ -22,6 +22,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_digi.o snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o @@ -131396,7 +116226,7 @@ index b407091a168af15062df7bc6410e48e3f92acd49..2c233080c40938c38f11bed79304830f obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -38,4 +39,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o +@@ -36,4 +37,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o @@ -131530,10 +116360,10 @@ index 0000000000000000000000000000000000000000..89e65317512bc774453ac8d0d5b0ff98 +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); +MODULE_LICENSE("GPL v2"); -From 20d707ddfb3d107dc828e607f181cce0a71d37de Mon Sep 17 00:00:00 2001 +From 3dcce9c448e2c55b6613864b70a105c7194a6c04 Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Mon, 19 Sep 2016 14:01:04 +0100 -Subject: [PATCH 090/208] Allo Piano DAC boards: Initial 2 channel (stereo) +Subject: [PATCH 083/111] Allo Piano DAC boards: Initial 2 channel (stereo) support (#1645) Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards, @@ -131558,10 +116388,10 @@ Tested-by: Clive Messer create mode 100644 sound/soc/bcm/allo-piano-dac.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 7eafe2c62d716d490df87f9c6fd92bf3b9100124..4ccaba67a887432afe7f527569c4e2865925734b 100644 +index b8cb5eb7af9b3e6d8d100926e04bfef629641d1d..4f0330a6c06115f077938cba3dc744d4ae10f056 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -123,3 +123,10 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO +@@ -116,3 +116,10 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO select SND_SOC_PCM5102a help Say Y or M if you want to add support for Dion Audio LOCO. @@ -131573,10 +116403,10 @@ index 7eafe2c62d716d490df87f9c6fd92bf3b9100124..4ccaba67a887432afe7f527569c4e286 + help + Say Y or M if you want to add support for Allo Piano DAC. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 2c233080c40938c38f11bed79304830fda851ae4..b9f98f0bcf3ee0d6b490e1bb185ba0de8f0f9701 100644 +index 28cdf019dbc7aafda194c83817d260ad1a477666..4b94a42efecaee41df37f3c59fddefa5fe78521c 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -24,6 +24,7 @@ snd-soc-raspidac3-objs := raspidac3.o +@@ -23,6 +23,7 @@ snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o snd-soc-dionaudio-loco-objs := dionaudio_loco.o @@ -131584,7 +116414,7 @@ index 2c233080c40938c38f11bed79304830fda851ae4..b9f98f0bcf3ee0d6b490e1bb185ba0de obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -40,3 +41,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o +@@ -38,3 +39,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o @@ -131740,8755 +116570,45 @@ index 0000000000000000000000000000000000000000..8e8e62e5a36a279b425ed4655cfbac99 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC"); +MODULE_LICENSE("GPL v2"); -From 957b05e2d651db6c7da732440955cb6e3e87155f Mon Sep 17 00:00:00 2001 -From: P33M -Date: Wed, 21 Oct 2015 14:55:21 +0100 -Subject: [PATCH 091/208] rpi_display: add backlight driver and overlay +From 6e56deb3cec1e3680db7ca2e00d3566fc981c194 Mon Sep 17 00:00:00 2001 +From: gtrainavicius +Date: Sun, 23 Oct 2016 12:06:53 +0300 +Subject: [PATCH 084/111] Support for Blokas Labs pisound board -Add a mailbox-driven backlight controller for the Raspberry Pi DSI -touchscreen display. Requires updated GPU firmware to recognise the -mailbox request. +Pisound dynamic overlay (#1760) -Signed-off-by: Gordon Hollingworth +Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay. + +Print a logline when the kernel module is removed. --- - drivers/video/backlight/Kconfig | 6 ++ - drivers/video/backlight/Makefile | 1 + - drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ - 3 files changed, 126 insertions(+) - create mode 100644 drivers/video/backlight/rpi_backlight.c - -diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig -index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 ---- a/drivers/video/backlight/Kconfig -+++ b/drivers/video/backlight/Kconfig -@@ -265,6 +265,12 @@ config BACKLIGHT_PWM - If you have a LCD backlight adjustable by PWM, say Y to enable - this driver. - -+config BACKLIGHT_RPI -+ tristate "Raspberry Pi display firmware driven backlight" -+ help -+ If you have the Raspberry Pi DSI touchscreen display, say Y to -+ enable the mailbox-controlled backlight driver. -+ - config BACKLIGHT_DA903X - tristate "Backlight Driver for DA9030/DA9034 using WLED" - depends on PMIC_DA903X -diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile -index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 ---- a/drivers/video/backlight/Makefile -+++ b/drivers/video/backlight/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o - obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o - obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o - obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o -+obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o - obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o - obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o - obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o -diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c -new file mode 100644 -index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad ---- /dev/null -+++ b/drivers/video/backlight/rpi_backlight.c -@@ -0,0 +1,119 @@ -+/* -+ * rpi_bl.c - Backlight controller through VPU -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct rpi_backlight { -+ struct device *dev; -+ struct device *fbdev; -+ struct rpi_firmware *fw; -+}; -+ -+static int rpi_backlight_update_status(struct backlight_device *bl) -+{ -+ struct rpi_backlight *gbl = bl_get_data(bl); -+ int brightness = bl->props.brightness; -+ int ret; -+ -+ if (bl->props.power != FB_BLANK_UNBLANK || -+ bl->props.fb_blank != FB_BLANK_UNBLANK || -+ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) -+ brightness = 0; -+ -+ ret = rpi_firmware_property(gbl->fw, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, -+ &brightness, sizeof(brightness)); -+ if (ret) { -+ dev_err(gbl->dev, "Failed to set brightness\n"); -+ return ret; -+ } -+ -+ if (brightness < 0) { -+ dev_err(gbl->dev, "Backlight change failed\n"); -+ return -EAGAIN; -+ } -+ -+ return 0; -+} -+ -+static const struct backlight_ops rpi_backlight_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .update_status = rpi_backlight_update_status, -+}; -+ -+static int rpi_backlight_probe(struct platform_device *pdev) -+{ -+ struct backlight_properties props; -+ struct backlight_device *bl; -+ struct rpi_backlight *gbl; -+ struct device_node *fw_node; -+ -+ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); -+ if (gbl == NULL) -+ return -ENOMEM; -+ -+ gbl->dev = &pdev->dev; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ gbl->fw = rpi_firmware_get(fw_node); -+ if (!gbl->fw) -+ return -EPROBE_DEFER; -+ -+ memset(&props, 0, sizeof(props)); -+ props.type = BACKLIGHT_RAW; -+ props.max_brightness = 255; -+ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), -+ &pdev->dev, gbl, &rpi_backlight_ops, -+ &props); -+ if (IS_ERR(bl)) { -+ dev_err(&pdev->dev, "failed to register backlight\n"); -+ return PTR_ERR(bl); -+ } -+ -+ bl->props.brightness = 255; -+ backlight_update_status(bl); -+ -+ platform_set_drvdata(pdev, bl); -+ return 0; -+} -+ -+static const struct of_device_id rpi_backlight_of_match[] = { -+ { .compatible = "raspberrypi,rpi-backlight" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); -+ -+static struct platform_driver rpi_backlight_driver = { -+ .driver = { -+ .name = "rpi-backlight", -+ .of_match_table = of_match_ptr(rpi_backlight_of_match), -+ }, -+ .probe = rpi_backlight_probe, -+}; -+ -+module_platform_driver(rpi_backlight_driver); -+ -+MODULE_AUTHOR("Gordon Hollingworth "); -+MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); -+MODULE_LICENSE("GPL"); - -From 20d35ff154f56e330bb4a3781721e271edecc54f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 23 Feb 2016 19:56:04 +0000 -Subject: [PATCH 092/208] bcm2835-virtgpio: Virtual GPIO driver - -Add a virtual GPIO driver that uses the firmware mailbox interface to -request that the VPU toggles LEDs. ---- - drivers/gpio/Kconfig | 6 ++ - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-bcm-virt.c | 179 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 186 insertions(+) - create mode 100644 drivers/gpio/gpio-bcm-virt.c - -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index 24caedb00a7a34f141bced4062f07a8d72439a63..343adff44f82b78d0a09d41518a2890c602fc83d 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -144,6 +144,12 @@ config GPIO_BCM_KONA - help - Turn on GPIO support for Broadcom "Kona" chips. - -+config GPIO_BCM_VIRT -+ bool "Broadcom Virt GPIO" -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) -+ help -+ Turn on virtual GPIO support for Broadcom BCM283X chips. -+ - config GPIO_BRCMSTB - tristate "BRCMSTB GPIO support" - default y if (ARCH_BRCMSTB || BMIPS_GENERIC) -diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index 2a035ed8f168196ec7596d303685b439b2c2938e..e6ccf796193b93a9e3d9bb190316c6a152f5eb9f 100644 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o - obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o - obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o -+obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o - obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o - obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o - obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o -diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c -new file mode 100644 -index 0000000000000000000000000000000000000000..f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4 ---- /dev/null -+++ b/drivers/gpio/gpio-bcm-virt.c -@@ -0,0 +1,179 @@ -+/* -+ * brcmvirt GPIO driver -+ * -+ * Copyright (C) 2012,2013 Dom Cobley -+ * Based on gpio-clps711x.c by Alexander Shiyan -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define MODULE_NAME "brcmvirt-gpio" -+#define NUM_GPIO 2 -+ -+struct brcmvirt_gpio { -+ struct gpio_chip gc; -+ u32 __iomem *ts_base; -+ /* two packed 16-bit counts of enabled and disables -+ Allows host to detect a brief enable that was missed */ -+ u32 enables_disables[NUM_GPIO]; -+}; -+ -+static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return -EINVAL; -+} -+ -+static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return 0; -+} -+ -+static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ unsigned v; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ v = readl(gpio->ts_base + off); -+ return (v >> off) & 1; -+} -+ -+static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ u16 enables, disables; -+ s16 diff; -+ bool lit; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ enables = gpio->enables_disables[off] >> 16; -+ disables = gpio->enables_disables[off] >> 0; -+ diff = (s16)(enables - disables); -+ lit = diff > 0; -+ if ((val && lit) || (!val && !lit)) -+ return; -+ if (val) -+ enables++; -+ else -+ disables++; -+ diff = (s16)(enables - disables); -+ BUG_ON(diff != 0 && diff != 1); -+ gpio->enables_disables[off] = (enables << 16) | (disables << 0); -+ writel(gpio->enables_disables[off], gpio->ts_base + off); -+} -+ -+static int brcmvirt_gpio_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ struct brcmvirt_gpio *ucb; -+ u32 gpiovirtbuf; -+ int err = 0; -+ -+ fw_node = of_parse_phandle(np, "firmware", 0); -+ if (!fw_node) { -+ dev_err(dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ fw = rpi_firmware_get(fw_node); -+ if (!fw) -+ return -EPROBE_DEFER; -+ -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, -+ &gpiovirtbuf, sizeof(gpiovirtbuf)); -+ -+ if (err) { -+ dev_err(dev, "Failed to get gpiovirtbuf\n"); -+ goto err; -+ } -+ -+ if (!gpiovirtbuf) { -+ dev_err(dev, "No virtgpio buffer\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); -+ if (!ucb) { -+ err = -EINVAL; -+ goto err; -+ } -+ -+ // mmap the physical memory -+ gpiovirtbuf &= ~0xc0000000; -+ ucb->ts_base = ioremap(gpiovirtbuf, 4096); -+ if (ucb->ts_base == NULL) { -+ dev_err(dev, "Failed to map physical address\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb->gc.label = MODULE_NAME; -+ ucb->gc.owner = THIS_MODULE; -+ //ucb->gc.dev = dev; -+ ucb->gc.of_node = np; -+ ucb->gc.base = 100; -+ ucb->gc.ngpio = NUM_GPIO; -+ -+ ucb->gc.direction_input = brcmvirt_gpio_dir_in; -+ ucb->gc.direction_output = brcmvirt_gpio_dir_out; -+ ucb->gc.get = brcmvirt_gpio_get; -+ ucb->gc.set = brcmvirt_gpio_set; -+ ucb->gc.can_sleep = true; -+ -+ err = gpiochip_add(&ucb->gc); -+ if (err) -+ goto err; -+ -+ platform_set_drvdata(pdev, ucb); -+ -+err: -+ return err; -+ -+} -+ -+static int brcmvirt_gpio_remove(struct platform_device *pdev) -+{ -+ int err = 0; -+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); -+ -+ gpiochip_remove(&ucb->gc); -+ iounmap(ucb->ts_base); -+ return err; -+} -+ -+static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { -+ { .compatible = "brcm,bcm2835-virtgpio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); -+ -+static struct platform_driver brcmvirt_gpio_driver = { -+ .driver = { -+ .name = MODULE_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), -+ }, -+ .probe = brcmvirt_gpio_probe, -+ .remove = brcmvirt_gpio_remove, -+}; -+module_platform_driver(brcmvirt_gpio_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dom Cobley "); -+MODULE_DESCRIPTION("brcmvirt GPIO driver"); -+MODULE_ALIAS("platform:brcmvirt-gpio"); - -From ff297e81b17d7bc931554a8246fe3eae8e6f47ef Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 4 Mar 2016 12:49:09 +0000 -Subject: [PATCH 093/208] DRM_VC4: Allow to be built for ARCH_BCM270x - ---- - drivers/gpu/drm/vc4/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index e53df59cb139f25f8e6ae916bca93abf0c49e063..f6e938208b73512f20eab46a383ca91bf675a845 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -1,6 +1,6 @@ - config DRM_VC4 - tristate "Broadcom VC4 Graphics" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - depends on DRM - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER - -From 50174cb70458ba4c0c70e88d3cd21defdd156bbb Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 23 Feb 2016 17:26:48 +0000 -Subject: [PATCH 094/208] amba_pl011: Don't use DT aliases for numbering - -The pl011 driver looks for DT aliases of the form "serial", -and if found uses as the device ID. This can cause -/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the -other serial port is provided by the 8250 driver which doesn't -use the same logic. ---- - drivers/tty/serial/amba-pl011.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 8a9e213387a79fcc335caad27520a68edf03f446..4a5a1c5cf9b345e255f4d79714a7ae461728fce0 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2414,7 +2414,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, - if (IS_ERR(base)) - return PTR_ERR(base); - -+ /* Don't use DT serial aliases - it causes the device to -+ be renumbered to ttyAMA1 if it is the second serial port in the -+ system, even though the other one is ttyS0. The 8250 driver -+ doesn't use this logic, so always remains ttyS0. - index = pl011_probe_dt_alias(index, dev); -+ */ - - uap->old_cr = 0; - uap->port.dev = dev; - -From 6a254068480d6ce7cc2ed93742c5412a8e46cda8 Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -Date: Wed, 3 Dec 2014 13:23:28 +0200 -Subject: [PATCH 095/208] OF: DT-Overlay configfs interface - -This is a port of Pantelis Antoniou's v3 port that makes use of the -new upstreamed configfs support for binary attributes. - -Original commit message: - -Add a runtime interface to using configfs for generic device tree overlay -usage. With it its possible to use device tree overlays without having -to use a per-platform overlay manager. - -Please see Documentation/devicetree/configfs-overlays.txt for more info. - -Changes since v2: -- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) -- Created a documentation entry -- Slight rewording in Kconfig - -Changes since v1: -- of_resolve() -> of_resolve_phandles(). - -Originally-signed-off-by: Pantelis Antoniou -Signed-off-by: Phil Elwell - -DT configfs: Fix build errors on other platforms - -Signed-off-by: Phil Elwell - -DT configfs: fix build error - -There is an error when compiling rpi-4.6.y branch: - CC drivers/of/configfs.o -drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] - .default_groups = of_cfs_def_groups, - ^ -drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') - -The .default_groups is linked list since commit -1ae1602de028acaa42a0f6ff18d19756f8e825c6. -This commit uses configfs_add_default_group to fix this problem. - -Signed-off-by: Slawomir Stepien ---- - Documentation/devicetree/configfs-overlays.txt | 31 +++ - drivers/of/Kconfig | 7 + - drivers/of/Makefile | 1 + - drivers/of/configfs.c | 311 +++++++++++++++++++++++++ - 4 files changed, 350 insertions(+) - create mode 100644 Documentation/devicetree/configfs-overlays.txt - create mode 100644 drivers/of/configfs.c - -diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt -new file mode 100644 -index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad ---- /dev/null -+++ b/Documentation/devicetree/configfs-overlays.txt -@@ -0,0 +1,31 @@ -+Howto use the configfs overlay interface. -+ -+A device-tree configfs entry is created in /config/device-tree/overlays -+and and it is manipulated using standard file system I/O. -+Note that this is a debug level interface, for use by developers and -+not necessarily something accessed by normal users due to the -+security implications of having direct access to the kernel's device tree. -+ -+* To create an overlay you mkdir the directory: -+ -+ # mkdir /config/device-tree/overlays/foo -+ -+* Either you echo the overlay firmware file to the path property file. -+ -+ # echo foo.dtbo >/config/device-tree/overlays/foo/path -+ -+* Or you cat the contents of the overlay to the dtbo file -+ -+ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo -+ -+The overlay file will be applied, and devices will be created/destroyed -+as required. -+ -+To remove it simply rmdir the directory. -+ -+ # rmdir /config/device-tree/overlays/foo -+ -+The rationalle of the dual interface (firmware & direct copy) is that each is -+better suited to different use patterns. The firmware interface is what's -+intended to be used by hardware managers in the kernel, while the copy interface -+make sense for developers (since it avoids problems with namespaces). -diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig -index bc07ad30c9bfa91fe0fcb0b544f2f07412a26680..f0fa9639d98a99bf7ac209f5b62283ed56a102f7 100644 ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -116,4 +116,11 @@ config OF_OVERLAY - config OF_NUMA - bool - -+config OF_CONFIGFS -+ bool "Device Tree Overlay ConfigFS interface" -+ select CONFIGFS_FS -+ select OF_OVERLAY -+ help -+ Enable a simple user-space driven DT overlay interface. -+ - endif # OF -diff --git a/drivers/of/Makefile b/drivers/of/Makefile -index d7efd9d458aab4554139e93c72a1688aa0eeef6a..aa5ef9dd1fedc14d4ae2d363818fc160df51bad9 100644 ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,4 +1,5 @@ - obj-y = base.o device.o platform.o -+obj-$(CONFIG_OF_CONFIGFS) += configfs.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o - obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o -diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c -new file mode 100644 -index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b6ea6cad7 ---- /dev/null -+++ b/drivers/of/configfs.c -@@ -0,0 +1,311 @@ -+/* -+ * Configfs entries for device-tree -+ * -+ * Copyright (C) 2013 - Pantelis Antoniou -+ * -+ * 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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "of_private.h" -+ -+struct cfs_overlay_item { -+ struct config_item item; -+ -+ char path[PATH_MAX]; -+ -+ const struct firmware *fw; -+ struct device_node *overlay; -+ int ov_id; -+ -+ void *dtbo; -+ int dtbo_size; -+}; -+ -+static int create_overlay(struct cfs_overlay_item *overlay, void *blob) -+{ -+ int err; -+ -+ /* unflatten the tree */ -+ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); -+ if (overlay->overlay == NULL) { -+ pr_err("%s: failed to unflatten tree\n", __func__); -+ err = -EINVAL; -+ goto out_err; -+ } -+ pr_debug("%s: unflattened OK\n", __func__); -+ -+ /* mark it as detached */ -+ of_node_set_flag(overlay->overlay, OF_DETACHED); -+ -+ /* perform resolution */ -+ err = of_resolve_phandles(overlay->overlay); -+ if (err != 0) { -+ pr_err("%s: Failed to resolve tree\n", __func__); -+ goto out_err; -+ } -+ pr_debug("%s: resolved OK\n", __func__); -+ -+ err = of_overlay_create(overlay->overlay); -+ if (err < 0) { -+ pr_err("%s: Failed to create overlay (err=%d)\n", -+ __func__, err); -+ goto out_err; -+ } -+ overlay->ov_id = err; -+ -+out_err: -+ return err; -+} -+ -+static inline struct cfs_overlay_item *to_cfs_overlay_item( -+ struct config_item *item) -+{ -+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; -+} -+ -+static ssize_t cfs_overlay_item_path_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ return sprintf(page, "%s\n", overlay->path); -+} -+ -+static ssize_t cfs_overlay_item_path_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ const char *p = page; -+ char *s; -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy to path buffer (and make sure it's always zero terminated */ -+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); -+ overlay->path[sizeof(overlay->path) - 1] = '\0'; -+ -+ /* strip trailing newlines */ -+ s = overlay->path + strlen(overlay->path); -+ while (s > overlay->path && *--s == '\n') -+ *s = '\0'; -+ -+ pr_debug("%s: path is '%s'\n", __func__, overlay->path); -+ -+ err = request_firmware(&overlay->fw, overlay->path, NULL); -+ if (err != 0) -+ goto out_err; -+ -+ err = create_overlay(overlay, (void *)overlay->fw->data); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ -+ release_firmware(overlay->fw); -+ overlay->fw = NULL; -+ -+ overlay->path[0] = '\0'; -+ return err; -+} -+ -+static ssize_t cfs_overlay_item_status_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ return sprintf(page, "%s\n", -+ overlay->ov_id >= 0 ? "applied" : "unapplied"); -+} -+ -+CONFIGFS_ATTR(cfs_overlay_item_, path); -+CONFIGFS_ATTR_RO(cfs_overlay_item_, status); -+ -+static struct configfs_attribute *cfs_overlay_attrs[] = { -+ &cfs_overlay_item_attr_path, -+ &cfs_overlay_item_attr_status, -+ NULL, -+}; -+ -+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, -+ void *buf, size_t max_count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ pr_debug("%s: buf=%p max_count=%zu\n", __func__, -+ buf, max_count); -+ -+ if (overlay->dtbo == NULL) -+ return 0; -+ -+ /* copy if buffer provided */ -+ if (buf != NULL) { -+ /* the buffer must be large enough */ -+ if (overlay->dtbo_size > max_count) -+ return -ENOSPC; -+ -+ memcpy(buf, overlay->dtbo, overlay->dtbo_size); -+ } -+ -+ return overlay->dtbo_size; -+} -+ -+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, -+ const void *buf, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy the contents */ -+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); -+ if (overlay->dtbo == NULL) -+ return -ENOMEM; -+ -+ overlay->dtbo_size = count; -+ -+ err = create_overlay(overlay, overlay->dtbo); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ -+ return err; -+} -+ -+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); -+ -+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { -+ &cfs_overlay_item_attr_dtbo, -+ NULL, -+}; -+ -+static void cfs_overlay_release(struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ if (overlay->ov_id >= 0) -+ of_overlay_destroy(overlay->ov_id); -+ if (overlay->fw) -+ release_firmware(overlay->fw); -+ /* kfree with NULL is safe */ -+ kfree(overlay->dtbo); -+ kfree(overlay); -+} -+ -+static struct configfs_item_operations cfs_overlay_item_ops = { -+ .release = cfs_overlay_release, -+}; -+ -+static struct config_item_type cfs_overlay_type = { -+ .ct_item_ops = &cfs_overlay_item_ops, -+ .ct_attrs = cfs_overlay_attrs, -+ .ct_bin_attrs = cfs_overlay_bin_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *cfs_overlay_group_make_item( -+ struct config_group *group, const char *name) -+{ -+ struct cfs_overlay_item *overlay; -+ -+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); -+ if (!overlay) -+ return ERR_PTR(-ENOMEM); -+ overlay->ov_id = -1; -+ -+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); -+ return &overlay->item; -+} -+ -+static void cfs_overlay_group_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ config_item_put(&overlay->item); -+} -+ -+static struct configfs_group_operations overlays_ops = { -+ .make_item = cfs_overlay_group_make_item, -+ .drop_item = cfs_overlay_group_drop_item, -+}; -+ -+static struct config_item_type overlays_type = { -+ .ct_group_ops = &overlays_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_group_operations of_cfs_ops = { -+ /* empty - we don't allow anything to be created */ -+}; -+ -+static struct config_item_type of_cfs_type = { -+ .ct_group_ops = &of_cfs_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group of_cfs_overlay_group; -+ -+static struct configfs_subsystem of_cfs_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "device-tree", -+ .ci_type = &of_cfs_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), -+}; -+ -+static int __init of_cfs_init(void) -+{ -+ int ret; -+ -+ pr_info("%s\n", __func__); -+ -+ config_group_init(&of_cfs_subsys.su_group); -+ config_group_init_type_name(&of_cfs_overlay_group, "overlays", -+ &overlays_type); -+ configfs_add_default_group(&of_cfs_overlay_group, -+ &of_cfs_subsys.su_group); -+ -+ ret = configfs_register_subsystem(&of_cfs_subsys); -+ if (ret != 0) { -+ pr_err("%s: failed to register subsys\n", __func__); -+ goto out; -+ } -+ pr_info("%s: OK\n", __func__); -+out: -+ return ret; -+} -+late_initcall(of_cfs_init); - -From 1fddcd40ba81c10c6895d5f7450648d22f4ff015 Mon Sep 17 00:00:00 2001 -From: Cheong2K -Date: Fri, 26 Feb 2016 18:20:10 +0800 -Subject: [PATCH 096/208] brcm: adds support for BCM43341 wifi - ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ - drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -index 68ab3ac156500864fbe27187311541986334ff3a..a008d3c264730e1611ce817b5a4a788b872c886c 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -603,6 +603,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); -+BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); -@@ -620,6 +621,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), -+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), -diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -index 3cc42bef6245529c37320f0ec6ab5e7b77f1d2f6..2ae9d0c9dbaaab6bc16610ac012039cd04886ada 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -@@ -35,6 +35,7 @@ - #define BRCM_CC_4330_CHIP_ID 0x4330 - #define BRCM_CC_4334_CHIP_ID 0x4334 - #define BRCM_CC_43340_CHIP_ID 43340 -+#define BRCM_CC_43341_CHIP_ID 43341 - #define BRCM_CC_43362_CHIP_ID 43362 - #define BRCM_CC_4335_CHIP_ID 0x4335 - #define BRCM_CC_4339_CHIP_ID 0x4339 - -From 4c93f16ed441b2c3ef4a6e4bbaf4da65d3947109 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 9 Mar 2016 17:25:59 +0000 -Subject: [PATCH 097/208] brcmfmac: Disable power management - -Disable wireless power saving in the brcmfmac WLAN driver. This is a -temporary measure until the connectivity loss resulting from power -saving is resolved. - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index abaf003a5b396f94e891c6569217ffbb595987e1..f6221c20ff8e2c07a9ddb329204cc59ce574117b 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2762,6 +2762,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, - * preference in cfg struct to apply this to - * FW later while initializing the dongle - */ -+ pr_info("power management disabled\n"); -+ enabled = false; - cfg->pwr_save = enabled; - if (!check_vif_up(ifp->vif)) { - - -From 27a452d3be16848428312107b1281a3a1a3d3752 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 Apr 2016 17:13:47 +0100 -Subject: [PATCH 098/208] brcmfmac: Use original country code as a fallback - -Commit 73345fd212980d2e28a5c6d83801c903bd773680: - - brcmfmac: Configure country code using device specific settings - -prevents region codes from working on devices that lack a region code -translation table. In the event of an absent table, preserve the old -behaviour of using the provided code as-is. - -Signed-off-by: Phil Elwell ---- - .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 20 +++++++++++++++----- - 1 file changed, 15 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index f6221c20ff8e2c07a9ddb329204cc59ce574117b..12bffe239e9d28ce8f73db48b3f5759ffe550162 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6740,12 +6740,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - struct brcmfmac_pd_cc *country_codes; - struct brcmfmac_pd_cc_entry *cc; - s32 found_index; -+ char ccode[BRCMF_COUNTRY_BUF_SZ]; -+ int rev; - int i; - -+ memcpy(ccode, alpha2, sizeof(ccode)); -+ rev = -1; -+ - country_codes = drvr->settings->country_codes; - if (!country_codes) { -- brcmf_dbg(TRACE, "No country codes configured for device\n"); -- return -EINVAL; -+ brcmf_dbg(TRACE, "No country codes configured for device" -+ " - use requested value\n"); -+ goto use_input_value; - } - - if ((alpha2[0] == ccreq->country_abbrev[0]) && -@@ -6769,10 +6775,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - brcmf_dbg(TRACE, "No country code match found\n"); - return -EINVAL; - } -- memset(ccreq, 0, sizeof(*ccreq)); -- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); -- memcpy(ccreq->ccode, country_codes->table[found_index].cc, -+ rev = country_codes->table[found_index].rev; -+ memcpy(ccode, country_codes->table[found_index].cc, - BRCMF_COUNTRY_BUF_SZ); -+ -+use_input_value: -+ memset(ccreq, 0, sizeof(*ccreq)); -+ ccreq->rev = cpu_to_le32(rev); -+ memcpy(ccreq->ccode, ccode, sizeof(ccode)); - ccreq->country_abbrev[0] = alpha2[0]; - ccreq->country_abbrev[1] = alpha2[1]; - ccreq->country_abbrev[2] = 0; - -From fb426eaf2b6cb5e4383d36f1b00c74afbed85c7b Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 13 Sep 2016 16:32:37 +0100 -Subject: [PATCH 099/208] brcmfmac: do not use internal roaming engine by - default - -Some evidence of curing disconnects with this disabled, so make it a default. -Can be overridden with module parameter roamoff=0 -See: http://projectable.me/optimize-my-pi-wi-fi/ ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -index 3e15d64c64813513bc22202dd9e468588699abb0..4051780f64f44a5ce522babe6c371a1beb79a824 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -@@ -69,7 +69,7 @@ static int brcmf_fcmode; - module_param_named(fcmode, brcmf_fcmode, int, 0); - MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); - --static int brcmf_roamoff; -+static int brcmf_roamoff = 1; - module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); - MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); - - -From 0b42c7b72a05fa0261c707571f0328fba44c8a9e Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 31 Aug 2016 17:10:09 +0100 -Subject: [PATCH 100/208] brcmfmac: Change stop_ap sequence - -Patch from Broadcom/Cypress to resolve a customer error - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index 12bffe239e9d28ce8f73db48b3f5759ffe550162..0c3cecb22763db2db5ccbc1789f50b2b361e4a9c 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -4750,12 +4750,15 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); - if (err < 0) - brcmf_err("BRCMF_C_DOWN error %d\n", err); -- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); -- if (err < 0) -- brcmf_err("setting AP mode failed %d\n", err); -+ - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); - if (err < 0) - brcmf_err("setting INFRA mode failed %d\n", err); -+ -+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); -+ if (err < 0) -+ brcmf_err("setting AP mode failed %d\n", err); -+ - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) - brcmf_fil_iovar_int_set(ifp, "mbss", 0); - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, - -From bae20097877011eea7b2342eee23788a14ceb380 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 17 Dec 2015 13:37:07 +0000 -Subject: [PATCH 101/208] hci_h5: Don't send conf_req when ACTIVE - -Without this patch, a modem and kernel can continuously bombard each -other with conf_req and conf_rsp messages, in a demented game of tag. ---- - drivers/bluetooth/hci_h5.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c -index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 ---- a/drivers/bluetooth/hci_h5.c -+++ b/drivers/bluetooth/hci_h5.c -@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) - h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_req, 2) == 0) { - h5_link_control(hu, conf_rsp, 2); -- h5_link_control(hu, conf_req, 3); -+ if (h5->state != H5_ACTIVE) -+ h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_rsp, 2) == 0) { - if (H5_HDR_LEN(hdr) > 2) - h5->tx_win = (data[2] & 0x07); - -From aa0a8cb875b64118fee48e451ea59561e3b18b1e Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 25 Jan 2016 13:03:33 -0800 -Subject: [PATCH 102/208] drm/vc4: Include vc4_drm.h in uapi in downstream - build. - -Signed-off-by: Eric Anholt ---- - include/uapi/drm/Kbuild | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild -index 9355dd8eff3ba39401dfe37e7fbf7737f0397f11..68828bf586f05a8d9b0a6ab409ee91a700e3d296 100644 ---- a/include/uapi/drm/Kbuild -+++ b/include/uapi/drm/Kbuild -@@ -15,6 +15,7 @@ header-y += radeon_drm.h - header-y += savage_drm.h - header-y += sis_drm.h - header-y += tegra_drm.h -+header-y += vc4_drm.h - header-y += via_drm.h - header-y += vmwgfx_drm.h - header-y += msm_drm.h - -From e6971437077eda153890c78e3428cd883499d7b2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 103/208] config: Add default configs - ---- - arch/arm/configs/bcm2709_defconfig | 1294 +++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1303 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 2597 insertions(+) - create mode 100644 arch/arm/configs/bcm2709_defconfig - create mode 100644 arch/arm/configs/bcmrpi_defconfig - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..dfbb3406e38b50bf38db84071f82c3a556da8057 ---- /dev/null -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1294 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_PHYS_OFFSET=0 -+CONFIG_LOCALVERSION="-v7" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2709=y -+# CONFIG_CACHE_L2X0 is not set -+CONFIG_SMP=y -+CONFIG_HAVE_ARM_ARCH_TIMER=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_IPVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=m -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VCIO=y -+CONFIG_BCM_VC_SM=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_BCM_VIRT=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=m -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+# CONFIG_CRYPTO_HW is not set -+CONFIG_ARM_CRYPTO=y -+CONFIG_CRYPTO_SHA1_ARM_NEON=m -+CONFIG_CRYPTO_AES_ARM_BS=m -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..cfe21355f7d95326b292be1b018b988fa3ffe865 ---- /dev/null -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1303 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_PHYS_OFFSET=0 -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2708=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_VFP=y -+CONFIG_BINFMT_MISC=m -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_IPVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=m -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VCIO=y -+CONFIG_BCM_VC_SM=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=m -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_DWC2=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_USB_GADGET=m -+CONFIG_USB_ZERO=m -+CONFIG_USB_AUDIO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_GADGETFS=m -+CONFIG_USB_MASS_STORAGE=m -+CONFIG_USB_G_SERIAL=m -+CONFIG_USB_MIDI_GADGET=m -+CONFIG_USB_G_PRINTER=m -+CONFIG_USB_CDC_COMPOSITE=m -+CONFIG_USB_G_ACM_MS=m -+CONFIG_USB_G_MULTI=m -+CONFIG_USB_G_HID=m -+CONFIG_USB_G_WEBCAM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_LATENCYTOP=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CRYPTD=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_SHA512=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+# CONFIG_CRYPTO_HW is not set -+CONFIG_ARM_CRYPTO=y -+CONFIG_CRYPTO_SHA1_ARM=m -+CONFIG_CRYPTO_AES_ARM=m -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y - -From fba149883c98450421b61cac552394f43efbfda2 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Wed, 24 Aug 2016 03:35:56 -0700 -Subject: [PATCH 104/208] Add arm64 configuration and device tree differences. - Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing - at the moment. - ---- - arch/arm64/Kconfig.platforms | 22 + - arch/arm64/boot/dts/broadcom/Makefile | 1 + - arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts | 3 + - arch/arm64/configs/bcmrpi3_defconfig | 1330 ++++++++++++++++++++++ - 4 files changed, 1356 insertions(+) - create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts - create mode 100644 arch/arm64/configs/bcmrpi3_defconfig - -diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index be5d824ebdba2dab24840bb7808abcc40da2053e..fee7af52fe1a9f8d49447a93df0017832e06c5d3 100644 ---- a/arch/arm64/Kconfig.platforms -+++ b/arch/arm64/Kconfig.platforms -@@ -1,5 +1,27 @@ - menu "Platform selection" - -+config MACH_BCM2709 -+ bool -+ -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ select MACH_BCM2709 -+ select HAVE_SMP -+ select ARM_AMBA -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select MULTI_IRQ_HANDLER -+ select SPARSE_IRQ -+ select MFD_SYSCON -+ select VC4 -+ select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - config ARCH_SUNXI - bool "Allwinner sunxi 64-bit SoC Family" - select GENERIC_IRQ_CHIP -diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index 05faf2a8a35ca5ba9049b9038dedb9be88eeb7c5..2152448c8cf5b22c573642d7ce45e85793f5fc9a 100644 ---- a/arch/arm64/boot/dts/broadcom/Makefile -+++ b/arch/arm64/boot/dts/broadcom/Makefile -@@ -1,6 +1,7 @@ - dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb - dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb - - always := $(dtb-y) - subdir-y := $(dts-dirs) -diff --git a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..deb33441da95220db0ed672e41639626fba682a5 ---- /dev/null -+++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts -@@ -0,0 +1,3 @@ -+#define RPI364 -+ -+#include "../../../../arm/boot/dts/bcm2710-rpi-3-b.dts" -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..1fcde8c1329bbfd329245a8bb17691999882ccfc ---- /dev/null -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -0,0 +1,1330 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_PHYS_OFFSET=0 -+CONFIG_LOCALVERSION="-v8" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_64BIT=y -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+ -+# -+# ARM errata workarounds via the alternatives framework -+# -+CONFIG_ARM64_ERRATUM_826319=n -+CONFIG_ARM64_ERRATUM_827319=n -+CONFIG_ARM64_ERRATUM_824069=n -+CONFIG_ARM64_ERRATUM_819472=n -+CONFIG_ARM64_ERRATUM_832075=n -+CONFIG_ARM64_ERRATUM_845719=n -+CONFIG_ARM64_ERRATUM_843419=n -+CONFIG_CAVIUM_ERRATUM_22375=n -+CONFIG_CAVIUM_ERRATUM_23154=n -+CONFIG_CAVIUM_ERRATUM_27456=n -+CONFIG_ARM64_4K_PAGES=y -+CONFIG_ARM64_VA_BITS_39=y -+CONFIG_ARM64_VA_BITS=39 -+CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=4 -+CONFIG_HOTPLUG_CPU=y -+ -+# -+# ARMv8.1 architectural features -+# -+CONFIG_ARM64_HW_AFDBM=n -+CONFIG_ARM64_PAN=n -+CONFIG_ARM64_LSE_ATOMICS=n -+CONFIG_ARM64_VHE=n -+ -+# -+# ARMv8.2 architectural features -+# -+CONFIG_ARM64_UAO=n -+CONFIG_ARM64_MODULE_CMODEL_LARGE=n -+CONFIG_RANDOMIZE_BASE=n -+ -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_TRIM_UNUSED_KSYMS=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2709=y -+# CONFIG_CACHE_L2X0 is not set -+CONFIG_SMP=y -+CONFIG_HAVE_ARM_ARCH_TIMER=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+CONFIG_COMPAT=y -+CONFIG_SYSVIPC_COMPAT=y -+ -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_IPVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=n -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=n -+CONFIG_BCM_VC_CMA=n -+CONFIG_BCM_VCIO=n -+CONFIG_BCM_VC_SM=n -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_BCM_VIRT=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=m -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=n -+CONFIG_VIDEO_BCM2835_MMAL=n -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_ARM=n -+CONFIG_SND_BCM2835=n -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=n -+CONFIG_USB_DWC2=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+CONFIG_ARM64_CRYPTO=y -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y -+CONFIG_BCM2708_VCHIQ=n - -From 54f507bf54343e3d66964683f676cbfef1beed5f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 5 Oct 2016 16:10:59 +0100 -Subject: [PATCH 105/208] bcm2835-cpufreq: Only report a single frequency when - max and min frequencies are the same - -4.8 kernel gives EINV error when max and min frequencies are the same (e.g. from using force_turbo=1) ---- - drivers/cpufreq/bcm2835-cpufreq.c | 27 ++++++++++++++++----------- - 1 file changed, 16 insertions(+), 11 deletions(-) - -diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c -index 3eb9e9326231b08e6ee95ad486485245c71cf868..414fbdc10dfbfc6e4bb47870a7af3fd5780f9c9a 100644 ---- a/drivers/cpufreq/bcm2835-cpufreq.c -+++ b/drivers/cpufreq/bcm2835-cpufreq.c -@@ -45,12 +45,8 @@ - - /* ---------- GLOBALS ---------- */ - static struct cpufreq_driver bcm2835_cpufreq_driver; /* the cpufreq driver global */ -- --static struct cpufreq_frequency_table bcm2835_freq_table[] = { -- {0, 0, 0}, -- {0, 0, 0}, -- {0, 0, CPUFREQ_TABLE_END}, --}; -+static unsigned int min_frequency, max_frequency; -+static struct cpufreq_frequency_table bcm2835_freq_table[3]; - - /* - =============================================== -@@ -155,10 +151,19 @@ static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy) - } - - /* now find out what the maximum and minimum frequencies are */ -- bcm2835_freq_table[0].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); -- bcm2835_freq_table[1].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); -+ min_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); -+ max_frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); -+ -+ if (min_frequency == max_frequency) { -+ bcm2835_freq_table[0].frequency = min_frequency; -+ bcm2835_freq_table[1].frequency = CPUFREQ_TABLE_END; -+ } else { -+ bcm2835_freq_table[0].frequency = min_frequency; -+ bcm2835_freq_table[1].frequency = max_frequency; -+ bcm2835_freq_table[2].frequency = CPUFREQ_TABLE_END; -+ } - -- print_info("min=%d max=%d\n", bcm2835_freq_table[0].frequency, bcm2835_freq_table[1].frequency); -+ print_info("min=%d max=%d\n", min_frequency, max_frequency); - return cpufreq_generic_init(policy, bcm2835_freq_table, transition_latency); - } - -@@ -170,7 +175,7 @@ static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy) - - static int bcm2835_cpufreq_driver_target_index(struct cpufreq_policy *policy, unsigned int state) - { -- unsigned int target_freq = bcm2835_freq_table[state].frequency; -+ unsigned int target_freq = state == 0 ? min_frequency : max_frequency; - unsigned int cur = bcm2835_cpufreq_set_clock(policy->cur, target_freq); - - if (!cur) -@@ -192,7 +197,7 @@ static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu) - { - unsigned int actual_rate = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_CLOCK_RATE); - print_debug("cpu%d: freq=%d\n", cpu, actual_rate); -- return actual_rate <= bcm2835_freq_table[0].frequency ? bcm2835_freq_table[0].frequency : bcm2835_freq_table[1].frequency; -+ return actual_rate <= min_frequency ? min_frequency : max_frequency; - } - - /* the CPUFreq driver */ - -From 4896a5fdcc6c95ae207070fe78e3aad60e597ce3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 7 Oct 2016 12:37:09 +0100 -Subject: [PATCH 106/208] scripts/mkknlimg: Change string for DDT detection - -The old "of_overlay_apply" string does not appear in 4.8 kernel builds. -"of_cfs_init" is both present and a more accurate indication of support -for dynamically loading overlays (although the trailer is now of little -practical use and the firmware assumes DT support and will look for -both .dtbo and -overlay.dtb overlays). - -Signed-off-by: Phil Elwell ---- - scripts/mkknlimg | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -index 78c5845d2f01deb04b477327d83fa60624f87f98..a21f7e31bc904233e980e66ae3e6337e2eab0f1c 100755 ---- a/scripts/mkknlimg -+++ b/scripts/mkknlimg -@@ -77,7 +77,7 @@ my $wanted_strings = - 'brcm,bcm2709' => FLAG_PI | FLAG_DTOK | FLAG_270X, - 'brcm,bcm2835' => FLAG_PI | FLAG_DTOK | FLAG_283X, - 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, -- 'of_overlay_apply' => FLAG_DTOK | FLAG_DDTK, -+ 'of_cfs_init' => FLAG_DTOK | FLAG_DDTK, - }; - - my $res = try_extract($kernel_file, $tmpfile1); - -From dc56c6cc7558f783449f7ff3943aa7698d9a2144 Mon Sep 17 00:00:00 2001 -From: Herve Jourdain -Date: Fri, 20 May 2016 16:02:23 +0800 -Subject: [PATCH 107/208] build: support for .dtbo files for dtb overlays - -Kernel 4.4.6+ on RaspberryPi support .dtbo files for overlays, instead of .dtb. -Patch the kernel, which has faulty rules to generate .dtbo the way yocto does - -Signed-off-by: Herve Jourdain -Signed-off-by: Khem Raj ---- - arch/arm/Makefile | 2 ++ - scripts/Makefile.lib | 5 +++-- - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index d1e45094ab4338f95dab09e81d358cd723f5eb3d..275c53561cd7c3b1f52a60c95b5fb287fb3ccb62 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -337,6 +337,8 @@ $(INSTALL_TARGETS): - - %.dtb: | scripts - $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ -+%.dtbo: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ - - PHONY += dtbs dtbs_install - -diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index 1d949b7410600dd3b04a3acde8c41cfead15bfa4..1967878a843461c3ff1f473b9a030eb01b7c726e 100644 ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -313,8 +313,9 @@ $(obj)/%.dtb: $(src)/%.dts FORCE - $(call if_changed_dep,dtc) - - quiet_cmd_dtco = DTCO $@ --cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -- $(objtree)/scripts/dtc/dtc -@ -H epapr -O dtb -o $@ -b 0 \ -+cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \ -+ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -+ $(DTC) -@ -H epapr -O dtb -o $@ -b 0 \ - -i $(dir $<) $(DTC_FLAGS) \ - -d $(depfile).dtc.tmp $(dtc-tmp) ; \ - cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) - -From e8fc35c718297a56d13a92eb51d984ba28e5916e Mon Sep 17 00:00:00 2001 -From: Khem Raj -Date: Thu, 6 Oct 2016 19:42:55 -0700 -Subject: [PATCH 108/208] [media]bcm2835-camera: fix compilation warning/werror - -| /a/builder/mnt/build/tmp-glibc/work-shared/raspberrypi3/kernel-source/drivers/media/platform/bcm2835/bcm2835-camera.c:656:17: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types -] -| .queue_setup = queue_setup, -| ^~~~~~~~~~~ -| /a/builder/mnt/build/tmp-glibc/work-shared/raspberrypi3/kernel-source/drivers/media/platform/bcm2835/bcm28 -35-camera.c:656:17: note: (near initialization for 'bm2835_mmal_video_qops.queue_setup') - -use struct device* instead of void* - -Signed-off-by: Khem Raj ---- - drivers/media/platform/bcm2835/bcm2835-camera.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index 70f4db2741037381e638d1dda5a95478809eb161..cb5bab642eaab2f60d641801dd0afdac45b7698f 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -244,7 +244,7 @@ static struct mmal_fmt *get_format(struct v4l2_format *f) - - static int queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, -- unsigned int sizes[], void *alloc_ctxs[]) -+ unsigned int sizes[], struct device *alloc_ctxs[]) - { - struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); - unsigned long size; - -From 6c91352d35ed41686937484e2777a8af6652d2a3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 8 Oct 2016 16:26:46 +0200 -Subject: [PATCH 109/208] bcm2709: Drop platform smp and timer init code -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -irq-bcm2836 handles this through these functions: -bcm2835_init_local_timer_frequency() -bcm2836_arm_irqchip_smp_init() - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2709/bcm2709.c | 126 ---------------------------------------- - 1 file changed, 126 deletions(-) - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 90773a30b87abbfda1615326c6faf59b9db6d68e..d4c9d57d78a964fbbf799b534471462d3c3b88f1 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -208,19 +208,6 @@ void __init bcm2709_init(void) - system_serial_low = serial; - } - --static void __init bcm2709_timer_init(void) --{ -- // timer control -- writel(0, __io_address(ARM_LOCAL_CONTROL)); -- // timer pre_scaler -- writel(0x80000000, __io_address(ARM_LOCAL_PRESCALER)); // 19.2MHz -- //writel(0x06AAAAAB, __io_address(ARM_LOCAL_PRESCALER)); // 1MHz -- -- of_clk_init(NULL); -- clocksource_probe(); --} -- -- - void __init bcm2709_init_early(void) - { - /* -@@ -236,111 +223,6 @@ static void __init board_reserve(void) - vc_cma_reserve(); - } - -- --#ifdef CONFIG_SMP --#include -- --#include --#include --int dc4=0; --//void dc4_log(unsigned x) { if (dc4) writel((x), __io_address(ST_BASE+10 + raw_smp_processor_id()*4)); } --void dc4_log_dead(unsigned x) { if (dc4) writel((readl(__io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)) & 0xffff) | ((x)<<16), __io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)); } -- --static void bcm2835_send_doorbell(const struct cpumask *mask, unsigned int irq) --{ -- int cpu; -- /* -- * Ensure that stores to Normal memory are visible to the -- * other CPUs before issuing the IPI. -- */ -- dsb(); -- -- /* Convert our logical CPU mask into a physical one. */ -- for_each_cpu(cpu, mask) -- { -- /* submit softirq */ -- writel(1<%x)\n", __FUNCTION__, (unsigned)virt_to_phys((void *)secondary_startup), (unsigned)__io_address(ST_BASE + 0x10)); -- printk("[%s] ncores=%d\n", __FUNCTION__, ncores); -- -- for (i = 0; i < ncores; i++) { -- set_cpu_possible(i, true); -- /* enable IRQ (not FIQ) */ -- writel(0x1, __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 0x4 * i)); -- //writel(0xf, __io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 0x4 * i)); -- } -- set_smp_cross_call(bcm2835_send_doorbell); --} -- --/* -- * for arch/arm/kernel/smp.c:smp_prepare_cpus(unsigned int max_cpus) -- */ --void __init bcm2709_smp_prepare_cpus(unsigned int max_cpus) --{ -- //void __iomem *scu_base; -- -- printk("[%s] enter\n", __FUNCTION__); -- //scu_base = scu_base_addr(); -- //scu_enable(scu_base); --} -- --/* -- * for linux/arch/arm/kernel/smp.c:secondary_start_kernel(void) -- */ --void __init bcm2709_secondary_init(unsigned int cpu) --{ -- printk("[%s] enter cpu:%d\n", __FUNCTION__, cpu); -- //gic_secondary_init(0); --} -- --/* -- * for linux/arch/arm/kernel/smp.c:__cpu_up(..) -- */ --int __init bcm2709_boot_secondary(unsigned int cpu, struct task_struct *idle) --{ -- void secondary_startup(void); -- void *mbox_set = __io_address(ARM_LOCAL_MAILBOX3_SET0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -- void *mbox_clr = __io_address(ARM_LOCAL_MAILBOX3_CLR0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); -- unsigned secondary_boot = (unsigned)virt_to_phys((void *)secondary_startup); -- int timeout=20; -- unsigned t = -1; -- //printk("[%s] enter cpu:%d (%x->%p) %x\n", __FUNCTION__, cpu, secondary_boot, wake, readl(wake)); -- -- dsb(); -- BUG_ON(readl(mbox_clr) != 0); -- writel(secondary_boot, mbox_set); -- -- while (--timeout > 0) { -- t = readl(mbox_clr); -- if (t == 0) break; -- cpu_relax(); -- } -- if (timeout==0) -- printk("[%s] cpu:%d failed to start (%x)\n", __FUNCTION__, cpu, t); -- else -- printk("[%s] cpu:%d started (%x) %d\n", __FUNCTION__, cpu, t, timeout); -- -- return 0; --} -- -- --struct smp_operations bcm2709_smp_ops __initdata = { -- .smp_init_cpus = bcm2709_smp_init_cpus, -- .smp_prepare_cpus = bcm2709_smp_prepare_cpus, -- .smp_secondary_init = bcm2709_secondary_init, -- .smp_boot_secondary = bcm2709_boot_secondary, --}; --#endif -- - static const char * const bcm2709_compat[] = { - "brcm,bcm2709", - "brcm,bcm2708", /* Could use bcm2708 in a pinch */ -@@ -349,11 +231,7 @@ static const char * const bcm2709_compat[] = { - - MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ --#ifdef CONFIG_SMP -- .smp = smp_ops(bcm2709_smp_ops), --#endif - .map_io = bcm2709_map_io, -- .init_time = bcm2709_timer_init, - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, -@@ -363,11 +241,7 @@ MACHINE_END - - MACHINE_START(BCM2708, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ --#ifdef CONFIG_SMP -- .smp = smp_ops(bcm2709_smp_ops), --#endif - .map_io = bcm2709_map_io, -- .init_time = bcm2709_timer_init, - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, - -From b9634bc3431cbe7aa5157750ab5943024019a99f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 3 Oct 2016 17:53:15 +0200 -Subject: [PATCH 110/208] BCM270X_DT: Use bcm283x.dtsi, bcm2835.dtsi and - bcm2836.dtsi -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The mainline Device Tree files are quite close to downstream now. -Let's use bcm283x.dtsi, bcm2835.dtsi and bcm2836.dtsi as base files -for our dts files. - -Mainline dts files are based on these files: - - bcm2835-rpi.dtsi - bcm2835.dtsi bcm2836.dtsi - bcm283x.dtsi - -Current downstream are based on these: - - bcm2708.dtsi bcm2709.dtsi bcm2710.dtsi - bcm2708_common.dtsi - -This patch introduces this dependency: - - bcm2708.dtsi bcm2709.dtsi - bcm2708-rpi.dtsi - bcm270x.dtsi - bcm2835.dtsi bcm2836.dtsi - bcm283x.dtsi - -And: - bcm2710.dtsi - bcm2708-rpi.dtsi - bcm270x.dtsi - bcm283x.dtsi - -bcm270x.dtsi contains the downstream bcm283x.dtsi diff. -bcm2708-rpi.dtsi is the downstream version of bcm2835-rpi.dtsi. - -Other changes: -- The led node has moved from /soc/leds to /leds. This is not a problem - since the label is used to reference it. -- The clk_osc reg property changes from 6 to 3. -- The gpu nodes has their interrupt property set in the base file. -- the clocks label does not point to the /clocks node anymore, but - points to the cprman node. This is not a problem since the overlays - that use the clock node refer to it directly: target-path = "/clocks"; -- some nodes now have 2 labels since mainline and downstream differs in - this respect: cprman/clocks, spi0/spi, gpu/vc4. -- some nodes doesn't have an explicit status = "okay" since they're not - disabled in the base file: watchdog and random. -- gpiomem doesn't need an explicit status = "okay". -- bcm2708-rpi-cm.dts got the hpd-gpios property from bcm2708_common.dtsi, - it's now set directly in that file. -- bcm2709-rpi-2-b.dts has the timer node moved from /soc/timer to /timer. -- Removed clock-frequency property on the bcm{2709,2710}.dtsi timer nodes. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 5 - - arch/arm/boot/dts/bcm2708-rpi-b.dts | 5 - - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 5 +- - arch/arm/boot/dts/bcm2708-rpi.dtsi | 105 ++++++++ - arch/arm/boot/dts/bcm2708.dtsi | 28 +- - arch/arm/boot/dts/bcm2708_common.dtsi | 436 ------------------------------- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 5 - - arch/arm/boot/dts/bcm2709.dtsi | 90 +------ - arch/arm/boot/dts/bcm270x.dtsi | 142 ++++++++++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 5 - - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 5 - - arch/arm/boot/dts/bcm2710.dtsi | 28 +- - 12 files changed, 272 insertions(+), 587 deletions(-) - mode change 100755 => 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dts - create mode 100644 arch/arm/boot/dts/bcm2708-rpi.dtsi - delete mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi - create mode 100644 arch/arm/boot/dts/bcm270x.dtsi - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 6c16c325cd2887a42c42665273834618c1937918..6bd8df44dc9163589074c1dec8a3ec69a47fb458 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -98,15 +98,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 7c132437671d43e76445a4bf1184cc9a316b0965..ba80832726004b1b0719f570a7d8b3a390344d56 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -98,15 +98,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -old mode 100755 -new mode 100644 -index ce9f54ff7e4ce76ad25ad0a19cf2ad48ba9df01a..eb8662f0d222b4c0a9a2bcb8bccb13e86a0006b3 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -81,13 +81,12 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; -+&hdmi { -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; - }; - - / { -diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..d85c05901c8f55f822b89c32d198f15559a2b4b0 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi -@@ -0,0 +1,105 @@ -+/* Downstream version of bcm2835-rpi.dtsi */ -+ -+#include -+ -+/ { -+ memory { -+ device_type = "memory"; -+ reg = <0x0 0x0>; -+ }; -+ -+ aliases { -+ audio = &audio; -+ aux = &aux; -+ sound = &sound; -+ soc = &soc; -+ dma = &dma; -+ intc = &intc; -+ watchdog = &watchdog; -+ random = &random; -+ mailbox = &mailbox; -+ gpio = &gpio; -+ uart0 = &uart0; -+ sdhost = &sdhost; -+ i2s = &i2s; -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ uart1 = &uart1; -+ spi1 = &spi1; -+ spi2 = &spi2; -+ mmc = &mmc; -+ i2c1 = &i2c1; -+ i2c2 = &i2c2; -+ usb = &usb; -+ leds = &leds; -+ fb = &fb; -+ vchiq = &vchiq; -+ thermal = &thermal; -+ }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ }; -+ -+ soc { -+ gpiomem { -+ compatible = "brcm,bcm2835-gpiomem"; -+ reg = <0x7e200000 0x1000>; -+ }; -+ -+ firmware: firmware { -+ compatible = "raspberrypi,bcm2835-firmware"; -+ mboxes = <&mailbox>; -+ }; -+ -+ power: power { -+ compatible = "raspberrypi,bcm2835-power"; -+ firmware = <&firmware>; -+ #power-domain-cells = <1>; -+ }; -+ -+ fb: fb { -+ compatible = "brcm,bcm2708-fb"; -+ firmware = <&firmware>; -+ status = "disabled"; -+ }; -+ -+ vchiq: vchiq { -+ compatible = "brcm,bcm2835-vchiq"; -+ reg = <0x7e00b840 0xf>; -+ interrupts = <0 2>; -+ cache-line-size = <32>; -+ firmware = <&firmware>; -+ }; -+ -+ thermal: thermal { -+ compatible = "brcm,bcm2835-thermal"; -+ firmware = <&firmware>; -+ }; -+ -+ /* Onboard audio */ -+ audio: audio { -+ compatible = "brcm,bcm2835-audio"; -+ brcm,pwm-channels = <8>; -+ status = "disabled"; -+ }; -+ -+ /* External sound card */ -+ sound: sound { -+ status = "disabled"; -+ }; -+ -+ }; -+ -+ __overrides__ { -+ cache_line_size = <&vchiq>, "cache-line-size:0"; -+ }; -+}; -+ -+&dma { -+ brcm,dma-channel-mask = <0x7f34>; -+}; -+ -+&hdmi { -+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>; -+}; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index f5a44cd4fef0ee221ed6ae1c43ca81dabffa110d..1bd2a707ef5c0d92f233296e6312916f5a550bd2 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -1,16 +1,14 @@ --#include "bcm2708_common.dtsi" -+#include "bcm2835.dtsi" -+#include "bcm270x.dtsi" -+#include "bcm2708-rpi.dtsi" - - / { + .../devicetree/bindings/vendor-prefixes.txt | 1 + + arch/arm/boot/dts/overlays/pisound-overlay.dts | 94 +- + sound/soc/bcm/Kconfig | 6 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/pisound.c | 989 +++++++++++++++++++++ + 5 files changed, 1048 insertions(+), 44 deletions(-) + create mode 100644 sound/soc/bcm/pisound.c + +diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt +index f0a48ea78659c933839554ca879babb1b621b264..779c19033acad30ed8fd71f015ee76caef1a0568 100644 +--- a/Documentation/devicetree/bindings/vendor-prefixes.txt ++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt +@@ -40,6 +40,7 @@ auvidea Auvidea GmbH + avago Avago Technologies + avic Shanghai AVIC Optoelectronics Co., Ltd. + axis Axis Communications AB ++blokaslabs Vilniaus Blokas UAB + boe BOE Technology Group Co., Ltd. + bosch Bosch Sensortec GmbH + boundary Boundary Devices Inc. +diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts +index 7cdfc29ba4fbffd3216376677922e7ae26019055..5197e656a3d741d14bd9dd6c812b4b93be1419a2 100644 +--- a/arch/arm/boot/dts/overlays/pisound-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts +@@ -26,6 +26,54 @@ compatible = "brcm,bcm2708"; - model = "BCM2708"; -- chosen { -- /* No padding required - the boot loader can do that. */ -- bootargs = ""; -- }; -- - soc { - ranges = <0x7e000000 0x20000000 0x01000000>; -+ /delete-property/ dma-ranges; - - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; -@@ -18,23 +16,7 @@ - interrupts = <1 0>, <1 1>, <1 2>, <1 3>; - clock-frequency = <1000000>; - }; -- -- arm-pmu { -- compatible = "arm,arm1176-pmu"; -- }; -- -- gpiomem { -- compatible = "brcm,bcm2835-gpiomem"; -- reg = <0x7e200000 0x1000>; -- status = "okay"; -- }; - }; --}; -- --&intc { -- compatible = "brcm,bcm2835-armctrl-ic"; --}; - --&watchdog { -- status = "okay"; -+ /delete-node/ cpus; - }; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -deleted file mode 100644 -index 6081b2aeb7ab1e1821506bcb93d36de13b5717ef..0000000000000000000000000000000000000000 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ /dev/null -@@ -1,436 +0,0 @@ --#include "dt-bindings/clock/bcm2835.h" --#include --#include "dt-bindings/power/raspberrypi-power.h" --#include "dt-bindings/gpio/gpio.h" --#include "skeleton.dtsi" -- --/ { -- interrupt-parent = <&intc>; -- -- aliases { -- audio = &audio; -- aux = &aux; -- sound = &sound; -- soc = &soc; -- dma = &dma; -- intc = &intc; -- watchdog = &watchdog; -- random = &random; -- mailbox = &mailbox; -- gpio = &gpio; -- uart0 = &uart0; -- sdhost = &sdhost; -- i2s = &i2s; -- spi0 = &spi0; -- i2c0 = &i2c0; -- uart1 = &uart1; -- spi1 = &spi1; -- spi2 = &spi2; -- mmc = &mmc; -- i2c1 = &i2c1; -- i2c2 = &i2c2; -- usb = &usb; -- leds = &leds; -- fb = &fb; -- vchiq = &vchiq; -- thermal = &thermal; -- clocks = &clocks; -- }; -- -- soc: soc { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <1>; -- -- dma: dma@7e007000 { -- compatible = "brcm,bcm2835-dma"; -- reg = <0x7e007000 0xf00>; -- interrupts = <1 16>, -- <1 17>, -- <1 18>, -- <1 19>, -- <1 20>, -- <1 21>, -- <1 22>, -- <1 23>, -- <1 24>, -- <1 25>, -- <1 26>, -- /* dma channel 11-14 share one irq */ -- <1 27>, -- <1 27>, -- <1 27>, -- <1 27>, -- /* unused shared irq for all channels */ -- <1 28>; -- interrupt-names = "dma0", -- "dma1", -- "dma2", -- "dma3", -- "dma4", -- "dma5", -- "dma6", -- "dma7", -- "dma8", -- "dma9", -- "dma10", -- "dma11", -- "dma12", -- "dma13", -- "dma14", -- "dma-shared-all"; -- -- #dma-cells = <1>; -- brcm,dma-channel-mask = <0x7f34>; -- }; -- -- intc: interrupt-controller@7e00b200 { --#ifdef RPI364 -- compatible = "brcm,bcm2835-armctrl-ic", "brcm,bcm2708-armctrl-ic"; --#else -- compatible = "brcm,bcm2708-armctrl-ic"; --#endif -- reg = <0x7e00b200 0x200>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- mailbox: mailbox@7e00b800 { -- compatible = "brcm,bcm2835-mbox"; -- reg = <0x7e00b880 0x40>; -- interrupts = <0 1>; -- #mbox-cells = <0>; -- }; -- -- watchdog: watchdog@7e100000 { -- compatible = "brcm,bcm2835-pm-wdt"; -- reg = <0x7e100000 0x28>; -- status = "disabled"; -- }; -- -- cprman: cprman@7e101000 { -- compatible = "brcm,bcm2835-cprman"; -- #clock-cells = <1>; -- reg = <0x7e101000 0x2000>; -- -- /* CPRMAN derives everything from the platform's -- * oscillator. -- */ -- clocks = <&clk_osc>; -- }; -- -- random: rng@7e104000 { -- compatible = "brcm,bcm2835-rng"; -- reg = <0x7e104000 0x10>; -- status = "disabled"; -- }; -- -- gpio: gpio@7e200000 { -- compatible = "brcm,bcm2835-gpio"; -- reg = <0x7e200000 0xb4>; -- interrupts = <2 17>, <2 18>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- uart0: serial@7e201000 { -- compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; -- reg = <0x7e201000 0x1000>; -- interrupts = <2 25>; -- clocks = <&cprman BCM2835_CLOCK_UART>, -- <&cprman BCM2835_CLOCK_VPU>; -- clock-names = "uartclk","apb_pclk"; -- arm,primecell-periphid = <0x00241011>; // For an explanation, see -- // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 -- status = "disabled"; -- }; -- -- sdhost: sdhost@7e202000 { -- compatible = "brcm,bcm2835-sdhost"; -- reg = <0x7e202000 0x100>; -- interrupts = <2 24>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- dmas = <&dma 13>; -- dma-names = "rx-tx"; -- brcm,overclock-50 = <0>; -- brcm,pio-limit = <1>; -- status = "disabled"; -- }; -- -- i2s: i2s@7e203000 { -- compatible = "brcm,bcm2835-i2s"; -- #sound-dai-cells = <0>; -- reg = <0x7e203000 0x24>; -- clocks = <&cprman BCM2835_CLOCK_PCM>; -- -- dmas = <&dma 2>, <&dma 3>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- spi0: spi@7e204000 { -- compatible = "brcm,bcm2835-spi"; -- reg = <0x7e204000 0x1000>; -- interrupts = <2 22>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- /* the dma channels */ -- dmas = <&dma 6>, <&dma 7>; -- dma-names = "tx", "rx"; -- /* the chipselects used - <0> means native GPIO -- * add more gpios if necessary as <&gpio 6 1> -- * (but do not forget to make them output!) -- */ -- cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -- }; -- -- i2c0: i2c@7e205000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e205000 0x1000>; -- interrupts = <2 21>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- pixelvalve0: pixelvalve@7e206000 { -- compatible = "brcm,bcm2835-pixelvalve0"; -- reg = <0x7e206000 0x100>; -- status = "disabled"; -- }; -- -- dpi: dpi@7e208000 { -- compatible = "brcm,bcm2835-dpi"; -- reg = <0x7e208000 0x8c>; -- clocks = <&cprman BCM2835_CLOCK_VPU>, -- <&cprman BCM2835_CLOCK_DPI>; -- clock-names = "core", "pixel"; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- pixelvalve1: pixelvalve@7e207000 { -- compatible = "brcm,bcm2835-pixelvalve1"; -- reg = <0x7e207000 0x100>; -- status = "disabled"; -- }; -- -- pwm: pwm@7e20c000 { -- compatible = "brcm,bcm2835-pwm"; -- reg = <0x7e20c000 0x28>; -- clocks = <&cprman BCM2835_CLOCK_PWM>; -- assigned-clocks = <&cprman BCM2835_CLOCK_PWM>; -- assigned-clock-rates = <10000000>; -- #pwm-cells = <2>; -- status = "disabled"; -- }; -- -- aux: aux@0x7e215000 { -- compatible = "brcm,bcm2835-aux"; -- #clock-cells = <1>; -- reg = <0x7e215000 0x8>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- }; -- -- uart1: serial@7e215040 { -- compatible = "brcm,bcm2835-aux-uart"; -- reg = <0x7e215040 0x40>; -- interrupts = <1 29>; -- clocks = <&aux BCM2835_AUX_CLOCK_UART>; -- status = "disabled"; -- }; -- -- spi1: spi@7e215080 { -- compatible = "brcm,bcm2835-aux-spi"; -- reg = <0x7e215080 0x40>; -- interrupts = <1 29>; -- clocks = <&aux BCM2835_AUX_CLOCK_SPI1>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- spi2: spi@7e2150C0 { -- compatible = "brcm,bcm2835-aux-spi"; -- reg = <0x7e2150C0 0x40>; -- interrupts = <1 29>; -- clocks = <&aux BCM2835_AUX_CLOCK_SPI2>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- mmc: mmc@7e300000 { -- compatible = "brcm,bcm2835-mmc"; -- reg = <0x7e300000 0x100>; -- interrupts = <2 30>; -- clocks = <&cprman BCM2835_CLOCK_EMMC>; -- dmas = <&dma 11>; -- dma-names = "rx-tx"; -- brcm,overclock-50 = <0>; -- status = "disabled"; -- }; -- -- hvs: hvs@7e400000 { -- compatible = "brcm,bcm2835-hvs"; -- reg = <0x7e400000 0x6000>; -- status = "disabled"; -- }; -- -- i2c1: i2c@7e804000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e804000 0x1000>; -- interrupts = <2 21>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c2: i2c@7e805000 { -- // Beware - this is shared with the HDMI module. -- // Careless use may break (really) your display. -- // Caveat emptor. -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e805000 0x1000>; -- interrupts = <2 21>; -- clocks = <&cprman BCM2835_CLOCK_VPU>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- smi: smi@7e600000 { -- compatible = "brcm,bcm2835-smi"; -- reg = <0x7e600000 0x100>; -- interrupts = <2 16>; -- clocks = <&cprman BCM2835_CLOCK_SMI>; -- assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; -- assigned-clock-rates = <125000000>; -- dmas = <&dma 4>; -- dma-names = "rx-tx"; -- status = "disabled"; -- }; -- -- pixelvalve2: pixelvalve@7e807000 { -- compatible = "brcm,bcm2835-pixelvalve2"; -- reg = <0x7e807000 0x100>; -- status = "disabled"; -- }; -- -- hdmi: hdmi@7e902000 { -- compatible = "brcm,bcm2835-hdmi"; -- reg = <0x7e902000 0x600>, -- <0x7e808000 0x100>; -- ddc = <&i2c2>; -- hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; -- clocks = <&cprman BCM2835_PLLH_PIX>, -- <&cprman BCM2835_CLOCK_HSM>; -- clock-names = "pixel", "hdmi"; -- power-domains = <&power RPI_POWER_DOMAIN_HDMI>; -- status = "disabled"; -- }; -- --#ifdef RPI364 -- usb: usb@7e980000 { -- compatible = "brcm,bcm2835-usb"; -- reg = <0x7e980000 0x10000>; -- interrupts = <1 9>; -- #address-cells = <1>; -- #size-cells = <0>; -- }; --#else -- usb: usb@7e980000 { -- compatible = "brcm,bcm2708-usb"; -- reg = <0x7e980000 0x10000>, -- <0x7e006000 0x1000>; -- interrupts = <2 0>, -- <1 9>; -- }; --#endif -- -- v3d: v3d@7ec00000 { -- compatible = "brcm,vc4-v3d"; -- reg = <0x7ec00000 0x1000>; -- status = "disabled"; -- }; -- -- firmware: firmware { -- compatible = "raspberrypi,bcm2835-firmware"; -- mboxes = <&mailbox>; -- }; -- -- power: power { -- compatible = "raspberrypi,bcm2835-power"; -- firmware = <&firmware>; -- #power-domain-cells = <1>; -- }; -- -- leds: leds { -- compatible = "gpio-leds"; -- }; -- -- fb: fb { -- compatible = "brcm,bcm2708-fb"; -- firmware = <&firmware>; -- status = "disabled"; -- }; -- -- vchiq: vchiq { -- compatible = "brcm,bcm2835-vchiq"; -- reg = <0x7e00b840 0xf>; -- interrupts = <0 2>; -- cache-line-size = <32>; -- firmware = <&firmware>; -- }; -- -- thermal: thermal { -- compatible = "brcm,bcm2835-thermal"; -- firmware = <&firmware>; -- }; -- -- gpu: gpu { -- compatible = "brcm,bcm2835-vc4"; -- status = "disabled"; -- }; -- -- /* Onboard audio */ -- audio: audio { -- compatible = "brcm,bcm2835-audio"; -- brcm,pwm-channels = <8>; -- status = "disabled"; -- }; -- -- /* External sound card */ -- sound: sound { -- status = "disabled"; -- }; -- }; -- -- clocks: clocks { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- /* The oscillator is the root of the clock tree. */ -- clk_osc: clock@6 { -- compatible = "fixed-clock"; -- reg = <6>; -- #clock-cells = <0>; -- clock-output-names = "osc"; -- clock-frequency = <19200000>; -- }; -- }; -- -- __overrides__ { -- cache_line_size = <&vchiq>, "cache-line-size:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 74fe4cc1d667e9508ca860bcc8c837fed0cbb855..4f79aaae149abc6f8ebc076d493eb8459e469862 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -98,15 +98,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index a8cfd7c4df5bcf7692d13882833c97852649932d..757d0053c1c07452babc63ca6ecd0a8f047b25dd 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -1,48 +1,15 @@ --#include "bcm2708_common.dtsi" -+#include "bcm2836.dtsi" -+#include "bcm270x.dtsi" -+#include "bcm2708-rpi.dtsi" - - / { - compatible = "brcm,bcm2709"; - model = "BCM2709"; - -- chosen { -- /* No padding required - the boot loader can do that. */ -- bootargs = ""; -- }; -- - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -- -- local_intc: local_intc { -- compatible = "brcm,bcm2836-l1-intc"; -- reg = <0x40000000 0x100>; -- interrupt-controller; -- #interrupt-cells = <1>; -- interrupt-parent = <&local_intc>; -- }; -- -- arm-pmu { -- compatible = "arm,cortex-a7-pmu"; -- interrupt-parent = <&local_intc>; -- interrupts = <9>; -- }; -- -- gpiomem { -- compatible = "brcm,bcm2835-gpiomem"; -- reg = <0x7e200000 0x1000>; -- status = "okay"; -- }; -- -- timer { -- compatible = "arm,armv7-timer"; -- clock-frequency = <19200000>; -- interrupt-parent = <&local_intc>; -- interrupts = <0>, // PHYS_SECURE_PPI -- <1>, // PHYS_NONSECURE_PPI -- <3>, // VIRT_PPI -- <2>; // HYP_PPI -- always-on; -- }; -+ /delete-property/ dma-ranges; - - syscon@40000000 { - compatible = "brcm,bcm2836-arm-local", "syscon"; -@@ -50,53 +17,10 @@ - }; - }; - -- cpus: cpus { -- #address-cells = <1>; -- #size-cells = <0>; -- -- v7_cpu0: cpu@0 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf00>; -- clock-frequency = <800000000>; -- }; -- -- v7_cpu1: cpu@1 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf01>; -- clock-frequency = <800000000>; -- }; -- -- v7_cpu2: cpu@2 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf02>; -- clock-frequency = <800000000>; -- }; -- -- v7_cpu3: cpu@3 { -- device_type = "cpu"; -- compatible = "arm,cortex-a7"; -- reg = <0xf03>; -- clock-frequency = <800000000>; -- }; -- }; -- - __overrides__ { - arm_freq = <&v7_cpu0>, "clock-frequency:0", -- <&v7_cpu1>, "clock-frequency:0", -- <&v7_cpu2>, "clock-frequency:0", -- <&v7_cpu3>, "clock-frequency:0"; -+ <&v7_cpu1>, "clock-frequency:0", -+ <&v7_cpu2>, "clock-frequency:0", -+ <&v7_cpu3>, "clock-frequency:0"; - }; - }; -- --&watchdog { -- status = "okay"; --}; -- --&intc { -- compatible = "brcm,bcm2836-armctrl-ic"; -- interrupt-parent = <&local_intc>; -- interrupts = <8>; --}; -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -new file mode 100644 -index 0000000000000000000000000000000000000000..7fb1f428332dc48bdd91dd4a0773f3bea7057238 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -0,0 +1,142 @@ -+/* Downstream bcm283x.dtsi diff */ -+ -+/ { -+ chosen { -+ bootargs = ""; -+ }; -+ -+ soc: soc { -+ -+ /delete-node/ timer@7e003000; -+ -+ watchdog: watchdog@7e100000 { -+ /* Add alias */ -+ }; -+ -+ cprman: cprman@7e101000 { -+ /* Add alias */ -+ }; -+ -+ random: rng@7e104000 { -+ /* Add alias */ -+ }; -+ -+ gpio@7e200000 { /* gpio */ -+ interrupts = <2 17>, <2 18>; -+ }; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ interrupts = <2 24>; -+ clocks = <&clocks BCM2835_CLOCK_VPU>; -+ dmas = <&dma 13>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ brcm,pio-limit = <1>; -+ status = "disabled"; -+ }; -+ -+ i2s@7e203000 { /* i2s */ -+ #sound-dai-cells = <0>; -+ reg = <0x7e203000 0x24>; -+ clocks = <&clocks BCM2835_CLOCK_PCM>; -+ }; -+ -+ spi0: spi@7e204000 { -+ /* Add alias */ -+ dmas = <&dma 6>, <&dma 7>; -+ dma-names = "tx", "rx"; -+ }; -+ -+ i2c@7e205000 { /* i2c0 */ -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ -+ pixelvalve0: pixelvalve@7e206000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ pixelvalve1: pixelvalve@7e207000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ dpi: dpi@7e208000 { -+ compatible = "brcm,bcm2835-dpi"; -+ reg = <0x7e208000 0x8c>; -+ clocks = <&clocks BCM2835_CLOCK_VPU>, -+ <&clocks BCM2835_CLOCK_DPI>; -+ clock-names = "core", "pixel"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ /delete-node/ sdhci@7e300000; -+ -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clocks BCM2835_CLOCK_EMMC>; -+ dmas = <&dma 11>; -+ dma-names = "rx-tx"; -+ brcm,overclock-50 = <0>; -+ status = "disabled"; -+ }; -+ -+ hvs: hvs@7e400000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ smi: smi@7e600000 { -+ compatible = "brcm,bcm2835-smi"; -+ reg = <0x7e600000 0x100>; -+ interrupts = <2 16>; -+ clocks = <&clocks BCM2835_CLOCK_SMI>; -+ assigned-clocks = <&cprman BCM2835_CLOCK_SMI>; -+ assigned-clock-rates = <125000000>; -+ dmas = <&dma 4>; -+ dma-names = "rx-tx"; -+ status = "disabled"; -+ }; -+ -+ i2c@7e804000 { /* i2c1 */ -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ -+ i2c@7e805000 { /* i2c2 */ -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ -+ pixelvalve2: pixelvalve@7e807000 { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ -+ hdmi@7e902000 { /* hdmi */ -+ status = "disabled"; -+ }; -+ -+ usb@7e980000 { /* usb */ -+ compatible = "brcm,bcm2708-usb"; -+ reg = <0x7e980000 0x10000>, -+ <0x7e006000 0x1000>; -+ interrupts = <2 0>, -+ <1 9>; -+ }; -+ -+ v3d@7ec00000 { /* vd3 */ -+ compatible = "brcm,vc4-v3d"; -+ status = "disabled"; -+ }; -+ -+ gpu: gpu { -+ /* Add alias */ -+ status = "disabled"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index d9ae00f95e6261eea582d7a2c6dfbc221f99953d..30060663ca712578f6d697fd02a3b31d94301707 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -153,15 +153,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index 20388084b98cf942529eb60c55dc540cfea71886..b5a5ae7747455438f8eabd28e8c11c6aeb0c1ecc 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -108,15 +108,10 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; - --&random { -- status = "okay"; --}; -- - &leds { - act_led: act { - label = "led0"; -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index 223bd9627b3dcaac5458909dc59c877eed751ce4..491594c918cf5da94fbb19a606edb0dd9a28c3a9 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -1,14 +1,11 @@ --#include "bcm2708_common.dtsi" -+#include "bcm283x.dtsi" -+#include "bcm270x.dtsi" -+#include "bcm2708-rpi.dtsi" - - / { - compatible = "brcm,bcm2710","brcm,bcm2709"; - model = "BCM2710"; - -- chosen { -- /* No padding required - the boot loader can do that. */ -- bootargs = ""; -- }; -- - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -@@ -34,19 +31,12 @@ - interrupts = <9>; - }; - -- gpiomem { -- compatible = "brcm,bcm2835-gpiomem"; -- reg = <0x7e200000 0x1000>; -- status = "okay"; -- }; -- - timer { - #ifdef RPI364 - compatible = "arm,armv8-timer", "arm,armv7-timer"; - #else - compatible = "arm,armv7-timer"; - #endif -- clock-frequency = <19200000>; - interrupt-parent = <&local_intc>; - interrupts = <0>, // PHYS_SECURE_PPI - <1>, // PHYS_NONSECURE_PPI -@@ -151,10 +141,6 @@ - #endif - }; - --&watchdog { -- status = "okay"; --}; -- - &intc { - compatible = "brcm,bcm2836-armctrl-ic"; - #ifdef RPI364 -@@ -163,3 +149,11 @@ - interrupt-parent = <&local_intc>; - interrupts = <8>; - }; -+ -+#ifdef RPI364 -+&usb { -+ compatible = "brcm,bcm2835-usb"; -+ reg = <0x7e980000 0x10000>; -+ interrupts = <1 9>; -+}; -+#endif - -From 3011169b346afd96213eb70e42af510451aabfec Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 7 Oct 2016 16:50:59 +0200 -Subject: [PATCH 111/208] watchdog: bcm2835: Support setting reboot partition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The Raspberry Pi firmware looks at the RSTS register to know which -partition to boot from. The reboot syscall command -LINUX_REBOOT_CMD_RESTART2 supports passing in a string argument. - -Add support for passing in a partition number 0..63 to boot from. -Partition 63 is a special partiton indicating halt. -If the partition doesn't exist, the firmware falls back to partition 0. - -Signed-off-by: Noralf Trønnes ---- - drivers/watchdog/bcm2835_wdt.c | 61 +++++++++++++++++++++++++----------------- - 1 file changed, 36 insertions(+), 25 deletions(-) - -diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c -index 4dddd8298a227d64862f2e92954a465f2e44b3f6..1f545e024422f59280932713e6a1b05150b39b22 100644 ---- a/drivers/watchdog/bcm2835_wdt.c -+++ b/drivers/watchdog/bcm2835_wdt.c -@@ -35,13 +35,7 @@ - #define PM_RSTC_WRCFG_SET 0x00000030 - #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 - #define PM_RSTC_RESET 0x00000102 -- --/* -- * The Raspberry Pi firmware uses the RSTS register to know which partiton -- * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. -- * Partiton 63 is a special partition used by the firmware to indicate halt. -- */ --#define PM_RSTS_RASPBERRYPI_HALT 0x555 -+#define PM_RSTS_PARTITION_CLR 0xfffffaaa - - #define SECS_TO_WDOG_TICKS(x) ((x) << 16) - #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) -@@ -111,15 +105,28 @@ static struct watchdog_device bcm2835_wdt_wdd = { - .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), - }; - --static int --bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) -+/* -+ * The Raspberry Pi firmware uses the RSTS register to know which partiton -+ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. -+ * Partiton 63 is a special partition used by the firmware to indicate halt. -+ */ -+ -+static void bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition) - { -- struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, -- restart_handler); -- u32 val; -+ u32 val, rsts; -+ -+ rsts = (partition & BIT(0)) | ((partition & BIT(1)) << 1) | -+ ((partition & BIT(2)) << 2) | ((partition & BIT(3)) << 3) | -+ ((partition & BIT(4)) << 4) | ((partition & BIT(5)) << 5); -+ -+ val = readl_relaxed(wdt->base + PM_RSTS); -+ val &= PM_RSTS_PARTITION_CLR; -+ val |= PM_PASSWORD | rsts; -+ writel_relaxed(val, wdt->base + PM_RSTS); - - /* use a timeout of 10 ticks (~150us) */ - writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG); -+ - val = readl_relaxed(wdt->base + PM_RSTC); - val &= PM_RSTC_WRCFG_CLR; - val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; -@@ -127,6 +134,20 @@ bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) - - /* No sleeping, possibly atomic. */ - mdelay(1); -+} -+ -+static int bcm2835_restart_notifier_call(struct notifier_block *this, -+ unsigned long mode, void *cmd) -+{ -+ struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, -+ restart_handler); -+ unsigned long long val; -+ u8 partition = 0; -+ -+ if (cmd && !kstrtoull(cmd, 0, &val) && val <= 63) -+ partition = val; -+ -+ bcm2835_restart(wdt, partition); - - return 0; - } -@@ -142,19 +163,9 @@ static void bcm2835_power_off(void) - of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt"); - struct platform_device *pdev = of_find_device_by_node(np); - struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); -- u32 val; -- -- /* -- * We set the watchdog hard reset bit here to distinguish this reset -- * from the normal (full) reset. bootcode.bin will not reboot after a -- * hard reset. -- */ -- val = readl_relaxed(wdt->base + PM_RSTS); -- val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT; -- writel_relaxed(val, wdt->base + PM_RSTS); - -- /* Continue with normal reset mechanism */ -- bcm2835_restart(&wdt->restart_handler, REBOOT_HARD, NULL); -+ /* Partition 63 tells the firmware that this is a halt */ -+ bcm2835_restart(wdt, 63); - } - - static int bcm2835_wdt_probe(struct platform_device *pdev) -@@ -188,7 +199,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) - return err; - } - -- wdt->restart_handler.notifier_call = bcm2835_restart; -+ wdt->restart_handler.notifier_call = bcm2835_restart_notifier_call; - wdt->restart_handler.priority = 128; - register_restart_handler(&wdt->restart_handler); - if (pm_power_off == NULL) - -From 4bea90c43d3fd3e0594f3dc52746f42ca16b8eb1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 7 Oct 2016 17:07:46 +0200 -Subject: [PATCH 112/208] bcm270x: Use watchdog for reboot/poweroff -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The watchdog driver already has support for reboot/poweroff. -Make use of this and remove the code from the platform files. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 2 +- - arch/arm/configs/bcmrpi_defconfig | 2 +- - arch/arm/mach-bcm2708/bcm2708.c | 70 ------------------------------------- - arch/arm/mach-bcm2709/bcm2709.c | 71 -------------------------------------- - 4 files changed, 2 insertions(+), 143 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index dfbb3406e38b50bf38db84071f82c3a556da8057..aa708638cc6f3bceb189c2deef7307252901291f 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -650,7 +650,7 @@ CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y --CONFIG_BCM2835_WDT=m -+CONFIG_BCM2835_WDT=y - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index cfe21355f7d95326b292be1b018b988fa3ffe865..952104ab6c4cd0e9d8f7bd5f2fba7a72da75424e 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -641,7 +641,7 @@ CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y --CONFIG_BCM2835_WDT=m -+CONFIG_BCM2835_WDT=y - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 280628ba8907d2a4323fc86dfc6db7fc684aeabc..a8e2a5b114b2f12f18378ce5fff2a88419b6f52f 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -44,7 +44,6 @@ - - /* command line parameters */ - static unsigned boardrev, serial; --static unsigned reboot_part = 0; - - static struct map_desc bcm2708_io_desc[] __initdata = { - { -@@ -99,71 +98,6 @@ void __init bcm2708_map_io(void) - iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); - } - --int calc_rsts(int partition) --{ -- return PM_PASSWORD | -- ((partition & (1 << 0)) << 0) | -- ((partition & (1 << 1)) << 1) | -- ((partition & (1 << 2)) << 2) | -- ((partition & (1 << 3)) << 3) | -- ((partition & (1 << 4)) << 4) | -- ((partition & (1 << 5)) << 5); --} -- --static void bcm2708_restart(enum reboot_mode mode, const char *cmd) --{ -- extern char bcm2708_reboot_mode; -- uint32_t pm_rstc, pm_wdog; -- uint32_t timeout = 10; -- uint32_t pm_rsts = 0; -- -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < 1.3 booting with reboot=q -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -- } -- else if(bcm2708_reboot_mode == 'p') -- { -- // NOOBS < 1.3 halting -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -- } -- else -- { -- pm_rsts = calc_rsts(reboot_part); -- } -- -- writel(pm_rsts, __io_address(PM_RSTS)); -- -- /* Setup watchdog for reset */ -- pm_rstc = readl(__io_address(PM_RSTC)); -- -- pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -- pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -- -- writel(pm_wdog, __io_address(PM_WDOG)); -- writel(pm_rstc, __io_address(PM_RSTC)); --} -- --/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ --static void bcm2708_power_off(void) --{ -- extern char bcm2708_reboot_mode; -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < v1.3 -- bcm2708_restart('p', ""); -- } -- else -- { -- /* partition 63 is special code for HALT the bootloader knows not to boot*/ -- reboot_part = 63; -- /* continue with normal reset mechanism */ -- bcm2708_restart(0, ""); -- } --} -- - static void __init bcm2708_init_uart1(void) - { - struct device_node *np; -@@ -181,8 +115,6 @@ void __init bcm2708_init(void) - - vc_cma_early_init(); - -- pm_power_off = bcm2708_power_off; -- - ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, - NULL); - if (ret) { -@@ -222,10 +154,8 @@ MACHINE_START(BCM2708, "BCM2708") - .init_machine = bcm2708_init, - .init_early = bcm2708_init_early, - .reserve = board_reserve, -- .restart = bcm2708_restart, - .dt_compat = bcm2708_compat, - MACHINE_END - - module_param(boardrev, uint, 0644); - module_param(serial, uint, 0644); --module_param(reboot_part, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d4c9d57d78a964fbbf799b534471462d3c3b88f1..ed5c5414f7a3ad7284cda881e9e550777cd29282 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -51,7 +51,6 @@ - - /* command line parameters */ - static unsigned boardrev, serial; --static unsigned reboot_part = 0; - - static struct map_desc bcm2709_io_desc[] __initdata = { - { -@@ -111,71 +110,6 @@ void __init bcm2709_map_io(void) - iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); - } - --int calc_rsts(int partition) --{ -- return PM_PASSWORD | -- ((partition & (1 << 0)) << 0) | -- ((partition & (1 << 1)) << 1) | -- ((partition & (1 << 2)) << 2) | -- ((partition & (1 << 3)) << 3) | -- ((partition & (1 << 4)) << 4) | -- ((partition & (1 << 5)) << 5); --} -- --static void bcm2709_restart(enum reboot_mode mode, const char *cmd) --{ -- extern char bcm2708_reboot_mode; -- uint32_t pm_rstc, pm_wdog; -- uint32_t timeout = 10; -- uint32_t pm_rsts = 0; -- -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < 1.3 booting with reboot=q -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; -- } -- else if(bcm2708_reboot_mode == 'p') -- { -- // NOOBS < 1.3 halting -- pm_rsts = readl(__io_address(PM_RSTS)); -- pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; -- } -- else -- { -- pm_rsts = calc_rsts(reboot_part); -- } -- -- writel(pm_rsts, __io_address(PM_RSTS)); -- -- /* Setup watchdog for reset */ -- pm_rstc = readl(__io_address(PM_RSTC)); -- -- pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) -- pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; -- -- writel(pm_wdog, __io_address(PM_WDOG)); -- writel(pm_rstc, __io_address(PM_RSTC)); --} -- --/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ --static void bcm2709_power_off(void) --{ -- extern char bcm2708_reboot_mode; -- if(bcm2708_reboot_mode == 'q') -- { -- // NOOBS < v1.3 -- bcm2709_restart('p', ""); -- } -- else -- { -- /* partition 63 is special code for HALT the bootloader knows not to boot*/ -- reboot_part = 63; -- /* continue with normal reset mechanism */ -- bcm2709_restart(0, ""); -- } --} -- - static void __init bcm2709_init_uart1(void) - { - struct device_node *np; -@@ -193,8 +127,6 @@ void __init bcm2709_init(void) - - vc_cma_early_init(); - -- pm_power_off = bcm2709_power_off; -- - ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, - NULL); - if (ret) { -@@ -235,7 +167,6 @@ MACHINE_START(BCM2709, "BCM2709") - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, -- .restart = bcm2709_restart, - .dt_compat = bcm2709_compat, - MACHINE_END - -@@ -245,10 +176,8 @@ MACHINE_START(BCM2708, "BCM2709") - .init_machine = bcm2709_init, - .init_early = bcm2709_init_early, - .reserve = board_reserve, -- .restart = bcm2709_restart, - .dt_compat = bcm2709_compat, - MACHINE_END - - module_param(boardrev, uint, 0644); - module_param(serial, uint, 0644); --module_param(reboot_part, uint, 0644); - -From f384e2b3b12499f3677facd847263c2669f71d51 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:35:40 +0200 -Subject: [PATCH 113/208] bcm270x: Remove dead files -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -include/mach/vmalloc.h has not been used since 2011. -include/mach/entry-macro.S is leftover from the move to the mainline -irq driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 ---- - arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 ----------------------- - arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 ---- - 3 files changed, 163 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h - -diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h -deleted file mode 100644 -index 502c6178101be60b10c9eb31afec938b5534c33f..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/vmalloc.h -+++ /dev/null -@@ -1,20 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vmalloc.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#define VMALLOC_END (0xe8000000) -diff --git a/arch/arm/mach-bcm2709/include/mach/entry-macro.S b/arch/arm/mach-bcm2709/include/mach/entry-macro.S -deleted file mode 100644 -index d08591b63c1a1710c40350d343d3eddc97ae74c1..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/entry-macro.S -+++ /dev/null -@@ -1,123 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/entry-macro.S -- * -- * Low-level IRQ helper macros for BCM2708 platforms -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#include --#include -- -- .macro disable_fiq -- .endm -- -- .macro get_irqnr_preamble, base, tmp -- ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) -- .endm -- -- .macro arch_ret_to_user, tmp1, tmp2 -- .endm -- -- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -- /* get core number */ -- mrc p15, 0, \tmp, c0, c0, 5 -- ubfx \tmp, \tmp, #0, #2 -- -- /* get core's local interrupt controller */ -- ldr \irqstat, = __io_address(ARM_LOCAL_IRQ_PENDING0) @ local interrupt source -- add \irqstat, \irqstat, \tmp, lsl #2 -- ldr \tmp, [\irqstat] -- /* ignore gpu interrupt */ -- bic \tmp, #0x100 -- /* ignore mailbox interrupts */ -- bics \tmp, #0xf0 -- beq 1005f -- -- @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -- @ N.B. CLZ is an ARM5 instruction. -- mov \irqnr, #(ARM_IRQ_LOCAL_BASE + 31) -- sub \irqstat, \tmp, #1 -- eor \irqstat, \irqstat, \tmp -- clz \tmp, \irqstat -- sub \irqnr, \tmp -- b 1020f --1005: -- /* get core number */ -- mrc p15, 0, \tmp, c0, c0, 5 -- ubfx \tmp, \tmp, #0, #2 -- -- cmp \tmp, #1 -- beq 1020f -- cmp \tmp, #2 -- beq 1020f -- cmp \tmp, #3 -- beq 1020f -- -- /* get masked status */ -- ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] -- mov \irqnr, #(ARM_IRQ0_BASE + 31) -- and \tmp, \irqstat, #0x300 @ save bits 8 and 9 -- /* clear bits 8 and 9, and test */ -- bics \irqstat, \irqstat, #0x300 -- bne 1010f -- -- tst \tmp, #0x100 -- ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] -- movne \irqnr, #(ARM_IRQ1_BASE + 31) -- @ Mask out the interrupts also present in PEND0 - see SW-5809 -- bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) -- bicne \irqstat, #((1<<18) | (1<<19)) -- bne 1010f -- -- tst \tmp, #0x200 -- ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] -- movne \irqnr, #(ARM_IRQ2_BASE + 31) -- @ Mask out the interrupts also present in PEND0 - see SW-5809 -- bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) -- bicne \irqstat, #((1<<30)) -- beq 1020f -- --1010: -- @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) -- @ N.B. CLZ is an ARM5 instruction. -- sub \tmp, \irqstat, #1 -- eor \irqstat, \irqstat, \tmp -- clz \tmp, \irqstat -- sub \irqnr, \tmp -- --1020: @ EQ will be set if no irqs pending -- -- .endm -- -- .macro test_for_ipi, irqnr, irqstat, base, tmp -- /* get core number */ -- mrc p15, 0, \tmp, c0, c0, 5 -- ubfx \tmp, \tmp, #0, #2 -- /* get core's mailbox interrupt control */ -- ldr \irqstat, = __io_address(ARM_LOCAL_MAILBOX0_CLR0) @ mbox_clr -- add \irqstat, \irqstat, \tmp, lsl #4 -- ldr \tmp, [\irqstat] -- cmp \tmp, #0 -- beq 1030f -- clz \tmp, \tmp -- rsb \irqnr, \tmp, #31 -- mov \tmp, #1 -- lsl \tmp, \irqnr -- str \tmp, [\irqstat] @ clear interrupt source -- dsb --1030: @ EQ will be set if no irqs pending -- .endm -diff --git a/arch/arm/mach-bcm2709/include/mach/vmalloc.h b/arch/arm/mach-bcm2709/include/mach/vmalloc.h -deleted file mode 100644 -index 6aa68260dd866c83527dffece8de483913231fb3..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/vmalloc.h -+++ /dev/null -@@ -1,20 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vmalloc.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#define VMALLOC_END (0xff000000) - -From 0b9d5789d2a90665ed8f46c3dcdff92d3da2e8d7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:37:43 +0200 -Subject: [PATCH 114/208] bcm270x: Drop bcm2835-aux-uart hack -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The gated bcm2835-aux clock is now used to enable uart1 so drop this hack. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 15 +-------------- - arch/arm/mach-bcm2709/bcm2709.c | 15 +-------------- - 2 files changed, 2 insertions(+), 28 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a8e2a5b114b2f12f18378ce5fff2a88419b6f52f..8d1e56db3a89295af18dff99f1ee572f56487e72 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -98,18 +98,7 @@ void __init bcm2708_map_io(void) - iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); - } - --static void __init bcm2708_init_uart1(void) --{ -- struct device_node *np; -- -- np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -- if (of_device_is_available(np)) { -- pr_info("bcm2708: Mini UART enabled\n"); -- writel(1, __io_address(UART1_BASE + 0x4)); -- } --} -- --void __init bcm2708_init(void) -+static void __init bcm2708_init(void) - { - int ret; - -@@ -122,8 +111,6 @@ void __init bcm2708_init(void) - BUG(); - } - -- bcm2708_init_uart1(); -- - system_rev = boardrev; - system_serial_low = serial; - } -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index ed5c5414f7a3ad7284cda881e9e550777cd29282..9a1ad48d13172856e3ec748db015cb95cd110b76 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -110,18 +110,7 @@ void __init bcm2709_map_io(void) - iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); - } - --static void __init bcm2709_init_uart1(void) --{ -- struct device_node *np; -- -- np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -- if (of_device_is_available(np)) { -- pr_info("bcm2709: Mini UART enabled\n"); -- writel(1, __io_address(UART1_BASE + 0x4)); -- } --} -- --void __init bcm2709_init(void) -+static void __init bcm2709_init(void) - { - int ret; - -@@ -134,8 +123,6 @@ void __init bcm2709_init(void) - BUG(); - } - -- bcm2709_init_uart1(); -- - system_rev = boardrev; - system_serial_low = serial; - } - -From 609fc508667ebfb25abaab84e856373ea13ad521 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:41:26 +0200 -Subject: [PATCH 115/208] bcm270x: Remove unnecessary of_platform_populate -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since 4.8 of_platform_default_populate_init() does the same and it is -called at arch_initcall_sync. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 10 ---------- - arch/arm/mach-bcm2709/bcm2709.c | 10 ---------- - 2 files changed, 20 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 8d1e56db3a89295af18dff99f1ee572f56487e72..0db44e566062751510494e2fe19926122aad7d5a 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -21,7 +21,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -100,17 +99,8 @@ void __init bcm2708_map_io(void) - - static void __init bcm2708_init(void) - { -- int ret; -- - vc_cma_early_init(); - -- ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -- NULL); -- if (ret) { -- pr_err("of_platform_populate failed: %d\n", ret); -- BUG(); -- } -- - system_rev = boardrev; - system_serial_low = serial; - } -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 9a1ad48d13172856e3ec748db015cb95cd110b76..d2762f558f644ac87c56ba9402a638a3c7a26397 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - - #include - #include -@@ -112,17 +111,8 @@ void __init bcm2709_map_io(void) - - static void __init bcm2709_init(void) - { -- int ret; -- - vc_cma_early_init(); - -- ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, -- NULL); -- if (ret) { -- pr_err("of_platform_populate failed: %d\n", ret); -- BUG(); -- } -- - system_rev = boardrev; - system_serial_low = serial; - } - -From f24c1d7e84b995a5c72dcfeaa4dec996f816438e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 17:46:27 +0200 -Subject: [PATCH 116/208] bcm270x: Remove 4MB dma coherent pool -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Drop the call to init_dma_coherent_pool_size(). The default 256kB is -enough since vchiq dropped that atomic allocation some time back. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 11 ----------- - arch/arm/mach-bcm2709/bcm2709.c | 12 ------------ - 2 files changed, 23 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 0db44e566062751510494e2fe19926122aad7d5a..0dc1efd48f385eea9f712fc8e18ffc92966271f2 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -105,16 +105,6 @@ static void __init bcm2708_init(void) - system_serial_low = serial; - } - --void __init bcm2708_init_early(void) --{ -- /* -- * Some devices allocate their coherent buffers from atomic -- * context. Increase size of atomic coherent pool to make sure such -- * the allocations won't fail. -- */ -- init_dma_coherent_pool_size(SZ_4M); --} -- - static void __init board_reserve(void) - { - vc_cma_reserve(); -@@ -129,7 +119,6 @@ MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2708_map_io, - .init_machine = bcm2708_init, -- .init_early = bcm2708_init_early, - .reserve = board_reserve, - .dt_compat = bcm2708_compat, - MACHINE_END -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d2762f558f644ac87c56ba9402a638a3c7a26397..d0e43619669e851350c5d9d7bb7e9dd19ea6ff1b 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -117,16 +117,6 @@ static void __init bcm2709_init(void) - system_serial_low = serial; - } - --void __init bcm2709_init_early(void) --{ -- /* -- * Some devices allocate their coherent buffers from atomic -- * context. Increase size of atomic coherent pool to make sure such -- * the allocations won't fail. -- */ -- init_dma_coherent_pool_size(SZ_4M); --} -- - static void __init board_reserve(void) - { - vc_cma_reserve(); -@@ -142,7 +132,6 @@ MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, -- .init_early = bcm2709_init_early, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, - MACHINE_END -@@ -151,7 +140,6 @@ MACHINE_START(BCM2708, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, -- .init_early = bcm2709_init_early, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, - MACHINE_END - -From 0fcba7b96ea2778232431b7ae302e1473c1abdb5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 19:26:42 +0200 -Subject: [PATCH 117/208] bcm270x: Drop map_io device mapping -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -All drivers map their own io now so it's not necessary to do this -mapping anymore. The mapping for the uart debug console is handled by -debug_ll_io_init() if necessary. - -Remove local uart debug code and rely on mainline. -Use these kconfig options to enable: -CONFIG_DEBUG_BCM2835 -CONFIG_DEBUG_BCM2836 - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig.debug | 18 +-- - arch/arm/mach-bcm2708/bcm2708.c | 75 +-------- - arch/arm/mach-bcm2708/include/mach/debug-macro.S | 22 --- - arch/arm/mach-bcm2708/include/mach/platform.h | 114 -------------- - arch/arm/mach-bcm2708/include/mach/system.h | 37 ----- - arch/arm/mach-bcm2708/include/mach/uncompress.h | 84 ---------- - arch/arm/mach-bcm2709/bcm2709.c | 86 +--------- - arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 --- - arch/arm/mach-bcm2709/include/mach/platform.h | 190 ----------------------- - arch/arm/mach-bcm2709/include/mach/system.h | 37 ----- - arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 ---------- - 11 files changed, 11 insertions(+), 758 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S - delete mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h - delete mode 100644 arch/arm/mach-bcm2708/include/mach/system.h - delete mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S - delete mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/system.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h - -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index f47f4e70395635fafeacd680c4392cc51660ea8e..11aa81fcaaa8e476ded9b9f41e30ddefa11c1cae 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -147,12 +147,12 @@ choice - - config DEBUG_BCM2835 - bool "Kernel low-level debugging on BCM2835 PL011 UART" -- depends on ARCH_BCM2835 && ARCH_MULTI_V6 -+ depends on (ARCH_BCM2835 && ARCH_MULTI_V6) || ARCH_BCM2708 - select DEBUG_UART_PL01X - - config DEBUG_BCM2836 - bool "Kernel low-level debugging on BCM2836 PL011 UART" -- depends on ARCH_BCM2835 && ARCH_MULTI_V7 -+ depends on (ARCH_BCM2835 && ARCH_MULTI_V7) || ARCH_BCM2709 - select DEBUG_UART_PL01X - - config DEBUG_BCM_5301X -@@ -1312,14 +1312,6 @@ choice - options; the platform specific options are deprecated - and will be soon removed. - -- config DEBUG_BCM2708_UART0 -- bool "Broadcom BCM270X UART0 (PL011)" -- depends on ARCH_BCM2708 || ARCH_BCM2709 -- help -- Say Y here if you want the debug print routines to direct -- their output to UART 0. The port must have been initialised -- by the boot-loader before use. -- - endchoice - - config DEBUG_AT91_UART -@@ -1703,7 +1695,8 @@ config DEBUG_UART_8250_FLOW_CONTROL - - config DEBUG_UNCOMPRESS - bool -- depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M -+ depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -+ ARCH_BCM2708 || ARCH_BCM2709 - default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ - (!DEBUG_TEGRA_UART || !ZBOOT_ROM) - help -@@ -1720,7 +1713,8 @@ config DEBUG_UNCOMPRESS - config UNCOMPRESS_INCLUDE - string - default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \ -- PLAT_SAMSUNG || ARM_SINGLE_ARMV7M -+ PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -+ ARCH_BCM2708 || ARCH_BCM2709 - default "mach/uncompress.h" - - config EARLY_PRINTK -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 0dc1efd48f385eea9f712fc8e18ffc92966271f2..47d5f363334ea317f09a6d6b7c8f3f2f797a2be3 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -19,84 +19,16 @@ - */ - - #include --#include - #include --#include --#include --#include --#include -- --#include -- - #include - --/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -- * give us IO access only to 64Mbytes of physical memory (26 bits). We could -- * represent this window by setting our dmamasks to 26 bits but, in fact -- * we're not going to use addresses outside this range (they're not in real -- * memory) so we don't bother. -- * -- * In the future we might include code to use this IOMMU to remap other -- * physical addresses onto VideoCore memory then the use of 32-bits would be -- * more legitimate. -- */ -+#include -+#include -+#include - - /* command line parameters */ - static unsigned boardrev, serial; - --static struct map_desc bcm2708_io_desc[] __initdata = { -- { -- .virtual = IO_ADDRESS(ARMCTRL_BASE), -- .pfn = __phys_to_pfn(ARMCTRL_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART0_BASE), -- .pfn = __phys_to_pfn(UART0_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART1_BASE), -- .pfn = __phys_to_pfn(UART1_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(DMA_BASE), -- .pfn = __phys_to_pfn(DMA_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(MCORE_BASE), -- .pfn = __phys_to_pfn(MCORE_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(ST_BASE), -- .pfn = __phys_to_pfn(ST_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(USB_BASE), -- .pfn = __phys_to_pfn(USB_BASE), -- .length = SZ_128K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(PM_BASE), -- .pfn = __phys_to_pfn(PM_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(GPIO_BASE), -- .pfn = __phys_to_pfn(GPIO_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE} --}; -- --void __init bcm2708_map_io(void) --{ -- iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); --} -- - static void __init bcm2708_init(void) - { - vc_cma_early_init(); -@@ -117,7 +49,6 @@ static const char * const bcm2708_compat[] = { - - MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ -- .map_io = bcm2708_map_io, - .init_machine = bcm2708_init, - .reserve = board_reserve, - .dt_compat = bcm2708_compat, -diff --git a/arch/arm/mach-bcm2708/include/mach/debug-macro.S b/arch/arm/mach-bcm2708/include/mach/debug-macro.S -deleted file mode 100644 -index b24304a6755e965b8a28eb048b7f4e2d868820f9..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/debug-macro.S -+++ /dev/null -@@ -1,22 +0,0 @@ --/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -- * -- * Debugging macro include header -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 1994-1999 Russell King -- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * --*/ -- --#include -- -- .macro addruart, rp, rv, tmp -- ldr \rp, =UART0_BASE -- ldr \rv, =IO_ADDRESS(UART0_BASE) -- .endm -- --#include -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -deleted file mode 100644 -index e98ec5acc70ba9eb2bc7ff560ed3c92e21518b73..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ /dev/null -@@ -1,114 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/platform.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _BCM2708_PLATFORM_H --#define _BCM2708_PLATFORM_H -- -- --/* macros to get at IO space when running virtually */ --#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -- --#define __io_address(n) IOMEM(IO_ADDRESS(n)) -- -- --/* -- * SDRAM -- */ --#define BCM2708_SDRAM_BASE 0x00000000 -- --/* -- * Logic expansion modules -- * -- */ -- -- --/* ------------------------------------------------------------------------ -- * BCM2708 ARMCTRL Registers -- * ------------------------------------------------------------------------ -- */ -- --#define HW_REGISTER_RW(addr) (addr) --#define HW_REGISTER_RO(addr) (addr) -- --/* -- * Definitions and addresses for the ARM CONTROL logic -- * This file is manually generated. -- */ -- --#define BCM2708_PERI_BASE 0x20000000 --#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) --#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ --#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ --#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ --#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ --#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ --#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ --#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ --#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ --#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ --#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ --#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ --#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ --#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ --#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ --#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ --#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ --#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ --#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ --#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -- --#define ARMCTRL_BASE (ARM_BASE + 0x000) --#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ --#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ --#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ --#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ --#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ -- --/* -- * Watchdog -- */ --#define PM_RSTC (PM_BASE+0x1c) --#define PM_RSTS (PM_BASE+0x20) --#define PM_WDOG (PM_BASE+0x24) -- --#define PM_WDOG_RESET 0000000000 --#define PM_PASSWORD 0x5a000000 --#define PM_WDOG_TIME_SET 0x000fffff --#define PM_RSTC_WRCFG_CLR 0xffffffcf --#define PM_RSTC_WRCFG_SET 0x00000030 --#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 --#define PM_RSTC_RESET 0x00000102 -- --#define PM_RSTS_HADPOR_SET 0x00001000 --#define PM_RSTS_HADSRH_SET 0x00000400 --#define PM_RSTS_HADSRF_SET 0x00000200 --#define PM_RSTS_HADSRQ_SET 0x00000100 --#define PM_RSTS_HADWRH_SET 0x00000040 --#define PM_RSTS_HADWRF_SET 0x00000020 --#define PM_RSTS_HADWRQ_SET 0x00000010 --#define PM_RSTS_HADDRH_SET 0x00000004 --#define PM_RSTS_HADDRF_SET 0x00000002 --#define PM_RSTS_HADDRQ_SET 0x00000001 -- --#define UART0_CLOCK 3000000 -- --#endif -- --/* END */ -diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h -deleted file mode 100644 -index c9a9c9a881102c5354971d15203a746906761a70..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/system.h -+++ /dev/null -@@ -1,37 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/system.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * Copyright (C) 2000 Deep Blue Solutions Ltd -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_SYSTEM_H --#define __ASM_ARCH_SYSTEM_H -- --#include --#include -- --static inline void arch_idle(void) --{ -- /* -- * This should do all the clock switching -- * and wait for interrupt tricks -- */ -- cpu_do_idle(); --} -- --#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/uncompress.h b/arch/arm/mach-bcm2708/include/mach/uncompress.h -deleted file mode 100644 -index de7504bfc20ba24be8707861b8389783860adb77..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/uncompress.h -+++ /dev/null -@@ -1,84 +0,0 @@ --/* -- * arch/arm/mach-bcn2708/include/mach/uncompress.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include --#include -- --#define UART_BAUD 115200 -- --#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) --#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) --#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) --#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) --#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) --#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -- --/* -- * This does not append a newline -- */ --static inline void putc(int c) --{ -- while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -- barrier(); -- -- __raw_writel(c, BCM2708_UART_DR); --} -- --static inline void flush(void) --{ -- int fr; -- -- do { -- fr = __raw_readl(BCM2708_UART_FR); -- barrier(); -- } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); --} -- --static inline void arch_decomp_setup(void) --{ -- int temp, div, rem, frac; -- -- temp = 16 * UART_BAUD; -- div = UART0_CLOCK / temp; -- rem = UART0_CLOCK % temp; -- temp = (8 * rem) / UART_BAUD; -- frac = (temp >> 1) + (temp & 1); -- -- /* Make sure the UART is disabled before we start */ -- __raw_writel(0, BCM2708_UART_CR); -- -- /* Set the baud rate */ -- __raw_writel(div, BCM2708_UART_IBRD); -- __raw_writel(frac, BCM2708_UART_FBRD); -- -- /* Set the UART to 8n1, FIFO enabled */ -- __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -- -- /* Enable the UART */ -- __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -- BCM2708_UART_CR); --} -- --/* -- * nothing to do -- */ --#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d0e43619669e851350c5d9d7bb7e9dd19ea6ff1b..39d304327bc84899a521aaeed8c1edd83c26d2d6 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -19,96 +19,16 @@ - */ - - #include --#include --#include --#include --#include --#include - #include -+#include - --#include - #include --#include -- - #include --#include -- --#include -- --#include -- --/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to -- * give us IO access only to 64Mbytes of physical memory (26 bits). We could -- * represent this window by setting our dmamasks to 26 bits but, in fact -- * we're not going to use addresses outside this range (they're not in real -- * memory) so we don't bother. -- * -- * In the future we might include code to use this IOMMU to remap other -- * physical addresses onto VideoCore memory then the use of 32-bits would be -- * more legitimate. -- */ -+#include - - /* command line parameters */ - static unsigned boardrev, serial; - --static struct map_desc bcm2709_io_desc[] __initdata = { -- { -- .virtual = IO_ADDRESS(ARMCTRL_BASE), -- .pfn = __phys_to_pfn(ARMCTRL_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART0_BASE), -- .pfn = __phys_to_pfn(UART0_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(UART1_BASE), -- .pfn = __phys_to_pfn(UART1_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(DMA_BASE), -- .pfn = __phys_to_pfn(DMA_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(MCORE_BASE), -- .pfn = __phys_to_pfn(MCORE_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(ST_BASE), -- .pfn = __phys_to_pfn(ST_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(USB_BASE), -- .pfn = __phys_to_pfn(USB_BASE), -- .length = SZ_128K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(PM_BASE), -- .pfn = __phys_to_pfn(PM_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(GPIO_BASE), -- .pfn = __phys_to_pfn(GPIO_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, -- { -- .virtual = IO_ADDRESS(ARM_LOCAL_BASE), -- .pfn = __phys_to_pfn(ARM_LOCAL_BASE), -- .length = SZ_4K, -- .type = MT_DEVICE}, --}; -- --void __init bcm2709_map_io(void) --{ -- iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); --} -- - static void __init bcm2709_init(void) - { - vc_cma_early_init(); -@@ -130,7 +50,6 @@ static const char * const bcm2709_compat[] = { - - MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ -- .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, -@@ -138,7 +57,6 @@ MACHINE_END - - MACHINE_START(BCM2708, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ -- .map_io = bcm2709_map_io, - .init_machine = bcm2709_init, - .reserve = board_reserve, - .dt_compat = bcm2709_compat, -diff --git a/arch/arm/mach-bcm2709/include/mach/debug-macro.S b/arch/arm/mach-bcm2709/include/mach/debug-macro.S -deleted file mode 100644 -index b24304a6755e965b8a28eb048b7f4e2d868820f9..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/debug-macro.S -+++ /dev/null -@@ -1,22 +0,0 @@ --/* arch/arm/mach-bcm2708/include/mach/debug-macro.S -- * -- * Debugging macro include header -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 1994-1999 Russell King -- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * --*/ -- --#include -- -- .macro addruart, rp, rv, tmp -- ldr \rp, =UART0_BASE -- ldr \rv, =IO_ADDRESS(UART0_BASE) -- .endm -- --#include -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -deleted file mode 100644 -index 9a638f528fcebc9206419a2cc68f3c9856dda3c3..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ /dev/null -@@ -1,190 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/platform.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _BCM2708_PLATFORM_H --#define _BCM2708_PLATFORM_H -- -- --/* macros to get at IO space when running virtually */ --#define IO_ADDRESS(x) (((x) & 0x00ffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -- --#define __io_address(n) IOMEM(IO_ADDRESS(n)) -- -- --/* -- * SDRAM -- */ --#define BCM2708_SDRAM_BASE 0x00000000 -- --/* -- * Logic expansion modules -- * -- */ -- -- --/* ------------------------------------------------------------------------ -- * BCM2708 ARMCTRL Registers -- * ------------------------------------------------------------------------ -- */ -- --#define HW_REGISTER_RW(addr) (addr) --#define HW_REGISTER_RO(addr) (addr) -- --/* -- * Definitions and addresses for the ARM CONTROL logic -- * This file is manually generated. -- */ -- --#define BCM2708_PERI_BASE 0x3F000000 --#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) --#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ --#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ --#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ --#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ --#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ --#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ --#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ --#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ --#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ --#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ --#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ --#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ --#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ --#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ --#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ --#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ --#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ --#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ --#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ -- --#define ARMCTRL_BASE (ARM_BASE + 0x000) --#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ --#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ --#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ --#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ --#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ -- --/* -- * Watchdog -- */ --#define PM_RSTC (PM_BASE+0x1c) --#define PM_RSTS (PM_BASE+0x20) --#define PM_WDOG (PM_BASE+0x24) -- --#define PM_WDOG_RESET 0000000000 --#define PM_PASSWORD 0x5a000000 --#define PM_WDOG_TIME_SET 0x000fffff --#define PM_RSTC_WRCFG_CLR 0xffffffcf --#define PM_RSTC_WRCFG_SET 0x00000030 --#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 --#define PM_RSTC_RESET 0x00000102 -- --#define PM_RSTS_HADPOR_SET 0x00001000 --#define PM_RSTS_HADSRH_SET 0x00000400 --#define PM_RSTS_HADSRF_SET 0x00000200 --#define PM_RSTS_HADSRQ_SET 0x00000100 --#define PM_RSTS_HADWRH_SET 0x00000040 --#define PM_RSTS_HADWRF_SET 0x00000020 --#define PM_RSTS_HADWRQ_SET 0x00000010 --#define PM_RSTS_HADDRH_SET 0x00000004 --#define PM_RSTS_HADDRF_SET 0x00000002 --#define PM_RSTS_HADDRQ_SET 0x00000001 -- --#define UART0_CLOCK 3000000 -- --#define ARM_LOCAL_BASE 0x40000000 --#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) -- --#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) --#define ARM_LOCAL_PRESCALER HW_REGISTER_RW(ARM_LOCAL_BASE+0x008) --#define ARM_LOCAL_GPU_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x00C) --#define ARM_LOCAL_PM_ROUTING_SET HW_REGISTER_RW(ARM_LOCAL_BASE+0x010) --#define ARM_LOCAL_PM_ROUTING_CLR HW_REGISTER_RW(ARM_LOCAL_BASE+0x014) --#define ARM_LOCAL_TIMER_LS HW_REGISTER_RW(ARM_LOCAL_BASE+0x01C) --#define ARM_LOCAL_TIMER_MS HW_REGISTER_RW(ARM_LOCAL_BASE+0x020) --#define ARM_LOCAL_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x024) --#define ARM_LOCAL_AXI_COUNT HW_REGISTER_RW(ARM_LOCAL_BASE+0x02C) --#define ARM_LOCAL_AXI_IRQ HW_REGISTER_RW(ARM_LOCAL_BASE+0x030) --#define ARM_LOCAL_TIMER_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x034) --#define ARM_LOCAL_TIMER_WRITE HW_REGISTER_RW(ARM_LOCAL_BASE+0x038) -- --#define ARM_LOCAL_TIMER_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x040) --#define ARM_LOCAL_TIMER_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x044) --#define ARM_LOCAL_TIMER_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x048) --#define ARM_LOCAL_TIMER_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x04C) -- --#define ARM_LOCAL_MAILBOX_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x050) --#define ARM_LOCAL_MAILBOX_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x054) --#define ARM_LOCAL_MAILBOX_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x058) --#define ARM_LOCAL_MAILBOX_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x05C) -- --#define ARM_LOCAL_IRQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x060) --#define ARM_LOCAL_IRQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x064) --#define ARM_LOCAL_IRQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x068) --#define ARM_LOCAL_IRQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x06C) -- --#define ARM_LOCAL_FIQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x070) --#define ARM_LOCAL_FIQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x074) --#define ARM_LOCAL_FIQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x078) --#define ARM_LOCAL_FIQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x07C) -- --#define ARM_LOCAL_MAILBOX0_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x080) --#define ARM_LOCAL_MAILBOX1_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x084) --#define ARM_LOCAL_MAILBOX2_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x088) --#define ARM_LOCAL_MAILBOX3_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x08C) -- --#define ARM_LOCAL_MAILBOX0_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x090) --#define ARM_LOCAL_MAILBOX1_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x094) --#define ARM_LOCAL_MAILBOX2_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x098) --#define ARM_LOCAL_MAILBOX3_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x09C) -- --#define ARM_LOCAL_MAILBOX0_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A0) --#define ARM_LOCAL_MAILBOX1_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A4) --#define ARM_LOCAL_MAILBOX2_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A8) --#define ARM_LOCAL_MAILBOX3_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0AC) -- --#define ARM_LOCAL_MAILBOX0_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B0) --#define ARM_LOCAL_MAILBOX1_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B4) --#define ARM_LOCAL_MAILBOX2_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B8) --#define ARM_LOCAL_MAILBOX3_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0BC) -- --#define ARM_LOCAL_MAILBOX0_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C0) --#define ARM_LOCAL_MAILBOX1_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C4) --#define ARM_LOCAL_MAILBOX2_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C8) --#define ARM_LOCAL_MAILBOX3_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0CC) -- --#define ARM_LOCAL_MAILBOX0_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D0) --#define ARM_LOCAL_MAILBOX1_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D4) --#define ARM_LOCAL_MAILBOX2_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D8) --#define ARM_LOCAL_MAILBOX3_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0DC) -- --#define ARM_LOCAL_MAILBOX0_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E0) --#define ARM_LOCAL_MAILBOX1_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E4) --#define ARM_LOCAL_MAILBOX2_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E8) --#define ARM_LOCAL_MAILBOX3_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0EC) -- --#define ARM_LOCAL_MAILBOX0_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F0) --#define ARM_LOCAL_MAILBOX1_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F4) --#define ARM_LOCAL_MAILBOX2_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F8) --#define ARM_LOCAL_MAILBOX3_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0FC) -- --#endif -- --/* END */ -diff --git a/arch/arm/mach-bcm2709/include/mach/system.h b/arch/arm/mach-bcm2709/include/mach/system.h -deleted file mode 100644 -index c9a9c9a881102c5354971d15203a746906761a70..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/system.h -+++ /dev/null -@@ -1,37 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/system.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * Copyright (C) 2000 Deep Blue Solutions Ltd -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_SYSTEM_H --#define __ASM_ARCH_SYSTEM_H -- --#include --#include -- --static inline void arch_idle(void) --{ -- /* -- * This should do all the clock switching -- * and wait for interrupt tricks -- */ -- cpu_do_idle(); --} -- --#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/uncompress.h b/arch/arm/mach-bcm2709/include/mach/uncompress.h -deleted file mode 100644 -index de7504bfc20ba24be8707861b8389783860adb77..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/uncompress.h -+++ /dev/null -@@ -1,84 +0,0 @@ --/* -- * arch/arm/mach-bcn2708/include/mach/uncompress.h -- * -- * Copyright (C) 2010 Broadcom -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include --#include -- --#define UART_BAUD 115200 -- --#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) --#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) --#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) --#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) --#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) --#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) -- --/* -- * This does not append a newline -- */ --static inline void putc(int c) --{ -- while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) -- barrier(); -- -- __raw_writel(c, BCM2708_UART_DR); --} -- --static inline void flush(void) --{ -- int fr; -- -- do { -- fr = __raw_readl(BCM2708_UART_FR); -- barrier(); -- } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); --} -- --static inline void arch_decomp_setup(void) --{ -- int temp, div, rem, frac; -- -- temp = 16 * UART_BAUD; -- div = UART0_CLOCK / temp; -- rem = UART0_CLOCK % temp; -- temp = (8 * rem) / UART_BAUD; -- frac = (temp >> 1) + (temp & 1); -- -- /* Make sure the UART is disabled before we start */ -- __raw_writel(0, BCM2708_UART_CR); -- -- /* Set the baud rate */ -- __raw_writel(div, BCM2708_UART_IBRD); -- __raw_writel(frac, BCM2708_UART_FBRD); -- -- /* Set the UART to 8n1, FIFO enabled */ -- __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); -- -- /* Enable the UART */ -- __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, -- BCM2708_UART_CR); --} -- --/* -- * nothing to do -- */ --#define arch_decomp_wdog() - -From 038f7a212a81706150142e5415ddb060d46c76bf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 10 Oct 2016 19:37:06 +0200 -Subject: [PATCH 118/208] bcm270x: Use DT_MACHINE_START -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We are all DT now so use DT_MACHINE_START. -Also drop the extra BCM2709-BCM2708 mix entry. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 3 +-- - arch/arm/mach-bcm2709/bcm2709.c | 11 +---------- - arch/arm/tools/mach-types | 2 -- - 3 files changed, 2 insertions(+), 14 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 47d5f363334ea317f09a6d6b7c8f3f2f797a2be3..ddf62c084981ecf02491ea6b2817782dae050ce1 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -22,7 +22,6 @@ - #include - #include - --#include - #include - #include - -@@ -47,7 +46,7 @@ static const char * const bcm2708_compat[] = { - NULL - }; - --MACHINE_START(BCM2708, "BCM2708") -+DT_MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ - .init_machine = bcm2708_init, - .reserve = board_reserve, -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 39d304327bc84899a521aaeed8c1edd83c26d2d6..9cf36118e57b3c362de9adcf089425023d4a601d 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -22,7 +22,6 @@ - #include - #include - --#include - #include - #include - -@@ -44,18 +43,10 @@ static void __init board_reserve(void) - - static const char * const bcm2709_compat[] = { - "brcm,bcm2709", -- "brcm,bcm2708", /* Could use bcm2708 in a pinch */ - NULL - }; - --MACHINE_START(BCM2709, "BCM2709") -- /* Maintainer: Broadcom Europe Ltd. */ -- .init_machine = bcm2709_init, -- .reserve = board_reserve, -- .dt_compat = bcm2709_compat, --MACHINE_END -- --MACHINE_START(BCM2708, "BCM2709") -+DT_MACHINE_START(BCM2709, "BCM2709") - /* Maintainer: Broadcom Europe Ltd. */ - .init_machine = bcm2709_init, - .reserve = board_reserve, -diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index b52d949ee91d96eb7672fbbb4969bfa1e7afc376..2ed1b8a922ed02b9e3545991873af77b4c1bf871 100644 ---- a/arch/arm/tools/mach-types -+++ b/arch/arm/tools/mach-types -@@ -522,8 +522,6 @@ torbreck MACH_TORBRECK TORBRECK 3090 - prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 - paz00 MACH_PAZ00 PAZ00 3128 - acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 --bcm2708 MACH_BCM2708 BCM2708 3138 --bcm2709 MACH_BCM2709 BCM2709 3139 - ag5evm MACH_AG5EVM AG5EVM 3189 - ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 - wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 - -From fde57b59c0e15f0416bc962bb82988aba3715acf Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 11 Oct 2016 17:48:07 +0100 -Subject: [PATCH 119/208] Use DT rather than modules params for board rev and - serial - ---- - arch/arm/mach-bcm2708/bcm2708.c | 18 +++++++++--------- - arch/arm/mach-bcm2709/bcm2709.c | 19 +++++++++---------- - 2 files changed, 18 insertions(+), 19 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index ddf62c084981ecf02491ea6b2817782dae050ce1..06b078569006a6d821d3d049f1a0fa5783c1c1b3 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -18,22 +18,24 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - --#include --#include -+#include - #include - - #include - #include - --/* command line parameters */ --static unsigned boardrev, serial; -- - static void __init bcm2708_init(void) - { -+ struct device_node *np = of_find_node_by_path("/system"); -+ u32 val; -+ u64 val64; -+ - vc_cma_early_init(); - -- system_rev = boardrev; -- system_serial_low = serial; -+ if (!of_property_read_u32(np, "linux,revision", &val)) -+ system_rev = val; -+ if (!of_property_read_u64(np, "linux,serial", &val64)) -+ system_serial_low = val64; - } - - static void __init board_reserve(void) -@@ -53,5 +55,3 @@ DT_MACHINE_START(BCM2708, "BCM2708") - .dt_compat = bcm2708_compat, - MACHINE_END - --module_param(boardrev, uint, 0644); --module_param(serial, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 9cf36118e57b3c362de9adcf089425023d4a601d..9f113736627175bdcb362e0eda469e09e3d5f2e0 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -18,22 +18,24 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - --#include --#include -+#include - #include - - #include - #include - --/* command line parameters */ --static unsigned boardrev, serial; -- - static void __init bcm2709_init(void) - { -+ struct device_node *np = of_find_node_by_path("/system"); -+ u32 val; -+ u64 val64; -+ - vc_cma_early_init(); - -- system_rev = boardrev; -- system_serial_low = serial; -+ if (!of_property_read_u32(np, "linux,revision", &val)) -+ system_rev = val; -+ if (!of_property_read_u64(np, "linux,serial", &val64)) -+ system_serial_low = val64; - } - - static void __init board_reserve(void) -@@ -52,6 +54,3 @@ DT_MACHINE_START(BCM2709, "BCM2709") - .reserve = board_reserve, - .dt_compat = bcm2709_compat, - MACHINE_END -- --module_param(boardrev, uint, 0644); --module_param(serial, uint, 0644); - -From c687c89cf84f71ee3e67c3b965106b5f4d9aa774 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 2 Sep 2016 16:45:27 +0100 -Subject: [PATCH 120/208] Register the clocks early during the boot process, so - that special/critical clocks can get enabled early on in the boot process - avoiding the risk of disabling a clock, pll_divider or pll when a claiming - driver fails to install propperly - maybe it needs to defer. - -Signed-off-by: Martin Sperl ---- - drivers/clk/bcm/clk-bcm2835.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index fbf616021704178a9d007219a0ea2a9f1704f0a6..cbbc8d4ddcffc797268c0ecb6477005fa14e228b 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1891,8 +1891,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - if (ret) - return ret; - -- return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, -- &cprman->onecell); -+ ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, -+ &cprman->onecell); -+ if (ret) -+ return ret; -+ -+ /* note that we have registered all the clocks */ -+ dev_dbg(dev, "registered %d clocks\n", asize); -+ -+ return 0; - } - - static const struct of_device_id bcm2835_clk_of_match[] = { -@@ -1909,7 +1916,11 @@ static struct platform_driver bcm2835_clk_driver = { - .probe = bcm2835_clk_probe, - }; - --builtin_platform_driver(bcm2835_clk_driver); -+static int __init __bcm2835_clk_driver_init(void) -+{ -+ return platform_driver_register(&bcm2835_clk_driver); -+} -+core_initcall(__bcm2835_clk_driver_init); - - MODULE_AUTHOR("Eric Anholt "); - MODULE_DESCRIPTION("BCM2835 clock driver"); - -From fd03919a330c5acea88972ccb762f5786b9b13f2 Mon Sep 17 00:00:00 2001 -From: Scott Ellis -Date: Tue, 27 Sep 2016 04:29:00 -0400 -Subject: [PATCH 121/208] Add Adafruit pitft35 touchscreen support (#1657) - -The dts comes from the Adafruit repository - - https://github.com/adafruit/Adafruit-Pi-Kernel-o-Matic/blob/pitft/pitft35r-overlay.dts - -Reformatted slightly to match conventions in the pitft28-resistive-overlay. - -Signed-off-by: Scott Ellis ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 12 ++ - .../dts/overlays/pitft35-resistive-overlay.dts | 121 +++++++++++++++++++++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 5 files changed, 136 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index b6ed1a3c06a7a67d1dd79bb7e55421d8eccba492..6179b21af2fa8ec63429c3d379fc46085681dc7e 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -64,6 +64,7 @@ dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pitft35-resistive.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pps-gpio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pwm.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pwm-2chan.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 1ebb94c005d68b17792f95bd9792a08679298b26..2252ab9f5bab5dd40be9ebefa8e37c5bfb07d00f 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -848,6 +848,18 @@ Params: speed Display SPI bus speed - debug Debug output level {0-7} - - -+Name: pitft35-resistive -+Info: Adafruit PiTFT 3.5" resistive touch screen -+Load: dtoverlay=pitft35-resistive,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ - Name: pps-gpio - Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). - Load: dtoverlay=pps-gpio,= -diff --git a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..25cb5cc9576dadc3539f4ea3c9507c592ccac9d6 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts -@@ -0,0 +1,121 @@ -+/* -+ * Device Tree overlay for Adafruit PiTFT 3.5" resistive touch screen -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; @@ -140505,441 +116625,11 @@ index 0000000000000000000000000000000000000000..25cb5cc9576dadc3539f4ea3c9507c59 + fragment@2 { + target = <&spidev1>; + __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target = <&gpio>; -+ __overlay__ { -+ pitft_pins: pitft_pins { -+ brcm,pins = <24 25>; -+ brcm,function = <0 1>; /* in out */ -+ brcm,pull = <2 0>; /* pullup none */ -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pitft: pitft@0{ -+ compatible = "himax,hx8357d"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pitft_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <90>; -+ fps = <25>; -+ bgr; -+ buswidth = <8>; -+ dc-gpios = <&gpio 25 0>; -+ debug = <0>; -+ }; -+ -+ pitft_ts@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stmpe610"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -+ interrupts = <24 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ interrupt-controller; -+ -+ stmpe_touchscreen { -+ compatible = "st,stmpe-ts"; -+ st,sample-time = <4>; -+ st,mod-12b = <1>; -+ st,ref-sel = <0>; -+ st,adc-freq = <2>; -+ st,ave-ctrl = <3>; -+ st,touch-det-delay = <4>; -+ st,settling = <2>; -+ st,fraction-z = <7>; -+ st,i-drive = <0>; -+ }; -+ -+ stmpe_gpio: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ /* -+ * only GPIO2 is wired/available -+ * and it is wired to the backlight -+ */ -+ st,norequest-mask = <0x7b>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@5 { -+ target-path = "/soc"; -+ __overlay__ { -+ backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&stmpe_gpio 2 0>; -+ default-on; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&pitft>,"spi-max-frequency:0"; -+ rotate = <&pitft>,"rotate:0"; -+ fps = <&pitft>,"fps:0"; -+ debug = <&pitft>,"debug:0"; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index aa708638cc6f3bceb189c2deef7307252901291f..aa57989600923198d4bfb913c4d2e8a565a93e07 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1111,6 +1111,7 @@ CONFIG_FB_TFT_BD663474=m - CONFIG_FB_TFT_HX8340BN=m - CONFIG_FB_TFT_HX8347D=m - CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m - CONFIG_FB_TFT_ILI9163=m - CONFIG_FB_TFT_ILI9320=m - CONFIG_FB_TFT_ILI9325=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 952104ab6c4cd0e9d8f7bd5f2fba7a72da75424e..26fa6c2b6b6d745178e666465ba226afee701ab1 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1117,6 +1117,7 @@ CONFIG_FB_TFT_BD663474=m - CONFIG_FB_TFT_HX8340BN=m - CONFIG_FB_TFT_HX8347D=m - CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m - CONFIG_FB_TFT_ILI9163=m - CONFIG_FB_TFT_ILI9320=m - CONFIG_FB_TFT_ILI9325=m - -From 0a83e0533ed80a1ae7f8dbbd570a2c245c9432de Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 10 Oct 2016 15:06:20 +0100 -Subject: [PATCH 122/208] BCM270X_DT: Update CM3 to use sdhost interface - ---- - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index b5a5ae7747455438f8eabd28e8c11c6aeb0c1ecc..d13e3d4dac4e198c8cac451e3f64ef687e2ace1b 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -8,10 +8,9 @@ - }; - - &gpio { -- -- mmc_pins: mmc_pins { -+ sdhost_pins: sdhost_pins { - brcm,pins = <48 49 50 51 52 53>; -- brcm,function = <7>; /* alt3 */ -+ brcm,function = <4>; /* alt0 */ - brcm,pull = <0 2 2 2 2 2>; - }; - -@@ -46,9 +45,9 @@ - }; - }; - --&mmc { -+&sdhost { - pinctrl-names = "default"; -- pinctrl-0 = <&mmc_pins>; -+ pinctrl-0 = <&sdhost_pins>; - non-removable; - bus-width = <4>; - status = "okay"; - -From e729cf9692cd384eb83f1291714965624604b8c0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 12 Oct 2016 15:10:14 +0100 -Subject: [PATCH 123/208] mmc: info (not err) msg on clock probe deferral - ---- - drivers/mmc/host/bcm2835-mmc.c | 5 ++++- - drivers/mmc/host/bcm2835-sdhost.c | 5 ++++- - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index ceb37930e167f47c9c848e8de757ad098eec9a19..4fe8d1fe44578fbefcd48f8c327ba3d03f3d0a2a 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -1459,8 +1459,11 @@ static int bcm2835_mmc_probe(struct platform_device *pdev) - #endif - clk = devm_clk_get(dev, NULL); - if (IS_ERR(clk)) { -- dev_err(dev, "could not get clk\n"); - ret = PTR_ERR(clk); -+ if (ret == -EPROBE_DEFER) -+ dev_info(dev, "could not get clk, deferring probe\n"); -+ else -+ dev_err(dev, "could not get clk\n"); - goto err; - } - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 23dea422182534e248435aeaee3ecb5da69c0d33..9e55d5ac08b5809c40fe391ae6e685fdb4d62df7 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -2089,8 +2089,11 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - - clk = devm_clk_get(dev, NULL); - if (IS_ERR(clk)) { -- dev_err(dev, "could not get clk\n"); - ret = PTR_ERR(clk); -+ if (ret == -EPROBE_DEFER) -+ dev_info(dev, "could not get clk, deferring probe\n"); -+ else -+ dev_err(dev, "could not get clk\n"); - goto err; - } - - -From 72b5f15453aca3a241e4fdc0751187f51d8d3f8e Mon Sep 17 00:00:00 2001 -From: Electron752 -Date: Sat, 15 Oct 2016 11:49:52 -0700 -Subject: [PATCH 124/208] ARM64: Modify default config to get raspbian to boot - (#1686) - -1. Enable emulation of deprecated instructions. -2. Enable ARM 8.1 and 8.2 features which are not detected at runtime. -3. Switch the default governer to powersave. -4. Include the watchdog timer driver in the kernel image rather then a module. - -Tested with raspbian-jessie 2016-09-23. ---- - arch/arm64/configs/bcmrpi3_defconfig | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -index 1fcde8c1329bbfd329245a8bb17691999882ccfc..d7406f5a4620151044b8f716b4d10bb818648e06 100644 ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -27,19 +27,23 @@ CONFIG_ARM64_VA_BITS=39 - CONFIG_SCHED_MC=y - CONFIG_NR_CPUS=4 - CONFIG_HOTPLUG_CPU=y -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y - - # - # ARMv8.1 architectural features - # --CONFIG_ARM64_HW_AFDBM=n --CONFIG_ARM64_PAN=n --CONFIG_ARM64_LSE_ATOMICS=n --CONFIG_ARM64_VHE=n -+CONFIG_ARM64_HW_AFDBM=y -+CONFIG_ARM64_PAN=y -+CONFIG_ARM64_LSE_ATOMICS=y -+CONFIG_ARM64_VHE=y - - # - # ARMv8.2 architectural features - # --CONFIG_ARM64_UAO=n -+CONFIG_ARM64_UAO=y - CONFIG_ARM64_MODULE_CMODEL_LARGE=n - CONFIG_RANDOMIZE_BASE=n - -@@ -98,7 +102,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_CPU_FREQ=y --CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y -@@ -687,7 +691,7 @@ CONFIG_SENSORS_SHTC1=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y --CONFIG_BCM2835_WDT=m -+CONFIG_BCM2835_WDT=y - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y - -From 058069f821d2a205b7e0d8b9741aee5a19e71814 Mon Sep 17 00:00:00 2001 -From: gtrainavicius -Date: Sun, 23 Oct 2016 12:06:53 +0300 -Subject: [PATCH 125/208] Support for Blokas Labs pisound board - ---- - .../devicetree/bindings/vendor-prefixes.txt | 1 + - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 + - arch/arm/boot/dts/overlays/pisound-overlay.dts | 114 +++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - sound/soc/bcm/Kconfig | 6 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/pisound.c | 987 +++++++++++++++++++++ - 9 files changed, 1119 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/pisound-overlay.dts - create mode 100644 sound/soc/bcm/pisound.c - -diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt -index 1992aa97d45ac8b0a9cfaefbaf5de40780c601ad..562cc57b75227e9dba77af035d26926b0ce8894e 100644 ---- a/Documentation/devicetree/bindings/vendor-prefixes.txt -+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt -@@ -39,6 +39,7 @@ auo AU Optronics Corporation - avago Avago Technologies - avic Shanghai AVIC Optoelectronics Co., Ltd. - axis Axis Communications AB -+blokaslabs Vilniaus Blokas UAB - boe BOE Technology Group Co., Ltd. - bosch Bosch Sensortec GmbH - boundary Boundary Devices Inc. -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 6179b21af2fa8ec63429c3d379fc46085681dc7e..555bb5050aaf8464e209f35c50dc1f5c0295e585 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -61,6 +61,7 @@ dtbo-$(RPI_DT_OVERLAYS) += pi3-disable-bt.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pi3-miniuart-bt.dtbo - dtbo-$(RPI_DT_OVERLAYS) += piscreen.dtbo - dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += pisound.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo - dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 2252ab9f5bab5dd40be9ebefa8e37c5bfb07d00f..4f9f0ac43f4fe2cb9376fff5a214ffdaf8179591 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -802,6 +802,12 @@ Params: speed Display SPI bus speed - xohms Touchpanel sensitivity (X-plate resistance) - - -+Name: pisound -+Info: Configures the Blokas Labs pisound card -+Load: dtoverlay=pisound -+Params: -+ -+ - Name: pitft22 - Info: Adafruit PiTFT 2.2" screen - Load: dtoverlay=pitft22,= -diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae26019055 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts -@@ -0,0 +1,114 @@ -+/* -+ * pisound Linux kernel module. -+ * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound -+ * -+ * 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; version 2 of the -+ * License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+#include -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "blokaslabs,pisound"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ -+ pinctrl-0 = <&pisound_button_pins>; -+ -+ osr-gpios = -+ <&gpio 13 GPIO_ACTIVE_HIGH>, -+ <&gpio 26 GPIO_ACTIVE_HIGH>, -+ <&gpio 16 GPIO_ACTIVE_HIGH>; -+ -+ reset-gpios = -+ <&gpio 12 GPIO_ACTIVE_HIGH>, -+ <&gpio 24 GPIO_ACTIVE_HIGH>; -+ -+ data_available-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; -+ -+ button-gpios = <&gpio 17 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pisound_button_pins>; -+ -+ pisound_button_pins: pisound_button_pins { -+ brcm,pins = <17>; -+ brcm,function = <0>; // Input -+ brcm,pull = <2>; // Pull-Up -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2s>; -+ __overlay__ { + status = "okay"; + }; + }; + + fragment@3 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@5 { + target = <&spi0>; + __overlay__ { + #address-cells = <1>; @@ -140954,36 +116644,90 @@ index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae + }; + }; + }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index aa57989600923198d4bfb913c4d2e8a565a93e07..40841d8421e44f8863cb23c53802388b502e61a3 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -875,6 +875,7 @@ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 26fa6c2b6b6d745178e666465ba226afee701ab1..46b91678fef473334b9417409fd1c529c0415977 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -866,6 +866,7 @@ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m ++ ++ fragment@4 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@5 { + target = <&sound>; + __overlay__ { + compatible = "blokaslabs,pisound"; +@@ -49,7 +97,7 @@ + }; + }; + +- fragment@1 { ++ fragment@6 { + target = <&gpio>; + __overlay__ { + pinctrl-names = "default"; +@@ -63,52 +111,10 @@ + }; + }; + +- fragment@2 { ++ fragment@7 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; +- +- fragment@3 { +- target-path = "/"; +- __overlay__ { +- pcm5102a-codec { +- #sound-dai-cells = <0>; +- compatible = "ti,pcm5102a"; +- status = "okay"; +- }; +- }; +- }; +- +- fragment@4 { +- target = <&spi0>; +- __overlay__ { +- status = "okay"; +- +- spidev@0{ +- status = "disabled"; +- }; +- +- spidev@1{ +- status = "okay"; +- }; +- }; +- }; +- +- fragment@5 { +- target = <&spi0>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- +- pisound_spi: pisound_spi@0{ +- compatible = "blokaslabs,pisound-spi"; +- reg = <0>; +- pinctrl-names = "default"; +- pinctrl-0 = <&spi0_pins>; +- spi-max-frequency = <1000000>; +- }; +- }; +- }; + }; diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 4ccaba67a887432afe7f527569c4e2865925734b..aed7b47d8736ea3fb1810b0c77916855082f3b2d 100644 +index 4f0330a6c06115f077938cba3dc744d4ae10f056..a0ef6a028136beb27ed13a4136712a70a60f2966 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -130,3 +130,9 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC +@@ -123,3 +123,9 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC select SND_SOC_PCM512x_I2C help Say Y or M if you want to add support for Allo Piano DAC. @@ -140994,10 +116738,10 @@ index 4ccaba67a887432afe7f527569c4e2865925734b..aed7b47d8736ea3fb1810b0c77916855 + help + Say Y or M if you want to add support for Blokas Labs pisound. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index b9f98f0bcf3ee0d6b490e1bb185ba0de8f0f9701..5fb380a2f8a87ed5e67786f5afb31682128b70ed 100644 +index 4b94a42efecaee41df37f3c59fddefa5fe78521c..f720a3d3b5832844ee6d0558317c728f00c40b65 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -25,6 +25,7 @@ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o +@@ -24,6 +24,7 @@ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o snd-soc-dionaudio-loco-objs := dionaudio_loco.o snd-soc-allo-piano-dac-objs := allo-piano-dac.o @@ -141005,17 +116749,17 @@ index b9f98f0bcf3ee0d6b490e1bb185ba0de8f0f9701..5fb380a2f8a87ed5e67786f5afb31682 obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -42,3 +43,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundca +@@ -40,3 +41,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundca obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o +obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o diff --git a/sound/soc/bcm/pisound.c b/sound/soc/bcm/pisound.c new file mode 100644 -index 0000000000000000000000000000000000000000..b156e5793e4c482385dedafd85bbf190acc8162b +index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb2310b3b94d0 --- /dev/null +++ b/sound/soc/bcm/pisound.c -@@ -0,0 +1,987 @@ +@@ -0,0 +1,989 @@ +/* + * pisound Linux kernel module. + * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound @@ -141972,6 +117716,8 @@ index 0000000000000000000000000000000000000000..b156e5793e4c482385dedafd85bbf190 + +static int pisnd_remove(struct platform_device *pdev) +{ ++ printi("Unloading.\n"); ++ + if (pisnd_kobj) { + kobject_put(pisnd_kobj); + pisnd_kobj = NULL; @@ -142004,4374 +117750,339 @@ index 0000000000000000000000000000000000000000..b156e5793e4c482385dedafd85bbf190 +MODULE_DESCRIPTION("ASoC Driver for pisound, http://blokas.io/pisound"); +MODULE_LICENSE("GPL v2"); -From 5c4d2949f96142001b815fb44e7a6aedec2d83c2 Mon Sep 17 00:00:00 2001 -From: Giedrius Trainavicius -Date: Tue, 25 Oct 2016 01:47:20 +0300 -Subject: [PATCH 126/208] FIXUP: pisound: Fix a warning in DEBUG builds +From 98377297665ab6bf02efbf28cc1f1d0821d840c9 Mon Sep 17 00:00:00 2001 +From: P33M +Date: Wed, 21 Oct 2015 14:55:21 +0100 +Subject: [PATCH 085/111] rpi_display: add backlight driver and overlay -Also change a macro that enables debug level printing from DEBUG to -PISOUND_DEBUG. +Add a mailbox-driven backlight controller for the Raspberry Pi DSI +touchscreen display. Requires updated GPU firmware to recognise the +mailbox request. + +Signed-off-by: Gordon Hollingworth --- - sound/soc/bcm/pisound.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) + drivers/video/backlight/Kconfig | 6 ++ + drivers/video/backlight/Makefile | 1 + + drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ + 3 files changed, 126 insertions(+) + create mode 100644 drivers/video/backlight/rpi_backlight.c -diff --git a/sound/soc/bcm/pisound.c b/sound/soc/bcm/pisound.c -index b156e5793e4c482385dedafd85bbf190acc8162b..a3cd089a01447bdb6741ed6bba3b21d40061d7df 100644 ---- a/sound/soc/bcm/pisound.c -+++ b/sound/soc/bcm/pisound.c -@@ -55,7 +55,7 @@ static void pisnd_midi_uninit(void); - - #define PISOUND_LOG_PREFIX "pisound: " - --#ifdef DEBUG -+#ifdef PISOUND_DEBUG - # define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__) - #else - # define printd(...) do {} while (0) -@@ -119,7 +119,7 @@ static void pisnd_midi_recv_callback(void *substream) - while ((n = pisnd_spi_recv(data, sizeof(data)))) { - int res = snd_rawmidi_receive(substream, data, n); - (void)res; -- printd("midi recv 0x%02x, res = %d\n", data, res); -+ printd("midi recv %u bytes, res = %d\n", n, res); - } - } - - -From b50c2a9e07bcdf93ca4110cdba3792a9bfb93167 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:25:41 +0200 -Subject: [PATCH 127/208] bcm270x: Remove bcm2708_reboot_mode parameter -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This isn't used anymore now that the watchdog driver does restart/poweroff. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/kernel/process.c | 10 ---------- - 1 file changed, 10 deletions(-) - -diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 0a0332cb13a7475ee0c4d75a97685b7de6475c95..612eb530f33fcd19bc4539facb26fc30a2583979 100644 ---- a/arch/arm/kernel/process.c -+++ b/arch/arm/kernel/process.c -@@ -91,16 +91,6 @@ void arch_cpu_idle_exit(void) - ledtrig_cpu(CPU_LED_IDLE_END); - } - --char bcm2708_reboot_mode = 'h'; -- --int __init reboot_setup(char *str) --{ -- bcm2708_reboot_mode = str[0]; -- return 1; --} -- --__setup("reboot=", reboot_setup); -- - void __show_regs(struct pt_regs *regs) - { - unsigned long flags; - -From 7c233a345d15064604d3194b35b0aa56ea2f9b02 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 15:54:41 +0200 -Subject: [PATCH 128/208] bcm270x: Remove NEED_MACH_IO_H -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -NEED_MACH_IO_H isn't necessary since we don't have -PC card/PCI/ISA IO space. -The __io macro is only used in the {in,out}[bwl] macros. - -arch/arm/include/asm/io.h will give these defaults now: - -define __io(a) __typesafe_io((a) & IO_SPACE_LIMIT) -define IO_SPACE_LIMIT ((resource_size_t)0) - -This is the same as ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 1 - - arch/arm/mach-bcm2708/Kconfig | 1 - - arch/arm/mach-bcm2708/include/mach/io.h | 27 --------------------------- - arch/arm/mach-bcm2709/include/mach/io.h | 27 --------------------------- - 4 files changed, 56 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/io.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/io.h - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 018ee76322d9e013598887c50ebea9628ecb9ee3..962d632c2af85c752b848c3ba7a8f3f3ba32c222 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -355,7 +355,6 @@ config ARCH_BCM2709 - select MIGHT_HAVE_CACHE_L2X0 - select HAVE_SCHED_CLOCK - select NEED_MACH_MEMORY_H -- select NEED_MACH_IO_H - select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 6eabe844767f7fa9bdc09a897bab83e5149fc0dd..e93df839ab8c6cddb8d784d0af3b827276ba9120 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -4,7 +4,6 @@ menu "Broadcom BCM2708 Implementations" - config MACH_BCM2708 - bool "Broadcom BCM2708 Development Platform" - select NEED_MACH_MEMORY_H -- select NEED_MACH_IO_H - select CPU_V6 - select USE_OF - select ARCH_REQUIRE_GPIOLIB -diff --git a/arch/arm/mach-bcm2708/include/mach/io.h b/arch/arm/mach-bcm2708/include/mach/io.h -deleted file mode 100644 -index e6eb84d71006db417dbd0afc4d08d3b19b09a619..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/io.h -+++ /dev/null -@@ -1,27 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/io.h -- * -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARM_ARCH_IO_H --#define __ASM_ARM_ARCH_IO_H -- --#define IO_SPACE_LIMIT 0xffffffff -- --#define __io(a) __typesafe_io(a) -- --#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/io.h b/arch/arm/mach-bcm2709/include/mach/io.h -deleted file mode 100644 -index e6eb84d71006db417dbd0afc4d08d3b19b09a619..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/io.h -+++ /dev/null -@@ -1,27 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/io.h -- * -- * Copyright (C) 2003 ARM Limited -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARM_ARCH_IO_H --#define __ASM_ARM_ARCH_IO_H -- --#define IO_SPACE_LIMIT 0xffffffff -- --#define __io(a) __typesafe_io(a) -- --#endif - -From f30338340fc8707bd44a054991d9bba94297ac80 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:01:01 +0200 -Subject: [PATCH 129/208] dwc_otg: Pass struct device to dma_alloc*() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This makes it possible to get the bus address from Device Tree. - -Signed-off-by: Noralf Trønnes ---- - .../usb/host/dwc_common_port/dwc_common_linux.c | 19 +---- - drivers/usb/host/dwc_common_port/dwc_os.h | 18 ++--- - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 13 ++-- - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 6 ++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 23 ++++-- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 +- - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 3 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 87 +++++++++++++--------- - drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 7 ++ - drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 3 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 3 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 2 +- - 12 files changed, 105 insertions(+), 81 deletions(-) - -diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -index 46646841dda96fb2bed01152de552ccac5f0e5e4..0d641e6da24beeb07109e23847d1d6e81dc7d4ea 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c -+++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -@@ -337,27 +337,12 @@ void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) - - void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) - { --#ifdef xxCOSIM /* Only works for 32-bit cosim */ -- void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); --#else -- void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); --#endif -- if (!buf) { -- return NULL; -- } -- -- memset(buf, 0, (size_t)size); -- return buf; -+ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_KERNEL | GFP_DMA32); - } - - void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) - { -- void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); -- if (!buf) { -- return NULL; -- } -- memset(buf, 0, (size_t)size); -- return buf; -+ return dma_zalloc_coherent(dma_ctx, size, dma_addr, GFP_ATOMIC); - } - - void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) -diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h -index a2bbe232ffc3b58001d026864c3019792cdf5efa..9a86d299403bd1dfdcdb6532fad702b2b65138d7 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_os.h -+++ b/drivers/usb/host/dwc_common_port/dwc_os.h -@@ -675,9 +675,9 @@ extern void __DWC_FREE(void *mem_ctx, void *addr); - #define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) - - # ifdef DWC_LINUX --#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) --#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) --#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) -+#define DWC_DMA_ALLOC(_dev, _size_, _dma_) __DWC_DMA_ALLOC(_dev, _size_, _dma_) -+#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) __DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) -+#define DWC_DMA_FREE(_dev, _size_,_virt_, _dma_) __DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) - # endif - - # if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -@@ -708,12 +708,12 @@ extern void dwc_memory_debug_report(void); - #define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) - - # ifdef DWC_LINUX --#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ -- _dma_, __func__, __LINE__) --#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ -- _dma_, __func__, __LINE__) --#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ -- _virt_, _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC(_dev, _size_, _dma_) \ -+ dwc_dma_alloc_debug(_dev, _size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) \ -+ dwc_dma_alloc_atomic_debug(_dev, _size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) \ -+ dwc_dma_free_debug(_dev, _size_, _virt_, _dma_, __func__, __LINE__) - # endif - - # if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -index 135b611abe08e141c937612ab7baada6b13113fc..027414bb2bf9fc3f3652407724187f3c6dc5ff68 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -884,6 +884,7 @@ void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num) - */ - static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) - { -+ struct device *dev = dwc_otg_hcd_to_dev(dwc_otg_hcd); - int i; - - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); -@@ -916,7 +917,7 @@ static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) - - if (dwc_otg_hcd->core_if->dma_enable) { - if (dwc_otg_hcd->status_buf_dma) { -- DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ DWC_DMA_FREE(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, - dwc_otg_hcd->status_buf, - dwc_otg_hcd->status_buf_dma); - } -@@ -946,6 +947,7 @@ int init_hcd_usecs(dwc_otg_hcd_t *_hcd); - - int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - int retval = 0; - int num_channels; - int i; -@@ -1041,7 +1043,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - * for use as transaction bounce buffers in a 2-D array. Our access into this chunk is done by some - * moderately readable array casts. - */ -- hcd->fiq_dmab = DWC_DMA_ALLOC((sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); -+ hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); - DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d", - (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base, - sizeof(struct fiq_dma_channel) * num_channels); -@@ -1092,7 +1094,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - */ - if (hcd->core_if->dma_enable) { - hcd->status_buf = -- DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ DWC_DMA_ALLOC(dev, DWC_OTG_HCD_STATUS_BUF_SIZE, - &hcd->status_buf_dma); - } else { - hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); -@@ -1187,6 +1189,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - uint32_t intr_enable; - unsigned long flags; - gintmsk_data_t gintmsk = { .d32 = 0, }; -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - - qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); - -@@ -1381,7 +1384,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - buf_size = 4096; - } - if (!qh->dw_align_buf) { -- qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, -+ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(dev, buf_size, - &qh->dw_align_buf_dma); - if (!qh->dw_align_buf) { - DWC_ERROR -@@ -1432,7 +1435,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); - } -- -+ - local_irq_restore(flags); - hc->qh = qh; - } -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -index 43dbed9fddbf5491bab33cc6e551b99ca8dce7dc..4539cd7b802d3e49ac9a6cb3f1d88b475a1ace16 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -41,6 +41,7 @@ - #include "dwc_list.h" - #include "dwc_otg_cil.h" - #include "dwc_otg_fiq_fsm.h" -+#include "dwc_otg_driver.h" - - - /** -@@ -613,6 +614,11 @@ struct dwc_otg_hcd { - #endif - }; - -+static inline struct device *dwc_otg_hcd_to_dev(struct dwc_otg_hcd *hcd) -+{ -+ return &hcd->otg_dev->os_dep.platformdev->dev; -+} -+ - /** @name Transaction Execution Functions */ - /** @{ */ - extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -index ee920c4d8f4a2980e4406cb878b81d809fec4e70..126e99ab2fc43f11d89a08ff0476181ead84029f 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -75,12 +75,12 @@ static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) - : qh->interval); - } - --static int desc_list_alloc(dwc_otg_qh_t * qh) -+static int desc_list_alloc(struct device *dev, dwc_otg_qh_t * qh) - { - int retval = 0; - - qh->desc_list = (dwc_otg_host_dma_desc_t *) -- DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), -+ DWC_DMA_ALLOC(dev, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), - &qh->desc_list_dma); - - if (!qh->desc_list) { -@@ -106,10 +106,10 @@ static int desc_list_alloc(dwc_otg_qh_t * qh) - - } - --static void desc_list_free(dwc_otg_qh_t * qh) -+static void desc_list_free(struct device *dev, dwc_otg_qh_t * qh) - { - if (qh->desc_list) { -- DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, -+ DWC_DMA_FREE(dev, max_desc_num(qh), qh->desc_list, - qh->desc_list_dma); - qh->desc_list = NULL; - } -@@ -122,11 +122,13 @@ static void desc_list_free(dwc_otg_qh_t * qh) - - static int frame_list_alloc(dwc_otg_hcd_t * hcd) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - int retval = 0; -+ - if (hcd->frame_list) - return 0; - -- hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, -+ hcd->frame_list = DWC_DMA_ALLOC(dev, 4 * MAX_FRLIST_EN_NUM, - &hcd->frame_list_dma); - if (!hcd->frame_list) { - retval = -DWC_E_NO_MEMORY; -@@ -140,10 +142,12 @@ static int frame_list_alloc(dwc_otg_hcd_t * hcd) - - static void frame_list_free(dwc_otg_hcd_t * hcd) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); -+ - if (!hcd->frame_list) - return; - -- DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); -+ DWC_DMA_FREE(dev, 4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); - hcd->frame_list = NULL; - } - -@@ -321,6 +325,7 @@ static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - int retval = 0; - - if (qh->do_split) { -@@ -328,7 +333,7 @@ int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - return -1; - } - -- retval = desc_list_alloc(qh); -+ retval = desc_list_alloc(dev, qh); - - if ((retval == 0) - && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { -@@ -355,7 +360,9 @@ int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -- desc_list_free(qh); -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); -+ -+ desc_list_free(dev, qh); - - /* - * Channel still assigned due to some reasons. -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 2ceed4212980f04ad082e78851c6a7e83aee1443..74cd5fa54aed5241b61371477ef67d706477fd30 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -517,6 +517,7 @@ int hcd_init(dwc_bus_dev_t *_dev) - ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = - dwc_otg_hcd; - otg_dev->hcd = dwc_otg_hcd; -+ otg_dev->hcd->otg_dev = otg_dev; - - if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { - goto error2; -@@ -531,7 +532,6 @@ int hcd_init(dwc_bus_dev_t *_dev) - } - } - -- otg_dev->hcd->otg_dev = otg_dev; - hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -index 3b2a60763b92fb2e9261a8ade3d4b33e3896cd62..c2dff94e8e6edd22e4427aaa1eac7aad972cb6bd 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -59,6 +59,7 @@ void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - uint32_t buf_size = 0; - uint8_t *align_buf_virt = NULL; - dwc_dma_t align_buf_dma; -+ struct device *dev = dwc_otg_hcd_to_dev(hcd); - - /* Free each QTD in the QTD list */ - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -@@ -82,7 +83,7 @@ void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - DWC_FREE(qh); - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - if (align_buf_virt) -- DWC_DMA_FREE(buf_size, align_buf_virt, align_buf_dma); -+ DWC_DMA_FREE(dev, buf_size, align_buf_virt, align_buf_dma); - return; - } - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -index ae0c72d02d007d5e7ce0f2dfb79b35d3d7ef86b8..9dabbe5c9791c5296d1cc7b663afa6ec462173cb 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -@@ -237,20 +237,22 @@ static dwc_otg_cil_callbacks_t pcd_callbacks = { - * This function allocates a DMA Descriptor chain for the Endpoint - * buffer to be used for a transfer to/from the specified endpoint. - */ --dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, -+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(struct device *dev, -+ dwc_dma_t * dma_desc_addr, - uint32_t count) - { -- return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), -+ return DWC_DMA_ALLOC_ATOMIC(dev, count * sizeof(dwc_otg_dev_dma_desc_t), - dma_desc_addr); - } - - /** - * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. - */ --void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, -+void dwc_otg_ep_free_desc_chain(struct device *dev, -+ dwc_otg_dev_dma_desc_t * desc_addr, - uint32_t dma_desc_addr, uint32_t count) - { -- DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, -+ DWC_DMA_FREE(dev, count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, - dma_desc_addr); - } - -@@ -1105,8 +1107,10 @@ static void start_xfer_tasklet_func(void *data) - * This function initialized the PCD portion of the driver. - * - */ --dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) -+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev) - { -+ struct device *dev = &otg_dev->os_dep.platformdev->dev; -+ dwc_otg_core_if_t *core_if = otg_dev->core_if; - dwc_otg_pcd_t *pcd = NULL; - dwc_otg_dev_if_t *dev_if; - int i; -@@ -1163,7 +1167,7 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - */ - if (GET_CORE_IF(pcd)->dma_enable) { - pcd->setup_pkt = -- DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_ALLOC(dev, sizeof(*pcd->setup_pkt) * 5, - &pcd->setup_pkt_dma_handle); - if (pcd->setup_pkt == NULL) { - DWC_FREE(pcd); -@@ -1171,10 +1175,10 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - } - - pcd->status_buf = -- DWC_DMA_ALLOC(sizeof(uint16_t), -+ DWC_DMA_ALLOC(dev, sizeof(uint16_t), - &pcd->status_buf_dma_handle); - if (pcd->status_buf == NULL) { -- DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, - pcd->setup_pkt, pcd->setup_pkt_dma_handle); - DWC_FREE(pcd); - return NULL; -@@ -1182,17 +1186,17 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - - if (GET_CORE_IF(pcd)->dma_desc_enable) { - dev_if->setup_desc_addr[0] = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_setup_desc_addr[0], 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_setup_desc_addr[0], 1); - dev_if->setup_desc_addr[1] = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_setup_desc_addr[1], 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_setup_desc_addr[1], 1); - dev_if->in_desc_addr = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_in_desc_addr, 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_in_desc_addr, 1); - dev_if->out_desc_addr = -- dwc_otg_ep_alloc_desc_chain -- (&dev_if->dma_out_desc_addr, 1); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &dev_if->dma_out_desc_addr, 1); - pcd->data_terminated = 0; - - if (dev_if->setup_desc_addr[0] == 0 -@@ -1201,26 +1205,26 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - || dev_if->out_desc_addr == 0) { - - if (dev_if->out_desc_addr) -- dwc_otg_ep_free_desc_chain -- (dev_if->out_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->out_desc_addr, - dev_if->dma_out_desc_addr, 1); - if (dev_if->in_desc_addr) -- dwc_otg_ep_free_desc_chain -- (dev_if->in_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->in_desc_addr, - dev_if->dma_in_desc_addr, 1); - if (dev_if->setup_desc_addr[1]) -- dwc_otg_ep_free_desc_chain -- (dev_if->setup_desc_addr[1], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[1], - dev_if->dma_setup_desc_addr[1], 1); - if (dev_if->setup_desc_addr[0]) -- dwc_otg_ep_free_desc_chain -- (dev_if->setup_desc_addr[0], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[0], - dev_if->dma_setup_desc_addr[0], 1); - -- DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, - pcd->setup_pkt, - pcd->setup_pkt_dma_handle); -- DWC_DMA_FREE(sizeof(*pcd->status_buf), -+ DWC_DMA_FREE(dev, sizeof(*pcd->status_buf), - pcd->status_buf, - pcd->status_buf_dma_handle); - -@@ -1302,7 +1306,9 @@ fail: - void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) - { - dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - int i; -+ - if (pcd->core_if->core_params->dev_out_nak) { - for (i = 0; i < MAX_EPS_CHANNELS; i++) { - DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); -@@ -1311,20 +1317,24 @@ void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) - } - - if (GET_CORE_IF(pcd)->dma_enable) { -- DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, -+ DWC_DMA_FREE(dev, sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, - pcd->setup_pkt_dma_handle); -- DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, -+ DWC_DMA_FREE(dev, sizeof(uint16_t), pcd->status_buf, - pcd->status_buf_dma_handle); - if (GET_CORE_IF(pcd)->dma_desc_enable) { -- dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[0], - dev_if->dma_setup_desc_addr - [0], 1); -- dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->setup_desc_addr[1], - dev_if->dma_setup_desc_addr - [1], 1); -- dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->in_desc_addr, - dev_if->dma_in_desc_addr, 1); -- dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, -+ dev_if->out_desc_addr, - dev_if->dma_out_desc_addr, - 1); - } -@@ -1463,6 +1473,7 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; - int retval = 0; - int i, epcount; -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - - desc = (const usb_endpoint_descriptor_t *)ep_desc; - -@@ -1571,9 +1582,9 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - if (ep->dwc_ep.type != UE_ISOCHRONOUS) { - #endif - ep->dwc_ep.desc_addr = -- dwc_otg_ep_alloc_desc_chain(&ep-> -- dwc_ep.dma_desc_addr, -- MAX_DMA_DESC_CNT); -+ dwc_otg_ep_alloc_desc_chain(dev, -+ &ep->dwc_ep.dma_desc_addr, -+ MAX_DMA_DESC_CNT); - if (!ep->dwc_ep.desc_addr) { - DWC_WARN("%s, can't allocate DMA descriptor\n", - __func__); -@@ -1624,6 +1635,7 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; - gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; - fifosize_data_t dptxfsiz = {.d32 = 0 }; -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - - ep = get_ep_from_handle(pcd, ep_handle); - -@@ -1678,7 +1690,7 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - - /* Cannot call dma_free_coherent() with IRQs disabled */ - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -- dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, -+ dwc_otg_ep_free_desc_chain(dev, desc_addr, dma_desc_addr, - MAX_DMA_DESC_CNT); - - goto out_unlocked; -@@ -2079,6 +2091,7 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, - int zero, void *req_handle, int atomic_alloc) - { -+ struct device *dev = dwc_otg_pcd_to_dev(pcd); - dwc_irqflags_t flags; - dwc_otg_pcd_request_t *req; - dwc_otg_pcd_ep_t *ep; -@@ -2115,7 +2128,7 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - req->dw_align_buf = NULL; - if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable - && !GET_CORE_IF(pcd)->dma_desc_enable) -- req->dw_align_buf = DWC_DMA_ALLOC(buflen, -+ req->dw_align_buf = DWC_DMA_ALLOC(dev, buflen, - &req->dw_align_buf_dma); - DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -index 8ef7ba648ad92b9b7e141f22db2a0c2837ddcfa8..a70ebd049d2cca3bf988a1f809832eebede14f96 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -@@ -38,6 +38,8 @@ - #include "usb.h" - #include "dwc_otg_cil.h" - #include "dwc_otg_pcd_if.h" -+#include "dwc_otg_driver.h" -+ - struct cfiobject; - - /** -@@ -253,6 +255,11 @@ struct dwc_otg_pcd { - - }; - -+static inline struct device *dwc_otg_pcd_to_dev(struct dwc_otg_pcd *pcd) -+{ -+ return &pcd->otg_dev->os_dep.platformdev->dev; -+} -+ - //FIXME this functions should be static, and this prototypes should be removed - extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); - extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -index c8d2e0e0c99486558a4964a8c82de80c64b496b4..4c1d591fbc098b2f4a745669e4f243e068735b20 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -@@ -37,6 +37,7 @@ - - //#include "dwc_os.h" - #include "dwc_otg_core_if.h" -+#include "dwc_otg_driver.h" - - /** @file - * This file defines DWC_OTG PCD Core API. -@@ -139,7 +140,7 @@ struct dwc_otg_pcd_function_ops { - * - * @param core_if The DWC_OTG Core - */ --extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); -+extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev); - - /** Frees PCD allocated by dwc_otg_pcd_init - * -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -index c8590b527110753b8064d35fab4c34226d094f84..e55ea9c74be46167a41dc14a2d88a1228878b1bb 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -@@ -2144,6 +2144,7 @@ static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep) - static void complete_ep(dwc_otg_pcd_ep_t * ep) - { - dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); -+ struct device *dev = dwc_otg_pcd_to_dev(ep->pcd); - dwc_otg_dev_if_t *dev_if = core_if->dev_if; - dwc_otg_dev_in_ep_regs_t *in_ep_regs = - dev_if->in_ep_regs[ep->dwc_ep.num]; -@@ -2484,7 +2485,7 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - if (!ep->dwc_ep.is_in) { - dwc_memcpy(req->buf, req->dw_align_buf, req->length); - } -- DWC_DMA_FREE(req->length, req->dw_align_buf, -+ DWC_DMA_FREE(dev, req->length, req->dw_align_buf, - req->dw_align_buf_dma); - } - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -index 5624f32c9ea9117599df451af29fca2e3bca36de..50aaeacdd12fff93d7a9cf1c54612367406c6bee 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -1206,7 +1206,7 @@ int pcd_init(dwc_bus_dev_t *_dev) - - DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); - -- otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); -+ otg_dev->pcd = dwc_otg_pcd_init(otg_dev); - - if (!otg_dev->pcd) { - DWC_ERROR("dwc_otg_pcd_init failed\n"); - -From 27dc18be13e874cdbe167edb6c2929ab4d2c2e1a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:05:36 +0200 -Subject: [PATCH 130/208] mmc: bcm2835-sdhost: Pass struct device to - dma_alloc*() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This makes it possible to get the bus address from Device Tree. -At the same time move the call to log_init() after getting the clock -to avoid allocating twice due to deferred probing. - -Signed-off-by: Noralf Trønnes ---- - drivers/mmc/host/bcm2835-sdhost.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 9e55d5ac08b5809c40fe391ae6e685fdb4d62df7..a9bc79bfdbb71807819dfe2d8f1651445997f92a 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -235,10 +235,10 @@ static void __iomem *timer_base; - #define LOG_ENTRIES (256*1) - #define LOG_SIZE (sizeof(LOG_ENTRY_T)*LOG_ENTRIES) - --static void log_init(u32 bus_to_phys) -+static void log_init(struct device *dev, u32 bus_to_phys) - { - spin_lock_init(&log_lock); -- sdhost_log_buf = dma_zalloc_coherent(NULL, LOG_SIZE, &sdhost_log_addr, -+ sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr, - GFP_KERNEL); - if (sdhost_log_buf) { - pr_info("sdhost: log_buf @ %p (%x)\n", -@@ -2037,7 +2037,6 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - return -ENODEV; - } - host->bus_addr = be32_to_cpup(addr); -- log_init(iomem->start - host->bus_addr); - pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n", - (unsigned long)host->ioaddr, - (unsigned long)iomem->start, -@@ -2110,6 +2109,8 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - (unsigned long)host->max_clk, - (int)host->irq); - -+ log_init(dev, iomem->start - host->bus_addr); -+ - if (node) - mmc_of_parse(mmc); - else - -From 22d03d1b65d08b5ed7bea59d49f1a455a3636cd9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 19 Oct 2016 16:16:48 +0200 -Subject: [PATCH 131/208] bcm270x: Drop NEED_MACH_MEMORY_H and use DT - dma-ranges -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Drop NEED_MACH_MEMORY_H and use dma-ranges from the Device Tree to -get the bus address, like ARCH_BCM2835 does. - -This means that we go from this: - -arch/arm/mach-bcm270x/include/mach/memory.h: - -define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) -define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) -define __pfn_to_bus(x) (__pfn_to_phys(x) + BUS_OFFSET) -define __bus_to_pfn(x) __phys_to_pfn((x) - BUS_OFFSET - -To this: - -arch/arm/include/asm/memory.h: - -define __virt_to_bus __virt_to_phys -define __bus_to_virt __phys_to_virt -define __pfn_to_bus(x) __pfn_to_phys(x) -define __bus_to_pfn(x) __phys_to_pfn(x) - -Drivers now have to use the DMA API to get to the bus address. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 2 - - arch/arm/boot/dts/bcm2708.dtsi | 3 -- - arch/arm/boot/dts/bcm2709.dtsi | 1 - - arch/arm/mach-bcm2708/Kconfig | 8 ---- - arch/arm/mach-bcm2708/include/mach/memory.h | 57 ----------------------------- - arch/arm/mach-bcm2709/Kconfig | 7 ---- - arch/arm/mach-bcm2709/include/mach/memory.h | 57 ----------------------------- - 7 files changed, 135 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 962d632c2af85c752b848c3ba7a8f3f3ba32c222..82cbd045d7894e1b75460021a862f8b56f5ec645 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -334,7 +334,6 @@ config ARCH_BCM2708 - select CLKSRC_OF if OF - select HAVE_SCHED_CLOCK - select NEED_MACH_GPIO_H -- select NEED_MACH_MEMORY_H - select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS -@@ -354,7 +353,6 @@ config ARCH_BCM2709 - select ARM_AMBA - select MIGHT_HAVE_CACHE_L2X0 - select HAVE_SCHED_CLOCK -- select NEED_MACH_MEMORY_H - select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 1bd2a707ef5c0d92f233296e6312916f5a550bd2..663843965027da5dbaefbec1285e275c56746367 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -7,9 +7,6 @@ - model = "BCM2708"; - - soc { -- ranges = <0x7e000000 0x20000000 0x01000000>; -- /delete-property/ dma-ranges; -- - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; - reg = <0x7e003000 0x1000>; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index 757d0053c1c07452babc63ca6ecd0a8f047b25dd..b1d82f9026d02e8b5371cbb4d8a144e67207a276 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -9,7 +9,6 @@ - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -- /delete-property/ dma-ranges; - - syscon@40000000 { - compatible = "brcm,bcm2836-arm-local", "syscon"; -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index e93df839ab8c6cddb8d784d0af3b827276ba9120..265c3fb90f3debfc439491a89346e4863edec427 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -3,7 +3,6 @@ menu "Broadcom BCM2708 Implementations" - - config MACH_BCM2708 - bool "Broadcom BCM2708 Development Platform" -- select NEED_MACH_MEMORY_H - select CPU_V6 - select USE_OF - select ARCH_REQUIRE_GPIOLIB -@@ -12,11 +11,4 @@ config MACH_BCM2708 - help - Include support for the Broadcom(R) BCM2708 platform. - --config BCM2708_NOL2CACHE -- bool "Videocore L2 cache disable" -- depends on MACH_BCM2708 -- default n -- help -- Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -- - endmenu -diff --git a/arch/arm/mach-bcm2708/include/mach/memory.h b/arch/arm/mach-bcm2708/include/mach/memory.h -deleted file mode 100644 -index 7548a52dcf84affa4d1b0667e5e2f89f591891b8..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/include/mach/memory.h -+++ /dev/null -@@ -1,57 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/memory.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_MEMORY_H --#define __ASM_ARCH_MEMORY_H -- --/* Memory overview: -- -- [ARMcore] <--virtual addr--> -- [ARMmmu] <--physical addr--> -- [GERTmap] <--bus add--> -- [VCperiph] -- --*/ -- --/* -- * Physical DRAM offset. -- */ --#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) --#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -- --#ifdef CONFIG_BCM2708_NOL2CACHE -- #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ --#else -- #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ --#endif -- --/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -- * will provide the offset into this area as well as setting the bits that -- * stop the L1 and L2 cache from being used -- * -- * WARNING: this only works because the ARM is given memory at a fixed location -- * (ARMMEM_OFFSET) -- */ --#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) --#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) --#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) --#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) --#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -- --#endif -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -index 643b4b984512a5f2ae33cee9beffa70a53e005ff..41f407ac1db3a86e87941153c1832b9fce1ead5d 100644 ---- a/arch/arm/mach-bcm2709/Kconfig -+++ b/arch/arm/mach-bcm2709/Kconfig -@@ -6,11 +6,4 @@ config MACH_BCM2709 - help - Include support for the Broadcom(R) BCM2709 platform. - --config BCM2708_NOL2CACHE -- bool "Videocore L2 cache disable" -- depends on MACH_BCM2709 -- default y -- help -- Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -- - endmenu -diff --git a/arch/arm/mach-bcm2709/include/mach/memory.h b/arch/arm/mach-bcm2709/include/mach/memory.h -deleted file mode 100644 -index 7548a52dcf84affa4d1b0667e5e2f89f591891b8..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/include/mach/memory.h -+++ /dev/null -@@ -1,57 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/memory.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef __ASM_ARCH_MEMORY_H --#define __ASM_ARCH_MEMORY_H -- --/* Memory overview: -- -- [ARMcore] <--virtual addr--> -- [ARMmmu] <--physical addr--> -- [GERTmap] <--bus add--> -- [VCperiph] -- --*/ -- --/* -- * Physical DRAM offset. -- */ --#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) --#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ -- --#ifdef CONFIG_BCM2708_NOL2CACHE -- #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ --#else -- #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ --#endif -- --/* We're using the memory at 64M in the VideoCore for Linux - this adjustment -- * will provide the offset into this area as well as setting the bits that -- * stop the L1 and L2 cache from being used -- * -- * WARNING: this only works because the ARM is given memory at a fixed location -- * (ARMMEM_OFFSET) -- */ --#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) --#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) --#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) --#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) --#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) -- --#endif - -From 26802db0c398a49668f6d029b50f59876a6f25f6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 15:55:09 +0200 -Subject: [PATCH 132/208] dts: Remove bcm2835-rpi-cm.dts -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This file doesn't build anymore and isn't used so remove it. -It was added as part of my ARCH_BCM2835 work last year, but the future -didn't pan out as expected. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 - - arch/arm/boot/dts/bcm2835-rpi-cm.dts | 93 ----------------------------------- - arch/arm/boot/dts/bcm2835-rpi-cm.dtsi | 30 ----------- - 3 files changed, 124 deletions(-) - delete mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dts - delete mode 100644 arch/arm/boot/dts/bcm2835-rpi-cm.dtsi - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 71f794ecc710ac533731854bd95961a6a4175b64..0cb86b7a5ab212fee36a34b3672856d27c446593 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -3,7 +3,6 @@ ifeq ($(CONFIG_OF),y) - dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b.dtb - dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b-plus.dtb - dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-cm.dtb --dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-cm.dtb - dtb-$(CONFIG_ARCH_BCM2709) += bcm2709-rpi-2-b.dtb - dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dts b/arch/arm/boot/dts/bcm2835-rpi-cm.dts -deleted file mode 100644 -index c6e6860a6d4356a613f4f7ab41c6befc76740a15..0000000000000000000000000000000000000000 ---- a/arch/arm/boot/dts/bcm2835-rpi-cm.dts -+++ /dev/null -@@ -1,93 +0,0 @@ --/dts-v1/; -- --#include "bcm2835-rpi-cm.dtsi" -- --/ { -- model = "Raspberry Pi Compute Module"; --}; -- --&uart0 { -- status = "okay"; --}; -- --&gpio { -- spi0_pins: spi0_pins { -- brcm,pins = <7 8 9 10 11>; -- brcm,function = <4>; /* alt0 */ -- }; -- -- i2c0_pins: i2c0 { -- brcm,pins = <0 1>; -- brcm,function = <4>; -- }; -- -- i2c1_pins: i2c1 { -- brcm,pins = <2 3>; -- brcm,function = <4>; -- }; -- -- i2s_pins: i2s { -- brcm,pins = <18 19 20 21>; -- brcm,function = <4>; /* alt0 */ -- }; --}; -- --&spi0 { -- pinctrl-names = "default"; -- pinctrl-0 = <&spi0_pins>; -- -- spidev@0{ -- compatible = "spidev"; -- reg = <0>; /* CE0 */ -- #address-cells = <1>; -- #size-cells = <0>; -- spi-max-frequency = <500000>; -- }; -- -- spidev@1{ -- compatible = "spidev"; -- reg = <1>; /* CE1 */ -- #address-cells = <1>; -- #size-cells = <0>; -- spi-max-frequency = <500000>; -- }; --}; -- --&i2c0 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c0_pins>; -- clock-frequency = <100000>; --}; -- --&i2c1 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c1_pins>; -- clock-frequency = <100000>; --}; -- --&i2c2 { -- clock-frequency = <100000>; --}; -- --&i2s { -- #sound-dai-cells = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&i2s_pins>; --}; -- --/ { -- __overrides__ { -- uart0 = <&uart0>,"status"; -- uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; -- uart1_clkrate = <&uart1>,"clock-frequency:0"; -- i2s = <&i2s>,"status"; -- spi = <&spi0>,"status"; -- i2c0 = <&i2c0>,"status"; -- i2c1 = <&i2c1>,"status"; -- i2c2_iknowwhatimdoing = <&i2c2>,"status"; -- i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -- i2c1_baudrate = <&i2c1>,"clock-frequency:0"; -- i2c2_baudrate = <&i2c2>,"clock-frequency:0"; -- core_freq = <&clk_core>,"clock-frequency:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -deleted file mode 100644 -index 9c4000fc686a9882b9ddde24fdcf937d52b0f86f..0000000000000000000000000000000000000000 ---- a/arch/arm/boot/dts/bcm2835-rpi-cm.dtsi -+++ /dev/null -@@ -1,30 +0,0 @@ --#include "bcm2835.dtsi" -- --&leds { -- act_led: act { -- label = "led0"; -- linux,default-trigger = "mmc0"; -- gpios = <&gpio 47 0>; -- }; --}; -- --&mmc { -- status = "okay"; -- bus-width = <4>; --}; -- --&fb { -- status = "okay"; --}; -- --/ { -- __overrides__ { -- act_led_gpio = <&act_led>,"gpios:4"; -- act_led_activelow = <&act_led>,"gpios:8"; -- act_led_trigger = <&act_led>,"linux,default-trigger"; -- -- audio = <&audio>,"status"; -- watchdog = <&watchdog>,"status"; -- random = <&random>,"status"; -- }; --}; - -From b709b3aa0d39d58479b4a579866ed27cebf3a9ed Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 16:00:07 +0200 -Subject: [PATCH 133/208] bcm2708: Convert to ARCH_MULTIPLATFORM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert to multi platform and base it on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 21 -------------- - arch/arm/Makefile | 1 - - arch/arm/configs/bcmrpi_defconfig | 6 ++-- - arch/arm/mach-bcm/Kconfig | 14 +++++++++ - arch/arm/mach-bcm/board_bcm2835.c | 21 ++++++++++++++ - arch/arm/mach-bcm2708/Kconfig | 14 --------- - arch/arm/mach-bcm2708/Makefile | 5 ---- - arch/arm/mach-bcm2708/Makefile.boot | 3 -- - arch/arm/mach-bcm2708/bcm2708.c | 57 ------------------------------------- - drivers/clk/bcm/Makefile | 4 +-- - drivers/clocksource/Makefile | 2 +- - drivers/irqchip/Makefile | 1 - - 12 files changed, 42 insertions(+), 107 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/Kconfig - delete mode 100644 arch/arm/mach-bcm2708/Makefile - delete mode 100644 arch/arm/mach-bcm2708/Makefile.boot - delete mode 100644 arch/arm/mach-bcm2708/bcm2708.c - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 82cbd045d7894e1b75460021a862f8b56f5ec645..4578b06fda58702f040477cabd0a828afa7eccf4 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -326,26 +326,6 @@ choice - default ARM_SINGLE_ARMV7M if !MMU - default ARCH_MULTIPLATFORM if MMU - --config ARCH_BCM2708 -- bool "Broadcom BCM2708 family" -- select CPU_V6 -- select ARM_AMBA -- select CLKSRC_MMIO -- select CLKSRC_OF if OF -- select HAVE_SCHED_CLOCK -- select NEED_MACH_GPIO_H -- select COMMON_CLK -- select ARCH_HAS_CPUFREQ -- select GENERIC_CLOCKEVENTS -- select ARM_ERRATA_411920 -- select MACH_BCM2708 -- select MULTI_IRQ_HANDLER -- select SPARSE_IRQ -- select VC4 -- select FIQ -- help -- This enables support for Broadcom BCM2708 boards. -- - config ARCH_BCM2709 - bool "Broadcom BCM2709 family" - select CPU_V7 -@@ -754,7 +734,6 @@ config ARCH_VIRT - # Kconfigs may be included either alphabetically (according to the - # plat- suffix) or along side the corresponding mach-* source. - # --source "arch/arm/mach-bcm2708/Kconfig" - source "arch/arm/mach-bcm2709/Kconfig" - - source "arch/arm/mach-mvebu/Kconfig" -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 275c53561cd7c3b1f52a60c95b5fb287fb3ccb62..ca1877e0c75d53091c8eee3373e8b8eb210022a2 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -152,7 +152,6 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 - - # Machine directory name. This list is sorted alphanumerically - # by CONFIG_* macro name. --machine-$(CONFIG_ARCH_BCM2708) += bcm2708 - machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_ALPINE) += alpine - machine-$(CONFIG_ARCH_ARTPEC) += artpec -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 46b91678fef473334b9417409fd1c529c0415977..27c61471a12a38feda62447af8010530bc89c141 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1,5 +1,3 @@ --# CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_PHYS_OFFSET=0 - # CONFIG_LOCALVERSION_AUTO is not set - CONFIG_SYSVIPC=y - CONFIG_POSIX_MQUEUE=y -@@ -38,7 +36,11 @@ CONFIG_BLK_DEV_THROTTLING=y - CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_MULTI_V6=y -+# CONFIG_ARCH_MULTI_V7 is not set -+CONFIG_ARCH_BCM=y - CONFIG_ARCH_BCM2708=y -+# CONFIG_CACHE_L2X0 is not set - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y - CONFIG_OABI_COMPAT=y -diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 5f6ab16792a93b2dd2e3f9e647f8ac4062d4fa6d..9461147888e20c10eba7eeca9d8601bff7d849c0 100644 ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -160,6 +160,20 @@ config ARCH_BCM2835 - This enables support for the Broadcom BCM2835 and BCM2836 SoCs. - This SoC is used in the Raspberry Pi and Roku 2 devices. - -+config MACH_BCM2708 -+ bool "Enable optimized __copy_to_user and __copy_from_user" -+ depends on ARCH_BCM2708 -+ default y +diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig +index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 +--- a/drivers/video/backlight/Kconfig ++++ b/drivers/video/backlight/Kconfig +@@ -265,6 +265,12 @@ config BACKLIGHT_PWM + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. + ++config BACKLIGHT_RPI ++ tristate "Raspberry Pi display firmware driven backlight" + help -+ Optimized versions of __copy_to_user and __copy_from_user for Pi1. ++ If you have the Raspberry Pi DSI touchscreen display, say Y to ++ enable the mailbox-controlled backlight driver. + -+config ARCH_BCM2708 -+ bool "Broadcom BCM2708 family" -+ depends on ARCH_MULTI_V6 -+ select ARCH_BCM2835 -+ help -+ This enables support for Broadcom BCM2708 boards. -+ - config ARCH_BCM_63XX - bool "Broadcom BCM63xx DSL SoC" - depends on ARCH_MULTI_V7 -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index 8f152266ba9b470df2eaaed9ebcf158ed2079834..309a336df05191450aa162c91687592a7107a1b0 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -27,6 +28,7 @@ static void __init bcm2835_init(void) - u32 val; - u64 val64; - -+ vc_cma_early_init(); - bcm2835_init_clocks(); - - if (!of_property_read_u32(np, "linux,revision", &val)) -@@ -35,6 +37,11 @@ static void __init bcm2835_init(void) - system_serial_low = val64; - } - -+static void __init bcm2835_board_reserve(void) -+{ -+ vc_cma_reserve(); -+} -+ - static const char * const bcm2835_compat[] = { - #ifdef CONFIG_ARCH_MULTI_V6 - "brcm,bcm2835", -@@ -47,5 +54,19 @@ static const char * const bcm2835_compat[] = { - - DT_MACHINE_START(BCM2835, "BCM2835") - .init_machine = bcm2835_init, -+ .reserve = bcm2835_board_reserve, - .dt_compat = bcm2835_compat - MACHINE_END -+ -+#ifdef CONFIG_ARCH_BCM2708 -+static const char * const bcm2708_compat[] = { -+ "brcm,bcm2708", -+ NULL -+}; -+ -+DT_MACHINE_START(BCM2708, "BCM2708") -+ .init_machine = bcm2835_init, -+ .reserve = bcm2835_board_reserve, -+ .dt_compat = bcm2708_compat, -+MACHINE_END -+#endif -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -deleted file mode 100644 -index 265c3fb90f3debfc439491a89346e4863edec427..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ /dev/null -@@ -1,14 +0,0 @@ --menu "Broadcom BCM2708 Implementations" -- depends on ARCH_BCM2708 -- --config MACH_BCM2708 -- bool "Broadcom BCM2708 Development Platform" -- select CPU_V6 -- select USE_OF -- select ARCH_REQUIRE_GPIOLIB -- select PINCTRL -- select PINCTRL_BCM2835 -- help -- Include support for the Broadcom(R) BCM2708 platform. -- --endmenu -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -deleted file mode 100644 -index 3da1a1b4ea1fb04ae0b535b2915ea9f386f5701c..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/Makefile -+++ /dev/null -@@ -1,5 +0,0 @@ --# --# Makefile for the linux kernel. --# -- --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o -diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot -deleted file mode 100644 -index 67039c3e0c48fa6b94f1147b3316f74afcecba9e..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/Makefile.boot -+++ /dev/null -@@ -1,3 +0,0 @@ -- zreladdr-y := 0x00008000 --params_phys-y := 0x00000100 --initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -deleted file mode 100644 -index 06b078569006a6d821d3d049f1a0fa5783c1c1b3..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ /dev/null -@@ -1,57 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/bcm2708.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include -- --#include --#include -- --static void __init bcm2708_init(void) --{ -- struct device_node *np = of_find_node_by_path("/system"); -- u32 val; -- u64 val64; -- -- vc_cma_early_init(); -- -- if (!of_property_read_u32(np, "linux,revision", &val)) -- system_rev = val; -- if (!of_property_read_u64(np, "linux,serial", &val64)) -- system_serial_low = val64; --} -- --static void __init board_reserve(void) --{ -- vc_cma_reserve(); --} -- --static const char * const bcm2708_compat[] = { -- "brcm,bcm2708", -- NULL --}; -- --DT_MACHINE_START(BCM2708, "BCM2708") -- /* Maintainer: Broadcom Europe Ltd. */ -- .init_machine = bcm2708_init, -- .reserve = board_reserve, -- .dt_compat = bcm2708_compat, --MACHINE_END -- -diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile -index fcf1bb5d792111a31226c33dec6b1da309a36e0d..84dc055849c0cea70aad86898a0cac757a93cc9e 100644 ---- a/drivers/clk/bcm/Makefile -+++ b/drivers/clk/bcm/Makefile -@@ -4,8 +4,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o - obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o - obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o -diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile -index a60aa840b28f0fa73c496a2e0d5c816eed6f771a..fd9d6df0bbc0993c3b7862a08f89dc3a9725be9d 100644 ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -19,7 +19,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o - obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o - obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o - obj-$(CONFIG_ORION_TIMER) += time-orion.o --obj-$(CONFIG_BCM2835_TIMER)$(CONFIG_ARCH_BCM2708) += bcm2835_timer.o -+obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o - obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o - obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o - obj-$(CONFIG_MOXART_TIMER) += moxart_timer.o -diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index 75da978fac0e06819d8a9740b95ee3d7035c1059..662790c8fa9c972bbf3ac7f41b9f5eace912b69c 100644 ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -5,7 +5,6 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o - obj-$(CONFIG_ATH79) += irq-ath79-misc.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o --obj-$(CONFIG_ARCH_BCM2708) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o - obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o - -From ef5da26a574bc300c0cffe21b7a1a041c0676465 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 16:02:39 +0200 -Subject: [PATCH 134/208] bcm2709: Convert to ARCH_MULTIPLATFORM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert to multi platform and base it on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig | 25 ----------------- - arch/arm/Makefile | 1 - - arch/arm/configs/bcm2709_defconfig | 4 +-- - arch/arm/mach-bcm/Kconfig | 9 ++++++ - arch/arm/mach-bcm/board_bcm2835.c | 13 +++++++++ - arch/arm/mach-bcm2709/Kconfig | 9 ------ - arch/arm/mach-bcm2709/Makefile | 5 ---- - arch/arm/mach-bcm2709/Makefile.boot | 3 -- - arch/arm/mach-bcm2709/bcm2709.c | 56 ------------------------------------- - drivers/clk/bcm/Makefile | 4 +-- - drivers/irqchip/Makefile | 2 -- - 11 files changed, 25 insertions(+), 106 deletions(-) - delete mode 100644 arch/arm/mach-bcm2709/Kconfig - delete mode 100644 arch/arm/mach-bcm2709/Makefile - delete mode 100644 arch/arm/mach-bcm2709/Makefile.boot - delete mode 100644 arch/arm/mach-bcm2709/bcm2709.c - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 4578b06fda58702f040477cabd0a828afa7eccf4..a9c4e48bb7ec997bec394066914d26f337a2fec4 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -326,29 +326,6 @@ choice - default ARM_SINGLE_ARMV7M if !MMU - default ARCH_MULTIPLATFORM if MMU - --config ARCH_BCM2709 -- bool "Broadcom BCM2709 family" -- select CPU_V7 -- select HAVE_SMP -- select ARM_AMBA -- select MIGHT_HAVE_CACHE_L2X0 -- select HAVE_SCHED_CLOCK -- select COMMON_CLK -- select ARCH_HAS_CPUFREQ -- select GENERIC_CLOCKEVENTS -- select MACH_BCM2709 -- select MULTI_IRQ_HANDLER -- select SPARSE_IRQ -- select MFD_SYSCON -- select VC4 -- select FIQ -- select USE_OF -- select ARCH_REQUIRE_GPIOLIB -- select PINCTRL -- select PINCTRL_BCM2835 -- help -- This enables support for Broadcom BCM2709 boards. -- - config ARCH_MULTIPLATFORM - bool "Allow multiple platforms to be selected" - depends on MMU -@@ -734,8 +711,6 @@ config ARCH_VIRT - # Kconfigs may be included either alphabetically (according to the - # plat- suffix) or along side the corresponding mach-* source. - # --source "arch/arm/mach-bcm2709/Kconfig" -- - source "arch/arm/mach-mvebu/Kconfig" - - source "arch/arm/mach-alpine/Kconfig" -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index ca1877e0c75d53091c8eee3373e8b8eb210022a2..5eb5aef84c1953d12cce666b8a587e0f1f7dd10a 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -152,7 +152,6 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 - - # Machine directory name. This list is sorted alphanumerically - # by CONFIG_* macro name. --machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_ALPINE) += alpine - machine-$(CONFIG_ARCH_ARTPEC) += artpec - machine-$(CONFIG_ARCH_AT91) += at91 -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 40841d8421e44f8863cb23c53802388b502e61a3..d246dd91b12d40a2d59d5e6758548471f1b195a0 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1,5 +1,3 @@ --# CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_PHYS_OFFSET=0 - CONFIG_LOCALVERSION="-v7" - # CONFIG_LOCALVERSION_AUTO is not set - CONFIG_SYSVIPC=y -@@ -39,10 +37,10 @@ CONFIG_BLK_DEV_THROTTLING=y - CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM=y - CONFIG_ARCH_BCM2709=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_SMP=y --CONFIG_HAVE_ARM_ARCH_TIMER=y - CONFIG_VMSPLIT_2G=y - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y -diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 9461147888e20c10eba7eeca9d8601bff7d849c0..929a5fa241fa94134993c61a137d1f79b514d64b 100644 ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -174,6 +174,15 @@ config ARCH_BCM2708 - help - This enables support for Broadcom BCM2708 boards. - -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ depends on ARCH_MULTI_V7 -+ select ARCH_BCM2835 -+ select HAVE_SMP -+ select MFD_SYSCON -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - config ARCH_BCM_63XX - bool "Broadcom BCM63xx DSL SoC" - depends on ARCH_MULTI_V7 -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index 309a336df05191450aa162c91687592a7107a1b0..6ce49dea7856b243b38f180231afd25b57dee729 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -70,3 +70,16 @@ DT_MACHINE_START(BCM2708, "BCM2708") - .dt_compat = bcm2708_compat, - MACHINE_END - #endif -+ -+#ifdef CONFIG_ARCH_BCM2709 -+static const char * const bcm2709_compat[] = { -+ "brcm,bcm2709", -+ NULL -+}; -+ -+DT_MACHINE_START(BCM2709, "BCM2709") -+ .init_machine = bcm2835_init, -+ .reserve = bcm2835_board_reserve, -+ .dt_compat = bcm2709_compat, -+MACHINE_END -+#endif -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -deleted file mode 100644 -index 41f407ac1db3a86e87941153c1832b9fce1ead5d..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/Kconfig -+++ /dev/null -@@ -1,9 +0,0 @@ --menu "Broadcom BCM2709 Implementations" -- depends on ARCH_BCM2709 -- --config MACH_BCM2709 -- bool "Broadcom BCM2709 Development Platform" -- help -- Include support for the Broadcom(R) BCM2709 platform. -- --endmenu -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -deleted file mode 100644 -index 26cd67d3dc343dbd250fa97855a82c28bbd95af0..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/Makefile -+++ /dev/null -@@ -1,5 +0,0 @@ --# --# Makefile for the linux kernel. --# -- --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o -diff --git a/arch/arm/mach-bcm2709/Makefile.boot b/arch/arm/mach-bcm2709/Makefile.boot -deleted file mode 100644 -index 67039c3e0c48fa6b94f1147b3316f74afcecba9e..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/Makefile.boot -+++ /dev/null -@@ -1,3 +0,0 @@ -- zreladdr-y := 0x00008000 --params_phys-y := 0x00000100 --initrd_phys-y := 0x00800000 -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -deleted file mode 100644 -index 9f113736627175bdcb362e0eda469e09e3d5f2e0..0000000000000000000000000000000000000000 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ /dev/null -@@ -1,56 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2709/bcm2709.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#include --#include -- --#include --#include -- --static void __init bcm2709_init(void) --{ -- struct device_node *np = of_find_node_by_path("/system"); -- u32 val; -- u64 val64; -- -- vc_cma_early_init(); -- -- if (!of_property_read_u32(np, "linux,revision", &val)) -- system_rev = val; -- if (!of_property_read_u64(np, "linux,serial", &val64)) -- system_serial_low = val64; --} -- --static void __init board_reserve(void) --{ -- vc_cma_reserve(); --} -- --static const char * const bcm2709_compat[] = { -- "brcm,bcm2709", -- NULL --}; -- --DT_MACHINE_START(BCM2709, "BCM2709") -- /* Maintainer: Broadcom Europe Ltd. */ -- .init_machine = bcm2709_init, -- .reserve = board_reserve, -- .dt_compat = bcm2709_compat, --MACHINE_END -diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile -index 84dc055849c0cea70aad86898a0cac757a93cc9e..1d79bd2c36f004669d1dcf78fa681025c3f074e2 100644 ---- a/drivers/clk/bcm/Makefile -+++ b/drivers/clk/bcm/Makefile -@@ -4,8 +4,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835.o --obj-$(CONFIG_ARCH_BCM2835)$(CONFIG_ARCH_BCM2709) += clk-bcm2835-aux.o -+obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o -+obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o - obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o - obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o - obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o -diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index 662790c8fa9c972bbf3ac7f41b9f5eace912b69c..4c203b6b816357dce8d7a768ac81feaba91d431b 100644 ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -5,8 +5,6 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o - obj-$(CONFIG_ATH79) += irq-ath79-misc.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o --obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2835.o --obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o - obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o - obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o - -From aba21f030087d28e7f8dc7177efe4632ea1a2e85 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 25 Oct 2016 17:32:02 +0200 -Subject: [PATCH 135/208] kconfig: Just use ARCH_BCM2835 for depends on -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -ARCH_BCM2708 and ARCH_BCM2709 selects ARCH_BCM2835 now, so the -dependencies can be simplified. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/Kconfig.debug | 10 ++++------ - drivers/char/broadcom/Kconfig | 2 +- - drivers/char/hw_random/Kconfig | 2 +- - drivers/dma/Kconfig | 2 +- - drivers/gpio/Kconfig | 2 +- - drivers/gpu/drm/vc4/Kconfig | 2 +- - drivers/i2c/busses/Kconfig | 4 ++-- - drivers/mailbox/Kconfig | 2 +- - drivers/media/platform/bcm2835/Kconfig | 2 +- - drivers/misc/Kconfig | 2 +- - drivers/mmc/host/Kconfig | 4 ++-- - drivers/mtd/nand/Kconfig | 2 +- - drivers/pwm/Kconfig | 2 +- - drivers/soc/bcm/Kconfig | 2 +- - drivers/spi/Kconfig | 4 ++-- - drivers/tty/serial/8250/Kconfig | 2 +- - drivers/watchdog/Kconfig | 2 +- - sound/arm/Kconfig | 3 +-- - sound/soc/bcm/Kconfig | 2 +- - 19 files changed, 25 insertions(+), 28 deletions(-) - -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 11aa81fcaaa8e476ded9b9f41e30ddefa11c1cae..a9693b6987a6e41c69702f1003d0d8bd2279530e 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -147,12 +147,12 @@ choice - - config DEBUG_BCM2835 - bool "Kernel low-level debugging on BCM2835 PL011 UART" -- depends on (ARCH_BCM2835 && ARCH_MULTI_V6) || ARCH_BCM2708 -+ depends on ARCH_BCM2835 && ARCH_MULTI_V6 - select DEBUG_UART_PL01X - - config DEBUG_BCM2836 - bool "Kernel low-level debugging on BCM2836 PL011 UART" -- depends on (ARCH_BCM2835 && ARCH_MULTI_V7) || ARCH_BCM2709 -+ depends on ARCH_BCM2835 && ARCH_MULTI_V7 - select DEBUG_UART_PL01X - - config DEBUG_BCM_5301X -@@ -1695,8 +1695,7 @@ config DEBUG_UART_8250_FLOW_CONTROL - - config DEBUG_UNCOMPRESS - bool -- depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -- ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M - default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ - (!DEBUG_TEGRA_UART || !ZBOOT_ROM) - help -@@ -1713,8 +1712,7 @@ config DEBUG_UNCOMPRESS - config UNCOMPRESS_INCLUDE - string - default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \ -- PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ -- ARCH_BCM2708 || ARCH_BCM2709 -+ PLAT_SAMSUNG || ARM_SINGLE_ARMV7M - default "mach/uncompress.h" - - config EARLY_PRINTK -diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 5489f19f05c620a30541e1a222d77b6ee4356d97..032164919350db25c586c36f0e05d3e4891fb835 100644 ---- a/drivers/char/broadcom/Kconfig -+++ b/drivers/char/broadcom/Kconfig -@@ -49,7 +49,7 @@ config BCM2835_DEVGPIOMEM - - config BCM2835_SMI_DEV - tristate "Character device driver for BCM2835 Secondary Memory Interface" -- depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI -+ depends on BCM2835_SMI - default m - help - This driver provides a character device interface (ioctl + read/write) to -diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 205b6b34d32c660d34c885e8391032d682c8870e..8c0770bf8881351c1d956d310c5d670684090770 100644 ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX - - config HW_RANDOM_BCM2835 - tristate "Broadcom BCM2835 Random Number Generator support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM_NSP || ARCH_BCM_5301X -+ depends on ARCH_BCM2835 || ARCH_BCM_NSP || ARCH_BCM_5301X - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 2a2108062687ff33ff540c987f6367fa3b8aad9d..61c3318e8c88e1cd88e4ccc20875321bb238d936 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -108,7 +108,7 @@ config COH901318 - - config DMA_BCM2835 - tristate "BCM2835 DMA engine support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index 343adff44f82b78d0a09d41518a2890c602fc83d..71d7754587afbb4d6446ebd5448ef7e7c110c47e 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -146,7 +146,7 @@ config GPIO_BCM_KONA - - config GPIO_BCM_VIRT - bool "Broadcom Virt GPIO" -- depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) - help - Turn on virtual GPIO support for Broadcom BCM283X chips. - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index f6e938208b73512f20eab46a383ca91bf675a845..e53df59cb139f25f8e6ae916bca93abf0c49e063 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -1,6 +1,6 @@ - config DRM_VC4 - tristate "Broadcom VC4 Graphics" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - depends on DRM - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 37f463232d6db91940763345600b095dbd8b5c58..9cd5735259276cfc823e6e51907a74db611a2ebc 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -10,7 +10,7 @@ comment "PC SMBus host controller drivers" - - config I2C_BCM2708 - tristate "BCM2708 BSC" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - help - Enabling this option will add BSC (Broadcom Serial Controller) - support for the BCM2708. BSC is a Broadcom proprietary bus compatible -@@ -385,7 +385,7 @@ config I2C_AXXIA - - config I2C_BCM2835 - tristate "Broadcom BCM2835 I2C controller" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - help - If you say yes to this option, support will be included for the - BCM2835 I2C controller. -diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index dc46b41705af8ea405dc961d9230058c7086db7d..7817d40d81e74ad282b1760b1dc50d090d10670d 100644 ---- a/drivers/mailbox/Kconfig -+++ b/drivers/mailbox/Kconfig -@@ -74,7 +74,7 @@ config ALTERA_MBOX - - config BCM2835_MBOX - tristate "BCM2835 Mailbox" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - help - An implementation of the BCM2385 Mailbox. It is used to invoke - the services of the Videocore. Say Y here if you want to use the -diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig -index 99a5cbccf0f3fa66ad5190ec0942b0c232c3e824..58d5f9600d726cb20e6d04c54c58c53ac3a586d2 100644 ---- a/drivers/media/platform/bcm2835/Kconfig -+++ b/drivers/media/platform/bcm2835/Kconfig -@@ -2,7 +2,7 @@ - - config VIDEO_BCM2835 - bool "Broadcom BCM2835 camera interface driver" -- depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) -+ depends on VIDEO_V4L2 && ARCH_BCM2835 - ---help--- - Say Y here to enable camera host interface devices for - Broadcom BCM2835 SoC. This operates over the VCHIQ interface -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index cff8c3df50c4b13d40fd1143eb86a66756bc097c..f34254bc14de8a33bb5922a680331b74f2fae4cb 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -12,7 +12,7 @@ config SENSORS_LIS3LV02D - - config BCM2835_SMI - tristate "Broadcom 283x Secondary Memory Interface driver" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - default m - help - Driver for enabling and using Broadcom's Secondary/Slow Memory Interface. -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 205d836b52e3bbcf8956fec98072c6ee7804a403..87d251e93913b216359383812cae196e91bf6cfb 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -6,7 +6,7 @@ comment "MMC/SD/SDIO Host Controller Drivers" - - config MMC_BCM2835 - tristate "MMC support on BCM2835" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - help - This selects the MMC Interface on BCM2835. - -@@ -35,7 +35,7 @@ config MMC_BCM2835_PIO_DMA_BARRIER - - config MMC_BCM2835_SDHOST - tristate "Support for the SDHost controller on BCM2708/9" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - help - This selects the SDHost controller on BCM2835/6. - -diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig -index b6a0529b2c15f37983169e3429b67bedb71fb14e..7825a51f7a4fee6468d16debab661fa3d210daee 100644 ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -43,7 +43,7 @@ config MTD_SM_COMMON - - config MTD_NAND_BCM2835_SMI - tristate "Use Broadcom's Secondary Memory Interface as a NAND controller (BCM283x)" -- depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI && MTD_NAND -+ depends on BCM2835_SMI - default m - help - Uses the BCM2835's SMI peripheral as a NAND controller. -diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig -index 549cf7a786e27e19863ec0ad53a8b2836afd0c2a..80a566a00d0437dcc8fca7715c1109e7c2d35f67 100644 ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -95,7 +95,7 @@ config PWM_BCM_KONA - - config PWM_BCM2835 - tristate "BCM2835 PWM support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - help - PWM framework driver for BCM2835 controller (Raspberry Pi) - -diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig -index 7d11a44f36d2e6f8697773cd49a72e53bca3a5a0..a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226 100644 ---- a/drivers/soc/bcm/Kconfig -+++ b/drivers/soc/bcm/Kconfig -@@ -2,7 +2,7 @@ menu "Broadcom SoC drivers" - - config RASPBERRYPI_POWER - bool "Raspberry Pi power domain driver" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || (COMPILE_TEST && OF) -+ depends on ARCH_BCM2835 || (COMPILE_TEST && OF) - depends on RASPBERRYPI_FIRMWARE=y - select PM_GENERIC_DOMAINS if PM - help -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 4b09be74af155c2a6e0590a6380242db40e6f914..d6fb8d4b778672fd006446c0eab710d35f6e6e3a 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -94,7 +94,7 @@ config SPI_AXI_SPI_ENGINE - config SPI_BCM2835 - tristate "BCM2835 SPI controller" - depends on GPIOLIB -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI master. - -@@ -105,7 +105,7 @@ config SPI_BCM2835 - - config SPI_BCM2835AUX - tristate "BCM2835 SPI auxiliary controller" -- depends on ((ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709) && GPIOLIB) || COMPILE_TEST -+ depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI aux master. - -diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig -index 748098f900d3474b5d535b24da76ad06e9690335..7c6f7afca5ddeed7b25fa6272246fc539bf31b04 100644 ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -291,7 +291,7 @@ config SERIAL_8250_ACORN - - config SERIAL_8250_BCM2835AUX - tristate "BCM2835 auxiliar mini UART support" -- depends on ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ - help - Support for the BCM2835 auxiliar mini UART. -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index 9a28f1fdf93a79104049c03ed51abc31d34165d5..1bffe006ca9a843e2e71bc1a461a2d67e97480c0 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1440,7 +1440,7 @@ config BCM63XX_WDT - - config BCM2835_WDT - tristate "Broadcom BCM2835 hardware watchdog" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - select WATCHDOG_CORE - help - Watchdog driver for the built in watchdog hardware in Broadcom -diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 8883c2f3a3269742e2bf6fc995643fb282f3509a..02b6d263035ca18c9ce53229369dfb00915c260b 100644 ---- a/sound/arm/Kconfig -+++ b/sound/arm/Kconfig -@@ -34,8 +34,7 @@ config SND_PXA2XX_AC97 - - config SND_BCM2835 - tristate "BCM2835 ALSA driver" -- depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ -- && BCM2708_VCHIQ && SND -+ depends on ARCH_BCM2835 && BCM2708_VCHIQ && SND - select SND_PCM - help - Say Y or M if you want to support BCM2835 Alsa pcm card driver -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index aed7b47d8736ea3fb1810b0c77916855082f3b2d..d024377e8450fb5402dcb5ea27161f774b04a8ec 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -1,6 +1,6 @@ - config SND_BCM2835_SOC_I2S - tristate "SoC Audio support for the Broadcom BCM2835 I2S module" -- depends on ARCH_BCM2835 || MACH_BCM2708 || MACH_BCM2709 || COMPILE_TEST -+ depends on ARCH_BCM2835 || COMPILE_TEST - select SND_SOC_GENERIC_DMAENGINE_PCM - select REGMAP_MMIO - help - -From d770fc68afb2244e1eae7cb99da07425244c500e Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 28 Oct 2016 13:55:36 +0100 -Subject: [PATCH 136/208] bcm270x: Use dma-ranges unconditionally on bcm2710 - -See: https://github.com/raspberrypi/linux/pull/1699 - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2710.dtsi | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index 491594c918cf5da94fbb19a606edb0dd9a28c3a9..df1a4ce1cd4e570876b7785b357d6c31f66191a4 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -9,9 +9,7 @@ - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; --#ifdef RPI364 - dma-ranges = <0xc0000000 0x00000000 0x3f000000>; --#endif - - local_intc: local_intc { - compatible = "brcm,bcm2836-l1-intc"; -@@ -143,9 +141,7 @@ - - &intc { - compatible = "brcm,bcm2836-armctrl-ic"; --#ifdef RPI364 - reg = <0x7e00b200 0x200>; --#endif - interrupt-parent = <&local_intc>; - interrupts = <8>; - }; - -From 3c5d9cfdf541f1da85a407745d790a5cef1d9b6c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 27 Oct 2016 21:57:56 +0200 -Subject: [PATCH 137/208] BCM270X_DT: Use raspberrypi-power to turn on USB - power -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use the raspberrypi-power driver to turn on USB power. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi -index d85c05901c8f55f822b89c32d198f15559a2b4b0..46cf8602c3b96e477b05b57dbfe5e349930c9d9a 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi -@@ -103,3 +103,7 @@ - &hdmi { - power-domains = <&power RPI_POWER_DOMAIN_HDMI>; - }; -+ -+&usb { -+ power-domains = <&power RPI_POWER_DOMAIN_USB>; -+}; - -From 3fc6c0966f06447cfabc8f5b220d32b59e9b7cf4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 27 Oct 2016 21:58:09 +0200 -Subject: [PATCH 138/208] firmware: bcm2835: Don't turn on USB power -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The raspberrypi-power driver is now used to turn on USB power. - -This partly reverts commit: -firmware: bcm2835: Support ARCH_BCM270x - -Signed-off-by: Noralf Trønnes ---- - drivers/firmware/raspberrypi.c | 22 ---------------------- - 1 file changed, 22 deletions(-) - -diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c -index b980d531b35b9981a88356ef1c8a7b868a85f2b5..3f070bd38a91511c986e3fb114b15bd4ac32634c 100644 ---- a/drivers/firmware/raspberrypi.c -+++ b/drivers/firmware/raspberrypi.c -@@ -185,25 +185,6 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) - } - } - --static int raspberrypi_firmware_set_power(struct rpi_firmware *fw, -- u32 domain, bool on) --{ -- struct { -- u32 domain; -- u32 on; -- } packet; -- int ret; -- -- packet.domain = domain; -- packet.on = on; -- ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POWER_STATE, -- &packet, sizeof(packet)); -- if (!ret && packet.on != on) -- ret = -EINVAL; -- -- return ret; --} -- - static int rpi_firmware_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -232,9 +213,6 @@ static int rpi_firmware_probe(struct platform_device *pdev) - - rpi_firmware_print_firmware_revision(fw); - -- if (raspberrypi_firmware_set_power(fw, 3, true)) -- dev_err(dev, "failed to turn on USB power\n"); -- - return 0; - } - - -From da310619ddd881d063323ee8e3bdc1c8b2b5d9a8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 31 Oct 2016 17:35:31 +0000 -Subject: [PATCH 139/208] bcm2835: Increase coherent allocation to 1M for - dwc_otg bounce buffers - ---- - arch/arm/mach-bcm/board_bcm2835.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index 6ce49dea7856b243b38f180231afd25b57dee729..efbd18020479c1cab40ce680446a4259c62c83cb 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -22,6 +22,8 @@ - #include - #include - -+#include -+ - static void __init bcm2835_init(void) - { - struct device_node *np = of_find_node_by_path("/system"); -@@ -37,6 +39,12 @@ static void __init bcm2835_init(void) - system_serial_low = val64; - } - -+static void __init bcm2835_init_early(void) -+{ -+ /* dwc_otg needs this for bounce buffers on non-aligned transfers */ -+ init_dma_coherent_pool_size(SZ_1M); -+} -+ - static void __init bcm2835_board_reserve(void) - { - vc_cma_reserve(); -@@ -55,6 +63,7 @@ static const char * const bcm2835_compat[] = { - DT_MACHINE_START(BCM2835, "BCM2835") - .init_machine = bcm2835_init, - .reserve = bcm2835_board_reserve, -+ .init_early = bcm2835_init_early, - .dt_compat = bcm2835_compat - MACHINE_END - -@@ -67,6 +76,7 @@ static const char * const bcm2708_compat[] = { - DT_MACHINE_START(BCM2708, "BCM2708") - .init_machine = bcm2835_init, - .reserve = bcm2835_board_reserve, -+ .init_early = bcm2835_init_early, - .dt_compat = bcm2708_compat, - MACHINE_END - #endif -@@ -80,6 +90,7 @@ static const char * const bcm2709_compat[] = { - DT_MACHINE_START(BCM2709, "BCM2709") - .init_machine = bcm2835_init, - .reserve = bcm2835_board_reserve, -+ .init_early = bcm2835_init_early, - .dt_compat = bcm2709_compat, - MACHINE_END - #endif - -From 48080e34503d7f5433c56d78586691429a431cdb Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 31 Oct 2016 17:35:57 +0000 -Subject: [PATCH 140/208] dwc_otg: Warn if dma_alloc_coherent fails - ---- - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -index 50aaeacdd12fff93d7a9cf1c54612367406c6bee..e799f15f294706ad7ac328dcb9ce68fbd0e71d38 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -270,6 +270,7 @@ static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, - } - - buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); -+ WARN_ON(!buf); - - /* Check dword alignment */ - if (((int)buf & 0x3UL) != 0) { - -From 556dcc28d787925ac811fede23d170daa24649fd Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Fri, 4 Nov 2016 16:13:07 -0700 -Subject: [PATCH 141/208] bcmrpi3_defconfig: Update config to be compatible - with latest Kconfig changes. - -This new config has been run through make savedefconfig. ---- - arch/arm64/configs/bcmrpi3_defconfig | 111 +++++++++++------------------------ - 1 file changed, 33 insertions(+), 78 deletions(-) - -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -index d7406f5a4620151044b8f716b4d10bb818648e06..cd1d39b467a947a015eb14568086a6ba4cfb729b 100644 ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -1,52 +1,9 @@ --# CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_PHYS_OFFSET=0 - CONFIG_LOCALVERSION="-v8" - # CONFIG_LOCALVERSION_AUTO is not set --CONFIG_64BIT=y - CONFIG_SYSVIPC=y - CONFIG_POSIX_MQUEUE=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y -- --# --# ARM errata workarounds via the alternatives framework --# --CONFIG_ARM64_ERRATUM_826319=n --CONFIG_ARM64_ERRATUM_827319=n --CONFIG_ARM64_ERRATUM_824069=n --CONFIG_ARM64_ERRATUM_819472=n --CONFIG_ARM64_ERRATUM_832075=n --CONFIG_ARM64_ERRATUM_845719=n --CONFIG_ARM64_ERRATUM_843419=n --CONFIG_CAVIUM_ERRATUM_22375=n --CONFIG_CAVIUM_ERRATUM_23154=n --CONFIG_CAVIUM_ERRATUM_27456=n --CONFIG_ARM64_4K_PAGES=y --CONFIG_ARM64_VA_BITS_39=y --CONFIG_ARM64_VA_BITS=39 --CONFIG_SCHED_MC=y --CONFIG_NR_CPUS=4 --CONFIG_HOTPLUG_CPU=y --CONFIG_ARMV8_DEPRECATED=y --CONFIG_SWP_EMULATION=y --CONFIG_CP15_BARRIER_EMULATION=y --CONFIG_SETEND_EMULATION=y -- --# --# ARMv8.1 architectural features --# --CONFIG_ARM64_HW_AFDBM=y --CONFIG_ARM64_PAN=y --CONFIG_ARM64_LSE_ATOMICS=y --CONFIG_ARM64_VHE=y -- --# --# ARMv8.2 architectural features --# --CONFIG_ARM64_UAO=y --CONFIG_ARM64_MODULE_CMODEL_LARGE=n --CONFIG_RANDOMIZE_BASE=n -- - CONFIG_BSD_PROCESS_ACCT=y - CONFIG_BSD_PROCESS_ACCT_V3=y - CONFIG_TASKSTATS=y -@@ -55,7 +12,6 @@ CONFIG_TASK_XACCT=y - CONFIG_TASK_IO_ACCOUNTING=y - CONFIG_IKCONFIG=m - CONFIG_IKCONFIG_PROC=y --CONFIG_NMI_LOG_BUF_SHIFT=12 - CONFIG_MEMCG=y - CONFIG_BLK_CGROUP=y - CONFIG_CGROUP_FREEZER=y -@@ -69,7 +25,6 @@ CONFIG_BLK_DEV_INITRD=y - CONFIG_EMBEDDED=y - # CONFIG_COMPAT_BRK is not set - CONFIG_PROFILING=y --CONFIG_OPROFILE=m - CONFIG_KPROBES=y - CONFIG_JUMP_LABEL=y - CONFIG_MODULES=y -@@ -82,25 +37,37 @@ CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_BCM2709=y --# CONFIG_CACHE_L2X0 is not set --CONFIG_SMP=y --CONFIG_HAVE_ARM_ARCH_TIMER=y --CONFIG_VMSPLIT_2G=y -+CONFIG_ARCH_BCM2835=y -+# CONFIG_ARM64_ERRATUM_826319 is not set -+# CONFIG_ARM64_ERRATUM_827319 is not set -+# CONFIG_ARM64_ERRATUM_824069 is not set -+# CONFIG_ARM64_ERRATUM_819472 is not set -+# CONFIG_ARM64_ERRATUM_832075 is not set -+# CONFIG_ARM64_ERRATUM_845719 is not set -+# CONFIG_ARM64_ERRATUM_843419 is not set -+# CONFIG_CAVIUM_ERRATUM_22375 is not set -+# CONFIG_CAVIUM_ERRATUM_23154 is not set -+# CONFIG_CAVIUM_ERRATUM_27456 is not set -+CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=4 -+CONFIG_HOTPLUG_CPU=y - CONFIG_PREEMPT_VOLUNTARY=y --CONFIG_AEABI=y --CONFIG_OABI_COMPAT=y --# CONFIG_CPU_SW_DOMAIN_PAN is not set - CONFIG_CLEANCACHE=y - CONFIG_FRONTSWAP=y - CONFIG_CMA=y - CONFIG_ZSMALLOC=m - CONFIG_PGTABLE_MAPPING=y --CONFIG_UACCESS_WITH_MEMCPY=y - CONFIG_SECCOMP=y --# CONFIG_ATAGS is not set --CONFIG_ZBOOT_ROM_TEXT=0x0 --CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y -+CONFIG_ARM64_LSE_ATOMICS=y - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_BINFMT_MISC=m -+CONFIG_COMPAT=y -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y - CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -@@ -108,15 +75,6 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y - CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y --CONFIG_VFP=y --CONFIG_NEON=y --CONFIG_KERNEL_MODE_NEON=y --CONFIG_BINFMT_MISC=m --CONFIG_COMPAT=y --CONFIG_SYSVIPC_COMPAT=y -- --# CONFIG_SUSPEND is not set --CONFIG_PM=y - CONFIG_NET=y - CONFIG_PACKET=y - CONFIG_UNIX=y -@@ -463,6 +421,7 @@ CONFIG_CDROM_PKTCDVD=m - CONFIG_ATA_OVER_ETH=m - CONFIG_EEPROM_AT24=m - CONFIG_TI_ST=m -+# CONFIG_BCM2708_VCHIQ is not set - CONFIG_SCSI=y - # CONFIG_SCSI_PROC_FS is not set - CONFIG_BLK_DEV_SD=y -@@ -580,7 +539,6 @@ CONFIG_RT2800USB_RT53XX=y - CONFIG_RT2800USB_RT55XX=y - CONFIG_RT2800USB_UNKNOWN=y - CONFIG_RTL8187=m --CONFIG_RTL8192CU=n - CONFIG_USB_ZD1201=m - CONFIG_ZD1211RW=m - CONFIG_MAC80211_HWSIM=m -@@ -626,10 +584,6 @@ CONFIG_SERIO_RAW=m - CONFIG_GAMEPORT=m - CONFIG_GAMEPORT_NS558=m - CONFIG_GAMEPORT_L4=m --CONFIG_BRCM_CHAR_DRIVERS=n --CONFIG_BCM_VC_CMA=n --CONFIG_BCM_VCIO=n --CONFIG_BCM_VC_SM=n - # CONFIG_LEGACY_PTYS is not set - # CONFIG_DEVKMEM is not set - CONFIG_SERIAL_8250=y -@@ -638,6 +592,9 @@ CONFIG_SERIAL_8250_CONSOLE=y - # CONFIG_SERIAL_8250_DMA is not set - CONFIG_SERIAL_8250_NR_UARTS=1 - CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y - CONFIG_SERIAL_OF_PLATFORM=y - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -@@ -682,12 +639,12 @@ CONFIG_W1_SLAVE_DS2781=m - CONFIG_W1_SLAVE_DS28E04=m - CONFIG_W1_SLAVE_BQ27000=m - CONFIG_BATTERY_DS2760=m --CONFIG_POWER_RESET=y - CONFIG_POWER_RESET_GPIO=y - CONFIG_HWMON=m - CONFIG_SENSORS_LM75=m - CONFIG_SENSORS_SHT21=m - CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y -@@ -835,8 +792,7 @@ CONFIG_VIDEO_EM28XX_V4L2=m - CONFIG_VIDEO_EM28XX_ALSA=m - CONFIG_VIDEO_EM28XX_DVB=m - CONFIG_V4L_PLATFORM_DRIVERS=y --CONFIG_VIDEO_BCM2835=n --CONFIG_VIDEO_BCM2835_MMAL=n -+CONFIG_VIDEO_BCM2835=y - CONFIG_RADIO_SI470X=y - CONFIG_USB_SI470X=m - CONFIG_I2C_SI470X=m -@@ -892,8 +848,6 @@ CONFIG_SND_VIRMIDI=m - CONFIG_SND_MTPAV=m - CONFIG_SND_SERIAL_U16550=m - CONFIG_SND_MPU401=m --CONFIG_SND_ARM=n --CONFIG_SND_BCM2835=n - CONFIG_SND_USB_AUDIO=m - CONFIG_SND_USB_UA101=m - CONFIG_SND_USB_CAIAQ=m -@@ -916,6 +870,8 @@ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m - CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m -@@ -979,8 +935,6 @@ CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - CONFIG_USB_MON=m --CONFIG_USB_DWCOTG=n --CONFIG_USB_DWC2=y - CONFIG_USB_PRINTER=m - CONFIG_USB_STORAGE=y - CONFIG_USB_STORAGE_REALTEK=m -@@ -1001,6 +955,7 @@ CONFIG_USB_MICROTEK=m - CONFIG_USBIP_CORE=m - CONFIG_USBIP_VHCI_HCD=m - CONFIG_USBIP_HOST=m -+CONFIG_USB_DWC2=y - CONFIG_USB_SERIAL=m - CONFIG_USB_SERIAL_GENERIC=y - CONFIG_USB_SERIAL_AIRCABLE=m -@@ -1153,6 +1108,7 @@ CONFIG_FB_TFT_BD663474=m - CONFIG_FB_TFT_HX8340BN=m - CONFIG_FB_TFT_HX8347D=m - CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m - CONFIG_FB_TFT_ILI9163=m - CONFIG_FB_TFT_ILI9320=m - CONFIG_FB_TFT_ILI9325=m -@@ -1331,4 +1287,3 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m - CONFIG_ARM64_CRYPTO=y - CONFIG_CRC_ITU_T=y - CONFIG_LIBCRC32C=y --CONFIG_BCM2708_VCHIQ=n - -From 8327ba9ec4f7544d9045f390e72e5305f79f0289 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 8 Nov 2016 21:35:38 +0000 -Subject: [PATCH 142/208] spi-bcm2835: Remove unused code - ---- - drivers/spi/spi-bcm2835.c | 61 ----------------------------------------------- - 1 file changed, 61 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 8493474d286f7a1ac6454a22c61c8c2cef9121bf..33d75ad38a7f77d085321ace9101900a83bebcac 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -679,17 +679,8 @@ static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - } - --static int chip_match_name(struct gpio_chip *chip, void *data) --{ -- return !strcmp(chip->label, data); --} -- - static int bcm2835_spi_setup(struct spi_device *spi) - { -- int err; -- struct gpio_chip *chip; -- struct device_node *pins; -- u32 pingroup_index; - /* - * sanity checking the native-chipselects - */ -@@ -707,58 +698,6 @@ static int bcm2835_spi_setup(struct spi_device *spi) - return -EINVAL; - } - --#if 0 -- /* now translate native cs to GPIO */ -- /* first look for chip select pins in the devices pin groups */ -- for (pingroup_index = 0; -- (pins = of_parse_phandle(spi->master->dev.of_node, -- "pinctrl-0", -- pingroup_index)) != 0; -- pingroup_index++) { -- u32 pin; -- u32 pin_index; -- for (pin_index = 0; -- of_property_read_u32_index(pins, -- "brcm,pins", -- pin_index, -- &pin) == 0; -- pin_index++) { -- if (((spi->chip_select == 0) && -- ((pin == 8) || (pin == 36) || (pin == 46))) || -- ((spi->chip_select == 1) && -- ((pin == 7) || (pin == 35)))) { -- spi->cs_gpio = pin; -- break; -- } -- } -- of_node_put(pins); -- } -- /* if that fails, assume GPIOs 7-11 are used */ -- if (!gpio_is_valid(spi->cs_gpio) ) { -- /* get the gpio chip for the base */ -- chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); -- if (!chip) -- return 0; -- -- /* and calculate the real CS */ -- spi->cs_gpio = chip->base + 8 - spi->chip_select; -- } -- -- /* and set up the "mode" and level */ -- dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -- spi->chip_select, spi->cs_gpio); -- -- /* set up GPIO as output and pull to the correct level */ -- err = gpio_direction_output(spi->cs_gpio, -- (spi->mode & SPI_CS_HIGH) ? 0 : 1); -- if (err) { -- dev_err(&spi->dev, -- "could not set CS%i gpio %i as output: %i", -- spi->chip_select, spi->cs_gpio, err); -- return err; -- } --#endif -- - return 0; - } - - -From a52fcdf0feb26148aa77f39f5ed28d40b45eb201 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 17 Sep 2016 15:07:10 +0200 -Subject: [PATCH 143/208] i2c: bcm2835: Fix hang for writing messages larger - than 16 bytes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Writing messages larger than the FIFO size results in a hang, rendering -the machine unusable. This is because the RXD status flag is set on the -first interrupt which results in bcm2835_drain_rxfifo() stealing bytes -from the buffer. The controller continues to trigger interrupts waiting -for the missing bytes, but bcm2835_fill_txfifo() has none to give. -In this situation wait_for_completion_timeout() apparently is unable to -stop the madness. - -The BCM2835 ARM Peripherals datasheet has this to say about the flags: - TXD: is set when the FIFO has space for at least one byte of data. - RXD: is set when the FIFO contains at least one byte of data. - TXW: is set during a write transfer and the FIFO is less than full. - RXR: is set during a read transfer and the FIFO is or more full. - -Implementing the logic from the downstream i2c-bcm2708 driver solved -the hang problem. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt -Reviewed-by: Martin Sperl ---- - drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index d4f3239b56865919e1b781b20a7c5ebcd76b4eb9..f283b714aa79e2e4685ed95b04b6b289f7e9eee7 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { - int irq; - struct i2c_adapter adapter; - struct completion completion; -+ struct i2c_msg *curr_msg; - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -@@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - return IRQ_HANDLED; - } - -- if (val & BCM2835_I2C_S_RXD) { -- bcm2835_drain_rxfifo(i2c_dev); -- if (!(val & BCM2835_I2C_S_DONE)) -- return IRQ_HANDLED; -- } -- - if (val & BCM2835_I2C_S_DONE) { -- if (i2c_dev->msg_buf_remaining) -+ if (i2c_dev->curr_msg->flags & I2C_M_RD) { -+ bcm2835_drain_rxfifo(i2c_dev); -+ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -+ } -+ -+ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) - i2c_dev->msg_err = BCM2835_I2C_S_LEN; - else - i2c_dev->msg_err = 0; -@@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - return IRQ_HANDLED; - } - -- if (val & BCM2835_I2C_S_TXD) { -+ if (val & BCM2835_I2C_S_TXW) { - bcm2835_fill_txfifo(i2c_dev); - return IRQ_HANDLED; - } - -+ if (val & BCM2835_I2C_S_RXR) { -+ bcm2835_drain_rxfifo(i2c_dev); -+ return IRQ_HANDLED; -+ } -+ - return IRQ_NONE; - } - -@@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - u32 c; - unsigned long time_left; - -+ i2c_dev->curr_msg = msg; - i2c_dev->msg_buf = msg->buf; - i2c_dev->msg_buf_remaining = msg->len; - reinit_completion(&i2c_dev->completion); - -From 2bfb98d7ef7b2599e323ce5bf7d55da796d1d73c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 18:24:38 +0200 -Subject: [PATCH 144/208] i2c: bcm2835: Protect against unexpected TXW/RXR - interrupts -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), -the driver has no way to fill/drain the FIFO to stop the interrupts. -In this case the controller has to be disabled and the transfer -completed to avoid hang. - -(CLKT | ERR) and DONE interrupts are completed in their own paths, and -the controller is disabled in the transfer function after completion. -Unite the code paths and do disabling inside the interrupt routine. - -Clear interrupt status bits in the united completion path instead of -trying to do it on every interrupt which isn't necessary. -Only CLKT, ERR and DONE can be cleared that way. - -Add the status value to the error value in case of TXW/RXR errors to -distinguish them from the other S_LEN error. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++--------- - 1 file changed, 31 insertions(+), 9 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index f283b714aa79e2e4685ed95b04b6b289f7e9eee7..d2ba1a4de36af512e8e3c97251bd3537ae61591a 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -50,8 +50,6 @@ - #define BCM2835_I2C_S_CLKT BIT(9) - #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ - --#define BCM2835_I2C_BITMSK_S 0x03FF -- - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - -@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) - } - } - + config BACKLIGHT_DA903X + tristate "Backlight Driver for DA9030/DA9034 using WLED" + depends on PMIC_DA903X +diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile +index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 +--- a/drivers/video/backlight/Makefile ++++ b/drivers/video/backlight/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o + obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o + obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o + obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o ++obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o + obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o + obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o + obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o +diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c +new file mode 100644 +index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad +--- /dev/null ++++ b/drivers/video/backlight/rpi_backlight.c +@@ -0,0 +1,119 @@ +/* -+ * Note about I2C_C_CLEAR on error: -+ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in -+ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through -+ * the state machine to send a NACK and a STOP. Since we're setting CLEAR -+ * without I2CEN, that NACK will be hanging around queued up for next time -+ * we start the engine. ++ * rpi_bl.c - Backlight controller through VPU ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. + */ + - static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - { - struct bcm2835_i2c_dev *i2c_dev = data; - u32 val, err; - - val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -- val &= BCM2835_I2C_BITMSK_S; -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); - - err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if (err) { - i2c_dev->msg_err = err; -- complete(&i2c_dev->completion); -- return IRQ_HANDLED; -+ goto complete; - } - - if (val & BCM2835_I2C_S_DONE) { -@@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - i2c_dev->msg_err = BCM2835_I2C_S_LEN; - else - i2c_dev->msg_err = 0; -- complete(&i2c_dev->completion); -- return IRQ_HANDLED; -+ goto complete; - } - - if (val & BCM2835_I2C_S_TXW) { -+ if (!i2c_dev->msg_buf_remaining) { -+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; -+ goto complete; -+ } ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + - bcm2835_fill_txfifo(i2c_dev); - return IRQ_HANDLED; - } - - if (val & BCM2835_I2C_S_RXR) { -+ if (!i2c_dev->msg_buf_remaining) { -+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; -+ goto complete; -+ } ++struct rpi_backlight { ++ struct device *dev; ++ struct device *fbdev; ++ struct rpi_firmware *fw; ++}; + - bcm2835_drain_rxfifo(i2c_dev); - return IRQ_HANDLED; - } - - return IRQ_NONE; -+ -+complete: -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT | -+ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE); -+ complete(&i2c_dev->completion); -+ -+ return IRQ_HANDLED; - } - - static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, -@@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - BCM2835_I2C_TIMEOUT); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); - if (!time_left) { -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, -+ BCM2835_I2C_C_CLEAR); - dev_err(i2c_dev->dev, "i2c transfer timed out\n"); - return -ETIMEDOUT; - } - -From 95c425e3ae8a01e772381b1d262599a85b6d1871 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 19 Sep 2016 17:19:41 +0200 -Subject: [PATCH 145/208] i2c: bcm2835: Use dev_dbg logging on transfer errors -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Writing to an AT24C32 generates on average 2x i2c transfer errors per -32-byte page write. Which amounts to a lot for a 4k write. This is due -to the fact that the chip doesn't respond during it's internal write -cycle when the at24 driver tries and retries the next write. -Only a handful drivers use dev_err() on transfer error, so switch to -dev_dbg() instead. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index d2ba1a4de36af512e8e3c97251bd3537ae61591a..54d510abd46a117c9238fc6d7edec84019d1f60d 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - (msg->flags & I2C_M_IGNORE_NAK)) - return 0; - -- dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); -+ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; - -From dd2fb326c9bea407665658538a993d907b681b90 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 22 Sep 2016 22:05:50 +0200 -Subject: [PATCH 146/208] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The controller can't support this flag, so remove it. - -Documentation/i2c/i2c-protocol states that all of the message is sent: - -I2C_M_IGNORE_NAK: - Normally message is interrupted immediately if there is [NA] from the - client. Setting this flag treats any [NA] as [A], and all of - message is sent. - -From the BCM2835 ARM Peripherals datasheet: - - The ERR field is set when the slave fails to acknowledge either - its address or a data byte written to it. - -So when the controller doesn't receive an ack, it sets ERR and raises -an interrupt. In other words, the whole message is not sent. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index 54d510abd46a117c9238fc6d7edec84019d1f60d..565ef69ce61423544dc0558c85ef318b0ae9c324 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - if (likely(!i2c_dev->msg_err)) - return 0; - -- if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && -- (msg->flags & I2C_M_IGNORE_NAK)) -- return 0; -- - dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - -From e8a3cc458193ad57270e74ceff8f5059ecdfb0ba Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 04:54:27 +0200 -Subject: [PATCH 147/208] i2c: bcm2835: Add support for Repeated Start - Condition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Documentation/i2c/i2c-protocol states that Combined transactions should -separate messages with a Start bit and end the whole transaction with a -Stop bit. This patch adds support for issuing only a Start between -messages instead of a Stop followed by a Start. - -This implementation differs from downstream i2c-bcm2708 in 2 respects: -- it uses an interrupt to detect that the transfer is active instead - of using polling. There is no interrupt for Transfer Active, but by - not prefilling the FIFO it's possible to use the TXW interrupt. -- when resetting/disabling the controller between transfers it writes - CLEAR to the control register instead of just zero. - Using just zero gave many errors. This might be the reason why - downstream had to disable this feature and make it available with a - module parameter. - -I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) -and AT24C32 (eeprom) in parallel without problems. - -Signed-off-by: Noralf Trønnes -Acked-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++--------------- - 1 file changed, 63 insertions(+), 38 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index 565ef69ce61423544dc0558c85ef318b0ae9c324..241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev { - struct i2c_adapter adapter; - struct completion completion; - struct i2c_msg *curr_msg; -+ int num_msgs; - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) - } - - /* -+ * Repeated Start Condition (Sr) -+ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it -+ * talks about reading from a slave with 10 bit address. This is achieved by -+ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then -+ * issue a read. -+ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the -+ * firmware actually does it using polling and says that it's a workaround for -+ * a problem in the state machine. -+ * It turns out that it is possible to use the TXW interrupt to know when the -+ * transfer is active, provided the FIFO has not been prefilled. -+ */ -+ -+static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) ++static int rpi_backlight_update_status(struct backlight_device *bl) +{ -+ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN; -+ struct i2c_msg *msg = i2c_dev->curr_msg; -+ bool last_msg = (i2c_dev->num_msgs == 1); ++ struct rpi_backlight *gbl = bl_get_data(bl); ++ int brightness = bl->props.brightness; ++ int ret; + -+ if (!i2c_dev->num_msgs) -+ return; ++ if (bl->props.power != FB_BLANK_UNBLANK || ++ bl->props.fb_blank != FB_BLANK_UNBLANK || ++ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) ++ brightness = 0; + -+ i2c_dev->num_msgs--; -+ i2c_dev->msg_buf = msg->buf; -+ i2c_dev->msg_buf_remaining = msg->len; -+ -+ if (msg->flags & I2C_M_RD) -+ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; -+ else -+ c |= BCM2835_I2C_C_INTT; -+ -+ if (last_msg) -+ c |= BCM2835_I2C_C_INTD; -+ -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+} -+ -+/* - * Note about I2C_C_CLEAR on error: - * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in - * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through -@@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - } - - bcm2835_fill_txfifo(i2c_dev); -+ -+ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { -+ i2c_dev->curr_msg++; -+ bcm2835_i2c_start_transfer(i2c_dev); -+ } -+ - return IRQ_HANDLED; - } - -@@ -175,30 +221,25 @@ complete: - return IRQ_HANDLED; - } - --static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, -- struct i2c_msg *msg) -+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], -+ int num) - { -- u32 c; -+ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - unsigned long time_left; -+ int i; - -- i2c_dev->curr_msg = msg; -- i2c_dev->msg_buf = msg->buf; -- i2c_dev->msg_buf_remaining = msg->len; -- reinit_completion(&i2c_dev->completion); -- -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -+ for (i = 0; i < (num - 1); i++) -+ if (msgs[i].flags & I2C_M_RD) { -+ dev_warn_once(i2c_dev->dev, -+ "only one read message supported, has to be last\n"); -+ return -EOPNOTSUPP; -+ } - -- if (msg->flags & I2C_M_RD) { -- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; -- } else { -- c = BCM2835_I2C_C_INTT; -- bcm2835_fill_txfifo(i2c_dev); -- } -- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; -+ i2c_dev->curr_msg = msgs; -+ i2c_dev->num_msgs = num; -+ reinit_completion(&i2c_dev->completion); - -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+ bcm2835_i2c_start_transfer(i2c_dev); - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - BCM2835_I2C_TIMEOUT); -@@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, - return -ETIMEDOUT; - } - -- if (likely(!i2c_dev->msg_err)) -- return 0; -+ if (!i2c_dev->msg_err) -+ return num; - - dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; -- else -- return -EIO; --} -- --static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], -- int num) --{ -- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); -- int i; -- int ret = 0; -- -- for (i = 0; i < num; i++) { -- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); -- if (ret) -- break; -- } - -- return ret ?: i; -+ return -EIO; - } - - static u32 bcm2835_i2c_func(struct i2c_adapter *adap) - -From 3b97a07025c5bda264cdec1cf56d84d7c5ee90be Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 04:57:17 +0200 -Subject: [PATCH 148/208] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use i2c_adapter->timeout for the completion timeout value. The core -default is 1 second. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index 241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f..d2085dd3742eabebc537621968088261f8dc7ea8 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -53,8 +53,6 @@ - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - --#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) -- - struct bcm2835_i2c_dev { - struct device *dev; - void __iomem *regs; -@@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - bcm2835_i2c_start_transfer(i2c_dev); - - time_left = wait_for_completion_timeout(&i2c_dev->completion, -- BCM2835_I2C_TIMEOUT); -+ adap->timeout); - if (!time_left) { - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, - BCM2835_I2C_C_CLEAR); - -From e67fa8bf66a0efa9d4604cb77c6f7b44a887618b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 27 Sep 2016 01:00:08 +0200 -Subject: [PATCH 149/208] i2c: bcm2835: Add support for dynamic clock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Support a dynamic clock by reading the frequency and setting the -divisor in the transfer function instead of during probe. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Martin Sperl ---- - drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++--------------- - 1 file changed, 32 insertions(+), 19 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index d2085dd3742eabebc537621968088261f8dc7ea8..c3436f627028477f7e21b47e079fd5ab06ec188a 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev { - void __iomem *regs; - struct clk *clk; - int irq; -+ u32 bus_clk_rate; - struct i2c_adapter adapter; - struct completion completion; - struct i2c_msg *curr_msg; -@@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) - return readl(i2c_dev->regs + reg); - } - -+static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ u32 divider; -+ -+ divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), -+ i2c_dev->bus_clk_rate); -+ /* -+ * Per the datasheet, the register is always interpreted as an even -+ * number, by rounding down. In other words, the LSB is ignored. So, -+ * if the LSB is set, increment the divider to avoid any issue. -+ */ -+ if (divider & 1) -+ divider++; -+ if ((divider < BCM2835_I2C_CDIV_MIN) || -+ (divider > BCM2835_I2C_CDIV_MAX)) { -+ dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); -+ return -EINVAL; ++ ret = rpi_firmware_property(gbl->fw, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, ++ &brightness, sizeof(brightness)); ++ if (ret) { ++ dev_err(gbl->dev, "Failed to set brightness\n"); ++ return ret; + } + -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); ++ if (brightness < 0) { ++ dev_err(gbl->dev, "Backlight change failed\n"); ++ return -EAGAIN; ++ } + + return 0; +} + - static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) - { - u32 val; -@@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - { - struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - unsigned long time_left; -- int i; -+ int i, ret; - - for (i = 0; i < (num - 1); i++) - if (msgs[i].flags & I2C_M_RD) { -@@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - return -EOPNOTSUPP; - } - -+ ret = bcm2835_i2c_set_divider(i2c_dev); -+ if (ret) -+ return ret; -+ - i2c_dev->curr_msg = msgs; - i2c_dev->num_msgs = num; - reinit_completion(&i2c_dev->completion); -@@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) - { - struct bcm2835_i2c_dev *i2c_dev; - struct resource *mem, *irq; -- u32 bus_clk_rate, divider; - int ret; - struct i2c_adapter *adap; - -@@ -306,27 +334,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) - } - - ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", -- &bus_clk_rate); -+ &i2c_dev->bus_clk_rate); - if (ret < 0) { - dev_warn(&pdev->dev, - "Could not read clock-frequency property\n"); -- bus_clk_rate = 100000; -- } -- -- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); -- /* -- * Per the datasheet, the register is always interpreted as an even -- * number, by rounding down. In other words, the LSB is ignored. So, -- * if the LSB is set, increment the divider to avoid any issue. -- */ -- if (divider & 1) -- divider++; -- if ((divider < BCM2835_I2C_CDIV_MIN) || -- (divider > BCM2835_I2C_CDIV_MAX)) { -- dev_err(&pdev->dev, "Invalid clock-frequency\n"); -- return -ENODEV; -+ i2c_dev->bus_clk_rate = 100000; - } -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); - - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) { - -From 93b4f7766d563b91a30df26ee3305e88d6d56c76 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 15:15:41 +0100 -Subject: [PATCH 150/208] i2c: bcm2835: Add debug support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds a debug module parameter to aid in debugging transfer issues -by printing info to the kernel log. When enabled, status values are -collected in the interrupt routine and msg info in -bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid -affecting timing. Having printk in the isr can mask issues. - -debug values (additive): -1: Print info on error -2: Print info on all transfers -3: Print messages before transfer is started - -The value can be changed at runtime: -/sys/module/i2c_bcm2835/parameters/debug - -Example output, debug=3: -[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] -[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] - -Signed-off-by: Noralf Trønnes ---- - drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 98 insertions(+), 1 deletion(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index c3436f627028477f7e21b47e079fd5ab06ec188a..8642f580ce41803bd22c76a0fa80d083d0747be1 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -53,6 +53,18 @@ - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - -+static unsigned int debug; -+module_param(debug, uint, 0644); -+MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); -+ -+#define BCM2835_DEBUG_MAX 512 -+struct bcm2835_debug { -+ struct i2c_msg *msg; -+ int msg_idx; -+ size_t remain; -+ u32 status; ++static const struct backlight_ops rpi_backlight_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .update_status = rpi_backlight_update_status, +}; + - struct bcm2835_i2c_dev { - struct device *dev; - void __iomem *regs; -@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -+ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; -+ unsigned int debug_num; -+ unsigned int debug_num_msgs; - }; - -+static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) ++static int rpi_backlight_probe(struct platform_device *pdev) +{ -+ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ return; ++ struct backlight_properties props; ++ struct backlight_device *bl; ++ struct rpi_backlight *gbl; ++ struct device_node *fw_node; + -+ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; -+ i2c_dev->debug[i2c_dev->debug_num].msg_idx = -+ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; -+ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; -+ i2c_dev->debug[i2c_dev->debug_num].status = s; -+ i2c_dev->debug_num++; -+} ++ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); ++ if (gbl == NULL) ++ return -ENOMEM; + -+static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, -+ struct bcm2835_debug *d) -+{ -+ u32 s = d->status; ++ gbl->dev = &pdev->dev; + -+ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", -+ d->remain, s, -+ s & BCM2835_I2C_S_TA ? "TA " : "", -+ s & BCM2835_I2C_S_DONE ? "DONE " : "", -+ s & BCM2835_I2C_S_TXW ? "TXW " : "", -+ s & BCM2835_I2C_S_RXR ? "RXR " : "", -+ s & BCM2835_I2C_S_TXD ? "TXD " : "", -+ s & BCM2835_I2C_S_RXD ? "RXD " : "", -+ s & BCM2835_I2C_S_TXE ? "TXE " : "", -+ s & BCM2835_I2C_S_RXF ? "RXF " : "", -+ s & BCM2835_I2C_S_ERR ? "ERR " : "", -+ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, -+ struct i2c_msg *msg, int i, int total, -+ const char *fname) -+{ -+ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", -+ fname, i, total, -+ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, -+ msg->flags & I2C_M_TEN ? "TEN" : "", -+ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", -+ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", -+ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", -+ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", -+ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", -+ msg->flags & I2C_M_STOP ? "STOP" : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ struct bcm2835_debug *d; -+ unsigned int i; -+ -+ for (i = 0; i < i2c_dev->debug_num; i++) { -+ d = &i2c_dev->debug[i]; -+ if (d->status == ~0) -+ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, -+ i2c_dev->debug_num_msgs, "start_transfer"); -+ else -+ bcm2835_debug_print_status(i2c_dev, d); ++ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ if (!fw_node) { ++ dev_err(&pdev->dev, "Missing firmware node\n"); ++ return -ENOENT; + } -+ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ pr_info("BCM2835_DEBUG_MAX reached\n"); ++ ++ gbl->fw = rpi_firmware_get(fw_node); ++ if (!gbl->fw) ++ return -EPROBE_DEFER; ++ ++ memset(&props, 0, sizeof(props)); ++ props.type = BACKLIGHT_RAW; ++ props.max_brightness = 255; ++ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), ++ &pdev->dev, gbl, &rpi_backlight_ops, ++ &props); ++ if (IS_ERR(bl)) { ++ dev_err(&pdev->dev, "failed to register backlight\n"); ++ return PTR_ERR(bl); ++ } ++ ++ bl->props.brightness = 255; ++ backlight_update_status(bl); ++ ++ platform_set_drvdata(pdev, bl); ++ return 0; +} + - static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, - u32 reg, u32 val) - { -@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+ bcm2835_debug_add(i2c_dev, ~0); - } - - /* -@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - u32 val, err; - - val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -+ bcm2835_debug_add(i2c_dev, val); - - err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if (err) { -@@ -251,6 +335,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - unsigned long time_left; - int i, ret; - -+ if (debug) -+ i2c_dev->debug_num_msgs = num; -+ -+ if (debug > 2) -+ for (i = 0; i < num; i++) -+ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); -+ - for (i = 0; i < (num - 1); i++) - if (msgs[i].flags & I2C_M_RD) { - dev_warn_once(i2c_dev->dev, -@@ -270,6 +361,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - adap->timeout); -+ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) -+ bcm2835_debug_print(i2c_dev); -+ i2c_dev->debug_num_msgs = 0; -+ i2c_dev->debug_num = 0; - if (!time_left) { - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, - BCM2835_I2C_C_CLEAR); -@@ -280,7 +375,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - if (!i2c_dev->msg_err) - return num; - -- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); -+ if (debug) -+ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", -+ i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; - -From 37134679c255f5b1b4c42e85b454c9dac1308e7f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 20:03:29 +0100 -Subject: [PATCH 151/208] config: Enable i2c-bcm2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index d246dd91b12d40a2d59d5e6758548471f1b195a0..816f832a5f676d905bfae1e06ae8003e38d5cff3 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -606,6 +606,7 @@ CONFIG_I2C=y - CONFIG_I2C_CHARDEV=m - CONFIG_I2C_MUX_PCA954x=m - CONFIG_I2C_BCM2708=m -+CONFIG_I2C_BCM2835=m - CONFIG_I2C_GPIO=m - CONFIG_SPI=y - CONFIG_SPI_BCM2835=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 27c61471a12a38feda62447af8010530bc89c141..98b2e5992a45a6212ef9a8b9826431d9fc024169 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -602,6 +602,7 @@ CONFIG_I2C=y - CONFIG_I2C_CHARDEV=m - CONFIG_I2C_MUX_PCA954x=m - CONFIG_I2C_BCM2708=m -+CONFIG_I2C_BCM2835=m - CONFIG_I2C_GPIO=m - CONFIG_SPI=y - CONFIG_SPI_BCM2835=m - -From 0abcf1feef4457158239d560a7c5c103eb1b347c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 15:42:55 +0100 -Subject: [PATCH 152/208] BCM270X_DT: Use i2c-bcm2835 as default -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -i2c-bcm2835 has gotten an overhaul so we can now use as default. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm270x.dtsi | 12 ------------ - 1 file changed, 12 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -index 7fb1f428332dc48bdd91dd4a0773f3bea7057238..514b481d4f4095dc8b55a216ac7335934973e145 100644 ---- a/arch/arm/boot/dts/bcm270x.dtsi -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -49,10 +49,6 @@ - dma-names = "tx", "rx"; - }; - -- i2c@7e205000 { /* i2c0 */ -- compatible = "brcm,bcm2708-i2c"; -- }; -- - pixelvalve0: pixelvalve@7e206000 { - /* Add alias */ - status = "disabled"; -@@ -104,14 +100,6 @@ - status = "disabled"; - }; - -- i2c@7e804000 { /* i2c1 */ -- compatible = "brcm,bcm2708-i2c"; -- }; -- -- i2c@7e805000 { /* i2c2 */ -- compatible = "brcm,bcm2708-i2c"; -- }; -- - pixelvalve2: pixelvalve@7e807000 { - /* Add alias */ - status = "disabled"; - -From 279b8a1317b5d18d1d61de902d95fb6fa60b08cc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 11 Nov 2016 18:24:26 +0100 -Subject: [PATCH 153/208] BCM270X_DT: Add fallback overlay for i2c-bcm2708 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 ++++++ - arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts | 13 +++++++++++++ - 3 files changed, 20 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 555bb5050aaf8464e209f35c50dc1f5c0295e585..7ef449dcfb206f9ab36d63b04bce9f9694c8c697 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -37,6 +37,7 @@ dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi-pro.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-bcm2708.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 4f9f0ac43f4fe2cb9376fff5a214ffdaf8179591..585f999474ca67155314f2e47d815b081a24d712 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -463,6 +463,12 @@ Params: speed Display SPI bus speed - ledgpio GPIO used to control backlight - - -+Name: i2c-bcm2708 -+Info: Fall back to the i2c_bcm2708 driver for the i2c_arm bus. -+Load: dtoverlay=i2c-bcm2708 -+Params: -+ -+ - Name: i2c-gpio - Info: Adds support for software i2c controller on gpio pins - Load: dtoverlay=i2c-gpio,= -diff --git a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..0afc6b405414c97428278dd3e8836759092aedb5 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts -@@ -0,0 +1,13 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ compatible = "brcm,bcm2708-i2c"; -+ }; -+ }; ++static const struct of_device_id rpi_backlight_of_match[] = { ++ { .compatible = "raspberrypi,rpi-backlight" }, ++ { /* sentinel */ } +}; - -From 4825aaa3b75f9a89acec9cfc3d13eaa0ff1eac4d Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 30 Sep 2016 10:07:27 -0700 -Subject: [PATCH 154/208] clk: bcm2835: Clamp the PLL's requested rate to the - hardware limits. - -Fixes setting low-resolution video modes on HDMI. Now the PLLH_PIX -divider adjusts itself until the PLLH is within bounds. - -Signed-off-by: Eric Anholt -Signed-off-by: Stephen Boyd ---- - drivers/clk/bcm/clk-bcm2835.c | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index cbbc8d4ddcffc797268c0ecb6477005fa14e228b..89645d63af53a3559c4b2e88f9a592fe11f5103f 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -502,8 +502,12 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate, - static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) - { -+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw); -+ const struct bcm2835_pll_data *data = pll->data; - u32 ndiv, fdiv; - -+ rate = clamp(rate, data->min_rate, data->max_rate); ++MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); + - bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv); - - return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1); -@@ -608,13 +612,6 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, - u32 ana[4]; - int i; - -- if (rate < data->min_rate || rate > data->max_rate) { -- dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n", -- clk_hw_get_name(hw), rate, -- data->min_rate, data->max_rate); -- return -EINVAL; -- } -- - if (rate > data->max_fb_rate) { - use_fb_prediv = true; - rate /= 2; - -From 2d17a0acdfe3de2822caab8c0ad00f7ef2b8f4b2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 1 Nov 2016 13:10:05 +0000 -Subject: [PATCH 155/208] config: Add CONFIG_HTU21 module - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 816f832a5f676d905bfae1e06ae8003e38d5cff3..a620bb77fd7934a9977adf3944bb2f3be9d83443 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1148,6 +1148,7 @@ CONFIG_IIO_KFIFO_BUF=m - CONFIG_MCP320X=m - CONFIG_MCP3422=m - CONFIG_DHT11=m -+CONFIG_HTU21=m - CONFIG_PWM_BCM2835=m - CONFIG_PWM_PCA9685=m - CONFIG_RASPBERRYPI_FIRMWARE=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 98b2e5992a45a6212ef9a8b9826431d9fc024169..43fc0a37f8bf2701aac84962203e7219645d5d7b 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1158,6 +1158,7 @@ CONFIG_IIO_KFIFO_BUF=m - CONFIG_MCP320X=m - CONFIG_MCP3422=m - CONFIG_DHT11=m -+CONFIG_HTU21=m - CONFIG_PWM_BCM2835=m - CONFIG_PWM_PCA9685=m - CONFIG_RASPBERRYPI_FIRMWARE=y - -From dc65fdccea2ae766cfa58a888f96072dca195659 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 5 Nov 2016 14:14:43 +0000 -Subject: [PATCH 156/208] bcm2708_fb: Add ioctl for reading gpu memory through - dma - ---- - drivers/video/fbdev/bcm2708_fb.c | 109 +++++++++++++++++++++++++++++++++++++++ - include/uapi/linux/fb.h | 7 +++ - 2 files changed, 116 insertions(+) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 37f60813fe1dd95d9f5f725c07ec2e75c09857bf..a6179186f5a65ebeb99bea34c546f690bb2fd903 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -31,8 +31,10 @@ - #include - #include - #include -+#include - #include - #include -+#include - #include - - //#define BCM2708_FB_DEBUG -@@ -426,6 +428,110 @@ static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info - return result; - } - -+static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, int size) -+{ -+ int burst_size = (fb->dma_chan == 0) ? 8 : 2; -+ struct bcm2708_dma_cb *cb = fb->cb_base; -+ -+ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | -+ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | -+ BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE; -+ cb->dst = dst; -+ cb->src = src; -+ cb->length = size; -+ cb->stride = 0; -+ cb->pad[0] = 0; -+ cb->pad[1] = 0; -+ cb->next = 0; -+ -+ if (size < dma_busy_wait_threshold) { -+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); -+ bcm_dma_wait_idle(fb->dma_chan_base); -+ } else { -+ void __iomem *dma_chan = fb->dma_chan_base; -+ cb->info |= BCM2708_DMA_INT_EN; -+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); -+ while (bcm_dma_is_busy(dma_chan)) { -+ wait_event_interruptible( -+ fb->dma_waitq, -+ !bcm_dma_is_busy(dma_chan)); -+ } -+ fb->stats.dma_irqs++; -+ } -+ fb->stats.dma_copies++; -+} -+ -+#define INTALIAS_NORMAL(x) ((x)&~0xc0000000) // address with no aliases -+#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000) // cache coherent but non-allocating in L1 and L2 -+ -+static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) -+{ -+ struct fb_dmacopy ioparam; -+ size_t size = PAGE_SIZE; -+ u32 *buf = NULL; -+ dma_addr_t bus_addr; -+ long rc = 0; -+ size_t offset; -+ struct { u32 base, length; } gpu = {}; -+ -+ /* restrict this to root user */ -+ if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) -+ { -+ rc = -EFAULT; -+ goto out; -+ } -+ -+ /* Get the parameter data. -+ */ -+ if (copy_from_user -+ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { -+ pr_err("[%s]: failed to copy-from-user\n", -+ __func__); -+ rc = -EFAULT; -+ goto out; -+ } -+ -+ rc = rpi_firmware_property(fb->fw, -+ RPI_FIRMWARE_GET_VC_MEMORY, -+ &gpu, sizeof(gpu)); -+ if (rc != 0 || gpu.base == 0 || gpu.length == 0) { -+ pr_err("[%s]: Unable to determine gpu memory %ld,%x,%x)\n", __func__, rc, gpu.base, gpu.length); -+ return -EFAULT; -+ } -+ -+ if (INTALIAS_NORMAL(ioparam.src) < gpu.base || INTALIAS_NORMAL(ioparam.src) >= gpu.base + gpu.length) { -+ pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__, INTALIAS_NORMAL(ioparam.src), gpu.base, gpu.base + gpu.length); -+ return -EFAULT; -+ } -+ -+ buf = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &bus_addr, -+ GFP_ATOMIC); -+ if (!buf) { -+ pr_err("[%s]: failed to dma_alloc_coherent(%d)\n", -+ __func__, size); -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ for (offset = 0; offset < ioparam.length; offset += size) { -+ size_t remaining = ioparam.length - offset; -+ size_t s = min(size, remaining); -+ unsigned char *p = (unsigned char *)ioparam.src + offset; -+ unsigned char *q = (unsigned char *)ioparam.dst + offset; -+ dma_memcpy(fb, (dma_addr_t)buf, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); -+ if (copy_to_user(q, buf, s) != 0) { -+ pr_err("[%s]: failed to copy-to-user\n", -+ __func__); -+ rc = -EFAULT; -+ goto out; -+ } -+ } -+out: -+ if (buf) -+ dma_free_coherent(NULL, PAGE_ALIGN(size), buf, bus_addr); -+ return rc; -+} -+ - static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) - { - struct bcm2708_fb *fb = to_bcm2708(info); -@@ -438,6 +544,9 @@ static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long a - RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, - &dummy, sizeof(dummy)); - break; -+ case FBIODMACOPY: -+ ret = vc_mem_copy(fb, arg); -+ break; - default: - dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd); - return -ENOTTY; -diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index fa72af0c981710fe80bacf4cf6612f6da19046ee..289e7c03c1e3308d5a02fc783af4a5692e791cfb 100644 ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -39,6 +39,7 @@ - * be concurrently added to the mainline kernel - */ - #define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) -+#define FBIODMACOPY _IOW('z', 0x22, struct fb_dmacopy) - - #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ - #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -@@ -351,6 +352,12 @@ struct fb_copyarea { - __u32 sy; - }; - -+struct fb_dmacopy { -+ dma_addr_t dst; -+ dma_addr_t src; -+ __u32 length; ++static struct platform_driver rpi_backlight_driver = { ++ .driver = { ++ .name = "rpi-backlight", ++ .of_match_table = of_match_ptr(rpi_backlight_of_match), ++ }, ++ .probe = rpi_backlight_probe, +}; + - struct fb_fillrect { - __u32 dx; /* screen-relative */ - __u32 dy; ++module_platform_driver(rpi_backlight_driver); ++ ++MODULE_AUTHOR("Gordon Hollingworth "); ++MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); ++MODULE_LICENSE("GPL"); -From 209d010a894c60b2d1d520b156ee388e7a1fcc9d Mon Sep 17 00:00:00 2001 +From 0d43b57dd46045cd251343c1ad168de2db528c01 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Fri, 11 Nov 2016 19:32:54 +0000 -Subject: [PATCH 157/208] rpi-ft5406: Create coherent buffer and push to - firmware +Date: Tue, 23 Feb 2016 19:56:04 +0000 +Subject: [PATCH 086/111] bcm2835-virtgpio: Virtual GPIO driver +Add a virtual GPIO driver that uses the firmware mailbox interface to +request that the VPU toggles LEDs. --- - drivers/input/touchscreen/rpi-ft5406.c | 152 +++++++++++++++++++---------- + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-bcm-virt.c | 214 +++++++++++++++++++++++++++++ include/soc/bcm2835/raspberrypi-firmware.h | 1 + - 2 files changed, 101 insertions(+), 52 deletions(-) + 4 files changed, 222 insertions(+) + create mode 100644 drivers/gpio/gpio-bcm-virt.c -diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c -index b27dbee8f56773dbd2a5503dc864747d0bebdddc..c5e31978c85a4ffd6839952ce0de50c001c7b875 100644 ---- a/drivers/input/touchscreen/rpi-ft5406.c -+++ b/drivers/input/touchscreen/rpi-ft5406.c -@@ -21,6 +21,7 @@ - #include - #include - #include +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index ed37e5908b910cd51cb378ffc171fe2a9104c082..edcb49f9051b703ce35fd1687a6cef8a31bf3627 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -134,6 +134,12 @@ config GPIO_BCM_KONA + help + Turn on GPIO support for Broadcom "Kona" chips. + ++config GPIO_BCM_VIRT ++ bool "Broadcom Virt GPIO" ++ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) ++ help ++ Turn on virtual GPIO support for Broadcom BCM283X chips. ++ + config GPIO_BRCMSTB + tristate "BRCMSTB GPIO support" + default y if (ARCH_BRCMSTB || BMIPS_GENERIC) +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index d074c2299393dc9cef3456b0068ff2d229677c27..cfb8d4bad6b0b20bed56643b0870fcff311c12c5 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -31,6 +31,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o + obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o + obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o + obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o ++obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o +diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c +new file mode 100644 +index 0000000000000000000000000000000000000000..c3725546def9d4a6264fbb1f6b9814d02b50e34e +--- /dev/null ++++ b/drivers/gpio/gpio-bcm-virt.c +@@ -0,0 +1,214 @@ ++/* ++ * brcmvirt GPIO driver ++ * ++ * Copyright (C) 2012,2013 Dom Cobley ++ * Based on gpio-clps711x.c by Alexander Shiyan ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include +#include - #include - - #define MAXIMUM_SUPPORTED_POINTS 10 -@@ -45,6 +46,7 @@ struct ft5406 { - struct platform_device * pdev; - struct input_dev * input_dev; - void __iomem * ts_base; -+ dma_addr_t bus_addr; - struct ft5406_regs * regs; - struct task_struct * thread; - }; -@@ -117,18 +119,19 @@ static int ft5406_thread(void *arg) - - static int ft5406_probe(struct platform_device *pdev) - { -- int ret; -- struct input_dev * input_dev = input_allocate_device(); ++#include ++ ++#define MODULE_NAME "brcmvirt-gpio" ++#define NUM_GPIO 2 ++ ++struct brcmvirt_gpio { ++ struct gpio_chip gc; ++ u32 __iomem *ts_base; ++ /* two packed 16-bit counts of enabled and disables ++ Allows host to detect a brief enable that was missed */ ++ u32 enables_disables[NUM_GPIO]; ++ dma_addr_t bus_addr; ++}; ++ ++static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return -EINVAL; ++} ++ ++static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return 0; ++} ++ ++static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ unsigned v; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ v = readl(gpio->ts_base + off); ++ return (v >> off) & 1; ++} ++ ++static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ u16 enables, disables; ++ s16 diff; ++ bool lit; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ enables = gpio->enables_disables[off] >> 16; ++ disables = gpio->enables_disables[off] >> 0; ++ diff = (s16)(enables - disables); ++ lit = diff > 0; ++ if ((val && lit) || (!val && !lit)) ++ return; ++ if (val) ++ enables++; ++ else ++ disables++; ++ diff = (s16)(enables - disables); ++ BUG_ON(diff != 0 && diff != 1); ++ gpio->enables_disables[off] = (enables << 16) | (disables << 0); ++ writel(gpio->enables_disables[off], gpio->ts_base + off); ++} ++ ++static int brcmvirt_gpio_probe(struct platform_device *pdev) ++{ + int err = 0; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; - struct ft5406 * ts; - struct device_node *fw_node; - struct rpi_firmware *fw; - u32 touchbuf; - -- dev_info(&pdev->dev, "Probing device\n"); -+ dev_info(dev, "Probing device\n"); - -- fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct brcmvirt_gpio *ucb; ++ u32 gpiovirtbuf; ++ + fw_node = of_parse_phandle(np, "firmware", 0); - if (!fw_node) { -- dev_err(&pdev->dev, "Missing firmware node\n"); ++ if (!fw_node) { + dev_err(dev, "Missing firmware node\n"); - return -ENOENT; - } - -@@ -136,62 +139,88 @@ static int ft5406_probe(struct platform_device *pdev) - if (!fw) - return -EPROBE_DEFER; - -- ret = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, -- &touchbuf, sizeof(touchbuf)); -- if (ret) { -- dev_err(&pdev->dev, "Failed to get touch buffer\n"); -- return ret; -+ ts = devm_kzalloc(dev, sizeof(struct ft5406), GFP_KERNEL); -+ if (!ts) { -+ dev_err(dev, "Failed to allocate memory\n"); -+ return -ENOMEM; - } - -- if (!touchbuf) { -- dev_err(&pdev->dev, "Touchscreen not detected\n"); -- return -ENODEV; -+ ts->input_dev = input_allocate_device(); -+ if (!ts->input_dev) { -+ dev_err(dev, "Failed to allocate input device\n"); -+ return -ENOMEM; - } - -- dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", touchbuf); -+ ts->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->bus_addr, GFP_KERNEL); -+ if (!ts->ts_base) { -+ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", -+ __func__, PAGE_SIZE); -+ err = -ENOMEM; -+ goto out; -+ } - -- ts = kzalloc(sizeof(struct ft5406), GFP_KERNEL); -+ touchbuf = (u32)ts->bus_addr; -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, -+ &touchbuf, sizeof(touchbuf)); - -- if (!ts || !input_dev) { -- ret = -ENOMEM; -- dev_err(&pdev->dev, "Failed to allocate memory\n"); -- return ret; -+ if (err || touchbuf != 0) { -+ dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n", err); -+ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); -+ ts->ts_base = 0; -+ ts->bus_addr = 0; ++ return -ENOENT; + } + -+ if (!ts->ts_base) { -+ dev_warn(dev, "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n", err, touchbuf, ts->ts_base, ts->bus_addr); ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; + -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, -+ &touchbuf, sizeof(touchbuf)); -+ if (err) { -+ dev_err(dev, "Failed to get touch buffer\n"); -+ goto out; -+ } -+ -+ if (!touchbuf) { -+ dev_err(dev, "Touchscreen not detected\n"); -+ err = -ENODEV; -+ goto out; -+ } -+ -+ dev_dbg(dev, "Got TS buffer 0x%x\n", touchbuf); -+ -+ // mmap the physical memory -+ touchbuf &= ~0xc0000000; -+ ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -+ if (ts->ts_base == NULL) -+ { -+ dev_err(dev, "Failed to map physical address\n"); -+ err = -ENOMEM; -+ goto out; -+ } - } -- ts->input_dev = input_dev; - platform_set_drvdata(pdev, ts); - ts->pdev = pdev; - -- input_dev->name = "FT5406 memory based driver"; -+ ts->input_dev->name = "FT5406 memory based driver"; - -- __set_bit(EV_KEY, input_dev->evbit); -- __set_bit(EV_SYN, input_dev->evbit); -- __set_bit(EV_ABS, input_dev->evbit); -+ __set_bit(EV_KEY, ts->input_dev->evbit); -+ __set_bit(EV_SYN, ts->input_dev->evbit); -+ __set_bit(EV_ABS, ts->input_dev->evbit); - -- input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, -+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, - SCREEN_WIDTH, 0, 0); -- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, -+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, - SCREEN_HEIGHT, 0, 0); - -- input_mt_init_slots(input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); -+ input_mt_init_slots(ts->input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); - -- input_set_drvdata(input_dev, ts); -+ input_set_drvdata(ts->input_dev, ts); - -- ret = input_register_device(input_dev); -- if (ret) { -- dev_err(&pdev->dev, "could not register input device, %d\n", -- ret); -- return ret; -- } -- -- // mmap the physical memory -- touchbuf &= ~0xc0000000; -- ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -- if(ts->ts_base == NULL) -- { -- dev_err(&pdev->dev, "Failed to map physical address\n"); -- input_unregister_device(input_dev); -- kzfree(ts); -- return -ENOMEM; -+ err = input_register_device(ts->input_dev); -+ if (err) { -+ dev_err(dev, "could not register input device, %d\n", -+ err); ++ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); ++ if (!ucb) { ++ err = -EINVAL; + goto out; - } - - ts->regs = (struct ft5406_regs *) ts->ts_base; -@@ -200,25 +229,44 @@ static int ft5406_probe(struct platform_device *pdev) - ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); - if(ts->thread == NULL) - { -- dev_err(&pdev->dev, "Failed to create kernel thread"); -- iounmap(ts->ts_base); -- input_unregister_device(input_dev); -- kzfree(ts); -+ dev_err(dev, "Failed to create kernel thread"); -+ err = -ENOMEM; -+ goto out; - } - - return 0; -+ -+out: -+ if (ts->bus_addr) { -+ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); -+ ts->bus_addr = 0; -+ ts->ts_base = NULL; -+ } else if (ts->ts_base) { -+ iounmap(ts->ts_base); -+ ts->ts_base = NULL; + } -+ if (ts->input_dev) { -+ input_unregister_device(ts->input_dev); -+ ts->input_dev = NULL; -+ } -+ return err; - } - - static int ft5406_remove(struct platform_device *pdev) - { -+ struct device *dev = &pdev->dev; - struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev); - -- dev_info(&pdev->dev, "Removing rpi-ft5406\n"); -+ dev_info(dev, "Removing rpi-ft5406\n"); - - kthread_stop(ts->thread); -- iounmap(ts->ts_base); -- input_unregister_device(ts->input_dev); -- kzfree(ts); + -+ if (ts->bus_addr) -+ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); -+ else if (ts->ts_base) -+ iounmap(ts->ts_base); -+ if (ts->input_dev) -+ input_unregister_device(ts->input_dev); - - return 0; - } -diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index 227a107214a02deadcca3db202da265eba1fdd21..b0f6e33bd30c35664ceee057f4c3ad32b914291d 100644 ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -115,6 +115,7 @@ enum rpi_firmware_property_tag { - RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, - RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, - RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, - RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, - RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, - - -From e9817038e0442920814b404514373ea9e7838573 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 9 Nov 2016 22:42:39 +0000 -Subject: [PATCH 158/208] brcmvirt_gpio: Create coherent buffer and push to - firmware - ---- - drivers/gpio/gpio-bcm-virt.c | 89 +++++++++++++++++++++--------- - include/soc/bcm2835/raspberrypi-firmware.h | 1 + - 2 files changed, 63 insertions(+), 27 deletions(-) - -diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c -index f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4..c3725546def9d4a6264fbb1f6b9814d02b50e34e 100644 ---- a/drivers/gpio/gpio-bcm-virt.c -+++ b/drivers/gpio/gpio-bcm-virt.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - - #define MODULE_NAME "brcmvirt-gpio" -@@ -25,6 +26,7 @@ struct brcmvirt_gpio { - /* two packed 16-bit counts of enabled and disables - Allows host to detect a brief enable that was missed */ - u32 enables_disables[NUM_GPIO]; -+ dma_addr_t bus_addr; - }; - - static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) -@@ -75,13 +77,13 @@ static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) - - static int brcmvirt_gpio_probe(struct platform_device *pdev) - { -+ int err = 0; - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct device_node *fw_node; - struct rpi_firmware *fw; - struct brcmvirt_gpio *ucb; - u32 gpiovirtbuf; -- int err = 0; - - fw_node = of_parse_phandle(np, "firmware", 0); - if (!fw_node) { -@@ -93,35 +95,56 @@ static int brcmvirt_gpio_probe(struct platform_device *pdev) - if (!fw) - return -EPROBE_DEFER; - -- err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, -- &gpiovirtbuf, sizeof(gpiovirtbuf)); -- -- if (err) { -- dev_err(dev, "Failed to get gpiovirtbuf\n"); -- goto err; -- } -- -- if (!gpiovirtbuf) { -- dev_err(dev, "No virtgpio buffer\n"); -- err = -ENOENT; -- goto err; -- } -- - ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); - if (!ucb) { - err = -EINVAL; -- goto err; -+ goto out; - } - -- // mmap the physical memory -- gpiovirtbuf &= ~0xc0000000; -- ucb->ts_base = ioremap(gpiovirtbuf, 4096); -- if (ucb->ts_base == NULL) { -- dev_err(dev, "Failed to map physical address\n"); -- err = -ENOENT; -- goto err; + ucb->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ucb->bus_addr, GFP_KERNEL); + if (!ucb->ts_base) { + pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", + __func__, PAGE_SIZE); + err = -ENOMEM; + goto out; - } - ++ } ++ + gpiovirtbuf = (u32)ucb->bus_addr; + err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF, + &gpiovirtbuf, sizeof(gpiovirtbuf)); @@ -146408,19 +118119,25 @@ index f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4..c3725546def9d4a6264fbb1f6b9814d0 + } + ucb->bus_addr = 0; + } - ucb->gc.label = MODULE_NAME; - ucb->gc.owner = THIS_MODULE; - //ucb->gc.dev = dev; -@@ -137,22 +160,34 @@ static int brcmvirt_gpio_probe(struct platform_device *pdev) - - err = gpiochip_add(&ucb->gc); - if (err) -- goto err; ++ ucb->gc.label = MODULE_NAME; ++ ucb->gc.owner = THIS_MODULE; ++ //ucb->gc.dev = dev; ++ ucb->gc.of_node = np; ++ ucb->gc.base = 100; ++ ucb->gc.ngpio = NUM_GPIO; ++ ++ ucb->gc.direction_input = brcmvirt_gpio_dir_in; ++ ucb->gc.direction_output = brcmvirt_gpio_dir_out; ++ ucb->gc.get = brcmvirt_gpio_get; ++ ucb->gc.set = brcmvirt_gpio_set; ++ ucb->gc.can_sleep = true; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) + goto out; - - platform_set_drvdata(pdev, ucb); - --err: ++ ++ platform_set_drvdata(pdev, ucb); ++ + return 0; +out: + if (ucb->bus_addr) { @@ -146431,25 +118148,44 @@ index f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4..c3725546def9d4a6264fbb1f6b9814d0 + iounmap(ucb->ts_base); + ucb->ts_base = NULL; + } - return err; -- - } - - static int brcmvirt_gpio_remove(struct platform_device *pdev) - { ++ return err; ++} ++ ++static int brcmvirt_gpio_remove(struct platform_device *pdev) ++{ + struct device *dev = &pdev->dev; - int err = 0; - struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); - - gpiochip_remove(&ucb->gc); -- iounmap(ucb->ts_base); ++ int err = 0; ++ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&ucb->gc); + if (ucb->bus_addr) + dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); + else if (ucb->ts_base) + iounmap(ucb->ts_base); - return err; - } - ++ return err; ++} ++ ++static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { ++ { .compatible = "brcm,bcm2835-virtgpio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); ++ ++static struct platform_driver brcmvirt_gpio_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), ++ }, ++ .probe = brcmvirt_gpio_probe, ++ .remove = brcmvirt_gpio_remove, ++}; ++module_platform_driver(brcmvirt_gpio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Dom Cobley "); ++MODULE_DESCRIPTION("brcmvirt GPIO driver"); ++MODULE_ALIAS("platform:brcmvirt-gpio"); diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h index b0f6e33bd30c35664ceee057f4c3ad32b914291d..e92278968b2b979db2a1f855f70e7aafb224fa98 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h @@ -146463,1369 +118199,5261 @@ index b0f6e33bd30c35664ceee057f4c3ad32b914291d..e92278968b2b979db2a1f855f70e7aaf RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, -From 1dff7d0212f9ac143489397d6da93253d8c79efa Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 14 Nov 2016 22:05:30 +0000 -Subject: [PATCH 159/208] fixup: fb: Use basic types for dma addresses as these - are also included from user code - ---- - include/uapi/linux/fb.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index 289e7c03c1e3308d5a02fc783af4a5692e791cfb..703fa8a70574323abe2fb32599254582cd5d891f 100644 ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -353,8 +353,8 @@ struct fb_copyarea { - }; - - struct fb_dmacopy { -- dma_addr_t dst; -- dma_addr_t src; -+ void *dst; -+ __u32 src; - __u32 length; - }; - - -From 5a82ccf30428b49333f0fcc3ca1729c97cb71592 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 12 Nov 2016 20:28:25 +0100 -Subject: [PATCH 160/208] BCM270x_DT: Drop using ARCH_BCM2708 and ARCH_BCM2709 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Both are based on ARCH_BCM2835 so use that instead. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 25 ++--- - arch/arm/boot/dts/overlays/Makefile | 199 +++++++++++++++++------------------- - 2 files changed, 101 insertions(+), 123 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 0cb86b7a5ab212fee36a34b3672856d27c446593..d59b0f01cdbd7ebe1d660701f47353746faeded6 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -1,23 +1,14 @@ - ifeq ($(CONFIG_OF),y) - --dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b.dtb --dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-b-plus.dtb --dtb-$(CONFIG_ARCH_BCM2708) += bcm2708-rpi-cm.dtb --dtb-$(CONFIG_ARCH_BCM2709) += bcm2709-rpi-2-b.dtb --dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb --dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb -+dtb-$(CONFIG_ARCH_BCM2835) += \ -+ bcm2708-rpi-b.dtb \ -+ bcm2708-rpi-b-plus.dtb \ -+ bcm2708-rpi-cm.dtb \ -+ bcm2709-rpi-2-b.dtb \ -+ bcm2710-rpi-3-b.dtb \ -+ bcm2710-rpi-cm3.dtb - --# Raspberry Pi --ifeq ($(CONFIG_ARCH_BCM2708),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(CONFIG_ARCH_BCM2709),y) -- RPI_DT_OVERLAYS=y --endif - ifeq ($(CONFIG_ARCH_BCM2835),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(RPI_DT_OVERLAYS),y) - dts-dirs += overlays - endif - -@@ -954,6 +945,6 @@ subdir-y := $(dts-dirs) - clean-files := *.dtb - - # Enable fixups to support overlays on BCM2708 platforms --ifeq ($(RPI_DT_OVERLAYS),y) -+ifeq ($(CONFIG_ARCH_BCM2835),y) - DTC_FLAGS ?= -@ -H epapr - endif -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 7ef449dcfb206f9ab36d63b04bce9f9694c8c697..c940eb3b685d7b9af4340ff184ca736471183e09 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -1,114 +1,101 @@ --ifeq ($(CONFIG_OF),y) -- - # Overlays for the Raspberry Pi platform - --ifeq ($(CONFIG_ARCH_BCM2708),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(CONFIG_ARCH_BCM2709),y) -- RPI_DT_OVERLAYS=y --endif --ifeq ($(CONFIG_ARCH_BCM2835),y) -- RPI_DT_OVERLAYS=y --endif -- --dtbo-$(RPI_DT_OVERLAYS) += adau1977-adc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += ads1015.dtbo --dtbo-$(RPI_DT_OVERLAYS) += ads7846.dtbo --dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo --dtbo-$(RPI_DT_OVERLAYS) += allo-piano-dac-pcm512x-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo --dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += audremap.dtbo --dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dionaudio-loco.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dpi18.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo --dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo --dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo --dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-amp.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacplus.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi-pro.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo --dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-bcm2708.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo --dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo --dtbo-$(RPI_DT_OVERLAYS) += iqaudio-digi-wm8804-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp23s17.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += mz61581.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pi3-act-led.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pi3-disable-bt.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pi3-miniuart-bt.dtbo --dtbo-$(RPI_DT_OVERLAYS) += piscreen.dtbo --dtbo-$(RPI_DT_OVERLAYS) += piscreen2r.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pisound.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft22.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft28-capacitive.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft28-resistive.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pitft35-resistive.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pps-gpio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pwm.dtbo --dtbo-$(RPI_DT_OVERLAYS) += pwm-2chan.dtbo --dtbo-$(RPI_DT_OVERLAYS) += qca7000.dtbo --dtbo-$(RPI_DT_OVERLAYS) += raspidac3.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-backlight.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-dac.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-display.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-ft5406.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-proto.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rpi-sense.dtbo --dtbo-$(RPI_DT_OVERLAYS) += rra-digidac1-wm8741-audio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sc16is750-i2c.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sc16is752-spi1.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo --dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi0-hw-cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo --dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo --dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo --dtbo-$(RPI_DT_OVERLAYS) += vga666.dtbo --dtbo-$(RPI_DT_OVERLAYS) += w1-gpio.dtbo --dtbo-$(RPI_DT_OVERLAYS) += w1-gpio-pullup.dtbo --dtbo-$(RPI_DT_OVERLAYS) += wittypi.dtbo -+dtbo-$(CONFIG_ARCH_BCM2835) += \ -+ adau1977-adc.dtbo \ -+ ads1015.dtbo \ -+ ads7846.dtbo \ -+ akkordion-iqdacplus.dtbo \ -+ allo-piano-dac-pcm512x-audio.dtbo \ -+ at86rf233.dtbo \ -+ audioinjector-wm8731-audio.dtbo \ -+ audremap.dtbo \ -+ bmp085_i2c-sensor.dtbo \ -+ dht11.dtbo \ -+ dionaudio-loco.dtbo \ -+ dpi18.dtbo \ -+ dpi24.dtbo \ -+ dwc-otg.dtbo \ -+ dwc2.dtbo \ -+ enc28j60.dtbo \ -+ gpio-ir.dtbo \ -+ gpio-poweroff.dtbo \ -+ hifiberry-amp.dtbo \ -+ hifiberry-dac.dtbo \ -+ hifiberry-dacplus.dtbo \ -+ hifiberry-digi.dtbo \ -+ hifiberry-digi-pro.dtbo \ -+ hy28a.dtbo \ -+ hy28b.dtbo \ -+ i2c-bcm2708.dtbo \ -+ i2c-gpio.dtbo \ -+ i2c-mux.dtbo \ -+ i2c-pwm-pca9685a.dtbo \ -+ i2c-rtc.dtbo \ -+ i2c0-bcm2708.dtbo \ -+ i2c1-bcm2708.dtbo \ -+ i2s-gpio28-31.dtbo \ -+ iqaudio-dac.dtbo \ -+ iqaudio-dacplus.dtbo \ -+ iqaudio-digi-wm8804-audio.dtbo \ -+ justboom-dac.dtbo \ -+ justboom-digi.dtbo \ -+ lirc-rpi.dtbo \ -+ mcp23017.dtbo \ -+ mcp23s17.dtbo \ -+ mcp2515-can0.dtbo \ -+ mcp2515-can1.dtbo \ -+ mmc.dtbo \ -+ mz61581.dtbo \ -+ pi3-act-led.dtbo \ -+ pi3-disable-bt.dtbo \ -+ pi3-miniuart-bt.dtbo \ -+ piscreen.dtbo \ -+ piscreen2r.dtbo \ -+ pisound.dtbo \ -+ pitft22.dtbo \ -+ pitft28-capacitive.dtbo \ -+ pitft28-resistive.dtbo \ -+ pitft35-resistive.dtbo \ -+ pps-gpio.dtbo \ -+ pwm.dtbo \ -+ pwm-2chan.dtbo \ -+ qca7000.dtbo \ -+ raspidac3.dtbo \ -+ rpi-backlight.dtbo \ -+ rpi-dac.dtbo \ -+ rpi-display.dtbo \ -+ rpi-ft5406.dtbo \ -+ rpi-proto.dtbo \ -+ rpi-sense.dtbo \ -+ rra-digidac1-wm8741-audio.dtbo \ -+ sc16is750-i2c.dtbo \ -+ sc16is752-spi1.dtbo \ -+ sdhost.dtbo \ -+ sdio.dtbo \ -+ sdio-1bit.dtbo \ -+ sdtweak.dtbo \ -+ smi.dtbo \ -+ smi-dev.dtbo \ -+ smi-nand.dtbo \ -+ spi-gpio35-39.dtbo \ -+ spi-rtc.dtbo \ -+ spi0-hw-cs.dtbo \ -+ spi1-1cs.dtbo \ -+ spi1-2cs.dtbo \ -+ spi1-3cs.dtbo \ -+ spi2-1cs.dtbo \ -+ spi2-2cs.dtbo \ -+ spi2-3cs.dtbo \ -+ tinylcd35.dtbo \ -+ uart1.dtbo \ -+ vc4-kms-v3d.dtbo \ -+ vga666.dtbo \ -+ w1-gpio.dtbo \ -+ w1-gpio-pullup.dtbo \ -+ wittypi.dtbo - - targets += dtbs dtbs_install - targets += $(dtbo-y) - --endif -- - always := $(dtbo-y) - clean-files := *.dtbo - -From 1c930dafefdf565e34d8e8246702c5dbcbcd6f84 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 12 Nov 2016 20:28:47 +0100 -Subject: [PATCH 161/208] Drop ARCH_BCM2708 and ARCH_BCM2709 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -They are not necessary anymore since both are based on ARCH_BCM2835. -Also use the compatible strings "brcm,bcm2835", "brcm,bcm2836" and "brcm,bcm2837". - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 - - arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 - - arch/arm/boot/dts/bcm2708.dtsi | 3 --- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 - - arch/arm/boot/dts/bcm2709.dtsi | 3 --- - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 1 - - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 1 - - arch/arm/boot/dts/bcm2710.dtsi | 4 ++-- - arch/arm/configs/bcm2709_defconfig | 2 +- - arch/arm/configs/bcmrpi_defconfig | 2 +- - arch/arm/mach-bcm/Kconfig | 19 ++----------------- - arch/arm/mach-bcm/board_bcm2835.c | 28 ---------------------------- - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 4 ++-- - 13 files changed, 8 insertions(+), 62 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 6bd8df44dc9163589074c1dec8a3ec69a47fb458..360da5c928dc5599b0d2a9055728087604c6b189 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -3,7 +3,6 @@ - #include "bcm2708.dtsi" - - / { -- compatible = "brcm,bcm2708"; - model = "Raspberry Pi Model B+"; - }; - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index ba80832726004b1b0719f570a7d8b3a390344d56..9c49659ab246bce0656f3514f3b924bc4826b421 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -3,7 +3,6 @@ - #include "bcm2708.dtsi" - - / { -- compatible = "brcm,bcm2708"; - model = "Raspberry Pi Model B"; - }; - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 663843965027da5dbaefbec1285e275c56746367..0f72bd90c591a2e8752d7437fa7e8c6308bd8c3f 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -3,9 +3,6 @@ - #include "bcm2708-rpi.dtsi" - - / { -- compatible = "brcm,bcm2708"; -- model = "BCM2708"; -- - soc { - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 4f79aaae149abc6f8ebc076d493eb8459e469862..19c83823420fc3cc20a01d07091100cb8720ff4d 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -3,7 +3,6 @@ - #include "bcm2709.dtsi" - - / { -- compatible = "brcm,bcm2709"; - model = "Raspberry Pi 2 Model B"; - }; - -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index b1d82f9026d02e8b5371cbb4d8a144e67207a276..343437db94820bb75a9b81e8bc6ecf6f31d9f04c 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -3,9 +3,6 @@ - #include "bcm2708-rpi.dtsi" - - / { -- compatible = "brcm,bcm2709"; -- model = "BCM2709"; -- - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, - <0x40000000 0x40000000 0x00040000>; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index 30060663ca712578f6d697fd02a3b31d94301707..cb1694da24b54d4024109fc481aa67f73e15e31f 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -7,7 +7,6 @@ - #include "bcm2710.dtsi" - - / { -- compatible = "brcm,bcm2710","brcm,bcm2709"; - model = "Raspberry Pi 3 Model B"; - }; - -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index d13e3d4dac4e198c8cac451e3f64ef687e2ace1b..41874c25a84226c0e4af92ec4059e0a571fe6123 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -3,7 +3,6 @@ - #include "bcm2710.dtsi" - - / { -- compatible = "brcm,bcm2710","brcm,bcm2709"; - model = "Raspberry Pi Compute Module 3"; - }; - -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index df1a4ce1cd4e570876b7785b357d6c31f66191a4..f6def5d7e5d622cf09e8f87332c7374fe28da08b 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -3,8 +3,8 @@ - #include "bcm2708-rpi.dtsi" - - / { -- compatible = "brcm,bcm2710","brcm,bcm2709"; -- model = "BCM2710"; -+ compatible = "brcm,bcm2837", "brcm,bcm2836"; -+ model = "BCM2837"; - - soc { - ranges = <0x7e000000 0x3f000000 0x01000000>, -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index a620bb77fd7934a9977adf3944bb2f3be9d83443..5b7d6177c69eec697a7db2c356263f7770938bd7 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -38,7 +38,7 @@ CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_BCM=y --CONFIG_ARCH_BCM2709=y -+CONFIG_ARCH_BCM2835=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_SMP=y - CONFIG_VMSPLIT_2G=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 43fc0a37f8bf2701aac84962203e7219645d5d7b..1834f3070bcde9dee21482483e95b9313fad6fc4 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -39,7 +39,7 @@ CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_MULTI_V6=y - # CONFIG_ARCH_MULTI_V7 is not set - CONFIG_ARCH_BCM=y --CONFIG_ARCH_BCM2708=y -+CONFIG_ARCH_BCM2835=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y -diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 929a5fa241fa94134993c61a137d1f79b514d64b..3968816e0ee07b813d30ca4bbdbe3f21ea97224e 100644 ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -156,33 +156,18 @@ config ARCH_BCM2835 - select FIQ - select PINCTRL - select PINCTRL_BCM2835 -+ select MFD_SYSCON if ARCH_MULTI_V7 - help - This enables support for the Broadcom BCM2835 and BCM2836 SoCs. - This SoC is used in the Raspberry Pi and Roku 2 devices. - - config MACH_BCM2708 - bool "Enable optimized __copy_to_user and __copy_from_user" -- depends on ARCH_BCM2708 -+ depends on ARCH_BCM2835 && ARCH_MULTI_V6 - default y - help - Optimized versions of __copy_to_user and __copy_from_user for Pi1. - --config ARCH_BCM2708 -- bool "Broadcom BCM2708 family" -- depends on ARCH_MULTI_V6 -- select ARCH_BCM2835 -- help -- This enables support for Broadcom BCM2708 boards. -- --config ARCH_BCM2709 -- bool "Broadcom BCM2709 family" -- depends on ARCH_MULTI_V7 -- select ARCH_BCM2835 -- select HAVE_SMP -- select MFD_SYSCON -- help -- This enables support for Broadcom BCM2709 boards. -- - config ARCH_BCM_63XX - bool "Broadcom BCM63xx DSL SoC" - depends on ARCH_MULTI_V7 -diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index efbd18020479c1cab40ce680446a4259c62c83cb..133338f0a21237fda9b7660d2c57a33b991f08ae 100644 ---- a/arch/arm/mach-bcm/board_bcm2835.c -+++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -66,31 +66,3 @@ DT_MACHINE_START(BCM2835, "BCM2835") - .init_early = bcm2835_init_early, - .dt_compat = bcm2835_compat - MACHINE_END -- --#ifdef CONFIG_ARCH_BCM2708 --static const char * const bcm2708_compat[] = { -- "brcm,bcm2708", -- NULL --}; -- --DT_MACHINE_START(BCM2708, "BCM2708") -- .init_machine = bcm2835_init, -- .reserve = bcm2835_board_reserve, -- .init_early = bcm2835_init_early, -- .dt_compat = bcm2708_compat, --MACHINE_END --#endif -- --#ifdef CONFIG_ARCH_BCM2709 --static const char * const bcm2709_compat[] = { -- "brcm,bcm2709", -- NULL --}; -- --DT_MACHINE_START(BCM2709, "BCM2709") -- .init_machine = bcm2835_init, -- .reserve = bcm2835_board_reserve, -- .init_early = bcm2835_init_early, -- .dt_compat = bcm2709_compat, --MACHINE_END --#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -index 85d82f31cb49631f03b23631882d2b6c063b33db..13047c08fb71cc6e44c66096720d4654d3f9e4e1 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -@@ -78,7 +78,7 @@ void notrace _fiq_print(enum fiq_debug_level dbg_lvl, volatile struct fiq_state - * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock - * Must be called with local interrupts and FIQ disabled. - */ --#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) -+#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) - inline void fiq_fsm_spin_lock(fiq_lock_t *lock) - { - unsigned long tmp; -@@ -111,7 +111,7 @@ inline void fiq_fsm_spin_lock(fiq_lock_t *lock) { } - /** - * fiq_fsm_spin_unlock() - ARMv6+ bare bones spinunlock - */ --#if defined(CONFIG_ARCH_BCM2709) && defined(CONFIG_SMP) -+#if defined(CONFIG_ARCH_BCM2835) && defined(CONFIG_SMP) - inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) - { - smp_mb(); - -From 947658a7a79e668f6421a94226e0a39dbbe3abe5 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 15 Nov 2016 15:58:49 +0000 -Subject: [PATCH 162/208] mkknlimg: Retain downstream-kernel detection - -With the death of ARCH_BCM2708 and ARCH_BCM2709, a new way is needed to -determine if this is a "downstream" build that wants the firmware to -load a bcm27xx .dtb. The vc_cma driver is used downstream but not -upstream, making vc_cma_init a suitable predicate symbol. ---- - scripts/mkknlimg | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -index a21f7e31bc904233e980e66ae3e6337e2eab0f1c..60206de7fa9a49bd027c635306674a29a568652f 100755 ---- a/scripts/mkknlimg -+++ b/scripts/mkknlimg -@@ -78,6 +78,7 @@ my $wanted_strings = - 'brcm,bcm2835' => FLAG_PI | FLAG_DTOK | FLAG_283X, - 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, - 'of_cfs_init' => FLAG_DTOK | FLAG_DDTK, -+ 'vc_cma_init' => FLAG_PI | FLAG_270X, - }; - - my $res = try_extract($kernel_file, $tmpfile1); - -From a30274434c39f55c32b179a06fbb57e3d3990294 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 16 Nov 2016 21:17:27 +0000 -Subject: [PATCH 163/208] fixup: fb: Use correct bus address for dest of dma - memcpy - ---- - drivers/video/fbdev/bcm2708_fb.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index a6179186f5a65ebeb99bea34c546f690bb2fd903..0d22e00a0adf2959f94b2f0897888c127062e8d5 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -435,7 +435,7 @@ static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, in - - cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | - BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | -- BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE; -+ BCM2708_DMA_D_INC; - cb->dst = dst; - cb->src = src; - cb->length = size; -@@ -518,7 +518,7 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) - size_t s = min(size, remaining); - unsigned char *p = (unsigned char *)ioparam.src + offset; - unsigned char *q = (unsigned char *)ioparam.dst + offset; -- dma_memcpy(fb, (dma_addr_t)buf, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); -+ dma_memcpy(fb, bus_addr, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); - if (copy_to_user(q, buf, s) != 0) { - pr_err("[%s]: failed to copy-to-user\n", - __func__); - -From b000467a6ec25d6e512ade86b384074608c6289f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 17 Nov 2016 16:49:33 +0000 -Subject: [PATCH 164/208] fixup: fb: Use struct device for dma_alloc_coherent - ---- - drivers/video/fbdev/bcm2708_fb.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 0d22e00a0adf2959f94b2f0897888c127062e8d5..53c5a0bdadb4be9251affdabed66305842a08e72 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -504,7 +504,7 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) - return -EFAULT; - } - -- buf = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &bus_addr, -+ buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr, - GFP_ATOMIC); - if (!buf) { - pr_err("[%s]: failed to dma_alloc_coherent(%d)\n", -@@ -528,7 +528,7 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg) - } - out: - if (buf) -- dma_free_coherent(NULL, PAGE_ALIGN(size), buf, bus_addr); -+ dma_free_coherent(fb->fb.device, PAGE_ALIGN(size), buf, bus_addr); - return rc; - } - - -From 805037ddae8a2857a35e5afa5635bcb77fb3534c Mon Sep 17 00:00:00 2001 +From 6e12f2b19d43ee028bfa2a9118585e65bec5c450 Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Fri, 18 Nov 2016 10:52:49 +0000 -Subject: [PATCH 165/208] ARM: dts: Visit overlays subdir unconditionally +Date: Tue, 23 Feb 2016 17:26:48 +0000 +Subject: [PATCH 087/111] amba_pl011: Don't use DT aliases for numbering -make clean processing occurs without loading the configuration, so the -overlays subdir must be added unconditionally. - -See: https://github.com/raspberrypi/linux/issues/1723 +The pl011 driver looks for DT aliases of the form "serial", +and if found uses as the device ID. This can cause +/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the +other serial port is provided by the 8250 driver which doesn't +use the same logic. --- - arch/arm/boot/dts/Makefile | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index d59b0f01cdbd7ebe1d660701f47353746faeded6..c8d3d5ac5b49b4bf2b2fb16078f1c5d56c75ac65 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -8,10 +8,6 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ - bcm2710-rpi-3-b.dtb \ - bcm2710-rpi-cm3.dtb - --ifeq ($(CONFIG_ARCH_BCM2835),y) -- dts-dirs += overlays --endif -- - dtb-$(CONFIG_ARCH_ALPINE) += \ - alpine-db.dtb - dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -941,7 +937,7 @@ dtstree := $(srctree)/$(src) - dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) - - always := $(dtb-y) --subdir-y := $(dts-dirs) -+subdir-y := $(dts-dirs) overlays - clean-files := *.dtb - - # Enable fixups to support overlays on BCM2708 platforms - -From 858b913571ad2b5a9b9f3f91c074b3255a3d18f0 Mon Sep 17 00:00:00 2001 -From: Matt Flax -Date: Sun, 20 Nov 2016 19:15:24 +1100 -Subject: [PATCH 166/208] [Audioinjector] Fix bit offsets for equal volume and - add 8 kHz operation (#1727) - -Applying to the audioinjector sound card only. This patch offsets channel -2 correctly from the LR clock. This ensures that channel 2 doesn't loose -any bits during capture. It also results in both channels 1 and 2 having -the same volume. This commit also adds 8 kHz operation. - -Signed-off-by: Matt Flax ---- - sound/soc/bcm/audioinjector-pi-soundcard.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c -index 5ff0985e07efb96b95634a65995f09f7c68d9e99..ef54e0f07ea03f59e9957b5d98f3e7fdc998e469 100644 ---- a/sound/soc/bcm/audioinjector-pi-soundcard.c -+++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -30,7 +30,7 @@ - #include "../codecs/wm8731.h" - - static const unsigned int bcm2835_rates_12000000[] = { -- 32000, 44100, 48000, 96000, 88200, -+ 8000, 16000, 32000, 44100, 48000, 96000, 88200, - }; - - static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { -@@ -55,19 +55,21 @@ static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *su - - switch (params_rate(params)){ - case 8000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1); -+ case 16000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 750); - case 32000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 375); - case 44100: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 272); - case 48000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 250); - case 88200: - return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); - case 96000: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); - default: -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); - } - } - - -From 3f01663c3ec2c0ae2a82a46b9484c5726052c295 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Sat, 26 Nov 2016 14:01:52 +0000 -Subject: [PATCH 167/208] ARM: dts: Restore dtbs_install functionality - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/Makefile | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index c8d3d5ac5b49b4bf2b2fb16078f1c5d56c75ac65..950714000b98cf92e60a72d8dde4774a8ef55429 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -937,10 +937,11 @@ dtstree := $(srctree)/$(src) - dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) - - always := $(dtb-y) --subdir-y := $(dts-dirs) overlays -+subdir-y := overlays - clean-files := *.dtb - --# Enable fixups to support overlays on BCM2708 platforms -+# Enable fixups to support overlays on BCM2835 platforms - ifeq ($(CONFIG_ARCH_BCM2835),y) - DTC_FLAGS ?= -@ -H epapr -+ dts-dirs += overlays - endif - -From 8569d7041b8778339e0a4cc6bf49aaf3c1dc4887 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 23 Nov 2016 14:19:40 +0000 -Subject: [PATCH 168/208] config: Add ABX80X RTC driver and overlay - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/README | 12 ++++++++++-- - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 12 +++++++++++- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 4 files changed, 23 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 585f999474ca67155314f2e47d815b081a24d712..180122b381361469ca9e8c4e14f4aa52c1f351dd 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -504,7 +504,11 @@ Params: addr I2C address of PCA9685A (default 0x40) - Name: i2c-rtc - Info: Adds support for a number of I2C Real Time Clock devices - Load: dtoverlay=i2c-rtc,= --Params: ds1307 Select the DS1307 device -+Params: abx80x Select one of the ABx80x family: -+ AB0801, AB0803, AB0804, AB0805, -+ AB1801, AB1803, AB1804, AB1805 -+ -+ ds1307 Select the DS1307 device - - ds1339 Select the DS1339 device - -@@ -520,7 +524,11 @@ Params: ds1307 Select the DS1307 device - - pcf8563 Select the PCF8563 device - -- trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) -+ trickle-diode-type Diode type for trickle charge - "standard" or -+ "schottky" (ABx80x only) -+ -+ trickle-resistor-ohms Resistor value for trickle charge (DS1339, -+ ABx80x) - - wakeup-source Specify that the RTC can be used as a wakeup - source -diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -index 8b6f978155c02409eeb7c83353b8194fa3462435..1efcf0b712c9c5c19210545002ac1f0931db58f5 100644 ---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -12,6 +12,13 @@ - #size-cells = <0>; - status = "okay"; - -+ abx80x: abx80x@69 { -+ compatible = "abracon,abx80x"; -+ reg = <0x69>; -+ abracon,tc-diode = "standard"; -+ abracon,tc-resistor = <0>; -+ status = "disable"; -+ }; - ds1307: ds1307@68 { - compatible = "maxim,ds1307"; - reg = <0x68>; -@@ -56,6 +63,7 @@ - }; - }; - __overrides__ { -+ abx80x = <&abx80x>,"status"; - ds1307 = <&ds1307>,"status"; - ds1339 = <&ds1339>,"status"; - ds3231 = <&ds3231>,"status"; -@@ -64,7 +72,9 @@ - pcf2127 = <&pcf2127>,"status"; - pcf8523 = <&pcf8523>,"status"; - pcf8563 = <&pcf8563>,"status"; -- trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; -+ trickle-diode-type = <&abx80x>,"abracon,tc-diode"; -+ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0", -+ <&abx80x>,"abracon,tc-resistor"; - wakeup-source = <&ds1339>,"wakeup-source?", - <&ds3231>,"wakeup-source?", - <&mcp7940x>,"wakeup-source?", -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 5b7d6177c69eec697a7db2c356263f7770938bd7..10b32a493f244521e6b3a17d54da192e7006db28 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1054,6 +1054,7 @@ CONFIG_LEDS_TRIGGER_INPUT=y - CONFIG_LEDS_TRIGGER_PANIC=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_ABX80X=m - CONFIG_RTC_DRV_DS1307=m - CONFIG_RTC_DRV_DS1374=m - CONFIG_RTC_DRV_DS1672=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 1834f3070bcde9dee21482483e95b9313fad6fc4..2979c31c583cba95096ce449ebc0ccdfa417b838 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1064,6 +1064,7 @@ CONFIG_LEDS_TRIGGER_INPUT=y - CONFIG_LEDS_TRIGGER_PANIC=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_ABX80X=m - CONFIG_RTC_DRV_DS1307=m - CONFIG_RTC_DRV_DS1374=m - CONFIG_RTC_DRV_DS1672=m - -From 17fa71aa67409771c6e323c905d6f07a49c0265b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 25 Nov 2016 15:01:15 +0000 -Subject: [PATCH 169/208] config: Add AK4554 audio codec driver - -See: https://github.com/raspberrypi/linux/issues/1730 - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 10b32a493f244521e6b3a17d54da192e7006db28..48ed6bfe263a6a3fab942d0b52b2f409055f23ad 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -876,6 +876,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 2979c31c583cba95096ce449ebc0ccdfa417b838..ff69cafd7fb706fc0069d59c37974c4ce5d50043 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -871,6 +871,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m - -From d93ed366eb57a05214b58910e6ee763d7bb16bb9 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson <6by9@users.noreply.github.com> -Date: Wed, 30 Nov 2016 20:17:14 +0000 -Subject: [PATCH 170/208] BCM2835-v4l2: Fix a conformance test failure - -Format ioctls: - test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK - warn: v4l2-test-formats.cpp(1195): S_PARM is supported but - doesn't report V4L2_CAP_TIMEPERFRAME. - fail: v4l2-test-formats.cpp(1118): node->has_frmintervals - && !cap->capability ---- - drivers/media/platform/bcm2835/bcm2835-camera.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index cb5bab642eaab2f60d641801dd0afdac45b7698f..4f03949aecf3afbf2e04df38289447195a8847a6 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -1399,6 +1399,7 @@ static int vidioc_s_parm(struct file *file, void *priv, - dev->capture.timeperframe = tpf; - parm->parm.capture.timeperframe = tpf; - parm->parm.capture.readbuffers = 1; -+ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - - fps_param.num = 0; /* Select variable fps, and then use - * FPS_RANGE to select the actual limits. - -From 1b81b02455bce965fbd642bce2eea1370b9461e2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 1 Dec 2016 15:32:23 +0000 -Subject: [PATCH 171/208] hifiberry: Make driver names unique in first 15 - characters - -See: LibreELEC PR1001 ---- - sound/soc/bcm/hifiberry_amp.c | 1 + - sound/soc/bcm/hifiberry_dac.c | 1 + - sound/soc/bcm/hifiberry_dacplus.c | 1 + - sound/soc/bcm/hifiberry_digi.c | 1 + - 4 files changed, 4 insertions(+) - -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -index 0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1..d17c29780507dc31c50f1d567ff5cea7c8241ff5 100644 ---- a/sound/soc/bcm/hifiberry_amp.c -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -61,6 +61,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { - - static struct snd_soc_card snd_rpi_hifiberry_amp = { - .name = "snd_rpi_hifiberry_amp", -+ .driver_name = "HifiberryAmp", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_amp_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -index 29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8..45f2b770ad9e67728ca599a7445d6ae9a01c0c29 100644 ---- a/sound/soc/bcm/hifiberry_dac.c -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -63,6 +63,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_hifiberry_dac = { - .name = "snd_rpi_hifiberry_dac", -+ .driver_name = "HifiberryDac", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_dac_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -index 65600674c286e8a7be8efd352d5a80889221a1d6..bdc35e7e6bc12dc1cf04f5ffad8f9ab49a0b0266 100644 ---- a/sound/soc/bcm/hifiberry_dacplus.c -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -291,6 +291,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_hifiberry_dacplus = { - .name = "snd_rpi_hifiberry_dacplus", -+ .driver_name = "HifiberryDacp", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_dacplus_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 52ab9dea2e724c4238986ca53c59c8492f64e345..19dc953b7227ba86123fc7a2ba654499e0c581c5 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -202,6 +202,7 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_hifiberry_digi = { - .name = "snd_rpi_hifiberry_digi", -+ .driver_name = "HifiberryDigi", - .owner = THIS_MODULE, - .dai_link = snd_rpi_hifiberry_digi_dai, - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), - -From c0c3bcda197b84fefc31ea5ef4a3c4c71d61d6cf Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 1 Dec 2016 22:58:07 +0000 -Subject: [PATCH 172/208] BCM2835 DT: Add DTC_FLAGS to support overlays - -Signed-off-by: Phil Elwell ---- - arch/arm64/boot/dts/broadcom/Makefile | 5 +++++ + drivers/tty/serial/amba-pl011.c | 5 +++++ 1 file changed, 5 insertions(+) -diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index 2152448c8cf5b22c573642d7ce45e85793f5fc9a..d6a4c2fccf68e4c692973e36b749e3571979ee5e 100644 ---- a/arch/arm64/boot/dts/broadcom/Makefile -+++ b/arch/arm64/boot/dts/broadcom/Makefile -@@ -6,3 +6,8 @@ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb - always := $(dtb-y) - subdir-y := $(dts-dirs) - clean-files := *.dtb -+ -+# Enable fixups to support overlays on BCM2835 platforms -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ DTC_FLAGS ?= -@ -H epapr -+endif +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index e2c33b9528d82ed7a2c27d083d7b1d222da68178..5a11ff833e1fd112ba04df3a427cd94bf6793ec5 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -2441,7 +2441,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, + if (IS_ERR(base)) + return PTR_ERR(base); + ++ /* Don't use DT serial aliases - it causes the device to ++ be renumbered to ttyAMA1 if it is the second serial port in the ++ system, even though the other one is ttyS0. The 8250 driver ++ doesn't use this logic, so always remains ttyS0. + index = pl011_probe_dt_alias(index, dev); ++ */ + + uap->old_cr = 0; + uap->port.dev = dev; -From b220b620b64b4663af9e6c285a9b8a6edb6b93be Mon Sep 17 00:00:00 2001 -From: Gerhard de Clercq -Date: Fri, 2 Dec 2016 12:15:26 +0200 -Subject: [PATCH 173/208] Add overlays symlink and dtbo target for ARM64 - (#1739) +From 71ead171a2d5a1c560884f919ff0c81f2dd07f0c Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Wed, 3 Dec 2014 13:23:28 +0200 +Subject: [PATCH 088/111] OF: DT-Overlay configfs interface -Signed-off-by: Gerhard de Clercq +This is a port of Pantelis Antoniou's v3 port that makes use of the +new upstreamed configfs support for binary attributes. + +Original commit message: + +Add a runtime interface to using configfs for generic device tree overlay +usage. With it its possible to use device tree overlays without having +to use a per-platform overlay manager. + +Please see Documentation/devicetree/configfs-overlays.txt for more info. + +Changes since v2: +- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) +- Created a documentation entry +- Slight rewording in Kconfig + +Changes since v1: +- of_resolve() -> of_resolve_phandles(). + +Originally-signed-off-by: Pantelis Antoniou +Signed-off-by: Phil Elwell + +DT configfs: Fix build errors on other platforms + +Signed-off-by: Phil Elwell + +DT configfs: fix build error + +There is an error when compiling rpi-4.6.y branch: + CC drivers/of/configfs.o +drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] + .default_groups = of_cfs_def_groups, + ^ +drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') + +The .default_groups is linked list since commit +1ae1602de028acaa42a0f6ff18d19756f8e825c6. +This commit uses configfs_add_default_group to fix this problem. + +Signed-off-by: Slawomir Stepien --- - arch/arm64/Makefile | 3 +++ - arch/arm64/boot/dts/Makefile | 1 + - arch/arm64/boot/dts/overlays | 1 + - 3 files changed, 5 insertions(+) - create mode 120000 arch/arm64/boot/dts/overlays + Documentation/devicetree/configfs-overlays.txt | 31 +++ + drivers/of/Kconfig | 7 + + drivers/of/Makefile | 1 + + drivers/of/configfs.c | 311 +++++++++++++++++++++++++ + 4 files changed, 350 insertions(+) + create mode 100644 Documentation/devicetree/configfs-overlays.txt + create mode 100644 drivers/of/configfs.c -diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile -index 5b54f8c021d8332624839e1c7eb8249eff7ba360..64c6bf2b75d1036fc73d43d1ecd2ebb4809f8a62 100644 ---- a/arch/arm64/Makefile -+++ b/arch/arm64/Makefile -@@ -102,6 +102,9 @@ zinstall install: - - %.dtb: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ -+ -+%.dtbo: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ - - PHONY += dtbs dtbs_install - -diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile -index 6e199c90367664a18a50b20372d58cbd57ba3276..4c203fb0be6dffb9057e8066bf21e83cedea92f6 100644 ---- a/arch/arm64/boot/dts/Makefile -+++ b/arch/arm64/boot/dts/Makefile -@@ -19,6 +19,7 @@ dts-dirs += socionext - dts-dirs += sprd - dts-dirs += xilinx - dts-dirs += lg -+dts-dirs += overlays - - subdir-y := $(dts-dirs) - -diff --git a/arch/arm64/boot/dts/overlays b/arch/arm64/boot/dts/overlays -new file mode 120000 -index 0000000000000000000000000000000000000000..413315acbfe83611bb2ae7cbd0da1039f47de34c ---- /dev/null -+++ b/arch/arm64/boot/dts/overlays -@@ -0,0 +1 @@ -+../../../arm/boot/dts/overlays/ -\ No newline at end of file - -From 0edb708d26ed355b63c61db6007b89ae8ce5a2ae Mon Sep 17 00:00:00 2001 -From: Alan Yiding Wang -Date: Sat, 3 Dec 2016 23:22:02 -0500 -Subject: [PATCH 174/208] BCM270X_DT: Add overlay for enc28j60 on SPI2 - -Works on SPI2 for compute module ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 10 ++++- - .../boot/dts/overlays/enc28j60-spi2-overlay.dts | 47 ++++++++++++++++++++++ - 3 files changed, 57 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index c940eb3b685d7b9af4340ff184ca736471183e09..20440abbe9a440d1f748b118f9c0ee3a0dbd039f 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -17,6 +17,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - dwc-otg.dtbo \ - dwc2.dtbo \ - enc28j60.dtbo \ -+ enc28j60-spi2.dtbo \ - gpio-ir.dtbo \ - gpio-poweroff.dtbo \ - hifiberry-amp.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 180122b381361469ca9e8c4e14f4aa52c1f351dd..4be81958d0f8a790c6a725b2367cf3f33ceaaec9 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -344,13 +344,21 @@ Params: dr_mode Dual role mode: "host", "peripheral" or "otg" - - - Name: enc28j60 --Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI0 - Load: dtoverlay=enc28j60,= - Params: int_pin GPIO used for INT (default 25) - - speed SPI bus speed (default 12000000) - - -+Name: enc28j60-spi2 -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller on SPI2 -+Load: dtoverlay=enc28j60-spi2,= -+Params: int_pin GPIO used for INT (default 39) -+ -+ speed SPI bus speed (default 12000000) -+ -+ - Name: gpio-ir - Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- - based gpio_ir_recv driver maps received keys directly to a -diff --git a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts +diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt new file mode 100644 -index 0000000000000000000000000000000000000000..946c9d2107a83335b11f094e75945a509595ab7c +index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad --- /dev/null -+++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts -@@ -0,0 +1,47 @@ -+// Overlay for the Microchip ENC28J60 Ethernet Controller - SPI2 Compute Module -+// Interrupt pin: 39 -+/dts-v1/; -+/plugin/; ++++ b/Documentation/devicetree/configfs-overlays.txt +@@ -0,0 +1,31 @@ ++Howto use the configfs overlay interface. + -+/ { -+ compatible = "brcm,bcm2708"; ++A device-tree configfs entry is created in /config/device-tree/overlays ++and and it is manipulated using standard file system I/O. ++Note that this is a debug level interface, for use by developers and ++not necessarily something accessed by normal users due to the ++security implications of having direct access to the kernel's device tree. + -+ fragment@0 { -+ target = <&spi2>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; ++* To create an overlay you mkdir the directory: + -+ status = "okay"; ++ # mkdir /config/device-tree/overlays/foo + -+ eth1: enc28j60@0{ -+ compatible = "microchip,enc28j60"; -+ reg = <0>; /* CE0 */ -+ pinctrl-names = "default"; -+ pinctrl-0 = <ð1_pins>; -+ interrupt-parent = <&gpio>; -+ interrupts = <39 0x2>; /* falling edge */ -+ spi-max-frequency = <12000000>; -+ status = "okay"; -+ }; -+ }; -+ }; ++* Either you echo the overlay firmware file to the path property file. + -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ eth1_pins: eth1_pins { -+ brcm,pins = <39>; -+ brcm,function = <0>; /* in */ -+ brcm,pull = <0>; /* none */ -+ }; -+ }; -+ }; ++ # echo foo.dtbo >/config/device-tree/overlays/foo/path + -+ __overrides__ { -+ int_pin = <ð1>, "interrupts:0", -+ <ð1_pins>, "brcm,pins:0"; -+ speed = <ð1>, "spi-max-frequency:0"; -+ }; ++* Or you cat the contents of the overlay to the dtbo file ++ ++ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo ++ ++The overlay file will be applied, and devices will be created/destroyed ++as required. ++ ++To remove it simply rmdir the directory. ++ ++ # rmdir /config/device-tree/overlays/foo ++ ++The rationalle of the dual interface (firmware & direct copy) is that each is ++better suited to different use patterns. The firmware interface is what's ++intended to be used by hardware managers in the kernel, while the copy interface ++make sense for developers (since it avoids problems with namespaces). +diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig +index ba7b034b2b91c94afb1b7135cdee7fc3d6955828..de0da10d66e6cdc6eedc4d36cf247370627f83f4 100644 +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -112,4 +112,11 @@ config OF_OVERLAY + config OF_NUMA + bool + ++config OF_CONFIGFS ++ bool "Device Tree Overlay ConfigFS interface" ++ select CONFIGFS_FS ++ select OF_OVERLAY ++ help ++ Enable a simple user-space driven DT overlay interface. ++ + endif # OF +diff --git a/drivers/of/Makefile b/drivers/of/Makefile +index d7efd9d458aab4554139e93c72a1688aa0eeef6a..aa5ef9dd1fedc14d4ae2d363818fc160df51bad9 100644 +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,4 +1,5 @@ + obj-y = base.o device.o platform.o ++obj-$(CONFIG_OF_CONFIGFS) += configfs.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o + obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o +diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b6ea6cad7 +--- /dev/null ++++ b/drivers/of/configfs.c +@@ -0,0 +1,311 @@ ++/* ++ * Configfs entries for device-tree ++ * ++ * Copyright (C) 2013 - Pantelis Antoniou ++ * ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "of_private.h" ++ ++struct cfs_overlay_item { ++ struct config_item item; ++ ++ char path[PATH_MAX]; ++ ++ const struct firmware *fw; ++ struct device_node *overlay; ++ int ov_id; ++ ++ void *dtbo; ++ int dtbo_size; +}; ++ ++static int create_overlay(struct cfs_overlay_item *overlay, void *blob) ++{ ++ int err; ++ ++ /* unflatten the tree */ ++ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); ++ if (overlay->overlay == NULL) { ++ pr_err("%s: failed to unflatten tree\n", __func__); ++ err = -EINVAL; ++ goto out_err; ++ } ++ pr_debug("%s: unflattened OK\n", __func__); ++ ++ /* mark it as detached */ ++ of_node_set_flag(overlay->overlay, OF_DETACHED); ++ ++ /* perform resolution */ ++ err = of_resolve_phandles(overlay->overlay); ++ if (err != 0) { ++ pr_err("%s: Failed to resolve tree\n", __func__); ++ goto out_err; ++ } ++ pr_debug("%s: resolved OK\n", __func__); ++ ++ err = of_overlay_create(overlay->overlay); ++ if (err < 0) { ++ pr_err("%s: Failed to create overlay (err=%d)\n", ++ __func__, err); ++ goto out_err; ++ } ++ overlay->ov_id = err; ++ ++out_err: ++ return err; ++} ++ ++static inline struct cfs_overlay_item *to_cfs_overlay_item( ++ struct config_item *item) ++{ ++ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; ++} ++ ++static ssize_t cfs_overlay_item_path_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ return sprintf(page, "%s\n", overlay->path); ++} ++ ++static ssize_t cfs_overlay_item_path_store(struct config_item *item, ++ const char *page, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ const char *p = page; ++ char *s; ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy to path buffer (and make sure it's always zero terminated */ ++ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); ++ overlay->path[sizeof(overlay->path) - 1] = '\0'; ++ ++ /* strip trailing newlines */ ++ s = overlay->path + strlen(overlay->path); ++ while (s > overlay->path && *--s == '\n') ++ *s = '\0'; ++ ++ pr_debug("%s: path is '%s'\n", __func__, overlay->path); ++ ++ err = request_firmware(&overlay->fw, overlay->path, NULL); ++ if (err != 0) ++ goto out_err; ++ ++ err = create_overlay(overlay, (void *)overlay->fw->data); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ ++ release_firmware(overlay->fw); ++ overlay->fw = NULL; ++ ++ overlay->path[0] = '\0'; ++ return err; ++} ++ ++static ssize_t cfs_overlay_item_status_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ return sprintf(page, "%s\n", ++ overlay->ov_id >= 0 ? "applied" : "unapplied"); ++} ++ ++CONFIGFS_ATTR(cfs_overlay_item_, path); ++CONFIGFS_ATTR_RO(cfs_overlay_item_, status); ++ ++static struct configfs_attribute *cfs_overlay_attrs[] = { ++ &cfs_overlay_item_attr_path, ++ &cfs_overlay_item_attr_status, ++ NULL, ++}; ++ ++ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, ++ void *buf, size_t max_count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ pr_debug("%s: buf=%p max_count=%zu\n", __func__, ++ buf, max_count); ++ ++ if (overlay->dtbo == NULL) ++ return 0; ++ ++ /* copy if buffer provided */ ++ if (buf != NULL) { ++ /* the buffer must be large enough */ ++ if (overlay->dtbo_size > max_count) ++ return -ENOSPC; ++ ++ memcpy(buf, overlay->dtbo, overlay->dtbo_size); ++ } ++ ++ return overlay->dtbo_size; ++} ++ ++ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, ++ const void *buf, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy the contents */ ++ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); ++ if (overlay->dtbo == NULL) ++ return -ENOMEM; ++ ++ overlay->dtbo_size = count; ++ ++ err = create_overlay(overlay, overlay->dtbo); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ kfree(overlay->dtbo); ++ overlay->dtbo = NULL; ++ overlay->dtbo_size = 0; ++ ++ return err; ++} ++ ++CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); ++ ++static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { ++ &cfs_overlay_item_attr_dtbo, ++ NULL, ++}; ++ ++static void cfs_overlay_release(struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ if (overlay->ov_id >= 0) ++ of_overlay_destroy(overlay->ov_id); ++ if (overlay->fw) ++ release_firmware(overlay->fw); ++ /* kfree with NULL is safe */ ++ kfree(overlay->dtbo); ++ kfree(overlay); ++} ++ ++static struct configfs_item_operations cfs_overlay_item_ops = { ++ .release = cfs_overlay_release, ++}; ++ ++static struct config_item_type cfs_overlay_type = { ++ .ct_item_ops = &cfs_overlay_item_ops, ++ .ct_attrs = cfs_overlay_attrs, ++ .ct_bin_attrs = cfs_overlay_bin_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_item *cfs_overlay_group_make_item( ++ struct config_group *group, const char *name) ++{ ++ struct cfs_overlay_item *overlay; ++ ++ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); ++ if (!overlay) ++ return ERR_PTR(-ENOMEM); ++ overlay->ov_id = -1; ++ ++ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); ++ return &overlay->item; ++} ++ ++static void cfs_overlay_group_drop_item(struct config_group *group, ++ struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ config_item_put(&overlay->item); ++} ++ ++static struct configfs_group_operations overlays_ops = { ++ .make_item = cfs_overlay_group_make_item, ++ .drop_item = cfs_overlay_group_drop_item, ++}; ++ ++static struct config_item_type overlays_type = { ++ .ct_group_ops = &overlays_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct configfs_group_operations of_cfs_ops = { ++ /* empty - we don't allow anything to be created */ ++}; ++ ++static struct config_item_type of_cfs_type = { ++ .ct_group_ops = &of_cfs_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++struct config_group of_cfs_overlay_group; ++ ++static struct configfs_subsystem of_cfs_subsys = { ++ .su_group = { ++ .cg_item = { ++ .ci_namebuf = "device-tree", ++ .ci_type = &of_cfs_type, ++ }, ++ }, ++ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), ++}; ++ ++static int __init of_cfs_init(void) ++{ ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ config_group_init(&of_cfs_subsys.su_group); ++ config_group_init_type_name(&of_cfs_overlay_group, "overlays", ++ &overlays_type); ++ configfs_add_default_group(&of_cfs_overlay_group, ++ &of_cfs_subsys.su_group); ++ ++ ret = configfs_register_subsystem(&of_cfs_subsys); ++ if (ret != 0) { ++ pr_err("%s: failed to register subsys\n", __func__); ++ goto out; ++ } ++ pr_info("%s: OK\n", __func__); ++out: ++ return ret; ++} ++late_initcall(of_cfs_init); -From 8d454bd4ff18ff2daeeddca6803edb68401c377c Mon Sep 17 00:00:00 2001 -From: Gerhard de Clercq -Date: Fri, 2 Dec 2016 13:45:06 +0200 -Subject: [PATCH 175/208] RPI-FT5406: Enable aarch64 support through explicit - iomem interface +From 2d043fc762bf4cc4aa2595adaad26496dfeb6eb8 Mon Sep 17 00:00:00 2001 +From: Cheong2K +Date: Fri, 26 Feb 2016 18:20:10 +0800 +Subject: [PATCH 089/111] brcm: adds support for BCM43341 wifi -Signed-off-by: Gerhard de Clercq ---- - drivers/input/touchscreen/rpi-ft5406.c | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) +brcmfmac: Disable power management -diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c -index c5e31978c85a4ffd6839952ce0de50c001c7b875..9d7d05482355d168c5c0c42508cd978979ee5f14 100644 ---- a/drivers/input/touchscreen/rpi-ft5406.c -+++ b/drivers/input/touchscreen/rpi-ft5406.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -47,7 +48,6 @@ struct ft5406 { - struct input_dev * input_dev; - void __iomem * ts_base; - dma_addr_t bus_addr; -- struct ft5406_regs * regs; - struct task_struct * thread; - }; - -@@ -68,8 +68,8 @@ static int ft5406_thread(void *arg) - { - // 60fps polling - msleep_interruptible(17); -- memcpy_fromio(®s, ts->regs, sizeof(*ts->regs)); -- writel(99, &ts->regs->num_points); -+ memcpy_fromio(®s, ts->ts_base, sizeof(struct ft5406_regs)); -+ iowrite8(99, ts->ts_base + offsetof(struct ft5406_regs, num_points)); - // Do not output if theres no new information (num_points is 99) - // or we have no touch points and don't need to release any - if(!(regs.num_points == 99 || (regs.num_points == 0 && known_ids == 0))) -@@ -190,7 +190,7 @@ static int ft5406_probe(struct platform_device *pdev) - - // mmap the physical memory - touchbuf &= ~0xc0000000; -- ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); -+ ts->ts_base = ioremap(touchbuf, sizeof(struct ft5406_regs)); - if (ts->ts_base == NULL) - { - dev_err(dev, "Failed to map physical address\n"); -@@ -222,8 +222,6 @@ static int ft5406_probe(struct platform_device *pdev) - err); - goto out; - } -- -- ts->regs = (struct ft5406_regs *) ts->ts_base; - - // create thread to poll the touch events - ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); +Disable wireless power saving in the brcmfmac WLAN driver. This is a +temporary measure until the connectivity loss resulting from power +saving is resolved. -From f014240610c93a7e95d58b5869a6d89209685e7b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 6 Dec 2016 17:27:50 +0000 -Subject: [PATCH 176/208] BCM270X_DT: Add midi-uart0 overlay +Signed-off-by: Phil Elwell -MIDI requires 31.25kbaud, a baudrate unsupported by Linux. The -midi-uart0 overlay configures uart0 (ttyAMA0) to use a fake clock -so that requesting 38.4kbaud actually gets 31.25kbaud. +brcmfmac: Use original country code as a fallback + +Commit 73345fd212980d2e28a5c6d83801c903bd773680: + + brcmfmac: Configure country code using device specific settings + +prevents region codes from working on devices that lack a region code +translation table. In the event of an absent table, preserve the old +behaviour of using the provided code as-is. + +Signed-off-by: Phil Elwell + +brcmfmac: Plug memory leak in brcmf_fill_bss_param + +See: https://github.com/raspberrypi/linux/issues/1471 + +Signed-off-by: Phil Elwell + +brcmfmac: do not use internal roaming engine by default + +Some evidence of curing disconnects with this disabled, so make it a default. +Can be overridden with module parameter roamoff=0 +See: http://projectable.me/optimize-my-pi-wi-fi/ + +brcmfmac: Change stop_ap sequence + +Patch from Broadcom/Cypress to resolve a customer error Signed-off-by: Phil Elwell --- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 7 +++++ - arch/arm/boot/dts/overlays/midi-uart0-overlay.dts | 36 +++++++++++++++++++++++ - 3 files changed, 44 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/midi-uart0-overlay.dts + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 31 ++++++++++++++++------ + .../wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ + .../broadcom/brcm80211/include/brcm_hw_ids.h | 1 + + 4 files changed, 27 insertions(+), 9 deletions(-) -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 20440abbe9a440d1f748b118f9c0ee3a0dbd039f..a3ddb4577ce1f671f4c23ebe32c434c97b00781c 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -45,6 +45,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - mcp23s17.dtbo \ - mcp2515-can0.dtbo \ - mcp2515-can1.dtbo \ -+ midi-uart0.dtbo \ - mmc.dtbo \ - mz61581.dtbo \ - pi3-act-led.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 4be81958d0f8a790c6a725b2367cf3f33ceaaec9..496e31db0c7d22934bd381aea5e7227c26a3f034 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -725,6 +725,13 @@ Params: oscillator Clock frequency for the CAN controller (Hz) - interrupt GPIO for interrupt signal +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 78d9966a3957b2b934fe6b21de5cade494ec2839..3fcb1887b2d312e050c02e9fe66ea20f48f0abcb 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2756,6 +2756,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, + * preference in cfg struct to apply this to + * FW later while initializing the dongle + */ ++ pr_info("power management disabled\n"); ++ enabled = false; + cfg->pwr_save = enabled; + if (!check_vif_up(ifp->vif)) { +@@ -4750,12 +4752,15 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); + if (err < 0) + brcmf_err("BRCMF_C_DOWN error %d\n", err); +- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); +- if (err < 0) +- brcmf_err("setting AP mode failed %d\n", err); ++ + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); + if (err < 0) + brcmf_err("setting INFRA mode failed %d\n", err); ++ ++ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); ++ if (err < 0) ++ brcmf_err("setting AP mode failed %d\n", err); ++ + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) + brcmf_fil_iovar_int_set(ifp, "mbss", 0); + brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, +@@ -6737,12 +6742,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + struct brcmfmac_pd_cc *country_codes; + struct brcmfmac_pd_cc_entry *cc; + s32 found_index; ++ char ccode[BRCMF_COUNTRY_BUF_SZ]; ++ int rev; + int i; -+Name: midi-uart0 -+Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets -+ 31.25kbaud, the frequency required for MIDI -+Load: dtoverlay=midi-uart0 -+Params: ++ memcpy(ccode, alpha2, sizeof(ccode)); ++ rev = -1; + + country_codes = drvr->settings->country_codes; + if (!country_codes) { +- brcmf_dbg(TRACE, "No country codes configured for device\n"); +- return -EINVAL; ++ brcmf_dbg(TRACE, "No country codes configured for device" ++ " - use requested value\n"); ++ goto use_input_value; + } + + if ((alpha2[0] == ccreq->country_abbrev[0]) && +@@ -6766,10 +6777,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + brcmf_dbg(TRACE, "No country code match found\n"); + return -EINVAL; + } +- memset(ccreq, 0, sizeof(*ccreq)); +- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); +- memcpy(ccreq->ccode, country_codes->table[found_index].cc, ++ rev = country_codes->table[found_index].rev; ++ memcpy(ccode, country_codes->table[found_index].cc, + BRCMF_COUNTRY_BUF_SZ); + - Name: mmc - Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock - Load: dtoverlay=mmc,= -diff --git a/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts ++use_input_value: ++ memset(ccreq, 0, sizeof(*ccreq)); ++ ccreq->rev = cpu_to_le32(rev); ++ memcpy(ccreq->ccode, ccode, sizeof(ccode)); + ccreq->country_abbrev[0] = alpha2[0]; + ccreq->country_abbrev[1] = alpha2[1]; + ccreq->country_abbrev[2] = 0; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index 3e15d64c64813513bc22202dd9e468588699abb0..4051780f64f44a5ce522babe6c371a1beb79a824 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -69,7 +69,7 @@ static int brcmf_fcmode; + module_param_named(fcmode, brcmf_fcmode, int, 0); + MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); + +-static int brcmf_roamoff; ++static int brcmf_roamoff = 1; + module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); + MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index b892dac70f4b02f76e01a7ccb580c6d8aed4bfe4..db5f8b70b407879f1c006ca4b7ab78d12974609d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -604,6 +604,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); ++BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); +@@ -621,6 +622,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), ++ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index d0407d9ad7827cd756b6311410ffe2d9a7cacc78..f1fb8a3c7a3211e8429585861f2f42e014878654 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -36,6 +36,7 @@ + #define BRCM_CC_4330_CHIP_ID 0x4330 + #define BRCM_CC_4334_CHIP_ID 0x4334 + #define BRCM_CC_43340_CHIP_ID 43340 ++#define BRCM_CC_43341_CHIP_ID 43341 + #define BRCM_CC_43362_CHIP_ID 43362 + #define BRCM_CC_4335_CHIP_ID 0x4335 + #define BRCM_CC_4339_CHIP_ID 0x4339 + +From e8bc1c301166d8273a8ae9f55cc5c41b970c6e53 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 17 Dec 2015 13:37:07 +0000 +Subject: [PATCH 090/111] hci_h5: Don't send conf_req when ACTIVE + +Without this patch, a modem and kernel can continuously bombard each +other with conf_req and conf_rsp messages, in a demented game of tag. +--- + drivers/bluetooth/hci_h5.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) + h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_req, 2) == 0) { + h5_link_control(hu, conf_rsp, 2); +- h5_link_control(hu, conf_req, 3); ++ if (h5->state != H5_ACTIVE) ++ h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_rsp, 2) == 0) { + if (H5_HDR_LEN(hdr) > 2) + h5->tx_win = (data[2] & 0x07); + +From 472db8146235a2a4e9109b9ffe9c80b815b24809 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 13 Apr 2015 17:16:29 +0100 +Subject: [PATCH 091/111] config: Add default configs + +--- + arch/arm/configs/bcm2709_defconfig | 1297 +++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1308 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 2605 insertions(+) + create mode 100644 arch/arm/configs/bcm2709_defconfig + create mode 100644 arch/arm/configs/bcmrpi_defconfig + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig new file mode 100644 -index 0000000000000000000000000000000000000000..565af7cf79d761877be3bd06191f31aabf9e1e9b +index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c1ddf5f7c --- /dev/null -+++ b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts -@@ -0,0 +1,36 @@ -+/dts-v1/; -+/plugin/; -+ -+#include -+ -+/* -+ * Fake a higher clock rate to get a larger divisor, and thereby a lower -+ * baudrate. The real clock is 48MHz, which we scale so that requesting -+ * 38.4kHz results in an actual 31.25kHz. -+ * -+ * 48000000*38400/31250 = 58982400 -+ */ -+ -+/{ -+ compatible = "brcm,bcm2835"; -+ -+ fragment@0 { -+ target-path = "/clocks"; -+ __overlay__ { -+ midi_clk: midi_clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-output-names = "uart0_pclk"; -+ clock-frequency = <58982400>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&uart0>; -+ __overlay__ { -+ clocks = <&midi_clk>, -+ <&clocks BCM2835_CLOCK_VPU>; -+ }; -+ }; -+}; ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -0,0 +1,1297 @@ ++CONFIG_LOCALVERSION="-v7" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_BCM=y ++CONFIG_ARCH_BCM2835=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_SMP=y ++CONFIG_VMSPLIT_2G=y ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_VFP=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_BINFMT_MISC=m ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_CFG80211=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_EKTF2127=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y ++CONFIG_BCM_VC_SM=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_BCM2835AUX=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_BCM2835=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_VIRT=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_BATTERY_DS2760=m ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_INA2XX=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_PISOUND=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_AK4554=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_ABX80X=m ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_HTU21=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM_NEON=m ++CONFIG_CRYPTO_AES_ARM_BS=m ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +new file mode 100644 +index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831cda8d7b51 +--- /dev/null ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -0,0 +1,1308 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_MULTI_V6=y ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_BCM=y ++CONFIG_ARCH_BCM2835=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_VFP=y ++CONFIG_BINFMT_MISC=m ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_CFG80211=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y ++CONFIG_BCM_VC_SM=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_BCM2835AUX=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_BCM2835=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_BATTERY_DS2760=m ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_INA2XX=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_PISOUND=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_AK4554=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_DWC2=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_USB_GADGET=m ++CONFIG_USB_ZERO=m ++CONFIG_USB_AUDIO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++CONFIG_USB_MIDI_GADGET=m ++CONFIG_USB_G_PRINTER=m ++CONFIG_USB_CDC_COMPOSITE=m ++CONFIG_USB_G_ACM_MS=m ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_HID=m ++CONFIG_USB_G_WEBCAM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_ABX80X=m ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_HTU21=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CRYPTD=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_SHA512=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM=m ++CONFIG_CRYPTO_AES_ARM=m ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y -From 2b4dc8b567a7432b754eb86291add0cb2a153ff4 Mon Sep 17 00:00:00 2001 +From f48b75a44a3a1b2fac53aa9e17c8bbb859799b17 Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Wed, 24 Aug 2016 03:35:56 -0700 +Subject: [PATCH 092/111] Add arm64 configuration and device tree differences. + Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing + at the moment. + +ARM64: Modify default config to get raspbian to boot (#1686) + +1. Enable emulation of deprecated instructions. +2. Enable ARM 8.1 and 8.2 features which are not detected at runtime. +3. Switch the default governer to powersave. +4. Include the watchdog timer driver in the kernel image rather then a module. + +Tested with raspbian-jessie 2016-09-23. +--- + arch/arm64/Kconfig.platforms | 22 + + arch/arm64/boot/dts/broadcom/Makefile | 1 + + arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts | 3 + + arch/arm64/configs/bcmrpi3_defconfig | 1334 ++++++++++++++++++++++ + 4 files changed, 1360 insertions(+) + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts + create mode 100644 arch/arm64/configs/bcmrpi3_defconfig + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 101794f5ce1008b7ff007fbfc7fa23d9e63bae67..7d213c2c904271c7a4622b83cd55a750d237bc2e 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -1,5 +1,27 @@ + menu "Platform selection" + ++config MACH_BCM2709 ++ bool ++ ++config ARCH_BCM2709 ++ bool "Broadcom BCM2709 family" ++ select MACH_BCM2709 ++ select HAVE_SMP ++ select ARM_AMBA ++ select COMMON_CLK ++ select ARCH_HAS_CPUFREQ ++ select GENERIC_CLOCKEVENTS ++ select MULTI_IRQ_HANDLER ++ select SPARSE_IRQ ++ select MFD_SYSCON ++ select VC4 ++ select USE_OF ++ select ARCH_REQUIRE_GPIOLIB ++ select PINCTRL ++ select PINCTRL_BCM2835 ++ help ++ This enables support for Broadcom BCM2709 boards. ++ + config ARCH_SUNXI + bool "Allwinner sunxi 64-bit SoC Family" + select GENERIC_IRQ_CHIP +diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile +index 05faf2a8a35ca5ba9049b9038dedb9be88eeb7c5..2152448c8cf5b22c573642d7ce45e85793f5fc9a 100644 +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -1,6 +1,7 @@ + dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb + dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb + dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb ++dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb + + always := $(dtb-y) + subdir-y := $(dts-dirs) +diff --git a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..deb33441da95220db0ed672e41639626fba682a5 +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts +@@ -0,0 +1,3 @@ ++#define RPI364 ++ ++#include "../../../../arm/boot/dts/bcm2710-rpi-3-b.dts" +diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig +new file mode 100644 +index 0000000000000000000000000000000000000000..d7406f5a4620151044b8f716b4d10bb818648e06 +--- /dev/null ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -0,0 +1,1334 @@ ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_PHYS_OFFSET=0 ++CONFIG_LOCALVERSION="-v8" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_64BIT=y ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=n ++CONFIG_ARM64_ERRATUM_827319=n ++CONFIG_ARM64_ERRATUM_824069=n ++CONFIG_ARM64_ERRATUM_819472=n ++CONFIG_ARM64_ERRATUM_832075=n ++CONFIG_ARM64_ERRATUM_845719=n ++CONFIG_ARM64_ERRATUM_843419=n ++CONFIG_CAVIUM_ERRATUM_22375=n ++CONFIG_CAVIUM_ERRATUM_23154=n ++CONFIG_CAVIUM_ERRATUM_27456=n ++CONFIG_ARM64_4K_PAGES=y ++CONFIG_ARM64_VA_BITS_39=y ++CONFIG_ARM64_VA_BITS=39 ++CONFIG_SCHED_MC=y ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++CONFIG_ARMV8_DEPRECATED=y ++CONFIG_SWP_EMULATION=y ++CONFIG_CP15_BARRIER_EMULATION=y ++CONFIG_SETEND_EMULATION=y ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++CONFIG_ARM64_LSE_ATOMICS=y ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=n ++CONFIG_RANDOMIZE_BASE=n ++ ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_TRIM_UNUSED_KSYMS=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_BCM2709=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_SMP=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_2G=y ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_VFP=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_BINFMT_MISC=m ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_IPVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=n ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_FT6236=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=n ++CONFIG_BCM_VC_CMA=n ++CONFIG_BCM_VCIO=n ++CONFIG_BCM_VC_SM=n ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_VIRT=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_BATTERY_DS2760=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=n ++CONFIG_VIDEO_BCM2835_MMAL=n ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_ARM=n ++CONFIG_SND_BCM2835=n ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=n ++CONFIG_USB_DWC2=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_ISL12057=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_R8723AU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++CONFIG_ARM64_CRYPTO=y ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y ++CONFIG_BCM2708_VCHIQ=n + +From 219a6fccb0da0e2e3533110a8871a6a64e11d8bf Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 7 Mar 2016 15:05:11 +0000 +Subject: [PATCH 093/111] vchiq_arm: Tweak the logging output + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 31 +++++++++------------- + 1 file changed, 13 insertions(+), 18 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +index 2c98da4307dff994a00dc246574ef0aaee05d5da..160db24aeea33a8296923501009c1f02bc41e599 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +@@ -891,16 +891,14 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + error_count); + return VCHIQ_ERROR; + } +- if (i == 0) { +- if (SRVTRACE_ENABLED(service, +- VCHIQ_LOG_INFO)) +- vchiq_log_dump_mem("Sent", 0, +- header->data + pos, +- min(64u, +- elements[0].size)); +- } + } + ++ if (SRVTRACE_ENABLED(service, ++ VCHIQ_LOG_INFO)) ++ vchiq_log_dump_mem("Sent", 0, ++ header->data, ++ min(16, pos)); ++ + spin_lock("a_spinlock); + service_quota->message_use_count++; + +@@ -1039,16 +1037,13 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + error_count); + return VCHIQ_ERROR; + } +- if (i == 0) { +- if (vchiq_sync_log_level >= +- VCHIQ_LOG_TRACE) +- vchiq_log_dump_mem("Sent Sync", +- 0, header->data + pos, +- min(64u, +- elements[0].size)); +- } + } + ++ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) ++ vchiq_log_dump_mem("Sent Sync", ++ 0, header->data, ++ min(16, pos)); ++ + VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); + } else { +@@ -1720,7 +1715,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, +- min(64, size)); ++ min(16, size)); + } + + if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) +@@ -2187,7 +2182,7 @@ sync_func(void *v) + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, +- min(64, size)); ++ min(16, size)); + } + + switch (type) { + +From 2ee990fac882706993ff1e41954e3f66329cf902 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 23 Mar 2016 14:16:25 +0000 +Subject: [PATCH 094/111] vchiq_arm: Access the dequeue_pending flag locked + +Reading through this code looking for another problem (now found in userland) +the use of dequeue_pending outside a lock didn't seem safe. + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 7b6cd4d80621e38ff6d47fcd87b45fbe9cd4259b..d8669fa7f39b077877eca1829ba9538bf2e21a82 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -279,6 +279,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + USER_SERVICE_T *user_service; + VCHIQ_SERVICE_T *service; + VCHIQ_INSTANCE_T instance; ++ int skip_completion = 0; + DEBUG_INITIALISE(g_state.local) + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); +@@ -345,9 +346,6 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + user_service->msg_queue[user_service->msg_insert & + (MSG_QUEUE_SIZE - 1)] = header; + user_service->msg_insert++; +- spin_unlock(&msg_queue_spinlock); +- +- up(&user_service->insert_event); + + /* If there is a thread waiting in DEQUEUE_MESSAGE, or if + ** there is a MESSAGE_AVAILABLE in the completion queue then +@@ -356,13 +354,22 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + if (((user_service->message_available_pos - + instance->completion_remove) >= 0) || + user_service->dequeue_pending) { +- DEBUG_TRACE(SERVICE_CALLBACK_LINE); + user_service->dequeue_pending = 0; +- return VCHIQ_SUCCESS; ++ skip_completion = 1; + } + ++ spin_unlock(&msg_queue_spinlock); ++ ++ up(&user_service->insert_event); ++ + header = NULL; + } ++ ++ if (skip_completion) { ++ DEBUG_TRACE(SERVICE_CALLBACK_LINE); ++ return VCHIQ_SUCCESS; ++ } ++ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + + return add_completion(instance, reason, header, user_service, + +From 3116aabedfc03a28116a5d3c5e60bf5ca036b81a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 23 Mar 2016 20:53:47 +0000 +Subject: [PATCH 095/111] vchiq_arm: Service callbacks must not fail + +Service callbacks are not allowed to return an error. The internal callback +that delivers events and messages to user tasks does not enqueue them if +the service is closing, but this is not an error and should not be +reported as such. + +Signed-off-by: Phil Elwell +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index d8669fa7f39b077877eca1829ba9538bf2e21a82..54552c6ce54f413c9781ba279b936f98be4f47b0 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -224,7 +224,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); +- return VCHIQ_ERROR; ++ return VCHIQ_SUCCESS; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + +From e14cabb05cf8aa75df960f82198ed6125c3e4b89 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 21 Apr 2016 13:49:32 +0100 +Subject: [PATCH 096/111] vchiq_arm: Add completion records under the mutex + +An issue was observed when flushing openmax components +which generate a large number of messages returning +buffers to host. + +We occasionally found a duplicate message from 16 +messages prior, resulting in a buffer returned twice. + +While only one thread adds completions, without the +mutex you don't get the protection of the automatic +memory barrier you get with synchronisation objects. + +Signed-off-by: Phil Elwell +--- + .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 54552c6ce54f413c9781ba279b936f98be4f47b0..bde8955b7d8505d73579b77b5b3921549cb9d2fb 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -210,6 +210,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + VCHIQ_COMPLETION_DATA_T *completion; + DEBUG_INITIALISE(g_state.local) + ++ mutex_lock(&instance->completion_mutex); ++ + while (instance->completion_insert == + (instance->completion_remove + MAX_COMPLETIONS)) { + /* Out of space - wait for the client */ +@@ -217,11 +219,17 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); ++ ++ mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; +- } else if (instance->closing) { ++ } ++ ++ mutex_lock(&instance->completion_mutex); ++ if (instance->closing) { ++ mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; +@@ -254,8 +262,11 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + if (reason == VCHIQ_MESSAGE_AVAILABLE) + user_service->message_available_pos = + instance->completion_insert; ++ + instance->completion_insert++; + ++ mutex_unlock(&instance->completion_mutex); ++ + up(&instance->insert_event); + + return VCHIQ_SUCCESS; + +From 720c0f193217c59539e4bd3cbf4c2315caa7fcb2 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Jun 2016 13:51:44 +0100 +Subject: [PATCH 097/111] vchiq_arm: Avoid use of mutex in add_completion + +Claiming the completion_mutex within add_completion did prevent some +messages appearing twice, but provokes a deadlock caused by vcsm using +vchiq within a page fault handler. + +Revert the use of completion_mutex, and instead fix the original +problem using more memory barriers. + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 55 +++++++++++----------- + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 14 ++++-- + 2 files changed, 37 insertions(+), 32 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index bde8955b7d8505d73579b77b5b3921549cb9d2fb..e5cdda12c7e5c35c69eb96991cfdb8326def167f 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -64,10 +64,10 @@ + #define VCHIQ_MINOR 0 + + /* Some per-instance constants */ +-#define MAX_COMPLETIONS 16 ++#define MAX_COMPLETIONS 128 + #define MAX_SERVICES 64 + #define MAX_ELEMENTS 8 +-#define MSG_QUEUE_SIZE 64 ++#define MSG_QUEUE_SIZE 128 + + #define KEEPALIVE_VER 1 + #define KEEPALIVE_VER_MIN KEEPALIVE_VER +@@ -208,28 +208,24 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + void *bulk_userdata) + { + VCHIQ_COMPLETION_DATA_T *completion; ++ int insert; + DEBUG_INITIALISE(g_state.local) + +- mutex_lock(&instance->completion_mutex); +- +- while (instance->completion_insert == +- (instance->completion_remove + MAX_COMPLETIONS)) { ++ insert = instance->completion_insert; ++ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { + /* Out of space - wait for the client */ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); + +- mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; + } + +- mutex_lock(&instance->completion_mutex); + if (instance->closing) { +- mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; +@@ -237,9 +233,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + +- completion = +- &instance->completions[instance->completion_insert & +- (MAX_COMPLETIONS - 1)]; ++ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; + + completion->header = header; + completion->reason = reason; +@@ -260,12 +254,9 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + wmb(); + + if (reason == VCHIQ_MESSAGE_AVAILABLE) +- user_service->message_available_pos = +- instance->completion_insert; ++ user_service->message_available_pos = insert; + +- instance->completion_insert++; +- +- mutex_unlock(&instance->completion_mutex); ++ instance->completion_insert = ++insert; + + up(&instance->insert_event); + +@@ -795,6 +786,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + instance->completion_insert) + && !instance->closing) { + int rc; ++ + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + mutex_unlock(&instance->completion_mutex); + rc = down_interruptible(&instance->insert_event); +@@ -809,24 +801,29 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + } + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + +- /* A read memory barrier is needed to stop prefetch of a stale +- ** completion record +- */ +- rmb(); +- + if (ret == 0) { + int msgbufcount = args.msgbufcount; ++ int remove; ++ ++ remove = instance->completion_remove; ++ + for (ret = 0; ret < args.count; ret++) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; +- if (instance->completion_remove == +- instance->completion_insert) ++ ++ if (remove == instance->completion_insert) + break; ++ + completion = &instance->completions[ +- instance->completion_remove & +- (MAX_COMPLETIONS - 1)]; ++ remove & (MAX_COMPLETIONS - 1)]; ++ ++ ++ /* A read memory barrier is needed to prevent ++ ** the prefetch of a stale completion record ++ */ ++ rmb(); + + service = completion->service_userdata; + user_service = service->base.userdata; +@@ -903,7 +900,11 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + } + +- instance->completion_remove++; ++ /* Ensure that the above copy has completed ++ ** before advancing the remove pointer. */ ++ mb(); ++ ++ instance->completion_remove = ++remove; + } + + if (msgbufcount != args.msgbufcount) { +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +index 160db24aeea33a8296923501009c1f02bc41e599..71a3bedc55314f3b22dbff40c05dedf03b5e7169 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +@@ -610,15 +610,15 @@ process_free_queue(VCHIQ_STATE_T *state) + BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + int slot_queue_available; + +- /* Use a read memory barrier to ensure that any state that may have +- ** been modified by another thread is not masked by stale prefetched +- ** values. */ +- rmb(); +- + /* Find slots which have been freed by the other side, and return them + ** to the available queue. */ + slot_queue_available = state->slot_queue_available; + ++ /* Use a memory barrier to ensure that any state that may have been ++ ** modified by another thread is not masked by stale prefetched ++ ** values. */ ++ mb(); ++ + while (slot_queue_available != local->slot_queue_recycle) { + unsigned int pos; + int slot_index = local->slot_queue[slot_queue_available++ & +@@ -626,6 +626,8 @@ process_free_queue(VCHIQ_STATE_T *state) + char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + int data_found = 0; + ++ rmb(); ++ + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", + state->id, slot_index, (unsigned int)data, + local->slot_queue_recycle, slot_queue_available); +@@ -741,6 +743,8 @@ process_free_queue(VCHIQ_STATE_T *state) + up(&state->data_quota_event); + } + ++ mb(); ++ + state->slot_queue_available = slot_queue_available; + up(&state->slot_available_event); + } + +From 27d47d64fcc3c859c0aa4e586260fe18a4d93ea0 Mon Sep 17 00:00:00 2001 From: Eric Anholt -Date: Wed, 14 Sep 2016 09:18:09 +0100 -Subject: [PATCH 177/208] raspberrypi-firmware: Define the MBOX channel in the - header. +Date: Mon, 3 Oct 2016 10:14:10 -0700 +Subject: [PATCH 098/111] staging/vchi: Convert to current get_user_pages() + arguments. Signed-off-by: Eric Anholt --- - include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ - 1 file changed, 2 insertions(+) + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 +-- + 2 files changed, 2 insertions(+), 3 deletions(-) -diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index e92278968b2b979db2a1f855f70e7aafb224fa98..6f19b27ae24ecfddc880e9b29290238df1f27087 100644 ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -12,6 +12,8 @@ - #include - #include +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +index 1091b9f1dd070e3d27c269402b43b0a09d96bcdc..8c7f31f8d39537e7e1c8135271c5f8eea76ed7a0 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -420,7 +420,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, + *need_release = 0; /* do not try and release vmalloc pages */ + } else { + down_read(&task->mm->mmap_sem); +- actual_pages = get_user_pages(task, task->mm, ++ actual_pages = get_user_pages( + (unsigned long)buf & ~(PAGE_SIZE - 1), + num_pages, + (type == PAGELIST_READ) ? FOLL_WRITE : 0, +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index e5cdda12c7e5c35c69eb96991cfdb8326def167f..085d37588c59198b4e5f00b9249bb8421695854f 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1492,8 +1492,7 @@ dump_phys_mem(void *virt_addr, uint32_t num_bytes) + } -+#define RPI_FIRMWARE_CHAN_FB 1 -+ - struct rpi_firmware; - - enum rpi_firmware_property_status { + down_read(¤t->mm->mmap_sem); +- rc = get_user_pages(current, /* task */ +- current->mm, /* mm */ ++ rc = get_user_pages( + (unsigned long)virt_addr, /* start */ + num_pages, /* len */ + 0, /* gup_flags */ -From 4b1d48bfd89c7a2edfd82be28e7896c9595417f0 Mon Sep 17 00:00:00 2001 +From e1c06a16857ef82b23542476ae90c19f8116759e Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 3 Oct 2016 10:16:03 -0700 +Subject: [PATCH 099/111] staging/vchi: Update for rename of + page_cache_release() to put_page(). + +Signed-off-by: Eric Anholt +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 ++-- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +index 8c7f31f8d39537e7e1c8135271c5f8eea76ed7a0..862fabf5682c7dededc8d7ca6773d5b227b72f3c 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -438,7 +438,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, + while (actual_pages > 0) + { + actual_pages--; +- page_cache_release(pages[actual_pages]); ++ put_page(pages[actual_pages]); + } + kfree(pagelist); + if (actual_pages == 0) +@@ -577,7 +577,7 @@ free_pagelist(PAGELIST_T *pagelist, int actual) + offset = 0; + set_page_dirty(pg); + } +- page_cache_release(pg); ++ put_page(pg); + } + } + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 085d37588c59198b4e5f00b9249bb8421695854f..5a2b8fb459ebe086ec229f37b6381bdbe6f808ca 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1530,7 +1530,7 @@ dump_phys_mem(void *virt_addr, uint32_t num_bytes) + kunmap(page); + + for (page_idx = 0; page_idx < num_pages; page_idx++) +- page_cache_release(pages[page_idx]); ++ put_page(pages[page_idx]); + + kfree(pages); + } + +From d4b6d1d96c30d9d162a96845fb9f6f1da82749d8 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 3 Oct 2016 10:21:17 -0700 +Subject: [PATCH 100/111] drivers/vchi: Remove dependency on CONFIG_BROKEN. + +The driver builds now. + +Signed-off-by: Eric Anholt +--- + drivers/staging/vc04_services/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig +index 9676fb29075a457109e4d4235f086987aec74868..db8e1beb89f9f8c48ea5964016c8285ea82497d8 100644 +--- a/drivers/staging/vc04_services/Kconfig ++++ b/drivers/staging/vc04_services/Kconfig +@@ -1,6 +1,6 @@ + config BCM2708_VCHIQ + tristate "Videocore VCHIQ" +- depends on RASPBERRYPI_FIRMWARE && BROKEN ++ depends on RASPBERRYPI_FIRMWARE + default y + help + Kernel to VideoCore communication interface for the + +From c6b2cd816480eb17449290d989909b8ba892e9a6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 09:16:19 +0100 -Subject: [PATCH 178/208] raspberrypi-firmware: Export the general transaction +Subject: [PATCH 101/111] raspberrypi-firmware: Export the general transaction function. The vc4-firmware-kms module is going to be doing the MBOX FB call. @@ -147858,10 +123486,10 @@ index 3f070bd38a91511c986e3fb114b15bd4ac32634c..f261b64d1657c02290904d841e1f087c /** * rpi_firmware_property_list - Submit firmware property list diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index 6f19b27ae24ecfddc880e9b29290238df1f27087..2859db09e25bb945251e85edb39bc43430857168 100644 +index e92278968b2b979db2a1f855f70e7aafb224fa98..09e3d871d110eb0762ebdb5ea329353738d58661 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -133,5 +133,6 @@ int rpi_firmware_property(struct rpi_firmware *fw, +@@ -131,5 +131,6 @@ int rpi_firmware_property(struct rpi_firmware *fw, int rpi_firmware_property_list(struct rpi_firmware *fw, void *data, size_t tag_size); struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node); @@ -147869,1273 +123497,35 @@ index 6f19b27ae24ecfddc880e9b29290238df1f27087..2859db09e25bb945251e85edb39bc434 #endif /* __SOC_RASPBERRY_FIRMWARE_H__ */ -From 0d1d276c7e42e7e7849ae973bf17d259ae958bc7 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Wed, 10 Aug 2016 18:52:34 +0200 -Subject: [PATCH 179/208] drm/fb-helper: Add a dummy - remove_conflicting_framebuffers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Lots of drivers don't properly compile without this when CONFIG_FB=n. -It's kinda a hack, but since CONFIG_FB doesn't stub any fucntions when -it's disabled I think it makes sense to add it to drm_fb_helper.h. - -Long term we probably need to rethink all the logic to unload firmware -framebuffer drivers, at least if we want to be able to move away from -CONFIG_FB and fbcon. - -v2: Unfortunately just stubbing out remove_conflicting_framebuffers in -drm_fb_helper.h upset gcc about static vs. non-static declarations, so -a new wrapper it needs to be. Means more churn :( - -Cc: Tobias Jakobi -Cc: Noralf Trønnes -Cc: tomi.valkeinen@ti.com -Cc: dh.herrmann@gmail.com -Reviewed-by: Alex Deucher -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1470847958-28465-2-git-send-email-daniel.vetter@ffwll.ch ---- - drivers/gpu/drm/vc4/vc4_drv.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 9ecef93854914579ee74b4d96432d15dfaa1fd6b..eff0530dc713f6ac3cdb5cb3e640abed1cc67492 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -16,6 +16,7 @@ - #include - #include - #include "drm_fb_cma_helper.h" -+#include - - #include "uapi/drm/vc4_drm.h" - #include "vc4_drv.h" -@@ -214,7 +215,7 @@ static void vc4_kick_out_firmware_fb(void) - ap->ranges[0].base = 0; - ap->ranges[0].size = ~0; - -- remove_conflicting_framebuffers(ap, "vc4drmfb", false); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "vc4drmfb", false); - kfree(ap); - } - - -From d970485b895a64a309054dea77693c48332db7fb Mon Sep 17 00:00:00 2001 -From: Laurent Pinchart -Date: Fri, 19 Aug 2016 11:39:29 +0300 -Subject: [PATCH 180/208] drm: Don't implement empty prepare_fb()/cleanup_fb() - -The plane .prepare_fb() and .cleanup_fb() helpers are optional, there's -no need to implement empty stubs, and no need to explicitly set the -function pointers to NULL either. - -Signed-off-by: Laurent Pinchart -[danvet: Resolved conflicts with Chris' patch.] -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/vc4/vc4_plane.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 29e4b400e25e34a63e4710e9edbba62541b9cdc5..881bf489478b01b34e9e4df6013fe608c42215ee 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -735,8 +735,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) - } - - static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { -- .prepare_fb = NULL, -- .cleanup_fb = NULL, - .atomic_check = vc4_plane_atomic_check, - .atomic_update = vc4_plane_atomic_update, - }; - -From 8046f42af8709ad32d6eaf964bc169f6e8e1136b Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:58:57 +0200 -Subject: [PATCH 181/208] drm/vc4: Disallow interlaced modes on DPI. - -We already don't expose such modes to userspace, but make -sure userspace can't sneak some interlaced mode in. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_dpi.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c -index 275fedbdbd9eae420939627e7fcdf9236cfce4fa..1e1f6b8184d058c6e55e092653798f4d75b55b7f 100644 ---- a/drivers/gpu/drm/vc4/vc4_dpi.c -+++ b/drivers/gpu/drm/vc4/vc4_dpi.c -@@ -340,9 +340,20 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) - } - } - -+static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder, -+ const struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) -+ return false; -+ -+ return true; -+} -+ - static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = { - .disable = vc4_dpi_encoder_disable, - .enable = vc4_dpi_encoder_enable, -+ .mode_fixup = vc4_dpi_encoder_mode_fixup, - }; - - static const struct of_device_id vc4_dpi_dt_match[] = { - -From 43e8caa26763825711b0f901d3a0544690363efd Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:58:58 +0200 -Subject: [PATCH 182/208] drm/vc4: Fix handling of interlaced video modes. - -We must not apply CRTC_INTERLACE_HALVE_V to interlaced modes during -mode enumeration, as drm_helper_probe_single_connector_modes -does, so wrap it and reset the effect of CRTC_INTERLACE_HALVE_V -on affected interlaced modes. - -Also mode_fixup interlaced modes passed in from user space. - -This fixes the vblank timestamping constants and entries in -the mode->crtc_xxx fields needed for precise vblank timestamping. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++++++++++ - drivers/gpu/drm/vc4/vc4_hdmi.c | 29 +++++++++++++++++++++++++++-- - 2 files changed, 45 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 8fc2b731b59a613fddce5853981e1ab8fd982837..a479d3d840c59257aaf0f411cc9600f4915bb62c 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -532,6 +532,23 @@ static void vc4_crtc_enable(struct drm_crtc *crtc) - CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); - } - -+static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, -+ const struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ /* -+ * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when -+ * coming from user space. We don't want this, as it screws up -+ * vblank timestamping, so fix it up. -+ */ -+ drm_mode_set_crtcinfo(adjusted_mode, 0); -+ -+ DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id); -+ drm_mode_debug_printmodeline(adjusted_mode); -+ -+ return true; -+} -+ - static int vc4_crtc_atomic_check(struct drm_crtc *crtc, - struct drm_crtc_state *state) - { -@@ -819,6 +836,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { - .mode_set_nofb = vc4_crtc_mode_set_nofb, - .disable = vc4_crtc_disable, - .enable = vc4_crtc_enable, -+ .mode_fixup = vc4_crtc_mode_fixup, - .atomic_check = vc4_crtc_atomic_check, - .atomic_flush = vc4_crtc_atomic_flush, - }; -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 4452f3631cacea37bbd5dc8a594367631e308adc..68ad10634b29ec7b716f70f0b5fd9f2046da1fe5 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -208,10 +208,35 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - return ret; - } - -+/* -+ * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to -+ * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it -+ * screws up vblank timestamping for interlaced modes, so fix it up. -+ */ -+static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector, -+ uint32_t maxX, uint32_t maxY) -+{ -+ struct drm_display_mode *mode; -+ int count; -+ -+ count = drm_helper_probe_single_connector_modes(connector, maxX, maxY); -+ if (count == 0) -+ return 0; -+ -+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n", -+ connector->base.id, connector->name); -+ list_for_each_entry(mode, &connector->modes, head) { -+ drm_mode_set_crtcinfo(mode, 0); -+ drm_mode_debug_printmodeline(mode); -+ } -+ -+ return count; -+} -+ - static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .detect = vc4_hdmi_connector_detect, -- .fill_modes = drm_helper_probe_single_connector_modes, -+ .fill_modes = vc4_hdmi_connector_probe_modes, - .destroy = vc4_hdmi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -@@ -246,7 +271,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, - connector->polled = (DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT); - -- connector->interlace_allowed = 0; -+ connector->interlace_allowed = 1; - connector->doublescan_allowed = 0; - - drm_mode_connector_attach_encoder(connector, encoder); - -From 991b87fa61335f5241088165fa667ea2ce5c8f90 Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:58:59 +0200 -Subject: [PATCH 183/208] drm/vc4: Reject doublescan modes. - -We can't handle doublescan modes at the moment, so if -userspace tries to set one, reject the mode set. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index a479d3d840c59257aaf0f411cc9600f4915bb62c..2bfa2470e66b3fb5aa3692c66cb803973985f68f 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -536,6 +536,13 @@ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - { -+ /* Do not allow doublescan modes from user space */ -+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { -+ DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n", -+ crtc->base.id); -+ return false; -+ } -+ - /* - * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when - * coming from user space. We don't want this, as it screws up - -From 503dc975e3a0fde5266a1528ebef09a384b9b1ff Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:59:00 +0200 -Subject: [PATCH 184/208] drm/vc4: Enable precise vblank timestamping for - interlaced modes. - -On top of the interlaced video mode fix and with some additional -adjustments, this now works well. It has almost the same accuracy -as on regular progressive scan modes. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 21 ++++++++------------- - 1 file changed, 8 insertions(+), 13 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 2bfa2470e66b3fb5aa3692c66cb803973985f68f..7ffdad543ed2cbb588ad8f2037620bde7bb25e95 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -163,14 +163,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - int vblank_lines; - int ret = 0; - -- /* -- * XXX Doesn't work well in interlaced mode yet, partially due -- * to problems in vc4 kms or drm core interlaced mode handling, -- * so disable for now in interlaced mode. -- */ -- if (mode->flags & DRM_MODE_FLAG_INTERLACE) -- return ret; -- - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ -@@ -191,10 +183,15 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - - /* Vertical position of hvs composed scanline. */ - *vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE); -+ *hpos = 0; -+ -+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) { -+ *vpos /= 2; - -- /* No hpos info available. */ -- if (hpos) -- *hpos = 0; -+ /* Use hpos to correct for field offset in interlaced mode. */ -+ if (VC4_GET_FIELD(val, SCALER_DISPSTATX_FRAME_COUNT) % 2) -+ *hpos += mode->crtc_htotal / 2; -+ } - - /* This is the offset we need for translating hvs -> pv scanout pos. */ - fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay; -@@ -217,8 +214,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - * position of the PV. - */ - *vpos -= fifo_lines + 1; -- if (mode->flags & DRM_MODE_FLAG_INTERLACE) -- *vpos /= 2; - - ret |= DRM_SCANOUTPOS_ACCURATE; - return ret; - -From ce12fad8b5a7bbe64cba4fea965cd9b9b3d3552b Mon Sep 17 00:00:00 2001 -From: Mario Kleiner -Date: Tue, 19 Jul 2016 20:59:01 +0200 -Subject: [PATCH 185/208] drm/vc4: Enable/Disable vblanks properly in crtc - en/disable. - -Add missing drm_crtc_vblank_on/off() calls so vblank irq -handling/updating/timestamping never runs with a crtc shut down -or during its shutdown/startup, as that causes large jumps in -vblank count and trouble for compositors. - -Signed-off-by: Mario Kleiner -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 7ffdad543ed2cbb588ad8f2037620bde7bb25e95..2682f07d8f1e6d3dc89ad0858f136c511040b517 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -475,6 +475,9 @@ static void vc4_crtc_disable(struct drm_crtc *crtc) - int ret; - require_hvs_enabled(dev); - -+ /* Disable vblank irq handling before crtc is disabled. */ -+ drm_crtc_vblank_off(crtc); -+ - CRTC_WRITE(PV_V_CONTROL, - CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN); - ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); -@@ -525,6 +528,9 @@ static void vc4_crtc_enable(struct drm_crtc *crtc) - /* Turn on the pixel valve, which will emit the vstart signal. */ - CRTC_WRITE(PV_V_CONTROL, - CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); -+ -+ /* Enable vblank irq handling after crtc is started. */ -+ drm_crtc_vblank_on(crtc); - } - - static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - -From fec57b3556993256fc654768dba939342ca25dc8 Mon Sep 17 00:00:00 2001 +From b3704dd955494e84e7ec6d7d07c8cdad72927139 Mon Sep 17 00:00:00 2001 From: Eric Anholt -Date: Tue, 2 Aug 2016 17:17:52 -0700 -Subject: [PATCH 186/208] drm/vc4: Don't force new binner overflow allocation - per draw. - -This came from the initial bringup code, which always idled the GPU -and always reset the overflow. That massively increases the size of -the working set when you're doing lots of small draws, though, as is -common on X desktops or piglit. +Date: Wed, 14 Sep 2016 09:18:09 +0100 +Subject: [PATCH 102/111] raspberrypi-firmware: Define the MBOX channel in the + header. Signed-off-by: Eric Anholt --- - drivers/gpu/drm/vc4/vc4_gem.c | 4 ---- - 1 file changed, 4 deletions(-) + include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ + 1 file changed, 2 insertions(+) -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index ae1609e739ef424d99207f830cd2bac41ce71557..47a095f392f8a7b5443227933c78b500a4c7137f 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -419,10 +419,6 @@ again: +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +index 09e3d871d110eb0762ebdb5ea329353738d58661..2859db09e25bb945251e85edb39bc43430857168 100644 +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -12,6 +12,8 @@ + #include + #include - vc4_flush_caches(dev); - -- /* Disable the binner's pre-loaded overflow memory address */ -- V3D_WRITE(V3D_BPOA, 0); -- V3D_WRITE(V3D_BPOS, 0); -- - /* Either put the job in the binner if it uses the binner, or - * immediately move it to the to-be-rendered queue. - */ - -From 3560e2aca2425e2b4ea5f5bdb0fa9589ecc125c3 Mon Sep 17 00:00:00 2001 -From: Liu Ying -Date: Mon, 29 Aug 2016 17:12:03 +0800 -Subject: [PATCH 187/208] drm/atomic-helper: Add NO_DISABLE_AFTER_MODESET flag - support for plane commit - -Drivers may set the NO_DISABLE_AFTER_MODESET flag in the 'flags' parameter -of the helper drm_atomic_helper_commit_planes() if the relevant display -controllers(e.g., IPUv3 for imx-drm) require to disable a CRTC's planes -when the CRTC is disabled. The helper would skip the ->atomic_disable -call for a plane if the CRTC of the old plane state needs a modesetting -operation. Of course, the drivers need to disable the planes in their CRTC -disable callbacks since no one else would do that. - -Suggested-by: Daniel Vetter -Cc: Philipp Zabel -Cc: David Airlie -Cc: Russell King -Cc: Peter Senna Tschudin -Cc: Lucas Stach -Signed-off-by: Liu Ying -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1472461923-14364-1-git-send-email-gnuiyl@gmail.com ---- - drivers/gpu/drm/vc4/vc4_kms.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 4ac894d993cd80472777b2a3bacc2fcf0dd52810..c1f65c6c8e601e9331768ca040a5609cad686b2e 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -44,7 +44,7 @@ vc4_atomic_complete_commit(struct vc4_commit *c) - - drm_atomic_helper_commit_modeset_disables(dev, state); - -- drm_atomic_helper_commit_planes(dev, state, false); -+ drm_atomic_helper_commit_planes(dev, state, 0); - - drm_atomic_helper_commit_modeset_enables(dev, state); - - -From 32db4f1829e5531aa6e60ca3020b2c487c945920 Mon Sep 17 00:00:00 2001 -From: Tom Gundersen -Date: Wed, 21 Sep 2016 16:59:19 +0200 -Subject: [PATCH 188/208] drm: Don't swallow error codes in drm_dev_alloc() - -There are many reasons other than ENOMEM that drm_dev_init() can -fail. Return ERR_PTR rather than NULL to be able to distinguish -these in the caller. - -Signed-off-by: Tom Gundersen -Signed-off-by: Sean Paul -Link: http://patchwork.freedesktop.org/patch/msgid/20160921145919.13754-2-teg@jklm.no ---- - drivers/gpu/drm/vc4/vc4_drv.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index eff0530dc713f6ac3cdb5cb3e640abed1cc67492..8703f56b794774ac4130a7b487472e293ebe7cdf 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -233,8 +233,8 @@ static int vc4_drm_bind(struct device *dev) - return -ENOMEM; - - drm = drm_dev_alloc(&vc4_drm_driver, dev); -- if (!drm) -- return -ENOMEM; -+ if (IS_ERR(drm)) -+ return PTR_ERR(drm); - platform_set_drvdata(pdev, drm); - vc4->dev = drm; - drm->dev_private = vc4; - -From 7f1274b2b1e0fe40b2965bad8853cbe3035a3fbe Mon Sep 17 00:00:00 2001 -From: Masahiro Yamada -Date: Tue, 13 Sep 2016 03:35:20 +0900 -Subject: [PATCH 189/208] drm/vc4: cleanup with list_first_entry_or_null() - -The combo of list_empty() check and return list_first_entry() -can be replaced with list_first_entry_or_null(). - -Signed-off-by: Masahiro Yamada -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_drv.h | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index f696b752886b153c4654c0b8acca3fe46c9136cb..7c1e4d97486fb57d9ce7002c30a23138519761ae 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -324,18 +324,15 @@ struct vc4_exec_info { - static inline struct vc4_exec_info * - vc4_first_bin_job(struct vc4_dev *vc4) - { -- if (list_empty(&vc4->bin_job_list)) -- return NULL; -- return list_first_entry(&vc4->bin_job_list, struct vc4_exec_info, head); -+ return list_first_entry_or_null(&vc4->bin_job_list, -+ struct vc4_exec_info, head); - } - - static inline struct vc4_exec_info * - vc4_first_render_job(struct vc4_dev *vc4) - { -- if (list_empty(&vc4->render_job_list)) -- return NULL; -- return list_first_entry(&vc4->render_job_list, -- struct vc4_exec_info, head); -+ return list_first_entry_or_null(&vc4->render_job_list, -+ struct vc4_exec_info, head); - } - - static inline struct vc4_exec_info * - -From ec746edb504c5ac7db80f613e52a0c0dbfc866fa Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 16 Sep 2016 10:59:45 +0100 -Subject: [PATCH 190/208] drm/vc4: Enable limited range RGB output on HDMI with - CEA modes. - -Fixes broken grayscale ramps on many HDMI monitors, where large areas -at the ends of the ramp would all appear as black or white. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 31 +++++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_regs.h | 9 ++++++++- - 2 files changed, 37 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 68ad10634b29ec7b716f70f0b5fd9f2046da1fe5..29be7b7273df5b2c75d3162d72097efe62ec93df 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -298,6 +298,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *unadjusted_mode, - struct drm_display_mode *mode) - { -+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - bool debug_dump_regs = false; -@@ -313,6 +314,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | - VC4_SET_FIELD(mode->vtotal - mode->vsync_end, - VC4_HDMI_VERTB_VBP)); -+ u32 csc_ctl; - - if (debug_dump_regs) { - DRM_INFO("HDMI regs before:\n"); -@@ -351,9 +353,34 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); - -+ csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, -+ VC4_HD_CSC_CTL_ORDER); ++#define RPI_FIRMWARE_CHAN_FB 1 + -+ if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) { -+ /* CEA VICs other than #1 requre limited range RGB -+ * output. Apply a colorspace conversion to squash -+ * 0-255 down to 16-235. The matrix here is: -+ * -+ * [ 0 0 0.8594 16] -+ * [ 0 0.8594 0 16] -+ * [ 0.8594 0 0 16] -+ * [ 0 0 0 1] -+ */ -+ csc_ctl |= VC4_HD_CSC_CTL_ENABLE; -+ csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC; -+ csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, -+ VC4_HD_CSC_CTL_MODE); -+ -+ HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000); -+ HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0); -+ HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000); -+ HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000); -+ HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0); -+ HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000); -+ } -+ - /* The RGB order applies even when CSC is disabled. */ -- HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, -- VC4_HD_CSC_CTL_ORDER)); -+ HD_WRITE(VC4_HD_CSC_CTL, csc_ctl); + struct rpi_firmware; - HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); - -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 160942a9180e716e6c6d890214f0fc6e0e081ecd..9ecd6ff3d493ffca5249256ce99dc2de2b21e0ee 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -528,10 +528,17 @@ - # define VC4_HD_CSC_CTL_MODE_SHIFT 2 - # define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0 - # define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1 --# define VC4_HD_CSC_CTL_MODE_CUSTOM 2 -+# define VC4_HD_CSC_CTL_MODE_CUSTOM 3 - # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) - # define VC4_HD_CSC_CTL_ENABLE BIT(0) - -+#define VC4_HD_CSC_12_11 0x044 -+#define VC4_HD_CSC_14_13 0x048 -+#define VC4_HD_CSC_22_21 0x04c -+#define VC4_HD_CSC_24_23 0x050 -+#define VC4_HD_CSC_32_31 0x054 -+#define VC4_HD_CSC_34_33 0x058 -+ - #define VC4_HD_FRAME_COUNT 0x068 - - /* HVS display list information. */ + enum rpi_firmware_property_status { -From 9bad67df07b8552d61731c2f0e5a5fe0f9d46849 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 19:21:29 +0100 -Subject: [PATCH 191/208] drm/vc4: Fall back to using an EDID probe in the - absence of a GPIO. - -On Pi0/1/2, we use an external GPIO line for hotplug detection, since -the HDMI_HOTPLUG register isn't connected to anything. However, with -the Pi3 the HPD GPIO line has moved off to a GPIO expander that will -be tricky to get to (the firmware is constantly polling the expander -using i2c0, so we'll need to coordinate with it). - -As a stop-gap, if we don't have a GPIO line, use an EDID probe to -detect connection. Fixes HDMI display on the pi3. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 29be7b7273df5b2c75d3162d72097efe62ec93df..1e61931846d3f10cdb7f914e54c260f8b9731cd7 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -174,6 +174,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - return connector_status_disconnected; - } - -+ if (drm_probe_ddc(vc4->hdmi->ddc)) -+ return connector_status_connected; -+ - if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) - return connector_status_connected; - else - -From 45f5d55e2e3214d8e8e0514b1fe7c32ec632357e Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 28 Sep 2016 17:21:05 -0700 -Subject: [PATCH 192/208] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL - changes. - -Fixes occasional debug spew at boot when connected directly through -HDMI, and probably confusing the HDMI state machine when we go trying -to poke registers for the enable sequence too soon. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 1e61931846d3f10cdb7f914e54c260f8b9731cd7..fe1c4e35e68142839756df10ed9b9e56c028d04e 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -424,7 +424,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - - ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & -- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1); -+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000); - WARN_ONCE(ret, "Timeout waiting for " - "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); - } else { -@@ -436,7 +436,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - - ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & -- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1); -+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000); - WARN_ONCE(ret, "Timeout waiting for " - "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); - } - -From 0ec96f64a32dc31a9f1bcbcb367d932622fd9cee Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 28 Sep 2016 17:30:25 -0700 -Subject: [PATCH 193/208] drm/vc4: Fix support for interlaced modes on HDMI. - -We really do need to be using the halved V fields. I had been -confused by the code I was using as a reference because it stored -halved vsync fields but not halved vdisplay, so it looked like I only -needed to divide vdisplay by 2. - -This reverts part of Mario's timestamping fixes that prevented -CRTC_HALVE_V from applying, and instead adjusts the timestamping code -to not use the crtc field in that case. - -Fixes locking of 1920x1080x60i on my Dell 2408WFP. There are black -bars on the top and bottom, but I suspect that might be an -under/overscan flags problem as opposed to video timings. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 49 ++++++++++++++++++++++-------------------- - drivers/gpu/drm/vc4/vc4_hdmi.c | 45 +++++++++++--------------------------- - drivers/gpu/drm/vc4/vc4_regs.h | 3 +++ - 3 files changed, 41 insertions(+), 56 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 2682f07d8f1e6d3dc89ad0858f136c511040b517..83cafea03eff720f9f7b80f484dedf22ac7f283f 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -229,7 +229,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - * and need to make things up in a approximative but consistent way. - */ - ret |= DRM_SCANOUTPOS_IN_VBLANK; -- vblank_lines = mode->crtc_vtotal - mode->crtc_vdisplay; -+ vblank_lines = mode->vtotal - mode->vdisplay; - - if (flags & DRM_CALLED_FROM_VBLIRQ) { - /* -@@ -378,7 +378,6 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - struct drm_crtc_state *state = crtc->state; - struct drm_display_mode *mode = &state->adjusted_mode; - bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; -- u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0)); - u32 format = PV_CONTROL_FORMAT_24; - bool debug_dump_regs = false; - int clock_select = vc4_get_clock_select(crtc); -@@ -404,32 +403,46 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); - - CRTC_WRITE(PV_VERTA, -- VC4_SET_FIELD(mode->vtotal - mode->vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, - PV_VERTA_VBP) | -- VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, -+ VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, - PV_VERTA_VSYNC)); - CRTC_WRITE(PV_VERTB, -- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, -+ VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, - PV_VERTB_VFP) | -- VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); -+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); - - if (interlace) { - CRTC_WRITE(PV_VERTA_EVEN, -- VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1, -+ VC4_SET_FIELD(mode->crtc_vtotal - -+ mode->crtc_vsync_end - 1, - PV_VERTA_VBP) | -- VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, -+ VC4_SET_FIELD(mode->crtc_vsync_end - -+ mode->crtc_vsync_start, - PV_VERTA_VSYNC)); - CRTC_WRITE(PV_VERTB_EVEN, -- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, -+ VC4_SET_FIELD(mode->crtc_vsync_start - -+ mode->crtc_vdisplay, - PV_VERTB_VFP) | -- VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); -+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); -+ -+ /* We set up first field even mode for HDMI. VEC's -+ * NTSC mode would want first field odd instead, once -+ * we support it (to do so, set ODD_FIRST and put the -+ * delay in VSYNCD_EVEN instead). -+ */ -+ CRTC_WRITE(PV_V_CONTROL, -+ PV_VCONTROL_CONTINUOUS | -+ PV_VCONTROL_INTERLACE | -+ VC4_SET_FIELD(mode->htotal / 2, -+ PV_VCONTROL_ODD_DELAY)); -+ CRTC_WRITE(PV_VSYNCD_EVEN, 0); -+ } else { -+ CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); - } - - CRTC_WRITE(PV_HACT_ACT, mode->hdisplay); - -- CRTC_WRITE(PV_V_CONTROL, -- PV_VCONTROL_CONTINUOUS | -- (interlace ? PV_VCONTROL_INTERLACE : 0)); - - CRTC_WRITE(PV_CONTROL, - VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | -@@ -544,16 +557,6 @@ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - return false; - } - -- /* -- * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when -- * coming from user space. We don't want this, as it screws up -- * vblank timestamping, so fix it up. -- */ -- drm_mode_set_crtcinfo(adjusted_mode, 0); -- -- DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id); -- drm_mode_debug_printmodeline(adjusted_mode); -- - return true; - } - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index fe1c4e35e68142839756df10ed9b9e56c028d04e..d94108ca961dac9278d2e38813d089b78acbc8ad 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -211,35 +211,10 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - return ret; - } - --/* -- * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to -- * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it -- * screws up vblank timestamping for interlaced modes, so fix it up. -- */ --static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector, -- uint32_t maxX, uint32_t maxY) --{ -- struct drm_display_mode *mode; -- int count; -- -- count = drm_helper_probe_single_connector_modes(connector, maxX, maxY); -- if (count == 0) -- return 0; -- -- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n", -- connector->base.id, connector->name); -- list_for_each_entry(mode, &connector->modes, head) { -- drm_mode_set_crtcinfo(mode, 0); -- drm_mode_debug_printmodeline(mode); -- } -- -- return count; --} -- - static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .detect = vc4_hdmi_connector_detect, -- .fill_modes = vc4_hdmi_connector_probe_modes, -+ .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_hdmi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -@@ -307,16 +282,20 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - bool debug_dump_regs = false; - bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; - bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; -- u32 vactive = (mode->vdisplay >> -- ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0)); -- u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, -+ bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; -+ u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, - VC4_HDMI_VERTA_VSP) | -- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, -+ VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, - VC4_HDMI_VERTA_VFP) | -- VC4_SET_FIELD(vactive, VC4_HDMI_VERTA_VAL)); -+ VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); - u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | -- VC4_SET_FIELD(mode->vtotal - mode->vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, - VC4_HDMI_VERTB_VBP)); -+ u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | -+ VC4_SET_FIELD(mode->crtc_vtotal - -+ mode->crtc_vsync_end - -+ interlaced, -+ VC4_HDMI_VERTB_VBP)); - u32 csc_ctl; - - if (debug_dump_regs) { -@@ -349,7 +328,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - HDMI_WRITE(VC4_HDMI_VERTA0, verta); - HDMI_WRITE(VC4_HDMI_VERTA1, verta); - -- HDMI_WRITE(VC4_HDMI_VERTB0, vertb); -+ HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even); - HDMI_WRITE(VC4_HDMI_VERTB1, vertb); - - HD_WRITE(VC4_HD_VID_CTL, -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 9ecd6ff3d493ffca5249256ce99dc2de2b21e0ee..c5a423ead86ffdd1ce2abada24f628b19c1ebc08 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -183,6 +183,9 @@ - # define PV_CONTROL_EN BIT(0) - - #define PV_V_CONTROL 0x04 -+# define PV_VCONTROL_ODD_DELAY_MASK VC4_MASK(22, 6) -+# define PV_VCONTROL_ODD_DELAY_SHIFT 6 -+# define PV_VCONTROL_ODD_FIRST BIT(5) - # define PV_VCONTROL_INTERLACE BIT(4) - # define PV_VCONTROL_CONTINUOUS BIT(1) - # define PV_VCONTROL_VIDEN BIT(0) - -From d1475342b1f4cf8f9a51428a64f04ae50c45c9c8 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 29 Sep 2016 15:34:43 -0700 -Subject: [PATCH 194/208] drm/vc4: Set up the AVI and SPD infoframes. - -Fixes a purple bar on the left side of the screen with my Dell -2408WFP. It will also be required for supporting the double-clocked -video modes. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 136 +++++++++++++++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_regs.h | 5 ++ - 2 files changed, 136 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index d94108ca961dac9278d2e38813d089b78acbc8ad..d6b54b905beeec33eee8a763969ffa9568cfa745 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -62,6 +62,8 @@ struct vc4_hdmi { - struct vc4_hdmi_encoder { - struct vc4_encoder base; - bool hdmi_monitor; -+ bool limited_rgb_range; -+ bool rgb_range_selectable; - }; - - static inline struct vc4_hdmi_encoder * -@@ -205,6 +207,12 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - return -ENODEV; - - vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); -+ -+ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { -+ vc4_encoder->rgb_range_selectable = -+ drm_rgb_quant_range_selectable(edid); -+ } -+ - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - -@@ -272,6 +280,117 @@ static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = { - .destroy = vc4_hdmi_encoder_destroy, - }; - -+static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, -+ enum hdmi_infoframe_type type) -+{ -+ struct drm_device *dev = encoder->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ u32 packet_id = type - 0x80; -+ -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, -+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); -+ -+ return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & -+ BIT(packet_id)), 100); -+} -+ -+static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, -+ union hdmi_infoframe *frame) -+{ -+ struct drm_device *dev = encoder->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ u32 packet_id = frame->any.type - 0x80; -+ u32 packet_reg = VC4_HDMI_GCP_0 + VC4_HDMI_PACKET_STRIDE * packet_id; -+ uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; -+ ssize_t len, i; -+ int ret; -+ -+ WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & -+ VC4_HDMI_RAM_PACKET_ENABLE), -+ "Packet RAM has to be on to store the packet."); -+ -+ len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); -+ if (len < 0) -+ return; -+ -+ ret = vc4_hdmi_stop_packet(encoder, frame->any.type); -+ if (ret) { -+ DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret); -+ return; -+ } -+ -+ for (i = 0; i < len; i += 7) { -+ HDMI_WRITE(packet_reg, -+ buffer[i + 0] << 0 | -+ buffer[i + 1] << 8 | -+ buffer[i + 2] << 16); -+ packet_reg += 4; -+ -+ HDMI_WRITE(packet_reg, -+ buffer[i + 3] << 0 | -+ buffer[i + 4] << 8 | -+ buffer[i + 5] << 16 | -+ buffer[i + 6] << 24); -+ packet_reg += 4; -+ } -+ -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, -+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); -+ ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & -+ BIT(packet_id)), 100); -+ if (ret) -+ DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); -+} -+ -+static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) -+{ -+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); -+ struct drm_crtc *crtc = encoder->crtc; -+ const struct drm_display_mode *mode = &crtc->state->adjusted_mode; -+ union hdmi_infoframe frame; -+ int ret; -+ -+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); -+ if (ret < 0) { -+ DRM_ERROR("couldn't fill AVI infoframe\n"); -+ return; -+ } -+ -+ if (vc4_encoder->rgb_range_selectable) { -+ if (vc4_encoder->limited_rgb_range) { -+ frame.avi.quantization_range = -+ HDMI_QUANTIZATION_RANGE_LIMITED; -+ } else { -+ frame.avi.quantization_range = -+ HDMI_QUANTIZATION_RANGE_FULL; -+ } -+ } -+ -+ vc4_hdmi_write_infoframe(encoder, &frame); -+} -+ -+static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) -+{ -+ union hdmi_infoframe frame; -+ int ret; -+ -+ ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore"); -+ if (ret < 0) { -+ DRM_ERROR("couldn't fill SPD infoframe\n"); -+ return; -+ } -+ -+ frame.spd.sdi = HDMI_SPD_SDI_PC; -+ -+ vc4_hdmi_write_infoframe(encoder, &frame); -+} -+ -+static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) -+{ -+ vc4_hdmi_set_avi_infoframe(encoder); -+ vc4_hdmi_set_spd_infoframe(encoder); -+} -+ - static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *unadjusted_mode, - struct drm_display_mode *mode) -@@ -340,8 +459,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - - if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) { - /* CEA VICs other than #1 requre limited range RGB -- * output. Apply a colorspace conversion to squash -- * 0-255 down to 16-235. The matrix here is: -+ * output unless overridden by an AVI infoframe. -+ * Apply a colorspace conversion to squash 0-255 down -+ * to 16-235. The matrix here is: - * - * [ 0 0 0.8594 16] - * [ 0 0.8594 0 16] -@@ -359,6 +479,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000); - HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0); - HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000); -+ vc4_encoder->limited_rgb_range = true; -+ } else { -+ vc4_encoder->limited_rgb_range = false; - } - - /* The RGB order applies even when CSC is disabled. */ -@@ -377,6 +500,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0); -+ - HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); - HD_WRITE(VC4_HD_VID_CTL, - HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); -@@ -429,9 +554,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | - VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT); - -- /* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set -- * up the infoframe. -- */ -+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, -+ VC4_HDMI_RAM_PACKET_ENABLE); -+ -+ vc4_hdmi_set_infoframes(encoder); - - drift = HDMI_READ(VC4_HDMI_FIFO_CTL); - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index c5a423ead86ffdd1ce2abada24f628b19c1ebc08..0b868aafa8db69b0a08fe9cbf293263a0a7c5bed 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -441,6 +441,8 @@ - #define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0 - # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16) - -+#define VC4_HDMI_RAM_PACKET_STATUS 0x0a4 -+ - #define VC4_HDMI_HORZA 0x0c4 - # define VC4_HDMI_HORZA_VPOS BIT(14) - # define VC4_HDMI_HORZA_HPOS BIT(13) -@@ -502,6 +504,9 @@ - - #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 - -+#define VC4_HDMI_GCP_0 0x400 -+#define VC4_HDMI_PACKET_STRIDE 0x24 -+ - #define VC4_HD_M_CTL 0x00c - # define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6) - # define VC4_HD_M_RAM_STANDBY (3 << 4) - -From d06d8d96a9423f1a5268377bddbd93a3a3fc20af Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 29 Sep 2016 15:34:44 -0700 -Subject: [PATCH 195/208] drm/vc4: Add support for double-clocked modes. - -Now that we have infoframes to report the pixel repeat flag, we can -start using it. Fixes locking the 720x480i and 720x576i modes on my -Dell 2408WFP. Like the 1920x1080i case, they don't fit properly on -the screen, though. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++------ - drivers/gpu/drm/vc4/vc4_hdmi.c | 16 +++++++++++----- - drivers/gpu/drm/vc4/vc4_regs.h | 2 ++ - 3 files changed, 24 insertions(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 83cafea03eff720f9f7b80f484dedf22ac7f283f..7f08d681a74b4e37529f6c09ae1d2c1a944dcabd 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -378,6 +378,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - struct drm_crtc_state *state = crtc->state; - struct drm_display_mode *mode = &state->adjusted_mode; - bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; -+ u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; - u32 format = PV_CONTROL_FORMAT_24; - bool debug_dump_regs = false; - int clock_select = vc4_get_clock_select(crtc); -@@ -393,14 +394,17 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - CRTC_WRITE(PV_CONTROL, 0); - - CRTC_WRITE(PV_HORZA, -- VC4_SET_FIELD(mode->htotal - mode->hsync_end, -+ VC4_SET_FIELD((mode->htotal - -+ mode->hsync_end) * pixel_rep, - PV_HORZA_HBP) | -- VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, -+ VC4_SET_FIELD((mode->hsync_end - -+ mode->hsync_start) * pixel_rep, - PV_HORZA_HSYNC)); - CRTC_WRITE(PV_HORZB, -- VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, -+ VC4_SET_FIELD((mode->hsync_start - -+ mode->hdisplay) * pixel_rep, - PV_HORZB_HFP) | -- VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); -+ VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE)); - - CRTC_WRITE(PV_VERTA, - VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, -@@ -434,20 +438,21 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - CRTC_WRITE(PV_V_CONTROL, - PV_VCONTROL_CONTINUOUS | - PV_VCONTROL_INTERLACE | -- VC4_SET_FIELD(mode->htotal / 2, -+ VC4_SET_FIELD(mode->htotal * pixel_rep / 2, - PV_VCONTROL_ODD_DELAY)); - CRTC_WRITE(PV_VSYNCD_EVEN, 0); - } else { - CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); - } - -- CRTC_WRITE(PV_HACT_ACT, mode->hdisplay); -+ CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); - - - CRTC_WRITE(PV_CONTROL, - VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | - VC4_SET_FIELD(vc4_get_fifo_full_level(format), - PV_CONTROL_FIFO_LEVEL) | -+ VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) | - PV_CONTROL_CLR_AT_START | - PV_CONTROL_TRIGGER_UNDERFLOW | - PV_CONTROL_WAIT_HSTART | -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index d6b54b905beeec33eee8a763969ffa9568cfa745..c4cb2e26de32f06db0abf3fd94b3117c3292eed5 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -402,6 +402,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; - bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; - bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; -+ u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; - u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, - VC4_HDMI_VERTA_VSP) | - VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, -@@ -424,7 +425,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - - HD_WRITE(VC4_HD_VID_CTL, 0); - -- clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000); -+ clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000 * -+ ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1)); - - HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | -@@ -434,14 +436,18 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, - HDMI_WRITE(VC4_HDMI_HORZA, - (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | - (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | -- VC4_SET_FIELD(mode->hdisplay, VC4_HDMI_HORZA_HAP)); -+ VC4_SET_FIELD(mode->hdisplay * pixel_rep, -+ VC4_HDMI_HORZA_HAP)); - - HDMI_WRITE(VC4_HDMI_HORZB, -- VC4_SET_FIELD(mode->htotal - mode->hsync_end, -+ VC4_SET_FIELD((mode->htotal - -+ mode->hsync_end) * pixel_rep, - VC4_HDMI_HORZB_HBP) | -- VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, -+ VC4_SET_FIELD((mode->hsync_end - -+ mode->hsync_start) * pixel_rep, - VC4_HDMI_HORZB_HSP) | -- VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, -+ VC4_SET_FIELD((mode->hsync_start - -+ mode->hdisplay) * pixel_rep, - VC4_HDMI_HORZB_HFP)); - - HDMI_WRITE(VC4_HDMI_VERTA0, verta); -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 0b868aafa8db69b0a08fe9cbf293263a0a7c5bed..1aa44c2db5565ba126d2ceb65495a6c98c555860 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -175,6 +175,8 @@ - # define PV_CONTROL_CLR_AT_START BIT(14) - # define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13) - # define PV_CONTROL_WAIT_HSTART BIT(12) -+# define PV_CONTROL_PIXEL_REP_MASK VC4_MASK(5, 4) -+# define PV_CONTROL_PIXEL_REP_SHIFT 4 - # define PV_CONTROL_CLK_SELECT_DSI_VEC 0 - # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 - # define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2) - -From 68dde0cad20ec7f9c40100cbcfd744d61bdc298a Mon Sep 17 00:00:00 2001 +From ea0597439af226851168bcee2b9e122c17e22567 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 08:39:33 +0100 -Subject: [PATCH 196/208] drm/vc4: Add a mode for using the closed firmware for +Subject: [PATCH 103/111] drm/vc4: Add a mode for using the closed firmware for display. Signed-off-by: Eric Anholt @@ -149902,1253 +124292,841 @@ index 0000000000000000000000000000000000000000..d18a1dae51a2275846c9826b5bf1ba57 + }, +}; -From 1e7e72efacf0401c04fe4295b8c615350a41d6d0 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Wed, 10 Aug 2016 18:52:34 +0200 -Subject: [PATCH 197/208] drm/fb-helper: Add a dummy - remove_conflicting_framebuffers +From d9f0d5cad9768b3b249cf0e45d45f31c0e941f26 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Sat, 17 Sep 2016 15:07:10 +0200 +Subject: [PATCH 104/111] i2c: bcm2835: Fix hang for writing messages larger + than 16 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Lots of drivers don't properly compile without this when CONFIG_FB=n. -It's kinda a hack, but since CONFIG_FB doesn't stub any fucntions when -it's disabled I think it makes sense to add it to drm_fb_helper.h. +Writing messages larger than the FIFO size results in a hang, rendering +the machine unusable. This is because the RXD status flag is set on the +first interrupt which results in bcm2835_drain_rxfifo() stealing bytes +from the buffer. The controller continues to trigger interrupts waiting +for the missing bytes, but bcm2835_fill_txfifo() has none to give. +In this situation wait_for_completion_timeout() apparently is unable to +stop the madness. -Long term we probably need to rethink all the logic to unload firmware -framebuffer drivers, at least if we want to be able to move away from -CONFIG_FB and fbcon. +The BCM2835 ARM Peripherals datasheet has this to say about the flags: + TXD: is set when the FIFO has space for at least one byte of data. + RXD: is set when the FIFO contains at least one byte of data. + TXW: is set during a write transfer and the FIFO is less than full. + RXR: is set during a read transfer and the FIFO is or more full. -v2: Unfortunately just stubbing out remove_conflicting_framebuffers in -drm_fb_helper.h upset gcc about static vs. non-static declarations, so -a new wrapper it needs to be. Means more churn :( +Implementing the logic from the downstream i2c-bcm2708 driver solved +the hang problem. -Cc: Tobias Jakobi -Cc: Noralf Trønnes -Cc: tomi.valkeinen@ti.com -Cc: dh.herrmann@gmail.com -Reviewed-by: Alex Deucher -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1470847958-28465-2-git-send-email-daniel.vetter@ffwll.ch ---- - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- - drivers/gpu/drm/bochs/bochs_drv.c | 3 ++- - drivers/gpu/drm/cirrus/cirrus_drv.c | 2 +- - drivers/gpu/drm/i915/i915_drv.c | 2 +- - drivers/gpu/drm/mgag200/mgag200_drv.c | 2 +- - drivers/gpu/drm/mgag200/mgag200_main.c | 2 +- - drivers/gpu/drm/nouveau/nouveau_drm.c | 2 +- - drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- - drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++- - drivers/gpu/drm/virtio/virtgpu_drm_bus.c | 3 ++- - include/drm/drm_fb_helper.h | 14 ++++++++++++++ - 11 files changed, 28 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -index 414a1600da54b5a108638d86246429d5796562db..6e37e8b7c0f2fc67ecb7e3b98515217d17808e22 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -@@ -341,7 +341,7 @@ static int amdgpu_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "amdgpudrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "amdgpudrmfb", primary); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c -index abace82de6eac2de22b747ff54a5612443f69647..277654abe0f79e768c525380623dc1896749b4cb 100644 ---- a/drivers/gpu/drm/bochs/bochs_drv.c -+++ b/drivers/gpu/drm/bochs/bochs_drv.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - #include "bochs.h" - -@@ -153,7 +154,7 @@ static int bochs_kick_out_firmware_fb(struct pci_dev *pdev) - - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); -- remove_conflicting_framebuffers(ap, "bochsdrmfb", false); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "bochsdrmfb", false); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c -index b05f7eae32ce756e39f656adcbadc2ddfb55893c..6c76d125995bef3f20b566292aeeb7ad9122c86d 100644 ---- a/drivers/gpu/drm/cirrus/cirrus_drv.c -+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c -@@ -57,7 +57,7 @@ static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c -index d46fa2206722855856920de5e6d3817fe75679ab..71d8859aa32d424f86d63f4df5e4b5240d6e0906 100644 ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -706,7 +706,7 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) - primary = - pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - -- ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary); -+ ret = drm_fb_helper_remove_conflicting_framebuffers(ap, "inteldrmfb", primary); - - kfree(ap); - -diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c -index 2b4b125eebc3ef9e5987d3bcc32d429f5b15ff8e..1443b3a34775cbcaca50532482cfa32fd3052671 100644 ---- a/drivers/gpu/drm/mgag200/mgag200_drv.c -+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c -@@ -56,7 +56,7 @@ static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "mgag200drmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "mgag200drmfb", primary); - kfree(ap); - } - -diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c -index 13798b3e6bebbf0b8a62b39c60b9494659d5264d..e79cbc25ae3c54048b21c6293ea340b91b0750fc 100644 ---- a/drivers/gpu/drm/mgag200/mgag200_main.c -+++ b/drivers/gpu/drm/mgag200/mgag200_main.c -@@ -135,7 +135,7 @@ static int mga_vram_init(struct mga_device *mdev) - aper->ranges[0].base = mdev->mc.vram_base; - aper->ranges[0].size = mdev->mc.vram_window; - -- remove_conflicting_framebuffers(aper, "mgafb", true); -+ drm_fb_helper_remove_conflicting_framebuffers(aper, "mgafb", true); - kfree(aper); - - if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window, -diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c -index 66c1280c0f1f2854aa501f810c50a11e6149eaaa..652ab111dd74d899cc9aac867e05791e0a64229f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c -@@ -351,7 +351,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev, - boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif - if (nouveau_modeset != 2) -- remove_conflicting_framebuffers(aper, "nouveaufb", boot); -+ drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot); - kfree(aper); - - ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug, -diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c -index c01a7c6abb491c4227ad02fd6525813a7a9d3d55..90f2ff217b3123e70ed17b6d0ed34c17eadd527e 100644 ---- a/drivers/gpu/drm/radeon/radeon_drv.c -+++ b/drivers/gpu/drm/radeon/radeon_drv.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - - #include "drm_crtc_helper.h" - #include "radeon_kfd.h" -@@ -324,7 +325,7 @@ static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) - #ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- remove_conflicting_framebuffers(ap, "radeondrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "radeondrmfb", primary); - kfree(ap); - - return 0; -diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c -index 7092daaf6c432b8fa8d2bb93bda63785cf307f01..8913c151b37f475acdbee1f41074188c4430a00d 100644 ---- a/drivers/gpu/drm/sun4i/sun4i_drv.c -+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "sun4i_crtc.h" - #include "sun4i_drv.h" -@@ -109,7 +110,7 @@ static void sun4i_remove_framebuffers(void) - ap->ranges[0].base = 0; - ap->ranges[0].size = ~0; - -- remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false); - kfree(ap); - } - -diff --git a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c -index 88a39165edd50705d561ca8c5d23df2ac628f9a1..cf142737a1667227240c9c88d0c6864df39003de 100644 ---- a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c -+++ b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c -@@ -24,6 +24,7 @@ - */ - - #include -+#include - - #include "virtgpu_drv.h" - -@@ -52,7 +53,7 @@ static void virtio_pci_kick_out_firmware_fb(struct pci_dev *pci_dev) - primary = pci_dev->resource[PCI_ROM_RESOURCE].flags - & IORESOURCE_ROM_SHADOW; - -- remove_conflicting_framebuffers(ap, "virtiodrmfb", primary); -+ drm_fb_helper_remove_conflicting_framebuffers(ap, "virtiodrmfb", primary); - - kfree(ap); - } -diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h -index db8d4780eaa27607baf7857111c72b50bbae5fd4..130c324f1aeeddd25c996a766baaf3d8e26ac110 100644 ---- a/include/drm/drm_fb_helper.h -+++ b/include/drm/drm_fb_helper.h -@@ -32,6 +32,7 @@ - - struct drm_fb_helper; - -+#include - #include - - enum mode_set_atomic { -@@ -282,6 +283,12 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, - int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); - int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector); -+static inline int -+drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, -+ const char *name, bool primary) -+{ -+ return remove_conflicting_framebuffers(a, name, primary); -+} - #else - static inline int drm_fb_helper_modinit(void) - { -@@ -475,5 +482,12 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - { - return 0; - } -+ -+static inline int -+drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, -+ const char *name, bool primary) -+{ -+ return 0; -+} - #endif - #endif - -From c5b9aa24bc98cb757a296d6d26cd27a1728a48cd Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 08:52:26 +0100 -Subject: [PATCH 198/208] BCM270X: Add an overlay for enabling the vc4 driver - in firmware-KMS mode. - -This gets us normal 3D support on top of the existing firmware display -stack. There's no real modesetting support, no async pageflips -(hurting performance), etc., but it means that the desktop can at -least run until we get full native modesetting. - -Signed-off-by: Eric Anholt ---- - arch/arm/boot/dts/bcm270x.dtsi | 11 +++ - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 11 +++ - .../arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 89 ++++++++++++++++++++++ - 4 files changed, 112 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts - -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -index 514b481d4f4095dc8b55a216ac7335934973e145..a46cb4a8b1419edd95e0e07c18b0f373222dc2bf 100644 ---- a/arch/arm/boot/dts/bcm270x.dtsi -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -1,4 +1,5 @@ - /* Downstream bcm283x.dtsi diff */ -+#include "dt-bindings/power/raspberrypi-power.h" - - / { - chosen { -@@ -88,6 +89,15 @@ - status = "disabled"; - }; - -+ firmwarekms: firmwarekms@7e600000 { -+ compatible = "raspberrypi,rpi-firmware-kms"; -+ /* SMI interrupt reg */ -+ reg = <0x7e600000 0x100>; -+ interrupts = <2 16>; -+ brcm,firmware = <&firmware>; -+ status = "disabled"; -+ }; -+ - smi: smi@7e600000 { - compatible = "brcm,bcm2835-smi"; - reg = <0x7e600000 0x100>; -@@ -119,6 +129,7 @@ - - v3d@7ec00000 { /* vd3 */ - compatible = "brcm,vc4-v3d"; -+ power-domains = <&power RPI_POWER_DOMAIN_V3D>; - status = "disabled"; - }; - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index a3ddb4577ce1f671f4c23ebe32c434c97b00781c..7624812d0cdc74728f3556159871c7a299f9f6b7 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -90,6 +90,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - spi2-3cs.dtbo \ - tinylcd35.dtbo \ - uart1.dtbo \ -+ vc4-fkms-v3d.dtbo \ - vc4-kms-v3d.dtbo \ - vga666.dtbo \ - w1-gpio.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 496e31db0c7d22934bd381aea5e7227c26a3f034..c0290531a61fedfe23e820ca4d9693a0acd3e876 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -1276,6 +1276,17 @@ Params: txd1_pin GPIO pin for TXD1 (14, 32 or 40 - default 14) - rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15) - - -+Name: vc4-fkms-v3d -+Info: Enable Eric Anholt's DRM VC4 V3D driver on top of the dispmanx -+ display stack. -+Load: dtoverlay=vc4-fkms-v3d, -+Params: cma-256 CMA is 256MB, 256MB-aligned (needs 1GB) -+ cma-192 CMA is 192MB, 256MB-aligned (needs 1GB) -+ cma-128 CMA is 128MB, 128MB-aligned -+ cma-96 CMA is 96MB, 128MB-aligned -+ cma-64 CMA is 64MB, 64MB-aligned -+ -+ - Name: vc4-kms-v3d - Info: Enable Eric Anholt's DRM VC4 HDMI/HVS/V3D driver. Running startx or - booting to GUI while this overlay is in use will cause interesting -diff --git a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..95a595a35cb4fbb707bf4b18161f6a46860aa4ae ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts -@@ -0,0 +1,89 @@ -+/* -+ * vc4-fkms-v3d-overlay.dts -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target-path = "/chosen"; -+ __overlay__ { -+ bootargs = "cma=256M@256M"; -+ }; -+ }; -+ -+ fragment@1 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=192M@256M"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=128M@128M"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=96M@128M"; -+ }; -+ }; -+ -+ fragment@4 { -+ target-path = "/chosen"; -+ __dormant__ { -+ bootargs = "cma=64M@64M"; -+ }; -+ }; -+ -+ fragment@5 { -+ target = <&fb>; -+ __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@6 { -+ target = <&firmwarekms>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@7 { -+ target = <&v3d>; -+ __overlay__ { -+ interrupts = <1 10>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@8 { -+ target = <&gpu>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@9 { -+ target-path = "/soc/dma"; -+ __overlay__ { -+ brcm,dma-channel-mask = <0x7f35>; -+ }; -+ }; -+ -+ __overrides__ { -+ cma-256 = <0>,"+0-1-2-3-4"; -+ cma-192 = <0>,"-0+1-2-3-4"; -+ cma-128 = <0>,"-0-1+2-3-4"; -+ cma-96 = <0>,"-0-1-2+3-4"; -+ cma-64 = <0>,"-0-1-2-3+4"; -+ }; -+}; - -From 23f34d57b322879bdba8291a9b41818fc9001d53 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Thu, 13 Oct 2016 11:54:31 +0300 -Subject: [PATCH 199/208] drm/vc4: Fix a couple error codes in - vc4_cl_lookup_bos() - -If the allocation fails the current code returns success. If -copy_from_user() fails it returns the number of bytes remaining instead -of -EFAULT. - -Fixes: d5b1a78a772f ("drm/vc4: Add support for drawing 3D frames.") -Signed-off-by: Dan Carpenter +Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt -(cherry picked from commit b2cdeb19f16ad984eb5bb9193f793d05a8101511) +Reviewed-by: Martin Sperl --- - drivers/gpu/drm/vc4/vc4_gem.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) + drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index 47a095f392f8a7b5443227933c78b500a4c7137f..303f23c962206836d8c95786ad835d7625e10ee8 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -544,14 +544,15 @@ vc4_cl_lookup_bos(struct drm_device *dev, - - handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t)); - if (!handles) { -+ ret = -ENOMEM; - DRM_ERROR("Failed to allocate incoming GEM handles\n"); - goto fail; +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index d4f3239b56865919e1b781b20a7c5ebcd76b4eb9..f283b714aa79e2e4685ed95b04b6b289f7e9eee7 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { + int irq; + struct i2c_adapter adapter; + struct completion completion; ++ struct i2c_msg *curr_msg; + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; +@@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + return IRQ_HANDLED; } -- ret = copy_from_user(handles, -- (void __user *)(uintptr_t)args->bo_handles, -- exec->bo_count * sizeof(uint32_t)); -- if (ret) { -+ if (copy_from_user(handles, -+ (void __user *)(uintptr_t)args->bo_handles, -+ exec->bo_count * sizeof(uint32_t))) { -+ ret = -EFAULT; - DRM_ERROR("Failed to copy in GEM handles\n"); - goto fail; - } - -From 46096f860ad1bbc61716e6b83b08c8e469da213b Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 20 Oct 2016 16:48:12 -0700 -Subject: [PATCH 200/208] drm/vc4: Fix termination of the initial scan for - branch targets. - -The loop is scanning until the original max_ip (size of the BO), but -we want to not examine any code after the PROG_END's delay slots. -There was a block trying to do that, except that we had some early -continue statements if the signal wasn't a PROG_END or a BRANCH. - -The failure mode would be that a valid shader is rejected because some -undefined memory after the PROG_END slots is parsed as a branch and -the rest of its setup is illegal. I haven't seen this in the wild, -but valgrind was complaining when about this up in the userland -simulator mode. - -Signed-off-by: Eric Anholt -(cherry picked from commit 457e67a728696c4f8e6423c64e93def50530db9a) ---- - drivers/gpu/drm/vc4/vc4_validate_shaders.c | 19 ++++++++----------- - 1 file changed, 8 insertions(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -index 2543cf5b8b51869d51b72a5db5017dded38761be..917321ce832ffda9d3e8ca20d987437eea9a1765 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c -+++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -@@ -608,9 +608,7 @@ static bool - vc4_validate_branches(struct vc4_shader_validation_state *validation_state) - { - uint32_t max_branch_target = 0; -- bool found_shader_end = false; - int ip; -- int shader_end_ip = 0; - int last_branch = -2; - - for (ip = 0; ip < validation_state->max_ip; ip++) { -@@ -621,8 +619,13 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state) - uint32_t branch_target_ip; - - if (sig == QPU_SIG_PROG_END) { -- shader_end_ip = ip; -- found_shader_end = true; -+ /* There are two delay slots after program end is -+ * signaled that are still executed, then we're -+ * finished. validation_state->max_ip is the -+ * instruction after the last valid instruction in the -+ * program. -+ */ -+ validation_state->max_ip = ip + 3; - continue; - } - -@@ -676,15 +679,9 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state) - } - set_bit(after_delay_ip, validation_state->branch_targets); - max_branch_target = max(max_branch_target, after_delay_ip); -- -- /* There are two delay slots after program end is signaled -- * that are still executed, then we're finished. -- */ -- if (found_shader_end && ip == shader_end_ip + 2) -- break; - } - -- if (max_branch_target > shader_end_ip) { -+ if (max_branch_target > validation_state->max_ip - 3) { - DRM_ERROR("Branch landed after QPU_SIG_PROG_END"); - return false; - } - -From 1d26463c7b768495482c7883e08685ade635c9c2 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 3 Nov 2016 18:53:10 -0700 -Subject: [PATCH 201/208] drm/vc4: Add support for rendering with ETC1 - textures. - -The validation for it ends up being quite simple, but I hadn't got -around to it before merging the driver. For backwards compatibility, -we also need to add a flag so that the userspace GL driver can easily -tell if the kernel will allow ETC1 textures (on an old kernel, it will -continue to convert to RGBA8) - -Signed-off-by: Eric Anholt -(cherry picked from commit 7154d76fedf549607afbc0d13db9aaf02da5cebf) ---- - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - drivers/gpu/drm/vc4/vc4_validate.c | 7 +++++++ - include/uapi/drm/vc4_drm.h | 1 + - 3 files changed, 9 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 6c4a4fbc86d0a30a6977b2081bca4372e693b817..157e08ab27771854ffbad101f61ce81e27001e1a 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -78,6 +78,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, - pm_runtime_put(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_SUPPORTS_BRANCHES: -+ case DRM_VC4_PARAM_SUPPORTS_ETC1: - args->value = true; - break; - default: -diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c -index 26503e307438a34fe526222c8c15be158eb332a2..e18f88203d32f828b7256a05c653586c14095ef3 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate.c -+++ b/drivers/gpu/drm/vc4/vc4_validate.c -@@ -644,6 +644,13 @@ reloc_tex(struct vc4_exec_info *exec, - cpp = 1; - break; - case VC4_TEXTURE_TYPE_ETC1: -+ /* ETC1 is arranged as 64-bit blocks, where each block is 4x4 -+ * pixels. -+ */ -+ cpp = 8; -+ width = (width + 3) >> 2; -+ height = (height + 3) >> 2; -+ break; - case VC4_TEXTURE_TYPE_BW1: - case VC4_TEXTURE_TYPE_A4: - case VC4_TEXTURE_TYPE_A1: -diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h -index ad7edc3edf7ca1d653a0bc025a5eda6692b74370..69caa21f0cb23c9439238f6239c0041b178d5669 100644 ---- a/include/uapi/drm/vc4_drm.h -+++ b/include/uapi/drm/vc4_drm.h -@@ -286,6 +286,7 @@ struct drm_vc4_get_hang_state { - #define DRM_VC4_PARAM_V3D_IDENT1 1 - #define DRM_VC4_PARAM_V3D_IDENT2 2 - #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 -+#define DRM_VC4_PARAM_SUPPORTS_ETC1 4 - - struct drm_vc4_get_param { - __u32 param; - -From 574fbee0c80641a4f2bcc24f30c8c14a54544d1d Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 4 Nov 2016 15:58:38 -0700 -Subject: [PATCH 202/208] drm/vc4: Use runtime autosuspend to avoid thrashing - V3D power state. - -The pm_runtime_put() we were using immediately released power on the -device, which meant that we were generally turning the device off and -on once per frame. In many profiles I've looked at, that added up to -about 1% of CPU time, but this could get worse in the case of frequent -rendering and readback (as may happen in X rendering). By keeping the -device on until we've been idle for a couple of frames, we drop the -overhead of runtime PM down to sub-.1%. - -Signed-off-by: Eric Anholt -(cherry picked from commit 3a62234680d86efa0239665ed8a0e908f1aef147) ---- - drivers/gpu/drm/vc4/vc4_drv.c | 9 ++++++--- - drivers/gpu/drm/vc4/vc4_gem.c | 6 ++++-- - drivers/gpu/drm/vc4/vc4_v3d.c | 2 ++ - 3 files changed, 12 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 157e08ab27771854ffbad101f61ce81e27001e1a..8302bd788be470fd61a7382b8c3ef16e26f6861d 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -61,21 +61,24 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, - if (ret < 0) - return ret; - args->value = V3D_READ(V3D_IDENT0); -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_V3D_IDENT1: - ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); - if (ret < 0) - return ret; - args->value = V3D_READ(V3D_IDENT1); -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_V3D_IDENT2: - ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); - if (ret < 0) - return ret; - args->value = V3D_READ(V3D_IDENT2); -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); - break; - case DRM_VC4_PARAM_SUPPORTS_BRANCHES: - case DRM_VC4_PARAM_SUPPORTS_ETC1: -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index 303f23c962206836d8c95786ad835d7625e10ee8..db920771bfb5641c9d5d8e53a8f73cf7ee501bb7 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -709,8 +709,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) - } - - mutex_lock(&vc4->power_lock); -- if (--vc4->power_refcount == 0) -- pm_runtime_put(&vc4->v3d->pdev->dev); -+ if (--vc4->power_refcount == 0) { -+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); -+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); -+ } - mutex_unlock(&vc4->power_lock); - - kfree(exec); -diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c -index e6d3c6028341e447df293cab525713ac10d8ee5e..7cc346ad9b0baed63701d1fae8f0306aa7713129 100644 ---- a/drivers/gpu/drm/vc4/vc4_v3d.c -+++ b/drivers/gpu/drm/vc4/vc4_v3d.c -@@ -222,6 +222,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) - return ret; - } - -+ pm_runtime_use_autosuspend(dev); -+ pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ - pm_runtime_enable(dev); - - return 0; - -From d90a754daaeb289afe12b1991c3cf08fe9bb423d Mon Sep 17 00:00:00 2001 -From: Jonas Pfeil -Date: Tue, 8 Nov 2016 00:18:39 +0100 -Subject: [PATCH 203/208] drm/vc4: Add fragment shader threading support - -FS threading brings performance improvements of 0-20% in glmark2. - -The validation code checks for thread switch signals and ensures that -the registers of the other thread are not touched, and that our clamps -are not live across thread switches. It also checks that the -threading and branching instructions do not interfere. - -(Original patch by Jonas, changes by anholt for style cleanup, -removing validation the kernel doesn't need to do, and adding the flag -for userspace). - -v2: Minor style fixes from checkpatch. - -Signed-off-by: Jonas Pfeil -Signed-off-by: Eric Anholt -(cherry picked from commit c778cc5df944291dcdb1ca7a6bb781fbc22550c5) ---- - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.h | 2 + - drivers/gpu/drm/vc4/vc4_validate.c | 17 +++++--- - drivers/gpu/drm/vc4/vc4_validate_shaders.c | 63 ++++++++++++++++++++++++++++++ - include/uapi/drm/vc4_drm.h | 1 + - 5 files changed, 79 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 8302bd788be470fd61a7382b8c3ef16e26f6861d..3abaa0f85da194016c65f46509d4c64f8e2c8de2 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -82,6 +82,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, - break; - case DRM_VC4_PARAM_SUPPORTS_BRANCHES: - case DRM_VC4_PARAM_SUPPORTS_ETC1: -+ case DRM_VC4_PARAM_SUPPORTS_THREADED_FS: - args->value = true; - break; - default: -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index e1f6ab747f36dd412e00a1e7ea772f13c2fc32d5..e15eb37ca6191e0eae3d4947751437d2646c996d 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -384,6 +384,8 @@ struct vc4_validated_shader_info { - - uint32_t num_uniform_addr_offsets; - uint32_t *uniform_addr_offsets; -+ -+ bool is_threaded; - }; - - /** -diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c -index e18f88203d32f828b7256a05c653586c14095ef3..9fd171c361c23b52a4d507919ec7e26fd1e87aac 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate.c -+++ b/drivers/gpu/drm/vc4/vc4_validate.c -@@ -789,11 +789,6 @@ validate_gl_shader_rec(struct drm_device *dev, - exec->shader_rec_v += roundup(packet_size, 16); - exec->shader_rec_size -= packet_size; - -- if (!(*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD)) { -- DRM_ERROR("Multi-threaded fragment shaders not supported.\n"); -- return -EINVAL; +- if (val & BCM2835_I2C_S_RXD) { +- bcm2835_drain_rxfifo(i2c_dev); +- if (!(val & BCM2835_I2C_S_DONE)) +- return IRQ_HANDLED; - } - - for (i = 0; i < shader_reloc_count; i++) { - if (src_handles[i] > exec->bo_count) { - DRM_ERROR("Shader handle %d too big\n", src_handles[i]); -@@ -810,6 +805,18 @@ validate_gl_shader_rec(struct drm_device *dev, - return -EINVAL; - } - -+ if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) != -+ to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) { -+ DRM_ERROR("Thread mode of CL and FS do not match\n"); -+ return -EINVAL; -+ } -+ -+ if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded || -+ to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) { -+ DRM_ERROR("cs and vs cannot be threaded\n"); -+ return -EINVAL; -+ } -+ - for (i = 0; i < shader_reloc_count; i++) { - struct vc4_validated_shader_info *validated_shader; - uint32_t o = shader_reloc_offsets[i]; -diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -index 917321ce832ffda9d3e8ca20d987437eea9a1765..5dba13dd1e9b600b43a769d086d6eb428547ab66 100644 ---- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c -+++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -@@ -83,6 +83,13 @@ struct vc4_shader_validation_state { - * basic blocks. - */ - bool needs_uniform_address_for_loop; -+ -+ /* Set when we find an instruction writing the top half of the -+ * register files. If we allowed writing the unusable regs in -+ * a threaded shader, then the other shader running on our -+ * QPU's clamp validation would be invalid. -+ */ -+ bool all_registers_used; - }; - - static uint32_t -@@ -119,6 +126,13 @@ raddr_add_a_to_live_reg_index(uint64_t inst) - } - - static bool -+live_reg_is_upper_half(uint32_t lri) -+{ -+ return (lri >= 16 && lri < 32) || -+ (lri >= 32 + 16 && lri < 32 + 32); -+} -+ -+static bool - is_tmu_submit(uint32_t waddr) - { - return (waddr == QPU_W_TMU0_S || -@@ -390,6 +404,9 @@ check_reg_write(struct vc4_validated_shader_info *validated_shader, - } else { - validation_state->live_immediates[lri] = ~0; - } -+ -+ if (live_reg_is_upper_half(lri)) -+ validation_state->all_registers_used = true; - } - - switch (waddr) { -@@ -598,6 +615,11 @@ check_instruction_reads(struct vc4_validated_shader_info *validated_shader, - } - } - -+ if ((raddr_a >= 16 && raddr_a < 32) || -+ (raddr_b >= 16 && raddr_b < 32 && sig != QPU_SIG_SMALL_IMM)) { -+ validation_state->all_registers_used = true; -+ } -+ - return true; - } - -@@ -753,6 +775,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - { - bool found_shader_end = false; - int shader_end_ip = 0; -+ uint32_t last_thread_switch_ip = -3; - uint32_t ip; - struct vc4_validated_shader_info *validated_shader = NULL; - struct vc4_shader_validation_state validation_state; -@@ -785,6 +808,17 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - if (!vc4_handle_branch_target(&validation_state)) - goto fail; - -+ if (ip == last_thread_switch_ip + 3) { -+ /* Reset r0-r3 live clamp data */ -+ int i; -+ -+ for (i = 64; i < LIVE_REG_COUNT; i++) { -+ validation_state.live_min_clamp_offsets[i] = ~0; -+ validation_state.live_max_clamp_regs[i] = false; -+ validation_state.live_immediates[i] = ~0; -+ } + if (val & BCM2835_I2C_S_DONE) { +- if (i2c_dev->msg_buf_remaining) ++ if (i2c_dev->curr_msg->flags & I2C_M_RD) { ++ bcm2835_drain_rxfifo(i2c_dev); ++ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); + } + - switch (sig) { - case QPU_SIG_NONE: - case QPU_SIG_WAIT_FOR_SCOREBOARD: -@@ -794,6 +828,8 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - case QPU_SIG_LOAD_TMU1: - case QPU_SIG_PROG_END: - case QPU_SIG_SMALL_IMM: -+ case QPU_SIG_THREAD_SWITCH: -+ case QPU_SIG_LAST_THREAD_SWITCH: - if (!check_instruction_writes(validated_shader, - &validation_state)) { - DRM_ERROR("Bad write at ip %d\n", ip); -@@ -809,6 +845,18 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - shader_end_ip = ip; - } - -+ if (sig == QPU_SIG_THREAD_SWITCH || -+ sig == QPU_SIG_LAST_THREAD_SWITCH) { -+ validated_shader->is_threaded = true; -+ -+ if (ip < last_thread_switch_ip + 3) { -+ DRM_ERROR("Thread switch too soon after " -+ "last switch at ip %d\n", ip); -+ goto fail; -+ } -+ last_thread_switch_ip = ip; -+ } -+ - break; - - case QPU_SIG_LOAD_IMM: -@@ -823,6 +871,13 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - if (!check_branch(inst, validated_shader, - &validation_state, ip)) - goto fail; -+ -+ if (ip < last_thread_switch_ip + 3) { -+ DRM_ERROR("Branch in thread switch at ip %d", -+ ip); -+ goto fail; -+ } -+ - break; - default: - DRM_ERROR("Unsupported QPU signal %d at " -@@ -844,6 +899,14 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj) - goto fail; ++ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) + i2c_dev->msg_err = BCM2835_I2C_S_LEN; + else + i2c_dev->msg_err = 0; +@@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + return IRQ_HANDLED; } -+ /* Might corrupt other thread */ -+ if (validated_shader->is_threaded && -+ validation_state.all_registers_used) { -+ DRM_ERROR("Shader uses threading, but uses the upper " -+ "half of the registers, too\n"); -+ goto fail; +- if (val & BCM2835_I2C_S_TXD) { ++ if (val & BCM2835_I2C_S_TXW) { + bcm2835_fill_txfifo(i2c_dev); + return IRQ_HANDLED; + } + ++ if (val & BCM2835_I2C_S_RXR) { ++ bcm2835_drain_rxfifo(i2c_dev); ++ return IRQ_HANDLED; + } + - /* If we did a backwards branch and we haven't emitted a uniforms - * reset since then, we still need the uniforms stream to have the - * uniforms address available so that the backwards branch can do its -diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h -index 69caa21f0cb23c9439238f6239c0041b178d5669..f07a090167261131076438960c1dec175d7d376e 100644 ---- a/include/uapi/drm/vc4_drm.h -+++ b/include/uapi/drm/vc4_drm.h -@@ -287,6 +287,7 @@ struct drm_vc4_get_hang_state { - #define DRM_VC4_PARAM_V3D_IDENT2 2 - #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 - #define DRM_VC4_PARAM_SUPPORTS_ETC1 4 -+#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 + return IRQ_NONE; + } - struct drm_vc4_get_param { - __u32 param; +@@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + u32 c; + unsigned long time_left; + ++ i2c_dev->curr_msg = msg; + i2c_dev->msg_buf = msg->buf; + i2c_dev->msg_buf_remaining = msg->len; + reinit_completion(&i2c_dev->completion); -From 963f20f2caa0018ef7fbb756852fcd6226cde43a Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 6 Dec 2016 18:54:24 +0000 -Subject: [PATCH 204/208] config: fixup +From ee341c5b195116a5edb761bfeba927f926b888cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 18:24:38 +0200 +Subject: [PATCH 105/111] i2c: bcm2835: Protect against unexpected TXW/RXR + interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), +the driver has no way to fill/drain the FIFO to stop the interrupts. +In this case the controller has to be disabled and the transfer +completed to avoid hang. + +(CLKT | ERR) and DONE interrupts are completed in their own paths, and +the controller is disabled in the transfer function after completion. +Unite the code paths and do disabling inside the interrupt routine. + +Clear interrupt status bits in the united completion path instead of +trying to do it on every interrupt which isn't necessary. +Only CLKT, ERR and DONE can be cleared that way. + +Add the status value to the error value in case of TXW/RXR errors to +distinguish them from the other S_LEN error. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt --- - arch/arm/configs/bcm2709_defconfig | 3 ++- - arch/arm/configs/bcmrpi_defconfig | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) + drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 9 deletions(-) -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 48ed6bfe263a6a3fab942d0b52b2f409055f23ad..6757f597213cb029ef5a7ded516848685b89fe4c 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -44,7 +44,6 @@ CONFIG_SMP=y - CONFIG_VMSPLIT_2G=y - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y --CONFIG_OABI_COMPAT=y - # CONFIG_CPU_SW_DOMAIN_PAN is not set - CONFIG_CLEANCACHE=y - CONFIG_FRONTSWAP=y -@@ -58,6 +57,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=y - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y -@@ -1271,6 +1271,7 @@ CONFIG_BOOT_PRINTK_DELAY=y - CONFIG_DEBUG_MEMORY_INIT=y - CONFIG_DETECT_HUNG_TASK=y - CONFIG_TIMER_STATS=y -+CONFIG_LATENCYTOP=y - CONFIG_IRQSOFF_TRACER=y - CONFIG_SCHED_TRACER=y - CONFIG_STACK_TRACER=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index ff69cafd7fb706fc0069d59c37974c4ce5d50043..e683fe6eb803fefaee137f7e6da6cf346ddd5a14 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -43,7 +43,6 @@ CONFIG_ARCH_BCM2835=y - # CONFIG_CACHE_L2X0 is not set - CONFIG_PREEMPT_VOLUNTARY=y - CONFIG_AEABI=y --CONFIG_OABI_COMPAT=y - # CONFIG_CPU_SW_DOMAIN_PAN is not set - CONFIG_CLEANCACHE=y - CONFIG_FRONTSWAP=y -@@ -57,11 +56,13 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=y - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y - CONFIG_VFP=y - CONFIG_BINFMT_MISC=m - # CONFIG_SUSPEND is not set +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index f283b714aa79e2e4685ed95b04b6b289f7e9eee7..d2ba1a4de36af512e8e3c97251bd3537ae61591a 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -50,8 +50,6 @@ + #define BCM2835_I2C_S_CLKT BIT(9) + #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ + +-#define BCM2835_I2C_BITMSK_S 0x03FF +- + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + +@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) + } + } + ++/* ++ * Note about I2C_C_CLEAR on error: ++ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in ++ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through ++ * the state machine to send a NACK and a STOP. Since we're setting CLEAR ++ * without I2CEN, that NACK will be hanging around queued up for next time ++ * we start the engine. ++ */ ++ + static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + { + struct bcm2835_i2c_dev *i2c_dev = data; + u32 val, err; + + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); +- val &= BCM2835_I2C_BITMSK_S; +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); + + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); + if (err) { + i2c_dev->msg_err = err; +- complete(&i2c_dev->completion); +- return IRQ_HANDLED; ++ goto complete; + } + + if (val & BCM2835_I2C_S_DONE) { +@@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + i2c_dev->msg_err = BCM2835_I2C_S_LEN; + else + i2c_dev->msg_err = 0; +- complete(&i2c_dev->completion); +- return IRQ_HANDLED; ++ goto complete; + } + + if (val & BCM2835_I2C_S_TXW) { ++ if (!i2c_dev->msg_buf_remaining) { ++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; ++ goto complete; ++ } ++ + bcm2835_fill_txfifo(i2c_dev); + return IRQ_HANDLED; + } + + if (val & BCM2835_I2C_S_RXR) { ++ if (!i2c_dev->msg_buf_remaining) { ++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; ++ goto complete; ++ } ++ + bcm2835_drain_rxfifo(i2c_dev); + return IRQ_HANDLED; + } + + return IRQ_NONE; ++ ++complete: ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT | ++ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE); ++ complete(&i2c_dev->completion); ++ ++ return IRQ_HANDLED; + } + + static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, +@@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + BCM2835_I2C_TIMEOUT); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); + if (!time_left) { ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, ++ BCM2835_I2C_C_CLEAR); + dev_err(i2c_dev->dev, "i2c transfer timed out\n"); + return -ETIMEDOUT; + } -From d6a316e01480a79073f6baf8b89b5cfcb4900f25 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 5 Dec 2016 17:10:44 +0000 -Subject: [PATCH 205/208] BCM270X_DT: Add i2c-sensor overlay +From 8cf47e3091e11ac5db049059d99c6358365eeafb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Mon, 19 Sep 2016 17:19:41 +0200 +Subject: [PATCH 106/111] i2c: bcm2835: Use dev_dbg logging on transfer errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit -The i2c-sensor overlay is a container for various pressure and -temperature sensors, currently bmp085 and bmp280. The standalone -bmp085_i2c-sensor overlay is now deprecated. +Writing to an AT24C32 generates on average 2x i2c transfer errors per +32-byte page write. Which amounts to a lot for a 4k write. This is due +to the fact that the chip doesn't respond during it's internal write +cycle when the at24 driver tries and retries the next write. +Only a handful drivers use dev_err() on transfer error, so switch to +dev_dbg() instead. -Signed-off-by: Phil Elwell +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt --- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 12 ++++++-- - arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 34 +++++++++++++++++++++++ - 3 files changed, 45 insertions(+), 2 deletions(-) - create mode 100644 arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 7624812d0cdc74728f3556159871c7a299f9f6b7..11dba31712840a9e4b91acd4565c2d6266315273 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -32,6 +32,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - i2c-mux.dtbo \ - i2c-pwm-pca9685a.dtbo \ - i2c-rtc.dtbo \ -+ i2c-sensor.dtbo \ - i2c0-bcm2708.dtbo \ - i2c1-bcm2708.dtbo \ - i2s-gpio28-31.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index c0290531a61fedfe23e820ca4d9693a0acd3e876..4ef35f4ac1622be08066dc74a80d907ae6c164b7 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -283,8 +283,7 @@ Params: swap_lr Reverse the channel allocation, which will also - - - Name: bmp085_i2c-sensor --Info: Configures the BMP085/BMP180 digital barometric pressure and temperature -- sensors from Bosch Sensortec -+Info: This overlay is now deprecated - see i2c-sensor - Load: dtoverlay=bmp085_i2c-sensor - Params: - -@@ -542,6 +541,15 @@ Params: abx80x Select one of the ABx80x family: - source - - -+Name: i2c-sensor -+Info: Adds support for a number of I2C barometric pressure and temperature -+ sensors on i2c_arm -+Load: dtoverlay=i2c-sensor,= -+Params: bmp085 Select the Bosch sensortronic BMP085 -+ -+ bmp280 Select the Bosch sensortronic BMP280 -+ -+ - Name: i2c0-bcm2708 - Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations - are usable on all platforms. -diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..f6d134c095af2398fc55ae7d2b0e86456c30627c ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for a few digital barometric pressure and temperature sensors -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ bmp085: bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "disable"; -+ }; -+ -+ bmp280: bmp280@76 { -+ compatible = "bosch,bmp280"; -+ reg = <0x76>; -+ status = "disable"; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ bmp085 = <&bmp085>,"status"; -+ bmp280 = <&bmp280>,"status"; -+ }; -+}; - -From 9265a25166962ef139810f8c1ca51366da98e6d1 Mon Sep 17 00:00:00 2001 -From: Georgii Staroselskii -Date: Wed, 7 Dec 2016 15:10:27 +0300 -Subject: [PATCH 206/208] BCM270X_DT: overlays/*-overlay.dtb -> overlays/*.dtbo - (#1752) - -We now create overlays as .dtbo files. ---- - arch/arm/boot/dts/overlays/README | 2 +- + drivers/i2c/busses/i2c-bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 4ef35f4ac1622be08066dc74a80d907ae6c164b7..81d991803be335e5a1bc3bb0a8c7a2c9f5c392bd 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -61,7 +61,7 @@ this becomes a line in config.txt: +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index d2ba1a4de36af512e8e3c97251bd3537ae61591a..54d510abd46a117c9238fc6d7edec84019d1f60d 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + (msg->flags & I2C_M_IGNORE_NAK)) + return 0; - dtoverlay=lirc-rpi - --This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By -+This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By - default it will use GPIOs 17 (out) and 18 (in), but this can be modified using - DT parameters: +- dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); ++ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; -From 366621f36df68f06589b2813a8fd715cf8f898a7 Mon Sep 17 00:00:00 2001 -From: Ioan-Adrian Ratiu -Date: Tue, 27 Sep 2016 21:41:37 +0300 -Subject: [PATCH 207/208] Revert "HID: dragonrise: fix HID Descriptor for - 0x0006 PID" +From ddda57262c214495254890c94e598b8fca25dfc9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Thu, 22 Sep 2016 22:05:50 +0200 +Subject: [PATCH 107/111] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit -[ Upstream commit 1bcaa05ebee115213e34f1806cc6a4f7a6175a88 ] +The controller can't support this flag, so remove it. -This reverts commit 18339f59c3a6 ("HID: dragonrise: fix HID...") because it -breaks certain dragonrise 0079:0006 gamepads. While it may fix a breakage -caused by commit 79346d620e9d ("HID: input: force generic axis to be mapped -to their user space axis"), it is probable that the manufacturer released -different hardware with the same PID so this fix works for only a subset -and breaks the other gamepads sharing the PID. +Documentation/i2c/i2c-protocol states that all of the message is sent: -What is needed is another more generic solution which fixes 79346d620e9d -("HID: input: force generic axis ...") breakage for this controller: we -need to add an exception for this driver to make it keep the old behaviour -previous to the initial breakage (this is done in patch 2 of this series). +I2C_M_IGNORE_NAK: + Normally message is interrupted immediately if there is [NA] from the + client. Setting this flag treats any [NA] as [A], and all of + message is sent. -Signed-off-by: Ioan-Adrian Ratiu -Reviewed-by: Benjamin Tissoires -Signed-off-by: Jiri Kosina +From the BCM2835 ARM Peripherals datasheet: + + The ERR field is set when the slave fails to acknowledge either + its address or a data byte written to it. + +So when the controller doesn't receive an ack, it sets ERR and raises +an interrupt. In other words, the whole message is not sent. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt --- - drivers/hid/hid-dr.c | 58 ---------------------------------------------------- - 1 file changed, 58 deletions(-) + drivers/i2c/busses/i2c-bcm2835.c | 4 ---- + 1 file changed, 4 deletions(-) -diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c -index 8fd4bf77f264940ec04631252062e06aafe148c8..2523f8a4b7de9fb3152d1268ba7f79c24208c4c9 100644 ---- a/drivers/hid/hid-dr.c -+++ b/drivers/hid/hid-dr.c -@@ -234,58 +234,6 @@ static __u8 pid0011_rdesc_fixed[] = { - 0xC0 /* End Collection */ +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index 54d510abd46a117c9238fc6d7edec84019d1f60d..565ef69ce61423544dc0558c85ef318b0ae9c324 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + if (likely(!i2c_dev->msg_err)) + return 0; + +- if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && +- (msg->flags & I2C_M_IGNORE_NAK)) +- return 0; +- + dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + +From eaf51d9298d9dde20bded52c63eda7f4e536b992 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 04:54:27 +0200 +Subject: [PATCH 108/111] i2c: bcm2835: Add support for Repeated Start + Condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Documentation/i2c/i2c-protocol states that Combined transactions should +separate messages with a Start bit and end the whole transaction with a +Stop bit. This patch adds support for issuing only a Start between +messages instead of a Stop followed by a Start. + +This implementation differs from downstream i2c-bcm2708 in 2 respects: +- it uses an interrupt to detect that the transfer is active instead + of using polling. There is no interrupt for Transfer Active, but by + not prefilling the FIFO it's possible to use the TXW interrupt. +- when resetting/disabling the controller between transfers it writes + CLEAR to the control register instead of just zero. + Using just zero gave many errors. This might be the reason why + downstream had to disable this feature and make it available with a + module parameter. + +I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) +and AT24C32 (eeprom) in parallel without problems. + +Signed-off-by: Noralf Trønnes +Acked-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++--------------- + 1 file changed, 63 insertions(+), 38 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index 565ef69ce61423544dc0558c85ef318b0ae9c324..241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev { + struct i2c_adapter adapter; + struct completion completion; + struct i2c_msg *curr_msg; ++ int num_msgs; + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; +@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) + } + + /* ++ * Repeated Start Condition (Sr) ++ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it ++ * talks about reading from a slave with 10 bit address. This is achieved by ++ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then ++ * issue a read. ++ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the ++ * firmware actually does it using polling and says that it's a workaround for ++ * a problem in the state machine. ++ * It turns out that it is possible to use the TXW interrupt to know when the ++ * transfer is active, provided the FIFO has not been prefilled. ++ */ ++ ++static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN; ++ struct i2c_msg *msg = i2c_dev->curr_msg; ++ bool last_msg = (i2c_dev->num_msgs == 1); ++ ++ if (!i2c_dev->num_msgs) ++ return; ++ ++ i2c_dev->num_msgs--; ++ i2c_dev->msg_buf = msg->buf; ++ i2c_dev->msg_buf_remaining = msg->len; ++ ++ if (msg->flags & I2C_M_RD) ++ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; ++ else ++ c |= BCM2835_I2C_C_INTT; ++ ++ if (last_msg) ++ c |= BCM2835_I2C_C_INTD; ++ ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++} ++ ++/* + * Note about I2C_C_CLEAR on error: + * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in + * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through +@@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + } + + bcm2835_fill_txfifo(i2c_dev); ++ ++ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { ++ i2c_dev->curr_msg++; ++ bcm2835_i2c_start_transfer(i2c_dev); ++ } ++ + return IRQ_HANDLED; + } + +@@ -175,30 +221,25 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + return IRQ_HANDLED; + } + +-static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, +- struct i2c_msg *msg) ++static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ++ int num) + { +- u32 c; ++ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + unsigned long time_left; ++ int i; + +- i2c_dev->curr_msg = msg; +- i2c_dev->msg_buf = msg->buf; +- i2c_dev->msg_buf_remaining = msg->len; +- reinit_completion(&i2c_dev->completion); +- +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); ++ for (i = 0; i < (num - 1); i++) ++ if (msgs[i].flags & I2C_M_RD) { ++ dev_warn_once(i2c_dev->dev, ++ "only one read message supported, has to be last\n"); ++ return -EOPNOTSUPP; ++ } + +- if (msg->flags & I2C_M_RD) { +- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; +- } else { +- c = BCM2835_I2C_C_INTT; +- bcm2835_fill_txfifo(i2c_dev); +- } +- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; ++ i2c_dev->curr_msg = msgs; ++ i2c_dev->num_msgs = num; ++ reinit_completion(&i2c_dev->completion); + +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++ bcm2835_i2c_start_transfer(i2c_dev); + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + BCM2835_I2C_TIMEOUT); +@@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, + return -ETIMEDOUT; + } + +- if (likely(!i2c_dev->msg_err)) +- return 0; ++ if (!i2c_dev->msg_err) ++ return num; + + dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; +- else +- return -EIO; +-} +- +-static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], +- int num) +-{ +- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); +- int i; +- int ret = 0; +- +- for (i = 0; i < num; i++) { +- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); +- if (ret) +- break; +- } + +- return ret ?: i; ++ return -EIO; + } + + static u32 bcm2835_i2c_func(struct i2c_adapter *adap) + +From f7b9050bbbf5e15b9f4c5af03d9a9bd9edc39049 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 04:57:17 +0200 +Subject: [PATCH 109/111] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use i2c_adapter->timeout for the completion timeout value. The core +default is 1 second. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index 241e08ae7c27cec23fad3c1bf3ebad3a4d2a8e6f..d2085dd3742eabebc537621968088261f8dc7ea8 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -53,8 +53,6 @@ + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + +-#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) +- + struct bcm2835_i2c_dev { + struct device *dev; + void __iomem *regs; +@@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + bcm2835_i2c_start_transfer(i2c_dev); + + time_left = wait_for_completion_timeout(&i2c_dev->completion, +- BCM2835_I2C_TIMEOUT); ++ adap->timeout); + if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); + +From 8b97b2301e5e691828b2ea1210cabd55fa930b5e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Tue, 27 Sep 2016 01:00:08 +0200 +Subject: [PATCH 110/111] i2c: bcm2835: Add support for dynamic clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Support a dynamic clock by reading the frequency and setting the +divisor in the transfer function instead of during probe. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Martin Sperl +--- + drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 19 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index d2085dd3742eabebc537621968088261f8dc7ea8..c3436f627028477f7e21b47e079fd5ab06ec188a 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev { + void __iomem *regs; + struct clk *clk; + int irq; ++ u32 bus_clk_rate; + struct i2c_adapter adapter; + struct completion completion; + struct i2c_msg *curr_msg; +@@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) + return readl(i2c_dev->regs + reg); + } + ++static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ u32 divider; ++ ++ divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), ++ i2c_dev->bus_clk_rate); ++ /* ++ * Per the datasheet, the register is always interpreted as an even ++ * number, by rounding down. In other words, the LSB is ignored. So, ++ * if the LSB is set, increment the divider to avoid any issue. ++ */ ++ if (divider & 1) ++ divider++; ++ if ((divider < BCM2835_I2C_CDIV_MIN) || ++ (divider > BCM2835_I2C_CDIV_MAX)) { ++ dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); ++ return -EINVAL; ++ } ++ ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); ++ ++ return 0; ++} ++ + static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) + { + u32 val; +@@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + { + struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + unsigned long time_left; +- int i; ++ int i, ret; + + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { +@@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + return -EOPNOTSUPP; + } + ++ ret = bcm2835_i2c_set_divider(i2c_dev); ++ if (ret) ++ return ret; ++ + i2c_dev->curr_msg = msgs; + i2c_dev->num_msgs = num; + reinit_completion(&i2c_dev->completion); +@@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) + { + struct bcm2835_i2c_dev *i2c_dev; + struct resource *mem, *irq; +- u32 bus_clk_rate, divider; + int ret; + struct i2c_adapter *adap; + +@@ -306,27 +334,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) + } + + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", +- &bus_clk_rate); ++ &i2c_dev->bus_clk_rate); + if (ret < 0) { + dev_warn(&pdev->dev, + "Could not read clock-frequency property\n"); +- bus_clk_rate = 100000; +- } +- +- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); +- /* +- * Per the datasheet, the register is always interpreted as an even +- * number, by rounding down. In other words, the LSB is ignored. So, +- * if the LSB is set, increment the divider to avoid any issue. +- */ +- if (divider & 1) +- divider++; +- if ((divider < BCM2835_I2C_CDIV_MIN) || +- (divider > BCM2835_I2C_CDIV_MAX)) { +- dev_err(&pdev->dev, "Invalid clock-frequency\n"); +- return -ENODEV; ++ i2c_dev->bus_clk_rate = 100000; + } +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) { + +From 5c14442e251ac2c6f434c914beb3f09ed6573821 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Tue, 1 Nov 2016 15:15:41 +0100 +Subject: [PATCH 111/111] i2c: bcm2835: Add debug support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds a debug module parameter to aid in debugging transfer issues +by printing info to the kernel log. When enabled, status values are +collected in the interrupt routine and msg info in +bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid +affecting timing. Having printk in the isr can mask issues. + +debug values (additive): +1: Print info on error +2: Print info on all transfers +3: Print messages before transfer is started + +The value can be changed at runtime: +/sys/module/i2c_bcm2835/parameters/debug + +Example output, debug=3: +[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] +[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] + +Signed-off-by: Noralf Trønnes +--- + drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 98 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index c3436f627028477f7e21b47e079fd5ab06ec188a..8642f580ce41803bd22c76a0fa80d083d0747be1 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -53,6 +53,18 @@ + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + ++static unsigned int debug; ++module_param(debug, uint, 0644); ++MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); ++ ++#define BCM2835_DEBUG_MAX 512 ++struct bcm2835_debug { ++ struct i2c_msg *msg; ++ int msg_idx; ++ size_t remain; ++ u32 status; ++}; ++ + struct bcm2835_i2c_dev { + struct device *dev; + void __iomem *regs; +@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; ++ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; ++ unsigned int debug_num; ++ unsigned int debug_num_msgs; }; --static __u8 pid0006_rdesc_fixed[] = { -- 0x05, 0x01, /* Usage Page (Generic Desktop) */ -- 0x09, 0x04, /* Usage (Joystick) */ -- 0xA1, 0x01, /* Collection (Application) */ -- 0xA1, 0x02, /* Collection (Logical) */ -- 0x75, 0x08, /* Report Size (8) */ -- 0x95, 0x05, /* Report Count (5) */ -- 0x15, 0x00, /* Logical Minimum (0) */ -- 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ -- 0x35, 0x00, /* Physical Minimum (0) */ -- 0x46, 0xFF, 0x00, /* Physical Maximum (255) */ -- 0x09, 0x30, /* Usage (X) */ -- 0x09, 0x33, /* Usage (Ry) */ -- 0x09, 0x32, /* Usage (Z) */ -- 0x09, 0x31, /* Usage (Y) */ -- 0x09, 0x34, /* Usage (Ry) */ -- 0x81, 0x02, /* Input (Variable) */ -- 0x75, 0x04, /* Report Size (4) */ -- 0x95, 0x01, /* Report Count (1) */ -- 0x25, 0x07, /* Logical Maximum (7) */ -- 0x46, 0x3B, 0x01, /* Physical Maximum (315) */ -- 0x65, 0x14, /* Unit (Centimeter) */ -- 0x09, 0x39, /* Usage (Hat switch) */ -- 0x81, 0x42, /* Input (Variable) */ -- 0x65, 0x00, /* Unit (None) */ -- 0x75, 0x01, /* Report Size (1) */ -- 0x95, 0x0C, /* Report Count (12) */ -- 0x25, 0x01, /* Logical Maximum (1) */ -- 0x45, 0x01, /* Physical Maximum (1) */ -- 0x05, 0x09, /* Usage Page (Button) */ -- 0x19, 0x01, /* Usage Minimum (0x01) */ -- 0x29, 0x0C, /* Usage Maximum (0x0C) */ -- 0x81, 0x02, /* Input (Variable) */ -- 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ -- 0x75, 0x01, /* Report Size (1) */ -- 0x95, 0x08, /* Report Count (8) */ -- 0x25, 0x01, /* Logical Maximum (1) */ -- 0x45, 0x01, /* Physical Maximum (1) */ -- 0x09, 0x01, /* Usage (0x01) */ -- 0x81, 0x02, /* Input (Variable) */ -- 0xC0, /* End Collection */ -- 0xA1, 0x02, /* Collection (Logical) */ -- 0x75, 0x08, /* Report Size (8) */ -- 0x95, 0x07, /* Report Count (7) */ -- 0x46, 0xFF, 0x00, /* Physical Maximum (255) */ -- 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ -- 0x09, 0x02, /* Usage (0x02) */ -- 0x91, 0x02, /* Output (Variable) */ -- 0xC0, /* End Collection */ -- 0xC0 /* End Collection */ --}; -- - static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) - { -@@ -296,12 +244,6 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - *rsize = sizeof(pid0011_rdesc_fixed); - } - break; -- case 0x0006: -- if (*rsize == sizeof(pid0006_rdesc_fixed)) { -- rdesc = pid0006_rdesc_fixed; -- *rsize = sizeof(pid0006_rdesc_fixed); -- } -- break; - } - return rdesc; - } - -From 822b0eb3dac2230ec04d71eeccea28b2528eb4a2 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 6 Dec 2016 17:05:39 +0000 -Subject: [PATCH 208/208] bcm2835-rng: Avoid initialising if already enabled - -Avoids the 0x40000 cycles of warmup again if firmware has already used it ---- - drivers/char/hw_random/bcm2835-rng.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c -index af2149273fe049b075d0953034cda0aab1525f23..e5b5222314b1677d989f7e7ea7085cacde8ff1b6 100644 ---- a/drivers/char/hw_random/bcm2835-rng.c -+++ b/drivers/char/hw_random/bcm2835-rng.c -@@ -101,9 +101,10 @@ static int bcm2835_rng_probe(struct platform_device *pdev) - rng_setup(rng_base); - - /* set warm-up count & enable */ -- __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); -- __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); -- -+ if (!(__raw_readl(rng_base + RNG_CTRL) & RNG_RBGEN)) { -+ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); -+ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); ++static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) ++{ ++ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ return; ++ ++ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; ++ i2c_dev->debug[i2c_dev->debug_num].msg_idx = ++ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; ++ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; ++ i2c_dev->debug[i2c_dev->debug_num].status = s; ++ i2c_dev->debug_num++; ++} ++ ++static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, ++ struct bcm2835_debug *d) ++{ ++ u32 s = d->status; ++ ++ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", ++ d->remain, s, ++ s & BCM2835_I2C_S_TA ? "TA " : "", ++ s & BCM2835_I2C_S_DONE ? "DONE " : "", ++ s & BCM2835_I2C_S_TXW ? "TXW " : "", ++ s & BCM2835_I2C_S_RXR ? "RXR " : "", ++ s & BCM2835_I2C_S_TXD ? "TXD " : "", ++ s & BCM2835_I2C_S_RXD ? "RXD " : "", ++ s & BCM2835_I2C_S_TXE ? "TXE " : "", ++ s & BCM2835_I2C_S_RXF ? "RXF " : "", ++ s & BCM2835_I2C_S_ERR ? "ERR " : "", ++ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, ++ struct i2c_msg *msg, int i, int total, ++ const char *fname) ++{ ++ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", ++ fname, i, total, ++ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, ++ msg->flags & I2C_M_TEN ? "TEN" : "", ++ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", ++ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", ++ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", ++ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", ++ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", ++ msg->flags & I2C_M_STOP ? "STOP" : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ struct bcm2835_debug *d; ++ unsigned int i; ++ ++ for (i = 0; i < i2c_dev->debug_num; i++) { ++ d = &i2c_dev->debug[i]; ++ if (d->status == ~0) ++ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, ++ i2c_dev->debug_num_msgs, "start_transfer"); ++ else ++ bcm2835_debug_print_status(i2c_dev, d); + } - /* register driver */ - err = hwrng_register(&bcm2835_rng_ops); ++ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ pr_info("BCM2835_DEBUG_MAX reached\n"); ++} ++ + static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, + u32 reg, u32 val) + { +@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++ bcm2835_debug_add(i2c_dev, ~0); + } + + /* +@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + u32 val, err; + + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); ++ bcm2835_debug_add(i2c_dev, val); + + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); if (err) { +@@ -251,6 +335,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + unsigned long time_left; + int i, ret; + ++ if (debug) ++ i2c_dev->debug_num_msgs = num; ++ ++ if (debug > 2) ++ for (i = 0; i < num; i++) ++ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); ++ + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { + dev_warn_once(i2c_dev->dev, +@@ -270,6 +361,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + adap->timeout); ++ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) ++ bcm2835_debug_print(i2c_dev); ++ i2c_dev->debug_num_msgs = 0; ++ i2c_dev->debug_num = 0; + if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); +@@ -280,7 +375,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + if (!i2c_dev->msg_err) + return num; + +- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); ++ if (debug) ++ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", ++ i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; diff --git a/projects/Virtual/linux/linux.x86_64.conf b/projects/Virtual/linux/linux.x86_64.conf index 61ed4144b8..7aa7025bf9 100644 --- a/projects/Virtual/linux/linux.x86_64.conf +++ b/projects/Virtual/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.8.11 Kernel Configuration +# Linux/x86_64 4.9.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -45,6 +45,7 @@ CONFIG_PGTABLE_LEVELS=4 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y # # General setup @@ -303,6 +304,8 @@ CONFIG_HAVE_STACK_VALIDATION=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_COMPAT_OLD_SIGACTION=y # CONFIG_CPU_NO_EFFICIENT_FFS is not set +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y # # GCOV-based kernel profiling @@ -355,6 +358,7 @@ CONFIG_EFI_PARTITION=y # CONFIG_SYSV68_PARTITION is not set # CONFIG_CMDLINE_PARTITION is not set CONFIG_BLOCK_COMPAT=y +CONFIG_BLK_MQ_PCI=y # # IO Schedulers @@ -636,7 +640,8 @@ CONFIG_HAVE_ACPI_APEI_NMI=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_ATTR_SET=y CONFIG_CPU_FREQ_GOV_COMMON=y -# CONFIG_CPU_FREQ_STAT is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set @@ -700,6 +705,7 @@ CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_PERFORMANCE is not set CONFIG_PCIE_PME=y # CONFIG_PCIE_DPC is not set +# CONFIG_PCIE_PTM is not set CONFIG_PCI_BUS_ADDR_T_64BIT=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_IRQ_DOMAIN=y @@ -717,6 +723,7 @@ CONFIG_PCI_LABEL=y # PCI host controller drivers # # CONFIG_PCIE_DW_PLAT is not set +# CONFIG_VMD is not set # CONFIG_ISA_BUS is not set CONFIG_ISA_DMA_API=y CONFIG_AMD_NB=y @@ -744,7 +751,6 @@ CONFIG_SYSVIPC_COMPAT=y CONFIG_KEYS_COMPAT=y CONFIG_X86_DEV_DMA_OPS=y CONFIG_PMC_ATOM=y -# CONFIG_VMD is not set CONFIG_NET=y CONFIG_COMPAT_NETLINK_MESSAGES=y @@ -1087,6 +1093,7 @@ CONFIG_BT_HCIBTUSB_RTL=y CONFIG_BT_ATH3K=m # CONFIG_AF_RXRPC is not set # CONFIG_AF_KCM is not set +# CONFIG_STREAM_PARSER is not set CONFIG_WIRELESS=y CONFIG_WIRELESS_EXT=y CONFIG_WEXT_CORE=y @@ -1154,6 +1161,7 @@ CONFIG_WANT_DEV_COREDUMP=y # CONFIG_ALLOW_DEV_COREDUMP is not set # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set CONFIG_GENERIC_CPU_AUTOPROBE=y @@ -1227,7 +1235,6 @@ CONFIG_BLK_DEV_NVME=y # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_BMP085_I2C is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_SRAM is not set # CONFIG_C2PORT is not set @@ -1362,6 +1369,7 @@ CONFIG_SCSI_MVSAS=y CONFIG_MEGARAID_SAS=y # CONFIG_SCSI_MPT3SAS is not set # CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_SMARTPQI is not set # CONFIG_SCSI_UFSHCD is not set # CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_BUSLOGIC is not set @@ -1505,7 +1513,6 @@ CONFIG_NET_CORE=y # CONFIG_NET_TEAM is not set CONFIG_MACVLAN=m # CONFIG_MACVTAP is not set -# CONFIG_IPVLAN is not set # CONFIG_VXLAN is not set # CONFIG_MACSEC is not set CONFIG_NETCONSOLE=y @@ -1534,6 +1541,7 @@ CONFIG_VORTEX=y # CONFIG_NET_VENDOR_AGERE is not set # CONFIG_NET_VENDOR_ALTEON is not set # CONFIG_ALTERA_TSE is not set +# CONFIG_NET_VENDOR_AMAZON is not set CONFIG_NET_VENDOR_AMD=y # CONFIG_AMD8111_ETH is not set CONFIG_PCNET32=y @@ -1562,6 +1570,7 @@ CONFIG_NET_VENDOR_CAVIUM=y # CONFIG_THUNDER_NIC_PF is not set # CONFIG_THUNDER_NIC_VF is not set # CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_RGX is not set # CONFIG_LIQUIDIO is not set # CONFIG_NET_VENDOR_CHELSIO is not set # CONFIG_NET_VENDOR_CISCO is not set @@ -1659,38 +1668,44 @@ CONFIG_VIA_VELOCITY=y CONFIG_PHYLIB=y # -# MII PHY device drivers +# MDIO bus device drivers # -# CONFIG_AQUANTIA_PHY is not set -CONFIG_AT803X_PHY=y -CONFIG_AMD_PHY=y -CONFIG_MARVELL_PHY=y -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_TERANETICS_PHY is not set -# CONFIG_SMSC_PHY is not set -CONFIG_BCM_NET_PHYLIB=y -CONFIG_BROADCOM_PHY=y -# CONFIG_BCM7XXX_PHY is not set -# CONFIG_BCM87XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -CONFIG_REALTEK_PHY=y -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_DP83848_PHY is not set -# CONFIG_DP83867_PHY is not set -# CONFIG_MICROCHIP_PHY is not set -# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BCM_UNIMAC is not set # CONFIG_MDIO_BITBANG is not set # CONFIG_MDIO_OCTEON is not set # CONFIG_MDIO_THUNDER is not set -# CONFIG_MDIO_BCM_UNIMAC is not set + +# +# MII PHY device drivers +# +CONFIG_AMD_PHY=y +# CONFIG_AQUANTIA_PHY is not set +CONFIG_AT803X_PHY=y +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BROADCOM_PHY=y +# CONFIG_CICADA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_ICPLUS_PHY is not set # CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +CONFIG_MARVELL_PHY=y +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +CONFIG_REALTEK_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set CONFIG_PPP=m CONFIG_PPP_BSDCOMP=m CONFIG_PPP_DEFLATE=m @@ -2034,11 +2049,11 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set # CONFIG_TOUCHSCREEN_EETI is not set # CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set -# CONFIG_TOUCHSCREEN_FT6236 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GOODIX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set CONFIG_TOUCHSCREEN_ELAN=y # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set @@ -2099,6 +2114,7 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_BEEPER is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_GPIO_DECODER is not set # CONFIG_INPUT_ATLAS_BTNS is not set CONFIG_INPUT_ATI_REMOTE2=m # CONFIG_INPUT_KEYSPAN_REMOTE is not set @@ -2169,6 +2185,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # CONFIG_SERIAL_8250_DW is not set # CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_LPSS is not set # CONFIG_SERIAL_8250_MID is not set # CONFIG_SERIAL_8250_MOXA is not set @@ -2335,7 +2352,6 @@ CONFIG_PINCTRL_CHERRYVIEW=y # CONFIG_PINCTRL_BROXTON is not set # CONFIG_PINCTRL_SUNRISEPOINT is not set CONFIG_GPIOLIB=y -CONFIG_GPIO_DEVRES=y CONFIG_GPIO_ACPI=y CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_DEBUG_GPIO is not set @@ -2349,6 +2365,7 @@ CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_ICH is not set # CONFIG_GPIO_LYNXPOINT is not set +# CONFIG_GPIO_MOCKUP is not set # CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_ZX is not set @@ -2370,6 +2387,7 @@ CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set # CONFIG_GPIO_TPIC2810 is not set +# CONFIG_GPIO_TS4900 is not set # # MFD GPIO expanders @@ -2391,6 +2409,8 @@ CONFIG_GPIOLIB_IRQCHIP=y # USB GPIO expanders # # CONFIG_W1 is not set +# CONFIG_POWER_AVS is not set +# CONFIG_POWER_RESET is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set @@ -2413,8 +2433,6 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set # CONFIG_CHARGER_RT9455 is not set -# CONFIG_POWER_RESET is not set -# CONFIG_POWER_AVS is not set CONFIG_HWMON=y CONFIG_HWMON_VID=y # CONFIG_HWMON_DEBUG_CHIP is not set @@ -2623,6 +2641,7 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_DA9063 is not set # CONFIG_MFD_DA9150 is not set # CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_EXYNOS_LPASS is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set @@ -2672,6 +2691,7 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_MFD_TPS65086 is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set # CONFIG_MFD_TPS65218 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set @@ -2802,6 +2822,7 @@ CONFIG_VIDEO_TM6000_DVB=m # CONFIG_DVB_USB=m # CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB3000MC=m # CONFIG_DVB_USB_A800 is not set CONFIG_DVB_USB_DIBUSB_MB=m CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y @@ -2827,6 +2848,18 @@ CONFIG_DVB_USB_DTV5100=m # CONFIG_DVB_USB_FRIIO is not set CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_TBSQBOX=m +CONFIG_DVB_USB_TBSQBOX2=m +CONFIG_DVB_USB_TBSQBOX22=m +CONFIG_DVB_USB_TBS5922SE=m +CONFIG_DVB_USB_TBSQBOXS2=m +CONFIG_DVB_USB_TBSQBOX2CI=m +CONFIG_DVB_USB_TBS5925=m +CONFIG_DVB_USB_TBS5880=m +CONFIG_DVB_USB_TBS5220=m +CONFIG_DVB_USB_TBS5881=m +CONFIG_DVB_USB_TBS5520=m +CONFIG_DVB_USB_TBS5927=m CONFIG_DVB_USB_V2=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m @@ -2861,6 +2894,7 @@ CONFIG_MEDIA_PCI_SUPPORT=y # Media capture support # # CONFIG_VIDEO_SOLO6X10 is not set +# CONFIG_VIDEO_TW5864 is not set # CONFIG_VIDEO_TW68 is not set # CONFIG_VIDEO_TW686X is not set # CONFIG_VIDEO_ZORAN is not set @@ -2894,6 +2928,7 @@ CONFIG_VIDEO_SAA7134=m CONFIG_VIDEO_SAA7134_RC=y CONFIG_VIDEO_SAA7134_DVB=m CONFIG_VIDEO_SAA7164=m +# CONFIG_SAA716X_SUPPORT is not set # # Media digital TV PCI Adapters @@ -2917,8 +2952,8 @@ CONFIG_DVB_MANTIS=m # CONFIG_DVB_HOPPER is not set CONFIG_DVB_NGENE=m CONFIG_DVB_DDBRIDGE=m -# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set CONFIG_DVB_SMIPCIE=m +CONFIG_DVB_TBSECP3=m # CONFIG_V4L_PLATFORM_DRIVERS is not set # CONFIG_V4L_MEM2MEM_DRIVERS is not set # CONFIG_V4L_TEST_DRIVERS is not set @@ -2950,7 +2985,7 @@ CONFIG_SMS_SIANO_RC=y # CONFIG_SMS_SIANO_DEBUGFS is not set # -# Media ancillary drivers (tuners, sensors, i2c, frontends) +# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_MEDIA_ATTACH=y @@ -3040,6 +3075,9 @@ CONFIG_MEDIA_TUNER_SI2157=m CONFIG_MEDIA_TUNER_IT913X=m CONFIG_MEDIA_TUNER_R820T=m CONFIG_MEDIA_TUNER_QM1D1C0042=m +CONFIG_MEDIA_TUNER_AV201X=m +CONFIG_MEDIA_TUNER_STV6120=m +CONFIG_MEDIA_TUNER_R848=m # # Multistandard (satellite) frontends @@ -3047,10 +3085,7 @@ CONFIG_MEDIA_TUNER_QM1D1C0042=m CONFIG_DVB_STB0899=m CONFIG_DVB_STB6100=m CONFIG_DVB_STV090x=m -CONFIG_DVB_STV0910=m CONFIG_DVB_STV6110x=m -CONFIG_DVB_STV6111=m -CONFIG_DVB_MXL5XX=m CONFIG_DVB_M88DS3103=m # @@ -3061,8 +3096,6 @@ CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_SI2165=m CONFIG_DVB_MN88472=m CONFIG_DVB_MN88473=m -CONFIG_DVB_STV0367DD=m -CONFIG_DVB_CXD2843=m # # DVB-S (satellite) frontends @@ -3117,6 +3150,7 @@ CONFIG_DVB_RTL2830=m CONFIG_DVB_RTL2832=m CONFIG_DVB_SI2168=m CONFIG_DVB_AS102_FE=m +# CONFIG_DVB_GP8PSK_FE is not set # # DVB-C (cable) frontends @@ -3164,7 +3198,6 @@ CONFIG_DVB_TUNER_DIB0090=m # SEC control devices for DVB-S # CONFIG_DVB_DRX39XYJ=m -CONFIG_DVB_LNBH25=m CONFIG_DVB_LNBP21=m CONFIG_DVB_LNBP22=m CONFIG_DVB_ISL6405=m @@ -3178,10 +3211,13 @@ CONFIG_DVB_TDA665x=m CONFIG_DVB_IX2505V=m CONFIG_DVB_M88RS2000=m CONFIG_DVB_AF9033=m +CONFIG_DVB_TAS2101=m # # Tools to develop new frontends # +CONFIG_DVB_STV0910=m +CONFIG_DVB_AVL6882=m # CONFIG_DVB_DUMMY_FE is not set # @@ -3211,22 +3247,19 @@ CONFIG_DRM_TTM=y # CONFIG_DRM_I2C_CH7006 is not set # CONFIG_DRM_I2C_SIL164 is not set # CONFIG_DRM_I2C_NXP_TDA998X is not set -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=y # CONFIG_DRM_RADEON_USERPTR is not set CONFIG_DRM_AMDGPU=y +CONFIG_DRM_AMDGPU_SI=y CONFIG_DRM_AMDGPU_CIK=y # CONFIG_DRM_AMDGPU_USERPTR is not set # CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set -CONFIG_DRM_AMD_POWERPLAY=y # # ACP (Audio CoProcessor) Configuration # CONFIG_DRM_AMD_ACP=y # CONFIG_DRM_NOUVEAU is not set -# CONFIG_DRM_I810 is not set CONFIG_DRM_I915=y # CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set CONFIG_DRM_I915_USERPTR=y @@ -3237,10 +3270,6 @@ CONFIG_DRM_I915_USERPTR=y # # CONFIG_DRM_I915_WERROR is not set # CONFIG_DRM_I915_DEBUG is not set -# CONFIG_DRM_MGA is not set -# CONFIG_DRM_SIS is not set -# CONFIG_DRM_VIA is not set -# CONFIG_DRM_SAVAGE is not set # CONFIG_DRM_VGEM is not set CONFIG_DRM_VMWGFX=y CONFIG_DRM_VMWGFX_FBCON=y @@ -3263,6 +3292,7 @@ CONFIG_DRM_BRIDGE=y # Display Interface Bridges # # CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_LEGACY is not set # # Frame buffer Devices @@ -3555,12 +3585,6 @@ CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m # CONFIG_SND_SOC_INTEL_SKL_RT286_MACH is not set # CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH is not set # CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH is not set - -# -# Allwinner SoC Audio support -# -# CONFIG_SND_SUN4I_CODEC is not set -# CONFIG_SND_SUN4I_I2S is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=y @@ -3640,6 +3664,7 @@ CONFIG_SND_SOC_TS3A227E=m # CONFIG_SND_SOC_WM8974 is not set # CONFIG_SND_SOC_WM8978 is not set # CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_NAU8810 is not set # CONFIG_SND_SOC_TPA6130A2 is not set CONFIG_SND_SIMPLE_CARD_UTILS=m CONFIG_SND_SIMPLE_CARD=m @@ -3750,6 +3775,11 @@ CONFIG_USB_HIDDEV=y # I2C HID support # # CONFIG_I2C_HID is not set + +# +# Intel ISH HID support +# +# CONFIG_INTEL_ISH_HID is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y @@ -3765,8 +3795,8 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_ULPI_BUS is not set -# CONFIG_USB_MON is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +CONFIG_USB_MON=m # CONFIG_USB_WUSB_CBAF is not set # @@ -3920,6 +3950,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_UCSI is not set @@ -3933,6 +3964,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_ISP1301 is not set # CONFIG_USB_GADGET is not set # CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_ULPI_BUS is not set # CONFIG_UWB is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set @@ -4015,6 +4047,7 @@ CONFIG_LEDS_CLASS_FLASH=y # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_MLXCPLD is not set # # LED Triggers @@ -4070,7 +4103,6 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_ISL12057 is not set # CONFIG_RTC_DRV_X1205 is not set # CONFIG_RTC_DRV_PCF8523 is not set # CONFIG_RTC_DRV_PCF85063 is not set @@ -4203,7 +4235,6 @@ CONFIG_VT6656=m CONFIG_STAGING_MEDIA=y # CONFIG_MEDIA_CEC is not set CONFIG_DVB_CXD2099=m -# CONFIG_VIDEO_TW686X_KH is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set # CONFIG_LIRC_IMON is not set @@ -4227,6 +4258,7 @@ CONFIG_LIRC_XBOX=m # CONFIG_WILC1000_SDIO is not set # CONFIG_MOST is not set # CONFIG_KS7010 is not set +# CONFIG_GREYBUS is not set # CONFIG_X86_PLATFORM_DEVICES is not set # CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y @@ -4242,7 +4274,6 @@ CONFIG_COMMON_CLK=y # CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_PIC32 is not set -# CONFIG_SUNXI_CCU is not set # # Hardware Spinlock drivers @@ -4347,6 +4378,7 @@ CONFIG_EFI_ESRT=y CONFIG_EFI_RUNTIME_WRAPPERS=y # CONFIG_EFI_BOOTLOADER_CONTROL is not set # CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_TEST is not set # # File systems @@ -4450,6 +4482,7 @@ CONFIG_TMPFS_POSIX_ACL=y CONFIG_TMPFS_XATTR=y # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y # CONFIG_CONFIGFS_FS is not set CONFIG_EFIVAR_FS=y CONFIG_MISC_FILESYSTEMS=y @@ -4709,7 +4742,6 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y @@ -4750,6 +4782,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set # CONFIG_UBSAN is not set CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y CONFIG_STRICT_DEVMEM=y @@ -5025,7 +5058,6 @@ CONFIG_DQL=y CONFIG_GLOB=y # CONFIG_GLOB_SELFTEST is not set CONFIG_NLATTR=y -CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set # CONFIG_IRQ_POLL is not set @@ -5040,3 +5072,4 @@ CONFIG_SG_POOL=y CONFIG_ARCH_HAS_SG_CHAIN=y CONFIG_ARCH_HAS_PMEM_API=y CONFIG_ARCH_HAS_MMIO_FLUSH=y +CONFIG_SBITMAP=y