diff options
Diffstat (limited to 'drivers/media')
189 files changed, 16862 insertions, 3724 deletions
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 9f47e383c57a..9af2140b57a4 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c | |||
| @@ -378,12 +378,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent | |||
| 378 | dev->pci = pci; | 378 | dev->pci = pci; |
| 379 | 379 | ||
| 380 | /* get chip-revision; this is needed to enable bug-fixes */ | 380 | /* get chip-revision; this is needed to enable bug-fixes */ |
| 381 | err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision); | 381 | dev->revision = pci->revision; |
| 382 | if (err < 0) { | ||
| 383 | ERR(("pci_read_config_dword() failed.\n")); | ||
| 384 | goto err_disable; | ||
| 385 | } | ||
| 386 | dev->revision &= 0xf; | ||
| 387 | 382 | ||
| 388 | /* remap the memory from virtual to physical address */ | 383 | /* remap the memory from virtual to physical address */ |
| 389 | 384 | ||
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 6fc79f15dcbc..22d3ca36370e 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig | |||
| @@ -186,4 +186,12 @@ config MEDIA_TUNER_TDA18218 | |||
| 186 | default m if MEDIA_TUNER_CUSTOMISE | 186 | default m if MEDIA_TUNER_CUSTOMISE |
| 187 | help | 187 | help |
| 188 | NXP TDA18218 silicon tuner driver. | 188 | NXP TDA18218 silicon tuner driver. |
| 189 | |||
| 190 | config MEDIA_TUNER_TDA18212 | ||
| 191 | tristate "NXP TDA18212 silicon tuner" | ||
| 192 | depends on VIDEO_MEDIA && I2C | ||
| 193 | default m if MEDIA_TUNER_CUSTOMISE | ||
| 194 | help | ||
| 195 | NXP TDA18212 silicon tuner driver. | ||
| 196 | |||
| 189 | endmenu | 197 | endmenu |
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile index 96da03d349ca..2cb4f5327843 100644 --- a/drivers/media/common/tuners/Makefile +++ b/drivers/media/common/tuners/Makefile | |||
| @@ -25,6 +25,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o | |||
| 25 | obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o | 25 | obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o |
| 26 | obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o | 26 | obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o |
| 27 | obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o | 27 | obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o |
| 28 | obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o | ||
| 28 | 29 | ||
| 29 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 30 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
| 30 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 31 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 0d6e09419044..56fe75c94deb 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c | |||
| @@ -4024,6 +4024,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe, | |||
| 4024 | case BANDWIDTH_8_MHZ: | 4024 | case BANDWIDTH_8_MHZ: |
| 4025 | req_bw = MXL5005S_BANDWIDTH_8MHZ; | 4025 | req_bw = MXL5005S_BANDWIDTH_8MHZ; |
| 4026 | break; | 4026 | break; |
| 4027 | default: | ||
| 4028 | return -EINVAL; | ||
| 4027 | } | 4029 | } |
| 4028 | } | 4030 | } |
| 4029 | 4031 | ||
diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c new file mode 100644 index 000000000000..1f1db20d46b1 --- /dev/null +++ b/drivers/media/common/tuners/tda18212.c | |||
| @@ -0,0 +1,265 @@ | |||
| 1 | /* | ||
| 2 | * NXP TDA18212HN silicon tuner driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include "tda18212_priv.h" | ||
| 22 | |||
| 23 | static int debug; | ||
| 24 | module_param(debug, int, 0644); | ||
| 25 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
| 26 | |||
| 27 | /* write multiple registers */ | ||
| 28 | static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val, | ||
| 29 | int len) | ||
| 30 | { | ||
| 31 | int ret; | ||
| 32 | u8 buf[len+1]; | ||
| 33 | struct i2c_msg msg[1] = { | ||
| 34 | { | ||
| 35 | .addr = priv->cfg->i2c_address, | ||
| 36 | .flags = 0, | ||
| 37 | .len = sizeof(buf), | ||
| 38 | .buf = buf, | ||
| 39 | } | ||
| 40 | }; | ||
| 41 | |||
| 42 | buf[0] = reg; | ||
| 43 | memcpy(&buf[1], val, len); | ||
| 44 | |||
| 45 | ret = i2c_transfer(priv->i2c, msg, 1); | ||
| 46 | if (ret == 1) { | ||
| 47 | ret = 0; | ||
| 48 | } else { | ||
| 49 | warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
| 50 | ret = -EREMOTEIO; | ||
| 51 | } | ||
| 52 | return ret; | ||
| 53 | } | ||
| 54 | |||
| 55 | /* read multiple registers */ | ||
| 56 | static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val, | ||
| 57 | int len) | ||
| 58 | { | ||
| 59 | int ret; | ||
| 60 | u8 buf[len]; | ||
| 61 | struct i2c_msg msg[2] = { | ||
| 62 | { | ||
| 63 | .addr = priv->cfg->i2c_address, | ||
| 64 | .flags = 0, | ||
| 65 | .len = 1, | ||
| 66 | .buf = ®, | ||
| 67 | }, { | ||
| 68 | .addr = priv->cfg->i2c_address, | ||
| 69 | .flags = I2C_M_RD, | ||
| 70 | .len = sizeof(buf), | ||
| 71 | .buf = buf, | ||
| 72 | } | ||
| 73 | }; | ||
| 74 | |||
| 75 | ret = i2c_transfer(priv->i2c, msg, 2); | ||
| 76 | if (ret == 2) { | ||
| 77 | memcpy(val, buf, len); | ||
| 78 | ret = 0; | ||
| 79 | } else { | ||
| 80 | warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
| 81 | ret = -EREMOTEIO; | ||
| 82 | } | ||
| 83 | |||
| 84 | return ret; | ||
| 85 | } | ||
| 86 | |||
| 87 | /* write single register */ | ||
| 88 | static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val) | ||
| 89 | { | ||
| 90 | return tda18212_wr_regs(priv, reg, &val, 1); | ||
| 91 | } | ||
| 92 | |||
| 93 | /* read single register */ | ||
| 94 | static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val) | ||
| 95 | { | ||
| 96 | return tda18212_rd_regs(priv, reg, val, 1); | ||
| 97 | } | ||
| 98 | |||
| 99 | #if 0 /* keep, useful when developing driver */ | ||
| 100 | static void tda18212_dump_regs(struct tda18212_priv *priv) | ||
| 101 | { | ||
| 102 | int i; | ||
| 103 | u8 buf[256]; | ||
| 104 | |||
| 105 | #define TDA18212_RD_LEN 32 | ||
| 106 | for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN) | ||
| 107 | tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN); | ||
| 108 | |||
| 109 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf, | ||
| 110 | sizeof(buf), true); | ||
| 111 | |||
| 112 | return; | ||
| 113 | } | ||
| 114 | #endif | ||
| 115 | |||
| 116 | static int tda18212_set_params(struct dvb_frontend *fe, | ||
| 117 | struct dvb_frontend_parameters *p) | ||
| 118 | { | ||
| 119 | struct tda18212_priv *priv = fe->tuner_priv; | ||
| 120 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 121 | int ret, i; | ||
| 122 | u32 if_khz; | ||
| 123 | u8 buf[9]; | ||
| 124 | static const u8 bw_params[][3] = { | ||
| 125 | /* 0f 13 23 */ | ||
| 126 | { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */ | ||
| 127 | { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */ | ||
| 128 | { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */ | ||
| 129 | { 0x92, 0x53, 0x03 }, /* DVB-C */ | ||
| 130 | }; | ||
| 131 | |||
| 132 | dbg("%s: delsys=%d RF=%d BW=%d", __func__, | ||
| 133 | c->delivery_system, c->frequency, c->bandwidth_hz); | ||
| 134 | |||
| 135 | if (fe->ops.i2c_gate_ctrl) | ||
| 136 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
| 137 | |||
| 138 | switch (c->delivery_system) { | ||
| 139 | case SYS_DVBT: | ||
| 140 | switch (c->bandwidth_hz) { | ||
| 141 | case 6000000: | ||
| 142 | if_khz = priv->cfg->if_dvbt_6; | ||
| 143 | i = 0; | ||
| 144 | break; | ||
| 145 | case 7000000: | ||
| 146 | if_khz = priv->cfg->if_dvbt_7; | ||
| 147 | i = 1; | ||
| 148 | break; | ||
| 149 | case 8000000: | ||
| 150 | if_khz = priv->cfg->if_dvbt_8; | ||
| 151 | i = 2; | ||
| 152 | break; | ||
| 153 | default: | ||
| 154 | ret = -EINVAL; | ||
| 155 | goto error; | ||
| 156 | } | ||
| 157 | break; | ||
| 158 | case SYS_DVBC_ANNEX_AC: | ||
| 159 | if_khz = priv->cfg->if_dvbc; | ||
| 160 | i = 3; | ||
| 161 | break; | ||
| 162 | default: | ||
| 163 | ret = -EINVAL; | ||
| 164 | goto error; | ||
| 165 | } | ||
| 166 | |||
| 167 | ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]); | ||
| 168 | if (ret) | ||
| 169 | goto error; | ||
| 170 | |||
| 171 | ret = tda18212_wr_reg(priv, 0x06, 0x00); | ||
| 172 | if (ret) | ||
| 173 | goto error; | ||
| 174 | |||
| 175 | ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]); | ||
| 176 | if (ret) | ||
| 177 | goto error; | ||
| 178 | |||
| 179 | buf[0] = 0x02; | ||
| 180 | buf[1] = bw_params[i][1]; | ||
| 181 | buf[2] = 0x03; /* default value */ | ||
| 182 | buf[3] = if_khz / 50; | ||
| 183 | buf[4] = ((c->frequency / 1000) >> 16) & 0xff; | ||
| 184 | buf[5] = ((c->frequency / 1000) >> 8) & 0xff; | ||
| 185 | buf[6] = ((c->frequency / 1000) >> 0) & 0xff; | ||
| 186 | buf[7] = 0xc1; | ||
| 187 | buf[8] = 0x01; | ||
| 188 | ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf)); | ||
| 189 | if (ret) | ||
| 190 | goto error; | ||
| 191 | |||
| 192 | exit: | ||
| 193 | if (fe->ops.i2c_gate_ctrl) | ||
| 194 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
| 195 | |||
| 196 | return ret; | ||
| 197 | |||
| 198 | error: | ||
| 199 | dbg("%s: failed:%d", __func__, ret); | ||
| 200 | goto exit; | ||
| 201 | } | ||
| 202 | |||
| 203 | static int tda18212_release(struct dvb_frontend *fe) | ||
| 204 | { | ||
| 205 | kfree(fe->tuner_priv); | ||
| 206 | fe->tuner_priv = NULL; | ||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static const struct dvb_tuner_ops tda18212_tuner_ops = { | ||
| 211 | .info = { | ||
| 212 | .name = "NXP TDA18212", | ||
| 213 | |||
| 214 | .frequency_min = 48000000, | ||
| 215 | .frequency_max = 864000000, | ||
| 216 | .frequency_step = 1000, | ||
| 217 | }, | ||
| 218 | |||
| 219 | .release = tda18212_release, | ||
| 220 | |||
| 221 | .set_params = tda18212_set_params, | ||
| 222 | }; | ||
| 223 | |||
| 224 | struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | ||
| 225 | struct i2c_adapter *i2c, struct tda18212_config *cfg) | ||
| 226 | { | ||
| 227 | struct tda18212_priv *priv = NULL; | ||
| 228 | int ret; | ||
| 229 | u8 val; | ||
| 230 | |||
| 231 | priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL); | ||
| 232 | if (priv == NULL) | ||
| 233 | return NULL; | ||
| 234 | |||
| 235 | priv->cfg = cfg; | ||
| 236 | priv->i2c = i2c; | ||
| 237 | fe->tuner_priv = priv; | ||
| 238 | |||
| 239 | if (fe->ops.i2c_gate_ctrl) | ||
| 240 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
| 241 | |||
| 242 | /* check if the tuner is there */ | ||
| 243 | ret = tda18212_rd_reg(priv, 0x00, &val); | ||
| 244 | |||
| 245 | if (fe->ops.i2c_gate_ctrl) | ||
| 246 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
| 247 | |||
| 248 | dbg("%s: ret:%d chip ID:%02x", __func__, ret, val); | ||
| 249 | if (ret || val != 0xc7) { | ||
| 250 | kfree(priv); | ||
| 251 | return NULL; | ||
| 252 | } | ||
| 253 | |||
| 254 | info("NXP TDA18212HN successfully identified."); | ||
| 255 | |||
| 256 | memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops, | ||
| 257 | sizeof(struct dvb_tuner_ops)); | ||
| 258 | |||
| 259 | return fe; | ||
| 260 | } | ||
| 261 | EXPORT_SYMBOL(tda18212_attach); | ||
| 262 | |||
| 263 | MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver"); | ||
| 264 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 265 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/tda18212.h b/drivers/media/common/tuners/tda18212.h new file mode 100644 index 000000000000..83b497f59e1b --- /dev/null +++ b/drivers/media/common/tuners/tda18212.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * NXP TDA18212HN silicon tuner driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef TDA18212_H | ||
| 22 | #define TDA18212_H | ||
| 23 | |||
| 24 | #include "dvb_frontend.h" | ||
| 25 | |||
| 26 | struct tda18212_config { | ||
| 27 | u8 i2c_address; | ||
| 28 | |||
| 29 | u16 if_dvbt_6; | ||
| 30 | u16 if_dvbt_7; | ||
| 31 | u16 if_dvbt_8; | ||
| 32 | u16 if_dvbc; | ||
| 33 | }; | ||
| 34 | |||
| 35 | #if defined(CONFIG_MEDIA_TUNER_TDA18212) || \ | ||
| 36 | (defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE)) | ||
| 37 | extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | ||
| 38 | struct i2c_adapter *i2c, struct tda18212_config *cfg); | ||
| 39 | #else | ||
| 40 | static inline struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | ||
| 41 | struct i2c_adapter *i2c, struct tda18212_config *cfg) | ||
| 42 | { | ||
| 43 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 44 | return NULL; | ||
| 45 | } | ||
| 46 | #endif | ||
| 47 | |||
| 48 | #endif | ||
diff --git a/drivers/media/common/tuners/tda18212_priv.h b/drivers/media/common/tuners/tda18212_priv.h new file mode 100644 index 000000000000..9adff9356b73 --- /dev/null +++ b/drivers/media/common/tuners/tda18212_priv.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* | ||
| 2 | * NXP TDA18212HN silicon tuner driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef TDA18212_PRIV_H | ||
| 22 | #define TDA18212_PRIV_H | ||
| 23 | |||
| 24 | #include "tda18212.h" | ||
| 25 | |||
| 26 | #define LOG_PREFIX "tda18212" | ||
| 27 | |||
| 28 | #undef dbg | ||
| 29 | #define dbg(f, arg...) \ | ||
| 30 | if (debug) \ | ||
| 31 | printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
| 32 | #undef err | ||
| 33 | #define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) | ||
| 34 | #undef info | ||
| 35 | #define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
| 36 | #undef warn | ||
| 37 | #define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) | ||
| 38 | |||
| 39 | struct tda18212_priv { | ||
| 40 | struct tda18212_config *cfg; | ||
| 41 | struct i2c_adapter *i2c; | ||
| 42 | }; | ||
| 43 | |||
| 44 | #endif | ||
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index d884f5eee73c..57022e88e338 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c | |||
| @@ -976,6 +976,10 @@ static int tda18271_set_params(struct dvb_frontend *fe, | |||
| 976 | tda_warn("bandwidth not set!\n"); | 976 | tda_warn("bandwidth not set!\n"); |
| 977 | return -EINVAL; | 977 | return -EINVAL; |
| 978 | } | 978 | } |
| 979 | } else if (fe->ops.info.type == FE_QAM) { | ||
| 980 | /* DVB-C */ | ||
| 981 | map = &std_map->qam_8; | ||
| 982 | bw = 8000000; | ||
| 979 | } else { | 983 | } else { |
| 980 | tda_warn("modulation type not supported!\n"); | 984 | tda_warn("modulation type not supported!\n"); |
| 981 | return -EINVAL; | 985 | return -EINVAL; |
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 1e28f7dcb26b..aa1b2e844d32 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c | |||
| @@ -628,6 +628,15 @@ static void xc_debug_dump(struct xc5000_priv *priv) | |||
| 628 | dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); | 628 | dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | /* | ||
| 632 | * As defined on EN 300 429, the DVB-C roll-off factor is 0.15. | ||
| 633 | * So, the amount of the needed bandwith is given by: | ||
| 634 | * Bw = Symbol_rate * (1 + 0.15) | ||
| 635 | * As such, the maximum symbol rate supported by 6 MHz is given by: | ||
| 636 | * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds | ||
| 637 | */ | ||
| 638 | #define MAX_SYMBOL_RATE_6MHz 5217391 | ||
| 639 | |||
| 631 | static int xc5000_set_params(struct dvb_frontend *fe, | 640 | static int xc5000_set_params(struct dvb_frontend *fe, |
| 632 | struct dvb_frontend_parameters *params) | 641 | struct dvb_frontend_parameters *params) |
| 633 | { | 642 | { |
| @@ -688,21 +697,32 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
| 688 | } | 697 | } |
| 689 | priv->rf_mode = XC_RF_MODE_AIR; | 698 | priv->rf_mode = XC_RF_MODE_AIR; |
| 690 | } else if (fe->ops.info.type == FE_QAM) { | 699 | } else if (fe->ops.info.type == FE_QAM) { |
| 691 | dprintk(1, "%s() QAM\n", __func__); | ||
| 692 | switch (params->u.qam.modulation) { | 700 | switch (params->u.qam.modulation) { |
| 701 | case QAM_256: | ||
| 702 | case QAM_AUTO: | ||
| 693 | case QAM_16: | 703 | case QAM_16: |
| 694 | case QAM_32: | 704 | case QAM_32: |
| 695 | case QAM_64: | 705 | case QAM_64: |
| 696 | case QAM_128: | 706 | case QAM_128: |
| 697 | case QAM_256: | ||
| 698 | case QAM_AUTO: | ||
| 699 | dprintk(1, "%s() QAM modulation\n", __func__); | 707 | dprintk(1, "%s() QAM modulation\n", __func__); |
| 700 | priv->bandwidth = BANDWIDTH_8_MHZ; | ||
| 701 | priv->video_standard = DTV7_8; | ||
| 702 | priv->freq_hz = params->frequency - 2750000; | ||
| 703 | priv->rf_mode = XC_RF_MODE_CABLE; | 708 | priv->rf_mode = XC_RF_MODE_CABLE; |
| 709 | /* | ||
| 710 | * Using a 8MHz bandwidth sometimes fail | ||
| 711 | * with 6MHz-spaced channels, due to inter-carrier | ||
| 712 | * interference. So, use DTV6 firmware | ||
| 713 | */ | ||
| 714 | if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) { | ||
| 715 | priv->bandwidth = BANDWIDTH_6_MHZ; | ||
| 716 | priv->video_standard = DTV6; | ||
| 717 | priv->freq_hz = params->frequency - 1750000; | ||
| 718 | } else { | ||
| 719 | priv->bandwidth = BANDWIDTH_8_MHZ; | ||
| 720 | priv->video_standard = DTV7_8; | ||
| 721 | priv->freq_hz = params->frequency - 2750000; | ||
| 722 | } | ||
| 704 | break; | 723 | break; |
| 705 | default: | 724 | default: |
| 725 | dprintk(1, "%s() Unsupported QAM type\n", __func__); | ||
| 706 | return -EINVAL; | 726 | return -EINVAL; |
| 707 | } | 727 | } |
| 708 | } else { | 728 | } else { |
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 03f96d6ca894..44f8fb5f17ff 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c | |||
| @@ -290,10 +290,8 @@ static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci) | |||
| 290 | static int flexcop_pci_init(struct flexcop_pci *fc_pci) | 290 | static int flexcop_pci_init(struct flexcop_pci *fc_pci) |
| 291 | { | 291 | { |
| 292 | int ret; | 292 | int ret; |
| 293 | u8 card_rev; | ||
| 294 | 293 | ||
| 295 | pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev); | 294 | info("card revision %x", fc_pci->pdev->revision); |
| 296 | info("card revision %x", card_rev); | ||
| 297 | 295 | ||
| 298 | if ((ret = pci_enable_device(fc_pci->pdev)) != 0) | 296 | if ((ret = pci_enable_device(fc_pci->pdev)) != 0) |
| 299 | return ret; | 297 | return ret; |
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 99d62094f908..b34fa95185e4 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c | |||
| @@ -460,7 +460,7 @@ static int __devinit bt878_probe(struct pci_dev *dev, | |||
| 460 | goto fail0; | 460 | goto fail0; |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); | 463 | bt->revision = dev->revision; |
| 464 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); | 464 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
| 465 | 465 | ||
| 466 | 466 | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 4a88a3e4db2b..faa3671b649e 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c | |||
| @@ -478,97 +478,94 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, | |||
| 478 | 478 | ||
| 479 | EXPORT_SYMBOL(dvb_dmx_swfilter_packets); | 479 | EXPORT_SYMBOL(dvb_dmx_swfilter_packets); |
| 480 | 480 | ||
| 481 | void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | 481 | static inline int find_next_packet(const u8 *buf, int pos, size_t count, |
| 482 | const int pktsize) | ||
| 482 | { | 483 | { |
| 483 | int p = 0, i, j; | 484 | int start = pos, lost; |
| 484 | 485 | ||
| 485 | spin_lock(&demux->lock); | 486 | while (pos < count) { |
| 486 | 487 | if (buf[pos] == 0x47 || | |
| 487 | if (demux->tsbufp) { | 488 | (pktsize == 204 && buf[pos] == 0xB8)) |
| 488 | i = demux->tsbufp; | 489 | break; |
| 489 | j = 188 - i; | 490 | pos++; |
| 490 | if (count < j) { | ||
| 491 | memcpy(&demux->tsbuf[i], buf, count); | ||
| 492 | demux->tsbufp += count; | ||
| 493 | goto bailout; | ||
| 494 | } | ||
| 495 | memcpy(&demux->tsbuf[i], buf, j); | ||
| 496 | if (demux->tsbuf[0] == 0x47) | ||
| 497 | dvb_dmx_swfilter_packet(demux, demux->tsbuf); | ||
| 498 | demux->tsbufp = 0; | ||
| 499 | p += j; | ||
| 500 | } | 491 | } |
| 501 | 492 | ||
| 502 | while (p < count) { | 493 | lost = pos - start; |
| 503 | if (buf[p] == 0x47) { | 494 | if (lost) { |
| 504 | if (count - p >= 188) { | 495 | /* This garbage is part of a valid packet? */ |
| 505 | dvb_dmx_swfilter_packet(demux, &buf[p]); | 496 | int backtrack = pos - pktsize; |
| 506 | p += 188; | 497 | if (backtrack >= 0 && (buf[backtrack] == 0x47 || |
| 507 | } else { | 498 | (pktsize == 204 && buf[backtrack] == 0xB8))) |
| 508 | i = count - p; | 499 | return backtrack; |
| 509 | memcpy(demux->tsbuf, &buf[p], i); | ||
| 510 | demux->tsbufp = i; | ||
| 511 | goto bailout; | ||
| 512 | } | ||
| 513 | } else | ||
| 514 | p++; | ||
| 515 | } | 500 | } |
| 516 | 501 | ||
| 517 | bailout: | 502 | return pos; |
| 518 | spin_unlock(&demux->lock); | ||
| 519 | } | 503 | } |
| 520 | 504 | ||
| 521 | EXPORT_SYMBOL(dvb_dmx_swfilter); | 505 | /* Filter all pktsize= 188 or 204 sized packets and skip garbage. */ |
| 522 | 506 | static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, | |
| 523 | void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | 507 | size_t count, const int pktsize) |
| 524 | { | 508 | { |
| 525 | int p = 0, i, j; | 509 | int p = 0, i, j; |
| 526 | u8 tmppack[188]; | 510 | const u8 *q; |
| 527 | 511 | ||
| 528 | spin_lock(&demux->lock); | 512 | spin_lock(&demux->lock); |
| 529 | 513 | ||
| 530 | if (demux->tsbufp) { | 514 | if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */ |
| 531 | i = demux->tsbufp; | 515 | i = demux->tsbufp; |
| 532 | j = 204 - i; | 516 | j = pktsize - i; |
| 533 | if (count < j) { | 517 | if (count < j) { |
| 534 | memcpy(&demux->tsbuf[i], buf, count); | 518 | memcpy(&demux->tsbuf[i], buf, count); |
| 535 | demux->tsbufp += count; | 519 | demux->tsbufp += count; |
| 536 | goto bailout; | 520 | goto bailout; |
| 537 | } | 521 | } |
| 538 | memcpy(&demux->tsbuf[i], buf, j); | 522 | memcpy(&demux->tsbuf[i], buf, j); |
| 539 | if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) { | 523 | if (demux->tsbuf[0] == 0x47) /* double check */ |
| 540 | memcpy(tmppack, demux->tsbuf, 188); | 524 | dvb_dmx_swfilter_packet(demux, demux->tsbuf); |
| 541 | if (tmppack[0] == 0xB8) | ||
| 542 | tmppack[0] = 0x47; | ||
| 543 | dvb_dmx_swfilter_packet(demux, tmppack); | ||
| 544 | } | ||
| 545 | demux->tsbufp = 0; | 525 | demux->tsbufp = 0; |
| 546 | p += j; | 526 | p += j; |
| 547 | } | 527 | } |
| 548 | 528 | ||
| 549 | while (p < count) { | 529 | while (1) { |
| 550 | if ((buf[p] == 0x47) || (buf[p] == 0xB8)) { | 530 | p = find_next_packet(buf, p, count, pktsize); |
| 551 | if (count - p >= 204) { | 531 | if (p >= count) |
| 552 | memcpy(tmppack, &buf[p], 188); | 532 | break; |
| 553 | if (tmppack[0] == 0xB8) | 533 | if (count - p < pktsize) |
| 554 | tmppack[0] = 0x47; | 534 | break; |
| 555 | dvb_dmx_swfilter_packet(demux, tmppack); | 535 | |
| 556 | p += 204; | 536 | q = &buf[p]; |
| 557 | } else { | 537 | |
| 558 | i = count - p; | 538 | if (pktsize == 204 && (*q == 0xB8)) { |
| 559 | memcpy(demux->tsbuf, &buf[p], i); | 539 | memcpy(demux->tsbuf, q, 188); |
| 560 | demux->tsbufp = i; | 540 | demux->tsbuf[0] = 0x47; |
| 561 | goto bailout; | 541 | q = demux->tsbuf; |
| 562 | } | ||
| 563 | } else { | ||
| 564 | p++; | ||
| 565 | } | 542 | } |
| 543 | dvb_dmx_swfilter_packet(demux, q); | ||
| 544 | p += pktsize; | ||
| 545 | } | ||
| 546 | |||
| 547 | i = count - p; | ||
| 548 | if (i) { | ||
| 549 | memcpy(demux->tsbuf, &buf[p], i); | ||
| 550 | demux->tsbufp = i; | ||
| 551 | if (pktsize == 204 && demux->tsbuf[0] == 0xB8) | ||
| 552 | demux->tsbuf[0] = 0x47; | ||
| 566 | } | 553 | } |
| 567 | 554 | ||
| 568 | bailout: | 555 | bailout: |
| 569 | spin_unlock(&demux->lock); | 556 | spin_unlock(&demux->lock); |
| 570 | } | 557 | } |
| 571 | 558 | ||
| 559 | void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | ||
| 560 | { | ||
| 561 | _dvb_dmx_swfilter(demux, buf, count, 188); | ||
| 562 | } | ||
| 563 | EXPORT_SYMBOL(dvb_dmx_swfilter); | ||
| 564 | |||
| 565 | void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | ||
| 566 | { | ||
| 567 | _dvb_dmx_swfilter(demux, buf, count, 204); | ||
| 568 | } | ||
| 572 | EXPORT_SYMBOL(dvb_dmx_swfilter_204); | 569 | EXPORT_SYMBOL(dvb_dmx_swfilter_204); |
| 573 | 570 | ||
| 574 | static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) | 571 | static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 31e2c0d45db3..98278041d75f 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
| @@ -105,7 +105,8 @@ struct dvb_frontend_private { | |||
| 105 | 105 | ||
| 106 | /* thread/frontend values */ | 106 | /* thread/frontend values */ |
| 107 | struct dvb_device *dvbdev; | 107 | struct dvb_device *dvbdev; |
| 108 | struct dvb_frontend_parameters parameters; | 108 | struct dvb_frontend_parameters parameters_in; |
| 109 | struct dvb_frontend_parameters parameters_out; | ||
| 109 | struct dvb_fe_events events; | 110 | struct dvb_fe_events events; |
| 110 | struct semaphore sem; | 111 | struct semaphore sem; |
| 111 | struct list_head list_head; | 112 | struct list_head list_head; |
| @@ -160,12 +161,11 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | |||
| 160 | 161 | ||
| 161 | e = &events->events[events->eventw]; | 162 | e = &events->events[events->eventw]; |
| 162 | 163 | ||
| 163 | memcpy (&e->parameters, &fepriv->parameters, | ||
| 164 | sizeof (struct dvb_frontend_parameters)); | ||
| 165 | |||
| 166 | if (status & FE_HAS_LOCK) | 164 | if (status & FE_HAS_LOCK) |
| 167 | if (fe->ops.get_frontend) | 165 | if (fe->ops.get_frontend) |
| 168 | fe->ops.get_frontend(fe, &e->parameters); | 166 | fe->ops.get_frontend(fe, &fepriv->parameters_out); |
| 167 | |||
| 168 | e->parameters = fepriv->parameters_out; | ||
| 169 | 169 | ||
| 170 | events->eventw = wp; | 170 | events->eventw = wp; |
| 171 | 171 | ||
| @@ -277,12 +277,12 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra | |||
| 277 | int ready = 0; | 277 | int ready = 0; |
| 278 | int fe_set_err = 0; | 278 | int fe_set_err = 0; |
| 279 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 279 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 280 | int original_inversion = fepriv->parameters.inversion; | 280 | int original_inversion = fepriv->parameters_in.inversion; |
| 281 | u32 original_frequency = fepriv->parameters.frequency; | 281 | u32 original_frequency = fepriv->parameters_in.frequency; |
| 282 | 282 | ||
| 283 | /* are we using autoinversion? */ | 283 | /* are we using autoinversion? */ |
| 284 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | 284 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && |
| 285 | (fepriv->parameters.inversion == INVERSION_AUTO)); | 285 | (fepriv->parameters_in.inversion == INVERSION_AUTO)); |
| 286 | 286 | ||
| 287 | /* setup parameters correctly */ | 287 | /* setup parameters correctly */ |
| 288 | while(!ready) { | 288 | while(!ready) { |
| @@ -348,18 +348,19 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra | |||
| 348 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); | 348 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); |
| 349 | 349 | ||
| 350 | /* set the frontend itself */ | 350 | /* set the frontend itself */ |
| 351 | fepriv->parameters.frequency += fepriv->lnb_drift; | 351 | fepriv->parameters_in.frequency += fepriv->lnb_drift; |
| 352 | if (autoinversion) | 352 | if (autoinversion) |
| 353 | fepriv->parameters.inversion = fepriv->inversion; | 353 | fepriv->parameters_in.inversion = fepriv->inversion; |
| 354 | if (fe->ops.set_frontend) | 354 | if (fe->ops.set_frontend) |
| 355 | fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters); | 355 | fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in); |
| 356 | fepriv->parameters_out = fepriv->parameters_in; | ||
| 356 | if (fe_set_err < 0) { | 357 | if (fe_set_err < 0) { |
| 357 | fepriv->state = FESTATE_ERROR; | 358 | fepriv->state = FESTATE_ERROR; |
| 358 | return fe_set_err; | 359 | return fe_set_err; |
| 359 | } | 360 | } |
| 360 | 361 | ||
| 361 | fepriv->parameters.frequency = original_frequency; | 362 | fepriv->parameters_in.frequency = original_frequency; |
| 362 | fepriv->parameters.inversion = original_inversion; | 363 | fepriv->parameters_in.inversion = original_inversion; |
| 363 | 364 | ||
| 364 | fepriv->auto_sub_step++; | 365 | fepriv->auto_sub_step++; |
| 365 | return 0; | 366 | return 0; |
| @@ -383,7 +384,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | |||
| 383 | if (fepriv->state & FESTATE_RETUNE) { | 384 | if (fepriv->state & FESTATE_RETUNE) { |
| 384 | if (fe->ops.set_frontend) | 385 | if (fe->ops.set_frontend) |
| 385 | retval = fe->ops.set_frontend(fe, | 386 | retval = fe->ops.set_frontend(fe, |
| 386 | &fepriv->parameters); | 387 | &fepriv->parameters_in); |
| 388 | fepriv->parameters_out = fepriv->parameters_in; | ||
| 387 | if (retval < 0) | 389 | if (retval < 0) |
| 388 | fepriv->state = FESTATE_ERROR; | 390 | fepriv->state = FESTATE_ERROR; |
| 389 | else | 391 | else |
| @@ -413,8 +415,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | |||
| 413 | 415 | ||
| 414 | /* if we're tuned, then we have determined the correct inversion */ | 416 | /* if we're tuned, then we have determined the correct inversion */ |
| 415 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | 417 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && |
| 416 | (fepriv->parameters.inversion == INVERSION_AUTO)) { | 418 | (fepriv->parameters_in.inversion == INVERSION_AUTO)) { |
| 417 | fepriv->parameters.inversion = fepriv->inversion; | 419 | fepriv->parameters_in.inversion = fepriv->inversion; |
| 418 | } | 420 | } |
| 419 | return; | 421 | return; |
| 420 | } | 422 | } |
| @@ -594,12 +596,14 @@ restart: | |||
| 594 | 596 | ||
| 595 | if (fepriv->state & FESTATE_RETUNE) { | 597 | if (fepriv->state & FESTATE_RETUNE) { |
| 596 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); | 598 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); |
| 597 | params = &fepriv->parameters; | 599 | params = &fepriv->parameters_in; |
| 598 | fepriv->state = FESTATE_TUNED; | 600 | fepriv->state = FESTATE_TUNED; |
| 599 | } | 601 | } |
| 600 | 602 | ||
| 601 | if (fe->ops.tune) | 603 | if (fe->ops.tune) |
| 602 | fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); | 604 | fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); |
| 605 | if (params) | ||
| 606 | fepriv->parameters_out = *params; | ||
| 603 | 607 | ||
| 604 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { | 608 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { |
| 605 | dprintk("%s: state changed, adding current state\n", __func__); | 609 | dprintk("%s: state changed, adding current state\n", __func__); |
| @@ -612,11 +616,9 @@ restart: | |||
| 612 | dvb_frontend_swzigzag(fe); | 616 | dvb_frontend_swzigzag(fe); |
| 613 | break; | 617 | break; |
| 614 | case DVBFE_ALGO_CUSTOM: | 618 | case DVBFE_ALGO_CUSTOM: |
| 615 | params = NULL; /* have we been asked to RETUNE ? */ | ||
| 616 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); | 619 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); |
| 617 | if (fepriv->state & FESTATE_RETUNE) { | 620 | if (fepriv->state & FESTATE_RETUNE) { |
| 618 | dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); | 621 | dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); |
| 619 | params = &fepriv->parameters; | ||
| 620 | fepriv->state = FESTATE_TUNED; | 622 | fepriv->state = FESTATE_TUNED; |
| 621 | } | 623 | } |
| 622 | /* Case where we are going to search for a carrier | 624 | /* Case where we are going to search for a carrier |
| @@ -625,7 +627,7 @@ restart: | |||
| 625 | */ | 627 | */ |
| 626 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { | 628 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { |
| 627 | if (fe->ops.search) { | 629 | if (fe->ops.search) { |
| 628 | fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters); | 630 | fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in); |
| 629 | /* We did do a search as was requested, the flags are | 631 | /* We did do a search as was requested, the flags are |
| 630 | * now unset as well and has the flags wrt to search. | 632 | * now unset as well and has the flags wrt to search. |
| 631 | */ | 633 | */ |
| @@ -636,11 +638,12 @@ restart: | |||
| 636 | /* Track the carrier if the search was successful */ | 638 | /* Track the carrier if the search was successful */ |
| 637 | if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) { | 639 | if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) { |
| 638 | if (fe->ops.track) | 640 | if (fe->ops.track) |
| 639 | fe->ops.track(fe, &fepriv->parameters); | 641 | fe->ops.track(fe, &fepriv->parameters_in); |
| 640 | } else { | 642 | } else { |
| 641 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | 643 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; |
| 642 | fepriv->delay = HZ / 2; | 644 | fepriv->delay = HZ / 2; |
| 643 | } | 645 | } |
| 646 | fepriv->parameters_out = fepriv->parameters_in; | ||
| 644 | fe->ops.read_status(fe, &s); | 647 | fe->ops.read_status(fe, &s); |
| 645 | if (s != fepriv->status) { | 648 | if (s != fepriv->status) { |
| 646 | dvb_frontend_add_event(fe, s); /* update event list */ | 649 | dvb_frontend_add_event(fe, s); /* update event list */ |
| @@ -860,34 +863,34 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, | |||
| 860 | 863 | ||
| 861 | static int dvb_frontend_clear_cache(struct dvb_frontend *fe) | 864 | static int dvb_frontend_clear_cache(struct dvb_frontend *fe) |
| 862 | { | 865 | { |
| 866 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 863 | int i; | 867 | int i; |
| 864 | 868 | ||
| 865 | memset(&(fe->dtv_property_cache), 0, | 869 | memset(c, 0, sizeof(struct dtv_frontend_properties)); |
| 866 | sizeof(struct dtv_frontend_properties)); | 870 | |
| 867 | 871 | c->state = DTV_CLEAR; | |
| 868 | fe->dtv_property_cache.state = DTV_CLEAR; | 872 | c->delivery_system = SYS_UNDEFINED; |
| 869 | fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; | 873 | c->inversion = INVERSION_AUTO; |
| 870 | fe->dtv_property_cache.inversion = INVERSION_AUTO; | 874 | c->fec_inner = FEC_AUTO; |
| 871 | fe->dtv_property_cache.fec_inner = FEC_AUTO; | 875 | c->transmission_mode = TRANSMISSION_MODE_AUTO; |
| 872 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; | 876 | c->bandwidth_hz = BANDWIDTH_AUTO; |
| 873 | fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO; | 877 | c->guard_interval = GUARD_INTERVAL_AUTO; |
| 874 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; | 878 | c->hierarchy = HIERARCHY_AUTO; |
| 875 | fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO; | 879 | c->symbol_rate = QAM_AUTO; |
| 876 | fe->dtv_property_cache.symbol_rate = QAM_AUTO; | 880 | c->code_rate_HP = FEC_AUTO; |
| 877 | fe->dtv_property_cache.code_rate_HP = FEC_AUTO; | 881 | c->code_rate_LP = FEC_AUTO; |
| 878 | fe->dtv_property_cache.code_rate_LP = FEC_AUTO; | 882 | |
| 879 | 883 | c->isdbt_partial_reception = -1; | |
| 880 | fe->dtv_property_cache.isdbt_partial_reception = -1; | 884 | c->isdbt_sb_mode = -1; |
| 881 | fe->dtv_property_cache.isdbt_sb_mode = -1; | 885 | c->isdbt_sb_subchannel = -1; |
| 882 | fe->dtv_property_cache.isdbt_sb_subchannel = -1; | 886 | c->isdbt_sb_segment_idx = -1; |
| 883 | fe->dtv_property_cache.isdbt_sb_segment_idx = -1; | 887 | c->isdbt_sb_segment_count = -1; |
| 884 | fe->dtv_property_cache.isdbt_sb_segment_count = -1; | 888 | c->isdbt_layer_enabled = 0x7; |
| 885 | fe->dtv_property_cache.isdbt_layer_enabled = 0x7; | ||
| 886 | for (i = 0; i < 3; i++) { | 889 | for (i = 0; i < 3; i++) { |
| 887 | fe->dtv_property_cache.layer[i].fec = FEC_AUTO; | 890 | c->layer[i].fec = FEC_AUTO; |
| 888 | fe->dtv_property_cache.layer[i].modulation = QAM_AUTO; | 891 | c->layer[i].modulation = QAM_AUTO; |
| 889 | fe->dtv_property_cache.layer[i].interleaving = -1; | 892 | c->layer[i].interleaving = -1; |
| 890 | fe->dtv_property_cache.layer[i].segment_count = -1; | 893 | c->layer[i].segment_count = -1; |
| 891 | } | 894 | } |
| 892 | 895 | ||
| 893 | return 0; | 896 | return 0; |
| @@ -1020,10 +1023,9 @@ static int is_legacy_delivery_system(fe_delivery_system_t s) | |||
| 1020 | * it's being used for the legacy or new API, reducing code and complexity. | 1023 | * it's being used for the legacy or new API, reducing code and complexity. |
| 1021 | */ | 1024 | */ |
| 1022 | static void dtv_property_cache_sync(struct dvb_frontend *fe, | 1025 | static void dtv_property_cache_sync(struct dvb_frontend *fe, |
| 1023 | struct dvb_frontend_parameters *p) | 1026 | struct dtv_frontend_properties *c, |
| 1027 | const struct dvb_frontend_parameters *p) | ||
| 1024 | { | 1028 | { |
| 1025 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1026 | |||
| 1027 | c->frequency = p->frequency; | 1029 | c->frequency = p->frequency; |
| 1028 | c->inversion = p->inversion; | 1030 | c->inversion = p->inversion; |
| 1029 | 1031 | ||
| @@ -1074,9 +1076,9 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe, | |||
| 1074 | */ | 1076 | */ |
| 1075 | static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | 1077 | static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) |
| 1076 | { | 1078 | { |
| 1077 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1079 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 1078 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 1080 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1079 | struct dvb_frontend_parameters *p = &fepriv->parameters; | 1081 | struct dvb_frontend_parameters *p = &fepriv->parameters_in; |
| 1080 | 1082 | ||
| 1081 | p->frequency = c->frequency; | 1083 | p->frequency = c->frequency; |
| 1082 | p->inversion = c->inversion; | 1084 | p->inversion = c->inversion; |
| @@ -1086,14 +1088,12 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | |||
| 1086 | dprintk("%s() Preparing QPSK req\n", __func__); | 1088 | dprintk("%s() Preparing QPSK req\n", __func__); |
| 1087 | p->u.qpsk.symbol_rate = c->symbol_rate; | 1089 | p->u.qpsk.symbol_rate = c->symbol_rate; |
| 1088 | p->u.qpsk.fec_inner = c->fec_inner; | 1090 | p->u.qpsk.fec_inner = c->fec_inner; |
| 1089 | c->delivery_system = SYS_DVBS; | ||
| 1090 | break; | 1091 | break; |
| 1091 | case FE_QAM: | 1092 | case FE_QAM: |
| 1092 | dprintk("%s() Preparing QAM req\n", __func__); | 1093 | dprintk("%s() Preparing QAM req\n", __func__); |
| 1093 | p->u.qam.symbol_rate = c->symbol_rate; | 1094 | p->u.qam.symbol_rate = c->symbol_rate; |
| 1094 | p->u.qam.fec_inner = c->fec_inner; | 1095 | p->u.qam.fec_inner = c->fec_inner; |
| 1095 | p->u.qam.modulation = c->modulation; | 1096 | p->u.qam.modulation = c->modulation; |
| 1096 | c->delivery_system = SYS_DVBC_ANNEX_AC; | ||
| 1097 | break; | 1097 | break; |
| 1098 | case FE_OFDM: | 1098 | case FE_OFDM: |
| 1099 | dprintk("%s() Preparing OFDM req\n", __func__); | 1099 | dprintk("%s() Preparing OFDM req\n", __func__); |
| @@ -1111,15 +1111,10 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | |||
| 1111 | p->u.ofdm.transmission_mode = c->transmission_mode; | 1111 | p->u.ofdm.transmission_mode = c->transmission_mode; |
| 1112 | p->u.ofdm.guard_interval = c->guard_interval; | 1112 | p->u.ofdm.guard_interval = c->guard_interval; |
| 1113 | p->u.ofdm.hierarchy_information = c->hierarchy; | 1113 | p->u.ofdm.hierarchy_information = c->hierarchy; |
| 1114 | c->delivery_system = SYS_DVBT; | ||
| 1115 | break; | 1114 | break; |
| 1116 | case FE_ATSC: | 1115 | case FE_ATSC: |
| 1117 | dprintk("%s() Preparing VSB req\n", __func__); | 1116 | dprintk("%s() Preparing VSB req\n", __func__); |
| 1118 | p->u.vsb.modulation = c->modulation; | 1117 | p->u.vsb.modulation = c->modulation; |
| 1119 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | ||
| 1120 | c->delivery_system = SYS_ATSC; | ||
| 1121 | else | ||
| 1122 | c->delivery_system = SYS_DVBC_ANNEX_B; | ||
| 1123 | break; | 1118 | break; |
| 1124 | } | 1119 | } |
| 1125 | } | 1120 | } |
| @@ -1129,9 +1124,9 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | |||
| 1129 | */ | 1124 | */ |
| 1130 | static void dtv_property_adv_params_sync(struct dvb_frontend *fe) | 1125 | static void dtv_property_adv_params_sync(struct dvb_frontend *fe) |
| 1131 | { | 1126 | { |
| 1132 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1127 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 1133 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 1128 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1134 | struct dvb_frontend_parameters *p = &fepriv->parameters; | 1129 | struct dvb_frontend_parameters *p = &fepriv->parameters_in; |
| 1135 | 1130 | ||
| 1136 | p->frequency = c->frequency; | 1131 | p->frequency = c->frequency; |
| 1137 | p->inversion = c->inversion; | 1132 | p->inversion = c->inversion; |
| @@ -1148,10 +1143,9 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) | |||
| 1148 | break; | 1143 | break; |
| 1149 | } | 1144 | } |
| 1150 | 1145 | ||
| 1151 | if(c->delivery_system == SYS_ISDBT) { | 1146 | /* Fake out a generic DVB-T request so we pass validation in the ioctl */ |
| 1152 | /* Fake out a generic DVB-T request so we pass validation in the ioctl */ | 1147 | if ((c->delivery_system == SYS_ISDBT) || |
| 1153 | p->frequency = c->frequency; | 1148 | (c->delivery_system == SYS_DVBT2)) { |
| 1154 | p->inversion = c->inversion; | ||
| 1155 | p->u.ofdm.constellation = QAM_AUTO; | 1149 | p->u.ofdm.constellation = QAM_AUTO; |
| 1156 | p->u.ofdm.code_rate_HP = FEC_AUTO; | 1150 | p->u.ofdm.code_rate_HP = FEC_AUTO; |
| 1157 | p->u.ofdm.code_rate_LP = FEC_AUTO; | 1151 | p->u.ofdm.code_rate_LP = FEC_AUTO; |
| @@ -1171,7 +1165,7 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) | |||
| 1171 | 1165 | ||
| 1172 | static void dtv_property_cache_submit(struct dvb_frontend *fe) | 1166 | static void dtv_property_cache_submit(struct dvb_frontend *fe) |
| 1173 | { | 1167 | { |
| 1174 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1168 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 1175 | 1169 | ||
| 1176 | /* For legacy delivery systems we don't need the delivery_system to | 1170 | /* For legacy delivery systems we don't need the delivery_system to |
| 1177 | * be specified, but we populate the older structures from the cache | 1171 | * be specified, but we populate the older structures from the cache |
| @@ -1204,133 +1198,149 @@ static int dtv_property_process_get(struct dvb_frontend *fe, | |||
| 1204 | struct dtv_property *tvp, | 1198 | struct dtv_property *tvp, |
| 1205 | struct file *file) | 1199 | struct file *file) |
| 1206 | { | 1200 | { |
| 1207 | int r = 0; | 1201 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 1208 | 1202 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | |
| 1209 | /* Allow the frontend to validate incoming properties */ | 1203 | struct dtv_frontend_properties cdetected; |
| 1210 | if (fe->ops.get_property) | 1204 | int r; |
| 1211 | r = fe->ops.get_property(fe, tvp); | ||
| 1212 | 1205 | ||
| 1213 | if (r < 0) | 1206 | /* |
| 1214 | return r; | 1207 | * If the driver implements a get_frontend function, then convert |
| 1208 | * detected parameters to S2API properties. | ||
| 1209 | */ | ||
| 1210 | if (fe->ops.get_frontend) { | ||
| 1211 | cdetected = *c; | ||
| 1212 | dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out); | ||
| 1213 | c = &cdetected; | ||
| 1214 | } | ||
| 1215 | 1215 | ||
| 1216 | switch(tvp->cmd) { | 1216 | switch(tvp->cmd) { |
| 1217 | case DTV_FREQUENCY: | 1217 | case DTV_FREQUENCY: |
| 1218 | tvp->u.data = fe->dtv_property_cache.frequency; | 1218 | tvp->u.data = c->frequency; |
| 1219 | break; | 1219 | break; |
| 1220 | case DTV_MODULATION: | 1220 | case DTV_MODULATION: |
| 1221 | tvp->u.data = fe->dtv_property_cache.modulation; | 1221 | tvp->u.data = c->modulation; |
| 1222 | break; | 1222 | break; |
| 1223 | case DTV_BANDWIDTH_HZ: | 1223 | case DTV_BANDWIDTH_HZ: |
| 1224 | tvp->u.data = fe->dtv_property_cache.bandwidth_hz; | 1224 | tvp->u.data = c->bandwidth_hz; |
| 1225 | break; | 1225 | break; |
| 1226 | case DTV_INVERSION: | 1226 | case DTV_INVERSION: |
| 1227 | tvp->u.data = fe->dtv_property_cache.inversion; | 1227 | tvp->u.data = c->inversion; |
| 1228 | break; | 1228 | break; |
| 1229 | case DTV_SYMBOL_RATE: | 1229 | case DTV_SYMBOL_RATE: |
| 1230 | tvp->u.data = fe->dtv_property_cache.symbol_rate; | 1230 | tvp->u.data = c->symbol_rate; |
| 1231 | break; | 1231 | break; |
| 1232 | case DTV_INNER_FEC: | 1232 | case DTV_INNER_FEC: |
| 1233 | tvp->u.data = fe->dtv_property_cache.fec_inner; | 1233 | tvp->u.data = c->fec_inner; |
| 1234 | break; | 1234 | break; |
| 1235 | case DTV_PILOT: | 1235 | case DTV_PILOT: |
| 1236 | tvp->u.data = fe->dtv_property_cache.pilot; | 1236 | tvp->u.data = c->pilot; |
| 1237 | break; | 1237 | break; |
| 1238 | case DTV_ROLLOFF: | 1238 | case DTV_ROLLOFF: |
| 1239 | tvp->u.data = fe->dtv_property_cache.rolloff; | 1239 | tvp->u.data = c->rolloff; |
| 1240 | break; | 1240 | break; |
| 1241 | case DTV_DELIVERY_SYSTEM: | 1241 | case DTV_DELIVERY_SYSTEM: |
| 1242 | tvp->u.data = fe->dtv_property_cache.delivery_system; | 1242 | tvp->u.data = c->delivery_system; |
| 1243 | break; | 1243 | break; |
| 1244 | case DTV_VOLTAGE: | 1244 | case DTV_VOLTAGE: |
| 1245 | tvp->u.data = fe->dtv_property_cache.voltage; | 1245 | tvp->u.data = c->voltage; |
| 1246 | break; | 1246 | break; |
| 1247 | case DTV_TONE: | 1247 | case DTV_TONE: |
| 1248 | tvp->u.data = fe->dtv_property_cache.sectone; | 1248 | tvp->u.data = c->sectone; |
| 1249 | break; | 1249 | break; |
| 1250 | case DTV_API_VERSION: | 1250 | case DTV_API_VERSION: |
| 1251 | tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; | 1251 | tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; |
| 1252 | break; | 1252 | break; |
| 1253 | case DTV_CODE_RATE_HP: | 1253 | case DTV_CODE_RATE_HP: |
| 1254 | tvp->u.data = fe->dtv_property_cache.code_rate_HP; | 1254 | tvp->u.data = c->code_rate_HP; |
| 1255 | break; | 1255 | break; |
| 1256 | case DTV_CODE_RATE_LP: | 1256 | case DTV_CODE_RATE_LP: |
| 1257 | tvp->u.data = fe->dtv_property_cache.code_rate_LP; | 1257 | tvp->u.data = c->code_rate_LP; |
| 1258 | break; | 1258 | break; |
| 1259 | case DTV_GUARD_INTERVAL: | 1259 | case DTV_GUARD_INTERVAL: |
| 1260 | tvp->u.data = fe->dtv_property_cache.guard_interval; | 1260 | tvp->u.data = c->guard_interval; |
| 1261 | break; | 1261 | break; |
| 1262 | case DTV_TRANSMISSION_MODE: | 1262 | case DTV_TRANSMISSION_MODE: |
| 1263 | tvp->u.data = fe->dtv_property_cache.transmission_mode; | 1263 | tvp->u.data = c->transmission_mode; |
| 1264 | break; | 1264 | break; |
| 1265 | case DTV_HIERARCHY: | 1265 | case DTV_HIERARCHY: |
| 1266 | tvp->u.data = fe->dtv_property_cache.hierarchy; | 1266 | tvp->u.data = c->hierarchy; |
| 1267 | break; | 1267 | break; |
| 1268 | 1268 | ||
| 1269 | /* ISDB-T Support here */ | 1269 | /* ISDB-T Support here */ |
| 1270 | case DTV_ISDBT_PARTIAL_RECEPTION: | 1270 | case DTV_ISDBT_PARTIAL_RECEPTION: |
| 1271 | tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception; | 1271 | tvp->u.data = c->isdbt_partial_reception; |
| 1272 | break; | 1272 | break; |
| 1273 | case DTV_ISDBT_SOUND_BROADCASTING: | 1273 | case DTV_ISDBT_SOUND_BROADCASTING: |
| 1274 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode; | 1274 | tvp->u.data = c->isdbt_sb_mode; |
| 1275 | break; | 1275 | break; |
| 1276 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | 1276 | case DTV_ISDBT_SB_SUBCHANNEL_ID: |
| 1277 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel; | 1277 | tvp->u.data = c->isdbt_sb_subchannel; |
| 1278 | break; | 1278 | break; |
| 1279 | case DTV_ISDBT_SB_SEGMENT_IDX: | 1279 | case DTV_ISDBT_SB_SEGMENT_IDX: |
| 1280 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx; | 1280 | tvp->u.data = c->isdbt_sb_segment_idx; |
| 1281 | break; | 1281 | break; |
| 1282 | case DTV_ISDBT_SB_SEGMENT_COUNT: | 1282 | case DTV_ISDBT_SB_SEGMENT_COUNT: |
| 1283 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count; | 1283 | tvp->u.data = c->isdbt_sb_segment_count; |
| 1284 | break; | 1284 | break; |
| 1285 | case DTV_ISDBT_LAYER_ENABLED: | 1285 | case DTV_ISDBT_LAYER_ENABLED: |
| 1286 | tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled; | 1286 | tvp->u.data = c->isdbt_layer_enabled; |
| 1287 | break; | 1287 | break; |
| 1288 | case DTV_ISDBT_LAYERA_FEC: | 1288 | case DTV_ISDBT_LAYERA_FEC: |
| 1289 | tvp->u.data = fe->dtv_property_cache.layer[0].fec; | 1289 | tvp->u.data = c->layer[0].fec; |
| 1290 | break; | 1290 | break; |
| 1291 | case DTV_ISDBT_LAYERA_MODULATION: | 1291 | case DTV_ISDBT_LAYERA_MODULATION: |
| 1292 | tvp->u.data = fe->dtv_property_cache.layer[0].modulation; | 1292 | tvp->u.data = c->layer[0].modulation; |
| 1293 | break; | 1293 | break; |
| 1294 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | 1294 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: |
| 1295 | tvp->u.data = fe->dtv_property_cache.layer[0].segment_count; | 1295 | tvp->u.data = c->layer[0].segment_count; |
| 1296 | break; | 1296 | break; |
| 1297 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | 1297 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: |
| 1298 | tvp->u.data = fe->dtv_property_cache.layer[0].interleaving; | 1298 | tvp->u.data = c->layer[0].interleaving; |
| 1299 | break; | 1299 | break; |
| 1300 | case DTV_ISDBT_LAYERB_FEC: | 1300 | case DTV_ISDBT_LAYERB_FEC: |
| 1301 | tvp->u.data = fe->dtv_property_cache.layer[1].fec; | 1301 | tvp->u.data = c->layer[1].fec; |
| 1302 | break; | 1302 | break; |
| 1303 | case DTV_ISDBT_LAYERB_MODULATION: | 1303 | case DTV_ISDBT_LAYERB_MODULATION: |
| 1304 | tvp->u.data = fe->dtv_property_cache.layer[1].modulation; | 1304 | tvp->u.data = c->layer[1].modulation; |
| 1305 | break; | 1305 | break; |
| 1306 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | 1306 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: |
| 1307 | tvp->u.data = fe->dtv_property_cache.layer[1].segment_count; | 1307 | tvp->u.data = c->layer[1].segment_count; |
| 1308 | break; | 1308 | break; |
| 1309 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | 1309 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: |
| 1310 | tvp->u.data = fe->dtv_property_cache.layer[1].interleaving; | 1310 | tvp->u.data = c->layer[1].interleaving; |
| 1311 | break; | 1311 | break; |
| 1312 | case DTV_ISDBT_LAYERC_FEC: | 1312 | case DTV_ISDBT_LAYERC_FEC: |
| 1313 | tvp->u.data = fe->dtv_property_cache.layer[2].fec; | 1313 | tvp->u.data = c->layer[2].fec; |
| 1314 | break; | 1314 | break; |
| 1315 | case DTV_ISDBT_LAYERC_MODULATION: | 1315 | case DTV_ISDBT_LAYERC_MODULATION: |
| 1316 | tvp->u.data = fe->dtv_property_cache.layer[2].modulation; | 1316 | tvp->u.data = c->layer[2].modulation; |
| 1317 | break; | 1317 | break; |
| 1318 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | 1318 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: |
| 1319 | tvp->u.data = fe->dtv_property_cache.layer[2].segment_count; | 1319 | tvp->u.data = c->layer[2].segment_count; |
| 1320 | break; | 1320 | break; |
| 1321 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | 1321 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: |
| 1322 | tvp->u.data = fe->dtv_property_cache.layer[2].interleaving; | 1322 | tvp->u.data = c->layer[2].interleaving; |
| 1323 | break; | 1323 | break; |
| 1324 | case DTV_ISDBS_TS_ID: | 1324 | case DTV_ISDBS_TS_ID: |
| 1325 | tvp->u.data = fe->dtv_property_cache.isdbs_ts_id; | 1325 | tvp->u.data = c->isdbs_ts_id; |
| 1326 | break; | ||
| 1327 | case DTV_DVBT2_PLP_ID: | ||
| 1328 | tvp->u.data = c->dvbt2_plp_id; | ||
| 1326 | break; | 1329 | break; |
| 1327 | default: | 1330 | default: |
| 1328 | r = -1; | 1331 | return -EINVAL; |
| 1332 | } | ||
| 1333 | |||
| 1334 | /* Allow the frontend to override outgoing properties */ | ||
| 1335 | if (fe->ops.get_property) { | ||
| 1336 | r = fe->ops.get_property(fe, tvp); | ||
| 1337 | if (r < 0) | ||
| 1338 | return r; | ||
| 1329 | } | 1339 | } |
| 1330 | 1340 | ||
| 1331 | dtv_property_dump(tvp); | 1341 | dtv_property_dump(tvp); |
| 1332 | 1342 | ||
| 1333 | return r; | 1343 | return 0; |
| 1334 | } | 1344 | } |
| 1335 | 1345 | ||
| 1336 | static int dtv_property_process_set(struct dvb_frontend *fe, | 1346 | static int dtv_property_process_set(struct dvb_frontend *fe, |
| @@ -1338,15 +1348,16 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
| 1338 | struct file *file) | 1348 | struct file *file) |
| 1339 | { | 1349 | { |
| 1340 | int r = 0; | 1350 | int r = 0; |
| 1351 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1341 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 1352 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1342 | dtv_property_dump(tvp); | 1353 | dtv_property_dump(tvp); |
| 1343 | 1354 | ||
| 1344 | /* Allow the frontend to validate incoming properties */ | 1355 | /* Allow the frontend to validate incoming properties */ |
| 1345 | if (fe->ops.set_property) | 1356 | if (fe->ops.set_property) { |
| 1346 | r = fe->ops.set_property(fe, tvp); | 1357 | r = fe->ops.set_property(fe, tvp); |
| 1347 | 1358 | if (r < 0) | |
| 1348 | if (r < 0) | 1359 | return r; |
| 1349 | return r; | 1360 | } |
| 1350 | 1361 | ||
| 1351 | switch(tvp->cmd) { | 1362 | switch(tvp->cmd) { |
| 1352 | case DTV_CLEAR: | 1363 | case DTV_CLEAR: |
| @@ -1361,126 +1372,129 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
| 1361 | * tunerequest so we can pass validation in the FE_SET_FRONTEND | 1372 | * tunerequest so we can pass validation in the FE_SET_FRONTEND |
| 1362 | * ioctl. | 1373 | * ioctl. |
| 1363 | */ | 1374 | */ |
| 1364 | fe->dtv_property_cache.state = tvp->cmd; | 1375 | c->state = tvp->cmd; |
| 1365 | dprintk("%s() Finalised property cache\n", __func__); | 1376 | dprintk("%s() Finalised property cache\n", __func__); |
| 1366 | dtv_property_cache_submit(fe); | 1377 | dtv_property_cache_submit(fe); |
| 1367 | 1378 | ||
| 1368 | r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, | 1379 | r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, |
| 1369 | &fepriv->parameters); | 1380 | &fepriv->parameters_in); |
| 1370 | break; | 1381 | break; |
| 1371 | case DTV_FREQUENCY: | 1382 | case DTV_FREQUENCY: |
| 1372 | fe->dtv_property_cache.frequency = tvp->u.data; | 1383 | c->frequency = tvp->u.data; |
| 1373 | break; | 1384 | break; |
| 1374 | case DTV_MODULATION: | 1385 | case DTV_MODULATION: |
| 1375 | fe->dtv_property_cache.modulation = tvp->u.data; | 1386 | c->modulation = tvp->u.data; |
| 1376 | break; | 1387 | break; |
| 1377 | case DTV_BANDWIDTH_HZ: | 1388 | case DTV_BANDWIDTH_HZ: |
| 1378 | fe->dtv_property_cache.bandwidth_hz = tvp->u.data; | 1389 | c->bandwidth_hz = tvp->u.data; |
| 1379 | break; | 1390 | break; |
| 1380 | case DTV_INVERSION: | 1391 | case DTV_INVERSION: |
| 1381 | fe->dtv_property_cache.inversion = tvp->u.data; | 1392 | c->inversion = tvp->u.data; |
| 1382 | break; | 1393 | break; |
| 1383 | case DTV_SYMBOL_RATE: | 1394 | case DTV_SYMBOL_RATE: |
| 1384 | fe->dtv_property_cache.symbol_rate = tvp->u.data; | 1395 | c->symbol_rate = tvp->u.data; |
| 1385 | break; | 1396 | break; |
| 1386 | case DTV_INNER_FEC: | 1397 | case DTV_INNER_FEC: |
| 1387 | fe->dtv_property_cache.fec_inner = tvp->u.data; | 1398 | c->fec_inner = tvp->u.data; |
| 1388 | break; | 1399 | break; |
| 1389 | case DTV_PILOT: | 1400 | case DTV_PILOT: |
| 1390 | fe->dtv_property_cache.pilot = tvp->u.data; | 1401 | c->pilot = tvp->u.data; |
| 1391 | break; | 1402 | break; |
| 1392 | case DTV_ROLLOFF: | 1403 | case DTV_ROLLOFF: |
| 1393 | fe->dtv_property_cache.rolloff = tvp->u.data; | 1404 | c->rolloff = tvp->u.data; |
| 1394 | break; | 1405 | break; |
| 1395 | case DTV_DELIVERY_SYSTEM: | 1406 | case DTV_DELIVERY_SYSTEM: |
| 1396 | fe->dtv_property_cache.delivery_system = tvp->u.data; | 1407 | c->delivery_system = tvp->u.data; |
| 1397 | break; | 1408 | break; |
| 1398 | case DTV_VOLTAGE: | 1409 | case DTV_VOLTAGE: |
| 1399 | fe->dtv_property_cache.voltage = tvp->u.data; | 1410 | c->voltage = tvp->u.data; |
| 1400 | r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, | 1411 | r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, |
| 1401 | (void *)fe->dtv_property_cache.voltage); | 1412 | (void *)c->voltage); |
| 1402 | break; | 1413 | break; |
| 1403 | case DTV_TONE: | 1414 | case DTV_TONE: |
| 1404 | fe->dtv_property_cache.sectone = tvp->u.data; | 1415 | c->sectone = tvp->u.data; |
| 1405 | r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, | 1416 | r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, |
| 1406 | (void *)fe->dtv_property_cache.sectone); | 1417 | (void *)c->sectone); |
| 1407 | break; | 1418 | break; |
| 1408 | case DTV_CODE_RATE_HP: | 1419 | case DTV_CODE_RATE_HP: |
| 1409 | fe->dtv_property_cache.code_rate_HP = tvp->u.data; | 1420 | c->code_rate_HP = tvp->u.data; |
| 1410 | break; | 1421 | break; |
| 1411 | case DTV_CODE_RATE_LP: | 1422 | case DTV_CODE_RATE_LP: |
| 1412 | fe->dtv_property_cache.code_rate_LP = tvp->u.data; | 1423 | c->code_rate_LP = tvp->u.data; |
| 1413 | break; | 1424 | break; |
| 1414 | case DTV_GUARD_INTERVAL: | 1425 | case DTV_GUARD_INTERVAL: |
| 1415 | fe->dtv_property_cache.guard_interval = tvp->u.data; | 1426 | c->guard_interval = tvp->u.data; |
| 1416 | break; | 1427 | break; |
| 1417 | case DTV_TRANSMISSION_MODE: | 1428 | case DTV_TRANSMISSION_MODE: |
| 1418 | fe->dtv_property_cache.transmission_mode = tvp->u.data; | 1429 | c->transmission_mode = tvp->u.data; |
| 1419 | break; | 1430 | break; |
| 1420 | case DTV_HIERARCHY: | 1431 | case DTV_HIERARCHY: |
| 1421 | fe->dtv_property_cache.hierarchy = tvp->u.data; | 1432 | c->hierarchy = tvp->u.data; |
| 1422 | break; | 1433 | break; |
| 1423 | 1434 | ||
| 1424 | /* ISDB-T Support here */ | 1435 | /* ISDB-T Support here */ |
| 1425 | case DTV_ISDBT_PARTIAL_RECEPTION: | 1436 | case DTV_ISDBT_PARTIAL_RECEPTION: |
| 1426 | fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data; | 1437 | c->isdbt_partial_reception = tvp->u.data; |
| 1427 | break; | 1438 | break; |
| 1428 | case DTV_ISDBT_SOUND_BROADCASTING: | 1439 | case DTV_ISDBT_SOUND_BROADCASTING: |
| 1429 | fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data; | 1440 | c->isdbt_sb_mode = tvp->u.data; |
| 1430 | break; | 1441 | break; |
| 1431 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | 1442 | case DTV_ISDBT_SB_SUBCHANNEL_ID: |
| 1432 | fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data; | 1443 | c->isdbt_sb_subchannel = tvp->u.data; |
| 1433 | break; | 1444 | break; |
| 1434 | case DTV_ISDBT_SB_SEGMENT_IDX: | 1445 | case DTV_ISDBT_SB_SEGMENT_IDX: |
| 1435 | fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data; | 1446 | c->isdbt_sb_segment_idx = tvp->u.data; |
| 1436 | break; | 1447 | break; |
| 1437 | case DTV_ISDBT_SB_SEGMENT_COUNT: | 1448 | case DTV_ISDBT_SB_SEGMENT_COUNT: |
| 1438 | fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data; | 1449 | c->isdbt_sb_segment_count = tvp->u.data; |
| 1439 | break; | 1450 | break; |
| 1440 | case DTV_ISDBT_LAYER_ENABLED: | 1451 | case DTV_ISDBT_LAYER_ENABLED: |
| 1441 | fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data; | 1452 | c->isdbt_layer_enabled = tvp->u.data; |
| 1442 | break; | 1453 | break; |
| 1443 | case DTV_ISDBT_LAYERA_FEC: | 1454 | case DTV_ISDBT_LAYERA_FEC: |
| 1444 | fe->dtv_property_cache.layer[0].fec = tvp->u.data; | 1455 | c->layer[0].fec = tvp->u.data; |
| 1445 | break; | 1456 | break; |
| 1446 | case DTV_ISDBT_LAYERA_MODULATION: | 1457 | case DTV_ISDBT_LAYERA_MODULATION: |
| 1447 | fe->dtv_property_cache.layer[0].modulation = tvp->u.data; | 1458 | c->layer[0].modulation = tvp->u.data; |
| 1448 | break; | 1459 | break; |
| 1449 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | 1460 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: |
| 1450 | fe->dtv_property_cache.layer[0].segment_count = tvp->u.data; | 1461 | c->layer[0].segment_count = tvp->u.data; |
| 1451 | break; | 1462 | break; |
| 1452 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | 1463 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: |
| 1453 | fe->dtv_property_cache.layer[0].interleaving = tvp->u.data; | 1464 | c->layer[0].interleaving = tvp->u.data; |
| 1454 | break; | 1465 | break; |
| 1455 | case DTV_ISDBT_LAYERB_FEC: | 1466 | case DTV_ISDBT_LAYERB_FEC: |
| 1456 | fe->dtv_property_cache.layer[1].fec = tvp->u.data; | 1467 | c->layer[1].fec = tvp->u.data; |
| 1457 | break; | 1468 | break; |
| 1458 | case DTV_ISDBT_LAYERB_MODULATION: | 1469 | case DTV_ISDBT_LAYERB_MODULATION: |
| 1459 | fe->dtv_property_cache.layer[1].modulation = tvp->u.data; | 1470 | c->layer[1].modulation = tvp->u.data; |
| 1460 | break; | 1471 | break; |
| 1461 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | 1472 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: |
| 1462 | fe->dtv_property_cache.layer[1].segment_count = tvp->u.data; | 1473 | c->layer[1].segment_count = tvp->u.data; |
| 1463 | break; | 1474 | break; |
| 1464 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | 1475 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: |
| 1465 | fe->dtv_property_cache.layer[1].interleaving = tvp->u.data; | 1476 | c->layer[1].interleaving = tvp->u.data; |
| 1466 | break; | 1477 | break; |
| 1467 | case DTV_ISDBT_LAYERC_FEC: | 1478 | case DTV_ISDBT_LAYERC_FEC: |
| 1468 | fe->dtv_property_cache.layer[2].fec = tvp->u.data; | 1479 | c->layer[2].fec = tvp->u.data; |
| 1469 | break; | 1480 | break; |
| 1470 | case DTV_ISDBT_LAYERC_MODULATION: | 1481 | case DTV_ISDBT_LAYERC_MODULATION: |
| 1471 | fe->dtv_property_cache.layer[2].modulation = tvp->u.data; | 1482 | c->layer[2].modulation = tvp->u.data; |
| 1472 | break; | 1483 | break; |
| 1473 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | 1484 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: |
| 1474 | fe->dtv_property_cache.layer[2].segment_count = tvp->u.data; | 1485 | c->layer[2].segment_count = tvp->u.data; |
| 1475 | break; | 1486 | break; |
| 1476 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | 1487 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: |
| 1477 | fe->dtv_property_cache.layer[2].interleaving = tvp->u.data; | 1488 | c->layer[2].interleaving = tvp->u.data; |
| 1478 | break; | 1489 | break; |
| 1479 | case DTV_ISDBS_TS_ID: | 1490 | case DTV_ISDBS_TS_ID: |
| 1480 | fe->dtv_property_cache.isdbs_ts_id = tvp->u.data; | 1491 | c->isdbs_ts_id = tvp->u.data; |
| 1492 | break; | ||
| 1493 | case DTV_DVBT2_PLP_ID: | ||
| 1494 | c->dvbt2_plp_id = tvp->u.data; | ||
| 1481 | break; | 1495 | break; |
| 1482 | default: | 1496 | default: |
| 1483 | r = -1; | 1497 | return -EINVAL; |
| 1484 | } | 1498 | } |
| 1485 | 1499 | ||
| 1486 | return r; | 1500 | return r; |
| @@ -1491,6 +1505,7 @@ static int dvb_frontend_ioctl(struct file *file, | |||
| 1491 | { | 1505 | { |
| 1492 | struct dvb_device *dvbdev = file->private_data; | 1506 | struct dvb_device *dvbdev = file->private_data; |
| 1493 | struct dvb_frontend *fe = dvbdev->priv; | 1507 | struct dvb_frontend *fe = dvbdev->priv; |
| 1508 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1494 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 1509 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1495 | int err = -EOPNOTSUPP; | 1510 | int err = -EOPNOTSUPP; |
| 1496 | 1511 | ||
| @@ -1510,7 +1525,7 @@ static int dvb_frontend_ioctl(struct file *file, | |||
| 1510 | if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) | 1525 | if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) |
| 1511 | err = dvb_frontend_ioctl_properties(file, cmd, parg); | 1526 | err = dvb_frontend_ioctl_properties(file, cmd, parg); |
| 1512 | else { | 1527 | else { |
| 1513 | fe->dtv_property_cache.state = DTV_UNDEFINED; | 1528 | c->state = DTV_UNDEFINED; |
| 1514 | err = dvb_frontend_ioctl_legacy(file, cmd, parg); | 1529 | err = dvb_frontend_ioctl_legacy(file, cmd, parg); |
| 1515 | } | 1530 | } |
| 1516 | 1531 | ||
| @@ -1523,6 +1538,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, | |||
| 1523 | { | 1538 | { |
| 1524 | struct dvb_device *dvbdev = file->private_data; | 1539 | struct dvb_device *dvbdev = file->private_data; |
| 1525 | struct dvb_frontend *fe = dvbdev->priv; | 1540 | struct dvb_frontend *fe = dvbdev->priv; |
| 1541 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1526 | int err = 0; | 1542 | int err = 0; |
| 1527 | 1543 | ||
| 1528 | struct dtv_properties *tvps = NULL; | 1544 | struct dtv_properties *tvps = NULL; |
| @@ -1554,11 +1570,13 @@ static int dvb_frontend_ioctl_properties(struct file *file, | |||
| 1554 | } | 1570 | } |
| 1555 | 1571 | ||
| 1556 | for (i = 0; i < tvps->num; i++) { | 1572 | for (i = 0; i < tvps->num; i++) { |
| 1557 | (tvp + i)->result = dtv_property_process_set(fe, tvp + i, file); | 1573 | err = dtv_property_process_set(fe, tvp + i, file); |
| 1558 | err |= (tvp + i)->result; | 1574 | if (err < 0) |
| 1575 | goto out; | ||
| 1576 | (tvp + i)->result = err; | ||
| 1559 | } | 1577 | } |
| 1560 | 1578 | ||
| 1561 | if(fe->dtv_property_cache.state == DTV_TUNE) | 1579 | if (c->state == DTV_TUNE) |
| 1562 | dprintk("%s() Property cache is full, tuning\n", __func__); | 1580 | dprintk("%s() Property cache is full, tuning\n", __func__); |
| 1563 | 1581 | ||
| 1564 | } else | 1582 | } else |
| @@ -1586,8 +1604,10 @@ static int dvb_frontend_ioctl_properties(struct file *file, | |||
| 1586 | } | 1604 | } |
| 1587 | 1605 | ||
| 1588 | for (i = 0; i < tvps->num; i++) { | 1606 | for (i = 0; i < tvps->num; i++) { |
| 1589 | (tvp + i)->result = dtv_property_process_get(fe, tvp + i, file); | 1607 | err = dtv_property_process_get(fe, tvp + i, file); |
| 1590 | err |= (tvp + i)->result; | 1608 | if (err < 0) |
| 1609 | goto out; | ||
| 1610 | (tvp + i)->result = err; | ||
| 1591 | } | 1611 | } |
| 1592 | 1612 | ||
| 1593 | if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { | 1613 | if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { |
| @@ -1787,10 +1807,11 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
| 1787 | break; | 1807 | break; |
| 1788 | 1808 | ||
| 1789 | case FE_SET_FRONTEND: { | 1809 | case FE_SET_FRONTEND: { |
| 1810 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1790 | struct dvb_frontend_tune_settings fetunesettings; | 1811 | struct dvb_frontend_tune_settings fetunesettings; |
| 1791 | 1812 | ||
| 1792 | if(fe->dtv_property_cache.state == DTV_TUNE) { | 1813 | if (c->state == DTV_TUNE) { |
| 1793 | if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { | 1814 | if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) { |
| 1794 | err = -EINVAL; | 1815 | err = -EINVAL; |
| 1795 | break; | 1816 | break; |
| 1796 | } | 1817 | } |
| @@ -1800,9 +1821,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
| 1800 | break; | 1821 | break; |
| 1801 | } | 1822 | } |
| 1802 | 1823 | ||
| 1803 | memcpy (&fepriv->parameters, parg, | 1824 | memcpy (&fepriv->parameters_in, parg, |
| 1804 | sizeof (struct dvb_frontend_parameters)); | 1825 | sizeof (struct dvb_frontend_parameters)); |
| 1805 | dtv_property_cache_sync(fe, &fepriv->parameters); | 1826 | dtv_property_cache_sync(fe, c, &fepriv->parameters_in); |
| 1806 | } | 1827 | } |
| 1807 | 1828 | ||
| 1808 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); | 1829 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); |
| @@ -1811,15 +1832,15 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
| 1811 | 1832 | ||
| 1812 | /* force auto frequency inversion if requested */ | 1833 | /* force auto frequency inversion if requested */ |
| 1813 | if (dvb_force_auto_inversion) { | 1834 | if (dvb_force_auto_inversion) { |
| 1814 | fepriv->parameters.inversion = INVERSION_AUTO; | 1835 | fepriv->parameters_in.inversion = INVERSION_AUTO; |
| 1815 | fetunesettings.parameters.inversion = INVERSION_AUTO; | 1836 | fetunesettings.parameters.inversion = INVERSION_AUTO; |
| 1816 | } | 1837 | } |
| 1817 | if (fe->ops.info.type == FE_OFDM) { | 1838 | if (fe->ops.info.type == FE_OFDM) { |
| 1818 | /* without hierarchical coding code_rate_LP is irrelevant, | 1839 | /* without hierarchical coding code_rate_LP is irrelevant, |
| 1819 | * so we tolerate the otherwise invalid FEC_NONE setting */ | 1840 | * so we tolerate the otherwise invalid FEC_NONE setting */ |
| 1820 | if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE && | 1841 | if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE && |
| 1821 | fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE) | 1842 | fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE) |
| 1822 | fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO; | 1843 | fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO; |
| 1823 | } | 1844 | } |
| 1824 | 1845 | ||
| 1825 | /* get frontend-specific tuning settings */ | 1846 | /* get frontend-specific tuning settings */ |
| @@ -1832,8 +1853,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
| 1832 | switch(fe->ops.info.type) { | 1853 | switch(fe->ops.info.type) { |
| 1833 | case FE_QPSK: | 1854 | case FE_QPSK: |
| 1834 | fepriv->min_delay = HZ/20; | 1855 | fepriv->min_delay = HZ/20; |
| 1835 | fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000; | 1856 | fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000; |
| 1836 | fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000; | 1857 | fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000; |
| 1837 | break; | 1858 | break; |
| 1838 | 1859 | ||
| 1839 | case FE_QAM: | 1860 | case FE_QAM: |
| @@ -1875,8 +1896,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
| 1875 | 1896 | ||
| 1876 | case FE_GET_FRONTEND: | 1897 | case FE_GET_FRONTEND: |
| 1877 | if (fe->ops.get_frontend) { | 1898 | if (fe->ops.get_frontend) { |
| 1878 | memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters)); | 1899 | err = fe->ops.get_frontend(fe, &fepriv->parameters_out); |
| 1879 | err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg); | 1900 | memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters)); |
| 1880 | } | 1901 | } |
| 1881 | break; | 1902 | break; |
| 1882 | 1903 | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 3b860504bf04..5590eb6eb408 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h | |||
| @@ -358,6 +358,9 @@ struct dtv_frontend_properties { | |||
| 358 | 358 | ||
| 359 | /* ISDB-T specifics */ | 359 | /* ISDB-T specifics */ |
| 360 | u32 isdbs_ts_id; | 360 | u32 isdbs_ts_id; |
| 361 | |||
| 362 | /* DVB-T2 specifics */ | ||
| 363 | u32 dvbt2_plp_id; | ||
| 361 | }; | 364 | }; |
| 362 | 365 | ||
| 363 | struct dvb_frontend { | 366 | struct dvb_frontend { |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index c545039287ad..e85304c59a2b 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
| @@ -292,6 +292,11 @@ config DVB_USB_ANYSEE | |||
| 292 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 292 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
| 293 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 293 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
| 294 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | 294 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE |
| 295 | select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE | ||
| 296 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
| 297 | select DVB_STV0900 if !DVB_FE_CUSTOMISE | ||
| 298 | select DVB_STV6110 if !DVB_FE_CUSTOMISE | ||
| 299 | select DVB_ISL6423 if !DVB_FE_CUSTOMISE | ||
| 295 | help | 300 | help |
| 296 | Say Y here to support the Anysee E30, Anysee E30 Plus or | 301 | Say Y here to support the Anysee E30, Anysee E30 Plus or |
| 297 | Anysee E30 C Plus DVB USB2.0 receiver. | 302 | Anysee E30 C Plus DVB USB2.0 receiver. |
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index f8e9bf116f21..b95a95e17840 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c | |||
| @@ -78,17 +78,26 @@ static struct rc_map_table rc_map_a800_table[] = { | |||
| 78 | 78 | ||
| 79 | static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 79 | static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 80 | { | 80 | { |
| 81 | u8 key[5]; | 81 | int ret; |
| 82 | u8 *key = kmalloc(5, GFP_KERNEL); | ||
| 83 | if (!key) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 82 | if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), | 86 | if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), |
| 83 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, | 87 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, |
| 84 | 2000) != 5) | 88 | 2000) != 5) { |
| 85 | return -ENODEV; | 89 | ret = -ENODEV; |
| 90 | goto out; | ||
| 91 | } | ||
| 86 | 92 | ||
| 87 | /* call the universal NEC remote processor, to find out the key's state and event */ | 93 | /* call the universal NEC remote processor, to find out the key's state and event */ |
| 88 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | 94 | dvb_usb_nec_rc_key_to_event(d,key,event,state); |
| 89 | if (key[0] != 0) | 95 | if (key[0] != 0) |
| 90 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | 96 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); |
| 91 | return 0; | 97 | ret = 0; |
| 98 | out: | ||
| 99 | kfree(key); | ||
| 100 | return ret; | ||
| 92 | } | 101 | } |
| 93 | 102 | ||
| 94 | /* USB Driver stuff */ | 103 | /* USB Driver stuff */ |
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 6b402e943539..4dc1ca333236 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
| @@ -36,6 +36,11 @@ | |||
| 36 | #include "mt352.h" | 36 | #include "mt352.h" |
| 37 | #include "mt352_priv.h" | 37 | #include "mt352_priv.h" |
| 38 | #include "zl10353.h" | 38 | #include "zl10353.h" |
| 39 | #include "tda18212.h" | ||
| 40 | #include "cx24116.h" | ||
| 41 | #include "stv0900.h" | ||
| 42 | #include "stv6110.h" | ||
| 43 | #include "isl6423.h" | ||
| 39 | 44 | ||
| 40 | /* debug */ | 45 | /* debug */ |
| 41 | static int dvb_usb_anysee_debug; | 46 | static int dvb_usb_anysee_debug; |
| @@ -105,6 +110,27 @@ static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val) | |||
| 105 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | 110 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); |
| 106 | } | 111 | } |
| 107 | 112 | ||
| 113 | /* write single register with mask */ | ||
| 114 | static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, | ||
| 115 | u8 mask) | ||
| 116 | { | ||
| 117 | int ret; | ||
| 118 | u8 tmp; | ||
| 119 | |||
| 120 | /* no need for read if whole reg is written */ | ||
| 121 | if (mask != 0xff) { | ||
| 122 | ret = anysee_read_reg(d, reg, &tmp); | ||
| 123 | if (ret) | ||
| 124 | return ret; | ||
| 125 | |||
| 126 | val &= mask; | ||
| 127 | tmp &= ~mask; | ||
| 128 | val |= tmp; | ||
| 129 | } | ||
| 130 | |||
| 131 | return anysee_write_reg(d, reg, val); | ||
| 132 | } | ||
| 133 | |||
| 108 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) | 134 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) |
| 109 | { | 135 | { |
| 110 | u8 buf[] = {CMD_GET_HW_INFO}; | 136 | u8 buf[] = {CMD_GET_HW_INFO}; |
| @@ -162,18 +188,18 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 162 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | 188 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { |
| 163 | u8 buf[6]; | 189 | u8 buf[6]; |
| 164 | buf[0] = CMD_I2C_READ; | 190 | buf[0] = CMD_I2C_READ; |
| 165 | buf[1] = msg[i].addr + 1; | 191 | buf[1] = (msg[i].addr << 1) | 0x01; |
| 166 | buf[2] = msg[i].buf[0]; | 192 | buf[2] = msg[i].buf[0]; |
| 167 | buf[3] = 0x00; | 193 | buf[3] = msg[i].buf[1]; |
| 168 | buf[4] = 0x00; | 194 | buf[4] = msg[i].len-1; |
| 169 | buf[5] = 0x01; | 195 | buf[5] = msg[i+1].len; |
| 170 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf, | 196 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf, |
| 171 | msg[i+1].len); | 197 | msg[i+1].len); |
| 172 | inc = 2; | 198 | inc = 2; |
| 173 | } else { | 199 | } else { |
| 174 | u8 buf[4+msg[i].len]; | 200 | u8 buf[4+msg[i].len]; |
| 175 | buf[0] = CMD_I2C_WRITE; | 201 | buf[0] = CMD_I2C_WRITE; |
| 176 | buf[1] = msg[i].addr; | 202 | buf[1] = (msg[i].addr << 1); |
| 177 | buf[2] = msg[i].len; | 203 | buf[2] = msg[i].len; |
| 178 | buf[3] = 0x01; | 204 | buf[3] = 0x01; |
| 179 | memcpy(&buf[4], msg[i].buf, msg[i].len); | 205 | memcpy(&buf[4], msg[i].buf, msg[i].len); |
| @@ -224,7 +250,7 @@ static int anysee_mt352_demod_init(struct dvb_frontend *fe) | |||
| 224 | 250 | ||
| 225 | /* Callbacks for DVB USB */ | 251 | /* Callbacks for DVB USB */ |
| 226 | static struct tda10023_config anysee_tda10023_config = { | 252 | static struct tda10023_config anysee_tda10023_config = { |
| 227 | .demod_address = 0x1a, | 253 | .demod_address = (0x1a >> 1), |
| 228 | .invert = 0, | 254 | .invert = 0, |
| 229 | .xtal = 16000000, | 255 | .xtal = 16000000, |
| 230 | .pll_m = 11, | 256 | .pll_m = 11, |
| @@ -235,143 +261,539 @@ static struct tda10023_config anysee_tda10023_config = { | |||
| 235 | }; | 261 | }; |
| 236 | 262 | ||
| 237 | static struct mt352_config anysee_mt352_config = { | 263 | static struct mt352_config anysee_mt352_config = { |
| 238 | .demod_address = 0x1e, | 264 | .demod_address = (0x1e >> 1), |
| 239 | .demod_init = anysee_mt352_demod_init, | 265 | .demod_init = anysee_mt352_demod_init, |
| 240 | }; | 266 | }; |
| 241 | 267 | ||
| 242 | static struct zl10353_config anysee_zl10353_config = { | 268 | static struct zl10353_config anysee_zl10353_config = { |
| 243 | .demod_address = 0x1e, | 269 | .demod_address = (0x1e >> 1), |
| 244 | .parallel_ts = 1, | 270 | .parallel_ts = 1, |
| 245 | }; | 271 | }; |
| 246 | 272 | ||
| 273 | static struct zl10353_config anysee_zl10353_tda18212_config2 = { | ||
| 274 | .demod_address = (0x1e >> 1), | ||
| 275 | .parallel_ts = 1, | ||
| 276 | .disable_i2c_gate_ctrl = 1, | ||
| 277 | .no_tuner = 1, | ||
| 278 | .if2 = 41500, | ||
| 279 | }; | ||
| 280 | |||
| 281 | static struct zl10353_config anysee_zl10353_tda18212_config = { | ||
| 282 | .demod_address = (0x18 >> 1), | ||
| 283 | .parallel_ts = 1, | ||
| 284 | .disable_i2c_gate_ctrl = 1, | ||
| 285 | .no_tuner = 1, | ||
| 286 | .if2 = 41500, | ||
| 287 | }; | ||
| 288 | |||
| 289 | static struct tda10023_config anysee_tda10023_tda18212_config = { | ||
| 290 | .demod_address = (0x1a >> 1), | ||
| 291 | .xtal = 16000000, | ||
| 292 | .pll_m = 12, | ||
| 293 | .pll_p = 3, | ||
| 294 | .pll_n = 1, | ||
| 295 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, | ||
| 296 | .deltaf = 0xba02, | ||
| 297 | }; | ||
| 298 | |||
| 299 | static struct tda18212_config anysee_tda18212_config = { | ||
| 300 | .i2c_address = (0xc0 >> 1), | ||
| 301 | .if_dvbt_6 = 4150, | ||
| 302 | .if_dvbt_7 = 4150, | ||
| 303 | .if_dvbt_8 = 4150, | ||
| 304 | .if_dvbc = 5000, | ||
| 305 | }; | ||
| 306 | |||
| 307 | static struct cx24116_config anysee_cx24116_config = { | ||
| 308 | .demod_address = (0xaa >> 1), | ||
| 309 | .mpg_clk_pos_pol = 0x00, | ||
| 310 | .i2c_wr_max = 48, | ||
| 311 | }; | ||
| 312 | |||
| 313 | static struct stv0900_config anysee_stv0900_config = { | ||
| 314 | .demod_address = (0xd0 >> 1), | ||
| 315 | .demod_mode = 0, | ||
| 316 | .xtal = 8000000, | ||
| 317 | .clkmode = 3, | ||
| 318 | .diseqc_mode = 2, | ||
| 319 | .tun1_maddress = 0, | ||
| 320 | .tun1_adc = 1, /* 1 Vpp */ | ||
| 321 | .path1_mode = 3, | ||
| 322 | }; | ||
| 323 | |||
| 324 | static struct stv6110_config anysee_stv6110_config = { | ||
| 325 | .i2c_address = (0xc0 >> 1), | ||
| 326 | .mclk = 16000000, | ||
| 327 | .clk_div = 1, | ||
| 328 | }; | ||
| 329 | |||
| 330 | static struct isl6423_config anysee_isl6423_config = { | ||
| 331 | .current_max = SEC_CURRENT_800m, | ||
| 332 | .curlim = SEC_CURRENT_LIM_OFF, | ||
| 333 | .mod_extern = 1, | ||
| 334 | .addr = (0x10 >> 1), | ||
| 335 | }; | ||
| 336 | |||
| 337 | /* | ||
| 338 | * New USB device strings: Mfr=1, Product=2, SerialNumber=0 | ||
| 339 | * Manufacturer: AMT.CO.KR | ||
| 340 | * | ||
| 341 | * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=???????? | ||
| 342 | * PCB: ? | ||
| 343 | * parts: DNOS404ZH102A(MT352, DTT7579(?)) | ||
| 344 | * | ||
| 345 | * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=???????? | ||
| 346 | * PCB: ? | ||
| 347 | * parts: DNOS404ZH103A(ZL10353, DTT7579(?)) | ||
| 348 | * | ||
| 349 | * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee" | ||
| 350 | * PCB: 507CD (rev1.1) | ||
| 351 | * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01 | ||
| 352 | * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe | ||
| 353 | * IOA=4f IOB=ff IOC=00 IOD=06 IOF=01 | ||
| 354 | * IOD[0] ZL10353 1=enabled | ||
| 355 | * IOA[7] TS 0=enabled | ||
| 356 | * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not) | ||
| 357 | * | ||
| 358 | * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)" | ||
| 359 | * PCB: 507DC (rev0.2) | ||
| 360 | * parts: TDA10023, DTOS403IH102B TM, CST56I01 | ||
| 361 | * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe | ||
| 362 | * IOA=4f IOB=ff IOC=00 IOD=26 IOF=01 | ||
| 363 | * IOD[0] TDA10023 1=enabled | ||
| 364 | * | ||
| 365 | * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)" | ||
| 366 | * PCB: 507SI (rev2.1) | ||
| 367 | * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024 | ||
| 368 | * OEA=80 OEB=00 OEC=ff OED=ff OEF=fe | ||
| 369 | * IOA=4d IOB=ff IOC=00 IOD=26 IOF=01 | ||
| 370 | * IOD[0] CX24116 1=enabled | ||
| 371 | * | ||
| 372 | * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | ||
| 373 | * PCB: 507FA (rev0.4) | ||
| 374 | * parts: TDA10023, DTOS403IH102B TM, TDA8024 | ||
| 375 | * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff | ||
| 376 | * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0 | ||
| 377 | * IOD[5] TDA10023 1=enabled | ||
| 378 | * IOE[0] tuner 1=enabled | ||
| 379 | * | ||
| 380 | * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | ||
| 381 | * PCB: 507FA (rev1.1) | ||
| 382 | * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024 | ||
| 383 | * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff | ||
| 384 | * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0 | ||
| 385 | * DVB-C: | ||
| 386 | * IOD[5] TDA10023 1=enabled | ||
| 387 | * IOE[0] tuner 1=enabled | ||
| 388 | * DVB-T: | ||
| 389 | * IOD[0] ZL10353 1=enabled | ||
| 390 | * IOE[0] tuner 0=enabled | ||
| 391 | * tuner is behind ZL10353 I2C-gate | ||
| 392 | * | ||
| 393 | * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)" | ||
| 394 | * PCB: 508TC (rev0.6) | ||
| 395 | * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212) | ||
| 396 | * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff | ||
| 397 | * IOA=4d IOB=00 IOC=cc IOD=48 IOF=e4 | ||
| 398 | * IOA[7] TS 1=enabled | ||
| 399 | * IOE[4] TDA18212 1=enabled | ||
| 400 | * DVB-C: | ||
| 401 | * IOD[6] ZL10353 0=disabled | ||
| 402 | * IOD[5] TDA10023 1=enabled | ||
| 403 | * IOE[0] IF 1=enabled | ||
| 404 | * DVB-T: | ||
| 405 | * IOD[5] TDA10023 0=disabled | ||
| 406 | * IOD[6] ZL10353 1=enabled | ||
| 407 | * IOE[0] IF 0=enabled | ||
| 408 | * | ||
| 409 | * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)" | ||
| 410 | * PCB: 508S2 (rev0.7) | ||
| 411 | * parts: DNBU10512IST(STV0903, STV6110), ISL6423 | ||
| 412 | * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff | ||
| 413 | * IOA=4d IOB=00 IOC=c4 IOD=08 IOF=e4 | ||
| 414 | * IOA[7] TS 1=enabled | ||
| 415 | * IOE[5] STV0903 1=enabled | ||
| 416 | * | ||
| 417 | */ | ||
| 418 | |||
| 247 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | 419 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) |
| 248 | { | 420 | { |
| 249 | int ret; | 421 | int ret; |
| 250 | struct anysee_state *state = adap->dev->priv; | 422 | struct anysee_state *state = adap->dev->priv; |
| 251 | u8 hw_info[3]; | 423 | u8 hw_info[3]; |
| 252 | u8 io_d; /* IO port D */ | 424 | u8 tmp; |
| 425 | struct i2c_msg msg[2] = { | ||
| 426 | { | ||
| 427 | .addr = anysee_tda18212_config.i2c_address, | ||
| 428 | .flags = 0, | ||
| 429 | .len = 1, | ||
| 430 | .buf = "\x00", | ||
| 431 | }, { | ||
| 432 | .addr = anysee_tda18212_config.i2c_address, | ||
| 433 | .flags = I2C_M_RD, | ||
| 434 | .len = 1, | ||
| 435 | .buf = &tmp, | ||
| 436 | } | ||
| 437 | }; | ||
| 253 | 438 | ||
| 254 | /* check which hardware we have | 439 | /* Check which hardware we have. |
| 255 | We must do this call two times to get reliable values (hw bug). */ | 440 | * We must do this call two times to get reliable values (hw bug). |
| 441 | */ | ||
| 256 | ret = anysee_get_hw_info(adap->dev, hw_info); | 442 | ret = anysee_get_hw_info(adap->dev, hw_info); |
| 257 | if (ret) | 443 | if (ret) |
| 258 | return ret; | 444 | goto error; |
| 445 | |||
| 259 | ret = anysee_get_hw_info(adap->dev, hw_info); | 446 | ret = anysee_get_hw_info(adap->dev, hw_info); |
| 260 | if (ret) | 447 | if (ret) |
| 261 | return ret; | 448 | goto error; |
| 262 | 449 | ||
| 263 | /* Meaning of these info bytes are guessed. */ | 450 | /* Meaning of these info bytes are guessed. */ |
| 264 | info("firmware version:%d.%d.%d hardware id:%d", | 451 | info("firmware version:%d.%d hardware id:%d", |
| 265 | 0, hw_info[1], hw_info[2], hw_info[0]); | 452 | hw_info[1], hw_info[2], hw_info[0]); |
| 266 | 453 | ||
| 267 | ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */ | 454 | state->hw = hw_info[0]; |
| 268 | if (ret) | ||
| 269 | return ret; | ||
| 270 | deb_info("%s: IO port D:%02x\n", __func__, io_d); | ||
| 271 | |||
| 272 | /* Select demod using trial and error method. */ | ||
| 273 | |||
| 274 | /* Try to attach demodulator in following order: | ||
| 275 | model demod hw firmware | ||
| 276 | 1. E30 MT352 02 0.2.1 | ||
| 277 | 2. E30 ZL10353 02 0.2.1 | ||
| 278 | 3. E30 Combo ZL10353 0f 0.1.2 DVB-T/C combo | ||
| 279 | 4. E30 Plus ZL10353 06 0.1.0 | ||
| 280 | 5. E30C Plus TDA10023 0a 0.1.0 rev 0.2 | ||
| 281 | E30C Plus TDA10023 0f 0.1.2 rev 0.4 | ||
| 282 | E30 Combo TDA10023 0f 0.1.2 DVB-T/C combo | ||
| 283 | */ | ||
| 284 | |||
| 285 | /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */ | ||
| 286 | adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config, | ||
| 287 | &adap->dev->i2c_adap); | ||
| 288 | if (adap->fe != NULL) { | ||
| 289 | state->tuner = DVB_PLL_THOMSON_DTT7579; | ||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | 455 | ||
| 293 | /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */ | 456 | switch (state->hw) { |
| 294 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | 457 | case ANYSEE_HW_02: /* 2 */ |
| 295 | &adap->dev->i2c_adap); | 458 | /* E30 */ |
| 296 | if (adap->fe != NULL) { | 459 | |
| 297 | state->tuner = DVB_PLL_THOMSON_DTT7579; | 460 | /* attach demod */ |
| 298 | return 0; | 461 | adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config, |
| 299 | } | 462 | &adap->dev->i2c_adap); |
| 463 | if (adap->fe) | ||
| 464 | break; | ||
| 465 | |||
| 466 | /* attach demod */ | ||
| 467 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
| 468 | &adap->dev->i2c_adap); | ||
| 469 | |||
| 470 | break; | ||
| 471 | case ANYSEE_HW_507CD: /* 6 */ | ||
| 472 | /* E30 Plus */ | ||
| 300 | 473 | ||
| 301 | /* for E30 Combo Plus DVB-T demodulator */ | 474 | /* enable DVB-T demod on IOD[0] */ |
| 302 | if (dvb_usb_anysee_delsys) { | 475 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); |
| 303 | ret = anysee_write_reg(adap->dev, 0xb0, 0x01); | ||
| 304 | if (ret) | 476 | if (ret) |
| 305 | return ret; | 477 | goto error; |
| 478 | |||
| 479 | /* enable transport stream on IOA[7] */ | ||
| 480 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80); | ||
| 481 | if (ret) | ||
| 482 | goto error; | ||
| 306 | 483 | ||
| 307 | /* Zarlink ZL10353 DVB-T demod */ | 484 | /* attach demod */ |
| 308 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | 485 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, |
| 309 | &adap->dev->i2c_adap); | 486 | &adap->dev->i2c_adap); |
| 310 | if (adap->fe != NULL) { | 487 | |
| 311 | state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A; | 488 | break; |
| 312 | return 0; | 489 | case ANYSEE_HW_507DC: /* 10 */ |
| 490 | /* E30 C Plus */ | ||
| 491 | |||
| 492 | /* enable DVB-C demod on IOD[0] */ | ||
| 493 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | ||
| 494 | if (ret) | ||
| 495 | goto error; | ||
| 496 | |||
| 497 | /* attach demod */ | ||
| 498 | adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config, | ||
| 499 | &adap->dev->i2c_adap, 0x48); | ||
| 500 | |||
| 501 | break; | ||
| 502 | case ANYSEE_HW_507SI: /* 11 */ | ||
| 503 | /* E30 S2 Plus */ | ||
| 504 | |||
| 505 | /* enable DVB-S/S2 demod on IOD[0] */ | ||
| 506 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | ||
| 507 | if (ret) | ||
| 508 | goto error; | ||
| 509 | |||
| 510 | /* attach demod */ | ||
| 511 | adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config, | ||
| 512 | &adap->dev->i2c_adap); | ||
| 513 | |||
| 514 | break; | ||
| 515 | case ANYSEE_HW_507FA: /* 15 */ | ||
| 516 | /* E30 Combo Plus */ | ||
| 517 | /* E30 C Plus */ | ||
| 518 | |||
| 519 | /* enable tuner on IOE[4] */ | ||
| 520 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | ||
| 521 | if (ret) | ||
| 522 | goto error; | ||
| 523 | |||
| 524 | /* probe TDA18212 */ | ||
| 525 | tmp = 0; | ||
| 526 | ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2); | ||
| 527 | if (ret == 2 && tmp == 0xc7) | ||
| 528 | deb_info("%s: TDA18212 found\n", __func__); | ||
| 529 | else | ||
| 530 | tmp = 0; | ||
| 531 | |||
| 532 | /* disable tuner on IOE[4] */ | ||
| 533 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); | ||
| 534 | if (ret) | ||
| 535 | goto error; | ||
| 536 | |||
| 537 | if (dvb_usb_anysee_delsys) { | ||
| 538 | /* disable DVB-C demod on IOD[5] */ | ||
| 539 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), | ||
| 540 | 0x20); | ||
| 541 | if (ret) | ||
| 542 | goto error; | ||
| 543 | |||
| 544 | /* enable DVB-T demod on IOD[0] */ | ||
| 545 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), | ||
| 546 | 0x01); | ||
| 547 | if (ret) | ||
| 548 | goto error; | ||
| 549 | |||
| 550 | /* attach demod */ | ||
| 551 | if (tmp == 0xc7) { | ||
| 552 | /* TDA18212 config */ | ||
| 553 | adap->fe = dvb_attach(zl10353_attach, | ||
| 554 | &anysee_zl10353_tda18212_config2, | ||
| 555 | &adap->dev->i2c_adap); | ||
| 556 | } else { | ||
| 557 | /* PLL config */ | ||
| 558 | adap->fe = dvb_attach(zl10353_attach, | ||
| 559 | &anysee_zl10353_config, | ||
| 560 | &adap->dev->i2c_adap); | ||
| 561 | } | ||
| 562 | } else { | ||
| 563 | /* disable DVB-T demod on IOD[0] */ | ||
| 564 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0), | ||
| 565 | 0x01); | ||
| 566 | if (ret) | ||
| 567 | goto error; | ||
| 568 | |||
| 569 | /* enable DVB-C demod on IOD[5] */ | ||
| 570 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), | ||
| 571 | 0x20); | ||
| 572 | if (ret) | ||
| 573 | goto error; | ||
| 574 | |||
| 575 | /* attach demod */ | ||
| 576 | if (tmp == 0xc7) { | ||
| 577 | /* TDA18212 config */ | ||
| 578 | adap->fe = dvb_attach(tda10023_attach, | ||
| 579 | &anysee_tda10023_tda18212_config, | ||
| 580 | &adap->dev->i2c_adap, 0x48); | ||
| 581 | } else { | ||
| 582 | /* PLL config */ | ||
| 583 | adap->fe = dvb_attach(tda10023_attach, | ||
| 584 | &anysee_tda10023_config, | ||
| 585 | &adap->dev->i2c_adap, 0x48); | ||
| 586 | } | ||
| 313 | } | 587 | } |
| 314 | } | ||
| 315 | 588 | ||
| 316 | /* connect demod on IO port D for TDA10023 & ZL10353 */ | 589 | break; |
| 317 | ret = anysee_write_reg(adap->dev, 0xb0, 0x25); | 590 | case ANYSEE_HW_508TC: /* 18 */ |
| 318 | if (ret) | 591 | /* E7 TC */ |
| 319 | return ret; | ||
| 320 | 592 | ||
| 321 | /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */ | 593 | /* enable transport stream on IOA[7] */ |
| 322 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | 594 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); |
| 323 | &adap->dev->i2c_adap); | 595 | if (ret) |
| 324 | if (adap->fe != NULL) { | 596 | goto error; |
| 325 | state->tuner = DVB_PLL_THOMSON_DTT7579; | 597 | |
| 326 | return 0; | 598 | if (dvb_usb_anysee_delsys) { |
| 327 | } | 599 | /* disable DVB-C demod on IOD[5] */ |
| 600 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), | ||
| 601 | 0x20); | ||
| 602 | if (ret) | ||
| 603 | goto error; | ||
| 604 | |||
| 605 | /* enable DVB-T demod on IOD[6] */ | ||
| 606 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6), | ||
| 607 | 0x40); | ||
| 608 | if (ret) | ||
| 609 | goto error; | ||
| 610 | |||
| 611 | /* enable IF route on IOE[0] */ | ||
| 612 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), | ||
| 613 | 0x01); | ||
| 614 | if (ret) | ||
| 615 | goto error; | ||
| 616 | |||
| 617 | /* attach demod */ | ||
| 618 | adap->fe = dvb_attach(zl10353_attach, | ||
| 619 | &anysee_zl10353_tda18212_config, | ||
| 620 | &adap->dev->i2c_adap); | ||
| 621 | } else { | ||
| 622 | /* disable DVB-T demod on IOD[6] */ | ||
| 623 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), | ||
| 624 | 0x40); | ||
| 625 | if (ret) | ||
| 626 | goto error; | ||
| 627 | |||
| 628 | /* enable DVB-C demod on IOD[5] */ | ||
| 629 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), | ||
| 630 | 0x20); | ||
| 631 | if (ret) | ||
| 632 | goto error; | ||
| 633 | |||
| 634 | /* enable IF route on IOE[0] */ | ||
| 635 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), | ||
| 636 | 0x01); | ||
| 637 | if (ret) | ||
| 638 | goto error; | ||
| 639 | |||
| 640 | /* attach demod */ | ||
| 641 | adap->fe = dvb_attach(tda10023_attach, | ||
| 642 | &anysee_tda10023_tda18212_config, | ||
| 643 | &adap->dev->i2c_adap, 0x48); | ||
| 644 | } | ||
| 328 | 645 | ||
| 329 | /* IO port E - E30C rev 0.4 board requires this */ | 646 | break; |
| 330 | ret = anysee_write_reg(adap->dev, 0xb1, 0xa7); | 647 | case ANYSEE_HW_508S2: /* 19 */ |
| 331 | if (ret) | 648 | /* E7 S2 */ |
| 332 | return ret; | ||
| 333 | 649 | ||
| 334 | /* Philips TDA10023 DVB-C demod */ | 650 | /* enable transport stream on IOA[7] */ |
| 335 | adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config, | 651 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); |
| 336 | &adap->dev->i2c_adap, 0x48); | 652 | if (ret) |
| 337 | if (adap->fe != NULL) { | 653 | goto error; |
| 338 | state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A; | ||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | 654 | ||
| 342 | /* return IO port D to init value for safe */ | 655 | /* enable DVB-S/S2 demod on IOE[5] */ |
| 343 | ret = anysee_write_reg(adap->dev, 0xb0, io_d); | 656 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); |
| 344 | if (ret) | 657 | if (ret) |
| 345 | return ret; | 658 | goto error; |
| 659 | |||
| 660 | /* attach demod */ | ||
| 661 | adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config, | ||
| 662 | &adap->dev->i2c_adap, 0); | ||
| 346 | 663 | ||
| 347 | err("Unknown Anysee version: %02x %02x %02x. "\ | 664 | break; |
| 348 | "Please report the <linux-dvb@linuxtv.org>.", | 665 | } |
| 349 | hw_info[0], hw_info[1], hw_info[2]); | ||
| 350 | 666 | ||
| 351 | return -ENODEV; | 667 | if (!adap->fe) { |
| 668 | /* we have no frontend :-( */ | ||
| 669 | ret = -ENODEV; | ||
| 670 | err("Unsupported Anysee version. " \ | ||
| 671 | "Please report the <linux-media@vger.kernel.org>."); | ||
| 672 | } | ||
| 673 | error: | ||
| 674 | return ret; | ||
| 352 | } | 675 | } |
| 353 | 676 | ||
| 354 | static int anysee_tuner_attach(struct dvb_usb_adapter *adap) | 677 | static int anysee_tuner_attach(struct dvb_usb_adapter *adap) |
| 355 | { | 678 | { |
| 356 | struct anysee_state *state = adap->dev->priv; | 679 | struct anysee_state *state = adap->dev->priv; |
| 680 | struct dvb_frontend *fe; | ||
| 681 | int ret; | ||
| 357 | deb_info("%s:\n", __func__); | 682 | deb_info("%s:\n", __func__); |
| 358 | 683 | ||
| 359 | switch (state->tuner) { | 684 | switch (state->hw) { |
| 360 | case DVB_PLL_THOMSON_DTT7579: | 685 | case ANYSEE_HW_02: /* 2 */ |
| 361 | /* Thomson dtt7579 (not sure) PLL inside of: | 686 | /* E30 */ |
| 362 | Samsung DNOS404ZH102A NIM | 687 | |
| 363 | Samsung DNOS404ZH103A NIM */ | 688 | /* attach tuner */ |
| 364 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, | 689 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1), |
| 365 | NULL, DVB_PLL_THOMSON_DTT7579); | 690 | NULL, DVB_PLL_THOMSON_DTT7579); |
| 691 | |||
| 692 | break; | ||
| 693 | case ANYSEE_HW_507CD: /* 6 */ | ||
| 694 | /* E30 Plus */ | ||
| 695 | |||
| 696 | /* attach tuner */ | ||
| 697 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1), | ||
| 698 | &adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579); | ||
| 699 | |||
| 700 | break; | ||
| 701 | case ANYSEE_HW_507DC: /* 10 */ | ||
| 702 | /* E30 C Plus */ | ||
| 703 | |||
| 704 | /* attach tuner */ | ||
| 705 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1), | ||
| 706 | &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
| 707 | |||
| 708 | break; | ||
| 709 | case ANYSEE_HW_507SI: /* 11 */ | ||
| 710 | /* E30 S2 Plus */ | ||
| 711 | |||
| 712 | /* attach LNB controller */ | ||
| 713 | fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 714 | &anysee_isl6423_config); | ||
| 715 | |||
| 716 | break; | ||
| 717 | case ANYSEE_HW_507FA: /* 15 */ | ||
| 718 | /* E30 Combo Plus */ | ||
| 719 | /* E30 C Plus */ | ||
| 720 | |||
| 721 | if (dvb_usb_anysee_delsys) { | ||
| 722 | /* enable DVB-T tuner on IOE[0] */ | ||
| 723 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), | ||
| 724 | 0x01); | ||
| 725 | if (ret) | ||
| 726 | goto error; | ||
| 727 | } else { | ||
| 728 | /* enable DVB-C tuner on IOE[0] */ | ||
| 729 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), | ||
| 730 | 0x01); | ||
| 731 | if (ret) | ||
| 732 | goto error; | ||
| 733 | } | ||
| 734 | |||
| 735 | /* Try first attach TDA18212 silicon tuner on IOE[4], if that | ||
| 736 | * fails attach old simple PLL. */ | ||
| 737 | |||
| 738 | /* enable tuner on IOE[4] */ | ||
| 739 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | ||
| 740 | if (ret) | ||
| 741 | goto error; | ||
| 742 | |||
| 743 | /* attach tuner */ | ||
| 744 | fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 745 | &anysee_tda18212_config); | ||
| 746 | if (fe) | ||
| 747 | break; | ||
| 748 | |||
| 749 | /* disable tuner on IOE[4] */ | ||
| 750 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); | ||
| 751 | if (ret) | ||
| 752 | goto error; | ||
| 753 | |||
| 754 | /* attach tuner */ | ||
| 755 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1), | ||
| 756 | &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
| 757 | |||
| 366 | break; | 758 | break; |
| 367 | case DVB_PLL_SAMSUNG_DTOS403IH102A: | 759 | case ANYSEE_HW_508TC: /* 18 */ |
| 368 | /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */ | 760 | /* E7 TC */ |
| 369 | dvb_attach(dvb_pll_attach, adap->fe, 0xc0, | 761 | |
| 370 | &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | 762 | /* enable tuner on IOE[4] */ |
| 763 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | ||
| 764 | if (ret) | ||
| 765 | goto error; | ||
| 766 | |||
| 767 | /* attach tuner */ | ||
| 768 | fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 769 | &anysee_tda18212_config); | ||
| 770 | |||
| 371 | break; | 771 | break; |
| 772 | case ANYSEE_HW_508S2: /* 19 */ | ||
| 773 | /* E7 S2 */ | ||
| 774 | |||
| 775 | /* attach tuner */ | ||
| 776 | fe = dvb_attach(stv6110_attach, adap->fe, | ||
| 777 | &anysee_stv6110_config, &adap->dev->i2c_adap); | ||
| 778 | |||
| 779 | if (fe) { | ||
| 780 | /* attach LNB controller */ | ||
| 781 | fe = dvb_attach(isl6423_attach, adap->fe, | ||
| 782 | &adap->dev->i2c_adap, &anysee_isl6423_config); | ||
| 783 | } | ||
| 784 | |||
| 785 | break; | ||
| 786 | default: | ||
| 787 | fe = NULL; | ||
| 372 | } | 788 | } |
| 373 | 789 | ||
| 374 | return 0; | 790 | if (fe) |
| 791 | ret = 0; | ||
| 792 | else | ||
| 793 | ret = -ENODEV; | ||
| 794 | |||
| 795 | error: | ||
| 796 | return ret; | ||
| 375 | } | 797 | } |
| 376 | 798 | ||
| 377 | static int anysee_rc_query(struct dvb_usb_device *d) | 799 | static int anysee_rc_query(struct dvb_usb_device *d) |
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h index 7ca01ff6e13c..a7673aa1e007 100644 --- a/drivers/media/dvb/dvb-usb/anysee.h +++ b/drivers/media/dvb/dvb-usb/anysee.h | |||
| @@ -57,10 +57,29 @@ enum cmd { | |||
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | struct anysee_state { | 59 | struct anysee_state { |
| 60 | u8 tuner; | 60 | u8 hw; /* PCB ID */ |
| 61 | u8 seq; | 61 | u8 seq; |
| 62 | }; | 62 | }; |
| 63 | 63 | ||
| 64 | #define ANYSEE_HW_02 2 /* E30 */ | ||
| 65 | #define ANYSEE_HW_507CD 6 /* E30 Plus */ | ||
| 66 | #define ANYSEE_HW_507DC 10 /* E30 C Plus */ | ||
| 67 | #define ANYSEE_HW_507SI 11 /* E30 S2 Plus */ | ||
| 68 | #define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */ | ||
| 69 | #define ANYSEE_HW_508TC 18 /* E7 TC */ | ||
| 70 | #define ANYSEE_HW_508S2 19 /* E7 S2 */ | ||
| 71 | |||
| 72 | #define REG_IOA 0x80 /* Port A (bit addressable) */ | ||
| 73 | #define REG_IOB 0x90 /* Port B (bit addressable) */ | ||
| 74 | #define REG_IOC 0xa0 /* Port C (bit addressable) */ | ||
| 75 | #define REG_IOD 0xb0 /* Port D (bit addressable) */ | ||
| 76 | #define REG_IOE 0xb1 /* Port E (NOT bit addressable) */ | ||
| 77 | #define REG_OEA 0xb2 /* Port A Output Enable */ | ||
| 78 | #define REG_OEB 0xb3 /* Port B Output Enable */ | ||
| 79 | #define REG_OEC 0xb4 /* Port C Output Enable */ | ||
| 80 | #define REG_OED 0xb5 /* Port D Output Enable */ | ||
| 81 | #define REG_OEE 0xb6 /* Port E Output Enable */ | ||
| 82 | |||
| 64 | #endif | 83 | #endif |
| 65 | 84 | ||
| 66 | /*************************************************************************** | 85 | /*************************************************************************** |
| @@ -136,7 +155,7 @@ General reply packet(s) are always used if not own reply defined. | |||
| 136 | ---------------------------------------------------------------------------- | 155 | ---------------------------------------------------------------------------- |
| 137 | | 04 | 0x00 | 156 | | 04 | 0x00 |
| 138 | ---------------------------------------------------------------------------- | 157 | ---------------------------------------------------------------------------- |
| 139 | | 05 | 0x01 | 158 | | 05 | data length |
| 140 | ---------------------------------------------------------------------------- | 159 | ---------------------------------------------------------------------------- |
| 141 | | 06-59 | don't care | 160 | | 06-59 | don't care |
| 142 | ---------------------------------------------------------------------------- | 161 | ---------------------------------------------------------------------------- |
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c index eb34cc3894e0..2351077ff2b3 100644 --- a/drivers/media/dvb/dvb-usb/au6610.c +++ b/drivers/media/dvb/dvb-usb/au6610.c | |||
| @@ -33,8 +33,16 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | |||
| 33 | { | 33 | { |
| 34 | int ret; | 34 | int ret; |
| 35 | u16 index; | 35 | u16 index; |
| 36 | u8 usb_buf[6]; /* enough for all known requests, | 36 | u8 *usb_buf; |
| 37 | read returns 5 and write 6 bytes */ | 37 | |
| 38 | /* | ||
| 39 | * allocate enough for all known requests, | ||
| 40 | * read returns 5 and write 6 bytes | ||
| 41 | */ | ||
| 42 | usb_buf = kmalloc(6, GFP_KERNEL); | ||
| 43 | if (!usb_buf) | ||
| 44 | return -ENOMEM; | ||
| 45 | |||
| 38 | switch (wlen) { | 46 | switch (wlen) { |
| 39 | case 1: | 47 | case 1: |
| 40 | index = wbuf[0] << 8; | 48 | index = wbuf[0] << 8; |
| @@ -45,14 +53,15 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | |||
| 45 | break; | 53 | break; |
| 46 | default: | 54 | default: |
| 47 | warn("wlen = %x, aborting.", wlen); | 55 | warn("wlen = %x, aborting.", wlen); |
| 48 | return -EINVAL; | 56 | ret = -EINVAL; |
| 57 | goto error; | ||
| 49 | } | 58 | } |
| 50 | 59 | ||
| 51 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, | 60 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, |
| 52 | USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, | 61 | USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, |
| 53 | usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT); | 62 | usb_buf, 6, AU6610_USB_TIMEOUT); |
| 54 | if (ret < 0) | 63 | if (ret < 0) |
| 55 | return ret; | 64 | goto error; |
| 56 | 65 | ||
| 57 | switch (operation) { | 66 | switch (operation) { |
| 58 | case AU6610_REQ_I2C_READ: | 67 | case AU6610_REQ_I2C_READ: |
| @@ -60,7 +69,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | |||
| 60 | /* requested value is always 5th byte in buffer */ | 69 | /* requested value is always 5th byte in buffer */ |
| 61 | rbuf[0] = usb_buf[4]; | 70 | rbuf[0] = usb_buf[4]; |
| 62 | } | 71 | } |
| 63 | 72 | error: | |
| 73 | kfree(usb_buf); | ||
| 64 | return ret; | 74 | return ret; |
| 65 | } | 75 | } |
| 66 | 76 | ||
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c index 3df2045b7d2d..6d1a3041540d 100644 --- a/drivers/media/dvb/dvb-usb/ce6230.c +++ b/drivers/media/dvb/dvb-usb/ce6230.c | |||
| @@ -39,7 +39,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) | |||
| 39 | u8 requesttype; | 39 | u8 requesttype; |
| 40 | u16 value; | 40 | u16 value; |
| 41 | u16 index; | 41 | u16 index; |
| 42 | u8 buf[req->data_len]; | 42 | u8 *buf; |
| 43 | 43 | ||
| 44 | request = req->cmd; | 44 | request = req->cmd; |
| 45 | value = req->value; | 45 | value = req->value; |
| @@ -62,6 +62,12 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) | |||
| 62 | goto error; | 62 | goto error; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | buf = kmalloc(req->data_len, GFP_KERNEL); | ||
| 66 | if (!buf) { | ||
| 67 | ret = -ENOMEM; | ||
| 68 | goto error; | ||
| 69 | } | ||
| 70 | |||
| 65 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { | 71 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { |
| 66 | /* write */ | 72 | /* write */ |
| 67 | memcpy(buf, req->data, req->data_len); | 73 | memcpy(buf, req->data, req->data_len); |
| @@ -74,7 +80,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) | |||
| 74 | msleep(1); /* avoid I2C errors */ | 80 | msleep(1); /* avoid I2C errors */ |
| 75 | 81 | ||
| 76 | ret = usb_control_msg(udev, pipe, request, requesttype, value, index, | 82 | ret = usb_control_msg(udev, pipe, request, requesttype, value, index, |
| 77 | buf, sizeof(buf), CE6230_USB_TIMEOUT); | 83 | buf, req->data_len, CE6230_USB_TIMEOUT); |
| 78 | 84 | ||
| 79 | ce6230_debug_dump(request, requesttype, value, index, buf, | 85 | ce6230_debug_dump(request, requesttype, value, index, buf, |
| 80 | req->data_len, deb_xfer); | 86 | req->data_len, deb_xfer); |
| @@ -88,6 +94,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) | |||
| 88 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | 94 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) |
| 89 | memcpy(req->data, buf, req->data_len); | 95 | memcpy(req->data, buf, req->data_len); |
| 90 | 96 | ||
| 97 | kfree(buf); | ||
| 91 | error: | 98 | error: |
| 92 | return ret; | 99 | return ret; |
| 93 | } | 100 | } |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index b2a87f2c2c3e..9bd6d51b3b93 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
| @@ -46,8 +46,9 @@ struct dib0700_state { | |||
| 46 | u8 is_dib7000pc; | 46 | u8 is_dib7000pc; |
| 47 | u8 fw_use_new_i2c_api; | 47 | u8 fw_use_new_i2c_api; |
| 48 | u8 disable_streaming_master_mode; | 48 | u8 disable_streaming_master_mode; |
| 49 | u32 fw_version; | 49 | u32 fw_version; |
| 50 | u32 nb_packet_buffer_size; | 50 | u32 nb_packet_buffer_size; |
| 51 | u8 buf[255]; | ||
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | 54 | extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index b79af68c54ae..5eb91b4f8fd0 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
| @@ -27,19 +27,25 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 27 | int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | 27 | int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, |
| 28 | u32 *romversion, u32 *ramversion, u32 *fwtype) | 28 | u32 *romversion, u32 *ramversion, u32 *fwtype) |
| 29 | { | 29 | { |
| 30 | u8 b[16]; | 30 | struct dib0700_state *st = d->priv; |
| 31 | int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | 31 | int ret; |
| 32 | |||
| 33 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | ||
| 32 | REQUEST_GET_VERSION, | 34 | REQUEST_GET_VERSION, |
| 33 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | 35 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 34 | b, sizeof(b), USB_CTRL_GET_TIMEOUT); | 36 | st->buf, 16, USB_CTRL_GET_TIMEOUT); |
| 35 | if (hwversion != NULL) | 37 | if (hwversion != NULL) |
| 36 | *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; | 38 | *hwversion = (st->buf[0] << 24) | (st->buf[1] << 16) | |
| 39 | (st->buf[2] << 8) | st->buf[3]; | ||
| 37 | if (romversion != NULL) | 40 | if (romversion != NULL) |
| 38 | *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; | 41 | *romversion = (st->buf[4] << 24) | (st->buf[5] << 16) | |
| 42 | (st->buf[6] << 8) | st->buf[7]; | ||
| 39 | if (ramversion != NULL) | 43 | if (ramversion != NULL) |
| 40 | *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; | 44 | *ramversion = (st->buf[8] << 24) | (st->buf[9] << 16) | |
| 45 | (st->buf[10] << 8) | st->buf[11]; | ||
| 41 | if (fwtype != NULL) | 46 | if (fwtype != NULL) |
| 42 | *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; | 47 | *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | |
| 48 | (st->buf[14] << 8) | st->buf[15]; | ||
| 43 | return ret; | 49 | return ret; |
| 44 | } | 50 | } |
| 45 | 51 | ||
| @@ -101,24 +107,31 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen | |||
| 101 | 107 | ||
| 102 | int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) | 108 | int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) |
| 103 | { | 109 | { |
| 104 | u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) }; | 110 | struct dib0700_state *st = d->priv; |
| 105 | return dib0700_ctrl_wr(d, buf, sizeof(buf)); | 111 | s16 ret; |
| 112 | |||
| 113 | st->buf[0] = REQUEST_SET_GPIO; | ||
| 114 | st->buf[1] = gpio; | ||
| 115 | st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6); | ||
| 116 | |||
| 117 | ret = dib0700_ctrl_wr(d, st->buf, 3); | ||
| 118 | |||
| 119 | return ret; | ||
| 106 | } | 120 | } |
| 107 | 121 | ||
| 108 | static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) | 122 | static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) |
| 109 | { | 123 | { |
| 110 | struct dib0700_state *st = d->priv; | 124 | struct dib0700_state *st = d->priv; |
| 111 | u8 b[3]; | ||
| 112 | int ret; | 125 | int ret; |
| 113 | 126 | ||
| 114 | if (st->fw_version >= 0x10201) { | 127 | if (st->fw_version >= 0x10201) { |
| 115 | b[0] = REQUEST_SET_USB_XFER_LEN; | 128 | st->buf[0] = REQUEST_SET_USB_XFER_LEN; |
| 116 | b[1] = (nb_ts_packets >> 8) & 0xff; | 129 | st->buf[1] = (nb_ts_packets >> 8) & 0xff; |
| 117 | b[2] = nb_ts_packets & 0xff; | 130 | st->buf[2] = nb_ts_packets & 0xff; |
| 118 | 131 | ||
| 119 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); | 132 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); |
| 120 | 133 | ||
| 121 | ret = dib0700_ctrl_wr(d, b, sizeof(b)); | 134 | ret = dib0700_ctrl_wr(d, st->buf, 3); |
| 122 | } else { | 135 | } else { |
| 123 | deb_info("this firmware does not allow to change the USB xfer len\n"); | 136 | deb_info("this firmware does not allow to change the USB xfer len\n"); |
| 124 | ret = -EIO; | 137 | ret = -EIO; |
| @@ -137,11 +150,11 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 137 | properly support i2c read calls not preceded by a write */ | 150 | properly support i2c read calls not preceded by a write */ |
| 138 | 151 | ||
| 139 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 152 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
| 153 | struct dib0700_state *st = d->priv; | ||
| 140 | uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ | 154 | uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ |
| 141 | uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ | 155 | uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ |
| 142 | uint8_t en_start = 0; | 156 | uint8_t en_start = 0; |
| 143 | uint8_t en_stop = 0; | 157 | uint8_t en_stop = 0; |
| 144 | uint8_t buf[255]; /* TBV: malloc ? */ | ||
| 145 | int result, i; | 158 | int result, i; |
| 146 | 159 | ||
| 147 | /* Ensure nobody else hits the i2c bus while we're sending our | 160 | /* Ensure nobody else hits the i2c bus while we're sending our |
| @@ -195,24 +208,24 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 195 | 208 | ||
| 196 | } else { | 209 | } else { |
| 197 | /* Write request */ | 210 | /* Write request */ |
| 198 | buf[0] = REQUEST_NEW_I2C_WRITE; | 211 | st->buf[0] = REQUEST_NEW_I2C_WRITE; |
| 199 | buf[1] = msg[i].addr << 1; | 212 | st->buf[1] = msg[i].addr << 1; |
| 200 | buf[2] = (en_start << 7) | (en_stop << 6) | | 213 | st->buf[2] = (en_start << 7) | (en_stop << 6) | |
| 201 | (msg[i].len & 0x3F); | 214 | (msg[i].len & 0x3F); |
| 202 | /* I2C ctrl + FE bus; */ | 215 | /* I2C ctrl + FE bus; */ |
| 203 | buf[3] = ((gen_mode << 6) & 0xC0) | | 216 | st->buf[3] = ((gen_mode << 6) & 0xC0) | |
| 204 | ((bus_mode << 4) & 0x30); | 217 | ((bus_mode << 4) & 0x30); |
| 205 | /* The Actual i2c payload */ | 218 | /* The Actual i2c payload */ |
| 206 | memcpy(&buf[4], msg[i].buf, msg[i].len); | 219 | memcpy(&st->buf[4], msg[i].buf, msg[i].len); |
| 207 | 220 | ||
| 208 | deb_data(">>> "); | 221 | deb_data(">>> "); |
| 209 | debug_dump(buf, msg[i].len + 4, deb_data); | 222 | debug_dump(st->buf, msg[i].len + 4, deb_data); |
| 210 | 223 | ||
| 211 | result = usb_control_msg(d->udev, | 224 | result = usb_control_msg(d->udev, |
| 212 | usb_sndctrlpipe(d->udev, 0), | 225 | usb_sndctrlpipe(d->udev, 0), |
| 213 | REQUEST_NEW_I2C_WRITE, | 226 | REQUEST_NEW_I2C_WRITE, |
| 214 | USB_TYPE_VENDOR | USB_DIR_OUT, | 227 | USB_TYPE_VENDOR | USB_DIR_OUT, |
| 215 | 0, 0, buf, msg[i].len + 4, | 228 | 0, 0, st->buf, msg[i].len + 4, |
| 216 | USB_CTRL_GET_TIMEOUT); | 229 | USB_CTRL_GET_TIMEOUT); |
| 217 | if (result < 0) { | 230 | if (result < 0) { |
| 218 | deb_info("i2c write error (status = %d)\n", result); | 231 | deb_info("i2c write error (status = %d)\n", result); |
| @@ -231,27 +244,29 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | |||
| 231 | struct i2c_msg *msg, int num) | 244 | struct i2c_msg *msg, int num) |
| 232 | { | 245 | { |
| 233 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 246 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
| 247 | struct dib0700_state *st = d->priv; | ||
| 234 | int i,len; | 248 | int i,len; |
| 235 | u8 buf[255]; | ||
| 236 | 249 | ||
| 237 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 250 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
| 238 | return -EAGAIN; | 251 | return -EAGAIN; |
| 239 | 252 | ||
| 240 | for (i = 0; i < num; i++) { | 253 | for (i = 0; i < num; i++) { |
| 241 | /* fill in the address */ | 254 | /* fill in the address */ |
| 242 | buf[1] = msg[i].addr << 1; | 255 | st->buf[1] = msg[i].addr << 1; |
| 243 | /* fill the buffer */ | 256 | /* fill the buffer */ |
| 244 | memcpy(&buf[2], msg[i].buf, msg[i].len); | 257 | memcpy(&st->buf[2], msg[i].buf, msg[i].len); |
| 245 | 258 | ||
| 246 | /* write/read request */ | 259 | /* write/read request */ |
| 247 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | 260 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { |
| 248 | buf[0] = REQUEST_I2C_READ; | 261 | st->buf[0] = REQUEST_I2C_READ; |
| 249 | buf[1] |= 1; | 262 | st->buf[1] |= 1; |
| 250 | 263 | ||
| 251 | /* special thing in the current firmware: when length is zero the read-failed */ | 264 | /* special thing in the current firmware: when length is zero the read-failed */ |
| 252 | if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) { | 265 | len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, |
| 266 | msg[i+1].buf, msg[i+1].len); | ||
| 267 | if (len <= 0) { | ||
| 253 | deb_info("I2C read failed on address 0x%02x\n", | 268 | deb_info("I2C read failed on address 0x%02x\n", |
| 254 | msg[i].addr); | 269 | msg[i].addr); |
| 255 | break; | 270 | break; |
| 256 | } | 271 | } |
| 257 | 272 | ||
| @@ -259,13 +274,13 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | |||
| 259 | 274 | ||
| 260 | i++; | 275 | i++; |
| 261 | } else { | 276 | } else { |
| 262 | buf[0] = REQUEST_I2C_WRITE; | 277 | st->buf[0] = REQUEST_I2C_WRITE; |
| 263 | if (dib0700_ctrl_wr(d, buf, msg[i].len + 2) < 0) | 278 | if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0) |
| 264 | break; | 279 | break; |
| 265 | } | 280 | } |
| 266 | } | 281 | } |
| 267 | |||
| 268 | mutex_unlock(&d->i2c_mutex); | 282 | mutex_unlock(&d->i2c_mutex); |
| 283 | |||
| 269 | return i; | 284 | return i; |
| 270 | } | 285 | } |
| 271 | 286 | ||
| @@ -297,15 +312,23 @@ struct i2c_algorithm dib0700_i2c_algo = { | |||
| 297 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, | 312 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, |
| 298 | struct dvb_usb_device_description **desc, int *cold) | 313 | struct dvb_usb_device_description **desc, int *cold) |
| 299 | { | 314 | { |
| 300 | u8 b[16]; | 315 | s16 ret; |
| 301 | s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), | 316 | u8 *b; |
| 317 | |||
| 318 | b = kmalloc(16, GFP_KERNEL); | ||
| 319 | if (!b) | ||
| 320 | return -ENOMEM; | ||
| 321 | |||
| 322 | |||
| 323 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 302 | REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); | 324 | REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); |
| 303 | 325 | ||
| 304 | deb_info("FW GET_VERSION length: %d\n",ret); | 326 | deb_info("FW GET_VERSION length: %d\n",ret); |
| 305 | 327 | ||
| 306 | *cold = ret <= 0; | 328 | *cold = ret <= 0; |
| 307 | |||
| 308 | deb_info("cold: %d\n", *cold); | 329 | deb_info("cold: %d\n", *cold); |
| 330 | |||
| 331 | kfree(b); | ||
| 309 | return 0; | 332 | return 0; |
| 310 | } | 333 | } |
| 311 | 334 | ||
| @@ -313,43 +336,50 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, | |||
| 313 | u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, | 336 | u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, |
| 314 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) | 337 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) |
| 315 | { | 338 | { |
| 316 | u8 b[10]; | 339 | struct dib0700_state *st = d->priv; |
| 317 | b[0] = REQUEST_SET_CLOCK; | 340 | s16 ret; |
| 318 | b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4); | 341 | |
| 319 | b[2] = (pll_prediv >> 8) & 0xff; // MSB | 342 | st->buf[0] = REQUEST_SET_CLOCK; |
| 320 | b[3] = pll_prediv & 0xff; // LSB | 343 | st->buf[1] = (en_pll << 7) | (pll_src << 6) | |
| 321 | b[4] = (pll_loopdiv >> 8) & 0xff; // MSB | 344 | (pll_range << 5) | (clock_gpio3 << 4); |
| 322 | b[5] = pll_loopdiv & 0xff; // LSB | 345 | st->buf[2] = (pll_prediv >> 8) & 0xff; /* MSB */ |
| 323 | b[6] = (free_div >> 8) & 0xff; // MSB | 346 | st->buf[3] = pll_prediv & 0xff; /* LSB */ |
| 324 | b[7] = free_div & 0xff; // LSB | 347 | st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */ |
| 325 | b[8] = (dsuScaler >> 8) & 0xff; // MSB | 348 | st->buf[5] = pll_loopdiv & 0xff; /* LSB */ |
| 326 | b[9] = dsuScaler & 0xff; // LSB | 349 | st->buf[6] = (free_div >> 8) & 0xff; /* MSB */ |
| 327 | 350 | st->buf[7] = free_div & 0xff; /* LSB */ | |
| 328 | return dib0700_ctrl_wr(d, b, 10); | 351 | st->buf[8] = (dsuScaler >> 8) & 0xff; /* MSB */ |
| 352 | st->buf[9] = dsuScaler & 0xff; /* LSB */ | ||
| 353 | |||
| 354 | ret = dib0700_ctrl_wr(d, st->buf, 10); | ||
| 355 | |||
| 356 | return ret; | ||
| 329 | } | 357 | } |
| 330 | 358 | ||
| 331 | int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) | 359 | int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) |
| 332 | { | 360 | { |
| 361 | struct dib0700_state *st = d->priv; | ||
| 333 | u16 divider; | 362 | u16 divider; |
| 334 | u8 b[8]; | ||
| 335 | 363 | ||
| 336 | if (scl_kHz == 0) | 364 | if (scl_kHz == 0) |
| 337 | return -EINVAL; | 365 | return -EINVAL; |
| 338 | 366 | ||
| 339 | b[0] = REQUEST_SET_I2C_PARAM; | 367 | st->buf[0] = REQUEST_SET_I2C_PARAM; |
| 340 | divider = (u16) (30000 / scl_kHz); | 368 | divider = (u16) (30000 / scl_kHz); |
| 341 | b[2] = (u8) (divider >> 8); | 369 | st->buf[1] = 0; |
| 342 | b[3] = (u8) (divider & 0xff); | 370 | st->buf[2] = (u8) (divider >> 8); |
| 371 | st->buf[3] = (u8) (divider & 0xff); | ||
| 343 | divider = (u16) (72000 / scl_kHz); | 372 | divider = (u16) (72000 / scl_kHz); |
| 344 | b[4] = (u8) (divider >> 8); | 373 | st->buf[4] = (u8) (divider >> 8); |
| 345 | b[5] = (u8) (divider & 0xff); | 374 | st->buf[5] = (u8) (divider & 0xff); |
| 346 | divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */ | 375 | divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */ |
| 347 | b[6] = (u8) (divider >> 8); | 376 | st->buf[6] = (u8) (divider >> 8); |
| 348 | b[7] = (u8) (divider & 0xff); | 377 | st->buf[7] = (u8) (divider & 0xff); |
| 349 | 378 | ||
| 350 | deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", | 379 | deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", |
| 351 | (b[2] << 8) | (b[3]), (b[4] << 8) | b[5], (b[6] << 8) | b[7], scl_kHz); | 380 | (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | |
| 352 | return dib0700_ctrl_wr(d, b, 8); | 381 | st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); |
| 382 | return dib0700_ctrl_wr(d, st->buf, 8); | ||
| 353 | } | 383 | } |
| 354 | 384 | ||
| 355 | 385 | ||
| @@ -364,32 +394,45 @@ int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) | |||
| 364 | 394 | ||
| 365 | static int dib0700_jumpram(struct usb_device *udev, u32 address) | 395 | static int dib0700_jumpram(struct usb_device *udev, u32 address) |
| 366 | { | 396 | { |
| 367 | int ret, actlen; | 397 | int ret = 0, actlen; |
| 368 | u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0, | 398 | u8 *buf; |
| 369 | (address >> 24) & 0xff, | 399 | |
| 370 | (address >> 16) & 0xff, | 400 | buf = kmalloc(8, GFP_KERNEL); |
| 371 | (address >> 8) & 0xff, | 401 | if (!buf) |
| 372 | address & 0xff }; | 402 | return -ENOMEM; |
| 403 | buf[0] = REQUEST_JUMPRAM; | ||
| 404 | buf[1] = 0; | ||
| 405 | buf[2] = 0; | ||
| 406 | buf[3] = 0; | ||
| 407 | buf[4] = (address >> 24) & 0xff; | ||
| 408 | buf[5] = (address >> 16) & 0xff; | ||
| 409 | buf[6] = (address >> 8) & 0xff; | ||
| 410 | buf[7] = address & 0xff; | ||
| 373 | 411 | ||
| 374 | if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) { | 412 | if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) { |
| 375 | deb_fw("jumpram to 0x%x failed\n",address); | 413 | deb_fw("jumpram to 0x%x failed\n",address); |
| 376 | return ret; | 414 | goto out; |
| 377 | } | 415 | } |
| 378 | if (actlen != 8) { | 416 | if (actlen != 8) { |
| 379 | deb_fw("jumpram to 0x%x failed\n",address); | 417 | deb_fw("jumpram to 0x%x failed\n",address); |
| 380 | return -EIO; | 418 | ret = -EIO; |
| 419 | goto out; | ||
| 381 | } | 420 | } |
| 382 | return 0; | 421 | out: |
| 422 | kfree(buf); | ||
| 423 | return ret; | ||
| 383 | } | 424 | } |
| 384 | 425 | ||
| 385 | int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) | 426 | int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) |
| 386 | { | 427 | { |
| 387 | struct hexline hx; | 428 | struct hexline hx; |
| 388 | int pos = 0, ret, act_len, i, adap_num; | 429 | int pos = 0, ret, act_len, i, adap_num; |
| 389 | u8 b[16]; | 430 | u8 *buf; |
| 390 | u32 fw_version; | 431 | u32 fw_version; |
| 391 | 432 | ||
| 392 | u8 buf[260]; | 433 | buf = kmalloc(260, GFP_KERNEL); |
| 434 | if (!buf) | ||
| 435 | return -ENOMEM; | ||
| 393 | 436 | ||
| 394 | while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) { | 437 | while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) { |
| 395 | deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n", | 438 | deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n", |
| @@ -411,7 +454,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw | |||
| 411 | 454 | ||
| 412 | if (ret < 0) { | 455 | if (ret < 0) { |
| 413 | err("firmware download failed at %d with %d",pos,ret); | 456 | err("firmware download failed at %d with %d",pos,ret); |
| 414 | return ret; | 457 | goto out; |
| 415 | } | 458 | } |
| 416 | } | 459 | } |
| 417 | 460 | ||
| @@ -432,8 +475,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw | |||
| 432 | usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 475 | usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 433 | REQUEST_GET_VERSION, | 476 | REQUEST_GET_VERSION, |
| 434 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | 477 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 435 | b, sizeof(b), USB_CTRL_GET_TIMEOUT); | 478 | buf, 16, USB_CTRL_GET_TIMEOUT); |
| 436 | fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; | 479 | fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]; |
| 437 | 480 | ||
| 438 | /* set the buffer size - DVB-USB is allocating URB buffers | 481 | /* set the buffer size - DVB-USB is allocating URB buffers |
| 439 | * only after the firwmare download was successful */ | 482 | * only after the firwmare download was successful */ |
| @@ -451,14 +494,14 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw | |||
| 451 | } | 494 | } |
| 452 | } | 495 | } |
| 453 | } | 496 | } |
| 454 | 497 | out: | |
| 498 | kfree(buf); | ||
| 455 | return ret; | 499 | return ret; |
| 456 | } | 500 | } |
| 457 | 501 | ||
| 458 | int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 502 | int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
| 459 | { | 503 | { |
| 460 | struct dib0700_state *st = adap->dev->priv; | 504 | struct dib0700_state *st = adap->dev->priv; |
| 461 | u8 b[4]; | ||
| 462 | int ret; | 505 | int ret; |
| 463 | 506 | ||
| 464 | if ((onoff != 0) && (st->fw_version >= 0x10201)) { | 507 | if ((onoff != 0) && (st->fw_version >= 0x10201)) { |
| @@ -472,15 +515,17 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
| 472 | } | 515 | } |
| 473 | } | 516 | } |
| 474 | 517 | ||
| 475 | b[0] = REQUEST_ENABLE_VIDEO; | 518 | st->buf[0] = REQUEST_ENABLE_VIDEO; |
| 476 | b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ | 519 | /* this bit gives a kind of command, |
| 520 | * rather than enabling something or not */ | ||
| 521 | st->buf[1] = (onoff << 4) | 0x00; | ||
| 477 | 522 | ||
| 478 | if (st->disable_streaming_master_mode == 1) | 523 | if (st->disable_streaming_master_mode == 1) |
| 479 | b[2] = 0x00; | 524 | st->buf[2] = 0x00; |
| 480 | else | 525 | else |
| 481 | b[2] = 0x01 << 4; /* Master mode */ | 526 | st->buf[2] = 0x01 << 4; /* Master mode */ |
| 482 | 527 | ||
| 483 | b[3] = 0x00; | 528 | st->buf[3] = 0x00; |
| 484 | 529 | ||
| 485 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); | 530 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); |
| 486 | 531 | ||
| @@ -499,20 +544,23 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
| 499 | st->channel_state |= 1 << (3-adap->stream.props.endpoint); | 544 | st->channel_state |= 1 << (3-adap->stream.props.endpoint); |
| 500 | } | 545 | } |
| 501 | 546 | ||
| 502 | b[2] |= st->channel_state; | 547 | st->buf[2] |= st->channel_state; |
| 503 | 548 | ||
| 504 | deb_info("data for streaming: %x %x\n", b[1], b[2]); | 549 | deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); |
| 505 | 550 | ||
| 506 | return dib0700_ctrl_wr(adap->dev, b, 4); | 551 | return dib0700_ctrl_wr(adap->dev, st->buf, 4); |
| 507 | } | 552 | } |
| 508 | 553 | ||
| 509 | int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) | 554 | int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) |
| 510 | { | 555 | { |
| 511 | struct dvb_usb_device *d = rc->priv; | 556 | struct dvb_usb_device *d = rc->priv; |
| 512 | struct dib0700_state *st = d->priv; | 557 | struct dib0700_state *st = d->priv; |
| 513 | u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 }; | ||
| 514 | int new_proto, ret; | 558 | int new_proto, ret; |
| 515 | 559 | ||
| 560 | st->buf[0] = REQUEST_SET_RC; | ||
| 561 | st->buf[1] = 0; | ||
| 562 | st->buf[2] = 0; | ||
| 563 | |||
| 516 | /* Set the IR mode */ | 564 | /* Set the IR mode */ |
| 517 | if (rc_type == RC_TYPE_RC5) | 565 | if (rc_type == RC_TYPE_RC5) |
| 518 | new_proto = 1; | 566 | new_proto = 1; |
| @@ -526,9 +574,9 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) | |||
| 526 | } else | 574 | } else |
| 527 | return -EINVAL; | 575 | return -EINVAL; |
| 528 | 576 | ||
| 529 | rc_setup[1] = new_proto; | 577 | st->buf[1] = new_proto; |
| 530 | 578 | ||
| 531 | ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup)); | 579 | ret = dib0700_ctrl_wr(d, st->buf, 3); |
| 532 | if (ret < 0) { | 580 | if (ret < 0) { |
| 533 | err("ir protocol setup failed"); | 581 | err("ir protocol setup failed"); |
| 534 | return ret; | 582 | return ret; |
| @@ -561,7 +609,6 @@ struct dib0700_rc_response { | |||
| 561 | static void dib0700_rc_urb_completion(struct urb *purb) | 609 | static void dib0700_rc_urb_completion(struct urb *purb) |
| 562 | { | 610 | { |
| 563 | struct dvb_usb_device *d = purb->context; | 611 | struct dvb_usb_device *d = purb->context; |
| 564 | struct dib0700_state *st; | ||
| 565 | struct dib0700_rc_response *poll_reply; | 612 | struct dib0700_rc_response *poll_reply; |
| 566 | u32 uninitialized_var(keycode); | 613 | u32 uninitialized_var(keycode); |
| 567 | u8 toggle; | 614 | u8 toggle; |
| @@ -576,7 +623,6 @@ static void dib0700_rc_urb_completion(struct urb *purb) | |||
| 576 | return; | 623 | return; |
| 577 | } | 624 | } |
| 578 | 625 | ||
| 579 | st = d->priv; | ||
| 580 | poll_reply = purb->transfer_buffer; | 626 | poll_reply = purb->transfer_buffer; |
| 581 | 627 | ||
| 582 | if (purb->status < 0) { | 628 | if (purb->status < 0) { |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 65214af5cd74..c519ad5eb731 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
| @@ -2439,7 +2439,6 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) | |||
| 2439 | 2439 | ||
| 2440 | dib0700_set_i2c_speed(adap->dev, 340); | 2440 | dib0700_set_i2c_speed(adap->dev, 340); |
| 2441 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]); | 2441 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]); |
| 2442 | |||
| 2443 | if (adap->fe == NULL) | 2442 | if (adap->fe == NULL) |
| 2444 | return -ENODEV; | 2443 | return -ENODEV; |
| 2445 | 2444 | ||
| @@ -2802,6 +2801,7 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
| 2802 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM7090) }, | 2801 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM7090) }, |
| 2803 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090PVR) }, | 2802 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090PVR) }, |
| 2804 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) }, | 2803 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) }, |
| 2804 | /* 75 */{ USB_DEVICE(USB_VID_MEDION, USB_PID_CREATIX_CTX1921) }, | ||
| 2805 | { 0 } /* Terminating entry */ | 2805 | { 0 } /* Terminating entry */ |
| 2806 | }; | 2806 | }; |
| 2807 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 2807 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
| @@ -3411,7 +3411,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
| 3411 | }, | 3411 | }, |
| 3412 | }, | 3412 | }, |
| 3413 | 3413 | ||
| 3414 | .num_device_descs = 3, | 3414 | .num_device_descs = 4, |
| 3415 | .devices = { | 3415 | .devices = { |
| 3416 | { "DiBcom STK7770P reference design", | 3416 | { "DiBcom STK7770P reference design", |
| 3417 | { &dib0700_usb_id_table[59], NULL }, | 3417 | { &dib0700_usb_id_table[59], NULL }, |
| @@ -3427,6 +3427,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
| 3427 | { &dib0700_usb_id_table[74], NULL }, | 3427 | { &dib0700_usb_id_table[74], NULL }, |
| 3428 | { NULL }, | 3428 | { NULL }, |
| 3429 | }, | 3429 | }, |
| 3430 | { "Medion CTX1921 DVB-T USB", | ||
| 3431 | { &dib0700_usb_id_table[75], NULL }, | ||
| 3432 | { NULL }, | ||
| 3433 | }, | ||
| 3430 | }, | 3434 | }, |
| 3431 | 3435 | ||
| 3432 | .rc.core = { | 3436 | .rc.core = { |
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index 956f7ae2e510..4c2a689c820e 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c | |||
| @@ -408,7 +408,7 @@ struct rc_map_table rc_map_dibusb_table[] = { | |||
| 408 | 408 | ||
| 409 | { 0x8008, KEY_DVD }, | 409 | { 0x8008, KEY_DVD }, |
| 410 | { 0x8009, KEY_AUDIO }, | 410 | { 0x8009, KEY_AUDIO }, |
| 411 | { 0x800a, KEY_MEDIA }, /* Pictures */ | 411 | { 0x800a, KEY_IMAGES }, /* Pictures */ |
| 412 | { 0x800b, KEY_VIDEO }, | 412 | { 0x800b, KEY_VIDEO }, |
| 413 | 413 | ||
| 414 | { 0x800c, KEY_BACK }, | 414 | { 0x800c, KEY_BACK }, |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index df1ec3e69f4a..b3cb626ed56e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) | 12 | static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) |
| 13 | { | 13 | { |
| 14 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; | 14 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; |
| 15 | int newfeedcount,ret; | 15 | int newfeedcount, ret; |
| 16 | 16 | ||
| 17 | if (adap == NULL) | 17 | if (adap == NULL) |
| 18 | return -ENODEV; | 18 | return -ENODEV; |
| @@ -24,9 +24,13 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) | |||
| 24 | deb_ts("stop feeding\n"); | 24 | deb_ts("stop feeding\n"); |
| 25 | usb_urb_kill(&adap->stream); | 25 | usb_urb_kill(&adap->stream); |
| 26 | 26 | ||
| 27 | if (adap->props.streaming_ctrl != NULL) | 27 | if (adap->props.streaming_ctrl != NULL) { |
| 28 | if ((ret = adap->props.streaming_ctrl(adap,0))) | 28 | ret = adap->props.streaming_ctrl(adap, 0); |
| 29 | if (ret < 0) { | ||
| 29 | err("error while stopping stream."); | 30 | err("error while stopping stream."); |
| 31 | return ret; | ||
| 32 | } | ||
| 33 | } | ||
| 30 | } | 34 | } |
| 31 | 35 | ||
| 32 | adap->feedcount = newfeedcount; | 36 | adap->feedcount = newfeedcount; |
| @@ -49,17 +53,24 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) | |||
| 49 | 53 | ||
| 50 | deb_ts("controlling pid parser\n"); | 54 | deb_ts("controlling pid parser\n"); |
| 51 | if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER && | 55 | if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER && |
| 52 | adap->props.caps & DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && | 56 | adap->props.caps & |
| 53 | adap->props.pid_filter_ctrl != NULL) | 57 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && |
| 54 | if (adap->props.pid_filter_ctrl(adap,adap->pid_filtering) < 0) | 58 | adap->props.pid_filter_ctrl != NULL) { |
| 59 | ret = adap->props.pid_filter_ctrl(adap, | ||
| 60 | adap->pid_filtering); | ||
| 61 | if (ret < 0) { | ||
| 55 | err("could not handle pid_parser"); | 62 | err("could not handle pid_parser"); |
| 56 | 63 | return ret; | |
| 64 | } | ||
| 65 | } | ||
| 57 | deb_ts("start feeding\n"); | 66 | deb_ts("start feeding\n"); |
| 58 | if (adap->props.streaming_ctrl != NULL) | 67 | if (adap->props.streaming_ctrl != NULL) { |
| 59 | if (adap->props.streaming_ctrl(adap,1)) { | 68 | ret = adap->props.streaming_ctrl(adap, 1); |
| 69 | if (ret < 0) { | ||
| 60 | err("error while enabling fifo."); | 70 | err("error while enabling fifo."); |
| 61 | return -ENODEV; | 71 | return ret; |
| 62 | } | 72 | } |
| 73 | } | ||
| 63 | 74 | ||
| 64 | } | 75 | } |
| 65 | return 0; | 76 | return 0; |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 3a8b7446b7b0..21b15495d2d7 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
| @@ -91,6 +91,7 @@ | |||
| 91 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 | 91 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 |
| 92 | #define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397 | 92 | #define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397 |
| 93 | #define USB_PID_CONEXANT_D680_DMB 0x86d6 | 93 | #define USB_PID_CONEXANT_D680_DMB 0x86d6 |
| 94 | #define USB_PID_CREATIX_CTX1921 0x1921 | ||
| 94 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | 95 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
| 95 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | 96 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
| 96 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | 97 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index d312323504a4..058b2318abed 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
| @@ -121,12 +121,16 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, | |||
| 121 | u16 index, u8 * data, u16 len, int flags) | 121 | u16 index, u8 * data, u16 len, int flags) |
| 122 | { | 122 | { |
| 123 | int ret; | 123 | int ret; |
| 124 | u8 u8buf[len]; | 124 | u8 *u8buf; |
| 125 | |||
| 126 | unsigned int pipe = (flags == DW210X_READ_MSG) ? | 125 | unsigned int pipe = (flags == DW210X_READ_MSG) ? |
| 127 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); | 126 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); |
| 128 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; | 127 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; |
| 129 | 128 | ||
| 129 | u8buf = kmalloc(len, GFP_KERNEL); | ||
| 130 | if (!u8buf) | ||
| 131 | return -ENOMEM; | ||
| 132 | |||
| 133 | |||
| 130 | if (flags == DW210X_WRITE_MSG) | 134 | if (flags == DW210X_WRITE_MSG) |
| 131 | memcpy(u8buf, data, len); | 135 | memcpy(u8buf, data, len); |
| 132 | ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, | 136 | ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, |
| @@ -134,6 +138,8 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, | |||
| 134 | 138 | ||
| 135 | if (flags == DW210X_READ_MSG) | 139 | if (flags == DW210X_READ_MSG) |
| 136 | memcpy(data, u8buf, len); | 140 | memcpy(data, u8buf, len); |
| 141 | |||
| 142 | kfree(u8buf); | ||
| 137 | return ret; | 143 | return ret; |
| 138 | } | 144 | } |
| 139 | 145 | ||
diff --git a/drivers/media/dvb/dvb-usb/ec168.c b/drivers/media/dvb/dvb-usb/ec168.c index 52f5d4f0f230..1ba3e5dbee10 100644 --- a/drivers/media/dvb/dvb-usb/ec168.c +++ b/drivers/media/dvb/dvb-usb/ec168.c | |||
| @@ -36,7 +36,9 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) | |||
| 36 | int ret; | 36 | int ret; |
| 37 | unsigned int pipe; | 37 | unsigned int pipe; |
| 38 | u8 request, requesttype; | 38 | u8 request, requesttype; |
| 39 | u8 buf[req->size]; | 39 | u8 *buf; |
| 40 | |||
| 41 | |||
| 40 | 42 | ||
| 41 | switch (req->cmd) { | 43 | switch (req->cmd) { |
| 42 | case DOWNLOAD_FIRMWARE: | 44 | case DOWNLOAD_FIRMWARE: |
| @@ -72,6 +74,12 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) | |||
| 72 | goto error; | 74 | goto error; |
| 73 | } | 75 | } |
| 74 | 76 | ||
| 77 | buf = kmalloc(req->size, GFP_KERNEL); | ||
| 78 | if (!buf) { | ||
| 79 | ret = -ENOMEM; | ||
| 80 | goto error; | ||
| 81 | } | ||
| 82 | |||
| 75 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { | 83 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { |
| 76 | /* write */ | 84 | /* write */ |
| 77 | memcpy(buf, req->data, req->size); | 85 | memcpy(buf, req->data, req->size); |
| @@ -84,13 +92,13 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) | |||
| 84 | msleep(1); /* avoid I2C errors */ | 92 | msleep(1); /* avoid I2C errors */ |
| 85 | 93 | ||
| 86 | ret = usb_control_msg(udev, pipe, request, requesttype, req->value, | 94 | ret = usb_control_msg(udev, pipe, request, requesttype, req->value, |
| 87 | req->index, buf, sizeof(buf), EC168_USB_TIMEOUT); | 95 | req->index, buf, req->size, EC168_USB_TIMEOUT); |
| 88 | 96 | ||
| 89 | ec168_debug_dump(request, requesttype, req->value, req->index, buf, | 97 | ec168_debug_dump(request, requesttype, req->value, req->index, buf, |
| 90 | req->size, deb_xfer); | 98 | req->size, deb_xfer); |
| 91 | 99 | ||
| 92 | if (ret < 0) | 100 | if (ret < 0) |
| 93 | goto error; | 101 | goto err_dealloc; |
| 94 | else | 102 | else |
| 95 | ret = 0; | 103 | ret = 0; |
| 96 | 104 | ||
| @@ -98,7 +106,11 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) | |||
| 98 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | 106 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) |
| 99 | memcpy(req->data, buf, req->size); | 107 | memcpy(req->data, buf, req->size); |
| 100 | 108 | ||
| 109 | kfree(buf); | ||
| 101 | return ret; | 110 | return ret; |
| 111 | |||
| 112 | err_dealloc: | ||
| 113 | kfree(buf); | ||
| 102 | error: | 114 | error: |
| 103 | deb_info("%s: failed:%d\n", __func__, ret); | 115 | deb_info("%s: failed:%d\n", __func__, ret); |
| 104 | return ret; | 116 | return ret; |
diff --git a/drivers/media/dvb/dvb-usb/friio.c b/drivers/media/dvb/dvb-usb/friio.c index 14a65b4aec07..76159aed9bb0 100644 --- a/drivers/media/dvb/dvb-usb/friio.c +++ b/drivers/media/dvb/dvb-usb/friio.c | |||
| @@ -142,17 +142,20 @@ static u32 gl861_i2c_func(struct i2c_adapter *adapter) | |||
| 142 | return I2C_FUNC_I2C; | 142 | return I2C_FUNC_I2C; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | |||
| 146 | static int friio_ext_ctl(struct dvb_usb_adapter *adap, | 145 | static int friio_ext_ctl(struct dvb_usb_adapter *adap, |
| 147 | u32 sat_color, int lnb_on) | 146 | u32 sat_color, int lnb_on) |
| 148 | { | 147 | { |
| 149 | int i; | 148 | int i; |
| 150 | int ret; | 149 | int ret; |
| 151 | struct i2c_msg msg; | 150 | struct i2c_msg msg; |
| 152 | u8 buf[2]; | 151 | u8 *buf; |
| 153 | u32 mask; | 152 | u32 mask; |
| 154 | u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0; | 153 | u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0; |
| 155 | 154 | ||
| 155 | buf = kmalloc(2, GFP_KERNEL); | ||
| 156 | if (!buf) | ||
| 157 | return -ENOMEM; | ||
| 158 | |||
| 156 | msg.addr = 0x00; | 159 | msg.addr = 0x00; |
| 157 | msg.flags = 0; | 160 | msg.flags = 0; |
| 158 | msg.len = 2; | 161 | msg.len = 2; |
| @@ -189,6 +192,7 @@ static int friio_ext_ctl(struct dvb_usb_adapter *adap, | |||
| 189 | buf[1] |= FRIIO_CTL_CLK; | 192 | buf[1] |= FRIIO_CTL_CLK; |
| 190 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | 193 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); |
| 191 | 194 | ||
| 195 | kfree(buf); | ||
| 192 | return (ret == 70); | 196 | return (ret == 70); |
| 193 | } | 197 | } |
| 194 | 198 | ||
| @@ -219,11 +223,20 @@ static int friio_initialize(struct dvb_usb_device *d) | |||
| 219 | int ret; | 223 | int ret; |
| 220 | int i; | 224 | int i; |
| 221 | int retry = 0; | 225 | int retry = 0; |
| 222 | u8 rbuf[2]; | 226 | u8 *rbuf, *wbuf; |
| 223 | u8 wbuf[3]; | ||
| 224 | 227 | ||
| 225 | deb_info("%s called.\n", __func__); | 228 | deb_info("%s called.\n", __func__); |
| 226 | 229 | ||
| 230 | wbuf = kmalloc(3, GFP_KERNEL); | ||
| 231 | if (!wbuf) | ||
| 232 | return -ENOMEM; | ||
| 233 | |||
| 234 | rbuf = kmalloc(2, GFP_KERNEL); | ||
| 235 | if (!rbuf) { | ||
| 236 | kfree(wbuf); | ||
| 237 | return -ENOMEM; | ||
| 238 | } | ||
| 239 | |||
| 227 | /* use gl861_i2c_msg instead of gl861_i2c_xfer(), */ | 240 | /* use gl861_i2c_msg instead of gl861_i2c_xfer(), */ |
| 228 | /* because the i2c device is not set up yet. */ | 241 | /* because the i2c device is not set up yet. */ |
| 229 | wbuf[0] = 0x11; | 242 | wbuf[0] = 0x11; |
| @@ -358,6 +371,8 @@ restart: | |||
| 358 | return 0; | 371 | return 0; |
| 359 | 372 | ||
| 360 | error: | 373 | error: |
| 374 | kfree(wbuf); | ||
| 375 | kfree(rbuf); | ||
| 361 | deb_info("%s:ret == %d\n", __func__, ret); | 376 | deb_info("%s:ret == %d\n", __func__, ret); |
| 362 | return -EIO; | 377 | return -EIO; |
| 363 | } | 378 | } |
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index f2db01212ca1..f36f471deae2 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c | |||
| @@ -62,8 +62,6 @@ | |||
| 62 | * LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system | 62 | * LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system |
| 63 | * with other tuners. After a cold reset streaming will not start. | 63 | * with other tuners. After a cold reset streaming will not start. |
| 64 | * | 64 | * |
| 65 | * PID functions have been removed from this driver version due to | ||
| 66 | * problems with different firmware and application versions. | ||
| 67 | */ | 65 | */ |
| 68 | #define DVB_USB_LOG_PREFIX "LME2510(C)" | 66 | #define DVB_USB_LOG_PREFIX "LME2510(C)" |
| 69 | #include <linux/usb.h> | 67 | #include <linux/usb.h> |
| @@ -104,6 +102,10 @@ static int dvb_usb_lme2510_firmware; | |||
| 104 | module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644); | 102 | module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644); |
| 105 | MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG"); | 103 | MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG"); |
| 106 | 104 | ||
| 105 | static int pid_filter; | ||
| 106 | module_param_named(pid, pid_filter, int, 0644); | ||
| 107 | MODULE_PARM_DESC(pid, "set default 0=on 1=off"); | ||
| 108 | |||
| 107 | 109 | ||
| 108 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 110 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 109 | 111 | ||
| @@ -125,6 +127,7 @@ struct lme2510_state { | |||
| 125 | u8 i2c_tuner_gate_r; | 127 | u8 i2c_tuner_gate_r; |
| 126 | u8 i2c_tuner_addr; | 128 | u8 i2c_tuner_addr; |
| 127 | u8 stream_on; | 129 | u8 stream_on; |
| 130 | u8 pid_size; | ||
| 128 | void *buffer; | 131 | void *buffer; |
| 129 | struct urb *lme_urb; | 132 | struct urb *lme_urb; |
| 130 | void *usb_buffer; | 133 | void *usb_buffer; |
| @@ -167,14 +170,14 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, | |||
| 167 | } | 170 | } |
| 168 | buff = st->usb_buffer; | 171 | buff = st->usb_buffer; |
| 169 | 172 | ||
| 170 | /* the read/write capped at 512 */ | ||
| 171 | memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen); | ||
| 172 | |||
| 173 | ret = mutex_lock_interruptible(&d->usb_mutex); | 173 | ret = mutex_lock_interruptible(&d->usb_mutex); |
| 174 | 174 | ||
| 175 | if (ret < 0) | 175 | if (ret < 0) |
| 176 | return -EAGAIN; | 176 | return -EAGAIN; |
| 177 | 177 | ||
| 178 | /* the read/write capped at 512 */ | ||
| 179 | memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen); | ||
| 180 | |||
| 178 | ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); | 181 | ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); |
| 179 | 182 | ||
| 180 | ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); | 183 | ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); |
| @@ -216,6 +219,37 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress) | |||
| 216 | return 0; | 219 | return 0; |
| 217 | } | 220 | } |
| 218 | 221 | ||
| 222 | static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) | ||
| 223 | { | ||
| 224 | struct lme2510_state *st = d->priv; | ||
| 225 | static u8 pid_buff[] = LME_ZERO_PID; | ||
| 226 | static u8 rbuf[1]; | ||
| 227 | u8 pid_no = index * 2; | ||
| 228 | u8 pid_len = pid_no + 2; | ||
| 229 | int ret = 0; | ||
| 230 | deb_info(1, "PID Setting Pid %04x", pid_out); | ||
| 231 | |||
| 232 | if (st->pid_size == 0) | ||
| 233 | ret |= lme2510_stream_restart(d); | ||
| 234 | |||
| 235 | pid_buff[2] = pid_no; | ||
| 236 | pid_buff[3] = (u8)pid_out & 0xff; | ||
| 237 | pid_buff[4] = pid_no + 1; | ||
| 238 | pid_buff[5] = (u8)(pid_out >> 8); | ||
| 239 | |||
| 240 | if (pid_len > st->pid_size) | ||
| 241 | st->pid_size = pid_len; | ||
| 242 | pid_buff[7] = 0x80 + st->pid_size; | ||
| 243 | |||
| 244 | ret |= lme2510_usb_talk(d, pid_buff , | ||
| 245 | sizeof(pid_buff) , rbuf, sizeof(rbuf)); | ||
| 246 | |||
| 247 | if (st->stream_on) | ||
| 248 | ret |= lme2510_stream_restart(d); | ||
| 249 | |||
| 250 | return ret; | ||
| 251 | } | ||
| 252 | |||
| 219 | static void lme2510_int_response(struct urb *lme_urb) | 253 | static void lme2510_int_response(struct urb *lme_urb) |
| 220 | { | 254 | { |
| 221 | struct dvb_usb_adapter *adap = lme_urb->context; | 255 | struct dvb_usb_adapter *adap = lme_urb->context; |
| @@ -326,16 +360,68 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) | |||
| 326 | return 0; | 360 | return 0; |
| 327 | } | 361 | } |
| 328 | 362 | ||
| 363 | static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 364 | { | ||
| 365 | struct lme2510_state *st = adap->dev->priv; | ||
| 366 | static u8 clear_pid_reg[] = LME_CLEAR_PID; | ||
| 367 | static u8 rbuf[1]; | ||
| 368 | int ret; | ||
| 369 | |||
| 370 | deb_info(1, "PID Clearing Filter"); | ||
| 371 | |||
| 372 | ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | ||
| 373 | if (ret < 0) | ||
| 374 | return -EAGAIN; | ||
| 375 | |||
| 376 | if (!onoff) | ||
| 377 | ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, | ||
| 378 | sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); | ||
| 379 | |||
| 380 | st->pid_size = 0; | ||
| 381 | |||
| 382 | mutex_unlock(&adap->dev->i2c_mutex); | ||
| 383 | |||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
| 388 | int onoff) | ||
| 389 | { | ||
| 390 | int ret = 0; | ||
| 391 | |||
| 392 | deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__, | ||
| 393 | pid, index, onoff); | ||
| 394 | |||
| 395 | if (onoff) | ||
| 396 | if (!pid_filter) { | ||
| 397 | ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | ||
| 398 | if (ret < 0) | ||
| 399 | return -EAGAIN; | ||
| 400 | ret |= lme2510_enable_pid(adap->dev, index, pid); | ||
| 401 | mutex_unlock(&adap->dev->i2c_mutex); | ||
| 402 | } | ||
| 403 | |||
| 404 | |||
| 405 | return ret; | ||
| 406 | } | ||
| 407 | |||
| 408 | |||
| 329 | static int lme2510_return_status(struct usb_device *dev) | 409 | static int lme2510_return_status(struct usb_device *dev) |
| 330 | { | 410 | { |
| 331 | int ret = 0; | 411 | int ret = 0; |
| 332 | u8 data[10] = {0}; | 412 | u8 *data; |
| 413 | |||
| 414 | data = kzalloc(10, GFP_KERNEL); | ||
| 415 | if (!data) | ||
| 416 | return -ENOMEM; | ||
| 333 | 417 | ||
| 334 | ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 418 | ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
| 335 | 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); | 419 | 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); |
| 336 | info("Firmware Status: %x (%x)", ret , data[2]); | 420 | info("Firmware Status: %x (%x)", ret , data[2]); |
| 337 | 421 | ||
| 338 | return (ret < 0) ? -ENODEV : data[2]; | 422 | ret = (ret < 0) ? -ENODEV : data[2]; |
| 423 | kfree(data); | ||
| 424 | return ret; | ||
| 339 | } | 425 | } |
| 340 | 426 | ||
| 341 | static int lme2510_msg(struct dvb_usb_device *d, | 427 | static int lme2510_msg(struct dvb_usb_device *d, |
| @@ -591,9 +677,10 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
| 591 | else { | 677 | else { |
| 592 | deb_info(1, "STM Steam Off"); | 678 | deb_info(1, "STM Steam Off"); |
| 593 | /* mutex is here only to avoid collision with I2C */ | 679 | /* mutex is here only to avoid collision with I2C */ |
| 594 | ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | 680 | if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) |
| 681 | return -EAGAIN; | ||
| 595 | 682 | ||
| 596 | ret |= lme2510_usb_talk(adap->dev, clear_reg_3, | 683 | ret = lme2510_usb_talk(adap->dev, clear_reg_3, |
| 597 | sizeof(clear_reg_3), rbuf, rlen); | 684 | sizeof(clear_reg_3), rbuf, rlen); |
| 598 | st->stream_on = 0; | 685 | st->stream_on = 0; |
| 599 | st->i2c_talk_onoff = 1; | 686 | st->i2c_talk_onoff = 1; |
| @@ -655,7 +742,7 @@ static int lme2510_download_firmware(struct usb_device *dev, | |||
| 655 | const struct firmware *fw) | 742 | const struct firmware *fw) |
| 656 | { | 743 | { |
| 657 | int ret = 0; | 744 | int ret = 0; |
| 658 | u8 data[512] = {0}; | 745 | u8 *data; |
| 659 | u16 j, wlen, len_in, start, end; | 746 | u16 j, wlen, len_in, start, end; |
| 660 | u8 packet_size, dlen, i; | 747 | u8 packet_size, dlen, i; |
| 661 | u8 *fw_data; | 748 | u8 *fw_data; |
| @@ -663,6 +750,11 @@ static int lme2510_download_firmware(struct usb_device *dev, | |||
| 663 | packet_size = 0x31; | 750 | packet_size = 0x31; |
| 664 | len_in = 1; | 751 | len_in = 1; |
| 665 | 752 | ||
| 753 | data = kzalloc(512, GFP_KERNEL); | ||
| 754 | if (!data) { | ||
| 755 | info("FRM Could not start Firmware Download (Buffer allocation failed)"); | ||
| 756 | return -ENOMEM; | ||
| 757 | } | ||
| 666 | 758 | ||
| 667 | info("FRM Starting Firmware Download"); | 759 | info("FRM Starting Firmware Download"); |
| 668 | 760 | ||
| @@ -678,15 +770,15 @@ static int lme2510_download_firmware(struct usb_device *dev, | |||
| 678 | data[0] = i | 0x80; | 770 | data[0] = i | 0x80; |
| 679 | dlen = (u8)(end - j)-1; | 771 | dlen = (u8)(end - j)-1; |
| 680 | } | 772 | } |
| 681 | data[1] = dlen; | 773 | data[1] = dlen; |
| 682 | memcpy(&data[2], fw_data, dlen+1); | 774 | memcpy(&data[2], fw_data, dlen+1); |
| 683 | wlen = (u8) dlen + 4; | 775 | wlen = (u8) dlen + 4; |
| 684 | data[wlen-1] = check_sum(fw_data, dlen+1); | 776 | data[wlen-1] = check_sum(fw_data, dlen+1); |
| 685 | deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], | 777 | deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], |
| 686 | data[dlen+2], data[dlen+3]); | 778 | data[dlen+2], data[dlen+3]); |
| 687 | ret |= lme2510_bulk_write(dev, data, wlen, 1); | 779 | ret |= lme2510_bulk_write(dev, data, wlen, 1); |
| 688 | ret |= lme2510_bulk_read(dev, data, len_in , 1); | 780 | ret |= lme2510_bulk_read(dev, data, len_in , 1); |
| 689 | ret |= (data[0] == 0x88) ? 0 : -1; | 781 | ret |= (data[0] == 0x88) ? 0 : -1; |
| 690 | } | 782 | } |
| 691 | } | 783 | } |
| 692 | 784 | ||
| @@ -706,7 +798,7 @@ static int lme2510_download_firmware(struct usb_device *dev, | |||
| 706 | else | 798 | else |
| 707 | info("FRM Firmware Download Completed - Resetting Device"); | 799 | info("FRM Firmware Download Completed - Resetting Device"); |
| 708 | 800 | ||
| 709 | 801 | kfree(data); | |
| 710 | return (ret < 0) ? -ENODEV : 0; | 802 | return (ret < 0) ? -ENODEV : 0; |
| 711 | } | 803 | } |
| 712 | 804 | ||
| @@ -747,7 +839,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) | |||
| 747 | fw_lme = fw_s0194; | 839 | fw_lme = fw_s0194; |
| 748 | ret = request_firmware(&fw, fw_lme, &udev->dev); | 840 | ret = request_firmware(&fw, fw_lme, &udev->dev); |
| 749 | if (ret == 0) { | 841 | if (ret == 0) { |
| 750 | cold = 0;/*lme2510-s0194 cannot cold reset*/ | 842 | cold = 0; |
| 751 | break; | 843 | break; |
| 752 | } | 844 | } |
| 753 | dvb_usb_lme2510_firmware = TUNER_LG; | 845 | dvb_usb_lme2510_firmware = TUNER_LG; |
| @@ -769,8 +861,10 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) | |||
| 769 | case TUNER_S7395: | 861 | case TUNER_S7395: |
| 770 | fw_lme = fw_c_s7395; | 862 | fw_lme = fw_c_s7395; |
| 771 | ret = request_firmware(&fw, fw_lme, &udev->dev); | 863 | ret = request_firmware(&fw, fw_lme, &udev->dev); |
| 772 | if (ret == 0) | 864 | if (ret == 0) { |
| 865 | cold = 0; | ||
| 773 | break; | 866 | break; |
| 867 | } | ||
| 774 | dvb_usb_lme2510_firmware = TUNER_LG; | 868 | dvb_usb_lme2510_firmware = TUNER_LG; |
| 775 | case TUNER_LG: | 869 | case TUNER_LG: |
| 776 | fw_lme = fw_c_lg; | 870 | fw_lme = fw_c_lg; |
| @@ -796,14 +890,14 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) | |||
| 796 | ret = lme2510_download_firmware(udev, fw); | 890 | ret = lme2510_download_firmware(udev, fw); |
| 797 | } | 891 | } |
| 798 | 892 | ||
| 893 | release_firmware(fw); | ||
| 894 | |||
| 799 | if (cold) { | 895 | if (cold) { |
| 800 | info("FRM Changing to %s firmware", fw_lme); | 896 | info("FRM Changing to %s firmware", fw_lme); |
| 801 | lme_coldreset(udev); | 897 | lme_coldreset(udev); |
| 802 | return -ENODEV; | 898 | return -ENODEV; |
| 803 | } | 899 | } |
| 804 | 900 | ||
| 805 | release_firmware(fw); | ||
| 806 | |||
| 807 | return ret; | 901 | return ret; |
| 808 | } | 902 | } |
| 809 | 903 | ||
| @@ -1017,12 +1111,13 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff) | |||
| 1017 | static u8 rbuf[1]; | 1111 | static u8 rbuf[1]; |
| 1018 | int ret, len = 3, rlen = 1; | 1112 | int ret, len = 3, rlen = 1; |
| 1019 | 1113 | ||
| 1020 | ret = mutex_lock_interruptible(&d->i2c_mutex); | 1114 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
| 1115 | return -EAGAIN; | ||
| 1021 | 1116 | ||
| 1022 | if (onoff) | 1117 | if (onoff) |
| 1023 | ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); | 1118 | ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); |
| 1024 | else | 1119 | else |
| 1025 | ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); | 1120 | ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); |
| 1026 | 1121 | ||
| 1027 | st->i2c_talk_onoff = 1; | 1122 | st->i2c_talk_onoff = 1; |
| 1028 | 1123 | ||
| @@ -1086,7 +1181,13 @@ static struct dvb_usb_device_properties lme2510_properties = { | |||
| 1086 | .num_adapters = 1, | 1181 | .num_adapters = 1, |
| 1087 | .adapter = { | 1182 | .adapter = { |
| 1088 | { | 1183 | { |
| 1184 | .caps = DVB_USB_ADAP_HAS_PID_FILTER| | ||
| 1185 | DVB_USB_ADAP_NEED_PID_FILTERING| | ||
| 1186 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1089 | .streaming_ctrl = lme2510_streaming_ctrl, | 1187 | .streaming_ctrl = lme2510_streaming_ctrl, |
| 1188 | .pid_filter_count = 15, | ||
| 1189 | .pid_filter = lme2510_pid_filter, | ||
| 1190 | .pid_filter_ctrl = lme2510_pid_filter_ctrl, | ||
| 1090 | .frontend_attach = dm04_lme2510_frontend_attach, | 1191 | .frontend_attach = dm04_lme2510_frontend_attach, |
| 1091 | .tuner_attach = dm04_lme2510_tuner, | 1192 | .tuner_attach = dm04_lme2510_tuner, |
| 1092 | /* parameter for the MPEG2-data transfer */ | 1193 | /* parameter for the MPEG2-data transfer */ |
| @@ -1122,7 +1223,13 @@ static struct dvb_usb_device_properties lme2510c_properties = { | |||
| 1122 | .num_adapters = 1, | 1223 | .num_adapters = 1, |
| 1123 | .adapter = { | 1224 | .adapter = { |
| 1124 | { | 1225 | { |
| 1226 | .caps = DVB_USB_ADAP_HAS_PID_FILTER| | ||
| 1227 | DVB_USB_ADAP_NEED_PID_FILTERING| | ||
| 1228 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1125 | .streaming_ctrl = lme2510_streaming_ctrl, | 1229 | .streaming_ctrl = lme2510_streaming_ctrl, |
| 1230 | .pid_filter_count = 15, | ||
| 1231 | .pid_filter = lme2510_pid_filter, | ||
| 1232 | .pid_filter_ctrl = lme2510_pid_filter_ctrl, | ||
| 1126 | .frontend_attach = dm04_lme2510_frontend_attach, | 1233 | .frontend_attach = dm04_lme2510_frontend_attach, |
| 1127 | .tuner_attach = dm04_lme2510_tuner, | 1234 | .tuner_attach = dm04_lme2510_tuner, |
| 1128 | /* parameter for the MPEG2-data transfer */ | 1235 | /* parameter for the MPEG2-data transfer */ |
| @@ -1151,7 +1258,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { | |||
| 1151 | } | 1258 | } |
| 1152 | }; | 1259 | }; |
| 1153 | 1260 | ||
| 1154 | void *lme2510_exit_int(struct dvb_usb_device *d) | 1261 | static void *lme2510_exit_int(struct dvb_usb_device *d) |
| 1155 | { | 1262 | { |
| 1156 | struct lme2510_state *st = d->priv; | 1263 | struct lme2510_state *st = d->priv; |
| 1157 | struct dvb_usb_adapter *adap = &d->adapter[0]; | 1264 | struct dvb_usb_adapter *adap = &d->adapter[0]; |
| @@ -1178,7 +1285,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d) | |||
| 1178 | return buffer; | 1285 | return buffer; |
| 1179 | } | 1286 | } |
| 1180 | 1287 | ||
| 1181 | void lme2510_exit(struct usb_interface *intf) | 1288 | static void lme2510_exit(struct usb_interface *intf) |
| 1182 | { | 1289 | { |
| 1183 | struct dvb_usb_device *d = usb_get_intfdata(intf); | 1290 | struct dvb_usb_device *d = usb_get_intfdata(intf); |
| 1184 | void *usb_buffer; | 1291 | void *usb_buffer; |
| @@ -1220,5 +1327,5 @@ module_exit(lme2510_module_exit); | |||
| 1220 | 1327 | ||
| 1221 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); | 1328 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); |
| 1222 | MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); | 1329 | MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); |
| 1223 | MODULE_VERSION("1.80"); | 1330 | MODULE_VERSION("1.86"); |
| 1224 | MODULE_LICENSE("GPL"); | 1331 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.h b/drivers/media/dvb/dvb-usb/lmedm04.h index e6af16c1e3e5..ab21e2ef53fa 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.h +++ b/drivers/media/dvb/dvb-usb/lmedm04.h | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | */ | 40 | */ |
| 41 | #define LME_ST_ON_W {0x06, 0x00} | 41 | #define LME_ST_ON_W {0x06, 0x00} |
| 42 | #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} | 42 | #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} |
| 43 | #define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} | ||
| 43 | 44 | ||
| 44 | /* LNB Voltage | 45 | /* LNB Voltage |
| 45 | * 07 XX XX | 46 | * 07 XX XX |
| @@ -108,14 +109,14 @@ static u8 s7395_inittab[] = { | |||
| 108 | 0x3d, 0x30, | 109 | 0x3d, 0x30, |
| 109 | 0x40, 0x63, | 110 | 0x40, 0x63, |
| 110 | 0x41, 0x04, | 111 | 0x41, 0x04, |
| 111 | 0x42, 0x60, | 112 | 0x42, 0x20, |
| 112 | 0x43, 0x00, | 113 | 0x43, 0x00, |
| 113 | 0x44, 0x00, | 114 | 0x44, 0x00, |
| 114 | 0x45, 0x00, | 115 | 0x45, 0x00, |
| 115 | 0x46, 0x00, | 116 | 0x46, 0x00, |
| 116 | 0x47, 0x00, | 117 | 0x47, 0x00, |
| 117 | 0x4a, 0x00, | 118 | 0x4a, 0x00, |
| 118 | 0x50, 0x12, | 119 | 0x50, 0x10, |
| 119 | 0x51, 0x36, | 120 | 0x51, 0x36, |
| 120 | 0x52, 0x21, | 121 | 0x52, 0x21, |
| 121 | 0x53, 0x94, | 122 | 0x53, 0x94, |
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index da9dc91ce910..9456792f219b 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
| @@ -134,13 +134,17 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 134 | { | 134 | { |
| 135 | struct m920x_state *m = d->priv; | 135 | struct m920x_state *m = d->priv; |
| 136 | int i, ret = 0; | 136 | int i, ret = 0; |
| 137 | u8 rc_state[2]; | 137 | u8 *rc_state; |
| 138 | |||
| 139 | rc_state = kmalloc(2, GFP_KERNEL); | ||
| 140 | if (!rc_state) | ||
| 141 | return -ENOMEM; | ||
| 138 | 142 | ||
| 139 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) | 143 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) |
| 140 | goto unlock; | 144 | goto out; |
| 141 | 145 | ||
| 142 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) | 146 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) |
| 143 | goto unlock; | 147 | goto out; |
| 144 | 148 | ||
| 145 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) | 149 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) |
| 146 | if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) { | 150 | if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) { |
| @@ -149,7 +153,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 149 | switch(rc_state[0]) { | 153 | switch(rc_state[0]) { |
| 150 | case 0x80: | 154 | case 0x80: |
| 151 | *state = REMOTE_NO_KEY_PRESSED; | 155 | *state = REMOTE_NO_KEY_PRESSED; |
| 152 | goto unlock; | 156 | goto out; |
| 153 | 157 | ||
| 154 | case 0x88: /* framing error or "invalid code" */ | 158 | case 0x88: /* framing error or "invalid code" */ |
| 155 | case 0x99: | 159 | case 0x99: |
| @@ -157,7 +161,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 157 | case 0xd8: | 161 | case 0xd8: |
| 158 | *state = REMOTE_NO_KEY_PRESSED; | 162 | *state = REMOTE_NO_KEY_PRESSED; |
| 159 | m->rep_count = 0; | 163 | m->rep_count = 0; |
| 160 | goto unlock; | 164 | goto out; |
| 161 | 165 | ||
| 162 | case 0x93: | 166 | case 0x93: |
| 163 | case 0x92: | 167 | case 0x92: |
| @@ -165,7 +169,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 165 | case 0x82: | 169 | case 0x82: |
| 166 | m->rep_count = 0; | 170 | m->rep_count = 0; |
| 167 | *state = REMOTE_KEY_PRESSED; | 171 | *state = REMOTE_KEY_PRESSED; |
| 168 | goto unlock; | 172 | goto out; |
| 169 | 173 | ||
| 170 | case 0x91: | 174 | case 0x91: |
| 171 | case 0x81: /* pinnacle PCTV310e */ | 175 | case 0x81: /* pinnacle PCTV310e */ |
| @@ -174,12 +178,12 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 174 | *state = REMOTE_KEY_REPEAT; | 178 | *state = REMOTE_KEY_REPEAT; |
| 175 | else | 179 | else |
| 176 | *state = REMOTE_NO_KEY_PRESSED; | 180 | *state = REMOTE_NO_KEY_PRESSED; |
| 177 | goto unlock; | 181 | goto out; |
| 178 | 182 | ||
| 179 | default: | 183 | default: |
| 180 | deb("Unexpected rc state %02x\n", rc_state[0]); | 184 | deb("Unexpected rc state %02x\n", rc_state[0]); |
| 181 | *state = REMOTE_NO_KEY_PRESSED; | 185 | *state = REMOTE_NO_KEY_PRESSED; |
| 182 | goto unlock; | 186 | goto out; |
| 183 | } | 187 | } |
| 184 | } | 188 | } |
| 185 | 189 | ||
| @@ -188,8 +192,8 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 188 | 192 | ||
| 189 | *state = REMOTE_NO_KEY_PRESSED; | 193 | *state = REMOTE_NO_KEY_PRESSED; |
| 190 | 194 | ||
| 191 | unlock: | 195 | out: |
| 192 | 196 | kfree(rc_state); | |
| 193 | return ret; | 197 | return ret; |
| 194 | } | 198 | } |
| 195 | 199 | ||
| @@ -339,13 +343,19 @@ static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in | |||
| 339 | static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw) | 343 | static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw) |
| 340 | { | 344 | { |
| 341 | u16 value, index, size; | 345 | u16 value, index, size; |
| 342 | u8 read[4], *buff; | 346 | u8 *read, *buff; |
| 343 | int i, pass, ret = 0; | 347 | int i, pass, ret = 0; |
| 344 | 348 | ||
| 345 | buff = kmalloc(65536, GFP_KERNEL); | 349 | buff = kmalloc(65536, GFP_KERNEL); |
| 346 | if (buff == NULL) | 350 | if (buff == NULL) |
| 347 | return -ENOMEM; | 351 | return -ENOMEM; |
| 348 | 352 | ||
| 353 | read = kmalloc(4, GFP_KERNEL); | ||
| 354 | if (!read) { | ||
| 355 | kfree(buff); | ||
| 356 | return -ENOMEM; | ||
| 357 | } | ||
| 358 | |||
| 349 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) | 359 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) |
| 350 | goto done; | 360 | goto done; |
| 351 | deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]); | 361 | deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]); |
| @@ -396,6 +406,7 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar | |||
| 396 | deb("firmware uploaded!\n"); | 406 | deb("firmware uploaded!\n"); |
| 397 | 407 | ||
| 398 | done: | 408 | done: |
| 409 | kfree(read); | ||
| 399 | kfree(buff); | 410 | kfree(buff); |
| 400 | 411 | ||
| 401 | return ret; | 412 | return ret; |
| @@ -632,9 +643,9 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { | |||
| 632 | { 0x16, KEY_POWER }, | 643 | { 0x16, KEY_POWER }, |
| 633 | { 0x17, KEY_FAVORITES }, | 644 | { 0x17, KEY_FAVORITES }, |
| 634 | { 0x0f, KEY_TEXT }, | 645 | { 0x0f, KEY_TEXT }, |
| 635 | { 0x48, KEY_MEDIA }, /* preview */ | 646 | { 0x48, KEY_PROGRAM }, /* preview */ |
| 636 | { 0x1c, KEY_EPG }, | 647 | { 0x1c, KEY_EPG }, |
| 637 | { 0x04, KEY_LIST }, /* record list */ | 648 | { 0x04, KEY_LIST }, /* record list */ |
| 638 | { 0x03, KEY_1 }, | 649 | { 0x03, KEY_1 }, |
| 639 | { 0x01, KEY_2 }, | 650 | { 0x01, KEY_2 }, |
| 640 | { 0x06, KEY_3 }, | 651 | { 0x06, KEY_3 }, |
| @@ -674,14 +685,14 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { | |||
| 674 | { 0x0e, KEY_MUTE }, | 685 | { 0x0e, KEY_MUTE }, |
| 675 | /* { 0x49, KEY_LR }, */ /* L/R */ | 686 | /* { 0x49, KEY_LR }, */ /* L/R */ |
| 676 | { 0x07, KEY_SLEEP }, /* Hibernate */ | 687 | { 0x07, KEY_SLEEP }, /* Hibernate */ |
| 677 | { 0x08, KEY_MEDIA }, /* A/V */ | 688 | { 0x08, KEY_VIDEO }, /* A/V */ |
| 678 | { 0x0e, KEY_MENU }, /* Recall */ | 689 | { 0x0e, KEY_MENU }, /* Recall */ |
| 679 | { 0x45, KEY_ZOOMIN }, | 690 | { 0x45, KEY_ZOOMIN }, |
| 680 | { 0x46, KEY_ZOOMOUT }, | 691 | { 0x46, KEY_ZOOMOUT }, |
| 681 | { 0x18, KEY_TV }, /* Red */ | 692 | { 0x18, KEY_RED }, /* Red */ |
| 682 | { 0x53, KEY_VCR }, /* Green */ | 693 | { 0x53, KEY_GREEN }, /* Green */ |
| 683 | { 0x5e, KEY_SAT }, /* Yellow */ | 694 | { 0x5e, KEY_YELLOW }, /* Yellow */ |
| 684 | { 0x5f, KEY_PLAYER }, /* Blue */ | 695 | { 0x5f, KEY_BLUE }, /* Blue */ |
| 685 | }; | 696 | }; |
| 686 | 697 | ||
| 687 | /* DVB USB Driver stuff */ | 698 | /* DVB USB Driver stuff */ |
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index 9d3cd2de46fc..bc350e982b72 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c | |||
| @@ -47,7 +47,7 @@ static struct rc_map_table rc_map_haupp_table[] = { | |||
| 47 | { 0x1e17, KEY_RIGHT }, | 47 | { 0x1e17, KEY_RIGHT }, |
| 48 | { 0x1e18, KEY_VIDEO }, | 48 | { 0x1e18, KEY_VIDEO }, |
| 49 | { 0x1e19, KEY_AUDIO }, | 49 | { 0x1e19, KEY_AUDIO }, |
| 50 | { 0x1e1a, KEY_MEDIA }, | 50 | { 0x1e1a, KEY_IMAGES }, |
| 51 | { 0x1e1b, KEY_EPG }, | 51 | { 0x1e1b, KEY_EPG }, |
| 52 | { 0x1e1c, KEY_TV }, | 52 | { 0x1e1c, KEY_TV }, |
| 53 | { 0x1e1e, KEY_NEXT }, | 53 | { 0x1e1e, KEY_NEXT }, |
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 7e569f4dd80b..2e4fab7215f5 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c | |||
| @@ -53,27 +53,36 @@ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value, | |||
| 53 | u8 * data, u16 len, int flags) | 53 | u8 * data, u16 len, int flags) |
| 54 | { | 54 | { |
| 55 | int ret; | 55 | int ret; |
| 56 | u8 r; | 56 | u8 tmp; |
| 57 | u8 u8buf[len]; | 57 | u8 *buf; |
| 58 | |||
| 59 | unsigned int pipe = (flags == OPERA_READ_MSG) ? | 58 | unsigned int pipe = (flags == OPERA_READ_MSG) ? |
| 60 | usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0); | 59 | usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0); |
| 61 | u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; | 60 | u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; |
| 62 | 61 | ||
| 62 | buf = kmalloc(len, GFP_KERNEL); | ||
| 63 | if (!buf) | ||
| 64 | return -ENOMEM; | ||
| 65 | |||
| 63 | if (flags == OPERA_WRITE_MSG) | 66 | if (flags == OPERA_WRITE_MSG) |
| 64 | memcpy(u8buf, data, len); | 67 | memcpy(buf, data, len); |
| 65 | ret = | 68 | ret = usb_control_msg(dev, pipe, request, |
| 66 | usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, | 69 | request_type | USB_TYPE_VENDOR, value, 0x0, |
| 67 | value, 0x0, u8buf, len, 2000); | 70 | buf, len, 2000); |
| 68 | 71 | ||
| 69 | if (request == OPERA_TUNER_REQ) { | 72 | if (request == OPERA_TUNER_REQ) { |
| 73 | tmp = buf[0]; | ||
| 70 | if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 74 | if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
| 71 | OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR, | 75 | OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR, |
| 72 | 0x01, 0x0, &r, 1, 2000)<1 || r!=0x08) | 76 | 0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) { |
| 73 | return 0; | 77 | ret = 0; |
| 78 | goto out; | ||
| 79 | } | ||
| 80 | buf[0] = tmp; | ||
| 74 | } | 81 | } |
| 75 | if (flags == OPERA_READ_MSG) | 82 | if (flags == OPERA_READ_MSG) |
| 76 | memcpy(data, u8buf, len); | 83 | memcpy(data, buf, len); |
| 84 | out: | ||
| 85 | kfree(buf); | ||
| 77 | return ret; | 86 | return ret; |
| 78 | } | 87 | } |
| 79 | 88 | ||
| @@ -189,7 +198,7 @@ static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, | |||
| 189 | static u8 opera1_inittab[] = { | 198 | static u8 opera1_inittab[] = { |
| 190 | 0x00, 0xa1, | 199 | 0x00, 0xa1, |
| 191 | 0x01, 0x15, | 200 | 0x01, 0x15, |
| 192 | 0x02, 0x00, | 201 | 0x02, 0x30, |
| 193 | 0x03, 0x00, | 202 | 0x03, 0x00, |
| 194 | 0x04, 0x7d, | 203 | 0x04, 0x7d, |
| 195 | 0x05, 0x05, | 204 | 0x05, 0x05, |
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c index ccc7e4452664..2bb8d4cc8d88 100644 --- a/drivers/media/dvb/dvb-usb/vp702x-fe.c +++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c | |||
| @@ -41,14 +41,23 @@ struct vp702x_fe_state { | |||
| 41 | 41 | ||
| 42 | static int vp702x_fe_refresh_state(struct vp702x_fe_state *st) | 42 | static int vp702x_fe_refresh_state(struct vp702x_fe_state *st) |
| 43 | { | 43 | { |
| 44 | u8 buf[10]; | 44 | struct vp702x_device_state *dst = st->d->priv; |
| 45 | if (time_after(jiffies,st->next_status_check)) { | 45 | u8 *buf; |
| 46 | vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10); | ||
| 47 | 46 | ||
| 47 | if (time_after(jiffies, st->next_status_check)) { | ||
| 48 | mutex_lock(&dst->buf_mutex); | ||
| 49 | buf = dst->buf; | ||
| 50 | |||
| 51 | vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10); | ||
| 48 | st->lock = buf[4]; | 52 | st->lock = buf[4]; |
| 49 | vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1); | ||
| 50 | vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1); | ||
| 51 | 53 | ||
| 54 | vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1); | ||
| 55 | st->snr = buf[0]; | ||
| 56 | |||
| 57 | vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1); | ||
| 58 | st->sig = buf[0]; | ||
| 59 | |||
| 60 | mutex_unlock(&dst->buf_mutex); | ||
| 52 | st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; | 61 | st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; |
| 53 | } | 62 | } |
| 54 | return 0; | 63 | return 0; |
| @@ -130,11 +139,17 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe, | |||
| 130 | struct dvb_frontend_parameters *fep) | 139 | struct dvb_frontend_parameters *fep) |
| 131 | { | 140 | { |
| 132 | struct vp702x_fe_state *st = fe->demodulator_priv; | 141 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 142 | struct vp702x_device_state *dst = st->d->priv; | ||
| 133 | u32 freq = fep->frequency/1000; | 143 | u32 freq = fep->frequency/1000; |
| 134 | /*CalFrequency*/ | 144 | /*CalFrequency*/ |
| 135 | /* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */ | 145 | /* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */ |
| 136 | u64 sr; | 146 | u64 sr; |
| 137 | u8 cmd[8] = { 0 },ibuf[10]; | 147 | u8 *cmd; |
| 148 | |||
| 149 | mutex_lock(&dst->buf_mutex); | ||
| 150 | |||
| 151 | cmd = dst->buf; | ||
| 152 | memset(cmd, 0, 10); | ||
| 138 | 153 | ||
| 139 | cmd[0] = (freq >> 8) & 0x7f; | 154 | cmd[0] = (freq >> 8) & 0x7f; |
| 140 | cmd[1] = freq & 0xff; | 155 | cmd[1] = freq & 0xff; |
| @@ -170,13 +185,15 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe, | |||
| 170 | st->status_check_interval = 250; | 185 | st->status_check_interval = 250; |
| 171 | st->next_status_check = jiffies; | 186 | st->next_status_check = jiffies; |
| 172 | 187 | ||
| 173 | vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); | 188 | vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); |
| 174 | 189 | ||
| 175 | if (ibuf[2] == 0 && ibuf[3] == 0) | 190 | if (cmd[2] == 0 && cmd[3] == 0) |
| 176 | deb_fe("tuning failed.\n"); | 191 | deb_fe("tuning failed.\n"); |
| 177 | else | 192 | else |
| 178 | deb_fe("tuning succeeded.\n"); | 193 | deb_fe("tuning succeeded.\n"); |
| 179 | 194 | ||
| 195 | mutex_unlock(&dst->buf_mutex); | ||
| 196 | |||
| 180 | return 0; | 197 | return 0; |
| 181 | } | 198 | } |
| 182 | 199 | ||
| @@ -204,27 +221,32 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe, | |||
| 204 | static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, | 221 | static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, |
| 205 | struct dvb_diseqc_master_cmd *m) | 222 | struct dvb_diseqc_master_cmd *m) |
| 206 | { | 223 | { |
| 224 | u8 *cmd; | ||
| 207 | struct vp702x_fe_state *st = fe->demodulator_priv; | 225 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 208 | u8 cmd[8],ibuf[10]; | 226 | struct vp702x_device_state *dst = st->d->priv; |
| 209 | memset(cmd,0,8); | ||
| 210 | 227 | ||
| 211 | deb_fe("%s\n",__func__); | 228 | deb_fe("%s\n",__func__); |
| 212 | 229 | ||
| 213 | if (m->msg_len > 4) | 230 | if (m->msg_len > 4) |
| 214 | return -EINVAL; | 231 | return -EINVAL; |
| 215 | 232 | ||
| 233 | mutex_lock(&dst->buf_mutex); | ||
| 234 | |||
| 235 | cmd = dst->buf; | ||
| 216 | cmd[1] = SET_DISEQC_CMD; | 236 | cmd[1] = SET_DISEQC_CMD; |
| 217 | cmd[2] = m->msg_len; | 237 | cmd[2] = m->msg_len; |
| 218 | memcpy(&cmd[3], m->msg, m->msg_len); | 238 | memcpy(&cmd[3], m->msg, m->msg_len); |
| 219 | cmd[7] = vp702x_chksum(cmd,0,7); | 239 | cmd[7] = vp702x_chksum(cmd, 0, 7); |
| 220 | 240 | ||
| 221 | vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); | 241 | vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); |
| 222 | 242 | ||
| 223 | if (ibuf[2] == 0 && ibuf[3] == 0) | 243 | if (cmd[2] == 0 && cmd[3] == 0) |
| 224 | deb_fe("diseqc cmd failed.\n"); | 244 | deb_fe("diseqc cmd failed.\n"); |
| 225 | else | 245 | else |
| 226 | deb_fe("diseqc cmd succeeded.\n"); | 246 | deb_fe("diseqc cmd succeeded.\n"); |
| 227 | 247 | ||
| 248 | mutex_unlock(&dst->buf_mutex); | ||
| 249 | |||
| 228 | return 0; | 250 | return 0; |
| 229 | } | 251 | } |
| 230 | 252 | ||
| @@ -237,7 +259,9 @@ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd | |||
| 237 | static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | 259 | static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) |
| 238 | { | 260 | { |
| 239 | struct vp702x_fe_state *st = fe->demodulator_priv; | 261 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 240 | u8 ibuf[10]; | 262 | struct vp702x_device_state *dst = st->d->priv; |
| 263 | u8 *buf; | ||
| 264 | |||
| 241 | deb_fe("%s\n",__func__); | 265 | deb_fe("%s\n",__func__); |
| 242 | 266 | ||
| 243 | st->tone_mode = tone; | 267 | st->tone_mode = tone; |
| @@ -247,14 +271,21 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | |||
| 247 | else | 271 | else |
| 248 | st->lnb_buf[2] = 0x00; | 272 | st->lnb_buf[2] = 0x00; |
| 249 | 273 | ||
| 250 | st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7); | 274 | st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); |
| 275 | |||
| 276 | mutex_lock(&dst->buf_mutex); | ||
| 277 | |||
| 278 | buf = dst->buf; | ||
| 279 | memcpy(buf, st->lnb_buf, 8); | ||
| 251 | 280 | ||
| 252 | vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100); | 281 | vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); |
| 253 | if (ibuf[2] == 0 && ibuf[3] == 0) | 282 | if (buf[2] == 0 && buf[3] == 0) |
| 254 | deb_fe("set_tone cmd failed.\n"); | 283 | deb_fe("set_tone cmd failed.\n"); |
| 255 | else | 284 | else |
| 256 | deb_fe("set_tone cmd succeeded.\n"); | 285 | deb_fe("set_tone cmd succeeded.\n"); |
| 257 | 286 | ||
| 287 | mutex_unlock(&dst->buf_mutex); | ||
| 288 | |||
| 258 | return 0; | 289 | return 0; |
| 259 | } | 290 | } |
| 260 | 291 | ||
| @@ -262,7 +293,8 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t | |||
| 262 | voltage) | 293 | voltage) |
| 263 | { | 294 | { |
| 264 | struct vp702x_fe_state *st = fe->demodulator_priv; | 295 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 265 | u8 ibuf[10]; | 296 | struct vp702x_device_state *dst = st->d->priv; |
| 297 | u8 *buf; | ||
| 266 | deb_fe("%s\n",__func__); | 298 | deb_fe("%s\n",__func__); |
| 267 | 299 | ||
| 268 | st->voltage = voltage; | 300 | st->voltage = voltage; |
| @@ -272,14 +304,20 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t | |||
| 272 | else | 304 | else |
| 273 | st->lnb_buf[4] = 0x00; | 305 | st->lnb_buf[4] = 0x00; |
| 274 | 306 | ||
| 275 | st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7); | 307 | st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); |
| 308 | |||
| 309 | mutex_lock(&dst->buf_mutex); | ||
| 310 | |||
| 311 | buf = dst->buf; | ||
| 312 | memcpy(buf, st->lnb_buf, 8); | ||
| 276 | 313 | ||
| 277 | vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100); | 314 | vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); |
| 278 | if (ibuf[2] == 0 && ibuf[3] == 0) | 315 | if (buf[2] == 0 && buf[3] == 0) |
| 279 | deb_fe("set_voltage cmd failed.\n"); | 316 | deb_fe("set_voltage cmd failed.\n"); |
| 280 | else | 317 | else |
| 281 | deb_fe("set_voltage cmd succeeded.\n"); | 318 | deb_fe("set_voltage cmd succeeded.\n"); |
| 282 | 319 | ||
| 320 | mutex_unlock(&dst->buf_mutex); | ||
| 283 | return 0; | 321 | return 0; |
| 284 | } | 322 | } |
| 285 | 323 | ||
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index 7890e75600df..54355f84a98f 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | * see Documentation/dvb/README.dvb-usb for more information | 15 | * see Documentation/dvb/README.dvb-usb for more information |
| 16 | */ | 16 | */ |
| 17 | #include "vp702x.h" | 17 | #include "vp702x.h" |
| 18 | #include <linux/mutex.h> | ||
| 18 | 19 | ||
| 19 | /* debug */ | 20 | /* debug */ |
| 20 | int dvb_usb_vp702x_debug; | 21 | int dvb_usb_vp702x_debug; |
| @@ -23,27 +24,23 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV | |||
| 23 | 24 | ||
| 24 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 25 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 25 | 26 | ||
| 26 | struct vp702x_state { | 27 | struct vp702x_adapter_state { |
| 27 | int pid_filter_count; | 28 | int pid_filter_count; |
| 28 | int pid_filter_can_bypass; | 29 | int pid_filter_can_bypass; |
| 29 | u8 pid_filter_state; | 30 | u8 pid_filter_state; |
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | struct vp702x_device_state { | 33 | static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req, |
| 33 | u8 power_state; | 34 | u16 value, u16 index, u8 *b, int blen) |
| 34 | }; | ||
| 35 | |||
| 36 | /* check for mutex FIXME */ | ||
| 37 | int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) | ||
| 38 | { | 35 | { |
| 39 | int ret = -1; | 36 | int ret; |
| 40 | 37 | ||
| 41 | ret = usb_control_msg(d->udev, | 38 | ret = usb_control_msg(d->udev, |
| 42 | usb_rcvctrlpipe(d->udev,0), | 39 | usb_rcvctrlpipe(d->udev, 0), |
| 43 | req, | 40 | req, |
| 44 | USB_TYPE_VENDOR | USB_DIR_IN, | 41 | USB_TYPE_VENDOR | USB_DIR_IN, |
| 45 | value,index,b,blen, | 42 | value, index, b, blen, |
| 46 | 2000); | 43 | 2000); |
| 47 | 44 | ||
| 48 | if (ret < 0) { | 45 | if (ret < 0) { |
| 49 | warn("usb in operation failed. (%d)", ret); | 46 | warn("usb in operation failed. (%d)", ret); |
| @@ -58,8 +55,20 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 | |||
| 58 | return ret; | 55 | return ret; |
| 59 | } | 56 | } |
| 60 | 57 | ||
| 61 | static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | 58 | int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, |
| 62 | u16 index, u8 *b, int blen) | 59 | u16 index, u8 *b, int blen) |
| 60 | { | ||
| 61 | int ret; | ||
| 62 | |||
| 63 | mutex_lock(&d->usb_mutex); | ||
| 64 | ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen); | ||
| 65 | mutex_unlock(&d->usb_mutex); | ||
| 66 | |||
| 67 | return ret; | ||
| 68 | } | ||
| 69 | |||
| 70 | int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value, | ||
| 71 | u16 index, u8 *b, int blen) | ||
| 63 | { | 72 | { |
| 64 | int ret; | 73 | int ret; |
| 65 | deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); | 74 | deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); |
| @@ -77,6 +86,18 @@ static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | |||
| 77 | return 0; | 86 | return 0; |
| 78 | } | 87 | } |
| 79 | 88 | ||
| 89 | int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | ||
| 90 | u16 index, u8 *b, int blen) | ||
| 91 | { | ||
| 92 | int ret; | ||
| 93 | |||
| 94 | mutex_lock(&d->usb_mutex); | ||
| 95 | ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen); | ||
| 96 | mutex_unlock(&d->usb_mutex); | ||
| 97 | |||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 80 | int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec) | 101 | int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec) |
| 81 | { | 102 | { |
| 82 | int ret; | 103 | int ret; |
| @@ -84,50 +105,93 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il | |||
| 84 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | 105 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) |
| 85 | return ret; | 106 | return ret; |
| 86 | 107 | ||
| 87 | ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen); | 108 | ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen); |
| 88 | msleep(msec); | 109 | msleep(msec); |
| 89 | ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen); | 110 | ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen); |
| 90 | 111 | ||
| 91 | mutex_unlock(&d->usb_mutex); | 112 | mutex_unlock(&d->usb_mutex); |
| 92 | |||
| 93 | return ret; | 113 | return ret; |
| 94 | } | 114 | } |
| 95 | 115 | ||
| 96 | static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, | 116 | static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, |
| 97 | int olen, u8 *i, int ilen, int msec) | 117 | int olen, u8 *i, int ilen, int msec) |
| 98 | { | 118 | { |
| 99 | u8 bout[olen+2]; | 119 | struct vp702x_device_state *st = d->priv; |
| 100 | u8 bin[ilen+1]; | ||
| 101 | int ret = 0; | 120 | int ret = 0; |
| 121 | u8 *buf; | ||
| 122 | int buflen = max(olen + 2, ilen + 1); | ||
| 123 | |||
| 124 | ret = mutex_lock_interruptible(&st->buf_mutex); | ||
| 125 | if (ret < 0) | ||
| 126 | return ret; | ||
| 127 | |||
| 128 | if (buflen > st->buf_len) { | ||
| 129 | buf = kmalloc(buflen, GFP_KERNEL); | ||
| 130 | if (!buf) { | ||
| 131 | mutex_unlock(&st->buf_mutex); | ||
| 132 | return -ENOMEM; | ||
| 133 | } | ||
| 134 | info("successfully reallocated a bigger buffer"); | ||
| 135 | kfree(st->buf); | ||
| 136 | st->buf = buf; | ||
| 137 | st->buf_len = buflen; | ||
| 138 | } else { | ||
| 139 | buf = st->buf; | ||
| 140 | } | ||
| 102 | 141 | ||
| 103 | bout[0] = 0x00; | 142 | buf[0] = 0x00; |
| 104 | bout[1] = cmd; | 143 | buf[1] = cmd; |
| 105 | memcpy(&bout[2],o,olen); | 144 | memcpy(&buf[2], o, olen); |
| 106 | 145 | ||
| 107 | ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec); | 146 | ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec); |
| 108 | 147 | ||
| 109 | if (ret == 0) | 148 | if (ret == 0) |
| 110 | memcpy(i,&bin[1],ilen); | 149 | memcpy(i, &buf[1], ilen); |
| 150 | mutex_unlock(&st->buf_mutex); | ||
| 111 | 151 | ||
| 112 | return ret; | 152 | return ret; |
| 113 | } | 153 | } |
| 114 | 154 | ||
| 115 | static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass) | 155 | static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass) |
| 116 | { | 156 | { |
| 117 | u8 buf[16] = { 0 }; | 157 | int ret; |
| 118 | return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16); | 158 | struct vp702x_device_state *st = adap->dev->priv; |
| 159 | u8 *buf; | ||
| 160 | |||
| 161 | mutex_lock(&st->buf_mutex); | ||
| 162 | |||
| 163 | buf = st->buf; | ||
| 164 | memset(buf, 0, 16); | ||
| 165 | |||
| 166 | ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, | ||
| 167 | 0, buf, 16); | ||
| 168 | mutex_unlock(&st->buf_mutex); | ||
| 169 | return ret; | ||
| 119 | } | 170 | } |
| 120 | 171 | ||
| 121 | static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state) | 172 | static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state) |
| 122 | { | 173 | { |
| 123 | u8 buf[16] = { 0 }; | 174 | int ret; |
| 124 | return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16); | 175 | struct vp702x_device_state *st = adap->dev->priv; |
| 176 | u8 *buf; | ||
| 177 | |||
| 178 | mutex_lock(&st->buf_mutex); | ||
| 179 | |||
| 180 | buf = st->buf; | ||
| 181 | memset(buf, 0, 16); | ||
| 182 | ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, | ||
| 183 | 0, buf, 16); | ||
| 184 | |||
| 185 | mutex_unlock(&st->buf_mutex); | ||
| 186 | |||
| 187 | return ret; | ||
| 125 | } | 188 | } |
| 126 | 189 | ||
| 127 | static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff) | 190 | static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff) |
| 128 | { | 191 | { |
| 129 | struct vp702x_state *st = adap->priv; | 192 | struct vp702x_adapter_state *st = adap->priv; |
| 130 | u8 buf[16] = { 0 }; | 193 | struct vp702x_device_state *dst = adap->dev->priv; |
| 194 | u8 *buf; | ||
| 131 | 195 | ||
| 132 | if (onoff) | 196 | if (onoff) |
| 133 | st->pid_filter_state |= (1 << id); | 197 | st->pid_filter_state |= (1 << id); |
| @@ -139,32 +203,45 @@ static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onof | |||
| 139 | id = 0x10 + id*2; | 203 | id = 0x10 + id*2; |
| 140 | 204 | ||
| 141 | vp702x_set_pld_state(adap, st->pid_filter_state); | 205 | vp702x_set_pld_state(adap, st->pid_filter_state); |
| 206 | |||
| 207 | mutex_lock(&dst->buf_mutex); | ||
| 208 | |||
| 209 | buf = dst->buf; | ||
| 210 | memset(buf, 0, 16); | ||
| 142 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16); | 211 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16); |
| 143 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid ) & 0xff) << 8) | (id+1), 0, buf, 16); | 212 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid ) & 0xff) << 8) | (id+1), 0, buf, 16); |
| 213 | |||
| 214 | mutex_unlock(&dst->buf_mutex); | ||
| 215 | |||
| 144 | return 0; | 216 | return 0; |
| 145 | } | 217 | } |
| 146 | 218 | ||
| 147 | 219 | ||
| 148 | static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap) | 220 | static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap) |
| 149 | { | 221 | { |
| 150 | struct vp702x_state *st = adap->priv; | 222 | struct vp702x_adapter_state *st = adap->priv; |
| 223 | struct vp702x_device_state *dst = adap->dev->priv; | ||
| 151 | int i; | 224 | int i; |
| 152 | u8 b[10] = { 0 }; | 225 | u8 *b; |
| 153 | 226 | ||
| 154 | st->pid_filter_count = 8; | 227 | st->pid_filter_count = 8; |
| 155 | st->pid_filter_can_bypass = 1; | 228 | st->pid_filter_can_bypass = 1; |
| 156 | st->pid_filter_state = 0x00; | 229 | st->pid_filter_state = 0x00; |
| 157 | 230 | ||
| 158 | vp702x_set_pld_mode(adap, 1); // bypass | 231 | vp702x_set_pld_mode(adap, 1); /* bypass */ |
| 159 | 232 | ||
| 160 | for (i = 0; i < st->pid_filter_count; i++) | 233 | for (i = 0; i < st->pid_filter_count; i++) |
| 161 | vp702x_set_pid(adap, 0xffff, i, 1); | 234 | vp702x_set_pid(adap, 0xffff, i, 1); |
| 162 | 235 | ||
| 236 | mutex_lock(&dst->buf_mutex); | ||
| 237 | b = dst->buf; | ||
| 238 | memset(b, 0, 10); | ||
| 163 | vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10); | 239 | vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10); |
| 164 | vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10); | 240 | vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10); |
| 165 | vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10); | 241 | vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10); |
| 242 | mutex_unlock(&dst->buf_mutex); | ||
| 243 | /*vp702x_set_pld_mode(d, 0); // filter */ | ||
| 166 | 244 | ||
| 167 | //vp702x_set_pld_mode(d, 0); // filter | ||
| 168 | return 0; | 245 | return 0; |
| 169 | } | 246 | } |
| 170 | 247 | ||
| @@ -182,18 +259,23 @@ static struct rc_map_table rc_map_vp702x_table[] = { | |||
| 182 | /* remote control stuff (does not work with my box) */ | 259 | /* remote control stuff (does not work with my box) */ |
| 183 | static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 260 | static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 184 | { | 261 | { |
| 185 | u8 key[10]; | 262 | u8 *key; |
| 186 | int i; | 263 | int i; |
| 187 | 264 | ||
| 188 | /* remove the following return to enabled remote querying */ | 265 | /* remove the following return to enabled remote querying */ |
| 189 | return 0; | 266 | return 0; |
| 190 | 267 | ||
| 268 | key = kmalloc(10, GFP_KERNEL); | ||
| 269 | if (!key) | ||
| 270 | return -ENOMEM; | ||
| 271 | |||
| 191 | vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10); | 272 | vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10); |
| 192 | 273 | ||
| 193 | deb_rc("remote query key: %x %d\n",key[1],key[1]); | 274 | deb_rc("remote query key: %x %d\n",key[1],key[1]); |
| 194 | 275 | ||
| 195 | if (key[1] == 0x44) { | 276 | if (key[1] == 0x44) { |
| 196 | *state = REMOTE_NO_KEY_PRESSED; | 277 | *state = REMOTE_NO_KEY_PRESSED; |
| 278 | kfree(key); | ||
| 197 | return 0; | 279 | return 0; |
| 198 | } | 280 | } |
| 199 | 281 | ||
| @@ -203,15 +285,23 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 203 | *event = rc_map_vp702x_table[i].keycode; | 285 | *event = rc_map_vp702x_table[i].keycode; |
| 204 | break; | 286 | break; |
| 205 | } | 287 | } |
| 288 | kfree(key); | ||
| 206 | return 0; | 289 | return 0; |
| 207 | } | 290 | } |
| 208 | 291 | ||
| 209 | 292 | ||
| 210 | static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) | 293 | static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) |
| 211 | { | 294 | { |
| 212 | u8 i; | 295 | u8 i, *buf; |
| 296 | struct vp702x_device_state *st = d->priv; | ||
| 297 | |||
| 298 | mutex_lock(&st->buf_mutex); | ||
| 299 | buf = st->buf; | ||
| 213 | for (i = 6; i < 12; i++) | 300 | for (i = 6; i < 12; i++) |
| 214 | vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1); | 301 | vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1); |
| 302 | |||
| 303 | memcpy(mac, buf, 6); | ||
| 304 | mutex_unlock(&st->buf_mutex); | ||
| 215 | return 0; | 305 | return 0; |
| 216 | } | 306 | } |
| 217 | 307 | ||
| @@ -221,7 +311,8 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 221 | 311 | ||
| 222 | vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0); | 312 | vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0); |
| 223 | 313 | ||
| 224 | if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10)) | 314 | if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, |
| 315 | buf, 10, 10)) | ||
| 225 | return -EIO; | 316 | return -EIO; |
| 226 | 317 | ||
| 227 | buf[9] = '\0'; | 318 | buf[9] = '\0'; |
| @@ -240,8 +331,38 @@ static struct dvb_usb_device_properties vp702x_properties; | |||
| 240 | static int vp702x_usb_probe(struct usb_interface *intf, | 331 | static int vp702x_usb_probe(struct usb_interface *intf, |
| 241 | const struct usb_device_id *id) | 332 | const struct usb_device_id *id) |
| 242 | { | 333 | { |
| 243 | return dvb_usb_device_init(intf, &vp702x_properties, | 334 | struct dvb_usb_device *d; |
| 244 | THIS_MODULE, NULL, adapter_nr); | 335 | struct vp702x_device_state *st; |
| 336 | int ret; | ||
| 337 | |||
| 338 | ret = dvb_usb_device_init(intf, &vp702x_properties, | ||
| 339 | THIS_MODULE, &d, adapter_nr); | ||
| 340 | if (ret) | ||
| 341 | goto out; | ||
| 342 | |||
| 343 | st = d->priv; | ||
| 344 | st->buf_len = 16; | ||
| 345 | st->buf = kmalloc(st->buf_len, GFP_KERNEL); | ||
| 346 | if (!st->buf) { | ||
| 347 | ret = -ENOMEM; | ||
| 348 | dvb_usb_device_exit(intf); | ||
| 349 | goto out; | ||
| 350 | } | ||
| 351 | mutex_init(&st->buf_mutex); | ||
| 352 | |||
| 353 | out: | ||
| 354 | return ret; | ||
| 355 | |||
| 356 | } | ||
| 357 | |||
| 358 | static void vp702x_usb_disconnect(struct usb_interface *intf) | ||
| 359 | { | ||
| 360 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 361 | struct vp702x_device_state *st = d->priv; | ||
| 362 | mutex_lock(&st->buf_mutex); | ||
| 363 | kfree(st->buf); | ||
| 364 | mutex_unlock(&st->buf_mutex); | ||
| 365 | dvb_usb_device_exit(intf); | ||
| 245 | } | 366 | } |
| 246 | 367 | ||
| 247 | static struct usb_device_id vp702x_usb_table [] = { | 368 | static struct usb_device_id vp702x_usb_table [] = { |
| @@ -278,7 +399,7 @@ static struct dvb_usb_device_properties vp702x_properties = { | |||
| 278 | } | 399 | } |
| 279 | } | 400 | } |
| 280 | }, | 401 | }, |
| 281 | .size_of_priv = sizeof(struct vp702x_state), | 402 | .size_of_priv = sizeof(struct vp702x_adapter_state), |
| 282 | } | 403 | } |
| 283 | }, | 404 | }, |
| 284 | .read_mac_address = vp702x_read_mac_addr, | 405 | .read_mac_address = vp702x_read_mac_addr, |
| @@ -307,9 +428,9 @@ static struct dvb_usb_device_properties vp702x_properties = { | |||
| 307 | /* usb specific object needed to register this driver with the usb subsystem */ | 428 | /* usb specific object needed to register this driver with the usb subsystem */ |
| 308 | static struct usb_driver vp702x_usb_driver = { | 429 | static struct usb_driver vp702x_usb_driver = { |
| 309 | .name = "dvb_usb_vp702x", | 430 | .name = "dvb_usb_vp702x", |
| 310 | .probe = vp702x_usb_probe, | 431 | .probe = vp702x_usb_probe, |
| 311 | .disconnect = dvb_usb_device_exit, | 432 | .disconnect = vp702x_usb_disconnect, |
| 312 | .id_table = vp702x_usb_table, | 433 | .id_table = vp702x_usb_table, |
| 313 | }; | 434 | }; |
| 314 | 435 | ||
| 315 | /* module stuff */ | 436 | /* module stuff */ |
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h index c2f97f96c21f..20b90055e7ac 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.h +++ b/drivers/media/dvb/dvb-usb/vp702x.h | |||
| @@ -98,6 +98,13 @@ extern int dvb_usb_vp702x_debug; | |||
| 98 | #define RESET_TUNER 0xBE | 98 | #define RESET_TUNER 0xBE |
| 99 | /* IN i: 0, v: 0, no extra buffer */ | 99 | /* IN i: 0, v: 0, no extra buffer */ |
| 100 | 100 | ||
| 101 | struct vp702x_device_state { | ||
| 102 | struct mutex buf_mutex; | ||
| 103 | int buf_len; | ||
| 104 | u8 *buf; | ||
| 105 | }; | ||
| 106 | |||
| 107 | |||
| 101 | extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); | 108 | extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); |
| 102 | 109 | ||
| 103 | extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); | 110 | extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); |
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index ab0ab3c35e80..3db89e3cb0bb 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
| @@ -28,9 +28,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 28 | int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) | 28 | int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) |
| 29 | { | 29 | { |
| 30 | int ret = 0; | 30 | int ret = 0; |
| 31 | u8 inbuf[12] = { 0 }, outbuf[20] = { 0 }; | 31 | u8 *buf = d->priv; |
| 32 | 32 | ||
| 33 | outbuf[0] = cmd; | 33 | buf[0] = cmd; |
| 34 | 34 | ||
| 35 | if (outlen > 19) | 35 | if (outlen > 19) |
| 36 | outlen = 19; | 36 | outlen = 19; |
| @@ -38,19 +38,21 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, | |||
| 38 | if (inlen > 11) | 38 | if (inlen > 11) |
| 39 | inlen = 11; | 39 | inlen = 11; |
| 40 | 40 | ||
| 41 | ret = mutex_lock_interruptible(&d->usb_mutex); | ||
| 42 | if (ret) | ||
| 43 | return ret; | ||
| 44 | |||
| 41 | if (out != NULL && outlen > 0) | 45 | if (out != NULL && outlen > 0) |
| 42 | memcpy(&outbuf[1], out, outlen); | 46 | memcpy(&buf[1], out, outlen); |
| 43 | 47 | ||
| 44 | deb_xfer("out buffer: "); | 48 | deb_xfer("out buffer: "); |
| 45 | debug_dump(outbuf,outlen+1,deb_xfer); | 49 | debug_dump(buf, outlen+1, deb_xfer); |
| 46 | 50 | ||
| 47 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | ||
| 48 | return ret; | ||
| 49 | 51 | ||
| 50 | if (usb_control_msg(d->udev, | 52 | if (usb_control_msg(d->udev, |
| 51 | usb_sndctrlpipe(d->udev,0), | 53 | usb_sndctrlpipe(d->udev,0), |
| 52 | TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, | 54 | TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, |
| 53 | outbuf, 20, 2000) != 20) { | 55 | buf, 20, 2000) != 20) { |
| 54 | err("USB control message 'out' went wrong."); | 56 | err("USB control message 'out' went wrong."); |
| 55 | ret = -EIO; | 57 | ret = -EIO; |
| 56 | goto unlock; | 58 | goto unlock; |
| @@ -61,17 +63,17 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, | |||
| 61 | if (usb_control_msg(d->udev, | 63 | if (usb_control_msg(d->udev, |
| 62 | usb_rcvctrlpipe(d->udev,0), | 64 | usb_rcvctrlpipe(d->udev,0), |
| 63 | TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | 65 | TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 64 | inbuf, 12, 2000) != 12) { | 66 | buf, 12, 2000) != 12) { |
| 65 | err("USB control message 'in' went wrong."); | 67 | err("USB control message 'in' went wrong."); |
| 66 | ret = -EIO; | 68 | ret = -EIO; |
| 67 | goto unlock; | 69 | goto unlock; |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | deb_xfer("in buffer: "); | 72 | deb_xfer("in buffer: "); |
| 71 | debug_dump(inbuf,12,deb_xfer); | 73 | debug_dump(buf, 12, deb_xfer); |
| 72 | 74 | ||
| 73 | if (in != NULL && inlen > 0) | 75 | if (in != NULL && inlen > 0) |
| 74 | memcpy(in,&inbuf[1],inlen); | 76 | memcpy(in, &buf[1], inlen); |
| 75 | 77 | ||
| 76 | unlock: | 78 | unlock: |
| 77 | mutex_unlock(&d->usb_mutex); | 79 | mutex_unlock(&d->usb_mutex); |
| @@ -222,8 +224,26 @@ static struct dvb_usb_device_properties vp7045_properties; | |||
| 222 | static int vp7045_usb_probe(struct usb_interface *intf, | 224 | static int vp7045_usb_probe(struct usb_interface *intf, |
| 223 | const struct usb_device_id *id) | 225 | const struct usb_device_id *id) |
| 224 | { | 226 | { |
| 225 | return dvb_usb_device_init(intf, &vp7045_properties, | 227 | struct dvb_usb_device *d; |
| 226 | THIS_MODULE, NULL, adapter_nr); | 228 | int ret = dvb_usb_device_init(intf, &vp7045_properties, |
| 229 | THIS_MODULE, &d, adapter_nr); | ||
| 230 | if (ret) | ||
| 231 | return ret; | ||
| 232 | |||
| 233 | d->priv = kmalloc(20, GFP_KERNEL); | ||
| 234 | if (!d->priv) { | ||
| 235 | dvb_usb_device_exit(intf); | ||
| 236 | return -ENOMEM; | ||
| 237 | } | ||
| 238 | |||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | |||
| 242 | static void vp7045_usb_disconnect(struct usb_interface *intf) | ||
| 243 | { | ||
| 244 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 245 | kfree(d->priv); | ||
| 246 | dvb_usb_device_exit(intf); | ||
| 227 | } | 247 | } |
| 228 | 248 | ||
| 229 | static struct usb_device_id vp7045_usb_table [] = { | 249 | static struct usb_device_id vp7045_usb_table [] = { |
| @@ -238,6 +258,7 @@ MODULE_DEVICE_TABLE(usb, vp7045_usb_table); | |||
| 238 | static struct dvb_usb_device_properties vp7045_properties = { | 258 | static struct dvb_usb_device_properties vp7045_properties = { |
| 239 | .usb_ctrl = CYPRESS_FX2, | 259 | .usb_ctrl = CYPRESS_FX2, |
| 240 | .firmware = "dvb-usb-vp7045-01.fw", | 260 | .firmware = "dvb-usb-vp7045-01.fw", |
| 261 | .size_of_priv = sizeof(u8 *), | ||
| 241 | 262 | ||
| 242 | .num_adapters = 1, | 263 | .num_adapters = 1, |
| 243 | .adapter = { | 264 | .adapter = { |
| @@ -284,7 +305,7 @@ static struct dvb_usb_device_properties vp7045_properties = { | |||
| 284 | static struct usb_driver vp7045_usb_driver = { | 305 | static struct usb_driver vp7045_usb_driver = { |
| 285 | .name = "dvb_usb_vp7045", | 306 | .name = "dvb_usb_vp7045", |
| 286 | .probe = vp7045_usb_probe, | 307 | .probe = vp7045_usb_probe, |
| 287 | .disconnect = dvb_usb_device_exit, | 308 | .disconnect = vp7045_usb_disconnect, |
| 288 | .id_table = vp7045_usb_table, | 309 | .id_table = vp7045_usb_table, |
| 289 | }; | 310 | }; |
| 290 | 311 | ||
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 83093d1f4f74..44b816f2601e 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
| @@ -263,18 +263,16 @@ config DVB_S5H1432 | |||
| 263 | help | 263 | help |
| 264 | A DVB-T tuner module. Say Y when you want to support this frontend. | 264 | A DVB-T tuner module. Say Y when you want to support this frontend. |
| 265 | 265 | ||
| 266 | config DVB_DRX397XD | 266 | config DVB_DRXD |
| 267 | tristate "Micronas DRX3975D/DRX3977D based" | 267 | tristate "Micronas DRXD driver" |
| 268 | depends on DVB_CORE && I2C | 268 | depends on DVB_CORE && I2C |
| 269 | default m if DVB_FE_CUSTOMISE | 269 | default m if DVB_FE_CUSTOMISE |
| 270 | help | 270 | help |
| 271 | A DVB-T tuner module. Say Y when you want to support this frontend. | 271 | A DVB-T tuner module. Say Y when you want to support this frontend. |
| 272 | 272 | ||
| 273 | TODO: | 273 | Note: this driver was based on vendor driver reference code (released |
| 274 | This driver needs external firmware. Please use the command | 274 | under the GPL) as opposed to the existing drx397xd driver, which |
| 275 | "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to | 275 | was written via reverse engineering. |
| 276 | download/extract them, and then copy them to /usr/lib/hotplug/firmware | ||
| 277 | or /lib/firmware (depending on configuration of firmware hotplug). | ||
| 278 | 276 | ||
| 279 | config DVB_L64781 | 277 | config DVB_L64781 |
| 280 | tristate "LSI L64781" | 278 | tristate "LSI L64781" |
| @@ -385,6 +383,13 @@ config DVB_STV0367 | |||
| 385 | help | 383 | help |
| 386 | A DVB-T/C tuner module. Say Y when you want to support this frontend. | 384 | A DVB-T/C tuner module. Say Y when you want to support this frontend. |
| 387 | 385 | ||
| 386 | config DVB_CXD2820R | ||
| 387 | tristate "Sony CXD2820R" | ||
| 388 | depends on DVB_CORE && I2C | ||
| 389 | default m if DVB_FE_CUSTOMISE | ||
| 390 | help | ||
| 391 | Say Y when you want to support this frontend. | ||
| 392 | |||
| 388 | comment "DVB-C (cable) frontends" | 393 | comment "DVB-C (cable) frontends" |
| 389 | depends on DVB_CORE | 394 | depends on DVB_CORE |
| 390 | 395 | ||
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 3b0c4bdc4b2b..2f3a6f736d64 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
| @@ -8,6 +8,8 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ | |||
| 8 | stb0899-objs = stb0899_drv.o stb0899_algo.o | 8 | stb0899-objs = stb0899_drv.o stb0899_algo.o |
| 9 | stv0900-objs = stv0900_core.o stv0900_sw.o | 9 | stv0900-objs = stv0900_core.o stv0900_sw.o |
| 10 | au8522-objs = au8522_dig.o au8522_decoder.o | 10 | au8522-objs = au8522_dig.o au8522_decoder.o |
| 11 | drxd-objs = drxd_firm.o drxd_hard.o | ||
| 12 | cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o | ||
| 11 | 13 | ||
| 12 | obj-$(CONFIG_DVB_PLL) += dvb-pll.o | 14 | obj-$(CONFIG_DVB_PLL) += dvb-pll.o |
| 13 | obj-$(CONFIG_DVB_STV0299) += stv0299.o | 15 | obj-$(CONFIG_DVB_STV0299) += stv0299.o |
| @@ -36,7 +38,7 @@ obj-$(CONFIG_DVB_ZL10036) += zl10036.o | |||
| 36 | obj-$(CONFIG_DVB_ZL10039) += zl10039.o | 38 | obj-$(CONFIG_DVB_ZL10039) += zl10039.o |
| 37 | obj-$(CONFIG_DVB_ZL10353) += zl10353.o | 39 | obj-$(CONFIG_DVB_ZL10353) += zl10353.o |
| 38 | obj-$(CONFIG_DVB_CX22702) += cx22702.o | 40 | obj-$(CONFIG_DVB_CX22702) += cx22702.o |
| 39 | obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o | 41 | obj-$(CONFIG_DVB_DRXD) += drxd.o |
| 40 | obj-$(CONFIG_DVB_TDA10021) += tda10021.o | 42 | obj-$(CONFIG_DVB_TDA10021) += tda10021.o |
| 41 | obj-$(CONFIG_DVB_TDA10023) += tda10023.o | 43 | obj-$(CONFIG_DVB_TDA10023) += tda10023.o |
| 42 | obj-$(CONFIG_DVB_STV0297) += stv0297.o | 44 | obj-$(CONFIG_DVB_STV0297) += stv0297.o |
| @@ -85,3 +87,5 @@ obj-$(CONFIG_DVB_MB86A16) += mb86a16.o | |||
| 85 | obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o | 87 | obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o |
| 86 | obj-$(CONFIG_DVB_IX2505V) += ix2505v.o | 88 | obj-$(CONFIG_DVB_IX2505V) += ix2505v.o |
| 87 | obj-$(CONFIG_DVB_STV0367) += stv0367.o | 89 | obj-$(CONFIG_DVB_STV0367) += stv0367.o |
| 90 | obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o | ||
| 91 | |||
diff --git a/drivers/media/dvb/frontends/bsbe1-d01a.h b/drivers/media/dvb/frontends/bsbe1-d01a.h new file mode 100644 index 000000000000..7ed3c424178c --- /dev/null +++ b/drivers/media/dvb/frontends/bsbe1-d01a.h | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | /* | ||
| 2 | * bsbe1-d01a.h - ALPS BSBE1-D01A tuner support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Oliver Endriss <o.endriss@gmx.de> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version 2 | ||
| 9 | * of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 22 | * | ||
| 23 | * | ||
| 24 | * the project's page is at http://www.linuxtv.org | ||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef BSBE1_D01A_H | ||
| 28 | #define BSBE1_D01A_H | ||
| 29 | |||
| 30 | #include "stb6000.h" | ||
| 31 | #include "stv0288.h" | ||
| 32 | |||
| 33 | static u8 stv0288_bsbe1_d01a_inittab[] = { | ||
| 34 | 0x01, 0x15, | ||
| 35 | 0x02, 0x20, | ||
| 36 | 0x09, 0x0, | ||
| 37 | 0x0a, 0x4, | ||
| 38 | 0x0b, 0x0, | ||
| 39 | 0x0c, 0x0, | ||
| 40 | 0x0d, 0x0, | ||
| 41 | 0x0e, 0xd4, | ||
| 42 | 0x0f, 0x30, | ||
| 43 | 0x11, 0x80, | ||
| 44 | 0x12, 0x03, | ||
| 45 | 0x13, 0x48, | ||
| 46 | 0x14, 0x84, | ||
| 47 | 0x15, 0x45, | ||
| 48 | 0x16, 0xb7, | ||
| 49 | 0x17, 0x9c, | ||
| 50 | 0x18, 0x0, | ||
| 51 | 0x19, 0xa6, | ||
| 52 | 0x1a, 0x88, | ||
| 53 | 0x1b, 0x8f, | ||
| 54 | 0x1c, 0xf0, | ||
| 55 | 0x20, 0x0b, | ||
| 56 | 0x21, 0x54, | ||
| 57 | 0x22, 0x0, | ||
| 58 | 0x23, 0x0, | ||
| 59 | 0x2b, 0xff, | ||
| 60 | 0x2c, 0xf7, | ||
| 61 | 0x30, 0x0, | ||
| 62 | 0x31, 0x1e, | ||
| 63 | 0x32, 0x14, | ||
| 64 | 0x33, 0x0f, | ||
| 65 | 0x34, 0x09, | ||
| 66 | 0x35, 0x0c, | ||
| 67 | 0x36, 0x05, | ||
| 68 | 0x37, 0x2f, | ||
| 69 | 0x38, 0x16, | ||
| 70 | 0x39, 0xbd, | ||
| 71 | 0x3a, 0x03, | ||
| 72 | 0x3b, 0x13, | ||
| 73 | 0x3c, 0x11, | ||
| 74 | 0x3d, 0x30, | ||
| 75 | 0x40, 0x63, | ||
| 76 | 0x41, 0x04, | ||
| 77 | 0x42, 0x60, | ||
| 78 | 0x43, 0x00, | ||
| 79 | 0x44, 0x00, | ||
| 80 | 0x45, 0x00, | ||
| 81 | 0x46, 0x00, | ||
| 82 | 0x47, 0x00, | ||
| 83 | 0x4a, 0x00, | ||
| 84 | 0x50, 0x10, | ||
| 85 | 0x51, 0x36, | ||
| 86 | 0x52, 0x09, | ||
| 87 | 0x53, 0x94, | ||
| 88 | 0x54, 0x62, | ||
| 89 | 0x55, 0x29, | ||
| 90 | 0x56, 0x64, | ||
| 91 | 0x57, 0x2b, | ||
| 92 | 0x58, 0x54, | ||
| 93 | 0x59, 0x86, | ||
| 94 | 0x5a, 0x0, | ||
| 95 | 0x5b, 0x9b, | ||
| 96 | 0x5c, 0x08, | ||
| 97 | 0x5d, 0x7f, | ||
| 98 | 0x5e, 0x0, | ||
| 99 | 0x5f, 0xff, | ||
| 100 | 0x70, 0x0, | ||
| 101 | 0x71, 0x0, | ||
| 102 | 0x72, 0x0, | ||
| 103 | 0x74, 0x0, | ||
| 104 | 0x75, 0x0, | ||
| 105 | 0x76, 0x0, | ||
| 106 | 0x81, 0x0, | ||
| 107 | 0x82, 0x3f, | ||
| 108 | 0x83, 0x3f, | ||
| 109 | 0x84, 0x0, | ||
| 110 | 0x85, 0x0, | ||
| 111 | 0x88, 0x0, | ||
| 112 | 0x89, 0x0, | ||
| 113 | 0x8a, 0x0, | ||
| 114 | 0x8b, 0x0, | ||
| 115 | 0x8c, 0x0, | ||
| 116 | 0x90, 0x0, | ||
| 117 | 0x91, 0x0, | ||
| 118 | 0x92, 0x0, | ||
| 119 | 0x93, 0x0, | ||
| 120 | 0x94, 0x1c, | ||
| 121 | 0x97, 0x0, | ||
| 122 | 0xa0, 0x48, | ||
| 123 | 0xa1, 0x0, | ||
| 124 | 0xb0, 0xb8, | ||
| 125 | 0xb1, 0x3a, | ||
| 126 | 0xb2, 0x10, | ||
| 127 | 0xb3, 0x82, | ||
| 128 | 0xb4, 0x80, | ||
| 129 | 0xb5, 0x82, | ||
| 130 | 0xb6, 0x82, | ||
| 131 | 0xb7, 0x82, | ||
| 132 | 0xb8, 0x20, | ||
| 133 | 0xb9, 0x0, | ||
| 134 | 0xf0, 0x0, | ||
| 135 | 0xf1, 0x0, | ||
| 136 | 0xf2, 0xc0, | ||
| 137 | 0xff, 0xff, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static struct stv0288_config stv0288_bsbe1_d01a_config = { | ||
| 141 | .demod_address = 0x68, | ||
| 142 | .min_delay_ms = 100, | ||
| 143 | .inittab = stv0288_bsbe1_d01a_inittab, | ||
| 144 | }; | ||
| 145 | |||
| 146 | #endif | ||
diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h index 45a6dfd8ebb5..c480c839b302 100644 --- a/drivers/media/dvb/frontends/bsru6.h +++ b/drivers/media/dvb/frontends/bsru6.h | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | static u8 alps_bsru6_inittab[] = { | 28 | static u8 alps_bsru6_inittab[] = { |
| 29 | 0x01, 0x15, | 29 | 0x01, 0x15, |
| 30 | 0x02, 0x00, | 30 | 0x02, 0x30, |
| 31 | 0x03, 0x00, | 31 | 0x03, 0x00, |
| 32 | 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ | 32 | 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ |
| 33 | 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ | 33 | 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ |
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index 2410d8b59b6b..95c6465b87a1 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c | |||
| @@ -137,7 +137,7 @@ MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\ | |||
| 137 | /* SNR measurements */ | 137 | /* SNR measurements */ |
| 138 | static int esno_snr; | 138 | static int esno_snr; |
| 139 | module_param(esno_snr, int, 0644); | 139 | module_param(esno_snr, int, 0644); |
| 140 | MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\ | 140 | MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\ |
| 141 | "1=ESNO(db * 10) (default:0)"); | 141 | "1=ESNO(db * 10) (default:0)"); |
| 142 | 142 | ||
| 143 | enum cmds { | 143 | enum cmds { |
| @@ -566,7 +566,7 @@ static int cx24116_load_firmware(struct dvb_frontend *fe, | |||
| 566 | { | 566 | { |
| 567 | struct cx24116_state *state = fe->demodulator_priv; | 567 | struct cx24116_state *state = fe->demodulator_priv; |
| 568 | struct cx24116_cmd cmd; | 568 | struct cx24116_cmd cmd; |
| 569 | int i, ret; | 569 | int i, ret, len, max, remaining; |
| 570 | unsigned char vers[4]; | 570 | unsigned char vers[4]; |
| 571 | 571 | ||
| 572 | dprintk("%s\n", __func__); | 572 | dprintk("%s\n", __func__); |
| @@ -603,8 +603,21 @@ static int cx24116_load_firmware(struct dvb_frontend *fe, | |||
| 603 | cx24116_writereg(state, 0xF5, 0x00); | 603 | cx24116_writereg(state, 0xF5, 0x00); |
| 604 | cx24116_writereg(state, 0xF6, 0x00); | 604 | cx24116_writereg(state, 0xF6, 0x00); |
| 605 | 605 | ||
| 606 | /* write the entire firmware as one transaction */ | 606 | /* Split firmware to the max I2C write len and write. |
| 607 | cx24116_writeregN(state, 0xF7, fw->data, fw->size); | 607 | * Writes whole firmware as one write when i2c_wr_max is set to 0. */ |
| 608 | if (state->config->i2c_wr_max) | ||
| 609 | max = state->config->i2c_wr_max; | ||
| 610 | else | ||
| 611 | max = INT_MAX; /* enough for 32k firmware */ | ||
| 612 | |||
| 613 | for (remaining = fw->size; remaining > 0; remaining -= max - 1) { | ||
| 614 | len = remaining; | ||
| 615 | if (len > max - 1) | ||
| 616 | len = max - 1; | ||
| 617 | |||
| 618 | cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining], | ||
| 619 | len); | ||
| 620 | } | ||
| 608 | 621 | ||
| 609 | cx24116_writereg(state, 0xF4, 0x10); | 622 | cx24116_writereg(state, 0xF4, 0x10); |
| 610 | cx24116_writereg(state, 0xF0, 0x00); | 623 | cx24116_writereg(state, 0xF0, 0x00); |
diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h index b1b76b47a14c..7d90ab949c03 100644 --- a/drivers/media/dvb/frontends/cx24116.h +++ b/drivers/media/dvb/frontends/cx24116.h | |||
| @@ -35,6 +35,9 @@ struct cx24116_config { | |||
| 35 | 35 | ||
| 36 | /* Need to set MPEG parameters */ | 36 | /* Need to set MPEG parameters */ |
| 37 | u8 mpg_clk_pos_pol:0x02; | 37 | u8 mpg_clk_pos_pol:0x02; |
| 38 | |||
| 39 | /* max bytes I2C provider can write at once */ | ||
| 40 | u16 i2c_wr_max; | ||
| 38 | }; | 41 | }; |
| 39 | 42 | ||
| 40 | #if defined(CONFIG_DVB_CX24116) || \ | 43 | #if defined(CONFIG_DVB_CX24116) || \ |
diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h new file mode 100644 index 000000000000..ad17845123d9 --- /dev/null +++ b/drivers/media/dvb/frontends/cxd2820r.h | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | /* | ||
| 2 | * Sony CXD2820R demodulator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | |||
| 22 | #ifndef CXD2820R_H | ||
| 23 | #define CXD2820R_H | ||
| 24 | |||
| 25 | #include <linux/dvb/frontend.h> | ||
| 26 | |||
| 27 | #define CXD2820R_GPIO_D (0 << 0) /* disable */ | ||
| 28 | #define CXD2820R_GPIO_E (1 << 0) /* enable */ | ||
| 29 | #define CXD2820R_GPIO_O (0 << 1) /* output */ | ||
| 30 | #define CXD2820R_GPIO_I (1 << 1) /* input */ | ||
| 31 | #define CXD2820R_GPIO_L (0 << 2) /* output low */ | ||
| 32 | #define CXD2820R_GPIO_H (1 << 2) /* output high */ | ||
| 33 | |||
| 34 | #define CXD2820R_TS_SERIAL 0x08 | ||
| 35 | #define CXD2820R_TS_SERIAL_MSB 0x28 | ||
| 36 | #define CXD2820R_TS_PARALLEL 0x30 | ||
| 37 | #define CXD2820R_TS_PARALLEL_MSB 0x70 | ||
| 38 | |||
| 39 | struct cxd2820r_config { | ||
| 40 | /* Demodulator I2C address. | ||
| 41 | * Driver determines DVB-C slave I2C address automatically from master | ||
| 42 | * address. | ||
| 43 | * Default: none, must set | ||
| 44 | * Values: 0x6c, 0x6d | ||
| 45 | */ | ||
| 46 | u8 i2c_address; | ||
| 47 | |||
| 48 | /* TS output mode. | ||
| 49 | * Default: none, must set. | ||
| 50 | * Values: | ||
| 51 | */ | ||
| 52 | u8 ts_mode; | ||
| 53 | |||
| 54 | /* IF AGC polarity. | ||
| 55 | * Default: 0 | ||
| 56 | * Values: 0, 1 | ||
| 57 | */ | ||
| 58 | int if_agc_polarity:1; | ||
| 59 | |||
| 60 | /* Spectrum inversion. | ||
| 61 | * Default: 0 | ||
| 62 | * Values: 0, 1 | ||
| 63 | */ | ||
| 64 | int spec_inv:1; | ||
| 65 | |||
| 66 | /* IFs for all used modes. | ||
| 67 | * Default: none, must set | ||
| 68 | * Values: <kHz> | ||
| 69 | */ | ||
| 70 | u16 if_dvbt_6; | ||
| 71 | u16 if_dvbt_7; | ||
| 72 | u16 if_dvbt_8; | ||
| 73 | u16 if_dvbt2_5; | ||
| 74 | u16 if_dvbt2_6; | ||
| 75 | u16 if_dvbt2_7; | ||
| 76 | u16 if_dvbt2_8; | ||
| 77 | u16 if_dvbc; | ||
| 78 | |||
| 79 | /* GPIOs for all used modes. | ||
| 80 | * Default: none, disabled | ||
| 81 | * Values: <see above> | ||
| 82 | */ | ||
| 83 | u8 gpio_dvbt[3]; | ||
| 84 | u8 gpio_dvbt2[3]; | ||
| 85 | u8 gpio_dvbc[3]; | ||
| 86 | }; | ||
| 87 | |||
| 88 | |||
| 89 | #if defined(CONFIG_DVB_CXD2820R) || \ | ||
| 90 | (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE)) | ||
| 91 | extern struct dvb_frontend *cxd2820r_attach( | ||
| 92 | const struct cxd2820r_config *config, | ||
| 93 | struct i2c_adapter *i2c, | ||
| 94 | struct dvb_frontend *fe | ||
| 95 | ); | ||
| 96 | extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter( | ||
| 97 | struct dvb_frontend *fe | ||
| 98 | ); | ||
| 99 | #else | ||
| 100 | static inline struct dvb_frontend *cxd2820r_attach( | ||
| 101 | const struct cxd2820r_config *config, | ||
| 102 | struct i2c_adapter *i2c, | ||
| 103 | struct dvb_frontend *fe | ||
| 104 | ) | ||
| 105 | { | ||
| 106 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 107 | return NULL; | ||
| 108 | } | ||
| 109 | static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter( | ||
| 110 | struct dvb_frontend *fe | ||
| 111 | ) | ||
| 112 | { | ||
| 113 | return NULL; | ||
| 114 | } | ||
| 115 | |||
| 116 | #endif | ||
| 117 | |||
| 118 | #endif /* CXD2820R_H */ | ||
diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb/frontends/cxd2820r_c.c new file mode 100644 index 000000000000..3c07d400731d --- /dev/null +++ b/drivers/media/dvb/frontends/cxd2820r_c.c | |||
| @@ -0,0 +1,338 @@ | |||
| 1 | /* | ||
| 2 | * Sony CXD2820R demodulator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | |||
| 22 | #include "cxd2820r_priv.h" | ||
| 23 | |||
| 24 | int cxd2820r_set_frontend_c(struct dvb_frontend *fe, | ||
| 25 | struct dvb_frontend_parameters *params) | ||
| 26 | { | ||
| 27 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 28 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 29 | int ret, i; | ||
| 30 | u8 buf[2]; | ||
| 31 | u16 if_ctl; | ||
| 32 | u64 num; | ||
| 33 | struct reg_val_mask tab[] = { | ||
| 34 | { 0x00080, 0x01, 0xff }, | ||
| 35 | { 0x00081, 0x05, 0xff }, | ||
| 36 | { 0x00085, 0x07, 0xff }, | ||
| 37 | { 0x00088, 0x01, 0xff }, | ||
| 38 | |||
| 39 | { 0x00082, 0x20, 0x60 }, | ||
| 40 | { 0x1016a, 0x48, 0xff }, | ||
| 41 | { 0x100a5, 0x00, 0x01 }, | ||
| 42 | { 0x10020, 0x06, 0x07 }, | ||
| 43 | { 0x10059, 0x50, 0xff }, | ||
| 44 | { 0x10087, 0x0c, 0x3c }, | ||
| 45 | { 0x1008b, 0x07, 0xff }, | ||
| 46 | { 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 }, | ||
| 47 | { 0x10070, priv->cfg.ts_mode, 0xff }, | ||
| 48 | }; | ||
| 49 | |||
| 50 | dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate); | ||
| 51 | |||
| 52 | /* update GPIOs */ | ||
| 53 | ret = cxd2820r_gpio(fe); | ||
| 54 | if (ret) | ||
| 55 | goto error; | ||
| 56 | |||
| 57 | /* program tuner */ | ||
| 58 | if (fe->ops.tuner_ops.set_params) | ||
| 59 | fe->ops.tuner_ops.set_params(fe, params); | ||
| 60 | |||
| 61 | if (priv->delivery_system != SYS_DVBC_ANNEX_AC) { | ||
| 62 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
| 63 | ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, | ||
| 64 | tab[i].val, tab[i].mask); | ||
| 65 | if (ret) | ||
| 66 | goto error; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | priv->delivery_system = SYS_DVBC_ANNEX_AC; | ||
| 71 | priv->ber_running = 0; /* tune stops BER counter */ | ||
| 72 | |||
| 73 | num = priv->cfg.if_dvbc; | ||
| 74 | num *= 0x4000; | ||
| 75 | if_ctl = cxd2820r_div_u64_round_closest(num, 41000); | ||
| 76 | buf[0] = (if_ctl >> 8) & 0x3f; | ||
| 77 | buf[1] = (if_ctl >> 0) & 0xff; | ||
| 78 | |||
| 79 | ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2); | ||
| 80 | if (ret) | ||
| 81 | goto error; | ||
| 82 | |||
| 83 | ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); | ||
| 84 | if (ret) | ||
| 85 | goto error; | ||
| 86 | |||
| 87 | ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); | ||
| 88 | if (ret) | ||
| 89 | goto error; | ||
| 90 | |||
| 91 | return ret; | ||
| 92 | error: | ||
| 93 | dbg("%s: failed:%d", __func__, ret); | ||
| 94 | return ret; | ||
| 95 | } | ||
| 96 | |||
| 97 | int cxd2820r_get_frontend_c(struct dvb_frontend *fe, | ||
| 98 | struct dvb_frontend_parameters *p) | ||
| 99 | { | ||
| 100 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 101 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 102 | int ret; | ||
| 103 | u8 buf[2]; | ||
| 104 | |||
| 105 | ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2); | ||
| 106 | if (ret) | ||
| 107 | goto error; | ||
| 108 | |||
| 109 | c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]); | ||
| 110 | |||
| 111 | ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]); | ||
| 112 | if (ret) | ||
| 113 | goto error; | ||
| 114 | |||
| 115 | switch ((buf[0] >> 0) & 0x03) { | ||
| 116 | case 0: | ||
| 117 | c->modulation = QAM_16; | ||
| 118 | break; | ||
| 119 | case 1: | ||
| 120 | c->modulation = QAM_32; | ||
| 121 | break; | ||
| 122 | case 2: | ||
| 123 | c->modulation = QAM_64; | ||
| 124 | break; | ||
| 125 | case 3: | ||
| 126 | c->modulation = QAM_128; | ||
| 127 | break; | ||
| 128 | case 4: | ||
| 129 | c->modulation = QAM_256; | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | |||
| 133 | switch ((buf[0] >> 7) & 0x01) { | ||
| 134 | case 0: | ||
| 135 | c->inversion = INVERSION_OFF; | ||
| 136 | break; | ||
| 137 | case 1: | ||
| 138 | c->inversion = INVERSION_ON; | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | return ret; | ||
| 143 | error: | ||
| 144 | dbg("%s: failed:%d", __func__, ret); | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | |||
| 148 | int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber) | ||
| 149 | { | ||
| 150 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 151 | int ret; | ||
| 152 | u8 buf[3], start_ber = 0; | ||
| 153 | *ber = 0; | ||
| 154 | |||
| 155 | if (priv->ber_running) { | ||
| 156 | ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf)); | ||
| 157 | if (ret) | ||
| 158 | goto error; | ||
| 159 | |||
| 160 | if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) { | ||
| 161 | *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0]; | ||
| 162 | start_ber = 1; | ||
| 163 | } | ||
| 164 | } else { | ||
| 165 | priv->ber_running = 1; | ||
| 166 | start_ber = 1; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (start_ber) { | ||
| 170 | /* (re)start BER */ | ||
| 171 | ret = cxd2820r_wr_reg(priv, 0x10079, 0x01); | ||
| 172 | if (ret) | ||
| 173 | goto error; | ||
| 174 | } | ||
| 175 | |||
| 176 | return ret; | ||
| 177 | error: | ||
| 178 | dbg("%s: failed:%d", __func__, ret); | ||
| 179 | return ret; | ||
| 180 | } | ||
| 181 | |||
| 182 | int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, | ||
| 183 | u16 *strength) | ||
| 184 | { | ||
| 185 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 186 | int ret; | ||
| 187 | u8 buf[2]; | ||
| 188 | u16 tmp; | ||
| 189 | |||
| 190 | ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf)); | ||
| 191 | if (ret) | ||
| 192 | goto error; | ||
| 193 | |||
| 194 | tmp = (buf[0] & 0x03) << 8 | buf[1]; | ||
| 195 | tmp = (~tmp & 0x03ff); | ||
| 196 | |||
| 197 | if (tmp == 512) | ||
| 198 | /* ~no signal */ | ||
| 199 | tmp = 0; | ||
| 200 | else if (tmp > 350) | ||
| 201 | tmp = 350; | ||
| 202 | |||
| 203 | /* scale value to 0x0000-0xffff */ | ||
| 204 | *strength = tmp * 0xffff / (350-0); | ||
| 205 | |||
| 206 | return ret; | ||
| 207 | error: | ||
| 208 | dbg("%s: failed:%d", __func__, ret); | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | |||
| 212 | int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr) | ||
| 213 | { | ||
| 214 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 215 | int ret; | ||
| 216 | u8 tmp; | ||
| 217 | unsigned int A, B; | ||
| 218 | /* report SNR in dB * 10 */ | ||
| 219 | |||
| 220 | ret = cxd2820r_rd_reg(priv, 0x10019, &tmp); | ||
| 221 | if (ret) | ||
| 222 | goto error; | ||
| 223 | |||
| 224 | if (((tmp >> 0) & 0x03) % 2) { | ||
| 225 | A = 875; | ||
| 226 | B = 650; | ||
| 227 | } else { | ||
| 228 | A = 950; | ||
| 229 | B = 760; | ||
| 230 | } | ||
| 231 | |||
| 232 | ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp); | ||
| 233 | if (ret) | ||
| 234 | goto error; | ||
| 235 | |||
| 236 | #define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */ | ||
| 237 | if (tmp) | ||
| 238 | *snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5) | ||
| 239 | / 10; | ||
| 240 | else | ||
| 241 | *snr = 0; | ||
| 242 | |||
| 243 | return ret; | ||
| 244 | error: | ||
| 245 | dbg("%s: failed:%d", __func__, ret); | ||
| 246 | return ret; | ||
| 247 | } | ||
| 248 | |||
| 249 | int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 250 | { | ||
| 251 | *ucblocks = 0; | ||
| 252 | /* no way to read ? */ | ||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status) | ||
| 257 | { | ||
| 258 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 259 | int ret; | ||
| 260 | u8 buf[2]; | ||
| 261 | *status = 0; | ||
| 262 | |||
| 263 | ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf)); | ||
| 264 | if (ret) | ||
| 265 | goto error; | ||
| 266 | |||
| 267 | if (((buf[0] >> 0) & 0x01) == 1) { | ||
| 268 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
| 269 | FE_HAS_VITERBI | FE_HAS_SYNC; | ||
| 270 | |||
| 271 | if (((buf[1] >> 3) & 0x01) == 1) { | ||
| 272 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
| 273 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]); | ||
| 278 | |||
| 279 | return ret; | ||
| 280 | error: | ||
| 281 | dbg("%s: failed:%d", __func__, ret); | ||
| 282 | return ret; | ||
| 283 | } | ||
| 284 | |||
| 285 | int cxd2820r_init_c(struct dvb_frontend *fe) | ||
| 286 | { | ||
| 287 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 288 | int ret; | ||
| 289 | |||
| 290 | ret = cxd2820r_wr_reg(priv, 0x00085, 0x07); | ||
| 291 | if (ret) | ||
| 292 | goto error; | ||
| 293 | |||
| 294 | return ret; | ||
| 295 | error: | ||
| 296 | dbg("%s: failed:%d", __func__, ret); | ||
| 297 | return ret; | ||
| 298 | } | ||
| 299 | |||
| 300 | int cxd2820r_sleep_c(struct dvb_frontend *fe) | ||
| 301 | { | ||
| 302 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 303 | int ret, i; | ||
| 304 | struct reg_val_mask tab[] = { | ||
| 305 | { 0x000ff, 0x1f, 0xff }, | ||
| 306 | { 0x00085, 0x00, 0xff }, | ||
| 307 | { 0x00088, 0x01, 0xff }, | ||
| 308 | { 0x00081, 0x00, 0xff }, | ||
| 309 | { 0x00080, 0x00, 0xff }, | ||
| 310 | }; | ||
| 311 | |||
| 312 | dbg("%s", __func__); | ||
| 313 | |||
| 314 | priv->delivery_system = SYS_UNDEFINED; | ||
| 315 | |||
| 316 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
| 317 | ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, | ||
| 318 | tab[i].mask); | ||
| 319 | if (ret) | ||
| 320 | goto error; | ||
| 321 | } | ||
| 322 | |||
| 323 | return ret; | ||
| 324 | error: | ||
| 325 | dbg("%s: failed:%d", __func__, ret); | ||
| 326 | return ret; | ||
| 327 | } | ||
| 328 | |||
| 329 | int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, | ||
| 330 | struct dvb_frontend_tune_settings *s) | ||
| 331 | { | ||
| 332 | s->min_delay_ms = 500; | ||
| 333 | s->step_size = 0; /* no zigzag */ | ||
| 334 | s->max_drift = 0; | ||
| 335 | |||
| 336 | return 0; | ||
| 337 | } | ||
| 338 | |||
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c new file mode 100644 index 000000000000..0779f69db793 --- /dev/null +++ b/drivers/media/dvb/frontends/cxd2820r_core.c | |||
| @@ -0,0 +1,915 @@ | |||
| 1 | /* | ||
| 2 | * Sony CXD2820R demodulator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | |||
| 22 | #include "cxd2820r_priv.h" | ||
| 23 | |||
| 24 | int cxd2820r_debug; | ||
| 25 | module_param_named(debug, cxd2820r_debug, int, 0644); | ||
| 26 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
| 27 | |||
| 28 | /* write multiple registers */ | ||
| 29 | static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, | ||
| 30 | u8 *val, int len) | ||
| 31 | { | ||
| 32 | int ret; | ||
| 33 | u8 buf[len+1]; | ||
| 34 | struct i2c_msg msg[1] = { | ||
| 35 | { | ||
| 36 | .addr = i2c, | ||
| 37 | .flags = 0, | ||
| 38 | .len = sizeof(buf), | ||
| 39 | .buf = buf, | ||
| 40 | } | ||
| 41 | }; | ||
| 42 | |||
| 43 | buf[0] = reg; | ||
| 44 | memcpy(&buf[1], val, len); | ||
| 45 | |||
| 46 | ret = i2c_transfer(priv->i2c, msg, 1); | ||
| 47 | if (ret == 1) { | ||
| 48 | ret = 0; | ||
| 49 | } else { | ||
| 50 | warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
| 51 | ret = -EREMOTEIO; | ||
| 52 | } | ||
| 53 | return ret; | ||
| 54 | } | ||
| 55 | |||
| 56 | /* read multiple registers */ | ||
| 57 | static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, | ||
| 58 | u8 *val, int len) | ||
| 59 | { | ||
| 60 | int ret; | ||
| 61 | u8 buf[len]; | ||
| 62 | struct i2c_msg msg[2] = { | ||
| 63 | { | ||
| 64 | .addr = i2c, | ||
| 65 | .flags = 0, | ||
| 66 | .len = 1, | ||
| 67 | .buf = ®, | ||
| 68 | }, { | ||
| 69 | .addr = i2c, | ||
| 70 | .flags = I2C_M_RD, | ||
| 71 | .len = sizeof(buf), | ||
| 72 | .buf = buf, | ||
| 73 | } | ||
| 74 | }; | ||
| 75 | |||
| 76 | ret = i2c_transfer(priv->i2c, msg, 2); | ||
| 77 | if (ret == 2) { | ||
| 78 | memcpy(val, buf, len); | ||
| 79 | ret = 0; | ||
| 80 | } else { | ||
| 81 | warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
| 82 | ret = -EREMOTEIO; | ||
| 83 | } | ||
| 84 | |||
| 85 | return ret; | ||
| 86 | } | ||
| 87 | |||
| 88 | /* write multiple registers */ | ||
| 89 | int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | ||
| 90 | int len) | ||
| 91 | { | ||
| 92 | int ret; | ||
| 93 | u8 i2c_addr; | ||
| 94 | u8 reg = (reginfo >> 0) & 0xff; | ||
| 95 | u8 bank = (reginfo >> 8) & 0xff; | ||
| 96 | u8 i2c = (reginfo >> 16) & 0x01; | ||
| 97 | |||
| 98 | /* select I2C */ | ||
| 99 | if (i2c) | ||
| 100 | i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */ | ||
| 101 | else | ||
| 102 | i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */ | ||
| 103 | |||
| 104 | /* switch bank if needed */ | ||
| 105 | if (bank != priv->bank[i2c]) { | ||
| 106 | ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1); | ||
| 107 | if (ret) | ||
| 108 | return ret; | ||
| 109 | priv->bank[i2c] = bank; | ||
| 110 | } | ||
| 111 | return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len); | ||
| 112 | } | ||
| 113 | |||
| 114 | /* read multiple registers */ | ||
| 115 | int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | ||
| 116 | int len) | ||
| 117 | { | ||
| 118 | int ret; | ||
| 119 | u8 i2c_addr; | ||
| 120 | u8 reg = (reginfo >> 0) & 0xff; | ||
| 121 | u8 bank = (reginfo >> 8) & 0xff; | ||
| 122 | u8 i2c = (reginfo >> 16) & 0x01; | ||
| 123 | |||
| 124 | /* select I2C */ | ||
| 125 | if (i2c) | ||
| 126 | i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */ | ||
| 127 | else | ||
| 128 | i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */ | ||
| 129 | |||
| 130 | /* switch bank if needed */ | ||
| 131 | if (bank != priv->bank[i2c]) { | ||
| 132 | ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1); | ||
| 133 | if (ret) | ||
| 134 | return ret; | ||
| 135 | priv->bank[i2c] = bank; | ||
| 136 | } | ||
| 137 | return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len); | ||
| 138 | } | ||
| 139 | |||
| 140 | /* write single register */ | ||
| 141 | int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val) | ||
| 142 | { | ||
| 143 | return cxd2820r_wr_regs(priv, reg, &val, 1); | ||
| 144 | } | ||
| 145 | |||
| 146 | /* read single register */ | ||
| 147 | int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val) | ||
| 148 | { | ||
| 149 | return cxd2820r_rd_regs(priv, reg, val, 1); | ||
| 150 | } | ||
| 151 | |||
| 152 | /* write single register with mask */ | ||
| 153 | int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, | ||
| 154 | u8 mask) | ||
| 155 | { | ||
| 156 | int ret; | ||
| 157 | u8 tmp; | ||
| 158 | |||
| 159 | /* no need for read if whole reg is written */ | ||
| 160 | if (mask != 0xff) { | ||
| 161 | ret = cxd2820r_rd_reg(priv, reg, &tmp); | ||
| 162 | if (ret) | ||
| 163 | return ret; | ||
| 164 | |||
| 165 | val &= mask; | ||
| 166 | tmp &= ~mask; | ||
| 167 | val |= tmp; | ||
| 168 | } | ||
| 169 | |||
| 170 | return cxd2820r_wr_reg(priv, reg, val); | ||
| 171 | } | ||
| 172 | |||
| 173 | int cxd2820r_gpio(struct dvb_frontend *fe) | ||
| 174 | { | ||
| 175 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 176 | int ret, i; | ||
| 177 | u8 *gpio, tmp0, tmp1; | ||
| 178 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 179 | |||
| 180 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 181 | case SYS_DVBT: | ||
| 182 | gpio = priv->cfg.gpio_dvbt; | ||
| 183 | break; | ||
| 184 | case SYS_DVBT2: | ||
| 185 | gpio = priv->cfg.gpio_dvbt2; | ||
| 186 | break; | ||
| 187 | case SYS_DVBC_ANNEX_AC: | ||
| 188 | gpio = priv->cfg.gpio_dvbc; | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | ret = -EINVAL; | ||
| 192 | goto error; | ||
| 193 | } | ||
| 194 | |||
| 195 | /* update GPIOs only when needed */ | ||
| 196 | if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio))) | ||
| 197 | return 0; | ||
| 198 | |||
| 199 | tmp0 = 0x00; | ||
| 200 | tmp1 = 0x00; | ||
| 201 | for (i = 0; i < sizeof(priv->gpio); i++) { | ||
| 202 | /* enable / disable */ | ||
| 203 | if (gpio[i] & CXD2820R_GPIO_E) | ||
| 204 | tmp0 |= (2 << 6) >> (2 * i); | ||
| 205 | else | ||
| 206 | tmp0 |= (1 << 6) >> (2 * i); | ||
| 207 | |||
| 208 | /* input / output */ | ||
| 209 | if (gpio[i] & CXD2820R_GPIO_I) | ||
| 210 | tmp1 |= (1 << (3 + i)); | ||
| 211 | else | ||
| 212 | tmp1 |= (0 << (3 + i)); | ||
| 213 | |||
| 214 | /* high / low */ | ||
| 215 | if (gpio[i] & CXD2820R_GPIO_H) | ||
| 216 | tmp1 |= (1 << (0 + i)); | ||
| 217 | else | ||
| 218 | tmp1 |= (0 << (0 + i)); | ||
| 219 | |||
| 220 | dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1); | ||
| 221 | } | ||
| 222 | |||
| 223 | dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1); | ||
| 224 | |||
| 225 | /* write bits [7:2] */ | ||
| 226 | ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc); | ||
| 227 | if (ret) | ||
| 228 | goto error; | ||
| 229 | |||
| 230 | /* write bits [5:0] */ | ||
| 231 | ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f); | ||
| 232 | if (ret) | ||
| 233 | goto error; | ||
| 234 | |||
| 235 | memcpy(priv->gpio, gpio, sizeof(priv->gpio)); | ||
| 236 | |||
| 237 | return ret; | ||
| 238 | error: | ||
| 239 | dbg("%s: failed:%d", __func__, ret); | ||
| 240 | return ret; | ||
| 241 | } | ||
| 242 | |||
| 243 | /* lock FE */ | ||
| 244 | static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe) | ||
| 245 | { | ||
| 246 | int ret = 0; | ||
| 247 | dbg("%s: active_fe=%d", __func__, active_fe); | ||
| 248 | |||
| 249 | mutex_lock(&priv->fe_lock); | ||
| 250 | |||
| 251 | /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */ | ||
| 252 | if (priv->active_fe == active_fe) | ||
| 253 | ; | ||
| 254 | else if (priv->active_fe == -1) | ||
| 255 | priv->active_fe = active_fe; | ||
| 256 | else | ||
| 257 | ret = -EBUSY; | ||
| 258 | |||
| 259 | mutex_unlock(&priv->fe_lock); | ||
| 260 | |||
| 261 | return ret; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* unlock FE */ | ||
| 265 | static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe) | ||
| 266 | { | ||
| 267 | dbg("%s: active_fe=%d", __func__, active_fe); | ||
| 268 | |||
| 269 | mutex_lock(&priv->fe_lock); | ||
| 270 | |||
| 271 | /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */ | ||
| 272 | if (priv->active_fe == active_fe) | ||
| 273 | priv->active_fe = -1; | ||
| 274 | |||
| 275 | mutex_unlock(&priv->fe_lock); | ||
| 276 | |||
| 277 | return; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */ | ||
| 281 | u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor) | ||
| 282 | { | ||
| 283 | return div_u64(dividend + (divisor / 2), divisor); | ||
| 284 | } | ||
| 285 | |||
| 286 | static int cxd2820r_set_frontend(struct dvb_frontend *fe, | ||
| 287 | struct dvb_frontend_parameters *p) | ||
| 288 | { | ||
| 289 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 290 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 291 | int ret; | ||
| 292 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 293 | |||
| 294 | if (fe->ops.info.type == FE_OFDM) { | ||
| 295 | /* DVB-T/T2 */ | ||
| 296 | ret = cxd2820r_lock(priv, 0); | ||
| 297 | if (ret) | ||
| 298 | return ret; | ||
| 299 | |||
| 300 | switch (priv->delivery_system) { | ||
| 301 | case SYS_UNDEFINED: | ||
| 302 | if (c->delivery_system == SYS_DVBT) { | ||
| 303 | /* SLEEP => DVB-T */ | ||
| 304 | ret = cxd2820r_set_frontend_t(fe, p); | ||
| 305 | } else { | ||
| 306 | /* SLEEP => DVB-T2 */ | ||
| 307 | ret = cxd2820r_set_frontend_t2(fe, p); | ||
| 308 | } | ||
| 309 | break; | ||
| 310 | case SYS_DVBT: | ||
| 311 | if (c->delivery_system == SYS_DVBT) { | ||
| 312 | /* DVB-T => DVB-T */ | ||
| 313 | ret = cxd2820r_set_frontend_t(fe, p); | ||
| 314 | } else if (c->delivery_system == SYS_DVBT2) { | ||
| 315 | /* DVB-T => DVB-T2 */ | ||
| 316 | ret = cxd2820r_sleep_t(fe); | ||
| 317 | ret = cxd2820r_set_frontend_t2(fe, p); | ||
| 318 | } | ||
| 319 | break; | ||
| 320 | case SYS_DVBT2: | ||
| 321 | if (c->delivery_system == SYS_DVBT2) { | ||
| 322 | /* DVB-T2 => DVB-T2 */ | ||
| 323 | ret = cxd2820r_set_frontend_t2(fe, p); | ||
| 324 | } else if (c->delivery_system == SYS_DVBT) { | ||
| 325 | /* DVB-T2 => DVB-T */ | ||
| 326 | ret = cxd2820r_sleep_t2(fe); | ||
| 327 | ret = cxd2820r_set_frontend_t(fe, p); | ||
| 328 | } | ||
| 329 | break; | ||
| 330 | default: | ||
| 331 | dbg("%s: error state=%d", __func__, | ||
| 332 | priv->delivery_system); | ||
| 333 | ret = -EINVAL; | ||
| 334 | } | ||
| 335 | } else { | ||
| 336 | /* DVB-C */ | ||
| 337 | ret = cxd2820r_lock(priv, 1); | ||
| 338 | if (ret) | ||
| 339 | return ret; | ||
| 340 | |||
| 341 | ret = cxd2820r_set_frontend_c(fe, p); | ||
| 342 | } | ||
| 343 | |||
| 344 | return ret; | ||
| 345 | } | ||
| 346 | |||
| 347 | static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
| 348 | { | ||
| 349 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 350 | int ret; | ||
| 351 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 352 | |||
| 353 | if (fe->ops.info.type == FE_OFDM) { | ||
| 354 | /* DVB-T/T2 */ | ||
| 355 | ret = cxd2820r_lock(priv, 0); | ||
| 356 | if (ret) | ||
| 357 | return ret; | ||
| 358 | |||
| 359 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 360 | case SYS_DVBT: | ||
| 361 | ret = cxd2820r_read_status_t(fe, status); | ||
| 362 | break; | ||
| 363 | case SYS_DVBT2: | ||
| 364 | ret = cxd2820r_read_status_t2(fe, status); | ||
| 365 | break; | ||
| 366 | default: | ||
| 367 | ret = -EINVAL; | ||
| 368 | } | ||
| 369 | } else { | ||
| 370 | /* DVB-C */ | ||
| 371 | ret = cxd2820r_lock(priv, 1); | ||
| 372 | if (ret) | ||
| 373 | return ret; | ||
| 374 | |||
| 375 | ret = cxd2820r_read_status_c(fe, status); | ||
| 376 | } | ||
| 377 | |||
| 378 | return ret; | ||
| 379 | } | ||
| 380 | |||
| 381 | static int cxd2820r_get_frontend(struct dvb_frontend *fe, | ||
| 382 | struct dvb_frontend_parameters *p) | ||
| 383 | { | ||
| 384 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 385 | int ret; | ||
| 386 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 387 | |||
| 388 | if (fe->ops.info.type == FE_OFDM) { | ||
| 389 | /* DVB-T/T2 */ | ||
| 390 | ret = cxd2820r_lock(priv, 0); | ||
| 391 | if (ret) | ||
| 392 | return ret; | ||
| 393 | |||
| 394 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 395 | case SYS_DVBT: | ||
| 396 | ret = cxd2820r_get_frontend_t(fe, p); | ||
| 397 | break; | ||
| 398 | case SYS_DVBT2: | ||
| 399 | ret = cxd2820r_get_frontend_t2(fe, p); | ||
| 400 | break; | ||
| 401 | default: | ||
| 402 | ret = -EINVAL; | ||
| 403 | } | ||
| 404 | } else { | ||
| 405 | /* DVB-C */ | ||
| 406 | ret = cxd2820r_lock(priv, 1); | ||
| 407 | if (ret) | ||
| 408 | return ret; | ||
| 409 | |||
| 410 | ret = cxd2820r_get_frontend_c(fe, p); | ||
| 411 | } | ||
| 412 | |||
| 413 | return ret; | ||
| 414 | } | ||
| 415 | |||
| 416 | static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 417 | { | ||
| 418 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 419 | int ret; | ||
| 420 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 421 | |||
| 422 | if (fe->ops.info.type == FE_OFDM) { | ||
| 423 | /* DVB-T/T2 */ | ||
| 424 | ret = cxd2820r_lock(priv, 0); | ||
| 425 | if (ret) | ||
| 426 | return ret; | ||
| 427 | |||
| 428 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 429 | case SYS_DVBT: | ||
| 430 | ret = cxd2820r_read_ber_t(fe, ber); | ||
| 431 | break; | ||
| 432 | case SYS_DVBT2: | ||
| 433 | ret = cxd2820r_read_ber_t2(fe, ber); | ||
| 434 | break; | ||
| 435 | default: | ||
| 436 | ret = -EINVAL; | ||
| 437 | } | ||
| 438 | } else { | ||
| 439 | /* DVB-C */ | ||
| 440 | ret = cxd2820r_lock(priv, 1); | ||
| 441 | if (ret) | ||
| 442 | return ret; | ||
| 443 | |||
| 444 | ret = cxd2820r_read_ber_c(fe, ber); | ||
| 445 | } | ||
| 446 | |||
| 447 | return ret; | ||
| 448 | } | ||
| 449 | |||
| 450 | static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
| 451 | { | ||
| 452 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 453 | int ret; | ||
| 454 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 455 | |||
| 456 | if (fe->ops.info.type == FE_OFDM) { | ||
| 457 | /* DVB-T/T2 */ | ||
| 458 | ret = cxd2820r_lock(priv, 0); | ||
| 459 | if (ret) | ||
| 460 | return ret; | ||
| 461 | |||
| 462 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 463 | case SYS_DVBT: | ||
| 464 | ret = cxd2820r_read_signal_strength_t(fe, strength); | ||
| 465 | break; | ||
| 466 | case SYS_DVBT2: | ||
| 467 | ret = cxd2820r_read_signal_strength_t2(fe, strength); | ||
| 468 | break; | ||
| 469 | default: | ||
| 470 | ret = -EINVAL; | ||
| 471 | } | ||
| 472 | } else { | ||
| 473 | /* DVB-C */ | ||
| 474 | ret = cxd2820r_lock(priv, 1); | ||
| 475 | if (ret) | ||
| 476 | return ret; | ||
| 477 | |||
| 478 | ret = cxd2820r_read_signal_strength_c(fe, strength); | ||
| 479 | } | ||
| 480 | |||
| 481 | return ret; | ||
| 482 | } | ||
| 483 | |||
| 484 | static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 485 | { | ||
| 486 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 487 | int ret; | ||
| 488 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 489 | |||
| 490 | if (fe->ops.info.type == FE_OFDM) { | ||
| 491 | /* DVB-T/T2 */ | ||
| 492 | ret = cxd2820r_lock(priv, 0); | ||
| 493 | if (ret) | ||
| 494 | return ret; | ||
| 495 | |||
| 496 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 497 | case SYS_DVBT: | ||
| 498 | ret = cxd2820r_read_snr_t(fe, snr); | ||
| 499 | break; | ||
| 500 | case SYS_DVBT2: | ||
| 501 | ret = cxd2820r_read_snr_t2(fe, snr); | ||
| 502 | break; | ||
| 503 | default: | ||
| 504 | ret = -EINVAL; | ||
| 505 | } | ||
| 506 | } else { | ||
| 507 | /* DVB-C */ | ||
| 508 | ret = cxd2820r_lock(priv, 1); | ||
| 509 | if (ret) | ||
| 510 | return ret; | ||
| 511 | |||
| 512 | ret = cxd2820r_read_snr_c(fe, snr); | ||
| 513 | } | ||
| 514 | |||
| 515 | return ret; | ||
| 516 | } | ||
| 517 | |||
| 518 | static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 519 | { | ||
| 520 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 521 | int ret; | ||
| 522 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 523 | |||
| 524 | if (fe->ops.info.type == FE_OFDM) { | ||
| 525 | /* DVB-T/T2 */ | ||
| 526 | ret = cxd2820r_lock(priv, 0); | ||
| 527 | if (ret) | ||
| 528 | return ret; | ||
| 529 | |||
| 530 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 531 | case SYS_DVBT: | ||
| 532 | ret = cxd2820r_read_ucblocks_t(fe, ucblocks); | ||
| 533 | break; | ||
| 534 | case SYS_DVBT2: | ||
| 535 | ret = cxd2820r_read_ucblocks_t2(fe, ucblocks); | ||
| 536 | break; | ||
| 537 | default: | ||
| 538 | ret = -EINVAL; | ||
| 539 | } | ||
| 540 | } else { | ||
| 541 | /* DVB-C */ | ||
| 542 | ret = cxd2820r_lock(priv, 1); | ||
| 543 | if (ret) | ||
| 544 | return ret; | ||
| 545 | |||
| 546 | ret = cxd2820r_read_ucblocks_c(fe, ucblocks); | ||
| 547 | } | ||
| 548 | |||
| 549 | return ret; | ||
| 550 | } | ||
| 551 | |||
| 552 | static int cxd2820r_init(struct dvb_frontend *fe) | ||
| 553 | { | ||
| 554 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 555 | int ret; | ||
| 556 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 557 | |||
| 558 | priv->delivery_system = SYS_UNDEFINED; | ||
| 559 | /* delivery system is unknown at that (init) phase */ | ||
| 560 | |||
| 561 | if (fe->ops.info.type == FE_OFDM) { | ||
| 562 | /* DVB-T/T2 */ | ||
| 563 | ret = cxd2820r_lock(priv, 0); | ||
| 564 | if (ret) | ||
| 565 | return ret; | ||
| 566 | |||
| 567 | ret = cxd2820r_init_t(fe); | ||
| 568 | } else { | ||
| 569 | /* DVB-C */ | ||
| 570 | ret = cxd2820r_lock(priv, 1); | ||
| 571 | if (ret) | ||
| 572 | return ret; | ||
| 573 | |||
| 574 | ret = cxd2820r_init_c(fe); | ||
| 575 | } | ||
| 576 | |||
| 577 | return ret; | ||
| 578 | } | ||
| 579 | |||
| 580 | static int cxd2820r_sleep(struct dvb_frontend *fe) | ||
| 581 | { | ||
| 582 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 583 | int ret; | ||
| 584 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 585 | |||
| 586 | if (fe->ops.info.type == FE_OFDM) { | ||
| 587 | /* DVB-T/T2 */ | ||
| 588 | ret = cxd2820r_lock(priv, 0); | ||
| 589 | if (ret) | ||
| 590 | return ret; | ||
| 591 | |||
| 592 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 593 | case SYS_DVBT: | ||
| 594 | ret = cxd2820r_sleep_t(fe); | ||
| 595 | break; | ||
| 596 | case SYS_DVBT2: | ||
| 597 | ret = cxd2820r_sleep_t2(fe); | ||
| 598 | break; | ||
| 599 | default: | ||
| 600 | ret = -EINVAL; | ||
| 601 | } | ||
| 602 | |||
| 603 | cxd2820r_unlock(priv, 0); | ||
| 604 | } else { | ||
| 605 | /* DVB-C */ | ||
| 606 | ret = cxd2820r_lock(priv, 1); | ||
| 607 | if (ret) | ||
| 608 | return ret; | ||
| 609 | |||
| 610 | ret = cxd2820r_sleep_c(fe); | ||
| 611 | |||
| 612 | cxd2820r_unlock(priv, 1); | ||
| 613 | } | ||
| 614 | |||
| 615 | return ret; | ||
| 616 | } | ||
| 617 | |||
| 618 | static int cxd2820r_get_tune_settings(struct dvb_frontend *fe, | ||
| 619 | struct dvb_frontend_tune_settings *s) | ||
| 620 | { | ||
| 621 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 622 | int ret; | ||
| 623 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 624 | |||
| 625 | if (fe->ops.info.type == FE_OFDM) { | ||
| 626 | /* DVB-T/T2 */ | ||
| 627 | ret = cxd2820r_lock(priv, 0); | ||
| 628 | if (ret) | ||
| 629 | return ret; | ||
| 630 | |||
| 631 | switch (fe->dtv_property_cache.delivery_system) { | ||
| 632 | case SYS_DVBT: | ||
| 633 | ret = cxd2820r_get_tune_settings_t(fe, s); | ||
| 634 | break; | ||
| 635 | case SYS_DVBT2: | ||
| 636 | ret = cxd2820r_get_tune_settings_t2(fe, s); | ||
| 637 | break; | ||
| 638 | default: | ||
| 639 | ret = -EINVAL; | ||
| 640 | } | ||
| 641 | } else { | ||
| 642 | /* DVB-C */ | ||
| 643 | ret = cxd2820r_lock(priv, 1); | ||
| 644 | if (ret) | ||
| 645 | return ret; | ||
| 646 | |||
| 647 | ret = cxd2820r_get_tune_settings_c(fe, s); | ||
| 648 | } | ||
| 649 | |||
| 650 | return ret; | ||
| 651 | } | ||
| 652 | |||
| 653 | static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe, | ||
| 654 | struct dvb_frontend_parameters *p) | ||
| 655 | { | ||
| 656 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 657 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 658 | int ret, i; | ||
| 659 | fe_status_t status = 0; | ||
| 660 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | ||
| 661 | |||
| 662 | /* switch between DVB-T and DVB-T2 when tune fails */ | ||
| 663 | if (priv->last_tune_failed) { | ||
| 664 | if (priv->delivery_system == SYS_DVBT) | ||
| 665 | c->delivery_system = SYS_DVBT2; | ||
| 666 | else | ||
| 667 | c->delivery_system = SYS_DVBT; | ||
| 668 | } | ||
| 669 | |||
| 670 | /* set frontend */ | ||
| 671 | ret = cxd2820r_set_frontend(fe, p); | ||
| 672 | if (ret) | ||
| 673 | goto error; | ||
| 674 | |||
| 675 | |||
| 676 | /* frontend lock wait loop count */ | ||
| 677 | switch (priv->delivery_system) { | ||
| 678 | case SYS_DVBT: | ||
| 679 | i = 20; | ||
| 680 | break; | ||
| 681 | case SYS_DVBT2: | ||
| 682 | i = 40; | ||
| 683 | break; | ||
| 684 | case SYS_UNDEFINED: | ||
| 685 | default: | ||
| 686 | i = 0; | ||
| 687 | break; | ||
| 688 | } | ||
| 689 | |||
| 690 | /* wait frontend lock */ | ||
| 691 | for (; i > 0; i--) { | ||
| 692 | dbg("%s: LOOP=%d", __func__, i); | ||
| 693 | msleep(50); | ||
| 694 | ret = cxd2820r_read_status(fe, &status); | ||
| 695 | if (ret) | ||
| 696 | goto error; | ||
| 697 | |||
| 698 | if (status & FE_HAS_SIGNAL) | ||
| 699 | break; | ||
| 700 | } | ||
| 701 | |||
| 702 | /* check if we have a valid signal */ | ||
| 703 | if (status) { | ||
| 704 | priv->last_tune_failed = 0; | ||
| 705 | return DVBFE_ALGO_SEARCH_SUCCESS; | ||
| 706 | } else { | ||
| 707 | priv->last_tune_failed = 1; | ||
| 708 | return DVBFE_ALGO_SEARCH_AGAIN; | ||
| 709 | } | ||
| 710 | |||
| 711 | error: | ||
| 712 | dbg("%s: failed:%d", __func__, ret); | ||
| 713 | return DVBFE_ALGO_SEARCH_ERROR; | ||
| 714 | } | ||
| 715 | |||
| 716 | static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe) | ||
| 717 | { | ||
| 718 | return DVBFE_ALGO_CUSTOM; | ||
| 719 | } | ||
| 720 | |||
| 721 | static void cxd2820r_release(struct dvb_frontend *fe) | ||
| 722 | { | ||
| 723 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 724 | dbg("%s", __func__); | ||
| 725 | |||
| 726 | if (fe->ops.info.type == FE_OFDM) { | ||
| 727 | i2c_del_adapter(&priv->tuner_i2c_adapter); | ||
| 728 | kfree(priv); | ||
| 729 | } | ||
| 730 | |||
| 731 | return; | ||
| 732 | } | ||
| 733 | |||
| 734 | static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter) | ||
| 735 | { | ||
| 736 | return I2C_FUNC_I2C; | ||
| 737 | } | ||
| 738 | |||
| 739 | static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, | ||
| 740 | struct i2c_msg msg[], int num) | ||
| 741 | { | ||
| 742 | struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap); | ||
| 743 | u8 obuf[msg[0].len + 2]; | ||
| 744 | struct i2c_msg msg2[2] = { | ||
| 745 | { | ||
| 746 | .addr = priv->cfg.i2c_address, | ||
| 747 | .flags = 0, | ||
| 748 | .len = sizeof(obuf), | ||
| 749 | .buf = obuf, | ||
| 750 | }, { | ||
| 751 | .addr = priv->cfg.i2c_address, | ||
| 752 | .flags = I2C_M_RD, | ||
| 753 | .len = msg[1].len, | ||
| 754 | .buf = msg[1].buf, | ||
| 755 | } | ||
| 756 | }; | ||
| 757 | |||
| 758 | obuf[0] = 0x09; | ||
| 759 | obuf[1] = (msg[0].addr << 1); | ||
| 760 | if (num == 2) { /* I2C read */ | ||
| 761 | obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */ | ||
| 762 | msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */ | ||
| 763 | } | ||
| 764 | memcpy(&obuf[2], msg[0].buf, msg[0].len); | ||
| 765 | |||
| 766 | return i2c_transfer(priv->i2c, msg2, num); | ||
| 767 | } | ||
| 768 | |||
| 769 | static struct i2c_algorithm cxd2820r_tuner_i2c_algo = { | ||
| 770 | .master_xfer = cxd2820r_tuner_i2c_xfer, | ||
| 771 | .functionality = cxd2820r_tuner_i2c_func, | ||
| 772 | }; | ||
| 773 | |||
| 774 | struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe) | ||
| 775 | { | ||
| 776 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 777 | return &priv->tuner_i2c_adapter; | ||
| 778 | } | ||
| 779 | EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter); | ||
| 780 | |||
| 781 | static struct dvb_frontend_ops cxd2820r_ops[2]; | ||
| 782 | |||
| 783 | struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, | ||
| 784 | struct i2c_adapter *i2c, struct dvb_frontend *fe) | ||
| 785 | { | ||
| 786 | int ret; | ||
| 787 | struct cxd2820r_priv *priv = NULL; | ||
| 788 | u8 tmp; | ||
| 789 | |||
| 790 | if (fe == NULL) { | ||
| 791 | /* FE0 */ | ||
| 792 | /* allocate memory for the internal priv */ | ||
| 793 | priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL); | ||
| 794 | if (priv == NULL) | ||
| 795 | goto error; | ||
| 796 | |||
| 797 | /* setup the priv */ | ||
| 798 | priv->i2c = i2c; | ||
| 799 | memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config)); | ||
| 800 | mutex_init(&priv->fe_lock); | ||
| 801 | |||
| 802 | priv->active_fe = -1; /* NONE */ | ||
| 803 | |||
| 804 | /* check if the demod is there */ | ||
| 805 | priv->bank[0] = priv->bank[1] = 0xff; | ||
| 806 | ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp); | ||
| 807 | dbg("%s: chip id=%02x", __func__, tmp); | ||
| 808 | if (ret || tmp != 0xe1) | ||
| 809 | goto error; | ||
| 810 | |||
| 811 | /* create frontends */ | ||
| 812 | memcpy(&priv->fe[0].ops, &cxd2820r_ops[0], | ||
| 813 | sizeof(struct dvb_frontend_ops)); | ||
| 814 | memcpy(&priv->fe[1].ops, &cxd2820r_ops[1], | ||
| 815 | sizeof(struct dvb_frontend_ops)); | ||
| 816 | |||
| 817 | priv->fe[0].demodulator_priv = priv; | ||
| 818 | priv->fe[1].demodulator_priv = priv; | ||
| 819 | |||
| 820 | /* create tuner i2c adapter */ | ||
| 821 | strlcpy(priv->tuner_i2c_adapter.name, | ||
| 822 | "CXD2820R tuner I2C adapter", | ||
| 823 | sizeof(priv->tuner_i2c_adapter.name)); | ||
| 824 | priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo; | ||
| 825 | priv->tuner_i2c_adapter.algo_data = NULL; | ||
| 826 | i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); | ||
| 827 | if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { | ||
| 828 | err("tuner I2C bus could not be initialized"); | ||
| 829 | goto error; | ||
| 830 | } | ||
| 831 | |||
| 832 | return &priv->fe[0]; | ||
| 833 | |||
| 834 | } else { | ||
| 835 | /* FE1: FE0 given as pointer, just return FE1 we have | ||
| 836 | * already created */ | ||
| 837 | priv = fe->demodulator_priv; | ||
| 838 | return &priv->fe[1]; | ||
| 839 | } | ||
| 840 | |||
| 841 | error: | ||
| 842 | kfree(priv); | ||
| 843 | return NULL; | ||
| 844 | } | ||
| 845 | EXPORT_SYMBOL(cxd2820r_attach); | ||
| 846 | |||
| 847 | static struct dvb_frontend_ops cxd2820r_ops[2] = { | ||
| 848 | { | ||
| 849 | /* DVB-T/T2 */ | ||
| 850 | .info = { | ||
| 851 | .name = "Sony CXD2820R (DVB-T/T2)", | ||
| 852 | .type = FE_OFDM, | ||
| 853 | .caps = | ||
| 854 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | ||
| 855 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | | ||
| 856 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 857 | FE_CAN_QPSK | FE_CAN_QAM_16 | | ||
| 858 | FE_CAN_QAM_64 | FE_CAN_QAM_256 | | ||
| 859 | FE_CAN_QAM_AUTO | | ||
| 860 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 861 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 862 | FE_CAN_HIERARCHY_AUTO | | ||
| 863 | FE_CAN_MUTE_TS | | ||
| 864 | FE_CAN_2G_MODULATION | ||
| 865 | }, | ||
| 866 | |||
| 867 | .release = cxd2820r_release, | ||
| 868 | .init = cxd2820r_init, | ||
| 869 | .sleep = cxd2820r_sleep, | ||
| 870 | |||
| 871 | .get_tune_settings = cxd2820r_get_tune_settings, | ||
| 872 | |||
| 873 | .get_frontend = cxd2820r_get_frontend, | ||
| 874 | |||
| 875 | .get_frontend_algo = cxd2820r_get_frontend_algo, | ||
| 876 | .search = cxd2820r_search, | ||
| 877 | |||
| 878 | .read_status = cxd2820r_read_status, | ||
| 879 | .read_snr = cxd2820r_read_snr, | ||
| 880 | .read_ber = cxd2820r_read_ber, | ||
| 881 | .read_ucblocks = cxd2820r_read_ucblocks, | ||
| 882 | .read_signal_strength = cxd2820r_read_signal_strength, | ||
| 883 | }, | ||
| 884 | { | ||
| 885 | /* DVB-C */ | ||
| 886 | .info = { | ||
| 887 | .name = "Sony CXD2820R (DVB-C)", | ||
| 888 | .type = FE_QAM, | ||
| 889 | .caps = | ||
| 890 | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | | ||
| 891 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||
| 892 | FE_CAN_FEC_AUTO | ||
| 893 | }, | ||
| 894 | |||
| 895 | .release = cxd2820r_release, | ||
| 896 | .init = cxd2820r_init, | ||
| 897 | .sleep = cxd2820r_sleep, | ||
| 898 | |||
| 899 | .get_tune_settings = cxd2820r_get_tune_settings, | ||
| 900 | |||
| 901 | .set_frontend = cxd2820r_set_frontend, | ||
| 902 | .get_frontend = cxd2820r_get_frontend, | ||
| 903 | |||
| 904 | .read_status = cxd2820r_read_status, | ||
| 905 | .read_snr = cxd2820r_read_snr, | ||
| 906 | .read_ber = cxd2820r_read_ber, | ||
| 907 | .read_ucblocks = cxd2820r_read_ucblocks, | ||
| 908 | .read_signal_strength = cxd2820r_read_signal_strength, | ||
| 909 | }, | ||
| 910 | }; | ||
| 911 | |||
| 912 | |||
| 913 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 914 | MODULE_DESCRIPTION("Sony CXD2820R demodulator driver"); | ||
| 915 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/cxd2820r_priv.h b/drivers/media/dvb/frontends/cxd2820r_priv.h new file mode 100644 index 000000000000..25adbeefa6d3 --- /dev/null +++ b/drivers/media/dvb/frontends/cxd2820r_priv.h | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | /* | ||
| 2 | * Sony CXD2820R demodulator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | |||
| 22 | #ifndef CXD2820R_PRIV_H | ||
| 23 | #define CXD2820R_PRIV_H | ||
| 24 | |||
| 25 | #include <linux/dvb/version.h> | ||
| 26 | #include "dvb_frontend.h" | ||
| 27 | #include "dvb_math.h" | ||
| 28 | #include "cxd2820r.h" | ||
| 29 | |||
| 30 | #define LOG_PREFIX "cxd2820r" | ||
| 31 | |||
| 32 | #undef dbg | ||
| 33 | #define dbg(f, arg...) \ | ||
| 34 | if (cxd2820r_debug) \ | ||
| 35 | printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
| 36 | #undef err | ||
| 37 | #define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) | ||
| 38 | #undef info | ||
| 39 | #define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
| 40 | #undef warn | ||
| 41 | #define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) | ||
| 42 | |||
| 43 | struct reg_val_mask { | ||
| 44 | u32 reg; | ||
| 45 | u8 val; | ||
| 46 | u8 mask; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct cxd2820r_priv { | ||
| 50 | struct i2c_adapter *i2c; | ||
| 51 | struct dvb_frontend fe[2]; | ||
| 52 | struct cxd2820r_config cfg; | ||
| 53 | struct i2c_adapter tuner_i2c_adapter; | ||
| 54 | |||
| 55 | struct mutex fe_lock; /*Â FE lock */ | ||
| 56 | int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */ | ||
| 57 | |||
| 58 | int ber_running:1; | ||
| 59 | |||
| 60 | u8 bank[2]; | ||
| 61 | u8 gpio[3]; | ||
| 62 | |||
| 63 | fe_delivery_system_t delivery_system; | ||
| 64 | int last_tune_failed:1; /* for switch between T and T2 tune */ | ||
| 65 | }; | ||
| 66 | |||
| 67 | /* cxd2820r_core.c */ | ||
| 68 | |||
| 69 | extern int cxd2820r_debug; | ||
| 70 | |||
| 71 | int cxd2820r_gpio(struct dvb_frontend *fe); | ||
| 72 | |||
| 73 | int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, | ||
| 74 | u8 mask); | ||
| 75 | |||
| 76 | int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | ||
| 77 | int len); | ||
| 78 | |||
| 79 | u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor); | ||
| 80 | |||
| 81 | int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | ||
| 82 | int len); | ||
| 83 | |||
| 84 | int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | ||
| 85 | int len); | ||
| 86 | |||
| 87 | int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val); | ||
| 88 | |||
| 89 | int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val); | ||
| 90 | |||
| 91 | /* cxd2820r_c.c */ | ||
| 92 | |||
| 93 | int cxd2820r_get_frontend_c(struct dvb_frontend *fe, | ||
| 94 | struct dvb_frontend_parameters *p); | ||
| 95 | |||
| 96 | int cxd2820r_set_frontend_c(struct dvb_frontend *fe, | ||
| 97 | struct dvb_frontend_parameters *params); | ||
| 98 | |||
| 99 | int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status); | ||
| 100 | |||
| 101 | int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber); | ||
| 102 | |||
| 103 | int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, u16 *strength); | ||
| 104 | |||
| 105 | int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr); | ||
| 106 | |||
| 107 | int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks); | ||
| 108 | |||
| 109 | int cxd2820r_init_c(struct dvb_frontend *fe); | ||
| 110 | |||
| 111 | int cxd2820r_sleep_c(struct dvb_frontend *fe); | ||
| 112 | |||
| 113 | int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, | ||
| 114 | struct dvb_frontend_tune_settings *s); | ||
| 115 | |||
| 116 | /* cxd2820r_t.c */ | ||
| 117 | |||
| 118 | int cxd2820r_get_frontend_t(struct dvb_frontend *fe, | ||
| 119 | struct dvb_frontend_parameters *p); | ||
| 120 | |||
| 121 | int cxd2820r_set_frontend_t(struct dvb_frontend *fe, | ||
| 122 | struct dvb_frontend_parameters *params); | ||
| 123 | |||
| 124 | int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status); | ||
| 125 | |||
| 126 | int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber); | ||
| 127 | |||
| 128 | int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, u16 *strength); | ||
| 129 | |||
| 130 | int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr); | ||
| 131 | |||
| 132 | int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks); | ||
| 133 | |||
| 134 | int cxd2820r_init_t(struct dvb_frontend *fe); | ||
| 135 | |||
| 136 | int cxd2820r_sleep_t(struct dvb_frontend *fe); | ||
| 137 | |||
| 138 | int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, | ||
| 139 | struct dvb_frontend_tune_settings *s); | ||
| 140 | |||
| 141 | /* cxd2820r_t2.c */ | ||
| 142 | |||
| 143 | int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, | ||
| 144 | struct dvb_frontend_parameters *p); | ||
| 145 | |||
| 146 | int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, | ||
| 147 | struct dvb_frontend_parameters *params); | ||
| 148 | |||
| 149 | int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status); | ||
| 150 | |||
| 151 | int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber); | ||
| 152 | |||
| 153 | int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, u16 *strength); | ||
| 154 | |||
| 155 | int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr); | ||
| 156 | |||
| 157 | int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks); | ||
| 158 | |||
| 159 | int cxd2820r_init_t2(struct dvb_frontend *fe); | ||
| 160 | |||
| 161 | int cxd2820r_sleep_t2(struct dvb_frontend *fe); | ||
| 162 | |||
| 163 | int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe, | ||
| 164 | struct dvb_frontend_tune_settings *s); | ||
| 165 | |||
| 166 | #endif /* CXD2820R_PRIV_H */ | ||
diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb/frontends/cxd2820r_t.c new file mode 100644 index 000000000000..6582564c930c --- /dev/null +++ b/drivers/media/dvb/frontends/cxd2820r_t.c | |||
| @@ -0,0 +1,449 @@ | |||
| 1 | /* | ||
| 2 | * Sony CXD2820R demodulator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | |||
| 22 | #include "cxd2820r_priv.h" | ||
| 23 | |||
| 24 | int cxd2820r_set_frontend_t(struct dvb_frontend *fe, | ||
| 25 | struct dvb_frontend_parameters *p) | ||
| 26 | { | ||
| 27 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 28 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 29 | int ret, i; | ||
| 30 | u32 if_khz, if_ctl; | ||
| 31 | u64 num; | ||
| 32 | u8 buf[3], bw_param; | ||
| 33 | u8 bw_params1[][5] = { | ||
| 34 | { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */ | ||
| 35 | { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */ | ||
| 36 | { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */ | ||
| 37 | }; | ||
| 38 | u8 bw_params2[][2] = { | ||
| 39 | { 0x1f, 0xdc }, /* 6 MHz */ | ||
| 40 | { 0x12, 0xf8 }, /* 7 MHz */ | ||
| 41 | { 0x01, 0xe0 }, /* 8 MHz */ | ||
| 42 | }; | ||
| 43 | struct reg_val_mask tab[] = { | ||
| 44 | { 0x00080, 0x00, 0xff }, | ||
| 45 | { 0x00081, 0x03, 0xff }, | ||
| 46 | { 0x00085, 0x07, 0xff }, | ||
| 47 | { 0x00088, 0x01, 0xff }, | ||
| 48 | |||
| 49 | { 0x00070, priv->cfg.ts_mode, 0xff }, | ||
| 50 | { 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 }, | ||
| 51 | { 0x000a5, 0x00, 0x01 }, | ||
| 52 | { 0x00082, 0x20, 0x60 }, | ||
| 53 | { 0x000c2, 0xc3, 0xff }, | ||
| 54 | { 0x0016a, 0x50, 0xff }, | ||
| 55 | { 0x00427, 0x41, 0xff }, | ||
| 56 | }; | ||
| 57 | |||
| 58 | dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); | ||
| 59 | |||
| 60 | /* update GPIOs */ | ||
| 61 | ret = cxd2820r_gpio(fe); | ||
| 62 | if (ret) | ||
| 63 | goto error; | ||
| 64 | |||
| 65 | /* program tuner */ | ||
| 66 | if (fe->ops.tuner_ops.set_params) | ||
| 67 | fe->ops.tuner_ops.set_params(fe, p); | ||
| 68 | |||
| 69 | if (priv->delivery_system != SYS_DVBT) { | ||
| 70 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
| 71 | ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, | ||
| 72 | tab[i].val, tab[i].mask); | ||
| 73 | if (ret) | ||
| 74 | goto error; | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | priv->delivery_system = SYS_DVBT; | ||
| 79 | priv->ber_running = 0; /* tune stops BER counter */ | ||
| 80 | |||
| 81 | switch (c->bandwidth_hz) { | ||
| 82 | case 6000000: | ||
| 83 | if_khz = priv->cfg.if_dvbt_6; | ||
| 84 | i = 0; | ||
| 85 | bw_param = 2; | ||
| 86 | break; | ||
| 87 | case 7000000: | ||
| 88 | if_khz = priv->cfg.if_dvbt_7; | ||
| 89 | i = 1; | ||
| 90 | bw_param = 1; | ||
| 91 | break; | ||
| 92 | case 8000000: | ||
| 93 | if_khz = priv->cfg.if_dvbt_8; | ||
| 94 | i = 2; | ||
| 95 | bw_param = 0; | ||
| 96 | break; | ||
| 97 | default: | ||
| 98 | return -EINVAL; | ||
| 99 | } | ||
| 100 | |||
| 101 | num = if_khz; | ||
| 102 | num *= 0x1000000; | ||
| 103 | if_ctl = cxd2820r_div_u64_round_closest(num, 41000); | ||
| 104 | buf[0] = ((if_ctl >> 16) & 0xff); | ||
| 105 | buf[1] = ((if_ctl >> 8) & 0xff); | ||
| 106 | buf[2] = ((if_ctl >> 0) & 0xff); | ||
| 107 | |||
| 108 | ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3); | ||
| 109 | if (ret) | ||
| 110 | goto error; | ||
| 111 | |||
| 112 | ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[i], 5); | ||
| 113 | if (ret) | ||
| 114 | goto error; | ||
| 115 | |||
| 116 | ret = cxd2820r_wr_reg_mask(priv, 0x000d7, bw_param << 6, 0xc0); | ||
| 117 | if (ret) | ||
| 118 | goto error; | ||
| 119 | |||
| 120 | ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[i], 2); | ||
| 121 | if (ret) | ||
| 122 | goto error; | ||
| 123 | |||
| 124 | ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); | ||
| 125 | if (ret) | ||
| 126 | goto error; | ||
| 127 | |||
| 128 | ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); | ||
| 129 | if (ret) | ||
| 130 | goto error; | ||
| 131 | |||
| 132 | return ret; | ||
| 133 | error: | ||
| 134 | dbg("%s: failed:%d", __func__, ret); | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | |||
| 138 | int cxd2820r_get_frontend_t(struct dvb_frontend *fe, | ||
| 139 | struct dvb_frontend_parameters *p) | ||
| 140 | { | ||
| 141 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 142 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 143 | int ret; | ||
| 144 | u8 buf[2]; | ||
| 145 | |||
| 146 | ret = cxd2820r_rd_regs(priv, 0x0002f, buf, sizeof(buf)); | ||
| 147 | if (ret) | ||
| 148 | goto error; | ||
| 149 | |||
| 150 | switch ((buf[0] >> 6) & 0x03) { | ||
| 151 | case 0: | ||
| 152 | c->modulation = QPSK; | ||
| 153 | break; | ||
| 154 | case 1: | ||
| 155 | c->modulation = QAM_16; | ||
| 156 | break; | ||
| 157 | case 2: | ||
| 158 | c->modulation = QAM_64; | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | |||
| 162 | switch ((buf[1] >> 1) & 0x03) { | ||
| 163 | case 0: | ||
| 164 | c->transmission_mode = TRANSMISSION_MODE_2K; | ||
| 165 | break; | ||
| 166 | case 1: | ||
| 167 | c->transmission_mode = TRANSMISSION_MODE_8K; | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | |||
| 171 | switch ((buf[1] >> 3) & 0x03) { | ||
| 172 | case 0: | ||
| 173 | c->guard_interval = GUARD_INTERVAL_1_32; | ||
| 174 | break; | ||
| 175 | case 1: | ||
| 176 | c->guard_interval = GUARD_INTERVAL_1_16; | ||
| 177 | break; | ||
| 178 | case 2: | ||
| 179 | c->guard_interval = GUARD_INTERVAL_1_8; | ||
| 180 | break; | ||
| 181 | case 3: | ||
| 182 | c->guard_interval = GUARD_INTERVAL_1_4; | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | switch ((buf[0] >> 3) & 0x07) { | ||
| 187 | case 0: | ||
| 188 | c->hierarchy = HIERARCHY_NONE; | ||
| 189 | break; | ||
| 190 | case 1: | ||
| 191 | c->hierarchy = HIERARCHY_1; | ||
| 192 | break; | ||
| 193 | case 2: | ||
| 194 | c->hierarchy = HIERARCHY_2; | ||
| 195 | break; | ||
| 196 | case 3: | ||
| 197 | c->hierarchy = HIERARCHY_4; | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | |||
| 201 | switch ((buf[0] >> 0) & 0x07) { | ||
| 202 | case 0: | ||
| 203 | c->code_rate_HP = FEC_1_2; | ||
| 204 | break; | ||
| 205 | case 1: | ||
| 206 | c->code_rate_HP = FEC_2_3; | ||
| 207 | break; | ||
| 208 | case 2: | ||
| 209 | c->code_rate_HP = FEC_3_4; | ||
| 210 | break; | ||
| 211 | case 3: | ||
| 212 | c->code_rate_HP = FEC_5_6; | ||
| 213 | break; | ||
| 214 | case 4: | ||
| 215 | c->code_rate_HP = FEC_7_8; | ||
| 216 | break; | ||
| 217 | } | ||
| 218 | |||
| 219 | switch ((buf[1] >> 5) & 0x07) { | ||
| 220 | case 0: | ||
| 221 | c->code_rate_LP = FEC_1_2; | ||
| 222 | break; | ||
| 223 | case 1: | ||
| 224 | c->code_rate_LP = FEC_2_3; | ||
| 225 | break; | ||
| 226 | case 2: | ||
| 227 | c->code_rate_LP = FEC_3_4; | ||
| 228 | break; | ||
| 229 | case 3: | ||
| 230 | c->code_rate_LP = FEC_5_6; | ||
| 231 | break; | ||
| 232 | case 4: | ||
| 233 | c->code_rate_LP = FEC_7_8; | ||
| 234 | break; | ||
| 235 | } | ||
| 236 | |||
| 237 | ret = cxd2820r_rd_reg(priv, 0x007c6, &buf[0]); | ||
| 238 | if (ret) | ||
| 239 | goto error; | ||
| 240 | |||
| 241 | switch ((buf[0] >> 0) & 0x01) { | ||
| 242 | case 0: | ||
| 243 | c->inversion = INVERSION_OFF; | ||
| 244 | break; | ||
| 245 | case 1: | ||
| 246 | c->inversion = INVERSION_ON; | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | |||
| 250 | return ret; | ||
| 251 | error: | ||
| 252 | dbg("%s: failed:%d", __func__, ret); | ||
| 253 | return ret; | ||
| 254 | } | ||
| 255 | |||
| 256 | int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber) | ||
| 257 | { | ||
| 258 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 259 | int ret; | ||
| 260 | u8 buf[3], start_ber = 0; | ||
| 261 | *ber = 0; | ||
| 262 | |||
| 263 | if (priv->ber_running) { | ||
| 264 | ret = cxd2820r_rd_regs(priv, 0x00076, buf, sizeof(buf)); | ||
| 265 | if (ret) | ||
| 266 | goto error; | ||
| 267 | |||
| 268 | if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) { | ||
| 269 | *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0]; | ||
| 270 | start_ber = 1; | ||
| 271 | } | ||
| 272 | } else { | ||
| 273 | priv->ber_running = 1; | ||
| 274 | start_ber = 1; | ||
| 275 | } | ||
| 276 | |||
| 277 | if (start_ber) { | ||
| 278 | /* (re)start BER */ | ||
| 279 | ret = cxd2820r_wr_reg(priv, 0x00079, 0x01); | ||
| 280 | if (ret) | ||
| 281 | goto error; | ||
| 282 | } | ||
| 283 | |||
| 284 | return ret; | ||
| 285 | error: | ||
| 286 | dbg("%s: failed:%d", __func__, ret); | ||
| 287 | return ret; | ||
| 288 | } | ||
| 289 | |||
| 290 | int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, | ||
| 291 | u16 *strength) | ||
| 292 | { | ||
| 293 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 294 | int ret; | ||
| 295 | u8 buf[2]; | ||
| 296 | u16 tmp; | ||
| 297 | |||
| 298 | ret = cxd2820r_rd_regs(priv, 0x00026, buf, sizeof(buf)); | ||
| 299 | if (ret) | ||
| 300 | goto error; | ||
| 301 | |||
| 302 | tmp = (buf[0] & 0x0f) << 8 | buf[1]; | ||
| 303 | tmp = ~tmp & 0x0fff; | ||
| 304 | |||
| 305 | /* scale value to 0x0000-0xffff from 0x0000-0x0fff */ | ||
| 306 | *strength = tmp * 0xffff / 0x0fff; | ||
| 307 | |||
| 308 | return ret; | ||
| 309 | error: | ||
| 310 | dbg("%s: failed:%d", __func__, ret); | ||
| 311 | return ret; | ||
| 312 | } | ||
| 313 | |||
| 314 | int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr) | ||
| 315 | { | ||
| 316 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 317 | int ret; | ||
| 318 | u8 buf[2]; | ||
| 319 | u16 tmp; | ||
| 320 | /* report SNR in dB * 10 */ | ||
| 321 | |||
| 322 | ret = cxd2820r_rd_regs(priv, 0x00028, buf, sizeof(buf)); | ||
| 323 | if (ret) | ||
| 324 | goto error; | ||
| 325 | |||
| 326 | tmp = (buf[0] & 0x1f) << 8 | buf[1]; | ||
| 327 | #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ | ||
| 328 | if (tmp) | ||
| 329 | *snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24) | ||
| 330 | / 100); | ||
| 331 | else | ||
| 332 | *snr = 0; | ||
| 333 | |||
| 334 | dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp); | ||
| 335 | |||
| 336 | return ret; | ||
| 337 | error: | ||
| 338 | dbg("%s: failed:%d", __func__, ret); | ||
| 339 | return ret; | ||
| 340 | } | ||
| 341 | |||
| 342 | int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 343 | { | ||
| 344 | *ucblocks = 0; | ||
| 345 | /* no way to read ? */ | ||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status) | ||
| 350 | { | ||
| 351 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 352 | int ret; | ||
| 353 | u8 buf[4]; | ||
| 354 | *status = 0; | ||
| 355 | |||
| 356 | ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]); | ||
| 357 | if (ret) | ||
| 358 | goto error; | ||
| 359 | |||
| 360 | if ((buf[0] & 0x07) == 6) { | ||
| 361 | ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]); | ||
| 362 | if (ret) | ||
| 363 | goto error; | ||
| 364 | |||
| 365 | if (((buf[1] >> 3) & 0x01) == 1) { | ||
| 366 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
| 367 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
| 368 | } else { | ||
| 369 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
| 370 | FE_HAS_VITERBI | FE_HAS_SYNC; | ||
| 371 | } | ||
| 372 | } else { | ||
| 373 | ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]); | ||
| 374 | if (ret) | ||
| 375 | goto error; | ||
| 376 | |||
| 377 | if ((buf[2] & 0x0f) >= 4) { | ||
| 378 | ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]); | ||
| 379 | if (ret) | ||
| 380 | goto error; | ||
| 381 | |||
| 382 | if (((buf[3] >> 4) & 0x01) == 1) | ||
| 383 | *status |= FE_HAS_SIGNAL; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | dbg("%s: lock=%02x %02x %02x %02x", __func__, | ||
| 388 | buf[0], buf[1], buf[2], buf[3]); | ||
| 389 | |||
| 390 | return ret; | ||
| 391 | error: | ||
| 392 | dbg("%s: failed:%d", __func__, ret); | ||
| 393 | return ret; | ||
| 394 | } | ||
| 395 | |||
| 396 | int cxd2820r_init_t(struct dvb_frontend *fe) | ||
| 397 | { | ||
| 398 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 399 | int ret; | ||
| 400 | |||
| 401 | ret = cxd2820r_wr_reg(priv, 0x00085, 0x07); | ||
| 402 | if (ret) | ||
| 403 | goto error; | ||
| 404 | |||
| 405 | return ret; | ||
| 406 | error: | ||
| 407 | dbg("%s: failed:%d", __func__, ret); | ||
| 408 | return ret; | ||
| 409 | } | ||
| 410 | |||
| 411 | int cxd2820r_sleep_t(struct dvb_frontend *fe) | ||
| 412 | { | ||
| 413 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 414 | int ret, i; | ||
| 415 | struct reg_val_mask tab[] = { | ||
| 416 | { 0x000ff, 0x1f, 0xff }, | ||
| 417 | { 0x00085, 0x00, 0xff }, | ||
| 418 | { 0x00088, 0x01, 0xff }, | ||
| 419 | { 0x00081, 0x00, 0xff }, | ||
| 420 | { 0x00080, 0x00, 0xff }, | ||
| 421 | }; | ||
| 422 | |||
| 423 | dbg("%s", __func__); | ||
| 424 | |||
| 425 | priv->delivery_system = SYS_UNDEFINED; | ||
| 426 | |||
| 427 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
| 428 | ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, | ||
| 429 | tab[i].mask); | ||
| 430 | if (ret) | ||
| 431 | goto error; | ||
| 432 | } | ||
| 433 | |||
| 434 | return ret; | ||
| 435 | error: | ||
| 436 | dbg("%s: failed:%d", __func__, ret); | ||
| 437 | return ret; | ||
| 438 | } | ||
| 439 | |||
| 440 | int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, | ||
| 441 | struct dvb_frontend_tune_settings *s) | ||
| 442 | { | ||
| 443 | s->min_delay_ms = 500; | ||
| 444 | s->step_size = fe->ops.info.frequency_stepsize * 2; | ||
| 445 | s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | ||
| 446 | |||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | |||
diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb/frontends/cxd2820r_t2.c new file mode 100644 index 000000000000..c47b35c8acf1 --- /dev/null +++ b/drivers/media/dvb/frontends/cxd2820r_t2.c | |||
| @@ -0,0 +1,423 @@ | |||
| 1 | /* | ||
| 2 | * Sony CXD2820R demodulator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | |||
| 22 | #include "cxd2820r_priv.h" | ||
| 23 | |||
| 24 | int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, | ||
| 25 | struct dvb_frontend_parameters *params) | ||
| 26 | { | ||
| 27 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 28 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 29 | int ret, i; | ||
| 30 | u32 if_khz, if_ctl; | ||
| 31 | u64 num; | ||
| 32 | u8 buf[3], bw_param; | ||
| 33 | u8 bw_params1[][5] = { | ||
| 34 | { 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */ | ||
| 35 | { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */ | ||
| 36 | { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */ | ||
| 37 | { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */ | ||
| 38 | }; | ||
| 39 | struct reg_val_mask tab[] = { | ||
| 40 | { 0x00080, 0x02, 0xff }, | ||
| 41 | { 0x00081, 0x20, 0xff }, | ||
| 42 | { 0x00085, 0x07, 0xff }, | ||
| 43 | { 0x00088, 0x01, 0xff }, | ||
| 44 | { 0x02069, 0x01, 0xff }, | ||
| 45 | |||
| 46 | { 0x0207f, 0x2a, 0xff }, | ||
| 47 | { 0x02082, 0x0a, 0xff }, | ||
| 48 | { 0x02083, 0x0a, 0xff }, | ||
| 49 | { 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 }, | ||
| 50 | { 0x02070, priv->cfg.ts_mode, 0xff }, | ||
| 51 | { 0x020b5, priv->cfg.spec_inv << 4, 0x10 }, | ||
| 52 | { 0x02567, 0x07, 0x0f }, | ||
| 53 | { 0x02569, 0x03, 0x03 }, | ||
| 54 | { 0x02595, 0x1a, 0xff }, | ||
| 55 | { 0x02596, 0x50, 0xff }, | ||
| 56 | { 0x02a8c, 0x00, 0xff }, | ||
| 57 | { 0x02a8d, 0x34, 0xff }, | ||
| 58 | { 0x02a45, 0x06, 0x07 }, | ||
| 59 | { 0x03f10, 0x0d, 0xff }, | ||
| 60 | { 0x03f11, 0x02, 0xff }, | ||
| 61 | { 0x03f12, 0x01, 0xff }, | ||
| 62 | { 0x03f23, 0x2c, 0xff }, | ||
| 63 | { 0x03f51, 0x13, 0xff }, | ||
| 64 | { 0x03f52, 0x01, 0xff }, | ||
| 65 | { 0x03f53, 0x00, 0xff }, | ||
| 66 | { 0x027e6, 0x14, 0xff }, | ||
| 67 | { 0x02786, 0x02, 0x07 }, | ||
| 68 | { 0x02787, 0x40, 0xe0 }, | ||
| 69 | { 0x027ef, 0x10, 0x18 }, | ||
| 70 | }; | ||
| 71 | |||
| 72 | dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); | ||
| 73 | |||
| 74 | /* update GPIOs */ | ||
| 75 | ret = cxd2820r_gpio(fe); | ||
| 76 | if (ret) | ||
| 77 | goto error; | ||
| 78 | |||
| 79 | /* program tuner */ | ||
| 80 | if (fe->ops.tuner_ops.set_params) | ||
| 81 | fe->ops.tuner_ops.set_params(fe, params); | ||
| 82 | |||
| 83 | if (priv->delivery_system != SYS_DVBT2) { | ||
| 84 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
| 85 | ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, | ||
| 86 | tab[i].val, tab[i].mask); | ||
| 87 | if (ret) | ||
| 88 | goto error; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | priv->delivery_system = SYS_DVBT2; | ||
| 93 | |||
| 94 | switch (c->bandwidth_hz) { | ||
| 95 | case 5000000: | ||
| 96 | if_khz = priv->cfg.if_dvbt2_5; | ||
| 97 | i = 0; | ||
| 98 | bw_param = 3; | ||
| 99 | break; | ||
| 100 | case 6000000: | ||
| 101 | if_khz = priv->cfg.if_dvbt2_6; | ||
| 102 | i = 1; | ||
| 103 | bw_param = 2; | ||
| 104 | break; | ||
| 105 | case 7000000: | ||
| 106 | if_khz = priv->cfg.if_dvbt2_7; | ||
| 107 | i = 2; | ||
| 108 | bw_param = 1; | ||
| 109 | break; | ||
| 110 | case 8000000: | ||
| 111 | if_khz = priv->cfg.if_dvbt2_8; | ||
| 112 | i = 3; | ||
| 113 | bw_param = 0; | ||
| 114 | break; | ||
| 115 | default: | ||
| 116 | return -EINVAL; | ||
| 117 | } | ||
| 118 | |||
| 119 | num = if_khz; | ||
| 120 | num *= 0x1000000; | ||
| 121 | if_ctl = cxd2820r_div_u64_round_closest(num, 41000); | ||
| 122 | buf[0] = ((if_ctl >> 16) & 0xff); | ||
| 123 | buf[1] = ((if_ctl >> 8) & 0xff); | ||
| 124 | buf[2] = ((if_ctl >> 0) & 0xff); | ||
| 125 | |||
| 126 | ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3); | ||
| 127 | if (ret) | ||
| 128 | goto error; | ||
| 129 | |||
| 130 | ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[i], 5); | ||
| 131 | if (ret) | ||
| 132 | goto error; | ||
| 133 | |||
| 134 | ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0); | ||
| 135 | if (ret) | ||
| 136 | goto error; | ||
| 137 | |||
| 138 | ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); | ||
| 139 | if (ret) | ||
| 140 | goto error; | ||
| 141 | |||
| 142 | ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); | ||
| 143 | if (ret) | ||
| 144 | goto error; | ||
| 145 | |||
| 146 | return ret; | ||
| 147 | error: | ||
| 148 | dbg("%s: failed:%d", __func__, ret); | ||
| 149 | return ret; | ||
| 150 | |||
| 151 | } | ||
| 152 | |||
| 153 | int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, | ||
| 154 | struct dvb_frontend_parameters *p) | ||
| 155 | { | ||
| 156 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 157 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 158 | int ret; | ||
| 159 | u8 buf[2]; | ||
| 160 | |||
| 161 | ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2); | ||
| 162 | if (ret) | ||
| 163 | goto error; | ||
| 164 | |||
| 165 | switch ((buf[0] >> 0) & 0x07) { | ||
| 166 | case 0: | ||
| 167 | c->transmission_mode = TRANSMISSION_MODE_2K; | ||
| 168 | break; | ||
| 169 | case 1: | ||
| 170 | c->transmission_mode = TRANSMISSION_MODE_8K; | ||
| 171 | break; | ||
| 172 | case 2: | ||
| 173 | c->transmission_mode = TRANSMISSION_MODE_4K; | ||
| 174 | break; | ||
| 175 | case 3: | ||
| 176 | c->transmission_mode = TRANSMISSION_MODE_1K; | ||
| 177 | break; | ||
| 178 | case 4: | ||
| 179 | c->transmission_mode = TRANSMISSION_MODE_16K; | ||
| 180 | break; | ||
| 181 | case 5: | ||
| 182 | c->transmission_mode = TRANSMISSION_MODE_32K; | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | switch ((buf[1] >> 4) & 0x07) { | ||
| 187 | case 0: | ||
| 188 | c->guard_interval = GUARD_INTERVAL_1_32; | ||
| 189 | break; | ||
| 190 | case 1: | ||
| 191 | c->guard_interval = GUARD_INTERVAL_1_16; | ||
| 192 | break; | ||
| 193 | case 2: | ||
| 194 | c->guard_interval = GUARD_INTERVAL_1_8; | ||
| 195 | break; | ||
| 196 | case 3: | ||
| 197 | c->guard_interval = GUARD_INTERVAL_1_4; | ||
| 198 | break; | ||
| 199 | case 4: | ||
| 200 | c->guard_interval = GUARD_INTERVAL_1_128; | ||
| 201 | break; | ||
| 202 | case 5: | ||
| 203 | c->guard_interval = GUARD_INTERVAL_19_128; | ||
| 204 | break; | ||
| 205 | case 6: | ||
| 206 | c->guard_interval = GUARD_INTERVAL_19_256; | ||
| 207 | break; | ||
| 208 | } | ||
| 209 | |||
| 210 | ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2); | ||
| 211 | if (ret) | ||
| 212 | goto error; | ||
| 213 | |||
| 214 | switch ((buf[0] >> 0) & 0x07) { | ||
| 215 | case 0: | ||
| 216 | c->fec_inner = FEC_1_2; | ||
| 217 | break; | ||
| 218 | case 1: | ||
| 219 | c->fec_inner = FEC_3_5; | ||
| 220 | break; | ||
| 221 | case 2: | ||
| 222 | c->fec_inner = FEC_2_3; | ||
| 223 | break; | ||
| 224 | case 3: | ||
| 225 | c->fec_inner = FEC_3_4; | ||
| 226 | break; | ||
| 227 | case 4: | ||
| 228 | c->fec_inner = FEC_4_5; | ||
| 229 | break; | ||
| 230 | case 5: | ||
| 231 | c->fec_inner = FEC_5_6; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | |||
| 235 | switch ((buf[1] >> 0) & 0x07) { | ||
| 236 | case 0: | ||
| 237 | c->modulation = QPSK; | ||
| 238 | break; | ||
| 239 | case 1: | ||
| 240 | c->modulation = QAM_16; | ||
| 241 | break; | ||
| 242 | case 2: | ||
| 243 | c->modulation = QAM_64; | ||
| 244 | break; | ||
| 245 | case 3: | ||
| 246 | c->modulation = QAM_256; | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | |||
| 250 | ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]); | ||
| 251 | if (ret) | ||
| 252 | goto error; | ||
| 253 | |||
| 254 | switch ((buf[0] >> 4) & 0x01) { | ||
| 255 | case 0: | ||
| 256 | c->inversion = INVERSION_OFF; | ||
| 257 | break; | ||
| 258 | case 1: | ||
| 259 | c->inversion = INVERSION_ON; | ||
| 260 | break; | ||
| 261 | } | ||
| 262 | |||
| 263 | return ret; | ||
| 264 | error: | ||
| 265 | dbg("%s: failed:%d", __func__, ret); | ||
| 266 | return ret; | ||
| 267 | } | ||
| 268 | |||
| 269 | int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status) | ||
| 270 | { | ||
| 271 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 272 | int ret; | ||
| 273 | u8 buf[1]; | ||
| 274 | *status = 0; | ||
| 275 | |||
| 276 | ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]); | ||
| 277 | if (ret) | ||
| 278 | goto error; | ||
| 279 | |||
| 280 | if ((buf[0] & 0x07) == 6) { | ||
| 281 | if (((buf[0] >> 5) & 0x01) == 1) { | ||
| 282 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
| 283 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
| 284 | } else { | ||
| 285 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
| 286 | FE_HAS_VITERBI | FE_HAS_SYNC; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | dbg("%s: lock=%02x", __func__, buf[0]); | ||
| 291 | |||
| 292 | return ret; | ||
| 293 | error: | ||
| 294 | dbg("%s: failed:%d", __func__, ret); | ||
| 295 | return ret; | ||
| 296 | } | ||
| 297 | |||
| 298 | int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber) | ||
| 299 | { | ||
| 300 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 301 | int ret; | ||
| 302 | u8 buf[4]; | ||
| 303 | unsigned int errbits; | ||
| 304 | *ber = 0; | ||
| 305 | /* FIXME: correct calculation */ | ||
| 306 | |||
| 307 | ret = cxd2820r_rd_regs(priv, 0x02039, buf, sizeof(buf)); | ||
| 308 | if (ret) | ||
| 309 | goto error; | ||
| 310 | |||
| 311 | if ((buf[0] >> 4) & 0x01) { | ||
| 312 | errbits = (buf[0] & 0x0f) << 24 | buf[1] << 16 | | ||
| 313 | buf[2] << 8 | buf[3]; | ||
| 314 | |||
| 315 | if (errbits) | ||
| 316 | *ber = errbits * 64 / 16588800; | ||
| 317 | } | ||
| 318 | |||
| 319 | return ret; | ||
| 320 | error: | ||
| 321 | dbg("%s: failed:%d", __func__, ret); | ||
| 322 | return ret; | ||
| 323 | } | ||
| 324 | |||
| 325 | int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, | ||
| 326 | u16 *strength) | ||
| 327 | { | ||
| 328 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 329 | int ret; | ||
| 330 | u8 buf[2]; | ||
| 331 | u16 tmp; | ||
| 332 | |||
| 333 | ret = cxd2820r_rd_regs(priv, 0x02026, buf, sizeof(buf)); | ||
| 334 | if (ret) | ||
| 335 | goto error; | ||
| 336 | |||
| 337 | tmp = (buf[0] & 0x0f) << 8 | buf[1]; | ||
| 338 | tmp = ~tmp & 0x0fff; | ||
| 339 | |||
| 340 | /* scale value to 0x0000-0xffff from 0x0000-0x0fff */ | ||
| 341 | *strength = tmp * 0xffff / 0x0fff; | ||
| 342 | |||
| 343 | return ret; | ||
| 344 | error: | ||
| 345 | dbg("%s: failed:%d", __func__, ret); | ||
| 346 | return ret; | ||
| 347 | } | ||
| 348 | |||
| 349 | int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr) | ||
| 350 | { | ||
| 351 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 352 | int ret; | ||
| 353 | u8 buf[2]; | ||
| 354 | u16 tmp; | ||
| 355 | /* report SNR in dB * 10 */ | ||
| 356 | |||
| 357 | ret = cxd2820r_rd_regs(priv, 0x02028, buf, sizeof(buf)); | ||
| 358 | if (ret) | ||
| 359 | goto error; | ||
| 360 | |||
| 361 | tmp = (buf[0] & 0x0f) << 8 | buf[1]; | ||
| 362 | #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ | ||
| 363 | if (tmp) | ||
| 364 | *snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24) | ||
| 365 | / 100); | ||
| 366 | else | ||
| 367 | *snr = 0; | ||
| 368 | |||
| 369 | dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp); | ||
| 370 | |||
| 371 | return ret; | ||
| 372 | error: | ||
| 373 | dbg("%s: failed:%d", __func__, ret); | ||
| 374 | return ret; | ||
| 375 | } | ||
| 376 | |||
| 377 | int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 378 | { | ||
| 379 | *ucblocks = 0; | ||
| 380 | /* no way to read ? */ | ||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | int cxd2820r_sleep_t2(struct dvb_frontend *fe) | ||
| 385 | { | ||
| 386 | struct cxd2820r_priv *priv = fe->demodulator_priv; | ||
| 387 | int ret, i; | ||
| 388 | struct reg_val_mask tab[] = { | ||
| 389 | { 0x000ff, 0x1f, 0xff }, | ||
| 390 | { 0x00085, 0x00, 0xff }, | ||
| 391 | { 0x00088, 0x01, 0xff }, | ||
| 392 | { 0x02069, 0x00, 0xff }, | ||
| 393 | { 0x00081, 0x00, 0xff }, | ||
| 394 | { 0x00080, 0x00, 0xff }, | ||
| 395 | }; | ||
| 396 | |||
| 397 | dbg("%s", __func__); | ||
| 398 | |||
| 399 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
| 400 | ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, | ||
| 401 | tab[i].mask); | ||
| 402 | if (ret) | ||
| 403 | goto error; | ||
| 404 | } | ||
| 405 | |||
| 406 | priv->delivery_system = SYS_UNDEFINED; | ||
| 407 | |||
| 408 | return ret; | ||
| 409 | error: | ||
| 410 | dbg("%s: failed:%d", __func__, ret); | ||
| 411 | return ret; | ||
| 412 | } | ||
| 413 | |||
| 414 | int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe, | ||
| 415 | struct dvb_frontend_tune_settings *s) | ||
| 416 | { | ||
| 417 | s->min_delay_ms = 1500; | ||
| 418 | s->step_size = fe->ops.info.frequency_stepsize * 2; | ||
| 419 | s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | ||
| 420 | |||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index d4e466a90e43..1d47d4da7d4c 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb/frontends/dib0070.c | |||
| @@ -73,27 +73,47 @@ struct dib0070_state { | |||
| 73 | 73 | ||
| 74 | u8 wbd_gain_current; | 74 | u8 wbd_gain_current; |
| 75 | u16 wbd_offset_3_3[2]; | 75 | u16 wbd_offset_3_3[2]; |
| 76 | |||
| 77 | /* for the I2C transfer */ | ||
| 78 | struct i2c_msg msg[2]; | ||
| 79 | u8 i2c_write_buffer[3]; | ||
| 80 | u8 i2c_read_buffer[2]; | ||
| 76 | }; | 81 | }; |
| 77 | 82 | ||
| 78 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | 83 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) |
| 79 | { | 84 | { |
| 80 | u8 b[2]; | 85 | state->i2c_write_buffer[0] = reg; |
| 81 | struct i2c_msg msg[2] = { | 86 | |
| 82 | { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, | 87 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); |
| 83 | { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, | 88 | state->msg[0].addr = state->cfg->i2c_address; |
| 84 | }; | 89 | state->msg[0].flags = 0; |
| 85 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | 90 | state->msg[0].buf = state->i2c_write_buffer; |
| 91 | state->msg[0].len = 1; | ||
| 92 | state->msg[1].addr = state->cfg->i2c_address; | ||
| 93 | state->msg[1].flags = I2C_M_RD; | ||
| 94 | state->msg[1].buf = state->i2c_read_buffer; | ||
| 95 | state->msg[1].len = 2; | ||
| 96 | |||
| 97 | if (i2c_transfer(state->i2c, state->msg, 2) != 2) { | ||
| 86 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); | 98 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); |
| 87 | return 0; | 99 | return 0; |
| 88 | } | 100 | } |
| 89 | return (b[0] << 8) | b[1]; | 101 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; |
| 90 | } | 102 | } |
| 91 | 103 | ||
| 92 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | 104 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) |
| 93 | { | 105 | { |
| 94 | u8 b[3] = { reg, val >> 8, val & 0xff }; | 106 | state->i2c_write_buffer[0] = reg; |
| 95 | struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; | 107 | state->i2c_write_buffer[1] = val >> 8; |
| 96 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 108 | state->i2c_write_buffer[2] = val & 0xff; |
| 109 | |||
| 110 | memset(state->msg, 0, sizeof(struct i2c_msg)); | ||
| 111 | state->msg[0].addr = state->cfg->i2c_address; | ||
| 112 | state->msg[0].flags = 0; | ||
| 113 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 114 | state->msg[0].len = 3; | ||
| 115 | |||
| 116 | if (i2c_transfer(state->i2c, state->msg, 1) != 1) { | ||
| 97 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); | 117 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); |
| 98 | return -EREMOTEIO; | 118 | return -EREMOTEIO; |
| 99 | } | 119 | } |
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index 52ff1a252a90..c9c935ae41e4 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c | |||
| @@ -191,6 +191,11 @@ struct dib0090_state { | |||
| 191 | u8 wbd_calibration_gain; | 191 | u8 wbd_calibration_gain; |
| 192 | const struct dib0090_wbd_slope *current_wbd_table; | 192 | const struct dib0090_wbd_slope *current_wbd_table; |
| 193 | u16 wbdmux; | 193 | u16 wbdmux; |
| 194 | |||
| 195 | /* for the I2C transfer */ | ||
| 196 | struct i2c_msg msg[2]; | ||
| 197 | u8 i2c_write_buffer[3]; | ||
| 198 | u8 i2c_read_buffer[2]; | ||
| 194 | }; | 199 | }; |
| 195 | 200 | ||
| 196 | struct dib0090_fw_state { | 201 | struct dib0090_fw_state { |
| @@ -198,27 +203,48 @@ struct dib0090_fw_state { | |||
| 198 | struct dvb_frontend *fe; | 203 | struct dvb_frontend *fe; |
| 199 | struct dib0090_identity identity; | 204 | struct dib0090_identity identity; |
| 200 | const struct dib0090_config *config; | 205 | const struct dib0090_config *config; |
| 206 | |||
| 207 | /* for the I2C transfer */ | ||
| 208 | struct i2c_msg msg; | ||
| 209 | u8 i2c_write_buffer[2]; | ||
| 210 | u8 i2c_read_buffer[2]; | ||
| 201 | }; | 211 | }; |
| 202 | 212 | ||
| 203 | static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) | 213 | static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) |
| 204 | { | 214 | { |
| 205 | u8 b[2]; | 215 | state->i2c_write_buffer[0] = reg; |
| 206 | struct i2c_msg msg[2] = { | 216 | |
| 207 | {.addr = state->config->i2c_address, .flags = 0, .buf = ®, .len = 1}, | 217 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); |
| 208 | {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2}, | 218 | state->msg[0].addr = state->config->i2c_address; |
| 209 | }; | 219 | state->msg[0].flags = 0; |
| 210 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | 220 | state->msg[0].buf = state->i2c_write_buffer; |
| 221 | state->msg[0].len = 1; | ||
| 222 | state->msg[1].addr = state->config->i2c_address; | ||
| 223 | state->msg[1].flags = I2C_M_RD; | ||
| 224 | state->msg[1].buf = state->i2c_read_buffer; | ||
| 225 | state->msg[1].len = 2; | ||
| 226 | |||
| 227 | if (i2c_transfer(state->i2c, state->msg, 2) != 2) { | ||
| 211 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); | 228 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); |
| 212 | return 0; | 229 | return 0; |
| 213 | } | 230 | } |
| 214 | return (b[0] << 8) | b[1]; | 231 | |
| 232 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | ||
| 215 | } | 233 | } |
| 216 | 234 | ||
| 217 | static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) | 235 | static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) |
| 218 | { | 236 | { |
| 219 | u8 b[3] = { reg & 0xff, val >> 8, val & 0xff }; | 237 | state->i2c_write_buffer[0] = reg & 0xff; |
| 220 | struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 }; | 238 | state->i2c_write_buffer[1] = val >> 8; |
| 221 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 239 | state->i2c_write_buffer[2] = val & 0xff; |
| 240 | |||
| 241 | memset(state->msg, 0, sizeof(struct i2c_msg)); | ||
| 242 | state->msg[0].addr = state->config->i2c_address; | ||
| 243 | state->msg[0].flags = 0; | ||
| 244 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 245 | state->msg[0].len = 3; | ||
| 246 | |||
| 247 | if (i2c_transfer(state->i2c, state->msg, 1) != 1) { | ||
| 222 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); | 248 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); |
| 223 | return -EREMOTEIO; | 249 | return -EREMOTEIO; |
| 224 | } | 250 | } |
| @@ -227,20 +253,31 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) | |||
| 227 | 253 | ||
| 228 | static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) | 254 | static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) |
| 229 | { | 255 | { |
| 230 | u8 b[2]; | 256 | state->i2c_write_buffer[0] = reg; |
| 231 | struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 }; | 257 | |
| 232 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 258 | memset(&state->msg, 0, sizeof(struct i2c_msg)); |
| 259 | state->msg.addr = reg; | ||
| 260 | state->msg.flags = I2C_M_RD; | ||
| 261 | state->msg.buf = state->i2c_read_buffer; | ||
| 262 | state->msg.len = 2; | ||
| 263 | if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { | ||
| 233 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); | 264 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); |
| 234 | return 0; | 265 | return 0; |
| 235 | } | 266 | } |
| 236 | return (b[0] << 8) | b[1]; | 267 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; |
| 237 | } | 268 | } |
| 238 | 269 | ||
| 239 | static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) | 270 | static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) |
| 240 | { | 271 | { |
| 241 | u8 b[2] = { val >> 8, val & 0xff }; | 272 | state->i2c_write_buffer[0] = val >> 8; |
| 242 | struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 }; | 273 | state->i2c_write_buffer[1] = val & 0xff; |
| 243 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 274 | |
| 275 | memset(&state->msg, 0, sizeof(struct i2c_msg)); | ||
| 276 | state->msg.addr = reg; | ||
| 277 | state->msg.flags = 0; | ||
| 278 | state->msg.buf = state->i2c_write_buffer; | ||
| 279 | state->msg.len = 2; | ||
| 280 | if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { | ||
| 244 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); | 281 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); |
| 245 | return -EREMOTEIO; | 282 | return -EREMOTEIO; |
| 246 | } | 283 | } |
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index 289a79837f24..79cb1c20df24 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c | |||
| @@ -50,6 +50,11 @@ struct dib7000m_state { | |||
| 50 | u16 revision; | 50 | u16 revision; |
| 51 | 51 | ||
| 52 | u8 agc_state; | 52 | u8 agc_state; |
| 53 | |||
| 54 | /* for the I2C transfer */ | ||
| 55 | struct i2c_msg msg[2]; | ||
| 56 | u8 i2c_write_buffer[4]; | ||
| 57 | u8 i2c_read_buffer[2]; | ||
| 53 | }; | 58 | }; |
| 54 | 59 | ||
| 55 | enum dib7000m_power_mode { | 60 | enum dib7000m_power_mode { |
| @@ -64,29 +69,39 @@ enum dib7000m_power_mode { | |||
| 64 | 69 | ||
| 65 | static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) | 70 | static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) |
| 66 | { | 71 | { |
| 67 | u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; | 72 | state->i2c_write_buffer[0] = (reg >> 8) | 0x80; |
| 68 | u8 rb[2]; | 73 | state->i2c_write_buffer[1] = reg & 0xff; |
| 69 | struct i2c_msg msg[2] = { | 74 | |
| 70 | { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, | 75 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); |
| 71 | { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, | 76 | state->msg[0].addr = state->i2c_addr >> 1; |
| 72 | }; | 77 | state->msg[0].flags = 0; |
| 73 | 78 | state->msg[0].buf = state->i2c_write_buffer; | |
| 74 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | 79 | state->msg[0].len = 2; |
| 80 | state->msg[1].addr = state->i2c_addr >> 1; | ||
| 81 | state->msg[1].flags = I2C_M_RD; | ||
| 82 | state->msg[1].buf = state->i2c_read_buffer; | ||
| 83 | state->msg[1].len = 2; | ||
| 84 | |||
| 85 | if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) | ||
| 75 | dprintk("i2c read error on %d",reg); | 86 | dprintk("i2c read error on %d",reg); |
| 76 | 87 | ||
| 77 | return (rb[0] << 8) | rb[1]; | 88 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; |
| 78 | } | 89 | } |
| 79 | 90 | ||
| 80 | static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) | 91 | static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) |
| 81 | { | 92 | { |
| 82 | u8 b[4] = { | 93 | state->i2c_write_buffer[0] = (reg >> 8) & 0xff; |
| 83 | (reg >> 8) & 0xff, reg & 0xff, | 94 | state->i2c_write_buffer[1] = reg & 0xff; |
| 84 | (val >> 8) & 0xff, val & 0xff, | 95 | state->i2c_write_buffer[2] = (val >> 8) & 0xff; |
| 85 | }; | 96 | state->i2c_write_buffer[3] = val & 0xff; |
| 86 | struct i2c_msg msg = { | 97 | |
| 87 | .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | 98 | memset(&state->msg[0], 0, sizeof(struct i2c_msg)); |
| 88 | }; | 99 | state->msg[0].addr = state->i2c_addr >> 1; |
| 89 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 100 | state->msg[0].flags = 0; |
| 101 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 102 | state->msg[0].len = 4; | ||
| 103 | |||
| 104 | return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; | ||
| 90 | } | 105 | } |
| 91 | static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) | 106 | static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) |
| 92 | { | 107 | { |
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 900af60b9d36..0c9f40c2a251 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c | |||
| @@ -63,6 +63,11 @@ struct dib7000p_state { | |||
| 63 | 63 | ||
| 64 | u16 tuner_enable; | 64 | u16 tuner_enable; |
| 65 | struct i2c_adapter dib7090_tuner_adap; | 65 | struct i2c_adapter dib7090_tuner_adap; |
| 66 | |||
| 67 | /* for the I2C transfer */ | ||
| 68 | struct i2c_msg msg[2]; | ||
| 69 | u8 i2c_write_buffer[4]; | ||
| 70 | u8 i2c_read_buffer[2]; | ||
| 66 | }; | 71 | }; |
| 67 | 72 | ||
| 68 | enum dib7000p_power_mode { | 73 | enum dib7000p_power_mode { |
| @@ -76,29 +81,39 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); | |||
| 76 | 81 | ||
| 77 | static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) | 82 | static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) |
| 78 | { | 83 | { |
| 79 | u8 wb[2] = { reg >> 8, reg & 0xff }; | 84 | state->i2c_write_buffer[0] = reg >> 8; |
| 80 | u8 rb[2]; | 85 | state->i2c_write_buffer[1] = reg & 0xff; |
| 81 | struct i2c_msg msg[2] = { | 86 | |
| 82 | {.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2}, | 87 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); |
| 83 | {.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2}, | 88 | state->msg[0].addr = state->i2c_addr >> 1; |
| 84 | }; | 89 | state->msg[0].flags = 0; |
| 90 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 91 | state->msg[0].len = 2; | ||
| 92 | state->msg[1].addr = state->i2c_addr >> 1; | ||
| 93 | state->msg[1].flags = I2C_M_RD; | ||
| 94 | state->msg[1].buf = state->i2c_read_buffer; | ||
| 95 | state->msg[1].len = 2; | ||
| 85 | 96 | ||
| 86 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | 97 | if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) |
| 87 | dprintk("i2c read error on %d", reg); | 98 | dprintk("i2c read error on %d", reg); |
| 88 | 99 | ||
| 89 | return (rb[0] << 8) | rb[1]; | 100 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; |
| 90 | } | 101 | } |
| 91 | 102 | ||
| 92 | static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) | 103 | static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) |
| 93 | { | 104 | { |
| 94 | u8 b[4] = { | 105 | state->i2c_write_buffer[0] = (reg >> 8) & 0xff; |
| 95 | (reg >> 8) & 0xff, reg & 0xff, | 106 | state->i2c_write_buffer[1] = reg & 0xff; |
| 96 | (val >> 8) & 0xff, val & 0xff, | 107 | state->i2c_write_buffer[2] = (val >> 8) & 0xff; |
| 97 | }; | 108 | state->i2c_write_buffer[3] = val & 0xff; |
| 98 | struct i2c_msg msg = { | 109 | |
| 99 | .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | 110 | memset(&state->msg[0], 0, sizeof(struct i2c_msg)); |
| 100 | }; | 111 | state->msg[0].addr = state->i2c_addr >> 1; |
| 101 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 112 | state->msg[0].flags = 0; |
| 113 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 114 | state->msg[0].len = 4; | ||
| 115 | |||
| 116 | return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; | ||
| 102 | } | 117 | } |
| 103 | 118 | ||
| 104 | static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) | 119 | static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) |
| @@ -1550,11 +1565,24 @@ static void dib7000p_release(struct dvb_frontend *demod) | |||
| 1550 | 1565 | ||
| 1551 | int dib7000pc_detection(struct i2c_adapter *i2c_adap) | 1566 | int dib7000pc_detection(struct i2c_adapter *i2c_adap) |
| 1552 | { | 1567 | { |
| 1553 | u8 tx[2], rx[2]; | 1568 | u8 *tx, *rx; |
| 1554 | struct i2c_msg msg[2] = { | 1569 | struct i2c_msg msg[2] = { |
| 1555 | {.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2}, | 1570 | {.addr = 18 >> 1, .flags = 0, .len = 2}, |
| 1556 | {.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2}, | 1571 | {.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2}, |
| 1557 | }; | 1572 | }; |
| 1573 | int ret = 0; | ||
| 1574 | |||
| 1575 | tx = kzalloc(2*sizeof(u8), GFP_KERNEL); | ||
| 1576 | if (!tx) | ||
| 1577 | return -ENOMEM; | ||
| 1578 | rx = kzalloc(2*sizeof(u8), GFP_KERNEL); | ||
| 1579 | if (!rx) { | ||
| 1580 | goto rx_memory_error; | ||
| 1581 | ret = -ENOMEM; | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | msg[0].buf = tx; | ||
| 1585 | msg[1].buf = rx; | ||
| 1558 | 1586 | ||
| 1559 | tx[0] = 0x03; | 1587 | tx[0] = 0x03; |
| 1560 | tx[1] = 0x00; | 1588 | tx[1] = 0x00; |
| @@ -1574,7 +1602,11 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap) | |||
| 1574 | } | 1602 | } |
| 1575 | 1603 | ||
| 1576 | dprintk("-D- DiB7000PC not detected"); | 1604 | dprintk("-D- DiB7000PC not detected"); |
| 1577 | return 0; | 1605 | |
| 1606 | kfree(rx); | ||
| 1607 | rx_memory_error: | ||
| 1608 | kfree(tx); | ||
| 1609 | return ret; | ||
| 1578 | } | 1610 | } |
| 1579 | EXPORT_SYMBOL(dib7000pc_detection); | 1611 | EXPORT_SYMBOL(dib7000pc_detection); |
| 1580 | 1612 | ||
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index c1c3e26906e2..7d2ea112ae2b 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c | |||
| @@ -35,6 +35,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
| 35 | struct i2c_device { | 35 | struct i2c_device { |
| 36 | struct i2c_adapter *adap; | 36 | struct i2c_adapter *adap; |
| 37 | u8 addr; | 37 | u8 addr; |
| 38 | u8 *i2c_write_buffer; | ||
| 39 | u8 *i2c_read_buffer; | ||
| 38 | }; | 40 | }; |
| 39 | 41 | ||
| 40 | struct dib8000_state { | 42 | struct dib8000_state { |
| @@ -70,6 +72,11 @@ struct dib8000_state { | |||
| 70 | u32 status; | 72 | u32 status; |
| 71 | 73 | ||
| 72 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; | 74 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; |
| 75 | |||
| 76 | /* for the I2C transfer */ | ||
| 77 | struct i2c_msg msg[2]; | ||
| 78 | u8 i2c_write_buffer[4]; | ||
| 79 | u8 i2c_read_buffer[2]; | ||
| 73 | }; | 80 | }; |
| 74 | 81 | ||
| 75 | enum dib8000_power_mode { | 82 | enum dib8000_power_mode { |
| @@ -79,22 +86,41 @@ enum dib8000_power_mode { | |||
| 79 | 86 | ||
| 80 | static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) | 87 | static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) |
| 81 | { | 88 | { |
| 82 | u8 wb[2] = { reg >> 8, reg & 0xff }; | ||
| 83 | u8 rb[2]; | ||
| 84 | struct i2c_msg msg[2] = { | 89 | struct i2c_msg msg[2] = { |
| 85 | {.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2}, | 90 | {.addr = i2c->addr >> 1, .flags = 0, |
| 86 | {.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2}, | 91 | .buf = i2c->i2c_write_buffer, .len = 2}, |
| 92 | {.addr = i2c->addr >> 1, .flags = I2C_M_RD, | ||
| 93 | .buf = i2c->i2c_read_buffer, .len = 2}, | ||
| 87 | }; | 94 | }; |
| 88 | 95 | ||
| 96 | msg[0].buf[0] = reg >> 8; | ||
| 97 | msg[0].buf[1] = reg & 0xff; | ||
| 98 | |||
| 89 | if (i2c_transfer(i2c->adap, msg, 2) != 2) | 99 | if (i2c_transfer(i2c->adap, msg, 2) != 2) |
| 90 | dprintk("i2c read error on %d", reg); | 100 | dprintk("i2c read error on %d", reg); |
| 91 | 101 | ||
| 92 | return (rb[0] << 8) | rb[1]; | 102 | return (msg[1].buf[0] << 8) | msg[1].buf[1]; |
| 93 | } | 103 | } |
| 94 | 104 | ||
| 95 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) | 105 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) |
| 96 | { | 106 | { |
| 97 | return dib8000_i2c_read16(&state->i2c, reg); | 107 | state->i2c_write_buffer[0] = reg >> 8; |
| 108 | state->i2c_write_buffer[1] = reg & 0xff; | ||
| 109 | |||
| 110 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | ||
| 111 | state->msg[0].addr = state->i2c.addr >> 1; | ||
| 112 | state->msg[0].flags = 0; | ||
| 113 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 114 | state->msg[0].len = 2; | ||
| 115 | state->msg[1].addr = state->i2c.addr >> 1; | ||
| 116 | state->msg[1].flags = I2C_M_RD; | ||
| 117 | state->msg[1].buf = state->i2c_read_buffer; | ||
| 118 | state->msg[1].len = 2; | ||
| 119 | |||
| 120 | if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) | ||
| 121 | dprintk("i2c read error on %d", reg); | ||
| 122 | |||
| 123 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | ||
| 98 | } | 124 | } |
| 99 | 125 | ||
| 100 | static u32 dib8000_read32(struct dib8000_state *state, u16 reg) | 126 | static u32 dib8000_read32(struct dib8000_state *state, u16 reg) |
| @@ -109,19 +135,34 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) | |||
| 109 | 135 | ||
| 110 | static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) | 136 | static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) |
| 111 | { | 137 | { |
| 112 | u8 b[4] = { | 138 | struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, |
| 113 | (reg >> 8) & 0xff, reg & 0xff, | 139 | .buf = i2c->i2c_write_buffer, .len = 4}; |
| 114 | (val >> 8) & 0xff, val & 0xff, | 140 | int ret = 0; |
| 115 | }; | 141 | |
| 116 | struct i2c_msg msg = { | 142 | msg.buf[0] = (reg >> 8) & 0xff; |
| 117 | .addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4 | 143 | msg.buf[1] = reg & 0xff; |
| 118 | }; | 144 | msg.buf[2] = (val >> 8) & 0xff; |
| 119 | return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 145 | msg.buf[3] = val & 0xff; |
| 146 | |||
| 147 | ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
| 148 | |||
| 149 | return ret; | ||
| 120 | } | 150 | } |
| 121 | 151 | ||
| 122 | static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) | 152 | static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) |
| 123 | { | 153 | { |
| 124 | return dib8000_i2c_write16(&state->i2c, reg, val); | 154 | state->i2c_write_buffer[0] = (reg >> 8) & 0xff; |
| 155 | state->i2c_write_buffer[1] = reg & 0xff; | ||
| 156 | state->i2c_write_buffer[2] = (val >> 8) & 0xff; | ||
| 157 | state->i2c_write_buffer[3] = val & 0xff; | ||
| 158 | |||
| 159 | memset(&state->msg[0], 0, sizeof(struct i2c_msg)); | ||
| 160 | state->msg[0].addr = state->i2c.addr >> 1; | ||
| 161 | state->msg[0].flags = 0; | ||
| 162 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 163 | state->msg[0].len = 4; | ||
| 164 | |||
| 165 | return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; | ||
| 125 | } | 166 | } |
| 126 | 167 | ||
| 127 | static const s16 coeff_2k_sb_1seg_dqpsk[8] = { | 168 | static const s16 coeff_2k_sb_1seg_dqpsk[8] = { |
| @@ -980,30 +1021,31 @@ static void dib8000_update_timf(struct dib8000_state *state) | |||
| 980 | dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default); | 1021 | dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default); |
| 981 | } | 1022 | } |
| 982 | 1023 | ||
| 1024 | static const u16 adc_target_16dB[11] = { | ||
| 1025 | (1 << 13) - 825 - 117, | ||
| 1026 | (1 << 13) - 837 - 117, | ||
| 1027 | (1 << 13) - 811 - 117, | ||
| 1028 | (1 << 13) - 766 - 117, | ||
| 1029 | (1 << 13) - 737 - 117, | ||
| 1030 | (1 << 13) - 693 - 117, | ||
| 1031 | (1 << 13) - 648 - 117, | ||
| 1032 | (1 << 13) - 619 - 117, | ||
| 1033 | (1 << 13) - 575 - 117, | ||
| 1034 | (1 << 13) - 531 - 117, | ||
| 1035 | (1 << 13) - 501 - 117 | ||
| 1036 | }; | ||
| 1037 | static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | ||
| 1038 | |||
| 983 | static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) | 1039 | static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) |
| 984 | { | 1040 | { |
| 985 | u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; | 1041 | u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; |
| 986 | u8 guard, crate, constellation, timeI; | 1042 | u8 guard, crate, constellation, timeI; |
| 987 | u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | ||
| 988 | u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled | 1043 | u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled |
| 989 | const s16 *ncoeff = NULL, *ana_fe; | 1044 | const s16 *ncoeff = NULL, *ana_fe; |
| 990 | u16 tmcc_pow = 0; | 1045 | u16 tmcc_pow = 0; |
| 991 | u16 coff_pow = 0x2800; | 1046 | u16 coff_pow = 0x2800; |
| 992 | u16 init_prbs = 0xfff; | 1047 | u16 init_prbs = 0xfff; |
| 993 | u16 ana_gain = 0; | 1048 | u16 ana_gain = 0; |
| 994 | u16 adc_target_16dB[11] = { | ||
| 995 | (1 << 13) - 825 - 117, | ||
| 996 | (1 << 13) - 837 - 117, | ||
| 997 | (1 << 13) - 811 - 117, | ||
| 998 | (1 << 13) - 766 - 117, | ||
| 999 | (1 << 13) - 737 - 117, | ||
| 1000 | (1 << 13) - 693 - 117, | ||
| 1001 | (1 << 13) - 648 - 117, | ||
| 1002 | (1 << 13) - 619 - 117, | ||
| 1003 | (1 << 13) - 575 - 117, | ||
| 1004 | (1 << 13) - 531 - 117, | ||
| 1005 | (1 << 13) - 501 - 117 | ||
| 1006 | }; | ||
| 1007 | 1049 | ||
| 1008 | if (state->ber_monitored_layer != LAYER_ALL) | 1050 | if (state->ber_monitored_layer != LAYER_ALL) |
| 1009 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer); | 1051 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer); |
| @@ -2379,10 +2421,22 @@ EXPORT_SYMBOL(dib8000_get_slave_frontend); | |||
| 2379 | 2421 | ||
| 2380 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) | 2422 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) |
| 2381 | { | 2423 | { |
| 2382 | int k = 0; | 2424 | int k = 0, ret = 0; |
| 2383 | u8 new_addr = 0; | 2425 | u8 new_addr = 0; |
| 2384 | struct i2c_device client = {.adap = host }; | 2426 | struct i2c_device client = {.adap = host }; |
| 2385 | 2427 | ||
| 2428 | client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
| 2429 | if (!client.i2c_write_buffer) { | ||
| 2430 | dprintk("%s: not enough memory", __func__); | ||
| 2431 | return -ENOMEM; | ||
| 2432 | } | ||
| 2433 | client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
| 2434 | if (!client.i2c_read_buffer) { | ||
| 2435 | dprintk("%s: not enough memory", __func__); | ||
| 2436 | ret = -ENOMEM; | ||
| 2437 | goto error_memory; | ||
| 2438 | } | ||
| 2439 | |||
| 2386 | for (k = no_of_demods - 1; k >= 0; k--) { | 2440 | for (k = no_of_demods - 1; k >= 0; k--) { |
| 2387 | /* designated i2c address */ | 2441 | /* designated i2c address */ |
| 2388 | new_addr = first_addr + (k << 1); | 2442 | new_addr = first_addr + (k << 1); |
| @@ -2394,7 +2448,8 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau | |||
| 2394 | client.addr = default_addr; | 2448 | client.addr = default_addr; |
| 2395 | if (dib8000_identify(&client) == 0) { | 2449 | if (dib8000_identify(&client) == 0) { |
| 2396 | dprintk("#%d: not identified", k); | 2450 | dprintk("#%d: not identified", k); |
| 2397 | return -EINVAL; | 2451 | ret = -EINVAL; |
| 2452 | goto error; | ||
| 2398 | } | 2453 | } |
| 2399 | } | 2454 | } |
| 2400 | 2455 | ||
| @@ -2420,7 +2475,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau | |||
| 2420 | dib8000_i2c_write16(&client, 1286, 0); | 2475 | dib8000_i2c_write16(&client, 1286, 0); |
| 2421 | } | 2476 | } |
| 2422 | 2477 | ||
| 2423 | return 0; | 2478 | error: |
| 2479 | kfree(client.i2c_read_buffer); | ||
| 2480 | error_memory: | ||
| 2481 | kfree(client.i2c_write_buffer); | ||
| 2482 | |||
| 2483 | return ret; | ||
| 2424 | } | 2484 | } |
| 2425 | 2485 | ||
| 2426 | EXPORT_SYMBOL(dib8000_i2c_enumeration); | 2486 | EXPORT_SYMBOL(dib8000_i2c_enumeration); |
| @@ -2519,6 +2579,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s | |||
| 2519 | memcpy(&state->cfg, cfg, sizeof(struct dib8000_config)); | 2579 | memcpy(&state->cfg, cfg, sizeof(struct dib8000_config)); |
| 2520 | state->i2c.adap = i2c_adap; | 2580 | state->i2c.adap = i2c_adap; |
| 2521 | state->i2c.addr = i2c_addr; | 2581 | state->i2c.addr = i2c_addr; |
| 2582 | state->i2c.i2c_write_buffer = state->i2c_write_buffer; | ||
| 2583 | state->i2c.i2c_read_buffer = state->i2c_read_buffer; | ||
| 2522 | state->gpio_val = cfg->gpio_val; | 2584 | state->gpio_val = cfg->gpio_val; |
| 2523 | state->gpio_dir = cfg->gpio_dir; | 2585 | state->gpio_dir = cfg->gpio_dir; |
| 2524 | 2586 | ||
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c index 91518761a2da..a0855883b5ce 100644 --- a/drivers/media/dvb/frontends/dib9000.c +++ b/drivers/media/dvb/frontends/dib9000.c | |||
| @@ -27,6 +27,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
| 27 | struct i2c_device { | 27 | struct i2c_device { |
| 28 | struct i2c_adapter *i2c_adap; | 28 | struct i2c_adapter *i2c_adap; |
| 29 | u8 i2c_addr; | 29 | u8 i2c_addr; |
| 30 | u8 *i2c_read_buffer; | ||
| 31 | u8 *i2c_write_buffer; | ||
| 30 | }; | 32 | }; |
| 31 | 33 | ||
| 32 | /* lock */ | 34 | /* lock */ |
| @@ -92,11 +94,16 @@ struct dib9000_state { | |||
| 92 | 94 | ||
| 93 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; | 95 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; |
| 94 | u16 component_bus_speed; | 96 | u16 component_bus_speed; |
| 97 | |||
| 98 | /* for the I2C transfer */ | ||
| 99 | struct i2c_msg msg[2]; | ||
| 100 | u8 i2c_write_buffer[255]; | ||
| 101 | u8 i2c_read_buffer[255]; | ||
| 95 | }; | 102 | }; |
| 96 | 103 | ||
| 97 | u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 104 | static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 98 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 105 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 99 | 0, 0, 0 | 106 | 0, 0, 0, 0, 0, 0, 0, 0 |
| 100 | }; | 107 | }; |
| 101 | 108 | ||
| 102 | enum dib9000_power_mode { | 109 | enum dib9000_power_mode { |
| @@ -217,25 +224,33 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 | |||
| 217 | u32 chunk_size = 126; | 224 | u32 chunk_size = 126; |
| 218 | u32 l; | 225 | u32 l; |
| 219 | int ret; | 226 | int ret; |
| 220 | u8 wb[2] = { reg >> 8, reg & 0xff }; | ||
| 221 | struct i2c_msg msg[2] = { | ||
| 222 | {.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2}, | ||
| 223 | {.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len}, | ||
| 224 | }; | ||
| 225 | 227 | ||
| 226 | if (state->platform.risc.fw_is_running && (reg < 1024)) | 228 | if (state->platform.risc.fw_is_running && (reg < 1024)) |
| 227 | return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len); | 229 | return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len); |
| 228 | 230 | ||
| 231 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | ||
| 232 | state->msg[0].addr = state->i2c.i2c_addr >> 1; | ||
| 233 | state->msg[0].flags = 0; | ||
| 234 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 235 | state->msg[0].len = 2; | ||
| 236 | state->msg[1].addr = state->i2c.i2c_addr >> 1; | ||
| 237 | state->msg[1].flags = I2C_M_RD; | ||
| 238 | state->msg[1].buf = b; | ||
| 239 | state->msg[1].len = len; | ||
| 240 | |||
| 241 | state->i2c_write_buffer[0] = reg >> 8; | ||
| 242 | state->i2c_write_buffer[1] = reg & 0xff; | ||
| 243 | |||
| 229 | if (attribute & DATA_BUS_ACCESS_MODE_8BIT) | 244 | if (attribute & DATA_BUS_ACCESS_MODE_8BIT) |
| 230 | wb[0] |= (1 << 5); | 245 | state->i2c_write_buffer[0] |= (1 << 5); |
| 231 | if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) | 246 | if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) |
| 232 | wb[0] |= (1 << 4); | 247 | state->i2c_write_buffer[0] |= (1 << 4); |
| 233 | 248 | ||
| 234 | do { | 249 | do { |
| 235 | l = len < chunk_size ? len : chunk_size; | 250 | l = len < chunk_size ? len : chunk_size; |
| 236 | msg[1].len = l; | 251 | state->msg[1].len = l; |
| 237 | msg[1].buf = b; | 252 | state->msg[1].buf = b; |
| 238 | ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0; | 253 | ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0; |
| 239 | if (ret != 0) { | 254 | if (ret != 0) { |
| 240 | dprintk("i2c read error on %d", reg); | 255 | dprintk("i2c read error on %d", reg); |
| 241 | return -EREMOTEIO; | 256 | return -EREMOTEIO; |
| @@ -253,50 +268,47 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 | |||
| 253 | 268 | ||
| 254 | static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg) | 269 | static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg) |
| 255 | { | 270 | { |
| 256 | u8 b[2]; | ||
| 257 | u8 wb[2] = { reg >> 8, reg & 0xff }; | ||
| 258 | struct i2c_msg msg[2] = { | 271 | struct i2c_msg msg[2] = { |
| 259 | {.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2}, | 272 | {.addr = i2c->i2c_addr >> 1, .flags = 0, |
| 260 | {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2}, | 273 | .buf = i2c->i2c_write_buffer, .len = 2}, |
| 274 | {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, | ||
| 275 | .buf = i2c->i2c_read_buffer, .len = 2}, | ||
| 261 | }; | 276 | }; |
| 262 | 277 | ||
| 278 | i2c->i2c_write_buffer[0] = reg >> 8; | ||
| 279 | i2c->i2c_write_buffer[1] = reg & 0xff; | ||
| 280 | |||
| 263 | if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) { | 281 | if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) { |
| 264 | dprintk("read register %x error", reg); | 282 | dprintk("read register %x error", reg); |
| 265 | return 0; | 283 | return 0; |
| 266 | } | 284 | } |
| 267 | 285 | ||
| 268 | return (b[0] << 8) | b[1]; | 286 | return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1]; |
| 269 | } | 287 | } |
| 270 | 288 | ||
| 271 | static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg) | 289 | static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg) |
| 272 | { | 290 | { |
| 273 | u8 b[2]; | 291 | if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0) |
| 274 | if (dib9000_read16_attr(state, reg, b, 2, 0) != 0) | ||
| 275 | return 0; | 292 | return 0; |
| 276 | return (b[0] << 8 | b[1]); | 293 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; |
| 277 | } | 294 | } |
| 278 | 295 | ||
| 279 | static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute) | 296 | static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute) |
| 280 | { | 297 | { |
| 281 | u8 b[2]; | 298 | if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, |
| 282 | if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0) | 299 | attribute) != 0) |
| 283 | return 0; | 300 | return 0; |
| 284 | return (b[0] << 8 | b[1]); | 301 | return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; |
| 285 | } | 302 | } |
| 286 | 303 | ||
| 287 | #define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) | 304 | #define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) |
| 288 | 305 | ||
| 289 | static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute) | 306 | static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute) |
| 290 | { | 307 | { |
| 291 | u8 b[255]; | ||
| 292 | u32 chunk_size = 126; | 308 | u32 chunk_size = 126; |
| 293 | u32 l; | 309 | u32 l; |
| 294 | int ret; | 310 | int ret; |
| 295 | 311 | ||
| 296 | struct i2c_msg msg = { | ||
| 297 | .addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2 | ||
| 298 | }; | ||
| 299 | |||
| 300 | if (state->platform.risc.fw_is_running && (reg < 1024)) { | 312 | if (state->platform.risc.fw_is_running && (reg < 1024)) { |
| 301 | if (dib9000_risc_apb_access_write | 313 | if (dib9000_risc_apb_access_write |
| 302 | (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0) | 314 | (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0) |
| @@ -304,20 +316,26 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * | |||
| 304 | return 0; | 316 | return 0; |
| 305 | } | 317 | } |
| 306 | 318 | ||
| 307 | b[0] = (reg >> 8) & 0xff; | 319 | memset(&state->msg[0], 0, sizeof(struct i2c_msg)); |
| 308 | b[1] = (reg) & 0xff; | 320 | state->msg[0].addr = state->i2c.i2c_addr >> 1; |
| 321 | state->msg[0].flags = 0; | ||
| 322 | state->msg[0].buf = state->i2c_write_buffer; | ||
| 323 | state->msg[0].len = len + 2; | ||
| 324 | |||
| 325 | state->i2c_write_buffer[0] = (reg >> 8) & 0xff; | ||
| 326 | state->i2c_write_buffer[1] = (reg) & 0xff; | ||
| 309 | 327 | ||
| 310 | if (attribute & DATA_BUS_ACCESS_MODE_8BIT) | 328 | if (attribute & DATA_BUS_ACCESS_MODE_8BIT) |
| 311 | b[0] |= (1 << 5); | 329 | state->i2c_write_buffer[0] |= (1 << 5); |
| 312 | if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) | 330 | if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) |
| 313 | b[0] |= (1 << 4); | 331 | state->i2c_write_buffer[0] |= (1 << 4); |
| 314 | 332 | ||
| 315 | do { | 333 | do { |
| 316 | l = len < chunk_size ? len : chunk_size; | 334 | l = len < chunk_size ? len : chunk_size; |
| 317 | msg.len = l + 2; | 335 | state->msg[0].len = l + 2; |
| 318 | memcpy(&b[2], buf, l); | 336 | memcpy(&state->i2c_write_buffer[2], buf, l); |
| 319 | 337 | ||
| 320 | ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 338 | ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; |
| 321 | 339 | ||
| 322 | buf += l; | 340 | buf += l; |
| 323 | len -= l; | 341 | len -= l; |
| @@ -331,11 +349,16 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * | |||
| 331 | 349 | ||
| 332 | static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) | 350 | static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) |
| 333 | { | 351 | { |
| 334 | u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff }; | ||
| 335 | struct i2c_msg msg = { | 352 | struct i2c_msg msg = { |
| 336 | .addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | 353 | .addr = i2c->i2c_addr >> 1, .flags = 0, |
| 354 | .buf = i2c->i2c_write_buffer, .len = 4 | ||
| 337 | }; | 355 | }; |
| 338 | 356 | ||
| 357 | i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff; | ||
| 358 | i2c->i2c_write_buffer[1] = reg & 0xff; | ||
| 359 | i2c->i2c_write_buffer[2] = (val >> 8) & 0xff; | ||
| 360 | i2c->i2c_write_buffer[3] = val & 0xff; | ||
| 361 | |||
| 339 | return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 362 | return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; |
| 340 | } | 363 | } |
| 341 | 364 | ||
| @@ -1015,8 +1038,8 @@ static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i) | |||
| 1015 | return 0; | 1038 | return 0; |
| 1016 | dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i); | 1039 | dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i); |
| 1017 | do { | 1040 | do { |
| 1018 | dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1); | 1041 | dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1); |
| 1019 | } while (i && index_loop--); | 1042 | } while (state->i2c_read_buffer[0] && index_loop--); |
| 1020 | 1043 | ||
| 1021 | if (index_loop > 0) | 1044 | if (index_loop > 0) |
| 1022 | return 0; | 1045 | return 0; |
| @@ -1139,7 +1162,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1139 | 1162 | ||
| 1140 | s8 intlv_native; | 1163 | s8 intlv_native; |
| 1141 | }; | 1164 | }; |
| 1142 | struct dibDVBTChannel ch; | 1165 | struct dibDVBTChannel *ch; |
| 1143 | int ret = 0; | 1166 | int ret = 0; |
| 1144 | 1167 | ||
| 1145 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 1168 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| @@ -1148,9 +1171,12 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1148 | ret = -EIO; | 1171 | ret = -EIO; |
| 1149 | } | 1172 | } |
| 1150 | 1173 | ||
| 1151 | dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel)); | 1174 | dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, |
| 1175 | state->i2c_read_buffer, sizeof(struct dibDVBTChannel)); | ||
| 1176 | ch = (struct dibDVBTChannel *)state->i2c_read_buffer; | ||
| 1177 | |||
| 1152 | 1178 | ||
| 1153 | switch (ch.spectrum_inversion & 0x7) { | 1179 | switch (ch->spectrum_inversion & 0x7) { |
| 1154 | case 1: | 1180 | case 1: |
| 1155 | state->fe[0]->dtv_property_cache.inversion = INVERSION_ON; | 1181 | state->fe[0]->dtv_property_cache.inversion = INVERSION_ON; |
| 1156 | break; | 1182 | break; |
| @@ -1162,7 +1188,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1162 | state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO; | 1188 | state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO; |
| 1163 | break; | 1189 | break; |
| 1164 | } | 1190 | } |
| 1165 | switch (ch.nfft) { | 1191 | switch (ch->nfft) { |
| 1166 | case 0: | 1192 | case 0: |
| 1167 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; | 1193 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; |
| 1168 | break; | 1194 | break; |
| @@ -1177,7 +1203,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1177 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; | 1203 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; |
| 1178 | break; | 1204 | break; |
| 1179 | } | 1205 | } |
| 1180 | switch (ch.guard) { | 1206 | switch (ch->guard) { |
| 1181 | case 0: | 1207 | case 0: |
| 1182 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; | 1208 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; |
| 1183 | break; | 1209 | break; |
| @@ -1195,7 +1221,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1195 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; | 1221 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; |
| 1196 | break; | 1222 | break; |
| 1197 | } | 1223 | } |
| 1198 | switch (ch.constellation) { | 1224 | switch (ch->constellation) { |
| 1199 | case 2: | 1225 | case 2: |
| 1200 | state->fe[0]->dtv_property_cache.modulation = QAM_64; | 1226 | state->fe[0]->dtv_property_cache.modulation = QAM_64; |
| 1201 | break; | 1227 | break; |
| @@ -1210,7 +1236,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1210 | state->fe[0]->dtv_property_cache.modulation = QAM_AUTO; | 1236 | state->fe[0]->dtv_property_cache.modulation = QAM_AUTO; |
| 1211 | break; | 1237 | break; |
| 1212 | } | 1238 | } |
| 1213 | switch (ch.hrch) { | 1239 | switch (ch->hrch) { |
| 1214 | case 0: | 1240 | case 0: |
| 1215 | state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE; | 1241 | state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE; |
| 1216 | break; | 1242 | break; |
| @@ -1222,7 +1248,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1222 | state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO; | 1248 | state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO; |
| 1223 | break; | 1249 | break; |
| 1224 | } | 1250 | } |
| 1225 | switch (ch.code_rate_hp) { | 1251 | switch (ch->code_rate_hp) { |
| 1226 | case 1: | 1252 | case 1: |
| 1227 | state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2; | 1253 | state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2; |
| 1228 | break; | 1254 | break; |
| @@ -1243,7 +1269,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p | |||
| 1243 | state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO; | 1269 | state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO; |
| 1244 | break; | 1270 | break; |
| 1245 | } | 1271 | } |
| 1246 | switch (ch.code_rate_lp) { | 1272 | switch (ch->code_rate_lp) { |
| 1247 | case 1: | 1273 | case 1: |
| 1248 | state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2; | 1274 | state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2; |
| 1249 | break; | 1275 | break; |
| @@ -1439,9 +1465,10 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete | |||
| 1439 | break; | 1465 | break; |
| 1440 | case CT_DEMOD_STEP_1: | 1466 | case CT_DEMOD_STEP_1: |
| 1441 | if (search) | 1467 | if (search) |
| 1442 | dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1); | 1468 | dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1); |
| 1443 | else | 1469 | else |
| 1444 | dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1); | 1470 | dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1); |
| 1471 | i = (s8)state->i2c_read_buffer[0]; | ||
| 1445 | switch (i) { /* something happened */ | 1472 | switch (i) { /* something happened */ |
| 1446 | case 0: | 1473 | case 0: |
| 1447 | break; | 1474 | break; |
| @@ -2038,14 +2065,17 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | |||
| 2038 | static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) | 2065 | static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) |
| 2039 | { | 2066 | { |
| 2040 | struct dib9000_state *state = fe->demodulator_priv; | 2067 | struct dib9000_state *state = fe->demodulator_priv; |
| 2041 | u16 c[16]; | 2068 | u16 *c; |
| 2042 | 2069 | ||
| 2043 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2070 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2044 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) | 2071 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2045 | return -EIO; | 2072 | return -EIO; |
| 2046 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | 2073 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, |
| 2074 | state->i2c_read_buffer, 16 * 2); | ||
| 2047 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2075 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2048 | 2076 | ||
| 2077 | c = (u16 *)state->i2c_read_buffer; | ||
| 2078 | |||
| 2049 | *ber = c[10] << 16 | c[11]; | 2079 | *ber = c[10] << 16 | c[11]; |
| 2050 | return 0; | 2080 | return 0; |
| 2051 | } | 2081 | } |
| @@ -2054,7 +2084,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | |||
| 2054 | { | 2084 | { |
| 2055 | struct dib9000_state *state = fe->demodulator_priv; | 2085 | struct dib9000_state *state = fe->demodulator_priv; |
| 2056 | u8 index_frontend; | 2086 | u8 index_frontend; |
| 2057 | u16 c[16]; | 2087 | u16 *c = (u16 *)state->i2c_read_buffer; |
| 2058 | u16 val; | 2088 | u16 val; |
| 2059 | 2089 | ||
| 2060 | *strength = 0; | 2090 | *strength = 0; |
| @@ -2069,7 +2099,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | |||
| 2069 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2099 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2070 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) | 2100 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2071 | return -EIO; | 2101 | return -EIO; |
| 2072 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | 2102 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); |
| 2073 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2103 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2074 | 2104 | ||
| 2075 | val = 65535 - c[4]; | 2105 | val = 65535 - c[4]; |
| @@ -2083,14 +2113,14 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | |||
| 2083 | static u32 dib9000_get_snr(struct dvb_frontend *fe) | 2113 | static u32 dib9000_get_snr(struct dvb_frontend *fe) |
| 2084 | { | 2114 | { |
| 2085 | struct dib9000_state *state = fe->demodulator_priv; | 2115 | struct dib9000_state *state = fe->demodulator_priv; |
| 2086 | u16 c[16]; | 2116 | u16 *c = (u16 *)state->i2c_read_buffer; |
| 2087 | u32 n, s, exp; | 2117 | u32 n, s, exp; |
| 2088 | u16 val; | 2118 | u16 val; |
| 2089 | 2119 | ||
| 2090 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2120 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2091 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) | 2121 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2092 | return -EIO; | 2122 | return -EIO; |
| 2093 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | 2123 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); |
| 2094 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2124 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2095 | 2125 | ||
| 2096 | val = c[7]; | 2126 | val = c[7]; |
| @@ -2137,12 +2167,12 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) | |||
| 2137 | static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) | 2167 | static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) |
| 2138 | { | 2168 | { |
| 2139 | struct dib9000_state *state = fe->demodulator_priv; | 2169 | struct dib9000_state *state = fe->demodulator_priv; |
| 2140 | u16 c[16]; | 2170 | u16 *c = (u16 *)state->i2c_read_buffer; |
| 2141 | 2171 | ||
| 2142 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2172 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2143 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) | 2173 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2144 | return -EIO; | 2174 | return -EIO; |
| 2145 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | 2175 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); |
| 2146 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2176 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2147 | 2177 | ||
| 2148 | *unc = c[12]; | 2178 | *unc = c[12]; |
| @@ -2151,10 +2181,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) | |||
| 2151 | 2181 | ||
| 2152 | int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) | 2182 | int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) |
| 2153 | { | 2183 | { |
| 2154 | int k = 0; | 2184 | int k = 0, ret = 0; |
| 2155 | u8 new_addr = 0; | 2185 | u8 new_addr = 0; |
| 2156 | struct i2c_device client = {.i2c_adap = i2c }; | 2186 | struct i2c_device client = {.i2c_adap = i2c }; |
| 2157 | 2187 | ||
| 2188 | client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
| 2189 | if (!client.i2c_write_buffer) { | ||
| 2190 | dprintk("%s: not enough memory", __func__); | ||
| 2191 | return -ENOMEM; | ||
| 2192 | } | ||
| 2193 | client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
| 2194 | if (!client.i2c_read_buffer) { | ||
| 2195 | dprintk("%s: not enough memory", __func__); | ||
| 2196 | ret = -ENOMEM; | ||
| 2197 | goto error_memory; | ||
| 2198 | } | ||
| 2199 | |||
| 2158 | client.i2c_addr = default_addr + 16; | 2200 | client.i2c_addr = default_addr + 16; |
| 2159 | dib9000_i2c_write16(&client, 1796, 0x0); | 2201 | dib9000_i2c_write16(&client, 1796, 0x0); |
| 2160 | 2202 | ||
| @@ -2178,7 +2220,8 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul | |||
| 2178 | client.i2c_addr = default_addr; | 2220 | client.i2c_addr = default_addr; |
| 2179 | if (dib9000_identify(&client) == 0) { | 2221 | if (dib9000_identify(&client) == 0) { |
| 2180 | dprintk("DiB9000 #%d: not identified", k); | 2222 | dprintk("DiB9000 #%d: not identified", k); |
| 2181 | return -EIO; | 2223 | ret = -EIO; |
| 2224 | goto error; | ||
| 2182 | } | 2225 | } |
| 2183 | } | 2226 | } |
| 2184 | 2227 | ||
| @@ -2196,7 +2239,12 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul | |||
| 2196 | dib9000_i2c_write16(&client, 1795, 0); | 2239 | dib9000_i2c_write16(&client, 1795, 0); |
| 2197 | } | 2240 | } |
| 2198 | 2241 | ||
| 2199 | return 0; | 2242 | error: |
| 2243 | kfree(client.i2c_read_buffer); | ||
| 2244 | error_memory: | ||
| 2245 | kfree(client.i2c_write_buffer); | ||
| 2246 | |||
| 2247 | return ret; | ||
| 2200 | } | 2248 | } |
| 2201 | EXPORT_SYMBOL(dib9000_i2c_enumeration); | 2249 | EXPORT_SYMBOL(dib9000_i2c_enumeration); |
| 2202 | 2250 | ||
| @@ -2255,12 +2303,16 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c | |||
| 2255 | if (st == NULL) | 2303 | if (st == NULL) |
| 2256 | return NULL; | 2304 | return NULL; |
| 2257 | fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL); | 2305 | fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL); |
| 2258 | if (fe == NULL) | 2306 | if (fe == NULL) { |
| 2307 | kfree(st); | ||
| 2259 | return NULL; | 2308 | return NULL; |
| 2309 | } | ||
| 2260 | 2310 | ||
| 2261 | memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config)); | 2311 | memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config)); |
| 2262 | st->i2c.i2c_adap = i2c_adap; | 2312 | st->i2c.i2c_adap = i2c_adap; |
| 2263 | st->i2c.i2c_addr = i2c_addr; | 2313 | st->i2c.i2c_addr = i2c_addr; |
| 2314 | st->i2c.i2c_write_buffer = st->i2c_write_buffer; | ||
| 2315 | st->i2c.i2c_read_buffer = st->i2c_read_buffer; | ||
| 2264 | 2316 | ||
| 2265 | st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS; | 2317 | st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS; |
| 2266 | st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES; | 2318 | st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES; |
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index f6938f97feb4..dc5d17a67579 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
| @@ -10,30 +10,39 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
| 10 | 10 | ||
| 11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) | 11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) |
| 12 | { | 12 | { |
| 13 | u8 b[4] = { | 13 | mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; |
| 14 | (reg >> 8) & 0xff, reg & 0xff, | 14 | mst->i2c_write_buffer[1] = reg & 0xff; |
| 15 | (val >> 8) & 0xff, val & 0xff, | 15 | mst->i2c_write_buffer[2] = (val >> 8) & 0xff; |
| 16 | }; | 16 | mst->i2c_write_buffer[3] = val & 0xff; |
| 17 | struct i2c_msg msg = { | 17 | |
| 18 | .addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4 | 18 | memset(mst->msg, 0, sizeof(struct i2c_msg)); |
| 19 | }; | 19 | mst->msg[0].addr = mst->i2c_addr; |
| 20 | 20 | mst->msg[0].flags = 0; | |
| 21 | return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 21 | mst->msg[0].buf = mst->i2c_write_buffer; |
| 22 | mst->msg[0].len = 4; | ||
| 23 | |||
| 24 | return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; | ||
| 22 | } | 25 | } |
| 23 | 26 | ||
| 24 | static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) | 27 | static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) |
| 25 | { | 28 | { |
| 26 | u8 wb[2] = { reg >> 8, reg & 0xff }; | 29 | mst->i2c_write_buffer[0] = reg >> 8; |
| 27 | u8 rb[2]; | 30 | mst->i2c_write_buffer[1] = reg & 0xff; |
| 28 | struct i2c_msg msg[2] = { | 31 | |
| 29 | {.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2}, | 32 | memset(mst->msg, 0, 2 * sizeof(struct i2c_msg)); |
| 30 | {.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2}, | 33 | mst->msg[0].addr = mst->i2c_addr; |
| 31 | }; | 34 | mst->msg[0].flags = 0; |
| 32 | 35 | mst->msg[0].buf = mst->i2c_write_buffer; | |
| 33 | if (i2c_transfer(mst->i2c_adap, msg, 2) != 2) | 36 | mst->msg[0].len = 2; |
| 37 | mst->msg[1].addr = mst->i2c_addr; | ||
| 38 | mst->msg[1].flags = I2C_M_RD; | ||
| 39 | mst->msg[1].buf = mst->i2c_read_buffer; | ||
| 40 | mst->msg[1].len = 2; | ||
| 41 | |||
| 42 | if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) | ||
| 34 | dprintk("i2c read error on %d", reg); | 43 | dprintk("i2c read error on %d", reg); |
| 35 | 44 | ||
| 36 | return (rb[0] << 8) | rb[1]; | 45 | return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; |
| 37 | } | 46 | } |
| 38 | 47 | ||
| 39 | static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) | 48 | static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) |
| @@ -248,26 +257,32 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, | |||
| 248 | struct i2c_msg msg[], int num) | 257 | struct i2c_msg msg[], int num) |
| 249 | { | 258 | { |
| 250 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | 259 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); |
| 251 | struct i2c_msg m[2 + num]; | ||
| 252 | u8 tx_open[4], tx_close[4]; | ||
| 253 | 260 | ||
| 254 | memset(m, 0, sizeof(struct i2c_msg) * (2 + num)); | 261 | if (num > 32) { |
| 262 | dprintk("%s: too much I2C message to be transmitted (%i).\ | ||
| 263 | Maximum is 32", __func__, num); | ||
| 264 | return -ENOMEM; | ||
| 265 | } | ||
| 266 | |||
| 267 | memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); | ||
| 255 | 268 | ||
| 256 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); | 269 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); |
| 257 | 270 | ||
| 258 | dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); | 271 | /* open the gate */ |
| 259 | m[0].addr = mst->i2c_addr; | 272 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); |
| 260 | m[0].buf = tx_open; | 273 | mst->msg[0].addr = mst->i2c_addr; |
| 261 | m[0].len = 4; | 274 | mst->msg[0].buf = &mst->i2c_write_buffer[0]; |
| 275 | mst->msg[0].len = 4; | ||
| 262 | 276 | ||
| 263 | memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); | 277 | memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); |
| 264 | 278 | ||
| 265 | dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); | 279 | /* close the gate */ |
| 266 | m[num + 1].addr = mst->i2c_addr; | 280 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); |
| 267 | m[num + 1].buf = tx_close; | 281 | mst->msg[num + 1].addr = mst->i2c_addr; |
| 268 | m[num + 1].len = 4; | 282 | mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; |
| 283 | mst->msg[num + 1].len = 4; | ||
| 269 | 284 | ||
| 270 | return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO; | 285 | return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; |
| 271 | } | 286 | } |
| 272 | 287 | ||
| 273 | static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { | 288 | static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { |
| @@ -279,26 +294,32 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, | |||
| 279 | struct i2c_msg msg[], int num) | 294 | struct i2c_msg msg[], int num) |
| 280 | { | 295 | { |
| 281 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | 296 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); |
| 282 | struct i2c_msg m[2 + num]; | ||
| 283 | u8 tx_open[4], tx_close[4]; | ||
| 284 | 297 | ||
| 285 | memset(m, 0, sizeof(struct i2c_msg) * (2 + num)); | 298 | if (num > 32) { |
| 299 | dprintk("%s: too much I2C message to be transmitted (%i).\ | ||
| 300 | Maximum is 32", __func__, num); | ||
| 301 | return -ENOMEM; | ||
| 302 | } | ||
| 303 | |||
| 304 | memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); | ||
| 286 | 305 | ||
| 287 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); | 306 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); |
| 288 | 307 | ||
| 289 | dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); | 308 | /* open the gate */ |
| 290 | m[0].addr = mst->i2c_addr; | 309 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); |
| 291 | m[0].buf = tx_open; | 310 | mst->msg[0].addr = mst->i2c_addr; |
| 292 | m[0].len = 4; | 311 | mst->msg[0].buf = &mst->i2c_write_buffer[0]; |
| 312 | mst->msg[0].len = 4; | ||
| 293 | 313 | ||
| 294 | memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); | 314 | memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); |
| 295 | 315 | ||
| 296 | dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); | 316 | /* close the gate */ |
| 297 | m[num + 1].addr = mst->i2c_addr; | 317 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); |
| 298 | m[num + 1].buf = tx_close; | 318 | mst->msg[num + 1].addr = mst->i2c_addr; |
| 299 | m[num + 1].len = 4; | 319 | mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; |
| 320 | mst->msg[num + 1].len = 4; | ||
| 300 | 321 | ||
| 301 | return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO; | 322 | return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; |
| 302 | } | 323 | } |
| 303 | 324 | ||
| 304 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { | 325 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { |
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index 977d343369aa..f031165c0459 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
| @@ -28,6 +28,11 @@ struct dibx000_i2c_master { | |||
| 28 | u8 i2c_addr; | 28 | u8 i2c_addr; |
| 29 | 29 | ||
| 30 | u16 base_reg; | 30 | u16 base_reg; |
| 31 | |||
| 32 | /* for the I2C transfer */ | ||
| 33 | struct i2c_msg msg[34]; | ||
| 34 | u8 i2c_write_buffer[8]; | ||
| 35 | u8 i2c_read_buffer[2]; | ||
| 31 | }; | 36 | }; |
| 32 | 37 | ||
| 33 | extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, | 38 | extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, |
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c deleted file mode 100644 index 536f02b17338..000000000000 --- a/drivers/media/dvb/frontends/drx397xD.c +++ /dev/null | |||
| @@ -1,1511 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Micronas drx397xD demodulator | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #define DEBUG /* uncomment if you want debugging output */ | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/moduleparam.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/device.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/string.h> | ||
| 28 | #include <linux/firmware.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <asm/div64.h> | ||
| 31 | |||
| 32 | #include "dvb_frontend.h" | ||
| 33 | #include "drx397xD.h" | ||
| 34 | |||
| 35 | static const char mod_name[] = "drx397xD"; | ||
| 36 | |||
| 37 | #define MAX_CLOCK_DRIFT 200 /* maximal 200 PPM allowed */ | ||
| 38 | |||
| 39 | #define F_SET_0D0h 1 | ||
| 40 | #define F_SET_0D4h 2 | ||
| 41 | |||
| 42 | enum fw_ix { | ||
| 43 | #define _FW_ENTRY(a, b, c) b | ||
| 44 | #include "drx397xD_fw.h" | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* chip specifics */ | ||
| 48 | struct drx397xD_state { | ||
| 49 | struct i2c_adapter *i2c; | ||
| 50 | struct dvb_frontend frontend; | ||
| 51 | struct drx397xD_config config; | ||
| 52 | enum fw_ix chip_rev; | ||
| 53 | int flags; | ||
| 54 | u32 bandwidth_parm; /* internal bandwidth conversions */ | ||
| 55 | u32 f_osc; /* w90: actual osc frequency [Hz] */ | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* Firmware */ | ||
| 59 | static const char *blob_name[] = { | ||
| 60 | #define _BLOB_ENTRY(a, b) a | ||
| 61 | #include "drx397xD_fw.h" | ||
| 62 | }; | ||
| 63 | |||
| 64 | enum blob_ix { | ||
| 65 | #define _BLOB_ENTRY(a, b) b | ||
| 66 | #include "drx397xD_fw.h" | ||
| 67 | }; | ||
| 68 | |||
| 69 | static struct { | ||
| 70 | const char *name; | ||
| 71 | const struct firmware *file; | ||
| 72 | rwlock_t lock; | ||
| 73 | int refcnt; | ||
| 74 | const u8 *data[ARRAY_SIZE(blob_name)]; | ||
| 75 | } fw[] = { | ||
| 76 | #define _FW_ENTRY(a, b, c) { \ | ||
| 77 | .name = a, \ | ||
| 78 | .file = NULL, \ | ||
| 79 | .lock = __RW_LOCK_UNLOCKED(fw[c].lock), \ | ||
| 80 | .refcnt = 0, \ | ||
| 81 | .data = { } } | ||
| 82 | #include "drx397xD_fw.h" | ||
| 83 | }; | ||
| 84 | |||
| 85 | /* use only with writer lock acquired */ | ||
| 86 | static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix) | ||
| 87 | { | ||
| 88 | memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); | ||
| 89 | if (fw[ix].file) | ||
| 90 | release_firmware(fw[ix].file); | ||
| 91 | } | ||
| 92 | |||
| 93 | static void drx_release_fw(struct drx397xD_state *s) | ||
| 94 | { | ||
| 95 | enum fw_ix ix = s->chip_rev; | ||
| 96 | |||
| 97 | pr_debug("%s\n", __func__); | ||
| 98 | |||
| 99 | write_lock(&fw[ix].lock); | ||
| 100 | if (fw[ix].refcnt) { | ||
| 101 | fw[ix].refcnt--; | ||
| 102 | if (fw[ix].refcnt == 0) | ||
| 103 | _drx_release_fw(s, ix); | ||
| 104 | } | ||
| 105 | write_unlock(&fw[ix].lock); | ||
| 106 | } | ||
| 107 | |||
| 108 | static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix) | ||
| 109 | { | ||
| 110 | const u8 *data; | ||
| 111 | size_t size, len; | ||
| 112 | int i = 0, j, rc = -EINVAL; | ||
| 113 | |||
| 114 | pr_debug("%s\n", __func__); | ||
| 115 | |||
| 116 | if (ix < 0 || ix >= ARRAY_SIZE(fw)) | ||
| 117 | return -EINVAL; | ||
| 118 | s->chip_rev = ix; | ||
| 119 | |||
| 120 | write_lock(&fw[ix].lock); | ||
| 121 | if (fw[ix].file) { | ||
| 122 | rc = 0; | ||
| 123 | goto exit_ok; | ||
| 124 | } | ||
| 125 | memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); | ||
| 126 | |||
| 127 | rc = request_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent); | ||
| 128 | if (rc != 0) { | ||
| 129 | printk(KERN_ERR "%s: Firmware \"%s\" not available\n", | ||
| 130 | mod_name, fw[ix].name); | ||
| 131 | goto exit_err; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (!fw[ix].file->data || fw[ix].file->size < 10) | ||
| 135 | goto exit_corrupt; | ||
| 136 | |||
| 137 | data = fw[ix].file->data; | ||
| 138 | size = fw[ix].file->size; | ||
| 139 | |||
| 140 | if (data[i++] != 2) /* check firmware version */ | ||
| 141 | goto exit_corrupt; | ||
| 142 | |||
| 143 | do { | ||
| 144 | switch (data[i++]) { | ||
| 145 | case 0x00: /* bytecode */ | ||
| 146 | if (i >= size) | ||
| 147 | break; | ||
| 148 | i += data[i]; | ||
| 149 | case 0x01: /* reset */ | ||
| 150 | case 0x02: /* sleep */ | ||
| 151 | i++; | ||
| 152 | break; | ||
| 153 | case 0xfe: /* name */ | ||
| 154 | len = strnlen(&data[i], size - i); | ||
| 155 | if (i + len + 1 >= size) | ||
| 156 | goto exit_corrupt; | ||
| 157 | if (data[i + len + 1] != 0) | ||
| 158 | goto exit_corrupt; | ||
| 159 | for (j = 0; j < ARRAY_SIZE(blob_name); j++) { | ||
| 160 | if (strcmp(blob_name[j], &data[i]) == 0) { | ||
| 161 | fw[ix].data[j] = &data[i + len + 1]; | ||
| 162 | pr_debug("Loading %s\n", blob_name[j]); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | i += len + 1; | ||
| 166 | break; | ||
| 167 | case 0xff: /* file terminator */ | ||
| 168 | if (i == size) { | ||
| 169 | rc = 0; | ||
| 170 | goto exit_ok; | ||
| 171 | } | ||
| 172 | default: | ||
| 173 | goto exit_corrupt; | ||
| 174 | } | ||
| 175 | } while (i < size); | ||
| 176 | |||
| 177 | exit_corrupt: | ||
| 178 | printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name); | ||
| 179 | exit_err: | ||
| 180 | _drx_release_fw(s, ix); | ||
| 181 | fw[ix].refcnt--; | ||
| 182 | exit_ok: | ||
| 183 | fw[ix].refcnt++; | ||
| 184 | write_unlock(&fw[ix].lock); | ||
| 185 | |||
| 186 | return rc; | ||
| 187 | } | ||
| 188 | |||
| 189 | /* i2c bus IO */ | ||
| 190 | static int write_fw(struct drx397xD_state *s, enum blob_ix ix) | ||
| 191 | { | ||
| 192 | const u8 *data; | ||
| 193 | int len, rc = 0, i = 0; | ||
| 194 | struct i2c_msg msg = { | ||
| 195 | .addr = s->config.demod_address, | ||
| 196 | .flags = 0 | ||
| 197 | }; | ||
| 198 | |||
| 199 | if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) { | ||
| 200 | pr_debug("%s drx_fw_ix_t out of range\n", __func__); | ||
| 201 | return -EINVAL; | ||
| 202 | } | ||
| 203 | pr_debug("%s %s\n", __func__, blob_name[ix]); | ||
| 204 | |||
| 205 | read_lock(&fw[s->chip_rev].lock); | ||
| 206 | data = fw[s->chip_rev].data[ix]; | ||
| 207 | if (!data) { | ||
| 208 | rc = -EINVAL; | ||
| 209 | goto exit_rc; | ||
| 210 | } | ||
| 211 | |||
| 212 | for (;;) { | ||
| 213 | switch (data[i++]) { | ||
| 214 | case 0: /* bytecode */ | ||
| 215 | len = data[i++]; | ||
| 216 | msg.len = len; | ||
| 217 | msg.buf = (__u8 *) &data[i]; | ||
| 218 | if (i2c_transfer(s->i2c, &msg, 1) != 1) { | ||
| 219 | rc = -EIO; | ||
| 220 | goto exit_rc; | ||
| 221 | } | ||
| 222 | i += len; | ||
| 223 | break; | ||
| 224 | case 1: /* reset */ | ||
| 225 | case 2: /* sleep */ | ||
| 226 | i++; | ||
| 227 | break; | ||
| 228 | default: | ||
| 229 | goto exit_rc; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | exit_rc: | ||
| 233 | read_unlock(&fw[s->chip_rev].lock); | ||
| 234 | |||
| 235 | return rc; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* Function is not endian safe, use the RD16 wrapper below */ | ||
| 239 | static int _read16(struct drx397xD_state *s, __le32 i2c_adr) | ||
| 240 | { | ||
| 241 | int rc; | ||
| 242 | u8 a[4]; | ||
| 243 | __le16 v; | ||
| 244 | struct i2c_msg msg[2] = { | ||
| 245 | { | ||
| 246 | .addr = s->config.demod_address, | ||
| 247 | .flags = 0, | ||
| 248 | .buf = a, | ||
| 249 | .len = sizeof(a) | ||
| 250 | }, { | ||
| 251 | .addr = s->config.demod_address, | ||
| 252 | .flags = I2C_M_RD, | ||
| 253 | .buf = (u8 *)&v, | ||
| 254 | .len = sizeof(v) | ||
| 255 | } | ||
| 256 | }; | ||
| 257 | |||
| 258 | *(__le32 *) a = i2c_adr; | ||
| 259 | |||
| 260 | rc = i2c_transfer(s->i2c, msg, 2); | ||
| 261 | if (rc != 2) | ||
| 262 | return -EIO; | ||
| 263 | |||
| 264 | return le16_to_cpu(v); | ||
| 265 | } | ||
| 266 | |||
| 267 | /* Function is not endian safe, use the WR16.. wrappers below */ | ||
| 268 | static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val) | ||
| 269 | { | ||
| 270 | u8 a[6]; | ||
| 271 | int rc; | ||
| 272 | struct i2c_msg msg = { | ||
| 273 | .addr = s->config.demod_address, | ||
| 274 | .flags = 0, | ||
| 275 | .buf = a, | ||
| 276 | .len = sizeof(a) | ||
| 277 | }; | ||
| 278 | |||
| 279 | *(__le32 *)a = i2c_adr; | ||
| 280 | *(__le16 *)&a[4] = val; | ||
| 281 | |||
| 282 | rc = i2c_transfer(s->i2c, &msg, 1); | ||
| 283 | if (rc != 1) | ||
| 284 | return -EIO; | ||
| 285 | |||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | #define WR16(ss, adr, val) \ | ||
| 290 | _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val)) | ||
| 291 | #define WR16_E0(ss, adr, val) \ | ||
| 292 | _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val)) | ||
| 293 | #define RD16(ss, adr) \ | ||
| 294 | _read16(ss, I2C_ADR_C0(adr)) | ||
| 295 | |||
| 296 | #define EXIT_RC(cmd) \ | ||
| 297 | if ((rc = (cmd)) < 0) \ | ||
| 298 | goto exit_rc | ||
| 299 | |||
| 300 | /* Tuner callback */ | ||
| 301 | static int PLL_Set(struct drx397xD_state *s, | ||
| 302 | struct dvb_frontend_parameters *fep, int *df_tuner) | ||
| 303 | { | ||
| 304 | struct dvb_frontend *fe = &s->frontend; | ||
| 305 | u32 f_tuner, f = fep->frequency; | ||
| 306 | int rc; | ||
| 307 | |||
| 308 | pr_debug("%s\n", __func__); | ||
| 309 | |||
| 310 | if ((f > s->frontend.ops.tuner_ops.info.frequency_max) || | ||
| 311 | (f < s->frontend.ops.tuner_ops.info.frequency_min)) | ||
| 312 | return -EINVAL; | ||
| 313 | |||
| 314 | *df_tuner = 0; | ||
| 315 | if (!s->frontend.ops.tuner_ops.set_params || | ||
| 316 | !s->frontend.ops.tuner_ops.get_frequency) | ||
| 317 | return -ENOSYS; | ||
| 318 | |||
| 319 | rc = s->frontend.ops.tuner_ops.set_params(fe, fep); | ||
| 320 | if (rc < 0) | ||
| 321 | return rc; | ||
| 322 | |||
| 323 | rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner); | ||
| 324 | if (rc < 0) | ||
| 325 | return rc; | ||
| 326 | |||
| 327 | *df_tuner = f_tuner - f; | ||
| 328 | pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f, | ||
| 329 | f_tuner); | ||
| 330 | |||
| 331 | return 0; | ||
| 332 | } | ||
| 333 | |||
| 334 | /* Demodulator helper functions */ | ||
| 335 | static int SC_WaitForReady(struct drx397xD_state *s) | ||
| 336 | { | ||
| 337 | int cnt = 1000; | ||
| 338 | int rc; | ||
| 339 | |||
| 340 | pr_debug("%s\n", __func__); | ||
| 341 | |||
| 342 | while (cnt--) { | ||
| 343 | rc = RD16(s, 0x820043); | ||
| 344 | if (rc == 0) | ||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | return -1; | ||
| 349 | } | ||
| 350 | |||
| 351 | static int SC_SendCommand(struct drx397xD_state *s, int cmd) | ||
| 352 | { | ||
| 353 | int rc; | ||
| 354 | |||
| 355 | pr_debug("%s\n", __func__); | ||
| 356 | |||
| 357 | WR16(s, 0x820043, cmd); | ||
| 358 | SC_WaitForReady(s); | ||
| 359 | rc = RD16(s, 0x820042); | ||
| 360 | if ((rc & 0xffff) == 0xffff) | ||
| 361 | return -1; | ||
| 362 | |||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | static int HI_Command(struct drx397xD_state *s, u16 cmd) | ||
| 367 | { | ||
| 368 | int rc, cnt = 1000; | ||
| 369 | |||
| 370 | pr_debug("%s\n", __func__); | ||
| 371 | |||
| 372 | rc = WR16(s, 0x420032, cmd); | ||
| 373 | if (rc < 0) | ||
| 374 | return rc; | ||
| 375 | |||
| 376 | do { | ||
| 377 | rc = RD16(s, 0x420032); | ||
| 378 | if (rc == 0) { | ||
| 379 | rc = RD16(s, 0x420031); | ||
| 380 | return rc; | ||
| 381 | } | ||
| 382 | if (rc < 0) | ||
| 383 | return rc; | ||
| 384 | } while (--cnt); | ||
| 385 | |||
| 386 | return rc; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int HI_CfgCommand(struct drx397xD_state *s) | ||
| 390 | { | ||
| 391 | |||
| 392 | pr_debug("%s\n", __func__); | ||
| 393 | |||
| 394 | WR16(s, 0x420033, 0x3973); | ||
| 395 | WR16(s, 0x420034, s->config.w50); /* code 4, log 4 */ | ||
| 396 | WR16(s, 0x420035, s->config.w52); /* code 15, log 9 */ | ||
| 397 | WR16(s, 0x420036, s->config.demod_address << 1); | ||
| 398 | WR16(s, 0x420037, s->config.w56); /* code (set_i2c ?? initX 1 ), log 1 */ | ||
| 399 | /* WR16(s, 0x420033, 0x3973); */ | ||
| 400 | if ((s->config.w56 & 8) == 0) | ||
| 401 | return HI_Command(s, 3); | ||
| 402 | |||
| 403 | return WR16(s, 0x420032, 0x3); | ||
| 404 | } | ||
| 405 | |||
| 406 | static const u8 fastIncrDecLUT_15273[] = { | ||
| 407 | 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, | ||
| 408 | 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f | ||
| 409 | }; | ||
| 410 | |||
| 411 | static const u8 slowIncrDecLUT_15272[] = { | ||
| 412 | 3, 4, 4, 5, 6 | ||
| 413 | }; | ||
| 414 | |||
| 415 | static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc) | ||
| 416 | { | ||
| 417 | u16 w06 = agc->w06; | ||
| 418 | u16 w08 = agc->w08; | ||
| 419 | u16 w0A = agc->w0A; | ||
| 420 | u16 w0C = agc->w0C; | ||
| 421 | int quot, rem, i, rc = -EINVAL; | ||
| 422 | |||
| 423 | pr_debug("%s\n", __func__); | ||
| 424 | |||
| 425 | if (agc->w04 > 0x3ff) | ||
| 426 | goto exit_rc; | ||
| 427 | |||
| 428 | if (agc->d00 == 1) { | ||
| 429 | EXIT_RC(RD16(s, 0x0c20010)); | ||
| 430 | rc &= ~0x10; | ||
| 431 | EXIT_RC(WR16(s, 0x0c20010, rc)); | ||
| 432 | return WR16(s, 0x0c20030, agc->w04 & 0x7ff); | ||
| 433 | } | ||
| 434 | |||
| 435 | if (agc->d00 != 0) | ||
| 436 | goto exit_rc; | ||
| 437 | if (w0A < w08) | ||
| 438 | goto exit_rc; | ||
| 439 | if (w0A > 0x3ff) | ||
| 440 | goto exit_rc; | ||
| 441 | if (w0C > 0x3ff) | ||
| 442 | goto exit_rc; | ||
| 443 | if (w06 > 0x3ff) | ||
| 444 | goto exit_rc; | ||
| 445 | |||
| 446 | EXIT_RC(RD16(s, 0x0c20010)); | ||
| 447 | rc |= 0x10; | ||
| 448 | EXIT_RC(WR16(s, 0x0c20010, rc)); | ||
| 449 | |||
| 450 | EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff)); | ||
| 451 | EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1)); | ||
| 452 | EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff)); | ||
| 453 | |||
| 454 | quot = w0C / 113; | ||
| 455 | rem = w0C % 113; | ||
| 456 | if (quot <= 8) { | ||
| 457 | quot = 8 - quot; | ||
| 458 | } else { | ||
| 459 | quot = 0; | ||
| 460 | rem += 113; | ||
| 461 | } | ||
| 462 | |||
| 463 | EXIT_RC(WR16(s, 0x0c20024, quot)); | ||
| 464 | |||
| 465 | i = fastIncrDecLUT_15273[rem / 8]; | ||
| 466 | EXIT_RC(WR16(s, 0x0c2002d, i)); | ||
| 467 | EXIT_RC(WR16(s, 0x0c2002e, i)); | ||
| 468 | |||
| 469 | i = slowIncrDecLUT_15272[rem / 28]; | ||
| 470 | EXIT_RC(WR16(s, 0x0c2002b, i)); | ||
| 471 | rc = WR16(s, 0x0c2002c, i); | ||
| 472 | exit_rc: | ||
| 473 | return rc; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) | ||
| 477 | { | ||
| 478 | u16 w04 = agc->w04; | ||
| 479 | u16 w06 = agc->w06; | ||
| 480 | int rc = -1; | ||
| 481 | |||
| 482 | pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06); | ||
| 483 | |||
| 484 | if (w04 > 0x3ff) | ||
| 485 | goto exit_rc; | ||
| 486 | |||
| 487 | switch (agc->d00) { | ||
| 488 | case 1: | ||
| 489 | if (w04 == 0x3ff) | ||
| 490 | w04 = 0x400; | ||
| 491 | |||
| 492 | EXIT_RC(WR16(s, 0x0c20036, w04)); | ||
| 493 | s->config.w9C &= ~2; | ||
| 494 | EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); | ||
| 495 | EXIT_RC(RD16(s, 0x0c20010)); | ||
| 496 | rc &= 0xbfdf; | ||
| 497 | EXIT_RC(WR16(s, 0x0c20010, rc)); | ||
| 498 | EXIT_RC(RD16(s, 0x0c20013)); | ||
| 499 | rc &= ~2; | ||
| 500 | break; | ||
| 501 | case 0: | ||
| 502 | /* loc_8000659 */ | ||
| 503 | s->config.w9C &= ~2; | ||
| 504 | EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); | ||
| 505 | EXIT_RC(RD16(s, 0x0c20010)); | ||
| 506 | rc &= 0xbfdf; | ||
| 507 | rc |= 0x4000; | ||
| 508 | EXIT_RC(WR16(s, 0x0c20010, rc)); | ||
| 509 | EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f)); | ||
| 510 | EXIT_RC(RD16(s, 0x0c20013)); | ||
| 511 | rc &= ~2; | ||
| 512 | break; | ||
| 513 | default: | ||
| 514 | s->config.w9C |= 2; | ||
| 515 | EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); | ||
| 516 | EXIT_RC(RD16(s, 0x0c20010)); | ||
| 517 | rc &= 0xbfdf; | ||
| 518 | EXIT_RC(WR16(s, 0x0c20010, rc)); | ||
| 519 | |||
| 520 | EXIT_RC(WR16(s, 0x0c20036, 0)); | ||
| 521 | |||
| 522 | EXIT_RC(RD16(s, 0x0c20013)); | ||
| 523 | rc |= 2; | ||
| 524 | } | ||
| 525 | rc = WR16(s, 0x0c20013, rc); | ||
| 526 | |||
| 527 | exit_rc: | ||
| 528 | return rc; | ||
| 529 | } | ||
| 530 | |||
| 531 | static int GetLockStatus(struct drx397xD_state *s, int *lockstat) | ||
| 532 | { | ||
| 533 | int rc; | ||
| 534 | |||
| 535 | *lockstat = 0; | ||
| 536 | |||
| 537 | rc = RD16(s, 0x082004b); | ||
| 538 | if (rc < 0) | ||
| 539 | return rc; | ||
| 540 | |||
| 541 | if (s->config.d60 != 2) | ||
| 542 | return 0; | ||
| 543 | |||
| 544 | if ((rc & 7) == 7) | ||
| 545 | *lockstat |= 1; | ||
| 546 | if ((rc & 3) == 3) | ||
| 547 | *lockstat |= 2; | ||
| 548 | if (rc & 1) | ||
| 549 | *lockstat |= 4; | ||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | static int CorrectSysClockDeviation(struct drx397xD_state *s) | ||
| 554 | { | ||
| 555 | int rc = -EINVAL; | ||
| 556 | int lockstat; | ||
| 557 | u32 clk, clk_limit; | ||
| 558 | |||
| 559 | pr_debug("%s\n", __func__); | ||
| 560 | |||
| 561 | if (s->config.d5C == 0) { | ||
| 562 | EXIT_RC(WR16(s, 0x08200e8, 0x010)); | ||
| 563 | EXIT_RC(WR16(s, 0x08200e9, 0x113)); | ||
| 564 | s->config.d5C = 1; | ||
| 565 | return rc; | ||
| 566 | } | ||
| 567 | if (s->config.d5C != 1) | ||
| 568 | goto exit_rc; | ||
| 569 | |||
| 570 | rc = RD16(s, 0x0820048); | ||
| 571 | |||
| 572 | rc = GetLockStatus(s, &lockstat); | ||
| 573 | if (rc < 0) | ||
| 574 | goto exit_rc; | ||
| 575 | if ((lockstat & 1) == 0) | ||
| 576 | goto exit_rc; | ||
| 577 | |||
| 578 | EXIT_RC(WR16(s, 0x0420033, 0x200)); | ||
| 579 | EXIT_RC(WR16(s, 0x0420034, 0xc5)); | ||
| 580 | EXIT_RC(WR16(s, 0x0420035, 0x10)); | ||
| 581 | EXIT_RC(WR16(s, 0x0420036, 0x1)); | ||
| 582 | EXIT_RC(WR16(s, 0x0420037, 0xa)); | ||
| 583 | EXIT_RC(HI_Command(s, 6)); | ||
| 584 | EXIT_RC(RD16(s, 0x0420040)); | ||
| 585 | clk = rc; | ||
| 586 | EXIT_RC(RD16(s, 0x0420041)); | ||
| 587 | clk |= rc << 16; | ||
| 588 | |||
| 589 | if (clk <= 0x26ffff) | ||
| 590 | goto exit_rc; | ||
| 591 | if (clk > 0x610000) | ||
| 592 | goto exit_rc; | ||
| 593 | |||
| 594 | if (!s->bandwidth_parm) | ||
| 595 | return -EINVAL; | ||
| 596 | |||
| 597 | /* round & convert to Hz */ | ||
| 598 | clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21; | ||
| 599 | clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000; | ||
| 600 | |||
| 601 | if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) { | ||
| 602 | s->f_osc = clk; | ||
| 603 | pr_debug("%s: osc %d %d [Hz]\n", __func__, | ||
| 604 | s->config.f_osc * 1000, clk - s->config.f_osc * 1000); | ||
| 605 | } | ||
| 606 | rc = WR16(s, 0x08200e8, 0); | ||
| 607 | |||
| 608 | exit_rc: | ||
| 609 | return rc; | ||
| 610 | } | ||
| 611 | |||
| 612 | static int ConfigureMPEGOutput(struct drx397xD_state *s, int type) | ||
| 613 | { | ||
| 614 | int rc, si, bp; | ||
| 615 | |||
| 616 | pr_debug("%s\n", __func__); | ||
| 617 | |||
| 618 | si = s->config.wA0; | ||
| 619 | if (s->config.w98 == 0) { | ||
| 620 | si |= 1; | ||
| 621 | bp = 0; | ||
| 622 | } else { | ||
| 623 | si &= ~1; | ||
| 624 | bp = 0x200; | ||
| 625 | } | ||
| 626 | if (s->config.w9A == 0) | ||
| 627 | si |= 0x80; | ||
| 628 | else | ||
| 629 | si &= ~0x80; | ||
| 630 | |||
| 631 | EXIT_RC(WR16(s, 0x2150045, 0)); | ||
| 632 | EXIT_RC(WR16(s, 0x2150010, si)); | ||
| 633 | EXIT_RC(WR16(s, 0x2150011, bp)); | ||
| 634 | rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0)); | ||
| 635 | |||
| 636 | exit_rc: | ||
| 637 | return rc; | ||
| 638 | } | ||
| 639 | |||
| 640 | static int drx_tune(struct drx397xD_state *s, | ||
| 641 | struct dvb_frontend_parameters *fep) | ||
| 642 | { | ||
| 643 | u16 v22 = 0; | ||
| 644 | u16 v1C = 0; | ||
| 645 | u16 v1A = 0; | ||
| 646 | u16 v18 = 0; | ||
| 647 | u32 edi = 0, ebx = 0, ebp = 0, edx = 0; | ||
| 648 | u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0; | ||
| 649 | |||
| 650 | int rc, df_tuner = 0; | ||
| 651 | int a, b, c, d; | ||
| 652 | pr_debug("%s %d\n", __func__, s->config.d60); | ||
| 653 | |||
| 654 | if (s->config.d60 != 2) | ||
| 655 | goto set_tuner; | ||
| 656 | rc = CorrectSysClockDeviation(s); | ||
| 657 | if (rc < 0) | ||
| 658 | goto set_tuner; | ||
| 659 | |||
| 660 | s->config.d60 = 1; | ||
| 661 | rc = ConfigureMPEGOutput(s, 0); | ||
| 662 | if (rc < 0) | ||
| 663 | goto set_tuner; | ||
| 664 | set_tuner: | ||
| 665 | |||
| 666 | rc = PLL_Set(s, fep, &df_tuner); | ||
| 667 | if (rc < 0) { | ||
| 668 | printk(KERN_ERR "Error in pll_set\n"); | ||
| 669 | goto exit_rc; | ||
| 670 | } | ||
| 671 | msleep(200); | ||
| 672 | |||
| 673 | a = rc = RD16(s, 0x2150016); | ||
| 674 | if (rc < 0) | ||
| 675 | goto exit_rc; | ||
| 676 | b = rc = RD16(s, 0x2150010); | ||
| 677 | if (rc < 0) | ||
| 678 | goto exit_rc; | ||
| 679 | c = rc = RD16(s, 0x2150034); | ||
| 680 | if (rc < 0) | ||
| 681 | goto exit_rc; | ||
| 682 | d = rc = RD16(s, 0x2150035); | ||
| 683 | if (rc < 0) | ||
| 684 | goto exit_rc; | ||
| 685 | rc = WR16(s, 0x2150014, c); | ||
| 686 | rc = WR16(s, 0x2150015, d); | ||
| 687 | rc = WR16(s, 0x2150010, 0); | ||
| 688 | rc = WR16(s, 0x2150000, 2); | ||
| 689 | rc = WR16(s, 0x2150036, 0x0fff); | ||
| 690 | rc = WR16(s, 0x2150016, a); | ||
| 691 | |||
| 692 | rc = WR16(s, 0x2150010, 2); | ||
| 693 | rc = WR16(s, 0x2150007, 0); | ||
| 694 | rc = WR16(s, 0x2150000, 1); | ||
| 695 | rc = WR16(s, 0x2110000, 0); | ||
| 696 | rc = WR16(s, 0x0800000, 0); | ||
| 697 | rc = WR16(s, 0x2800000, 0); | ||
| 698 | rc = WR16(s, 0x2110010, 0x664); | ||
| 699 | |||
| 700 | rc = write_fw(s, DRXD_ResetECRAM); | ||
| 701 | rc = WR16(s, 0x2110000, 1); | ||
| 702 | |||
| 703 | rc = write_fw(s, DRXD_InitSC); | ||
| 704 | if (rc < 0) | ||
| 705 | goto exit_rc; | ||
| 706 | |||
| 707 | rc = SetCfgIfAgc(s, &s->config.ifagc); | ||
| 708 | if (rc < 0) | ||
| 709 | goto exit_rc; | ||
| 710 | |||
| 711 | rc = SetCfgRfAgc(s, &s->config.rfagc); | ||
| 712 | if (rc < 0) | ||
| 713 | goto exit_rc; | ||
| 714 | |||
| 715 | if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K) | ||
| 716 | v22 = 1; | ||
| 717 | switch (fep->u.ofdm.transmission_mode) { | ||
| 718 | case TRANSMISSION_MODE_8K: | ||
| 719 | edi = 1; | ||
| 720 | if (s->chip_rev == DRXD_FW_B1) | ||
| 721 | break; | ||
| 722 | |||
| 723 | rc = WR16(s, 0x2010010, 0); | ||
| 724 | if (rc < 0) | ||
| 725 | break; | ||
| 726 | v1C = 0x63; | ||
| 727 | v1A = 0x53; | ||
| 728 | v18 = 0x43; | ||
| 729 | break; | ||
| 730 | default: | ||
| 731 | edi = 0; | ||
| 732 | if (s->chip_rev == DRXD_FW_B1) | ||
| 733 | break; | ||
| 734 | |||
| 735 | rc = WR16(s, 0x2010010, 1); | ||
| 736 | if (rc < 0) | ||
| 737 | break; | ||
| 738 | |||
| 739 | v1C = 0x61; | ||
| 740 | v1A = 0x47; | ||
| 741 | v18 = 0x41; | ||
| 742 | } | ||
| 743 | |||
| 744 | switch (fep->u.ofdm.guard_interval) { | ||
| 745 | case GUARD_INTERVAL_1_4: | ||
| 746 | edi |= 0x0c; | ||
| 747 | break; | ||
| 748 | case GUARD_INTERVAL_1_8: | ||
| 749 | edi |= 0x08; | ||
| 750 | break; | ||
| 751 | case GUARD_INTERVAL_1_16: | ||
| 752 | edi |= 0x04; | ||
| 753 | break; | ||
| 754 | case GUARD_INTERVAL_1_32: | ||
| 755 | break; | ||
| 756 | default: | ||
| 757 | v22 |= 2; | ||
| 758 | } | ||
| 759 | |||
| 760 | ebx = 0; | ||
| 761 | ebp = 0; | ||
| 762 | v20 = 0; | ||
| 763 | v1E = 0; | ||
| 764 | v16 = 0; | ||
| 765 | v14 = 0; | ||
| 766 | v12 = 0; | ||
| 767 | v10 = 0; | ||
| 768 | v0E = 0; | ||
| 769 | |||
| 770 | switch (fep->u.ofdm.hierarchy_information) { | ||
| 771 | case HIERARCHY_1: | ||
| 772 | edi |= 0x40; | ||
| 773 | if (s->chip_rev == DRXD_FW_B1) | ||
| 774 | break; | ||
| 775 | rc = WR16(s, 0x1c10047, 1); | ||
| 776 | if (rc < 0) | ||
| 777 | goto exit_rc; | ||
| 778 | rc = WR16(s, 0x2010012, 1); | ||
| 779 | if (rc < 0) | ||
| 780 | goto exit_rc; | ||
| 781 | ebx = 0x19f; | ||
| 782 | ebp = 0x1fb; | ||
| 783 | v20 = 0x0c0; | ||
| 784 | v1E = 0x195; | ||
| 785 | v16 = 0x1d6; | ||
| 786 | v14 = 0x1ef; | ||
| 787 | v12 = 4; | ||
| 788 | v10 = 5; | ||
| 789 | v0E = 5; | ||
| 790 | break; | ||
| 791 | case HIERARCHY_2: | ||
| 792 | edi |= 0x80; | ||
| 793 | if (s->chip_rev == DRXD_FW_B1) | ||
| 794 | break; | ||
| 795 | rc = WR16(s, 0x1c10047, 2); | ||
| 796 | if (rc < 0) | ||
| 797 | goto exit_rc; | ||
| 798 | rc = WR16(s, 0x2010012, 2); | ||
| 799 | if (rc < 0) | ||
| 800 | goto exit_rc; | ||
| 801 | ebx = 0x08f; | ||
| 802 | ebp = 0x12f; | ||
| 803 | v20 = 0x0c0; | ||
| 804 | v1E = 0x11e; | ||
| 805 | v16 = 0x1d6; | ||
| 806 | v14 = 0x15e; | ||
| 807 | v12 = 4; | ||
| 808 | v10 = 5; | ||
| 809 | v0E = 5; | ||
| 810 | break; | ||
| 811 | case HIERARCHY_4: | ||
| 812 | edi |= 0xc0; | ||
| 813 | if (s->chip_rev == DRXD_FW_B1) | ||
| 814 | break; | ||
| 815 | rc = WR16(s, 0x1c10047, 3); | ||
| 816 | if (rc < 0) | ||
| 817 | goto exit_rc; | ||
| 818 | rc = WR16(s, 0x2010012, 3); | ||
| 819 | if (rc < 0) | ||
| 820 | goto exit_rc; | ||
| 821 | ebx = 0x14d; | ||
| 822 | ebp = 0x197; | ||
| 823 | v20 = 0x0c0; | ||
| 824 | v1E = 0x1ce; | ||
| 825 | v16 = 0x1d6; | ||
| 826 | v14 = 0x11a; | ||
| 827 | v12 = 4; | ||
| 828 | v10 = 6; | ||
| 829 | v0E = 5; | ||
| 830 | break; | ||
| 831 | default: | ||
| 832 | v22 |= 8; | ||
| 833 | if (s->chip_rev == DRXD_FW_B1) | ||
| 834 | break; | ||
| 835 | rc = WR16(s, 0x1c10047, 0); | ||
| 836 | if (rc < 0) | ||
| 837 | goto exit_rc; | ||
| 838 | rc = WR16(s, 0x2010012, 0); | ||
| 839 | if (rc < 0) | ||
| 840 | goto exit_rc; | ||
| 841 | /* QPSK QAM16 QAM64 */ | ||
| 842 | ebx = 0x19f; /* 62 */ | ||
| 843 | ebp = 0x1fb; /* 15 */ | ||
| 844 | v20 = 0x16a; /* 62 */ | ||
| 845 | v1E = 0x195; /* 62 */ | ||
| 846 | v16 = 0x1bb; /* 15 */ | ||
| 847 | v14 = 0x1ef; /* 15 */ | ||
| 848 | v12 = 5; /* 16 */ | ||
| 849 | v10 = 5; /* 16 */ | ||
| 850 | v0E = 5; /* 16 */ | ||
| 851 | } | ||
| 852 | |||
| 853 | switch (fep->u.ofdm.constellation) { | ||
| 854 | default: | ||
| 855 | v22 |= 4; | ||
| 856 | case QPSK: | ||
| 857 | if (s->chip_rev == DRXD_FW_B1) | ||
| 858 | break; | ||
| 859 | |||
| 860 | rc = WR16(s, 0x1c10046, 0); | ||
| 861 | if (rc < 0) | ||
| 862 | goto exit_rc; | ||
| 863 | rc = WR16(s, 0x2010011, 0); | ||
| 864 | if (rc < 0) | ||
| 865 | goto exit_rc; | ||
| 866 | rc = WR16(s, 0x201001a, 0x10); | ||
| 867 | if (rc < 0) | ||
| 868 | goto exit_rc; | ||
| 869 | rc = WR16(s, 0x201001b, 0); | ||
| 870 | if (rc < 0) | ||
| 871 | goto exit_rc; | ||
| 872 | rc = WR16(s, 0x201001c, 0); | ||
| 873 | if (rc < 0) | ||
| 874 | goto exit_rc; | ||
| 875 | rc = WR16(s, 0x1c10062, v20); | ||
| 876 | if (rc < 0) | ||
| 877 | goto exit_rc; | ||
| 878 | rc = WR16(s, 0x1c1002a, v1C); | ||
| 879 | if (rc < 0) | ||
| 880 | goto exit_rc; | ||
| 881 | rc = WR16(s, 0x1c10015, v16); | ||
| 882 | if (rc < 0) | ||
| 883 | goto exit_rc; | ||
| 884 | rc = WR16(s, 0x1c10016, v12); | ||
| 885 | if (rc < 0) | ||
| 886 | goto exit_rc; | ||
| 887 | break; | ||
| 888 | case QAM_16: | ||
| 889 | edi |= 0x10; | ||
| 890 | if (s->chip_rev == DRXD_FW_B1) | ||
| 891 | break; | ||
| 892 | |||
| 893 | rc = WR16(s, 0x1c10046, 1); | ||
| 894 | if (rc < 0) | ||
| 895 | goto exit_rc; | ||
| 896 | rc = WR16(s, 0x2010011, 1); | ||
| 897 | if (rc < 0) | ||
| 898 | goto exit_rc; | ||
| 899 | rc = WR16(s, 0x201001a, 0x10); | ||
| 900 | if (rc < 0) | ||
| 901 | goto exit_rc; | ||
| 902 | rc = WR16(s, 0x201001b, 4); | ||
| 903 | if (rc < 0) | ||
| 904 | goto exit_rc; | ||
| 905 | rc = WR16(s, 0x201001c, 0); | ||
| 906 | if (rc < 0) | ||
| 907 | goto exit_rc; | ||
| 908 | rc = WR16(s, 0x1c10062, v1E); | ||
| 909 | if (rc < 0) | ||
| 910 | goto exit_rc; | ||
| 911 | rc = WR16(s, 0x1c1002a, v1A); | ||
| 912 | if (rc < 0) | ||
| 913 | goto exit_rc; | ||
| 914 | rc = WR16(s, 0x1c10015, v14); | ||
| 915 | if (rc < 0) | ||
| 916 | goto exit_rc; | ||
| 917 | rc = WR16(s, 0x1c10016, v10); | ||
| 918 | if (rc < 0) | ||
| 919 | goto exit_rc; | ||
| 920 | break; | ||
| 921 | case QAM_64: | ||
| 922 | edi |= 0x20; | ||
| 923 | rc = WR16(s, 0x1c10046, 2); | ||
| 924 | if (rc < 0) | ||
| 925 | goto exit_rc; | ||
| 926 | rc = WR16(s, 0x2010011, 2); | ||
| 927 | if (rc < 0) | ||
| 928 | goto exit_rc; | ||
| 929 | rc = WR16(s, 0x201001a, 0x20); | ||
| 930 | if (rc < 0) | ||
| 931 | goto exit_rc; | ||
| 932 | rc = WR16(s, 0x201001b, 8); | ||
| 933 | if (rc < 0) | ||
| 934 | goto exit_rc; | ||
| 935 | rc = WR16(s, 0x201001c, 2); | ||
| 936 | if (rc < 0) | ||
| 937 | goto exit_rc; | ||
| 938 | rc = WR16(s, 0x1c10062, ebx); | ||
| 939 | if (rc < 0) | ||
| 940 | goto exit_rc; | ||
| 941 | rc = WR16(s, 0x1c1002a, v18); | ||
| 942 | if (rc < 0) | ||
| 943 | goto exit_rc; | ||
| 944 | rc = WR16(s, 0x1c10015, ebp); | ||
| 945 | if (rc < 0) | ||
| 946 | goto exit_rc; | ||
| 947 | rc = WR16(s, 0x1c10016, v0E); | ||
| 948 | if (rc < 0) | ||
| 949 | goto exit_rc; | ||
| 950 | break; | ||
| 951 | } | ||
| 952 | |||
| 953 | if (s->config.s20d24 == 1) { | ||
| 954 | rc = WR16(s, 0x2010013, 0); | ||
| 955 | } else { | ||
| 956 | rc = WR16(s, 0x2010013, 1); | ||
| 957 | edi |= 0x1000; | ||
| 958 | } | ||
| 959 | |||
| 960 | switch (fep->u.ofdm.code_rate_HP) { | ||
| 961 | default: | ||
| 962 | v22 |= 0x10; | ||
| 963 | case FEC_1_2: | ||
| 964 | if (s->chip_rev == DRXD_FW_B1) | ||
| 965 | break; | ||
| 966 | rc = WR16(s, 0x2090011, 0); | ||
| 967 | break; | ||
| 968 | case FEC_2_3: | ||
| 969 | edi |= 0x200; | ||
| 970 | if (s->chip_rev == DRXD_FW_B1) | ||
| 971 | break; | ||
| 972 | rc = WR16(s, 0x2090011, 1); | ||
| 973 | break; | ||
| 974 | case FEC_3_4: | ||
| 975 | edi |= 0x400; | ||
| 976 | if (s->chip_rev == DRXD_FW_B1) | ||
| 977 | break; | ||
| 978 | rc = WR16(s, 0x2090011, 2); | ||
| 979 | break; | ||
| 980 | case FEC_5_6: /* 5 */ | ||
| 981 | edi |= 0x600; | ||
| 982 | if (s->chip_rev == DRXD_FW_B1) | ||
| 983 | break; | ||
| 984 | rc = WR16(s, 0x2090011, 3); | ||
| 985 | break; | ||
| 986 | case FEC_7_8: /* 7 */ | ||
| 987 | edi |= 0x800; | ||
| 988 | if (s->chip_rev == DRXD_FW_B1) | ||
| 989 | break; | ||
| 990 | rc = WR16(s, 0x2090011, 4); | ||
| 991 | break; | ||
| 992 | }; | ||
| 993 | if (rc < 0) | ||
| 994 | goto exit_rc; | ||
| 995 | |||
| 996 | switch (fep->u.ofdm.bandwidth) { | ||
| 997 | default: | ||
| 998 | rc = -EINVAL; | ||
| 999 | goto exit_rc; | ||
| 1000 | case BANDWIDTH_8_MHZ: /* 0 */ | ||
| 1001 | case BANDWIDTH_AUTO: | ||
| 1002 | rc = WR16(s, 0x0c2003f, 0x32); | ||
| 1003 | s->bandwidth_parm = ebx = 0x8b8249; | ||
| 1004 | edx = 0; | ||
| 1005 | break; | ||
| 1006 | case BANDWIDTH_7_MHZ: | ||
| 1007 | rc = WR16(s, 0x0c2003f, 0x3b); | ||
| 1008 | s->bandwidth_parm = ebx = 0x7a1200; | ||
| 1009 | edx = 0x4807; | ||
| 1010 | break; | ||
| 1011 | case BANDWIDTH_6_MHZ: | ||
| 1012 | rc = WR16(s, 0x0c2003f, 0x47); | ||
| 1013 | s->bandwidth_parm = ebx = 0x68a1b6; | ||
| 1014 | edx = 0x0f07; | ||
| 1015 | break; | ||
| 1016 | }; | ||
| 1017 | |||
| 1018 | if (rc < 0) | ||
| 1019 | goto exit_rc; | ||
| 1020 | |||
| 1021 | rc = WR16(s, 0x08200ec, edx); | ||
| 1022 | if (rc < 0) | ||
| 1023 | goto exit_rc; | ||
| 1024 | |||
| 1025 | rc = RD16(s, 0x0820050); | ||
| 1026 | if (rc < 0) | ||
| 1027 | goto exit_rc; | ||
| 1028 | rc = WR16(s, 0x0820050, rc); | ||
| 1029 | |||
| 1030 | { | ||
| 1031 | /* Configure bandwidth specific factor */ | ||
| 1032 | ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1), | ||
| 1033 | (u64)ebx) - 0x800000; | ||
| 1034 | EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff)); | ||
| 1035 | EXIT_RC(WR16(s, 0x0c50011, ebx >> 16)); | ||
| 1036 | |||
| 1037 | /* drx397xD oscillator calibration */ | ||
| 1038 | ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) + | ||
| 1039 | (s->f_osc >> 1), (u64)s->f_osc); | ||
| 1040 | } | ||
| 1041 | ebx &= 0xfffffff; | ||
| 1042 | if (fep->inversion == INVERSION_ON) | ||
| 1043 | ebx = 0x10000000 - ebx; | ||
| 1044 | |||
| 1045 | EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff)); | ||
| 1046 | EXIT_RC(WR16(s, 0x0c30011, ebx >> 16)); | ||
| 1047 | |||
| 1048 | EXIT_RC(WR16(s, 0x0800000, 1)); | ||
| 1049 | EXIT_RC(RD16(s, 0x0800000)); | ||
| 1050 | |||
| 1051 | |||
| 1052 | EXIT_RC(SC_WaitForReady(s)); | ||
| 1053 | EXIT_RC(WR16(s, 0x0820042, 0)); | ||
| 1054 | EXIT_RC(WR16(s, 0x0820041, v22)); | ||
| 1055 | EXIT_RC(WR16(s, 0x0820040, edi)); | ||
| 1056 | EXIT_RC(SC_SendCommand(s, 3)); | ||
| 1057 | |||
| 1058 | rc = RD16(s, 0x0800000); | ||
| 1059 | |||
| 1060 | SC_WaitForReady(s); | ||
| 1061 | WR16(s, 0x0820042, 0); | ||
| 1062 | WR16(s, 0x0820041, 1); | ||
| 1063 | WR16(s, 0x0820040, 1); | ||
| 1064 | SC_SendCommand(s, 1); | ||
| 1065 | |||
| 1066 | |||
| 1067 | rc = WR16(s, 0x2150000, 2); | ||
| 1068 | rc = WR16(s, 0x2150016, a); | ||
| 1069 | rc = WR16(s, 0x2150010, 4); | ||
| 1070 | rc = WR16(s, 0x2150036, 0); | ||
| 1071 | rc = WR16(s, 0x2150000, 1); | ||
| 1072 | s->config.d60 = 2; | ||
| 1073 | |||
| 1074 | exit_rc: | ||
| 1075 | return rc; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | /******************************************************************************* | ||
| 1079 | * DVB interface | ||
| 1080 | ******************************************************************************/ | ||
| 1081 | |||
| 1082 | static int drx397x_init(struct dvb_frontend *fe) | ||
| 1083 | { | ||
| 1084 | struct drx397xD_state *s = fe->demodulator_priv; | ||
| 1085 | int rc; | ||
| 1086 | |||
| 1087 | pr_debug("%s\n", __func__); | ||
| 1088 | |||
| 1089 | s->config.rfagc.d00 = 2; /* 0x7c */ | ||
| 1090 | s->config.rfagc.w04 = 0; | ||
| 1091 | s->config.rfagc.w06 = 0x3ff; | ||
| 1092 | |||
| 1093 | s->config.ifagc.d00 = 0; /* 0x68 */ | ||
| 1094 | s->config.ifagc.w04 = 0; | ||
| 1095 | s->config.ifagc.w06 = 140; | ||
| 1096 | s->config.ifagc.w08 = 0; | ||
| 1097 | s->config.ifagc.w0A = 0x3ff; | ||
| 1098 | s->config.ifagc.w0C = 0x388; | ||
| 1099 | |||
| 1100 | /* for signal strength calculations */ | ||
| 1101 | s->config.ss76 = 820; | ||
| 1102 | s->config.ss78 = 2200; | ||
| 1103 | s->config.ss7A = 150; | ||
| 1104 | |||
| 1105 | /* HI_CfgCommand */ | ||
| 1106 | s->config.w50 = 4; | ||
| 1107 | s->config.w52 = 9; | ||
| 1108 | |||
| 1109 | s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */ | ||
| 1110 | s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */ | ||
| 1111 | s->config.w92 = 12000; | ||
| 1112 | |||
| 1113 | s->config.w9C = 0x000e; | ||
| 1114 | s->config.w9E = 0x0000; | ||
| 1115 | |||
| 1116 | /* ConfigureMPEGOutput params */ | ||
| 1117 | s->config.wA0 = 4; | ||
| 1118 | s->config.w98 = 1; | ||
| 1119 | s->config.w9A = 1; | ||
| 1120 | |||
| 1121 | /* get chip revision */ | ||
| 1122 | rc = RD16(s, 0x2410019); | ||
| 1123 | if (rc < 0) | ||
| 1124 | return -ENODEV; | ||
| 1125 | |||
| 1126 | if (rc == 0) { | ||
| 1127 | printk(KERN_INFO "%s: chip revision A2\n", mod_name); | ||
| 1128 | rc = drx_load_fw(s, DRXD_FW_A2); | ||
| 1129 | } else { | ||
| 1130 | |||
| 1131 | rc = (rc >> 12) - 3; | ||
| 1132 | switch (rc) { | ||
| 1133 | case 1: | ||
| 1134 | s->flags |= F_SET_0D4h; | ||
| 1135 | case 0: | ||
| 1136 | case 4: | ||
| 1137 | s->flags |= F_SET_0D0h; | ||
| 1138 | break; | ||
| 1139 | case 2: | ||
| 1140 | case 5: | ||
| 1141 | break; | ||
| 1142 | case 3: | ||
| 1143 | s->flags |= F_SET_0D4h; | ||
| 1144 | break; | ||
| 1145 | default: | ||
| 1146 | return -ENODEV; | ||
| 1147 | }; | ||
| 1148 | printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc); | ||
| 1149 | rc = drx_load_fw(s, DRXD_FW_B1); | ||
| 1150 | } | ||
| 1151 | if (rc < 0) | ||
| 1152 | goto error; | ||
| 1153 | |||
| 1154 | rc = WR16(s, 0x0420033, 0x3973); | ||
| 1155 | if (rc < 0) | ||
| 1156 | goto error; | ||
| 1157 | |||
| 1158 | rc = HI_Command(s, 2); | ||
| 1159 | |||
| 1160 | msleep(1); | ||
| 1161 | |||
| 1162 | if (s->chip_rev == DRXD_FW_A2) { | ||
| 1163 | rc = WR16(s, 0x043012d, 0x47F); | ||
| 1164 | if (rc < 0) | ||
| 1165 | goto error; | ||
| 1166 | } | ||
| 1167 | rc = WR16_E0(s, 0x0400000, 0); | ||
| 1168 | if (rc < 0) | ||
| 1169 | goto error; | ||
| 1170 | |||
| 1171 | if (s->config.w92 > 20000 || s->config.w92 % 4000) { | ||
| 1172 | printk(KERN_ERR "%s: invalid osc frequency\n", mod_name); | ||
| 1173 | rc = -1; | ||
| 1174 | goto error; | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | rc = WR16(s, 0x2410010, 1); | ||
| 1178 | if (rc < 0) | ||
| 1179 | goto error; | ||
| 1180 | rc = WR16(s, 0x2410011, 0x15); | ||
| 1181 | if (rc < 0) | ||
| 1182 | goto error; | ||
| 1183 | rc = WR16(s, 0x2410012, s->config.w92 / 4000); | ||
| 1184 | if (rc < 0) | ||
| 1185 | goto error; | ||
| 1186 | #ifdef ORIG_FW | ||
| 1187 | rc = WR16(s, 0x2410015, 2); | ||
| 1188 | if (rc < 0) | ||
| 1189 | goto error; | ||
| 1190 | #endif | ||
| 1191 | rc = WR16(s, 0x2410017, 0x3973); | ||
| 1192 | if (rc < 0) | ||
| 1193 | goto error; | ||
| 1194 | |||
| 1195 | s->f_osc = s->config.f_osc * 1000; /* initial estimator */ | ||
| 1196 | |||
| 1197 | s->config.w56 = 1; | ||
| 1198 | |||
| 1199 | rc = HI_CfgCommand(s); | ||
| 1200 | if (rc < 0) | ||
| 1201 | goto error; | ||
| 1202 | |||
| 1203 | rc = write_fw(s, DRXD_InitAtomicRead); | ||
| 1204 | if (rc < 0) | ||
| 1205 | goto error; | ||
| 1206 | |||
| 1207 | if (s->chip_rev == DRXD_FW_A2) { | ||
| 1208 | rc = WR16(s, 0x2150013, 0); | ||
| 1209 | if (rc < 0) | ||
| 1210 | goto error; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | rc = WR16_E0(s, 0x0400002, 0); | ||
| 1214 | if (rc < 0) | ||
| 1215 | goto error; | ||
| 1216 | rc = WR16(s, 0x0400002, 0); | ||
| 1217 | if (rc < 0) | ||
| 1218 | goto error; | ||
| 1219 | |||
| 1220 | if (s->chip_rev == DRXD_FW_A2) { | ||
| 1221 | rc = write_fw(s, DRXD_ResetCEFR); | ||
| 1222 | if (rc < 0) | ||
| 1223 | goto error; | ||
| 1224 | } | ||
| 1225 | rc = write_fw(s, DRXD_microcode); | ||
| 1226 | if (rc < 0) | ||
| 1227 | goto error; | ||
| 1228 | |||
| 1229 | s->config.w9C = 0x0e; | ||
| 1230 | if (s->flags & F_SET_0D0h) { | ||
| 1231 | s->config.w9C = 0; | ||
| 1232 | rc = RD16(s, 0x0c20010); | ||
| 1233 | if (rc < 0) | ||
| 1234 | goto write_DRXD_InitFE_1; | ||
| 1235 | |||
| 1236 | rc &= ~0x1000; | ||
| 1237 | rc = WR16(s, 0x0c20010, rc); | ||
| 1238 | if (rc < 0) | ||
| 1239 | goto write_DRXD_InitFE_1; | ||
| 1240 | |||
| 1241 | rc = RD16(s, 0x0c20011); | ||
| 1242 | if (rc < 0) | ||
| 1243 | goto write_DRXD_InitFE_1; | ||
| 1244 | |||
| 1245 | rc &= ~0x8; | ||
| 1246 | rc = WR16(s, 0x0c20011, rc); | ||
| 1247 | if (rc < 0) | ||
| 1248 | goto write_DRXD_InitFE_1; | ||
| 1249 | |||
| 1250 | rc = WR16(s, 0x0c20012, 1); | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | write_DRXD_InitFE_1: | ||
| 1254 | |||
| 1255 | rc = write_fw(s, DRXD_InitFE_1); | ||
| 1256 | if (rc < 0) | ||
| 1257 | goto error; | ||
| 1258 | |||
| 1259 | rc = 1; | ||
| 1260 | if (s->chip_rev == DRXD_FW_B1) { | ||
| 1261 | if (s->flags & F_SET_0D0h) | ||
| 1262 | rc = 0; | ||
| 1263 | } else { | ||
| 1264 | if (s->flags & F_SET_0D0h) | ||
| 1265 | rc = 4; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | rc = WR16(s, 0x0C20012, rc); | ||
| 1269 | if (rc < 0) | ||
| 1270 | goto error; | ||
| 1271 | |||
| 1272 | rc = WR16(s, 0x0C20013, s->config.w9E); | ||
| 1273 | if (rc < 0) | ||
| 1274 | goto error; | ||
| 1275 | rc = WR16(s, 0x0C20015, s->config.w9C); | ||
| 1276 | if (rc < 0) | ||
| 1277 | goto error; | ||
| 1278 | |||
| 1279 | rc = write_fw(s, DRXD_InitFE_2); | ||
| 1280 | if (rc < 0) | ||
| 1281 | goto error; | ||
| 1282 | rc = write_fw(s, DRXD_InitFT); | ||
| 1283 | if (rc < 0) | ||
| 1284 | goto error; | ||
| 1285 | rc = write_fw(s, DRXD_InitCP); | ||
| 1286 | if (rc < 0) | ||
| 1287 | goto error; | ||
| 1288 | rc = write_fw(s, DRXD_InitCE); | ||
| 1289 | if (rc < 0) | ||
| 1290 | goto error; | ||
| 1291 | rc = write_fw(s, DRXD_InitEQ); | ||
| 1292 | if (rc < 0) | ||
| 1293 | goto error; | ||
| 1294 | rc = write_fw(s, DRXD_InitEC); | ||
| 1295 | if (rc < 0) | ||
| 1296 | goto error; | ||
| 1297 | rc = write_fw(s, DRXD_InitSC); | ||
| 1298 | if (rc < 0) | ||
| 1299 | goto error; | ||
| 1300 | |||
| 1301 | rc = SetCfgIfAgc(s, &s->config.ifagc); | ||
| 1302 | if (rc < 0) | ||
| 1303 | goto error; | ||
| 1304 | |||
| 1305 | rc = SetCfgRfAgc(s, &s->config.rfagc); | ||
| 1306 | if (rc < 0) | ||
| 1307 | goto error; | ||
| 1308 | |||
| 1309 | rc = ConfigureMPEGOutput(s, 1); | ||
| 1310 | rc = WR16(s, 0x08201fe, 0x0017); | ||
| 1311 | rc = WR16(s, 0x08201ff, 0x0101); | ||
| 1312 | |||
| 1313 | s->config.d5C = 0; | ||
| 1314 | s->config.d60 = 1; | ||
| 1315 | s->config.d48 = 1; | ||
| 1316 | |||
| 1317 | error: | ||
| 1318 | return rc; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | static int drx397x_get_frontend(struct dvb_frontend *fe, | ||
| 1322 | struct dvb_frontend_parameters *params) | ||
| 1323 | { | ||
| 1324 | return 0; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | static int drx397x_set_frontend(struct dvb_frontend *fe, | ||
| 1328 | struct dvb_frontend_parameters *params) | ||
| 1329 | { | ||
| 1330 | struct drx397xD_state *s = fe->demodulator_priv; | ||
| 1331 | |||
| 1332 | s->config.s20d24 = 1; | ||
| 1333 | |||
| 1334 | return drx_tune(s, params); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | static int drx397x_get_tune_settings(struct dvb_frontend *fe, | ||
| 1338 | struct dvb_frontend_tune_settings | ||
| 1339 | *fe_tune_settings) | ||
| 1340 | { | ||
| 1341 | fe_tune_settings->min_delay_ms = 10000; | ||
| 1342 | fe_tune_settings->step_size = 0; | ||
| 1343 | fe_tune_settings->max_drift = 0; | ||
| 1344 | |||
| 1345 | return 0; | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
| 1349 | { | ||
| 1350 | struct drx397xD_state *s = fe->demodulator_priv; | ||
| 1351 | int lockstat; | ||
| 1352 | |||
| 1353 | GetLockStatus(s, &lockstat); | ||
| 1354 | |||
| 1355 | *status = 0; | ||
| 1356 | if (lockstat & 2) { | ||
| 1357 | CorrectSysClockDeviation(s); | ||
| 1358 | ConfigureMPEGOutput(s, 1); | ||
| 1359 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; | ||
| 1360 | } | ||
| 1361 | if (lockstat & 4) | ||
| 1362 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||
| 1363 | |||
| 1364 | return 0; | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber) | ||
| 1368 | { | ||
| 1369 | *ber = 0; | ||
| 1370 | |||
| 1371 | return 0; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 1375 | { | ||
| 1376 | *snr = 0; | ||
| 1377 | |||
| 1378 | return 0; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
| 1382 | { | ||
| 1383 | struct drx397xD_state *s = fe->demodulator_priv; | ||
| 1384 | int rc; | ||
| 1385 | |||
| 1386 | if (s->config.ifagc.d00 == 2) { | ||
| 1387 | *strength = 0xffff; | ||
| 1388 | return 0; | ||
| 1389 | } | ||
| 1390 | rc = RD16(s, 0x0c20035); | ||
| 1391 | if (rc < 0) { | ||
| 1392 | *strength = 0; | ||
| 1393 | return 0; | ||
| 1394 | } | ||
| 1395 | rc &= 0x3ff; | ||
| 1396 | /* Signal strength is calculated using the following formula: | ||
| 1397 | * | ||
| 1398 | * a = 2200 * 150 / (2200 + 150); | ||
| 1399 | * a = a * 3300 / (a + 820); | ||
| 1400 | * b = 2200 * 3300 / (2200 + 820); | ||
| 1401 | * c = (((b-a) * rc) >> 10 + a) << 4; | ||
| 1402 | * strength = ~c & 0xffff; | ||
| 1403 | * | ||
| 1404 | * The following does the same but with less rounding errors: | ||
| 1405 | */ | ||
| 1406 | *strength = ~(7720 + (rc * 30744 >> 10)); | ||
| 1407 | |||
| 1408 | return 0; | ||
| 1409 | } | ||
| 1410 | |||
| 1411 | static int drx397x_read_ucblocks(struct dvb_frontend *fe, | ||
| 1412 | unsigned int *ucblocks) | ||
| 1413 | { | ||
| 1414 | *ucblocks = 0; | ||
| 1415 | |||
| 1416 | return 0; | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | static int drx397x_sleep(struct dvb_frontend *fe) | ||
| 1420 | { | ||
| 1421 | return 0; | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | static void drx397x_release(struct dvb_frontend *fe) | ||
| 1425 | { | ||
| 1426 | struct drx397xD_state *s = fe->demodulator_priv; | ||
| 1427 | printk(KERN_INFO "%s: release demodulator\n", mod_name); | ||
| 1428 | if (s) { | ||
| 1429 | drx_release_fw(s); | ||
| 1430 | kfree(s); | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | } | ||
| 1434 | |||
| 1435 | static struct dvb_frontend_ops drx397x_ops = { | ||
| 1436 | |||
| 1437 | .info = { | ||
| 1438 | .name = "Micronas DRX397xD DVB-T Frontend", | ||
| 1439 | .type = FE_OFDM, | ||
| 1440 | .frequency_min = 47125000, | ||
| 1441 | .frequency_max = 855250000, | ||
| 1442 | .frequency_stepsize = 166667, | ||
| 1443 | .frequency_tolerance = 0, | ||
| 1444 | .caps = /* 0x0C01B2EAE */ | ||
| 1445 | FE_CAN_FEC_1_2 | /* = 0x2, */ | ||
| 1446 | FE_CAN_FEC_2_3 | /* = 0x4, */ | ||
| 1447 | FE_CAN_FEC_3_4 | /* = 0x8, */ | ||
| 1448 | FE_CAN_FEC_5_6 | /* = 0x20, */ | ||
| 1449 | FE_CAN_FEC_7_8 | /* = 0x80, */ | ||
| 1450 | FE_CAN_FEC_AUTO | /* = 0x200, */ | ||
| 1451 | FE_CAN_QPSK | /* = 0x400, */ | ||
| 1452 | FE_CAN_QAM_16 | /* = 0x800, */ | ||
| 1453 | FE_CAN_QAM_64 | /* = 0x2000, */ | ||
| 1454 | FE_CAN_QAM_AUTO | /* = 0x10000, */ | ||
| 1455 | FE_CAN_TRANSMISSION_MODE_AUTO | /* = 0x20000, */ | ||
| 1456 | FE_CAN_GUARD_INTERVAL_AUTO | /* = 0x80000, */ | ||
| 1457 | FE_CAN_HIERARCHY_AUTO | /* = 0x100000, */ | ||
| 1458 | FE_CAN_RECOVER | /* = 0x40000000, */ | ||
| 1459 | FE_CAN_MUTE_TS /* = 0x80000000 */ | ||
| 1460 | }, | ||
| 1461 | |||
| 1462 | .release = drx397x_release, | ||
| 1463 | .init = drx397x_init, | ||
| 1464 | .sleep = drx397x_sleep, | ||
| 1465 | |||
| 1466 | .set_frontend = drx397x_set_frontend, | ||
| 1467 | .get_tune_settings = drx397x_get_tune_settings, | ||
| 1468 | .get_frontend = drx397x_get_frontend, | ||
| 1469 | |||
| 1470 | .read_status = drx397x_read_status, | ||
| 1471 | .read_snr = drx397x_read_snr, | ||
| 1472 | .read_signal_strength = drx397x_read_signal_strength, | ||
| 1473 | .read_ber = drx397x_read_ber, | ||
| 1474 | .read_ucblocks = drx397x_read_ucblocks, | ||
| 1475 | }; | ||
| 1476 | |||
| 1477 | struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config, | ||
| 1478 | struct i2c_adapter *i2c) | ||
| 1479 | { | ||
| 1480 | struct drx397xD_state *state; | ||
| 1481 | |||
| 1482 | /* allocate memory for the internal state */ | ||
| 1483 | state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL); | ||
| 1484 | if (!state) | ||
| 1485 | goto error; | ||
| 1486 | |||
| 1487 | /* setup the state */ | ||
| 1488 | state->i2c = i2c; | ||
| 1489 | memcpy(&state->config, config, sizeof(struct drx397xD_config)); | ||
| 1490 | |||
| 1491 | /* check if the demod is there */ | ||
| 1492 | if (RD16(state, 0x2410019) < 0) | ||
| 1493 | goto error; | ||
| 1494 | |||
| 1495 | /* create dvb_frontend */ | ||
| 1496 | memcpy(&state->frontend.ops, &drx397x_ops, | ||
| 1497 | sizeof(struct dvb_frontend_ops)); | ||
| 1498 | state->frontend.demodulator_priv = state; | ||
| 1499 | |||
| 1500 | return &state->frontend; | ||
| 1501 | error: | ||
| 1502 | kfree(state); | ||
| 1503 | |||
| 1504 | return NULL; | ||
| 1505 | } | ||
| 1506 | EXPORT_SYMBOL(drx397xD_attach); | ||
| 1507 | |||
| 1508 | MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend"); | ||
| 1509 | MODULE_AUTHOR("Henk Vergonet"); | ||
| 1510 | MODULE_LICENSE("GPL"); | ||
| 1511 | |||
diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h deleted file mode 100644 index ba05d17290c6..000000000000 --- a/drivers/media/dvb/frontends/drx397xD.h +++ /dev/null | |||
| @@ -1,130 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Micronas DVB-T drx397xD demodulator | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Henk vergonet <Henk.Vergonet@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef _DRX397XD_H_INCLUDED | ||
| 23 | #define _DRX397XD_H_INCLUDED | ||
| 24 | |||
| 25 | #include <linux/dvb/frontend.h> | ||
| 26 | |||
| 27 | #define DRX_F_STEPSIZE 166667 | ||
| 28 | #define DRX_F_OFFSET 36000000 | ||
| 29 | |||
| 30 | #define I2C_ADR_C0(x) \ | ||
| 31 | ( cpu_to_le32( \ | ||
| 32 | (u32)( \ | ||
| 33 | (((u32)(x) & (u32)0x000000ffUL) ) | \ | ||
| 34 | (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ | ||
| 35 | (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \ | ||
| 36 | ( (u32)0x00c00000UL) \ | ||
| 37 | )) \ | ||
| 38 | ) | ||
| 39 | |||
| 40 | #define I2C_ADR_E0(x) \ | ||
| 41 | ( cpu_to_le32( \ | ||
| 42 | (u32)( \ | ||
| 43 | (((u32)(x) & (u32)0x000000ffUL) ) | \ | ||
| 44 | (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ | ||
| 45 | (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \ | ||
| 46 | ( (u32)0x00e00000UL) \ | ||
| 47 | )) \ | ||
| 48 | ) | ||
| 49 | |||
| 50 | struct drx397xD_CfgRfAgc /* 0x7c */ | ||
| 51 | { | ||
| 52 | int d00; /* 2 */ | ||
| 53 | u16 w04; | ||
| 54 | u16 w06; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct drx397xD_CfgIfAgc /* 0x68 */ | ||
| 58 | { | ||
| 59 | int d00; /* 0 */ | ||
| 60 | u16 w04; /* 0 */ | ||
| 61 | u16 w06; | ||
| 62 | u16 w08; | ||
| 63 | u16 w0A; | ||
| 64 | u16 w0C; | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct drx397xD_s20 { | ||
| 68 | int d04; | ||
| 69 | u32 d18; | ||
| 70 | u32 d1C; | ||
| 71 | u32 d20; | ||
| 72 | u32 d14; | ||
| 73 | u32 d24; | ||
| 74 | u32 d0C; | ||
| 75 | u32 d08; | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct drx397xD_config | ||
| 79 | { | ||
| 80 | /* demodulator's I2C address */ | ||
| 81 | u8 demod_address; /* 0x0f */ | ||
| 82 | |||
| 83 | struct drx397xD_CfgIfAgc ifagc; /* 0x68 */ | ||
| 84 | struct drx397xD_CfgRfAgc rfagc; /* 0x7c */ | ||
| 85 | u32 s20d24; | ||
| 86 | |||
| 87 | /* HI_CfgCommand parameters */ | ||
| 88 | u16 w50, w52, /* w54, */ w56; | ||
| 89 | |||
| 90 | int d5C; | ||
| 91 | int d60; | ||
| 92 | int d48; | ||
| 93 | int d28; | ||
| 94 | |||
| 95 | u32 f_if; /* d14: intermediate frequency [Hz] */ | ||
| 96 | /* 36000000 on Cinergy 2400i DT */ | ||
| 97 | /* 42800000 on Pinnacle Hybrid PRO 330e */ | ||
| 98 | |||
| 99 | u16 f_osc; /* s66: 48000 oscillator frequency [kHz] */ | ||
| 100 | |||
| 101 | u16 w92; /* 20000 */ | ||
| 102 | |||
| 103 | u16 wA0; | ||
| 104 | u16 w98; | ||
| 105 | u16 w9A; | ||
| 106 | |||
| 107 | u16 w9C; /* 0xe0 */ | ||
| 108 | u16 w9E; /* 0x00 */ | ||
| 109 | |||
| 110 | /* used for signal strength calculations in | ||
| 111 | drx397x_read_signal_strength | ||
| 112 | */ | ||
| 113 | u16 ss78; // 2200 | ||
| 114 | u16 ss7A; // 150 | ||
| 115 | u16 ss76; // 820 | ||
| 116 | }; | ||
| 117 | |||
| 118 | #if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE)) | ||
| 119 | extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config, | ||
| 120 | struct i2c_adapter *i2c); | ||
| 121 | #else | ||
| 122 | static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config, | ||
| 123 | struct i2c_adapter *i2c) | ||
| 124 | { | ||
| 125 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 126 | return NULL; | ||
| 127 | } | ||
| 128 | #endif /* CONFIG_DVB_DRX397XD */ | ||
| 129 | |||
| 130 | #endif /* _DRX397XD_H_INCLUDED */ | ||
diff --git a/drivers/media/dvb/frontends/drx397xD_fw.h b/drivers/media/dvb/frontends/drx397xD_fw.h deleted file mode 100644 index c8b44c1e807f..000000000000 --- a/drivers/media/dvb/frontends/drx397xD_fw.h +++ /dev/null | |||
| @@ -1,40 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Firmware definitions for Micronas drx397xD | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifdef _FW_ENTRY | ||
| 21 | _FW_ENTRY("drx397xD.A2.fw", DRXD_FW_A2 = 0, DRXD_FW_A2 ), | ||
| 22 | _FW_ENTRY("drx397xD.B1.fw", DRXD_FW_B1, DRXD_FW_B1 ), | ||
| 23 | #undef _FW_ENTRY | ||
| 24 | #endif /* _FW_ENTRY */ | ||
| 25 | |||
| 26 | #ifdef _BLOB_ENTRY | ||
| 27 | _BLOB_ENTRY("InitAtomicRead", DRXD_InitAtomicRead = 0 ), | ||
| 28 | _BLOB_ENTRY("InitCE", DRXD_InitCE ), | ||
| 29 | _BLOB_ENTRY("InitCP", DRXD_InitCP ), | ||
| 30 | _BLOB_ENTRY("InitEC", DRXD_InitEC ), | ||
| 31 | _BLOB_ENTRY("InitEQ", DRXD_InitEQ ), | ||
| 32 | _BLOB_ENTRY("InitFE_1", DRXD_InitFE_1 ), | ||
| 33 | _BLOB_ENTRY("InitFE_2", DRXD_InitFE_2 ), | ||
| 34 | _BLOB_ENTRY("InitFT", DRXD_InitFT ), | ||
| 35 | _BLOB_ENTRY("InitSC", DRXD_InitSC ), | ||
| 36 | _BLOB_ENTRY("ResetCEFR", DRXD_ResetCEFR ), | ||
| 37 | _BLOB_ENTRY("ResetECRAM", DRXD_ResetECRAM ), | ||
| 38 | _BLOB_ENTRY("microcode", DRXD_microcode ), | ||
| 39 | #undef _BLOB_ENTRY | ||
| 40 | #endif /* _BLOB_ENTRY */ | ||
diff --git a/drivers/media/dvb/frontends/drxd.h b/drivers/media/dvb/frontends/drxd.h new file mode 100644 index 000000000000..7113535844f2 --- /dev/null +++ b/drivers/media/dvb/frontends/drxd.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | /* | ||
| 2 | * drxd.h: DRXD DVB-T demodulator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2007 Micronas | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 only, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 20 | * 02110-1301, USA | ||
| 21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef _DRXD_H_ | ||
| 25 | #define _DRXD_H_ | ||
| 26 | |||
| 27 | #include <linux/types.h> | ||
| 28 | #include <linux/i2c.h> | ||
| 29 | |||
| 30 | struct drxd_config { | ||
| 31 | u8 index; | ||
| 32 | |||
| 33 | u8 pll_address; | ||
| 34 | u8 pll_type; | ||
| 35 | #define DRXD_PLL_NONE 0 | ||
| 36 | #define DRXD_PLL_DTT7520X 1 | ||
| 37 | #define DRXD_PLL_MT3X0823 2 | ||
| 38 | |||
| 39 | u32 clock; | ||
| 40 | u8 insert_rs_byte; | ||
| 41 | |||
| 42 | u8 demod_address; | ||
| 43 | u8 demoda_address; | ||
| 44 | u8 demod_revision; | ||
| 45 | |||
| 46 | /* If the tuner is not behind an i2c gate, be sure to flip this bit | ||
| 47 | or else the i2c bus could get wedged */ | ||
| 48 | u8 disable_i2c_gate_ctrl; | ||
| 49 | |||
| 50 | u32 IF; | ||
| 51 | int (*pll_set) (void *priv, void *priv_params, | ||
| 52 | u8 pll_addr, u8 demoda_addr, s32 *off); | ||
| 53 | s16(*osc_deviation) (void *priv, s16 dev, int flag); | ||
| 54 | }; | ||
| 55 | |||
| 56 | extern | ||
| 57 | struct dvb_frontend *drxd_attach(const struct drxd_config *config, | ||
| 58 | void *priv, struct i2c_adapter *i2c, | ||
| 59 | struct device *dev); | ||
| 60 | extern int drxd_config_i2c(struct dvb_frontend *, int); | ||
| 61 | #endif | ||
diff --git a/drivers/media/dvb/frontends/drxd_firm.c b/drivers/media/dvb/frontends/drxd_firm.c new file mode 100644 index 000000000000..5418b0b1dadc --- /dev/null +++ b/drivers/media/dvb/frontends/drxd_firm.c | |||
| @@ -0,0 +1,929 @@ | |||
| 1 | /* | ||
| 2 | * drxd_firm.c : DRXD firmware tables | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006-2007 Micronas | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 only, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 20 | * 02110-1301, USA | ||
| 21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 22 | */ | ||
| 23 | |||
| 24 | /* TODO: generate this file with a script from a settings file */ | ||
| 25 | |||
| 26 | /* Contains A2 firmware version: 1.4.2 | ||
| 27 | * Contains B1 firmware version: 3.3.33 | ||
| 28 | * Contains settings from driver 1.4.23 | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include "drxd_firm.h" | ||
| 32 | |||
| 33 | #define ADDRESS(x) ((x) & 0xFF), (((x)>>8) & 0xFF), (((x)>>16) & 0xFF), (((x)>>24) & 0xFF) | ||
| 34 | #define LENGTH(x) ((x) & 0xFF), (((x)>>8) & 0xFF) | ||
| 35 | |||
| 36 | /* Is written via block write, must be little endian */ | ||
| 37 | #define DATA16(x) ((x) & 0xFF), (((x)>>8) & 0xFF) | ||
| 38 | |||
| 39 | #define WRBLOCK(a, l) ADDRESS(a), LENGTH(l) | ||
| 40 | #define WR16(a, d) ADDRESS(a), LENGTH(1), DATA16(d) | ||
| 41 | |||
| 42 | #define END_OF_TABLE 0xFF, 0xFF, 0xFF, 0xFF | ||
| 43 | |||
| 44 | /* HI firmware patches */ | ||
| 45 | |||
| 46 | #define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A | ||
| 47 | #define HI_TR_FUNC_SIZE 9 /* size of this function in instruction words */ | ||
| 48 | |||
| 49 | u8 DRXD_InitAtomicRead[] = { | ||
| 50 | WRBLOCK(HI_TR_FUNC_ADDR, HI_TR_FUNC_SIZE), | ||
| 51 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 52 | 0x60, 0x04, /* r0rami.dt -> ring.xba; */ | ||
| 53 | 0x61, 0x04, /* r0rami.dt -> ring.xad; */ | ||
| 54 | 0xE3, 0x07, /* HI_RA_RAM_USR_BEGIN -> ring.iad; */ | ||
| 55 | 0x40, 0x00, /* (long immediate) */ | ||
| 56 | 0x64, 0x04, /* r0rami.dt -> ring.len; */ | ||
| 57 | 0x65, 0x04, /* r0rami.dt -> ring.ctl; */ | ||
| 58 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 59 | 0x38, 0x00, /* 0 -> jumps.ad; */ | ||
| 60 | END_OF_TABLE | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* Pins D0 and D1 of the parallel MPEG output can be used | ||
| 64 | to set the I2C address of a device. */ | ||
| 65 | |||
| 66 | #define HI_RST_FUNC_ADDR (HI_IF_RAM_USR_BEGIN__A + HI_TR_FUNC_SIZE) | ||
| 67 | #define HI_RST_FUNC_SIZE 54 /* size of this function in instruction words */ | ||
| 68 | |||
| 69 | /* D0 Version */ | ||
| 70 | u8 DRXD_HiI2cPatch_1[] = { | ||
| 71 | WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE), | ||
| 72 | 0xC8, 0x07, 0x01, 0x00, /* MASK -> reg0.dt; */ | ||
| 73 | 0xE0, 0x07, 0x15, 0x02, /* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */ | ||
| 74 | 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | ||
| 75 | 0xA2, 0x00, /* M_BNK_ID_DAT -> ring.iba; */ | ||
| 76 | 0x23, 0x00, /* &data -> ring.iad; */ | ||
| 77 | 0x24, 0x00, /* 0 -> ring.len; */ | ||
| 78 | 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | ||
| 79 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 80 | 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | ||
| 81 | 0xC0, 0x07, 0xFF, 0x0F, /* -1 -> w0ram.dt; */ | ||
| 82 | 0x63, 0x00, /* &data+1 -> ring.iad; */ | ||
| 83 | 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | ||
| 84 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 85 | 0xE1, 0x07, 0x38, 0x00, /* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad; */ | ||
| 86 | 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | ||
| 87 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 88 | 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | ||
| 89 | 0x23, 0x00, /* &data -> ring.iad; */ | ||
| 90 | 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | ||
| 91 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 92 | 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | ||
| 93 | 0x0F, 0x04, /* r0ram.dt -> and.op; */ | ||
| 94 | 0x1C, 0x06, /* reg0.dt -> and.tr; */ | ||
| 95 | 0xCF, 0x04, /* and.rs -> add.op; */ | ||
| 96 | 0xD0, 0x07, 0x70, 0x00, /* DEF_DEV_ID -> add.tr; */ | ||
| 97 | 0xD0, 0x04, /* add.rs -> add.tr; */ | ||
| 98 | 0xC8, 0x04, /* add.rs -> reg0.dt; */ | ||
| 99 | 0x60, 0x00, /* reg0.dt -> w0ram.dt; */ | ||
| 100 | 0xC2, 0x07, 0x10, 0x00, /* SLV0_BASE -> w0rami.ad; */ | ||
| 101 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 102 | 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | ||
| 103 | 0xC2, 0x07, 0x20, 0x00, /* SLV1_BASE -> w0rami.ad; */ | ||
| 104 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 105 | 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | ||
| 106 | 0xC2, 0x07, 0x30, 0x00, /* CMD_BASE -> w0rami.ad; */ | ||
| 107 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 108 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 109 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 110 | 0x68, 0x00, /* M_IC_SEL_PT1 -> i2c.sel; */ | ||
| 111 | 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | ||
| 112 | 0x28, 0x00, /* M_IC_SEL_PT0 -> i2c.sel; */ | ||
| 113 | 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | ||
| 114 | 0xF8, 0x07, 0x2F, 0x00, /* 0x2F -> jumps.ad; */ | ||
| 115 | |||
| 116 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)), | ||
| 117 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 118 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)), | ||
| 119 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 120 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)), | ||
| 121 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 122 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)), | ||
| 123 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 124 | |||
| 125 | /* Force quick and dirty reset */ | ||
| 126 | WR16(B_HI_CT_REG_COMM_STATE__A, 0), | ||
| 127 | END_OF_TABLE | ||
| 128 | }; | ||
| 129 | |||
| 130 | /* D0,D1 Version */ | ||
| 131 | u8 DRXD_HiI2cPatch_3[] = { | ||
| 132 | WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE), | ||
| 133 | 0xC8, 0x07, 0x03, 0x00, /* MASK -> reg0.dt; */ | ||
| 134 | 0xE0, 0x07, 0x15, 0x02, /* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */ | ||
| 135 | 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | ||
| 136 | 0xA2, 0x00, /* M_BNK_ID_DAT -> ring.iba; */ | ||
| 137 | 0x23, 0x00, /* &data -> ring.iad; */ | ||
| 138 | 0x24, 0x00, /* 0 -> ring.len; */ | ||
| 139 | 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | ||
| 140 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 141 | 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | ||
| 142 | 0xC0, 0x07, 0xFF, 0x0F, /* -1 -> w0ram.dt; */ | ||
| 143 | 0x63, 0x00, /* &data+1 -> ring.iad; */ | ||
| 144 | 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | ||
| 145 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 146 | 0xE1, 0x07, 0x38, 0x00, /* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad; */ | ||
| 147 | 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | ||
| 148 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 149 | 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | ||
| 150 | 0x23, 0x00, /* &data -> ring.iad; */ | ||
| 151 | 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | ||
| 152 | 0x26, 0x00, /* 0 -> ring.rdy; */ | ||
| 153 | 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | ||
| 154 | 0x0F, 0x04, /* r0ram.dt -> and.op; */ | ||
| 155 | 0x1C, 0x06, /* reg0.dt -> and.tr; */ | ||
| 156 | 0xCF, 0x04, /* and.rs -> add.op; */ | ||
| 157 | 0xD0, 0x07, 0x70, 0x00, /* DEF_DEV_ID -> add.tr; */ | ||
| 158 | 0xD0, 0x04, /* add.rs -> add.tr; */ | ||
| 159 | 0xC8, 0x04, /* add.rs -> reg0.dt; */ | ||
| 160 | 0x60, 0x00, /* reg0.dt -> w0ram.dt; */ | ||
| 161 | 0xC2, 0x07, 0x10, 0x00, /* SLV0_BASE -> w0rami.ad; */ | ||
| 162 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 163 | 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | ||
| 164 | 0xC2, 0x07, 0x20, 0x00, /* SLV1_BASE -> w0rami.ad; */ | ||
| 165 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 166 | 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | ||
| 167 | 0xC2, 0x07, 0x30, 0x00, /* CMD_BASE -> w0rami.ad; */ | ||
| 168 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 169 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 170 | 0x01, 0x00, /* 0 -> w0rami.dt; */ | ||
| 171 | 0x68, 0x00, /* M_IC_SEL_PT1 -> i2c.sel; */ | ||
| 172 | 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | ||
| 173 | 0x28, 0x00, /* M_IC_SEL_PT0 -> i2c.sel; */ | ||
| 174 | 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | ||
| 175 | 0xF8, 0x07, 0x2F, 0x00, /* 0x2F -> jumps.ad; */ | ||
| 176 | |||
| 177 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)), | ||
| 178 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 179 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)), | ||
| 180 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 181 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)), | ||
| 182 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 183 | WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)), | ||
| 184 | (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | ||
| 185 | |||
| 186 | /* Force quick and dirty reset */ | ||
| 187 | WR16(B_HI_CT_REG_COMM_STATE__A, 0), | ||
| 188 | END_OF_TABLE | ||
| 189 | }; | ||
| 190 | |||
| 191 | u8 DRXD_ResetCEFR[] = { | ||
| 192 | WRBLOCK(CE_REG_FR_TREAL00__A, 57), | ||
| 193 | 0x52, 0x00, /* CE_REG_FR_TREAL00__A */ | ||
| 194 | 0x00, 0x00, /* CE_REG_FR_TIMAG00__A */ | ||
| 195 | 0x52, 0x00, /* CE_REG_FR_TREAL01__A */ | ||
| 196 | 0x00, 0x00, /* CE_REG_FR_TIMAG01__A */ | ||
| 197 | 0x52, 0x00, /* CE_REG_FR_TREAL02__A */ | ||
| 198 | 0x00, 0x00, /* CE_REG_FR_TIMAG02__A */ | ||
| 199 | 0x52, 0x00, /* CE_REG_FR_TREAL03__A */ | ||
| 200 | 0x00, 0x00, /* CE_REG_FR_TIMAG03__A */ | ||
| 201 | 0x52, 0x00, /* CE_REG_FR_TREAL04__A */ | ||
| 202 | 0x00, 0x00, /* CE_REG_FR_TIMAG04__A */ | ||
| 203 | 0x52, 0x00, /* CE_REG_FR_TREAL05__A */ | ||
| 204 | 0x00, 0x00, /* CE_REG_FR_TIMAG05__A */ | ||
| 205 | 0x52, 0x00, /* CE_REG_FR_TREAL06__A */ | ||
| 206 | 0x00, 0x00, /* CE_REG_FR_TIMAG06__A */ | ||
| 207 | 0x52, 0x00, /* CE_REG_FR_TREAL07__A */ | ||
| 208 | 0x00, 0x00, /* CE_REG_FR_TIMAG07__A */ | ||
| 209 | 0x52, 0x00, /* CE_REG_FR_TREAL08__A */ | ||
| 210 | 0x00, 0x00, /* CE_REG_FR_TIMAG08__A */ | ||
| 211 | 0x52, 0x00, /* CE_REG_FR_TREAL09__A */ | ||
| 212 | 0x00, 0x00, /* CE_REG_FR_TIMAG09__A */ | ||
| 213 | 0x52, 0x00, /* CE_REG_FR_TREAL10__A */ | ||
| 214 | 0x00, 0x00, /* CE_REG_FR_TIMAG10__A */ | ||
| 215 | 0x52, 0x00, /* CE_REG_FR_TREAL11__A */ | ||
| 216 | 0x00, 0x00, /* CE_REG_FR_TIMAG11__A */ | ||
| 217 | |||
| 218 | 0x52, 0x00, /* CE_REG_FR_MID_TAP__A */ | ||
| 219 | |||
| 220 | 0x0B, 0x00, /* CE_REG_FR_SQS_G00__A */ | ||
| 221 | 0x0B, 0x00, /* CE_REG_FR_SQS_G01__A */ | ||
| 222 | 0x0B, 0x00, /* CE_REG_FR_SQS_G02__A */ | ||
| 223 | 0x0B, 0x00, /* CE_REG_FR_SQS_G03__A */ | ||
| 224 | 0x0B, 0x00, /* CE_REG_FR_SQS_G04__A */ | ||
| 225 | 0x0B, 0x00, /* CE_REG_FR_SQS_G05__A */ | ||
| 226 | 0x0B, 0x00, /* CE_REG_FR_SQS_G06__A */ | ||
| 227 | 0x0B, 0x00, /* CE_REG_FR_SQS_G07__A */ | ||
| 228 | 0x0B, 0x00, /* CE_REG_FR_SQS_G08__A */ | ||
| 229 | 0x0B, 0x00, /* CE_REG_FR_SQS_G09__A */ | ||
| 230 | 0x0B, 0x00, /* CE_REG_FR_SQS_G10__A */ | ||
| 231 | 0x0B, 0x00, /* CE_REG_FR_SQS_G11__A */ | ||
| 232 | 0x0B, 0x00, /* CE_REG_FR_SQS_G12__A */ | ||
| 233 | |||
| 234 | 0xFF, 0x01, /* CE_REG_FR_RIO_G00__A */ | ||
| 235 | 0x90, 0x01, /* CE_REG_FR_RIO_G01__A */ | ||
| 236 | 0x0B, 0x01, /* CE_REG_FR_RIO_G02__A */ | ||
| 237 | 0xC8, 0x00, /* CE_REG_FR_RIO_G03__A */ | ||
| 238 | 0xA0, 0x00, /* CE_REG_FR_RIO_G04__A */ | ||
| 239 | 0x85, 0x00, /* CE_REG_FR_RIO_G05__A */ | ||
| 240 | 0x72, 0x00, /* CE_REG_FR_RIO_G06__A */ | ||
| 241 | 0x64, 0x00, /* CE_REG_FR_RIO_G07__A */ | ||
| 242 | 0x59, 0x00, /* CE_REG_FR_RIO_G08__A */ | ||
| 243 | 0x50, 0x00, /* CE_REG_FR_RIO_G09__A */ | ||
| 244 | 0x49, 0x00, /* CE_REG_FR_RIO_G10__A */ | ||
| 245 | |||
| 246 | 0x10, 0x00, /* CE_REG_FR_MODE__A */ | ||
| 247 | 0x78, 0x00, /* CE_REG_FR_SQS_TRH__A */ | ||
| 248 | 0x00, 0x00, /* CE_REG_FR_RIO_GAIN__A */ | ||
| 249 | 0x00, 0x02, /* CE_REG_FR_BYPASS__A */ | ||
| 250 | 0x0D, 0x00, /* CE_REG_FR_PM_SET__A */ | ||
| 251 | 0x07, 0x00, /* CE_REG_FR_ERR_SH__A */ | ||
| 252 | 0x04, 0x00, /* CE_REG_FR_MAN_SH__A */ | ||
| 253 | 0x06, 0x00, /* CE_REG_FR_TAP_SH__A */ | ||
| 254 | |||
| 255 | END_OF_TABLE | ||
| 256 | }; | ||
| 257 | |||
| 258 | u8 DRXD_InitFEA2_1[] = { | ||
| 259 | WRBLOCK(FE_AD_REG_PD__A, 3), | ||
| 260 | 0x00, 0x00, /* FE_AD_REG_PD__A */ | ||
| 261 | 0x01, 0x00, /* FE_AD_REG_INVEXT__A */ | ||
| 262 | 0x00, 0x00, /* FE_AD_REG_CLKNEG__A */ | ||
| 263 | |||
| 264 | WRBLOCK(FE_AG_REG_DCE_AUR_CNT__A, 2), | ||
| 265 | 0x10, 0x00, /* FE_AG_REG_DCE_AUR_CNT__A */ | ||
| 266 | 0x10, 0x00, /* FE_AG_REG_DCE_RUR_CNT__A */ | ||
| 267 | |||
| 268 | WRBLOCK(FE_AG_REG_ACE_AUR_CNT__A, 2), | ||
| 269 | 0x0E, 0x00, /* FE_AG_REG_ACE_AUR_CNT__A */ | ||
| 270 | 0x00, 0x00, /* FE_AG_REG_ACE_RUR_CNT__A */ | ||
| 271 | |||
| 272 | WRBLOCK(FE_AG_REG_EGC_FLA_RGN__A, 5), | ||
| 273 | 0x04, 0x00, /* FE_AG_REG_EGC_FLA_RGN__A */ | ||
| 274 | 0x1F, 0x00, /* FE_AG_REG_EGC_SLO_RGN__A */ | ||
| 275 | 0x00, 0x00, /* FE_AG_REG_EGC_JMP_PSN__A */ | ||
| 276 | 0x00, 0x00, /* FE_AG_REG_EGC_FLA_INC__A */ | ||
| 277 | 0x00, 0x00, /* FE_AG_REG_EGC_FLA_DEC__A */ | ||
| 278 | |||
| 279 | WRBLOCK(FE_AG_REG_GC1_AGC_MAX__A, 2), | ||
| 280 | 0xFF, 0x01, /* FE_AG_REG_GC1_AGC_MAX__A */ | ||
| 281 | 0x00, 0xFE, /* FE_AG_REG_GC1_AGC_MIN__A */ | ||
| 282 | |||
| 283 | WRBLOCK(FE_AG_REG_IND_WIN__A, 29), | ||
| 284 | 0x00, 0x00, /* FE_AG_REG_IND_WIN__A */ | ||
| 285 | 0x05, 0x00, /* FE_AG_REG_IND_THD_LOL__A */ | ||
| 286 | 0x0F, 0x00, /* FE_AG_REG_IND_THD_HIL__A */ | ||
| 287 | 0x00, 0x00, /* FE_AG_REG_IND_DEL__A don't care */ | ||
| 288 | 0x1E, 0x00, /* FE_AG_REG_IND_PD1_WRI__A */ | ||
| 289 | 0x0C, 0x00, /* FE_AG_REG_PDA_AUR_CNT__A */ | ||
| 290 | 0x00, 0x00, /* FE_AG_REG_PDA_RUR_CNT__A */ | ||
| 291 | 0x00, 0x00, /* FE_AG_REG_PDA_AVE_DAT__A don't care */ | ||
| 292 | 0x00, 0x00, /* FE_AG_REG_PDC_RUR_CNT__A */ | ||
| 293 | 0x01, 0x00, /* FE_AG_REG_PDC_SET_LVL__A */ | ||
| 294 | 0x02, 0x00, /* FE_AG_REG_PDC_FLA_RGN__A */ | ||
| 295 | 0x00, 0x00, /* FE_AG_REG_PDC_JMP_PSN__A don't care */ | ||
| 296 | 0xFF, 0xFF, /* FE_AG_REG_PDC_FLA_STP__A */ | ||
| 297 | 0xFF, 0xFF, /* FE_AG_REG_PDC_SLO_STP__A */ | ||
| 298 | 0x00, 0x1F, /* FE_AG_REG_PDC_PD2_WRI__A don't care */ | ||
| 299 | 0x00, 0x00, /* FE_AG_REG_PDC_MAP_DAT__A don't care */ | ||
| 300 | 0x02, 0x00, /* FE_AG_REG_PDC_MAX__A */ | ||
| 301 | 0x0C, 0x00, /* FE_AG_REG_TGA_AUR_CNT__A */ | ||
| 302 | 0x00, 0x00, /* FE_AG_REG_TGA_RUR_CNT__A */ | ||
| 303 | 0x00, 0x00, /* FE_AG_REG_TGA_AVE_DAT__A don't care */ | ||
| 304 | 0x00, 0x00, /* FE_AG_REG_TGC_RUR_CNT__A */ | ||
| 305 | 0x22, 0x00, /* FE_AG_REG_TGC_SET_LVL__A */ | ||
| 306 | 0x15, 0x00, /* FE_AG_REG_TGC_FLA_RGN__A */ | ||
| 307 | 0x00, 0x00, /* FE_AG_REG_TGC_JMP_PSN__A don't care */ | ||
| 308 | 0x01, 0x00, /* FE_AG_REG_TGC_FLA_STP__A */ | ||
| 309 | 0x0A, 0x00, /* FE_AG_REG_TGC_SLO_STP__A */ | ||
| 310 | 0x00, 0x00, /* FE_AG_REG_TGC_MAP_DAT__A don't care */ | ||
| 311 | 0x10, 0x00, /* FE_AG_REG_FGA_AUR_CNT__A */ | ||
| 312 | 0x10, 0x00, /* FE_AG_REG_FGA_RUR_CNT__A */ | ||
| 313 | |||
| 314 | WRBLOCK(FE_AG_REG_BGC_FGC_WRI__A, 2), | ||
| 315 | 0x00, 0x00, /* FE_AG_REG_BGC_FGC_WRI__A */ | ||
| 316 | 0x00, 0x00, /* FE_AG_REG_BGC_CGC_WRI__A */ | ||
| 317 | |||
| 318 | WRBLOCK(FE_FD_REG_SCL__A, 3), | ||
| 319 | 0x05, 0x00, /* FE_FD_REG_SCL__A */ | ||
| 320 | 0x03, 0x00, /* FE_FD_REG_MAX_LEV__A */ | ||
| 321 | 0x05, 0x00, /* FE_FD_REG_NR__A */ | ||
| 322 | |||
| 323 | WRBLOCK(FE_CF_REG_SCL__A, 5), | ||
| 324 | 0x16, 0x00, /* FE_CF_REG_SCL__A */ | ||
| 325 | 0x04, 0x00, /* FE_CF_REG_MAX_LEV__A */ | ||
| 326 | 0x06, 0x00, /* FE_CF_REG_NR__A */ | ||
| 327 | 0x00, 0x00, /* FE_CF_REG_IMP_VAL__A */ | ||
| 328 | 0x01, 0x00, /* FE_CF_REG_MEAS_VAL__A */ | ||
| 329 | |||
| 330 | WRBLOCK(FE_CU_REG_FRM_CNT_RST__A, 2), | ||
| 331 | 0x00, 0x08, /* FE_CU_REG_FRM_CNT_RST__A */ | ||
| 332 | 0x00, 0x00, /* FE_CU_REG_FRM_CNT_STR__A */ | ||
| 333 | |||
| 334 | END_OF_TABLE | ||
| 335 | }; | ||
| 336 | |||
| 337 | /* with PGA */ | ||
| 338 | /* WR16COND( DRXD_WITH_PGA, FE_AG_REG_AG_PGA_MODE__A , 0x0004), */ | ||
| 339 | /* without PGA */ | ||
| 340 | /* WR16COND( DRXD_WITHOUT_PGA, FE_AG_REG_AG_PGA_MODE__A , 0x0001), */ | ||
| 341 | /* WR16(FE_AG_REG_AG_AGC_SIO__A, (extAttr -> FeAgRegAgAgcSio), 0x0000 );*/ | ||
| 342 | /* WR16(FE_AG_REG_AG_PWD__A ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/ | ||
| 343 | |||
| 344 | u8 DRXD_InitFEA2_2[] = { | ||
| 345 | WR16(FE_AG_REG_CDR_RUR_CNT__A, 0x0010), | ||
| 346 | WR16(FE_AG_REG_FGM_WRI__A, 48), | ||
| 347 | /* Activate measurement, activate scale */ | ||
| 348 | WR16(FE_FD_REG_MEAS_VAL__A, 0x0001), | ||
| 349 | |||
| 350 | WR16(FE_CU_REG_COMM_EXEC__A, 0x0001), | ||
| 351 | WR16(FE_CF_REG_COMM_EXEC__A, 0x0001), | ||
| 352 | WR16(FE_IF_REG_COMM_EXEC__A, 0x0001), | ||
| 353 | WR16(FE_FD_REG_COMM_EXEC__A, 0x0001), | ||
| 354 | WR16(FE_FS_REG_COMM_EXEC__A, 0x0001), | ||
| 355 | WR16(FE_AD_REG_COMM_EXEC__A, 0x0001), | ||
| 356 | WR16(FE_AG_REG_COMM_EXEC__A, 0x0001), | ||
| 357 | WR16(FE_AG_REG_AG_MODE_LOP__A, 0x895E), | ||
| 358 | |||
| 359 | END_OF_TABLE | ||
| 360 | }; | ||
| 361 | |||
| 362 | u8 DRXD_InitFEB1_1[] = { | ||
| 363 | WR16(B_FE_AD_REG_PD__A, 0x0000), | ||
| 364 | WR16(B_FE_AD_REG_CLKNEG__A, 0x0000), | ||
| 365 | WR16(B_FE_AG_REG_BGC_FGC_WRI__A, 0x0000), | ||
| 366 | WR16(B_FE_AG_REG_BGC_CGC_WRI__A, 0x0000), | ||
| 367 | WR16(B_FE_AG_REG_AG_MODE_LOP__A, 0x000a), | ||
| 368 | WR16(B_FE_AG_REG_IND_PD1_WRI__A, 35), | ||
| 369 | WR16(B_FE_AG_REG_IND_WIN__A, 0), | ||
| 370 | WR16(B_FE_AG_REG_IND_THD_LOL__A, 8), | ||
| 371 | WR16(B_FE_AG_REG_IND_THD_HIL__A, 8), | ||
| 372 | WR16(B_FE_CF_REG_IMP_VAL__A, 1), | ||
| 373 | WR16(B_FE_AG_REG_EGC_FLA_RGN__A, 7), | ||
| 374 | END_OF_TABLE | ||
| 375 | }; | ||
| 376 | |||
| 377 | /* with PGA */ | ||
| 378 | /* WR16(B_FE_AG_REG_AG_PGA_MODE__A , 0x0000, 0x0000); */ | ||
| 379 | /* without PGA */ | ||
| 380 | /* WR16(B_FE_AG_REG_AG_PGA_MODE__A , | ||
| 381 | B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);*/ | ||
| 382 | /* WR16(B_FE_AG_REG_AG_AGC_SIO__A,(extAttr -> FeAgRegAgAgcSio), 0x0000 );*//*added HS 23-05-2005 */ | ||
| 383 | /* WR16(B_FE_AG_REG_AG_PWD__A ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/ | ||
| 384 | |||
| 385 | u8 DRXD_InitFEB1_2[] = { | ||
| 386 | WR16(B_FE_COMM_EXEC__A, 0x0001), | ||
| 387 | |||
| 388 | /* RF-AGC setup */ | ||
| 389 | WR16(B_FE_AG_REG_PDA_AUR_CNT__A, 0x0C), | ||
| 390 | WR16(B_FE_AG_REG_PDC_SET_LVL__A, 0x01), | ||
| 391 | WR16(B_FE_AG_REG_PDC_FLA_RGN__A, 0x02), | ||
| 392 | WR16(B_FE_AG_REG_PDC_FLA_STP__A, 0xFFFF), | ||
| 393 | WR16(B_FE_AG_REG_PDC_SLO_STP__A, 0xFFFF), | ||
| 394 | WR16(B_FE_AG_REG_PDC_MAX__A, 0x02), | ||
| 395 | WR16(B_FE_AG_REG_TGA_AUR_CNT__A, 0x0C), | ||
| 396 | WR16(B_FE_AG_REG_TGC_SET_LVL__A, 0x22), | ||
| 397 | WR16(B_FE_AG_REG_TGC_FLA_RGN__A, 0x15), | ||
| 398 | WR16(B_FE_AG_REG_TGC_FLA_STP__A, 0x01), | ||
| 399 | WR16(B_FE_AG_REG_TGC_SLO_STP__A, 0x0A), | ||
| 400 | |||
| 401 | WR16(B_FE_CU_REG_DIV_NFC_CLP__A, 0), | ||
| 402 | WR16(B_FE_CU_REG_CTR_NFC_OCR__A, 25000), | ||
| 403 | WR16(B_FE_CU_REG_CTR_NFC_ICR__A, 1), | ||
| 404 | END_OF_TABLE | ||
| 405 | }; | ||
| 406 | |||
| 407 | u8 DRXD_InitCPA2[] = { | ||
| 408 | WRBLOCK(CP_REG_BR_SPL_OFFSET__A, 2), | ||
| 409 | 0x07, 0x00, /* CP_REG_BR_SPL_OFFSET__A */ | ||
| 410 | 0x0A, 0x00, /* CP_REG_BR_STR_DEL__A */ | ||
| 411 | |||
| 412 | WRBLOCK(CP_REG_RT_ANG_INC0__A, 4), | ||
| 413 | 0x00, 0x00, /* CP_REG_RT_ANG_INC0__A */ | ||
| 414 | 0x00, 0x00, /* CP_REG_RT_ANG_INC1__A */ | ||
| 415 | 0x03, 0x00, /* CP_REG_RT_DETECT_ENA__A */ | ||
| 416 | 0x03, 0x00, /* CP_REG_RT_DETECT_TRH__A */ | ||
| 417 | |||
| 418 | WRBLOCK(CP_REG_AC_NEXP_OFFS__A, 5), | ||
| 419 | 0x32, 0x00, /* CP_REG_AC_NEXP_OFFS__A */ | ||
| 420 | 0x62, 0x00, /* CP_REG_AC_AVER_POW__A */ | ||
| 421 | 0x82, 0x00, /* CP_REG_AC_MAX_POW__A */ | ||
| 422 | 0x26, 0x00, /* CP_REG_AC_WEIGHT_MAN__A */ | ||
| 423 | 0x0F, 0x00, /* CP_REG_AC_WEIGHT_EXP__A */ | ||
| 424 | |||
| 425 | WRBLOCK(CP_REG_AC_AMP_MODE__A, 2), | ||
| 426 | 0x02, 0x00, /* CP_REG_AC_AMP_MODE__A */ | ||
| 427 | 0x01, 0x00, /* CP_REG_AC_AMP_FIX__A */ | ||
| 428 | |||
| 429 | WR16(CP_REG_INTERVAL__A, 0x0005), | ||
| 430 | WR16(CP_REG_RT_EXP_MARG__A, 0x0004), | ||
| 431 | WR16(CP_REG_AC_ANG_MODE__A, 0x0003), | ||
| 432 | |||
| 433 | WR16(CP_REG_COMM_EXEC__A, 0x0001), | ||
| 434 | END_OF_TABLE | ||
| 435 | }; | ||
| 436 | |||
| 437 | u8 DRXD_InitCPB1[] = { | ||
| 438 | WR16(B_CP_REG_BR_SPL_OFFSET__A, 0x0008), | ||
| 439 | WR16(B_CP_COMM_EXEC__A, 0x0001), | ||
| 440 | END_OF_TABLE | ||
| 441 | }; | ||
| 442 | |||
| 443 | u8 DRXD_InitCEA2[] = { | ||
| 444 | WRBLOCK(CE_REG_AVG_POW__A, 4), | ||
| 445 | 0x62, 0x00, /* CE_REG_AVG_POW__A */ | ||
| 446 | 0x78, 0x00, /* CE_REG_MAX_POW__A */ | ||
| 447 | 0x62, 0x00, /* CE_REG_ATT__A */ | ||
| 448 | 0x17, 0x00, /* CE_REG_NRED__A */ | ||
| 449 | |||
| 450 | WRBLOCK(CE_REG_NE_ERR_SELECT__A, 2), | ||
| 451 | 0x07, 0x00, /* CE_REG_NE_ERR_SELECT__A */ | ||
| 452 | 0xEB, 0xFF, /* CE_REG_NE_TD_CAL__A */ | ||
| 453 | |||
| 454 | WRBLOCK(CE_REG_NE_MIXAVG__A, 2), | ||
| 455 | 0x06, 0x00, /* CE_REG_NE_MIXAVG__A */ | ||
| 456 | 0x00, 0x00, /* CE_REG_NE_NUPD_OFS__A */ | ||
| 457 | |||
| 458 | WRBLOCK(CE_REG_PE_NEXP_OFFS__A, 2), | ||
| 459 | 0x00, 0x00, /* CE_REG_PE_NEXP_OFFS__A */ | ||
| 460 | 0x00, 0x00, /* CE_REG_PE_TIMESHIFT__A */ | ||
| 461 | |||
| 462 | WRBLOCK(CE_REG_TP_A0_TAP_NEW__A, 3), | ||
| 463 | 0x00, 0x01, /* CE_REG_TP_A0_TAP_NEW__A */ | ||
| 464 | 0x01, 0x00, /* CE_REG_TP_A0_TAP_NEW_VALID__A */ | ||
| 465 | 0x0E, 0x00, /* CE_REG_TP_A0_MU_LMS_STEP__A */ | ||
| 466 | |||
| 467 | WRBLOCK(CE_REG_TP_A1_TAP_NEW__A, 3), | ||
| 468 | 0x00, 0x00, /* CE_REG_TP_A1_TAP_NEW__A */ | ||
| 469 | 0x01, 0x00, /* CE_REG_TP_A1_TAP_NEW_VALID__A */ | ||
| 470 | 0x0A, 0x00, /* CE_REG_TP_A1_MU_LMS_STEP__A */ | ||
| 471 | |||
| 472 | WRBLOCK(CE_REG_FI_SHT_INCR__A, 2), | ||
| 473 | 0x12, 0x00, /* CE_REG_FI_SHT_INCR__A */ | ||
| 474 | 0x0C, 0x00, /* CE_REG_FI_EXP_NORM__A */ | ||
| 475 | |||
| 476 | WRBLOCK(CE_REG_IR_INPUTSEL__A, 3), | ||
| 477 | 0x00, 0x00, /* CE_REG_IR_INPUTSEL__A */ | ||
| 478 | 0x00, 0x00, /* CE_REG_IR_STARTPOS__A */ | ||
| 479 | 0xFF, 0x00, /* CE_REG_IR_NEXP_THRES__A */ | ||
| 480 | |||
| 481 | WR16(CE_REG_TI_NEXP_OFFS__A, 0x0000), | ||
| 482 | |||
| 483 | END_OF_TABLE | ||
| 484 | }; | ||
| 485 | |||
| 486 | u8 DRXD_InitCEB1[] = { | ||
| 487 | WR16(B_CE_REG_TI_PHN_ENABLE__A, 0x0001), | ||
| 488 | WR16(B_CE_REG_FR_PM_SET__A, 0x000D), | ||
| 489 | |||
| 490 | END_OF_TABLE | ||
| 491 | }; | ||
| 492 | |||
| 493 | u8 DRXD_InitEQA2[] = { | ||
| 494 | WRBLOCK(EQ_REG_OT_QNT_THRES0__A, 4), | ||
| 495 | 0x1E, 0x00, /* EQ_REG_OT_QNT_THRES0__A */ | ||
| 496 | 0x1F, 0x00, /* EQ_REG_OT_QNT_THRES1__A */ | ||
| 497 | 0x06, 0x00, /* EQ_REG_OT_CSI_STEP__A */ | ||
| 498 | 0x02, 0x00, /* EQ_REG_OT_CSI_OFFSET__A */ | ||
| 499 | |||
| 500 | WR16(EQ_REG_TD_REQ_SMB_CNT__A, 0x0200), | ||
| 501 | WR16(EQ_REG_IS_CLIP_EXP__A, 0x001F), | ||
| 502 | WR16(EQ_REG_SN_OFFSET__A, (u16) (-7)), | ||
| 503 | WR16(EQ_REG_RC_SEL_CAR__A, 0x0002), | ||
| 504 | WR16(EQ_REG_COMM_EXEC__A, 0x0001), | ||
| 505 | END_OF_TABLE | ||
| 506 | }; | ||
| 507 | |||
| 508 | u8 DRXD_InitEQB1[] = { | ||
| 509 | WR16(B_EQ_REG_COMM_EXEC__A, 0x0001), | ||
| 510 | END_OF_TABLE | ||
| 511 | }; | ||
| 512 | |||
| 513 | u8 DRXD_ResetECRAM[] = { | ||
| 514 | /* Reset packet sync bytes in EC_VD ram */ | ||
| 515 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | ||
| 516 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | ||
| 517 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | ||
| 518 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | ||
| 519 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | ||
| 520 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | ||
| 521 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | ||
| 522 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | ||
| 523 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | ||
| 524 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | ||
| 525 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | ||
| 526 | |||
| 527 | /* Reset packet sync bytes in EC_RS ram */ | ||
| 528 | WR16(EC_RS_EC_RAM__A, 0x0000), | ||
| 529 | WR16(EC_RS_EC_RAM__A + 204, 0x0000), | ||
| 530 | END_OF_TABLE | ||
| 531 | }; | ||
| 532 | |||
| 533 | u8 DRXD_InitECA2[] = { | ||
| 534 | WRBLOCK(EC_SB_REG_CSI_HI__A, 6), | ||
| 535 | 0x1F, 0x00, /* EC_SB_REG_CSI_HI__A */ | ||
| 536 | 0x1E, 0x00, /* EC_SB_REG_CSI_LO__A */ | ||
| 537 | 0x01, 0x00, /* EC_SB_REG_SMB_TGL__A */ | ||
| 538 | 0x7F, 0x00, /* EC_SB_REG_SNR_HI__A */ | ||
| 539 | 0x7F, 0x00, /* EC_SB_REG_SNR_MID__A */ | ||
| 540 | 0x7F, 0x00, /* EC_SB_REG_SNR_LO__A */ | ||
| 541 | |||
| 542 | WRBLOCK(EC_RS_REG_REQ_PCK_CNT__A, 2), | ||
| 543 | 0x00, 0x10, /* EC_RS_REG_REQ_PCK_CNT__A */ | ||
| 544 | DATA16(EC_RS_REG_VAL_PCK), /* EC_RS_REG_VAL__A */ | ||
| 545 | |||
| 546 | WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5), | ||
| 547 | 0x03, 0x00, /* EC_OC_REG_TMD_TOP_MODE__A */ | ||
| 548 | 0xF4, 0x01, /* EC_OC_REG_TMD_TOP_CNT__A */ | ||
| 549 | 0xC0, 0x03, /* EC_OC_REG_TMD_HIL_MAR__A */ | ||
| 550 | 0x40, 0x00, /* EC_OC_REG_TMD_LOL_MAR__A */ | ||
| 551 | 0x03, 0x00, /* EC_OC_REG_TMD_CUR_CNT__A */ | ||
| 552 | |||
| 553 | WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2), | ||
| 554 | 0x06, 0x00, /* EC_OC_REG_AVR_ASH_CNT__A */ | ||
| 555 | 0x02, 0x00, /* EC_OC_REG_AVR_BSH_CNT__A */ | ||
| 556 | |||
| 557 | WRBLOCK(EC_OC_REG_RCN_MODE__A, 7), | ||
| 558 | 0x07, 0x00, /* EC_OC_REG_RCN_MODE__A */ | ||
| 559 | 0x00, 0x00, /* EC_OC_REG_RCN_CRA_LOP__A */ | ||
| 560 | 0xc0, 0x00, /* EC_OC_REG_RCN_CRA_HIP__A */ | ||
| 561 | 0x00, 0x10, /* EC_OC_REG_RCN_CST_LOP__A */ | ||
| 562 | 0x00, 0x00, /* EC_OC_REG_RCN_CST_HIP__A */ | ||
| 563 | 0xFF, 0x01, /* EC_OC_REG_RCN_SET_LVL__A */ | ||
| 564 | 0x0D, 0x00, /* EC_OC_REG_RCN_GAI_LVL__A */ | ||
| 565 | |||
| 566 | WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2), | ||
| 567 | 0x00, 0x00, /* EC_OC_REG_RCN_CLP_LOP__A */ | ||
| 568 | 0xC0, 0x00, /* EC_OC_REG_RCN_CLP_HIP__A */ | ||
| 569 | |||
| 570 | WR16(EC_SB_REG_CSI_OFS__A, 0x0001), | ||
| 571 | WR16(EC_VD_REG_FORCE__A, 0x0002), | ||
| 572 | WR16(EC_VD_REG_REQ_SMB_CNT__A, 0x0001), | ||
| 573 | WR16(EC_VD_REG_RLK_ENA__A, 0x0001), | ||
| 574 | WR16(EC_OD_REG_SYNC__A, 0x0664), | ||
| 575 | WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000), | ||
| 576 | WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C), | ||
| 577 | /* Output zero on monitorbus pads, power saving */ | ||
| 578 | WR16(EC_OC_REG_OCR_MON_UOS__A, | ||
| 579 | (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE | | ||
| 580 | EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE | | ||
| 581 | EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE | | ||
| 582 | EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE | | ||
| 583 | EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE | | ||
| 584 | EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE | | ||
| 585 | EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE | | ||
| 586 | EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE | | ||
| 587 | EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE | | ||
| 588 | EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE | | ||
| 589 | EC_OC_REG_OCR_MON_UOS_VAL_ENABLE | | ||
| 590 | EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)), | ||
| 591 | WR16(EC_OC_REG_OCR_MON_WRI__A, | ||
| 592 | EC_OC_REG_OCR_MON_WRI_INIT), | ||
| 593 | |||
| 594 | /* CHK_ERROR(ResetECRAM(demod)); */ | ||
| 595 | /* Reset packet sync bytes in EC_VD ram */ | ||
| 596 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | ||
| 597 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | ||
| 598 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | ||
| 599 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | ||
| 600 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | ||
| 601 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | ||
| 602 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | ||
| 603 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | ||
| 604 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | ||
| 605 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | ||
| 606 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | ||
| 607 | |||
| 608 | /* Reset packet sync bytes in EC_RS ram */ | ||
| 609 | WR16(EC_RS_EC_RAM__A, 0x0000), | ||
| 610 | WR16(EC_RS_EC_RAM__A + 204, 0x0000), | ||
| 611 | |||
| 612 | WR16(EC_SB_REG_COMM_EXEC__A, 0x0001), | ||
| 613 | WR16(EC_VD_REG_COMM_EXEC__A, 0x0001), | ||
| 614 | WR16(EC_OD_REG_COMM_EXEC__A, 0x0001), | ||
| 615 | WR16(EC_RS_REG_COMM_EXEC__A, 0x0001), | ||
| 616 | END_OF_TABLE | ||
| 617 | }; | ||
| 618 | |||
| 619 | u8 DRXD_InitECB1[] = { | ||
| 620 | WR16(B_EC_SB_REG_CSI_OFS0__A, 0x0001), | ||
| 621 | WR16(B_EC_SB_REG_CSI_OFS1__A, 0x0001), | ||
| 622 | WR16(B_EC_SB_REG_CSI_OFS2__A, 0x0001), | ||
| 623 | WR16(B_EC_SB_REG_CSI_LO__A, 0x000c), | ||
| 624 | WR16(B_EC_SB_REG_CSI_HI__A, 0x0018), | ||
| 625 | WR16(B_EC_SB_REG_SNR_HI__A, 0x007f), | ||
| 626 | WR16(B_EC_SB_REG_SNR_MID__A, 0x007f), | ||
| 627 | WR16(B_EC_SB_REG_SNR_LO__A, 0x007f), | ||
| 628 | |||
| 629 | WR16(B_EC_OC_REG_DTO_CLKMODE__A, 0x0002), | ||
| 630 | WR16(B_EC_OC_REG_DTO_PER__A, 0x0006), | ||
| 631 | WR16(B_EC_OC_REG_DTO_BUR__A, 0x0001), | ||
| 632 | WR16(B_EC_OC_REG_RCR_CLKMODE__A, 0x0000), | ||
| 633 | WR16(B_EC_OC_REG_RCN_GAI_LVL__A, 0x000D), | ||
| 634 | WR16(B_EC_OC_REG_OC_MPG_SIO__A, 0x0000), | ||
| 635 | |||
| 636 | /* Needed because shadow registers do not have correct default value */ | ||
| 637 | WR16(B_EC_OC_REG_RCN_CST_LOP__A, 0x1000), | ||
| 638 | WR16(B_EC_OC_REG_RCN_CST_HIP__A, 0x0000), | ||
| 639 | WR16(B_EC_OC_REG_RCN_CRA_LOP__A, 0x0000), | ||
| 640 | WR16(B_EC_OC_REG_RCN_CRA_HIP__A, 0x00C0), | ||
| 641 | WR16(B_EC_OC_REG_RCN_CLP_LOP__A, 0x0000), | ||
| 642 | WR16(B_EC_OC_REG_RCN_CLP_HIP__A, 0x00C0), | ||
| 643 | WR16(B_EC_OC_REG_DTO_INC_LOP__A, 0x0000), | ||
| 644 | WR16(B_EC_OC_REG_DTO_INC_HIP__A, 0x00C0), | ||
| 645 | |||
| 646 | WR16(B_EC_OD_REG_SYNC__A, 0x0664), | ||
| 647 | WR16(B_EC_RS_REG_REQ_PCK_CNT__A, 0x1000), | ||
| 648 | |||
| 649 | /* CHK_ERROR(ResetECRAM(demod)); */ | ||
| 650 | /* Reset packet sync bytes in EC_VD ram */ | ||
| 651 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | ||
| 652 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | ||
| 653 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | ||
| 654 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | ||
| 655 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | ||
| 656 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | ||
| 657 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | ||
| 658 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | ||
| 659 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | ||
| 660 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | ||
| 661 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | ||
| 662 | |||
| 663 | /* Reset packet sync bytes in EC_RS ram */ | ||
| 664 | WR16(EC_RS_EC_RAM__A, 0x0000), | ||
| 665 | WR16(EC_RS_EC_RAM__A + 204, 0x0000), | ||
| 666 | |||
| 667 | WR16(B_EC_SB_REG_COMM_EXEC__A, 0x0001), | ||
| 668 | WR16(B_EC_VD_REG_COMM_EXEC__A, 0x0001), | ||
| 669 | WR16(B_EC_OD_REG_COMM_EXEC__A, 0x0001), | ||
| 670 | WR16(B_EC_RS_REG_COMM_EXEC__A, 0x0001), | ||
| 671 | END_OF_TABLE | ||
| 672 | }; | ||
| 673 | |||
| 674 | u8 DRXD_ResetECA2[] = { | ||
| 675 | |||
| 676 | WR16(EC_OC_REG_COMM_EXEC__A, 0x0000), | ||
| 677 | WR16(EC_OD_REG_COMM_EXEC__A, 0x0000), | ||
| 678 | |||
| 679 | WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5), | ||
| 680 | 0x03, 0x00, /* EC_OC_REG_TMD_TOP_MODE__A */ | ||
| 681 | 0xF4, 0x01, /* EC_OC_REG_TMD_TOP_CNT__A */ | ||
| 682 | 0xC0, 0x03, /* EC_OC_REG_TMD_HIL_MAR__A */ | ||
| 683 | 0x40, 0x00, /* EC_OC_REG_TMD_LOL_MAR__A */ | ||
| 684 | 0x03, 0x00, /* EC_OC_REG_TMD_CUR_CNT__A */ | ||
| 685 | |||
| 686 | WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2), | ||
| 687 | 0x06, 0x00, /* EC_OC_REG_AVR_ASH_CNT__A */ | ||
| 688 | 0x02, 0x00, /* EC_OC_REG_AVR_BSH_CNT__A */ | ||
| 689 | |||
| 690 | WRBLOCK(EC_OC_REG_RCN_MODE__A, 7), | ||
| 691 | 0x07, 0x00, /* EC_OC_REG_RCN_MODE__A */ | ||
| 692 | 0x00, 0x00, /* EC_OC_REG_RCN_CRA_LOP__A */ | ||
| 693 | 0xc0, 0x00, /* EC_OC_REG_RCN_CRA_HIP__A */ | ||
| 694 | 0x00, 0x10, /* EC_OC_REG_RCN_CST_LOP__A */ | ||
| 695 | 0x00, 0x00, /* EC_OC_REG_RCN_CST_HIP__A */ | ||
| 696 | 0xFF, 0x01, /* EC_OC_REG_RCN_SET_LVL__A */ | ||
| 697 | 0x0D, 0x00, /* EC_OC_REG_RCN_GAI_LVL__A */ | ||
| 698 | |||
| 699 | WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2), | ||
| 700 | 0x00, 0x00, /* EC_OC_REG_RCN_CLP_LOP__A */ | ||
| 701 | 0xC0, 0x00, /* EC_OC_REG_RCN_CLP_HIP__A */ | ||
| 702 | |||
| 703 | WR16(EC_OD_REG_SYNC__A, 0x0664), | ||
| 704 | WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000), | ||
| 705 | WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C), | ||
| 706 | /* Output zero on monitorbus pads, power saving */ | ||
| 707 | WR16(EC_OC_REG_OCR_MON_UOS__A, | ||
| 708 | (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE | | ||
| 709 | EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE | | ||
| 710 | EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE | | ||
| 711 | EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE | | ||
| 712 | EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE | | ||
| 713 | EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE | | ||
| 714 | EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE | | ||
| 715 | EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE | | ||
| 716 | EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE | | ||
| 717 | EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE | | ||
| 718 | EC_OC_REG_OCR_MON_UOS_VAL_ENABLE | | ||
| 719 | EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)), | ||
| 720 | WR16(EC_OC_REG_OCR_MON_WRI__A, | ||
| 721 | EC_OC_REG_OCR_MON_WRI_INIT), | ||
| 722 | |||
| 723 | /* CHK_ERROR(ResetECRAM(demod)); */ | ||
| 724 | /* Reset packet sync bytes in EC_VD ram */ | ||
| 725 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | ||
| 726 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | ||
| 727 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | ||
| 728 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | ||
| 729 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | ||
| 730 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | ||
| 731 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | ||
| 732 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | ||
| 733 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | ||
| 734 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | ||
| 735 | WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | ||
| 736 | |||
| 737 | /* Reset packet sync bytes in EC_RS ram */ | ||
| 738 | WR16(EC_RS_EC_RAM__A, 0x0000), | ||
| 739 | WR16(EC_RS_EC_RAM__A + 204, 0x0000), | ||
| 740 | |||
| 741 | WR16(EC_OD_REG_COMM_EXEC__A, 0x0001), | ||
| 742 | END_OF_TABLE | ||
| 743 | }; | ||
| 744 | |||
| 745 | u8 DRXD_InitSC[] = { | ||
| 746 | WR16(SC_COMM_EXEC__A, 0), | ||
| 747 | WR16(SC_COMM_STATE__A, 0), | ||
| 748 | |||
| 749 | #ifdef COMPILE_FOR_QT | ||
| 750 | WR16(SC_RA_RAM_BE_OPT_DELAY__A, 0x100), | ||
| 751 | #endif | ||
| 752 | |||
| 753 | /* SC is not started, this is done in SetChannels() */ | ||
| 754 | END_OF_TABLE | ||
| 755 | }; | ||
| 756 | |||
| 757 | /* Diversity settings */ | ||
| 758 | |||
| 759 | u8 DRXD_InitDiversityFront[] = { | ||
| 760 | /* Start demod ********* RF in , diversity out **************************** */ | ||
| 761 | WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M | | ||
| 762 | B_SC_RA_RAM_CONFIG_FREQSCAN__M), | ||
| 763 | |||
| 764 | WR16(B_SC_RA_RAM_LC_ABS_2K__A, 0x7), | ||
| 765 | WR16(B_SC_RA_RAM_LC_ABS_8K__A, 0x7), | ||
| 766 | WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K), | ||
| 767 | WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)), | ||
| 768 | WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)), | ||
| 769 | WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K), | ||
| 770 | WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)), | ||
| 771 | WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)), | ||
| 772 | |||
| 773 | WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K), | ||
| 774 | WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)), | ||
| 775 | WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)), | ||
| 776 | WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K), | ||
| 777 | WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)), | ||
| 778 | WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)), | ||
| 779 | |||
| 780 | WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7), | ||
| 781 | WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4), | ||
| 782 | WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7), | ||
| 783 | WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4), | ||
| 784 | WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500), | ||
| 785 | |||
| 786 | WR16(B_CC_REG_DIVERSITY__A, 0x0001), | ||
| 787 | WR16(B_EC_OC_REG_OC_MODE_HIP__A, 0x0010), | ||
| 788 | WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE | | ||
| 789 | B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE), | ||
| 790 | |||
| 791 | /* 0x2a ), *//* CE to PASS mux */ | ||
| 792 | |||
| 793 | END_OF_TABLE | ||
| 794 | }; | ||
| 795 | |||
| 796 | u8 DRXD_InitDiversityEnd[] = { | ||
| 797 | /* End demod *********** combining RF in and diversity in, MPEG TS out **** */ | ||
| 798 | /* disable near/far; switch on timing slave mode */ | ||
| 799 | WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M | | ||
| 800 | B_SC_RA_RAM_CONFIG_FREQSCAN__M | | ||
| 801 | B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M | | ||
| 802 | B_SC_RA_RAM_CONFIG_SLAVE__M | | ||
| 803 | B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M | ||
| 804 | /* MV from CtrlDiversity */ | ||
| 805 | ), | ||
| 806 | #ifdef DRXDDIV_SRMM_SLAVING | ||
| 807 | WR16(SC_RA_RAM_LC_ABS_2K__A, 0x3c7), | ||
| 808 | WR16(SC_RA_RAM_LC_ABS_8K__A, 0x3c7), | ||
| 809 | #else | ||
| 810 | WR16(SC_RA_RAM_LC_ABS_2K__A, 0x7), | ||
| 811 | WR16(SC_RA_RAM_LC_ABS_8K__A, 0x7), | ||
| 812 | #endif | ||
| 813 | |||
| 814 | WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K), | ||
| 815 | WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)), | ||
| 816 | WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)), | ||
| 817 | WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K), | ||
| 818 | WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)), | ||
| 819 | WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)), | ||
| 820 | |||
| 821 | WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K), | ||
| 822 | WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)), | ||
| 823 | WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)), | ||
| 824 | WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K), | ||
| 825 | WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)), | ||
| 826 | WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)), | ||
| 827 | |||
| 828 | WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7), | ||
| 829 | WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4), | ||
| 830 | WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7), | ||
| 831 | WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4), | ||
| 832 | WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500), | ||
| 833 | |||
| 834 | WR16(B_CC_REG_DIVERSITY__A, 0x0001), | ||
| 835 | END_OF_TABLE | ||
| 836 | }; | ||
| 837 | |||
| 838 | u8 DRXD_DisableDiversity[] = { | ||
| 839 | WR16(B_SC_RA_RAM_LC_ABS_2K__A, B_SC_RA_RAM_LC_ABS_2K__PRE), | ||
| 840 | WR16(B_SC_RA_RAM_LC_ABS_8K__A, B_SC_RA_RAM_LC_ABS_8K__PRE), | ||
| 841 | WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, | ||
| 842 | B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE), | ||
| 843 | WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, | ||
| 844 | B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE), | ||
| 845 | WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, | ||
| 846 | B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE), | ||
| 847 | WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, | ||
| 848 | B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE), | ||
| 849 | WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, | ||
| 850 | B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE), | ||
| 851 | WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, | ||
| 852 | B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE), | ||
| 853 | |||
| 854 | WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, | ||
| 855 | B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE), | ||
| 856 | WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, | ||
| 857 | B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE), | ||
| 858 | WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, | ||
| 859 | B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE), | ||
| 860 | WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, | ||
| 861 | B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE), | ||
| 862 | WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, | ||
| 863 | B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE), | ||
| 864 | WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, | ||
| 865 | B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE), | ||
| 866 | |||
| 867 | WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, B_LC_RA_RAM_FILTER_CRMM_A__PRE), | ||
| 868 | WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, B_LC_RA_RAM_FILTER_CRMM_B__PRE), | ||
| 869 | WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, B_LC_RA_RAM_FILTER_SRMM_A__PRE), | ||
| 870 | WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, B_LC_RA_RAM_FILTER_SRMM_B__PRE), | ||
| 871 | WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, B_LC_RA_RAM_FILTER_SYM_SET__PRE), | ||
| 872 | |||
| 873 | WR16(B_CC_REG_DIVERSITY__A, 0x0000), | ||
| 874 | WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_INIT), /* combining disabled */ | ||
| 875 | |||
| 876 | END_OF_TABLE | ||
| 877 | }; | ||
| 878 | |||
| 879 | u8 DRXD_StartDiversityFront[] = { | ||
| 880 | /* Start demod, RF in and diversity out, no combining */ | ||
| 881 | WR16(B_FE_CF_REG_IMP_VAL__A, 0x0), | ||
| 882 | WR16(B_FE_AD_REG_FDB_IN__A, 0x0), | ||
| 883 | WR16(B_FE_AD_REG_INVEXT__A, 0x0), | ||
| 884 | WR16(B_EQ_REG_COMM_MB__A, 0x12), /* EQ to MB out */ | ||
| 885 | WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE | /* CE to PASS mux */ | ||
| 886 | B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE), | ||
| 887 | |||
| 888 | WR16(SC_RA_RAM_ECHO_SHIFT_LIM__A, 2), | ||
| 889 | |||
| 890 | END_OF_TABLE | ||
| 891 | }; | ||
| 892 | |||
| 893 | u8 DRXD_StartDiversityEnd[] = { | ||
| 894 | /* End demod, combining RF in and diversity in, MPEG TS out */ | ||
| 895 | WR16(B_FE_CF_REG_IMP_VAL__A, 0x0), /* disable impulse noise cruncher */ | ||
| 896 | WR16(B_FE_AD_REG_INVEXT__A, 0x0), /* clock inversion (for sohard board) */ | ||
| 897 | WR16(B_CP_REG_BR_STR_DEL__A, 10), /* apperently no mb delay matching is best */ | ||
| 898 | |||
| 899 | WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_DIV_ON | /* org = 0x81 combining enabled */ | ||
| 900 | B_EQ_REG_RC_SEL_CAR_MEAS_A_CC | | ||
| 901 | B_EQ_REG_RC_SEL_CAR_PASS_A_CC | B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC), | ||
| 902 | |||
| 903 | END_OF_TABLE | ||
| 904 | }; | ||
| 905 | |||
| 906 | u8 DRXD_DiversityDelay8MHZ[] = { | ||
| 907 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1150 - 50), | ||
| 908 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1100 - 50), | ||
| 909 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 1000 - 50), | ||
| 910 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 800 - 50), | ||
| 911 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5420 - 50), | ||
| 912 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5200 - 50), | ||
| 913 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4800 - 50), | ||
| 914 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 4000 - 50), | ||
| 915 | END_OF_TABLE | ||
| 916 | }; | ||
| 917 | |||
| 918 | u8 DRXD_DiversityDelay6MHZ[] = /* also used ok for 7 MHz */ | ||
| 919 | { | ||
| 920 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1100 - 50), | ||
| 921 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1000 - 50), | ||
| 922 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 900 - 50), | ||
| 923 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 600 - 50), | ||
| 924 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5300 - 50), | ||
| 925 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5000 - 50), | ||
| 926 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4500 - 50), | ||
| 927 | WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 3500 - 50), | ||
| 928 | END_OF_TABLE | ||
| 929 | }; | ||
diff --git a/drivers/media/dvb/frontends/drxd_firm.h b/drivers/media/dvb/frontends/drxd_firm.h new file mode 100644 index 000000000000..41597e89941c --- /dev/null +++ b/drivers/media/dvb/frontends/drxd_firm.h | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | /* | ||
| 2 | * drxd_firm.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006-2007 Micronas | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 only, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 20 | * 02110-1301, USA | ||
| 21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef _DRXD_FIRM_H_ | ||
| 25 | #define _DRXD_FIRM_H_ | ||
| 26 | |||
| 27 | #include <linux/types.h> | ||
| 28 | #include "drxd_map_firm.h" | ||
| 29 | |||
| 30 | #define VERSION_MAJOR 1 | ||
| 31 | #define VERSION_MINOR 4 | ||
| 32 | #define VERSION_PATCH 23 | ||
| 33 | |||
| 34 | #define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A | ||
| 35 | |||
| 36 | #define DRXD_MAX_RETRIES (1000) | ||
| 37 | #define HI_I2C_DELAY 84 | ||
| 38 | #define HI_I2C_BRIDGE_DELAY 750 | ||
| 39 | |||
| 40 | #define EQ_TD_TPS_PWR_UNKNOWN 0x00C0 /* Unknown configurations */ | ||
| 41 | #define EQ_TD_TPS_PWR_QPSK 0x016a | ||
| 42 | #define EQ_TD_TPS_PWR_QAM16_ALPHAN 0x0195 | ||
| 43 | #define EQ_TD_TPS_PWR_QAM16_ALPHA1 0x0195 | ||
| 44 | #define EQ_TD_TPS_PWR_QAM16_ALPHA2 0x011E | ||
| 45 | #define EQ_TD_TPS_PWR_QAM16_ALPHA4 0x01CE | ||
| 46 | #define EQ_TD_TPS_PWR_QAM64_ALPHAN 0x019F | ||
| 47 | #define EQ_TD_TPS_PWR_QAM64_ALPHA1 0x019F | ||
| 48 | #define EQ_TD_TPS_PWR_QAM64_ALPHA2 0x00F8 | ||
| 49 | #define EQ_TD_TPS_PWR_QAM64_ALPHA4 0x014D | ||
| 50 | |||
| 51 | #define DRXD_DEF_AG_PWD_CONSUMER 0x000E | ||
| 52 | #define DRXD_DEF_AG_PWD_PRO 0x0000 | ||
| 53 | #define DRXD_DEF_AG_AGC_SIO 0x0000 | ||
| 54 | |||
| 55 | #define DRXD_FE_CTRL_MAX 1023 | ||
| 56 | |||
| 57 | #define DRXD_OSCDEV_DO_SCAN (16) | ||
| 58 | |||
| 59 | #define DRXD_OSCDEV_DONT_SCAN (0) | ||
| 60 | |||
| 61 | #define DRXD_OSCDEV_STEP (275) | ||
| 62 | |||
| 63 | #define DRXD_SCAN_TIMEOUT (650) | ||
| 64 | |||
| 65 | #define DRXD_BANDWIDTH_8MHZ_IN_HZ (0x8B8249L) | ||
| 66 | #define DRXD_BANDWIDTH_7MHZ_IN_HZ (0x7A1200L) | ||
| 67 | #define DRXD_BANDWIDTH_6MHZ_IN_HZ (0x68A1B6L) | ||
| 68 | |||
| 69 | #define IRLEN_COARSE_8K (10) | ||
| 70 | #define IRLEN_FINE_8K (10) | ||
| 71 | #define IRLEN_COARSE_2K (7) | ||
| 72 | #define IRLEN_FINE_2K (9) | ||
| 73 | #define DIFF_INVALID (511) | ||
| 74 | #define DIFF_TARGET (4) | ||
| 75 | #define DIFF_MARGIN (1) | ||
| 76 | |||
| 77 | extern u8 DRXD_InitAtomicRead[]; | ||
| 78 | extern u8 DRXD_HiI2cPatch_1[]; | ||
| 79 | extern u8 DRXD_HiI2cPatch_3[]; | ||
| 80 | |||
| 81 | extern u8 DRXD_InitSC[]; | ||
| 82 | |||
| 83 | extern u8 DRXD_ResetCEFR[]; | ||
| 84 | extern u8 DRXD_InitFEA2_1[]; | ||
| 85 | extern u8 DRXD_InitFEA2_2[]; | ||
| 86 | extern u8 DRXD_InitCPA2[]; | ||
| 87 | extern u8 DRXD_InitCEA2[]; | ||
| 88 | extern u8 DRXD_InitEQA2[]; | ||
| 89 | extern u8 DRXD_InitECA2[]; | ||
| 90 | extern u8 DRXD_ResetECA2[]; | ||
| 91 | extern u8 DRXD_ResetECRAM[]; | ||
| 92 | |||
| 93 | extern u8 DRXD_A2_microcode[]; | ||
| 94 | extern u32 DRXD_A2_microcode_length; | ||
| 95 | |||
| 96 | extern u8 DRXD_InitFEB1_1[]; | ||
| 97 | extern u8 DRXD_InitFEB1_2[]; | ||
| 98 | extern u8 DRXD_InitCPB1[]; | ||
| 99 | extern u8 DRXD_InitCEB1[]; | ||
| 100 | extern u8 DRXD_InitEQB1[]; | ||
| 101 | extern u8 DRXD_InitECB1[]; | ||
| 102 | |||
| 103 | extern u8 DRXD_InitDiversityFront[]; | ||
| 104 | extern u8 DRXD_InitDiversityEnd[]; | ||
| 105 | extern u8 DRXD_DisableDiversity[]; | ||
| 106 | extern u8 DRXD_StartDiversityFront[]; | ||
| 107 | extern u8 DRXD_StartDiversityEnd[]; | ||
| 108 | |||
| 109 | extern u8 DRXD_DiversityDelay8MHZ[]; | ||
| 110 | extern u8 DRXD_DiversityDelay6MHZ[]; | ||
| 111 | |||
| 112 | extern u8 DRXD_B1_microcode[]; | ||
| 113 | extern u32 DRXD_B1_microcode_length; | ||
| 114 | |||
| 115 | #endif | ||
diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c new file mode 100644 index 000000000000..ea4c1c361d2b --- /dev/null +++ b/drivers/media/dvb/frontends/drxd_hard.c | |||
| @@ -0,0 +1,3001 @@ | |||
| 1 | /* | ||
| 2 | * drxd_hard.c: DVB-T Demodulator Micronas DRX3975D-A2,DRX397xD-B1 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2003-2007 Micronas | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 only, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 20 | * 02110-1301, USA | ||
| 21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/moduleparam.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/firmware.h> | ||
| 30 | #include <linux/i2c.h> | ||
| 31 | #include <linux/version.h> | ||
| 32 | #include <asm/div64.h> | ||
| 33 | |||
| 34 | #include "dvb_frontend.h" | ||
| 35 | #include "drxd.h" | ||
| 36 | #include "drxd_firm.h" | ||
| 37 | |||
| 38 | #define DRX_FW_FILENAME_A2 "drxd-a2-1.1.fw" | ||
| 39 | #define DRX_FW_FILENAME_B1 "drxd-b1-1.1.fw" | ||
| 40 | |||
| 41 | #define CHUNK_SIZE 48 | ||
| 42 | |||
| 43 | #define DRX_I2C_RMW 0x10 | ||
| 44 | #define DRX_I2C_BROADCAST 0x20 | ||
| 45 | #define DRX_I2C_CLEARCRC 0x80 | ||
| 46 | #define DRX_I2C_SINGLE_MASTER 0xC0 | ||
| 47 | #define DRX_I2C_MODEFLAGS 0xC0 | ||
| 48 | #define DRX_I2C_FLAGS 0xF0 | ||
| 49 | |||
| 50 | #ifndef SIZEOF_ARRAY | ||
| 51 | #define SIZEOF_ARRAY(array) (sizeof((array))/sizeof((array)[0])) | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #define DEFAULT_LOCK_TIMEOUT 1100 | ||
| 55 | |||
| 56 | #define DRX_CHANNEL_AUTO 0 | ||
| 57 | #define DRX_CHANNEL_HIGH 1 | ||
| 58 | #define DRX_CHANNEL_LOW 2 | ||
| 59 | |||
| 60 | #define DRX_LOCK_MPEG 1 | ||
| 61 | #define DRX_LOCK_FEC 2 | ||
| 62 | #define DRX_LOCK_DEMOD 4 | ||
| 63 | |||
| 64 | /****************************************************************************/ | ||
| 65 | |||
| 66 | enum CSCDState { | ||
| 67 | CSCD_INIT = 0, | ||
| 68 | CSCD_SET, | ||
| 69 | CSCD_SAVED | ||
| 70 | }; | ||
| 71 | |||
| 72 | enum CDrxdState { | ||
| 73 | DRXD_UNINITIALIZED = 0, | ||
| 74 | DRXD_STOPPED, | ||
| 75 | DRXD_STARTED | ||
| 76 | }; | ||
| 77 | |||
| 78 | enum AGC_CTRL_MODE { | ||
| 79 | AGC_CTRL_AUTO = 0, | ||
| 80 | AGC_CTRL_USER, | ||
| 81 | AGC_CTRL_OFF | ||
| 82 | }; | ||
| 83 | |||
| 84 | enum OperationMode { | ||
| 85 | OM_Default, | ||
| 86 | OM_DVBT_Diversity_Front, | ||
| 87 | OM_DVBT_Diversity_End | ||
| 88 | }; | ||
| 89 | |||
| 90 | struct SCfgAgc { | ||
| 91 | enum AGC_CTRL_MODE ctrlMode; | ||
| 92 | u16 outputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | ||
| 93 | u16 settleLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | ||
| 94 | u16 minOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | ||
| 95 | u16 maxOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | ||
| 96 | u16 speed; /* range [0, ... , 1023], 1/n of fullscale range */ | ||
| 97 | |||
| 98 | u16 R1; | ||
| 99 | u16 R2; | ||
| 100 | u16 R3; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct SNoiseCal { | ||
| 104 | int cpOpt; | ||
| 105 | u16 cpNexpOfs; | ||
| 106 | u16 tdCal2k; | ||
| 107 | u16 tdCal8k; | ||
| 108 | }; | ||
| 109 | |||
| 110 | enum app_env { | ||
| 111 | APPENV_STATIC = 0, | ||
| 112 | APPENV_PORTABLE = 1, | ||
| 113 | APPENV_MOBILE = 2 | ||
| 114 | }; | ||
| 115 | |||
| 116 | enum EIFFilter { | ||
| 117 | IFFILTER_SAW = 0, | ||
| 118 | IFFILTER_DISCRETE = 1 | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct drxd_state { | ||
| 122 | struct dvb_frontend frontend; | ||
| 123 | struct dvb_frontend_ops ops; | ||
| 124 | struct dvb_frontend_parameters param; | ||
| 125 | |||
| 126 | const struct firmware *fw; | ||
| 127 | struct device *dev; | ||
| 128 | |||
| 129 | struct i2c_adapter *i2c; | ||
| 130 | void *priv; | ||
| 131 | struct drxd_config config; | ||
| 132 | |||
| 133 | int i2c_access; | ||
| 134 | int init_done; | ||
| 135 | struct mutex mutex; | ||
| 136 | |||
| 137 | u8 chip_adr; | ||
| 138 | u16 hi_cfg_timing_div; | ||
| 139 | u16 hi_cfg_bridge_delay; | ||
| 140 | u16 hi_cfg_wakeup_key; | ||
| 141 | u16 hi_cfg_ctrl; | ||
| 142 | |||
| 143 | u16 intermediate_freq; | ||
| 144 | u16 osc_clock_freq; | ||
| 145 | |||
| 146 | enum CSCDState cscd_state; | ||
| 147 | enum CDrxdState drxd_state; | ||
| 148 | |||
| 149 | u16 sys_clock_freq; | ||
| 150 | s16 osc_clock_deviation; | ||
| 151 | u16 expected_sys_clock_freq; | ||
| 152 | |||
| 153 | u16 insert_rs_byte; | ||
| 154 | u16 enable_parallel; | ||
| 155 | |||
| 156 | int operation_mode; | ||
| 157 | |||
| 158 | struct SCfgAgc if_agc_cfg; | ||
| 159 | struct SCfgAgc rf_agc_cfg; | ||
| 160 | |||
| 161 | struct SNoiseCal noise_cal; | ||
| 162 | |||
| 163 | u32 fe_fs_add_incr; | ||
| 164 | u32 org_fe_fs_add_incr; | ||
| 165 | u16 current_fe_if_incr; | ||
| 166 | |||
| 167 | u16 m_FeAgRegAgPwd; | ||
| 168 | u16 m_FeAgRegAgAgcSio; | ||
| 169 | |||
| 170 | u16 m_EcOcRegOcModeLop; | ||
| 171 | u16 m_EcOcRegSncSncLvl; | ||
| 172 | u8 *m_InitAtomicRead; | ||
| 173 | u8 *m_HiI2cPatch; | ||
| 174 | |||
| 175 | u8 *m_ResetCEFR; | ||
| 176 | u8 *m_InitFE_1; | ||
| 177 | u8 *m_InitFE_2; | ||
| 178 | u8 *m_InitCP; | ||
| 179 | u8 *m_InitCE; | ||
| 180 | u8 *m_InitEQ; | ||
| 181 | u8 *m_InitSC; | ||
| 182 | u8 *m_InitEC; | ||
| 183 | u8 *m_ResetECRAM; | ||
| 184 | u8 *m_InitDiversityFront; | ||
| 185 | u8 *m_InitDiversityEnd; | ||
| 186 | u8 *m_DisableDiversity; | ||
| 187 | u8 *m_StartDiversityFront; | ||
| 188 | u8 *m_StartDiversityEnd; | ||
| 189 | |||
| 190 | u8 *m_DiversityDelay8MHZ; | ||
| 191 | u8 *m_DiversityDelay6MHZ; | ||
| 192 | |||
| 193 | u8 *microcode; | ||
| 194 | u32 microcode_length; | ||
| 195 | |||
| 196 | int type_A; | ||
| 197 | int PGA; | ||
| 198 | int diversity; | ||
| 199 | int tuner_mirrors; | ||
| 200 | |||
| 201 | enum app_env app_env_default; | ||
| 202 | enum app_env app_env_diversity; | ||
| 203 | |||
| 204 | }; | ||
| 205 | |||
| 206 | /****************************************************************************/ | ||
| 207 | /* I2C **********************************************************************/ | ||
| 208 | /****************************************************************************/ | ||
| 209 | |||
| 210 | static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 * data, int len) | ||
| 211 | { | ||
| 212 | struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len }; | ||
| 213 | |||
| 214 | if (i2c_transfer(adap, &msg, 1) != 1) | ||
| 215 | return -1; | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int i2c_read(struct i2c_adapter *adap, | ||
| 220 | u8 adr, u8 *msg, int len, u8 *answ, int alen) | ||
| 221 | { | ||
| 222 | struct i2c_msg msgs[2] = { | ||
| 223 | { | ||
| 224 | .addr = adr, .flags = 0, | ||
| 225 | .buf = msg, .len = len | ||
| 226 | }, { | ||
| 227 | .addr = adr, .flags = I2C_M_RD, | ||
| 228 | .buf = answ, .len = alen | ||
| 229 | } | ||
| 230 | }; | ||
| 231 | if (i2c_transfer(adap, msgs, 2) != 2) | ||
| 232 | return -1; | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | inline u32 MulDiv32(u32 a, u32 b, u32 c) | ||
| 237 | { | ||
| 238 | u64 tmp64; | ||
| 239 | |||
| 240 | tmp64 = (u64)a * (u64)b; | ||
| 241 | do_div(tmp64, c); | ||
| 242 | |||
| 243 | return (u32) tmp64; | ||
| 244 | } | ||
| 245 | |||
| 246 | static int Read16(struct drxd_state *state, u32 reg, u16 *data, u8 flags) | ||
| 247 | { | ||
| 248 | u8 adr = state->config.demod_address; | ||
| 249 | u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, | ||
| 250 | flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff | ||
| 251 | }; | ||
| 252 | u8 mm2[2]; | ||
| 253 | if (i2c_read(state->i2c, adr, mm1, 4, mm2, 2) < 0) | ||
| 254 | return -1; | ||
| 255 | if (data) | ||
| 256 | *data = mm2[0] | (mm2[1] << 8); | ||
| 257 | return mm2[0] | (mm2[1] << 8); | ||
| 258 | } | ||
| 259 | |||
| 260 | static int Read32(struct drxd_state *state, u32 reg, u32 *data, u8 flags) | ||
| 261 | { | ||
| 262 | u8 adr = state->config.demod_address; | ||
| 263 | u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, | ||
| 264 | flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff | ||
| 265 | }; | ||
| 266 | u8 mm2[4]; | ||
| 267 | |||
| 268 | if (i2c_read(state->i2c, adr, mm1, 4, mm2, 4) < 0) | ||
| 269 | return -1; | ||
| 270 | if (data) | ||
| 271 | *data = | ||
| 272 | mm2[0] | (mm2[1] << 8) | (mm2[2] << 16) | (mm2[3] << 24); | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | static int Write16(struct drxd_state *state, u32 reg, u16 data, u8 flags) | ||
| 277 | { | ||
| 278 | u8 adr = state->config.demod_address; | ||
| 279 | u8 mm[6] = { reg & 0xff, (reg >> 16) & 0xff, | ||
| 280 | flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, | ||
| 281 | data & 0xff, (data >> 8) & 0xff | ||
| 282 | }; | ||
| 283 | |||
| 284 | if (i2c_write(state->i2c, adr, mm, 6) < 0) | ||
| 285 | return -1; | ||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | static int Write32(struct drxd_state *state, u32 reg, u32 data, u8 flags) | ||
| 290 | { | ||
| 291 | u8 adr = state->config.demod_address; | ||
| 292 | u8 mm[8] = { reg & 0xff, (reg >> 16) & 0xff, | ||
| 293 | flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, | ||
| 294 | data & 0xff, (data >> 8) & 0xff, | ||
| 295 | (data >> 16) & 0xff, (data >> 24) & 0xff | ||
| 296 | }; | ||
| 297 | |||
| 298 | if (i2c_write(state->i2c, adr, mm, 8) < 0) | ||
| 299 | return -1; | ||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int write_chunk(struct drxd_state *state, | ||
| 304 | u32 reg, u8 *data, u32 len, u8 flags) | ||
| 305 | { | ||
| 306 | u8 adr = state->config.demod_address; | ||
| 307 | u8 mm[CHUNK_SIZE + 4] = { reg & 0xff, (reg >> 16) & 0xff, | ||
| 308 | flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff | ||
| 309 | }; | ||
| 310 | int i; | ||
| 311 | |||
| 312 | for (i = 0; i < len; i++) | ||
| 313 | mm[4 + i] = data[i]; | ||
| 314 | if (i2c_write(state->i2c, adr, mm, 4 + len) < 0) { | ||
| 315 | printk(KERN_ERR "error in write_chunk\n"); | ||
| 316 | return -1; | ||
| 317 | } | ||
| 318 | return 0; | ||
| 319 | } | ||
| 320 | |||
| 321 | static int WriteBlock(struct drxd_state *state, | ||
| 322 | u32 Address, u16 BlockSize, u8 *pBlock, u8 Flags) | ||
| 323 | { | ||
| 324 | while (BlockSize > 0) { | ||
| 325 | u16 Chunk = BlockSize > CHUNK_SIZE ? CHUNK_SIZE : BlockSize; | ||
| 326 | |||
| 327 | if (write_chunk(state, Address, pBlock, Chunk, Flags) < 0) | ||
| 328 | return -1; | ||
| 329 | pBlock += Chunk; | ||
| 330 | Address += (Chunk >> 1); | ||
| 331 | BlockSize -= Chunk; | ||
| 332 | } | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | static int WriteTable(struct drxd_state *state, u8 * pTable) | ||
| 337 | { | ||
| 338 | int status = 0; | ||
| 339 | |||
| 340 | if (pTable == NULL) | ||
| 341 | return 0; | ||
| 342 | |||
| 343 | while (!status) { | ||
| 344 | u16 Length; | ||
| 345 | u32 Address = pTable[0] | (pTable[1] << 8) | | ||
| 346 | (pTable[2] << 16) | (pTable[3] << 24); | ||
| 347 | |||
| 348 | if (Address == 0xFFFFFFFF) | ||
| 349 | break; | ||
| 350 | pTable += sizeof(u32); | ||
| 351 | |||
| 352 | Length = pTable[0] | (pTable[1] << 8); | ||
| 353 | pTable += sizeof(u16); | ||
| 354 | if (!Length) | ||
| 355 | break; | ||
| 356 | status = WriteBlock(state, Address, Length * 2, pTable, 0); | ||
| 357 | pTable += (Length * 2); | ||
| 358 | } | ||
| 359 | return status; | ||
| 360 | } | ||
| 361 | |||
| 362 | /****************************************************************************/ | ||
| 363 | /****************************************************************************/ | ||
| 364 | /****************************************************************************/ | ||
| 365 | |||
| 366 | static int ResetCEFR(struct drxd_state *state) | ||
| 367 | { | ||
| 368 | return WriteTable(state, state->m_ResetCEFR); | ||
| 369 | } | ||
| 370 | |||
| 371 | static int InitCP(struct drxd_state *state) | ||
| 372 | { | ||
| 373 | return WriteTable(state, state->m_InitCP); | ||
| 374 | } | ||
| 375 | |||
| 376 | static int InitCE(struct drxd_state *state) | ||
| 377 | { | ||
| 378 | int status; | ||
| 379 | enum app_env AppEnv = state->app_env_default; | ||
| 380 | |||
| 381 | do { | ||
| 382 | status = WriteTable(state, state->m_InitCE); | ||
| 383 | if (status < 0) | ||
| 384 | break; | ||
| 385 | |||
| 386 | if (state->operation_mode == OM_DVBT_Diversity_Front || | ||
| 387 | state->operation_mode == OM_DVBT_Diversity_End) { | ||
| 388 | AppEnv = state->app_env_diversity; | ||
| 389 | } | ||
| 390 | if (AppEnv == APPENV_STATIC) { | ||
| 391 | status = Write16(state, CE_REG_TAPSET__A, 0x0000, 0); | ||
| 392 | if (status < 0) | ||
| 393 | break; | ||
| 394 | } else if (AppEnv == APPENV_PORTABLE) { | ||
| 395 | status = Write16(state, CE_REG_TAPSET__A, 0x0001, 0); | ||
| 396 | if (status < 0) | ||
| 397 | break; | ||
| 398 | } else if (AppEnv == APPENV_MOBILE && state->type_A) { | ||
| 399 | status = Write16(state, CE_REG_TAPSET__A, 0x0002, 0); | ||
| 400 | if (status < 0) | ||
| 401 | break; | ||
| 402 | } else if (AppEnv == APPENV_MOBILE && !state->type_A) { | ||
| 403 | status = Write16(state, CE_REG_TAPSET__A, 0x0006, 0); | ||
| 404 | if (status < 0) | ||
| 405 | break; | ||
| 406 | } | ||
| 407 | |||
| 408 | /* start ce */ | ||
| 409 | status = Write16(state, B_CE_REG_COMM_EXEC__A, 0x0001, 0); | ||
| 410 | if (status < 0) | ||
| 411 | break; | ||
| 412 | } while (0); | ||
| 413 | return status; | ||
| 414 | } | ||
| 415 | |||
| 416 | static int StopOC(struct drxd_state *state) | ||
| 417 | { | ||
| 418 | int status = 0; | ||
| 419 | u16 ocSyncLvl = 0; | ||
| 420 | u16 ocModeLop = state->m_EcOcRegOcModeLop; | ||
| 421 | u16 dtoIncLop = 0; | ||
| 422 | u16 dtoIncHip = 0; | ||
| 423 | |||
| 424 | do { | ||
| 425 | /* Store output configuration */ | ||
| 426 | status = Read16(state, EC_OC_REG_SNC_ISC_LVL__A, &ocSyncLvl, 0); | ||
| 427 | if (status < 0) | ||
| 428 | break; | ||
| 429 | /* CHK_ERROR(Read16(EC_OC_REG_OC_MODE_LOP__A, &ocModeLop)); */ | ||
| 430 | state->m_EcOcRegSncSncLvl = ocSyncLvl; | ||
| 431 | /* m_EcOcRegOcModeLop = ocModeLop; */ | ||
| 432 | |||
| 433 | /* Flush FIFO (byte-boundary) at fixed rate */ | ||
| 434 | status = Read16(state, EC_OC_REG_RCN_MAP_LOP__A, &dtoIncLop, 0); | ||
| 435 | if (status < 0) | ||
| 436 | break; | ||
| 437 | status = Read16(state, EC_OC_REG_RCN_MAP_HIP__A, &dtoIncHip, 0); | ||
| 438 | if (status < 0) | ||
| 439 | break; | ||
| 440 | status = Write16(state, EC_OC_REG_DTO_INC_LOP__A, dtoIncLop, 0); | ||
| 441 | if (status < 0) | ||
| 442 | break; | ||
| 443 | status = Write16(state, EC_OC_REG_DTO_INC_HIP__A, dtoIncHip, 0); | ||
| 444 | if (status < 0) | ||
| 445 | break; | ||
| 446 | ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M); | ||
| 447 | ocModeLop |= EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC; | ||
| 448 | status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); | ||
| 449 | if (status < 0) | ||
| 450 | break; | ||
| 451 | status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); | ||
| 452 | if (status < 0) | ||
| 453 | break; | ||
| 454 | |||
| 455 | msleep(1); | ||
| 456 | /* Output pins to '0' */ | ||
| 457 | status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS__M, 0); | ||
| 458 | if (status < 0) | ||
| 459 | break; | ||
| 460 | |||
| 461 | /* Force the OC out of sync */ | ||
| 462 | ocSyncLvl &= ~(EC_OC_REG_SNC_ISC_LVL_OSC__M); | ||
| 463 | status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, ocSyncLvl, 0); | ||
| 464 | if (status < 0) | ||
| 465 | break; | ||
| 466 | ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M); | ||
| 467 | ocModeLop |= EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE; | ||
| 468 | ocModeLop |= 0x2; /* Magically-out-of-sync */ | ||
| 469 | status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); | ||
| 470 | if (status < 0) | ||
| 471 | break; | ||
| 472 | status = Write16(state, EC_OC_REG_COMM_INT_STA__A, 0x0, 0); | ||
| 473 | if (status < 0) | ||
| 474 | break; | ||
| 475 | status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); | ||
| 476 | if (status < 0) | ||
| 477 | break; | ||
| 478 | } while (0); | ||
| 479 | |||
| 480 | return status; | ||
| 481 | } | ||
| 482 | |||
| 483 | static int StartOC(struct drxd_state *state) | ||
| 484 | { | ||
| 485 | int status = 0; | ||
| 486 | |||
| 487 | do { | ||
| 488 | /* Stop OC */ | ||
| 489 | status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); | ||
| 490 | if (status < 0) | ||
| 491 | break; | ||
| 492 | |||
| 493 | /* Restore output configuration */ | ||
| 494 | status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, state->m_EcOcRegSncSncLvl, 0); | ||
| 495 | if (status < 0) | ||
| 496 | break; | ||
| 497 | status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, state->m_EcOcRegOcModeLop, 0); | ||
| 498 | if (status < 0) | ||
| 499 | break; | ||
| 500 | |||
| 501 | /* Output pins active again */ | ||
| 502 | status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS_INIT, 0); | ||
| 503 | if (status < 0) | ||
| 504 | break; | ||
| 505 | |||
| 506 | /* Start OC */ | ||
| 507 | status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); | ||
| 508 | if (status < 0) | ||
| 509 | break; | ||
| 510 | } while (0); | ||
| 511 | return status; | ||
| 512 | } | ||
| 513 | |||
| 514 | static int InitEQ(struct drxd_state *state) | ||
| 515 | { | ||
| 516 | return WriteTable(state, state->m_InitEQ); | ||
| 517 | } | ||
| 518 | |||
| 519 | static int InitEC(struct drxd_state *state) | ||
| 520 | { | ||
| 521 | return WriteTable(state, state->m_InitEC); | ||
| 522 | } | ||
| 523 | |||
| 524 | static int InitSC(struct drxd_state *state) | ||
| 525 | { | ||
| 526 | return WriteTable(state, state->m_InitSC); | ||
| 527 | } | ||
| 528 | |||
| 529 | static int InitAtomicRead(struct drxd_state *state) | ||
| 530 | { | ||
| 531 | return WriteTable(state, state->m_InitAtomicRead); | ||
| 532 | } | ||
| 533 | |||
| 534 | static int CorrectSysClockDeviation(struct drxd_state *state); | ||
| 535 | |||
| 536 | static int DRX_GetLockStatus(struct drxd_state *state, u32 * pLockStatus) | ||
| 537 | { | ||
| 538 | u16 ScRaRamLock = 0; | ||
| 539 | const u16 mpeg_lock_mask = (SC_RA_RAM_LOCK_MPEG__M | | ||
| 540 | SC_RA_RAM_LOCK_FEC__M | | ||
| 541 | SC_RA_RAM_LOCK_DEMOD__M); | ||
| 542 | const u16 fec_lock_mask = (SC_RA_RAM_LOCK_FEC__M | | ||
| 543 | SC_RA_RAM_LOCK_DEMOD__M); | ||
| 544 | const u16 demod_lock_mask = SC_RA_RAM_LOCK_DEMOD__M; | ||
| 545 | |||
| 546 | int status; | ||
| 547 | |||
| 548 | *pLockStatus = 0; | ||
| 549 | |||
| 550 | status = Read16(state, SC_RA_RAM_LOCK__A, &ScRaRamLock, 0x0000); | ||
| 551 | if (status < 0) { | ||
| 552 | printk(KERN_ERR "Can't read SC_RA_RAM_LOCK__A status = %08x\n", status); | ||
| 553 | return status; | ||
| 554 | } | ||
| 555 | |||
| 556 | if (state->drxd_state != DRXD_STARTED) | ||
| 557 | return 0; | ||
| 558 | |||
| 559 | if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) { | ||
| 560 | *pLockStatus |= DRX_LOCK_MPEG; | ||
| 561 | CorrectSysClockDeviation(state); | ||
| 562 | } | ||
| 563 | |||
| 564 | if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) | ||
| 565 | *pLockStatus |= DRX_LOCK_FEC; | ||
| 566 | |||
| 567 | if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) | ||
| 568 | *pLockStatus |= DRX_LOCK_DEMOD; | ||
| 569 | return 0; | ||
| 570 | } | ||
| 571 | |||
| 572 | /****************************************************************************/ | ||
| 573 | |||
| 574 | static int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg) | ||
| 575 | { | ||
| 576 | int status; | ||
| 577 | |||
| 578 | if (cfg->outputLevel > DRXD_FE_CTRL_MAX) | ||
| 579 | return -1; | ||
| 580 | |||
| 581 | if (cfg->ctrlMode == AGC_CTRL_USER) { | ||
| 582 | do { | ||
| 583 | u16 FeAgRegPm1AgcWri; | ||
| 584 | u16 FeAgRegAgModeLop; | ||
| 585 | |||
| 586 | status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); | ||
| 587 | if (status < 0) | ||
| 588 | break; | ||
| 589 | FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); | ||
| 590 | FeAgRegAgModeLop |= FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC; | ||
| 591 | status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); | ||
| 592 | if (status < 0) | ||
| 593 | break; | ||
| 594 | |||
| 595 | FeAgRegPm1AgcWri = (u16) (cfg->outputLevel & | ||
| 596 | FE_AG_REG_PM1_AGC_WRI__M); | ||
| 597 | status = Write16(state, FE_AG_REG_PM1_AGC_WRI__A, FeAgRegPm1AgcWri, 0); | ||
| 598 | if (status < 0) | ||
| 599 | break; | ||
| 600 | } while (0); | ||
| 601 | } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { | ||
| 602 | if (((cfg->maxOutputLevel) < (cfg->minOutputLevel)) || | ||
| 603 | ((cfg->maxOutputLevel) > DRXD_FE_CTRL_MAX) || | ||
| 604 | ((cfg->speed) > DRXD_FE_CTRL_MAX) || | ||
| 605 | ((cfg->settleLevel) > DRXD_FE_CTRL_MAX) | ||
| 606 | ) | ||
| 607 | return -1; | ||
| 608 | do { | ||
| 609 | u16 FeAgRegAgModeLop; | ||
| 610 | u16 FeAgRegEgcSetLvl; | ||
| 611 | u16 slope, offset; | ||
| 612 | |||
| 613 | /* == Mode == */ | ||
| 614 | |||
| 615 | status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); | ||
| 616 | if (status < 0) | ||
| 617 | break; | ||
| 618 | FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); | ||
| 619 | FeAgRegAgModeLop |= | ||
| 620 | FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC; | ||
| 621 | status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); | ||
| 622 | if (status < 0) | ||
| 623 | break; | ||
| 624 | |||
| 625 | /* == Settle level == */ | ||
| 626 | |||
| 627 | FeAgRegEgcSetLvl = (u16) ((cfg->settleLevel >> 1) & | ||
| 628 | FE_AG_REG_EGC_SET_LVL__M); | ||
| 629 | status = Write16(state, FE_AG_REG_EGC_SET_LVL__A, FeAgRegEgcSetLvl, 0); | ||
| 630 | if (status < 0) | ||
| 631 | break; | ||
| 632 | |||
| 633 | /* == Min/Max == */ | ||
| 634 | |||
| 635 | slope = (u16) ((cfg->maxOutputLevel - | ||
| 636 | cfg->minOutputLevel) / 2); | ||
| 637 | offset = (u16) ((cfg->maxOutputLevel + | ||
| 638 | cfg->minOutputLevel) / 2 - 511); | ||
| 639 | |||
| 640 | status = Write16(state, FE_AG_REG_GC1_AGC_RIC__A, slope, 0); | ||
| 641 | if (status < 0) | ||
| 642 | break; | ||
| 643 | status = Write16(state, FE_AG_REG_GC1_AGC_OFF__A, offset, 0); | ||
| 644 | if (status < 0) | ||
| 645 | break; | ||
| 646 | |||
| 647 | /* == Speed == */ | ||
| 648 | { | ||
| 649 | const u16 maxRur = 8; | ||
| 650 | const u16 slowIncrDecLUT[] = { 3, 4, 4, 5, 6 }; | ||
| 651 | const u16 fastIncrDecLUT[] = { 14, 15, 15, 16, | ||
| 652 | 17, 18, 18, 19, | ||
| 653 | 20, 21, 22, 23, | ||
| 654 | 24, 26, 27, 28, | ||
| 655 | 29, 31 | ||
| 656 | }; | ||
| 657 | |||
| 658 | u16 fineSteps = (DRXD_FE_CTRL_MAX + 1) / | ||
| 659 | (maxRur + 1); | ||
| 660 | u16 fineSpeed = (u16) (cfg->speed - | ||
| 661 | ((cfg->speed / | ||
| 662 | fineSteps) * | ||
| 663 | fineSteps)); | ||
| 664 | u16 invRurCount = (u16) (cfg->speed / | ||
| 665 | fineSteps); | ||
| 666 | u16 rurCount; | ||
| 667 | if (invRurCount > maxRur) { | ||
| 668 | rurCount = 0; | ||
| 669 | fineSpeed += fineSteps; | ||
| 670 | } else { | ||
| 671 | rurCount = maxRur - invRurCount; | ||
| 672 | } | ||
| 673 | |||
| 674 | /* | ||
| 675 | fastInc = default * | ||
| 676 | (2^(fineSpeed/fineSteps)) | ||
| 677 | => range[default...2*default> | ||
| 678 | slowInc = default * | ||
| 679 | (2^(fineSpeed/fineSteps)) | ||
| 680 | */ | ||
| 681 | { | ||
| 682 | u16 fastIncrDec = | ||
| 683 | fastIncrDecLUT[fineSpeed / | ||
| 684 | ((fineSteps / | ||
| 685 | (14 + 1)) + 1)]; | ||
| 686 | u16 slowIncrDec = | ||
| 687 | slowIncrDecLUT[fineSpeed / | ||
| 688 | (fineSteps / | ||
| 689 | (3 + 1))]; | ||
| 690 | |||
| 691 | status = Write16(state, FE_AG_REG_EGC_RUR_CNT__A, rurCount, 0); | ||
| 692 | if (status < 0) | ||
| 693 | break; | ||
| 694 | status = Write16(state, FE_AG_REG_EGC_FAS_INC__A, fastIncrDec, 0); | ||
| 695 | if (status < 0) | ||
| 696 | break; | ||
| 697 | status = Write16(state, FE_AG_REG_EGC_FAS_DEC__A, fastIncrDec, 0); | ||
| 698 | if (status < 0) | ||
| 699 | break; | ||
| 700 | status = Write16(state, FE_AG_REG_EGC_SLO_INC__A, slowIncrDec, 0); | ||
| 701 | if (status < 0) | ||
| 702 | break; | ||
| 703 | status = Write16(state, FE_AG_REG_EGC_SLO_DEC__A, slowIncrDec, 0); | ||
| 704 | if (status < 0) | ||
| 705 | break; | ||
| 706 | } | ||
| 707 | } | ||
| 708 | } while (0); | ||
| 709 | |||
| 710 | } else { | ||
| 711 | /* No OFF mode for IF control */ | ||
| 712 | return -1; | ||
| 713 | } | ||
| 714 | return status; | ||
| 715 | } | ||
| 716 | |||
| 717 | static int SetCfgRfAgc(struct drxd_state *state, struct SCfgAgc *cfg) | ||
| 718 | { | ||
| 719 | int status = 0; | ||
| 720 | |||
| 721 | if (cfg->outputLevel > DRXD_FE_CTRL_MAX) | ||
| 722 | return -1; | ||
| 723 | |||
| 724 | if (cfg->ctrlMode == AGC_CTRL_USER) { | ||
| 725 | do { | ||
| 726 | u16 AgModeLop = 0; | ||
| 727 | u16 level = (cfg->outputLevel); | ||
| 728 | |||
| 729 | if (level == DRXD_FE_CTRL_MAX) | ||
| 730 | level++; | ||
| 731 | |||
| 732 | status = Write16(state, FE_AG_REG_PM2_AGC_WRI__A, level, 0x0000); | ||
| 733 | if (status < 0) | ||
| 734 | break; | ||
| 735 | |||
| 736 | /*==== Mode ====*/ | ||
| 737 | |||
| 738 | /* Powerdown PD2, WRI source */ | ||
| 739 | state->m_FeAgRegAgPwd &= ~(FE_AG_REG_AG_PWD_PWD_PD2__M); | ||
| 740 | state->m_FeAgRegAgPwd |= | ||
| 741 | FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; | ||
| 742 | status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); | ||
| 743 | if (status < 0) | ||
| 744 | break; | ||
| 745 | |||
| 746 | status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | ||
| 747 | if (status < 0) | ||
| 748 | break; | ||
| 749 | AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | | ||
| 750 | FE_AG_REG_AG_MODE_LOP_MODE_E__M)); | ||
| 751 | AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | | ||
| 752 | FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); | ||
| 753 | status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | ||
| 754 | if (status < 0) | ||
| 755 | break; | ||
| 756 | |||
| 757 | /* enable AGC2 pin */ | ||
| 758 | { | ||
| 759 | u16 FeAgRegAgAgcSio = 0; | ||
| 760 | status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); | ||
| 761 | if (status < 0) | ||
| 762 | break; | ||
| 763 | FeAgRegAgAgcSio &= | ||
| 764 | ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); | ||
| 765 | FeAgRegAgAgcSio |= | ||
| 766 | FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; | ||
| 767 | status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); | ||
| 768 | if (status < 0) | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | |||
| 772 | } while (0); | ||
| 773 | } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { | ||
| 774 | u16 AgModeLop = 0; | ||
| 775 | |||
| 776 | do { | ||
| 777 | u16 level; | ||
| 778 | /* Automatic control */ | ||
| 779 | /* Powerup PD2, AGC2 as output, TGC source */ | ||
| 780 | (state->m_FeAgRegAgPwd) &= | ||
| 781 | ~(FE_AG_REG_AG_PWD_PWD_PD2__M); | ||
| 782 | (state->m_FeAgRegAgPwd) |= | ||
| 783 | FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; | ||
| 784 | status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); | ||
| 785 | if (status < 0) | ||
| 786 | break; | ||
| 787 | |||
| 788 | status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | ||
| 789 | if (status < 0) | ||
| 790 | break; | ||
| 791 | AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | | ||
| 792 | FE_AG_REG_AG_MODE_LOP_MODE_E__M)); | ||
| 793 | AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | | ||
| 794 | FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC); | ||
| 795 | status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | ||
| 796 | if (status < 0) | ||
| 797 | break; | ||
| 798 | /* Settle level */ | ||
| 799 | level = (((cfg->settleLevel) >> 4) & | ||
| 800 | FE_AG_REG_TGC_SET_LVL__M); | ||
| 801 | status = Write16(state, FE_AG_REG_TGC_SET_LVL__A, level, 0x0000); | ||
| 802 | if (status < 0) | ||
| 803 | break; | ||
| 804 | |||
| 805 | /* Min/max: don't care */ | ||
| 806 | |||
| 807 | /* Speed: TODO */ | ||
| 808 | |||
| 809 | /* enable AGC2 pin */ | ||
| 810 | { | ||
| 811 | u16 FeAgRegAgAgcSio = 0; | ||
| 812 | status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); | ||
| 813 | if (status < 0) | ||
| 814 | break; | ||
| 815 | FeAgRegAgAgcSio &= | ||
| 816 | ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); | ||
| 817 | FeAgRegAgAgcSio |= | ||
| 818 | FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; | ||
| 819 | status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); | ||
| 820 | if (status < 0) | ||
| 821 | break; | ||
| 822 | } | ||
| 823 | |||
| 824 | } while (0); | ||
| 825 | } else { | ||
| 826 | u16 AgModeLop = 0; | ||
| 827 | |||
| 828 | do { | ||
| 829 | /* No RF AGC control */ | ||
| 830 | /* Powerdown PD2, AGC2 as output, WRI source */ | ||
| 831 | (state->m_FeAgRegAgPwd) &= | ||
| 832 | ~(FE_AG_REG_AG_PWD_PWD_PD2__M); | ||
| 833 | (state->m_FeAgRegAgPwd) |= | ||
| 834 | FE_AG_REG_AG_PWD_PWD_PD2_ENABLE; | ||
| 835 | status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); | ||
| 836 | if (status < 0) | ||
| 837 | break; | ||
| 838 | |||
| 839 | status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | ||
| 840 | if (status < 0) | ||
| 841 | break; | ||
| 842 | AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | | ||
| 843 | FE_AG_REG_AG_MODE_LOP_MODE_E__M)); | ||
| 844 | AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | | ||
| 845 | FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); | ||
| 846 | status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | ||
| 847 | if (status < 0) | ||
| 848 | break; | ||
| 849 | |||
| 850 | /* set FeAgRegAgAgcSio AGC2 (RF) as input */ | ||
| 851 | { | ||
| 852 | u16 FeAgRegAgAgcSio = 0; | ||
| 853 | status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); | ||
| 854 | if (status < 0) | ||
| 855 | break; | ||
| 856 | FeAgRegAgAgcSio &= | ||
| 857 | ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); | ||
| 858 | FeAgRegAgAgcSio |= | ||
| 859 | FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT; | ||
| 860 | status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); | ||
| 861 | if (status < 0) | ||
| 862 | break; | ||
| 863 | } | ||
| 864 | } while (0); | ||
| 865 | } | ||
| 866 | return status; | ||
| 867 | } | ||
| 868 | |||
| 869 | static int ReadIFAgc(struct drxd_state *state, u32 * pValue) | ||
| 870 | { | ||
| 871 | int status = 0; | ||
| 872 | |||
| 873 | *pValue = 0; | ||
| 874 | if (state->if_agc_cfg.ctrlMode != AGC_CTRL_OFF) { | ||
| 875 | u16 Value; | ||
| 876 | status = Read16(state, FE_AG_REG_GC1_AGC_DAT__A, &Value, 0); | ||
| 877 | Value &= FE_AG_REG_GC1_AGC_DAT__M; | ||
| 878 | if (status >= 0) { | ||
| 879 | /* 3.3V | ||
| 880 | | | ||
| 881 | R1 | ||
| 882 | | | ||
| 883 | Vin - R3 - * -- Vout | ||
| 884 | | | ||
| 885 | R2 | ||
| 886 | | | ||
| 887 | GND | ||
| 888 | */ | ||
| 889 | u32 R1 = state->if_agc_cfg.R1; | ||
| 890 | u32 R2 = state->if_agc_cfg.R2; | ||
| 891 | u32 R3 = state->if_agc_cfg.R3; | ||
| 892 | |||
| 893 | u32 Vmax = (3300 * R2) / (R1 + R2); | ||
| 894 | u32 Rpar = (R2 * R3) / (R3 + R2); | ||
| 895 | u32 Vmin = (3300 * Rpar) / (R1 + Rpar); | ||
| 896 | u32 Vout = Vmin + ((Vmax - Vmin) * Value) / 1024; | ||
| 897 | |||
| 898 | *pValue = Vout; | ||
| 899 | } | ||
| 900 | } | ||
| 901 | return status; | ||
| 902 | } | ||
| 903 | |||
| 904 | static int load_firmware(struct drxd_state *state, const char *fw_name) | ||
| 905 | { | ||
| 906 | const struct firmware *fw; | ||
| 907 | |||
| 908 | if (request_firmware(&fw, fw_name, state->dev) < 0) { | ||
| 909 | printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name); | ||
| 910 | return -EIO; | ||
| 911 | } | ||
| 912 | |||
| 913 | state->microcode = kzalloc(fw->size, GFP_KERNEL); | ||
| 914 | if (state->microcode == NULL) { | ||
| 915 | printk(KERN_ERR "drxd: firmware load failure: nomemory\n"); | ||
| 916 | return -ENOMEM; | ||
| 917 | } | ||
| 918 | |||
| 919 | memcpy(state->microcode, fw->data, fw->size); | ||
| 920 | state->microcode_length = fw->size; | ||
| 921 | return 0; | ||
| 922 | } | ||
| 923 | |||
| 924 | static int DownloadMicrocode(struct drxd_state *state, | ||
| 925 | const u8 *pMCImage, u32 Length) | ||
| 926 | { | ||
| 927 | u8 *pSrc; | ||
| 928 | u16 Flags; | ||
| 929 | u32 Address; | ||
| 930 | u16 nBlocks; | ||
| 931 | u16 BlockSize; | ||
| 932 | u16 BlockCRC; | ||
| 933 | u32 offset = 0; | ||
| 934 | int i, status = 0; | ||
| 935 | |||
| 936 | pSrc = (u8 *) pMCImage; | ||
| 937 | Flags = (pSrc[0] << 8) | pSrc[1]; | ||
| 938 | pSrc += sizeof(u16); | ||
| 939 | offset += sizeof(u16); | ||
| 940 | nBlocks = (pSrc[0] << 8) | pSrc[1]; | ||
| 941 | pSrc += sizeof(u16); | ||
| 942 | offset += sizeof(u16); | ||
| 943 | |||
| 944 | for (i = 0; i < nBlocks; i++) { | ||
| 945 | Address = (pSrc[0] << 24) | (pSrc[1] << 16) | | ||
| 946 | (pSrc[2] << 8) | pSrc[3]; | ||
| 947 | pSrc += sizeof(u32); | ||
| 948 | offset += sizeof(u32); | ||
| 949 | |||
| 950 | BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); | ||
| 951 | pSrc += sizeof(u16); | ||
| 952 | offset += sizeof(u16); | ||
| 953 | |||
| 954 | Flags = (pSrc[0] << 8) | pSrc[1]; | ||
| 955 | pSrc += sizeof(u16); | ||
| 956 | offset += sizeof(u16); | ||
| 957 | |||
| 958 | BlockCRC = (pSrc[0] << 8) | pSrc[1]; | ||
| 959 | pSrc += sizeof(u16); | ||
| 960 | offset += sizeof(u16); | ||
| 961 | |||
| 962 | status = WriteBlock(state, Address, BlockSize, | ||
| 963 | pSrc, DRX_I2C_CLEARCRC); | ||
| 964 | if (status < 0) | ||
| 965 | break; | ||
| 966 | pSrc += BlockSize; | ||
| 967 | offset += BlockSize; | ||
| 968 | } | ||
| 969 | |||
| 970 | return status; | ||
| 971 | } | ||
| 972 | |||
| 973 | static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult) | ||
| 974 | { | ||
| 975 | u32 nrRetries = 0; | ||
| 976 | u16 waitCmd; | ||
| 977 | int status; | ||
| 978 | |||
| 979 | status = Write16(state, HI_RA_RAM_SRV_CMD__A, cmd, 0); | ||
| 980 | if (status < 0) | ||
| 981 | return status; | ||
| 982 | |||
| 983 | do { | ||
| 984 | nrRetries += 1; | ||
| 985 | if (nrRetries > DRXD_MAX_RETRIES) { | ||
| 986 | status = -1; | ||
| 987 | break; | ||
| 988 | }; | ||
| 989 | status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0); | ||
| 990 | } while (waitCmd != 0); | ||
| 991 | |||
| 992 | if (status >= 0) | ||
| 993 | status = Read16(state, HI_RA_RAM_SRV_RES__A, pResult, 0); | ||
| 994 | return status; | ||
| 995 | } | ||
| 996 | |||
| 997 | static int HI_CfgCommand(struct drxd_state *state) | ||
| 998 | { | ||
| 999 | int status = 0; | ||
| 1000 | |||
| 1001 | mutex_lock(&state->mutex); | ||
| 1002 | Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); | ||
| 1003 | Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, state->hi_cfg_timing_div, 0); | ||
| 1004 | Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, state->hi_cfg_bridge_delay, 0); | ||
| 1005 | Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, state->hi_cfg_wakeup_key, 0); | ||
| 1006 | Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, state->hi_cfg_ctrl, 0); | ||
| 1007 | |||
| 1008 | Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); | ||
| 1009 | |||
| 1010 | if ((state->hi_cfg_ctrl & HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) == | ||
| 1011 | HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) | ||
| 1012 | status = Write16(state, HI_RA_RAM_SRV_CMD__A, | ||
| 1013 | HI_RA_RAM_SRV_CMD_CONFIG, 0); | ||
| 1014 | else | ||
| 1015 | status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, 0); | ||
| 1016 | mutex_unlock(&state->mutex); | ||
| 1017 | return status; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | static int InitHI(struct drxd_state *state) | ||
| 1021 | { | ||
| 1022 | state->hi_cfg_wakeup_key = (state->chip_adr); | ||
| 1023 | /* port/bridge/power down ctrl */ | ||
| 1024 | state->hi_cfg_ctrl = HI_RA_RAM_SRV_CFG_ACT_SLV0_ON; | ||
| 1025 | return HI_CfgCommand(state); | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | static int HI_ResetCommand(struct drxd_state *state) | ||
| 1029 | { | ||
| 1030 | int status; | ||
| 1031 | |||
| 1032 | mutex_lock(&state->mutex); | ||
| 1033 | status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A, | ||
| 1034 | HI_RA_RAM_SRV_RST_KEY_ACT, 0); | ||
| 1035 | if (status == 0) | ||
| 1036 | status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, 0); | ||
| 1037 | mutex_unlock(&state->mutex); | ||
| 1038 | msleep(1); | ||
| 1039 | return status; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | static int DRX_ConfigureI2CBridge(struct drxd_state *state, int bEnableBridge) | ||
| 1043 | { | ||
| 1044 | state->hi_cfg_ctrl &= (~HI_RA_RAM_SRV_CFG_ACT_BRD__M); | ||
| 1045 | if (bEnableBridge) | ||
| 1046 | state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_ON; | ||
| 1047 | else | ||
| 1048 | state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_OFF; | ||
| 1049 | |||
| 1050 | return HI_CfgCommand(state); | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | #define HI_TR_WRITE 0x9 | ||
| 1054 | #define HI_TR_READ 0xA | ||
| 1055 | #define HI_TR_READ_WRITE 0xB | ||
| 1056 | #define HI_TR_BROADCAST 0x4 | ||
| 1057 | |||
| 1058 | #if 0 | ||
| 1059 | static int AtomicReadBlock(struct drxd_state *state, | ||
| 1060 | u32 Addr, u16 DataSize, u8 *pData, u8 Flags) | ||
| 1061 | { | ||
| 1062 | int status; | ||
| 1063 | int i = 0; | ||
| 1064 | |||
| 1065 | /* Parameter check */ | ||
| 1066 | if ((!pData) || ((DataSize & 1) != 0)) | ||
| 1067 | return -1; | ||
| 1068 | |||
| 1069 | mutex_lock(&state->mutex); | ||
| 1070 | |||
| 1071 | do { | ||
| 1072 | /* Instruct HI to read n bytes */ | ||
| 1073 | /* TODO use proper names forthese egisters */ | ||
| 1074 | status = Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, (HI_TR_FUNC_ADDR & 0xFFFF), 0); | ||
| 1075 | if (status < 0) | ||
| 1076 | break; | ||
| 1077 | status = Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, (u16) (Addr >> 16), 0); | ||
| 1078 | if (status < 0) | ||
| 1079 | break; | ||
| 1080 | status = Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, (u16) (Addr & 0xFFFF), 0); | ||
| 1081 | if (status < 0) | ||
| 1082 | break; | ||
| 1083 | status = Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, (u16) ((DataSize / 2) - 1), 0); | ||
| 1084 | if (status < 0) | ||
| 1085 | break; | ||
| 1086 | status = Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, HI_TR_READ, 0); | ||
| 1087 | if (status < 0) | ||
| 1088 | break; | ||
| 1089 | |||
| 1090 | status = HI_Command(state, HI_RA_RAM_SRV_CMD_EXECUTE, 0); | ||
| 1091 | if (status < 0) | ||
| 1092 | break; | ||
| 1093 | |||
| 1094 | } while (0); | ||
| 1095 | |||
| 1096 | if (status >= 0) { | ||
| 1097 | for (i = 0; i < (DataSize / 2); i += 1) { | ||
| 1098 | u16 word; | ||
| 1099 | |||
| 1100 | status = Read16(state, (HI_RA_RAM_USR_BEGIN__A + i), | ||
| 1101 | &word, 0); | ||
| 1102 | if (status < 0) | ||
| 1103 | break; | ||
| 1104 | pData[2 * i] = (u8) (word & 0xFF); | ||
| 1105 | pData[(2 * i) + 1] = (u8) (word >> 8); | ||
| 1106 | } | ||
| 1107 | } | ||
| 1108 | mutex_unlock(&state->mutex); | ||
| 1109 | return status; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | static int AtomicReadReg32(struct drxd_state *state, | ||
| 1113 | u32 Addr, u32 *pData, u8 Flags) | ||
| 1114 | { | ||
| 1115 | u8 buf[sizeof(u32)]; | ||
| 1116 | int status; | ||
| 1117 | |||
| 1118 | if (!pData) | ||
| 1119 | return -1; | ||
| 1120 | status = AtomicReadBlock(state, Addr, sizeof(u32), buf, Flags); | ||
| 1121 | *pData = (((u32) buf[0]) << 0) + | ||
| 1122 | (((u32) buf[1]) << 8) + | ||
| 1123 | (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24); | ||
| 1124 | return status; | ||
| 1125 | } | ||
| 1126 | #endif | ||
| 1127 | |||
| 1128 | static int StopAllProcessors(struct drxd_state *state) | ||
| 1129 | { | ||
| 1130 | return Write16(state, HI_COMM_EXEC__A, | ||
| 1131 | SC_COMM_EXEC_CTL_STOP, DRX_I2C_BROADCAST); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | static int EnableAndResetMB(struct drxd_state *state) | ||
| 1135 | { | ||
| 1136 | if (state->type_A) { | ||
| 1137 | /* disable? monitor bus observe @ EC_OC */ | ||
| 1138 | Write16(state, EC_OC_REG_OC_MON_SIO__A, 0x0000, 0x0000); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | /* do inverse broadcast, followed by explicit write to HI */ | ||
| 1142 | Write16(state, HI_COMM_MB__A, 0x0000, DRX_I2C_BROADCAST); | ||
| 1143 | Write16(state, HI_COMM_MB__A, 0x0000, 0x0000); | ||
| 1144 | return 0; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | static int InitCC(struct drxd_state *state) | ||
| 1148 | { | ||
| 1149 | if (state->osc_clock_freq == 0 || | ||
| 1150 | state->osc_clock_freq > 20000 || | ||
| 1151 | (state->osc_clock_freq % 4000) != 0) { | ||
| 1152 | printk(KERN_ERR "invalid osc frequency %d\n", state->osc_clock_freq); | ||
| 1153 | return -1; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0); | ||
| 1157 | Write16(state, CC_REG_PLL_MODE__A, CC_REG_PLL_MODE_BYPASS_PLL | | ||
| 1158 | CC_REG_PLL_MODE_PUMP_CUR_12, 0); | ||
| 1159 | Write16(state, CC_REG_REF_DIVIDE__A, state->osc_clock_freq / 4000, 0); | ||
| 1160 | Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 0); | ||
| 1161 | Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0); | ||
| 1162 | |||
| 1163 | return 0; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | static int ResetECOD(struct drxd_state *state) | ||
| 1167 | { | ||
| 1168 | int status = 0; | ||
| 1169 | |||
| 1170 | if (state->type_A) | ||
| 1171 | status = Write16(state, EC_OD_REG_SYNC__A, 0x0664, 0); | ||
| 1172 | else | ||
| 1173 | status = Write16(state, B_EC_OD_REG_SYNC__A, 0x0664, 0); | ||
| 1174 | |||
| 1175 | if (!(status < 0)) | ||
| 1176 | status = WriteTable(state, state->m_ResetECRAM); | ||
| 1177 | if (!(status < 0)) | ||
| 1178 | status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0001, 0); | ||
| 1179 | return status; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | /* Configure PGA switch */ | ||
| 1183 | |||
| 1184 | static int SetCfgPga(struct drxd_state *state, int pgaSwitch) | ||
| 1185 | { | ||
| 1186 | int status; | ||
| 1187 | u16 AgModeLop = 0; | ||
| 1188 | u16 AgModeHip = 0; | ||
| 1189 | do { | ||
| 1190 | if (pgaSwitch) { | ||
| 1191 | /* PGA on */ | ||
| 1192 | /* fine gain */ | ||
| 1193 | status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | ||
| 1194 | if (status < 0) | ||
| 1195 | break; | ||
| 1196 | AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); | ||
| 1197 | AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC; | ||
| 1198 | status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | ||
| 1199 | if (status < 0) | ||
| 1200 | break; | ||
| 1201 | |||
| 1202 | /* coarse gain */ | ||
| 1203 | status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); | ||
| 1204 | if (status < 0) | ||
| 1205 | break; | ||
| 1206 | AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); | ||
| 1207 | AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC; | ||
| 1208 | status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); | ||
| 1209 | if (status < 0) | ||
| 1210 | break; | ||
| 1211 | |||
| 1212 | /* enable fine and coarse gain, enable AAF, | ||
| 1213 | no ext resistor */ | ||
| 1214 | status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN, 0x0000); | ||
| 1215 | if (status < 0) | ||
| 1216 | break; | ||
| 1217 | } else { | ||
| 1218 | /* PGA off, bypass */ | ||
| 1219 | |||
| 1220 | /* fine gain */ | ||
| 1221 | status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | ||
| 1222 | if (status < 0) | ||
| 1223 | break; | ||
| 1224 | AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); | ||
| 1225 | AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC; | ||
| 1226 | status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | ||
| 1227 | if (status < 0) | ||
| 1228 | break; | ||
| 1229 | |||
| 1230 | /* coarse gain */ | ||
| 1231 | status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); | ||
| 1232 | if (status < 0) | ||
| 1233 | break; | ||
| 1234 | AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); | ||
| 1235 | AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC; | ||
| 1236 | status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); | ||
| 1237 | if (status < 0) | ||
| 1238 | break; | ||
| 1239 | |||
| 1240 | /* disable fine and coarse gain, enable AAF, | ||
| 1241 | no ext resistor */ | ||
| 1242 | status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000); | ||
| 1243 | if (status < 0) | ||
| 1244 | break; | ||
| 1245 | } | ||
| 1246 | } while (0); | ||
| 1247 | return status; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | static int InitFE(struct drxd_state *state) | ||
| 1251 | { | ||
| 1252 | int status; | ||
| 1253 | |||
| 1254 | do { | ||
| 1255 | status = WriteTable(state, state->m_InitFE_1); | ||
| 1256 | if (status < 0) | ||
| 1257 | break; | ||
| 1258 | |||
| 1259 | if (state->type_A) { | ||
| 1260 | status = Write16(state, FE_AG_REG_AG_PGA_MODE__A, | ||
| 1261 | FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, | ||
| 1262 | 0); | ||
| 1263 | } else { | ||
| 1264 | if (state->PGA) | ||
| 1265 | status = SetCfgPga(state, 0); | ||
| 1266 | else | ||
| 1267 | status = | ||
| 1268 | Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, | ||
| 1269 | B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, | ||
| 1270 | 0); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | if (status < 0) | ||
| 1274 | break; | ||
| 1275 | status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, state->m_FeAgRegAgAgcSio, 0x0000); | ||
| 1276 | if (status < 0) | ||
| 1277 | break; | ||
| 1278 | status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); | ||
| 1279 | if (status < 0) | ||
| 1280 | break; | ||
| 1281 | |||
| 1282 | status = WriteTable(state, state->m_InitFE_2); | ||
| 1283 | if (status < 0) | ||
| 1284 | break; | ||
| 1285 | |||
| 1286 | } while (0); | ||
| 1287 | |||
| 1288 | return status; | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | static int InitFT(struct drxd_state *state) | ||
| 1292 | { | ||
| 1293 | /* | ||
| 1294 | norm OFFSET, MB says =2 voor 8K en =3 voor 2K waarschijnlijk | ||
| 1295 | SC stuff | ||
| 1296 | */ | ||
| 1297 | return Write16(state, FT_REG_COMM_EXEC__A, 0x0001, 0x0000); | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | static int SC_WaitForReady(struct drxd_state *state) | ||
| 1301 | { | ||
| 1302 | u16 curCmd; | ||
| 1303 | int i; | ||
| 1304 | |||
| 1305 | for (i = 0; i < DRXD_MAX_RETRIES; i += 1) { | ||
| 1306 | int status = Read16(state, SC_RA_RAM_CMD__A, &curCmd, 0); | ||
| 1307 | if (status == 0 || curCmd == 0) | ||
| 1308 | return status; | ||
| 1309 | } | ||
| 1310 | return -1; | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | static int SC_SendCommand(struct drxd_state *state, u16 cmd) | ||
| 1314 | { | ||
| 1315 | int status = 0; | ||
| 1316 | u16 errCode; | ||
| 1317 | |||
| 1318 | Write16(state, SC_RA_RAM_CMD__A, cmd, 0); | ||
| 1319 | SC_WaitForReady(state); | ||
| 1320 | |||
| 1321 | Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0); | ||
| 1322 | |||
| 1323 | if (errCode == 0xFFFF) { | ||
| 1324 | printk(KERN_ERR "Command Error\n"); | ||
| 1325 | status = -1; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | return status; | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | static int SC_ProcStartCommand(struct drxd_state *state, | ||
| 1332 | u16 subCmd, u16 param0, u16 param1) | ||
| 1333 | { | ||
| 1334 | int status = 0; | ||
| 1335 | u16 scExec; | ||
| 1336 | |||
| 1337 | mutex_lock(&state->mutex); | ||
| 1338 | do { | ||
| 1339 | Read16(state, SC_COMM_EXEC__A, &scExec, 0); | ||
| 1340 | if (scExec != 1) { | ||
| 1341 | status = -1; | ||
| 1342 | break; | ||
| 1343 | } | ||
| 1344 | SC_WaitForReady(state); | ||
| 1345 | Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); | ||
| 1346 | Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); | ||
| 1347 | Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); | ||
| 1348 | |||
| 1349 | SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START); | ||
| 1350 | } while (0); | ||
| 1351 | mutex_unlock(&state->mutex); | ||
| 1352 | return status; | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | static int SC_SetPrefParamCommand(struct drxd_state *state, | ||
| 1356 | u16 subCmd, u16 param0, u16 param1) | ||
| 1357 | { | ||
| 1358 | int status; | ||
| 1359 | |||
| 1360 | mutex_lock(&state->mutex); | ||
| 1361 | do { | ||
| 1362 | status = SC_WaitForReady(state); | ||
| 1363 | if (status < 0) | ||
| 1364 | break; | ||
| 1365 | status = Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); | ||
| 1366 | if (status < 0) | ||
| 1367 | break; | ||
| 1368 | status = Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); | ||
| 1369 | if (status < 0) | ||
| 1370 | break; | ||
| 1371 | status = Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); | ||
| 1372 | if (status < 0) | ||
| 1373 | break; | ||
| 1374 | |||
| 1375 | status = SC_SendCommand(state, SC_RA_RAM_CMD_SET_PREF_PARAM); | ||
| 1376 | if (status < 0) | ||
| 1377 | break; | ||
| 1378 | } while (0); | ||
| 1379 | mutex_unlock(&state->mutex); | ||
| 1380 | return status; | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | #if 0 | ||
| 1384 | static int SC_GetOpParamCommand(struct drxd_state *state, u16 * result) | ||
| 1385 | { | ||
| 1386 | int status = 0; | ||
| 1387 | |||
| 1388 | mutex_lock(&state->mutex); | ||
| 1389 | do { | ||
| 1390 | status = SC_WaitForReady(state); | ||
| 1391 | if (status < 0) | ||
| 1392 | break; | ||
| 1393 | status = SC_SendCommand(state, SC_RA_RAM_CMD_GET_OP_PARAM); | ||
| 1394 | if (status < 0) | ||
| 1395 | break; | ||
| 1396 | status = Read16(state, SC_RA_RAM_PARAM0__A, result, 0); | ||
| 1397 | if (status < 0) | ||
| 1398 | break; | ||
| 1399 | } while (0); | ||
| 1400 | mutex_unlock(&state->mutex); | ||
| 1401 | return status; | ||
| 1402 | } | ||
| 1403 | #endif | ||
| 1404 | |||
| 1405 | static int ConfigureMPEGOutput(struct drxd_state *state, int bEnableOutput) | ||
| 1406 | { | ||
| 1407 | int status; | ||
| 1408 | |||
| 1409 | do { | ||
| 1410 | u16 EcOcRegIprInvMpg = 0; | ||
| 1411 | u16 EcOcRegOcModeLop = 0; | ||
| 1412 | u16 EcOcRegOcModeHip = 0; | ||
| 1413 | u16 EcOcRegOcMpgSio = 0; | ||
| 1414 | |||
| 1415 | /*CHK_ERROR(Read16(state, EC_OC_REG_OC_MODE_LOP__A, &EcOcRegOcModeLop, 0)); */ | ||
| 1416 | |||
| 1417 | if (state->operation_mode == OM_DVBT_Diversity_Front) { | ||
| 1418 | if (bEnableOutput) { | ||
| 1419 | EcOcRegOcModeHip |= | ||
| 1420 | B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR; | ||
| 1421 | } else | ||
| 1422 | EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; | ||
| 1423 | EcOcRegOcModeLop |= | ||
| 1424 | EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; | ||
| 1425 | } else { | ||
| 1426 | EcOcRegOcModeLop = state->m_EcOcRegOcModeLop; | ||
| 1427 | |||
| 1428 | if (bEnableOutput) | ||
| 1429 | EcOcRegOcMpgSio &= (~(EC_OC_REG_OC_MPG_SIO__M)); | ||
| 1430 | else | ||
| 1431 | EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; | ||
| 1432 | |||
| 1433 | /* Don't Insert RS Byte */ | ||
| 1434 | if (state->insert_rs_byte) { | ||
| 1435 | EcOcRegOcModeLop &= | ||
| 1436 | (~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M)); | ||
| 1437 | EcOcRegOcModeHip &= | ||
| 1438 | (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); | ||
| 1439 | EcOcRegOcModeHip |= | ||
| 1440 | EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE; | ||
| 1441 | } else { | ||
| 1442 | EcOcRegOcModeLop |= | ||
| 1443 | EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; | ||
| 1444 | EcOcRegOcModeHip &= | ||
| 1445 | (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); | ||
| 1446 | EcOcRegOcModeHip |= | ||
| 1447 | EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | /* Mode = Parallel */ | ||
| 1451 | if (state->enable_parallel) | ||
| 1452 | EcOcRegOcModeLop &= | ||
| 1453 | (~(EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M)); | ||
| 1454 | else | ||
| 1455 | EcOcRegOcModeLop |= | ||
| 1456 | EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL; | ||
| 1457 | } | ||
| 1458 | /* Invert Data */ | ||
| 1459 | /* EcOcRegIprInvMpg |= 0x00FF; */ | ||
| 1460 | EcOcRegIprInvMpg &= (~(0x00FF)); | ||
| 1461 | |||
| 1462 | /* Invert Error ( we don't use the pin ) */ | ||
| 1463 | /* EcOcRegIprInvMpg |= 0x0100; */ | ||
| 1464 | EcOcRegIprInvMpg &= (~(0x0100)); | ||
| 1465 | |||
| 1466 | /* Invert Start ( we don't use the pin ) */ | ||
| 1467 | /* EcOcRegIprInvMpg |= 0x0200; */ | ||
| 1468 | EcOcRegIprInvMpg &= (~(0x0200)); | ||
| 1469 | |||
| 1470 | /* Invert Valid ( we don't use the pin ) */ | ||
| 1471 | /* EcOcRegIprInvMpg |= 0x0400; */ | ||
| 1472 | EcOcRegIprInvMpg &= (~(0x0400)); | ||
| 1473 | |||
| 1474 | /* Invert Clock */ | ||
| 1475 | /* EcOcRegIprInvMpg |= 0x0800; */ | ||
| 1476 | EcOcRegIprInvMpg &= (~(0x0800)); | ||
| 1477 | |||
| 1478 | /* EcOcRegOcModeLop =0x05; */ | ||
| 1479 | status = Write16(state, EC_OC_REG_IPR_INV_MPG__A, EcOcRegIprInvMpg, 0); | ||
| 1480 | if (status < 0) | ||
| 1481 | break; | ||
| 1482 | status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, EcOcRegOcModeLop, 0); | ||
| 1483 | if (status < 0) | ||
| 1484 | break; | ||
| 1485 | status = Write16(state, EC_OC_REG_OC_MODE_HIP__A, EcOcRegOcModeHip, 0x0000); | ||
| 1486 | if (status < 0) | ||
| 1487 | break; | ||
| 1488 | status = Write16(state, EC_OC_REG_OC_MPG_SIO__A, EcOcRegOcMpgSio, 0); | ||
| 1489 | if (status < 0) | ||
| 1490 | break; | ||
| 1491 | } while (0); | ||
| 1492 | return status; | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | static int SetDeviceTypeId(struct drxd_state *state) | ||
| 1496 | { | ||
| 1497 | int status = 0; | ||
| 1498 | u16 deviceId = 0; | ||
| 1499 | |||
| 1500 | do { | ||
| 1501 | status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); | ||
| 1502 | if (status < 0) | ||
| 1503 | break; | ||
| 1504 | /* TODO: why twice? */ | ||
| 1505 | status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); | ||
| 1506 | if (status < 0) | ||
| 1507 | break; | ||
| 1508 | printk(KERN_INFO "drxd: deviceId = %04x\n", deviceId); | ||
| 1509 | |||
| 1510 | state->type_A = 0; | ||
| 1511 | state->PGA = 0; | ||
| 1512 | state->diversity = 0; | ||
| 1513 | if (deviceId == 0) { /* on A2 only 3975 available */ | ||
| 1514 | state->type_A = 1; | ||
| 1515 | printk(KERN_INFO "DRX3975D-A2\n"); | ||
| 1516 | } else { | ||
| 1517 | deviceId >>= 12; | ||
| 1518 | printk(KERN_INFO "DRX397%dD-B1\n", deviceId); | ||
| 1519 | switch (deviceId) { | ||
| 1520 | case 4: | ||
| 1521 | state->diversity = 1; | ||
| 1522 | case 3: | ||
| 1523 | case 7: | ||
| 1524 | state->PGA = 1; | ||
| 1525 | break; | ||
| 1526 | case 6: | ||
| 1527 | state->diversity = 1; | ||
| 1528 | case 5: | ||
| 1529 | case 8: | ||
| 1530 | break; | ||
| 1531 | default: | ||
| 1532 | status = -1; | ||
| 1533 | break; | ||
| 1534 | } | ||
| 1535 | } | ||
| 1536 | } while (0); | ||
| 1537 | |||
| 1538 | if (status < 0) | ||
| 1539 | return status; | ||
| 1540 | |||
| 1541 | /* Init Table selection */ | ||
| 1542 | state->m_InitAtomicRead = DRXD_InitAtomicRead; | ||
| 1543 | state->m_InitSC = DRXD_InitSC; | ||
| 1544 | state->m_ResetECRAM = DRXD_ResetECRAM; | ||
| 1545 | if (state->type_A) { | ||
| 1546 | state->m_ResetCEFR = DRXD_ResetCEFR; | ||
| 1547 | state->m_InitFE_1 = DRXD_InitFEA2_1; | ||
| 1548 | state->m_InitFE_2 = DRXD_InitFEA2_2; | ||
| 1549 | state->m_InitCP = DRXD_InitCPA2; | ||
| 1550 | state->m_InitCE = DRXD_InitCEA2; | ||
| 1551 | state->m_InitEQ = DRXD_InitEQA2; | ||
| 1552 | state->m_InitEC = DRXD_InitECA2; | ||
| 1553 | if (load_firmware(state, DRX_FW_FILENAME_A2)) | ||
| 1554 | return -EIO; | ||
| 1555 | } else { | ||
| 1556 | state->m_ResetCEFR = NULL; | ||
| 1557 | state->m_InitFE_1 = DRXD_InitFEB1_1; | ||
| 1558 | state->m_InitFE_2 = DRXD_InitFEB1_2; | ||
| 1559 | state->m_InitCP = DRXD_InitCPB1; | ||
| 1560 | state->m_InitCE = DRXD_InitCEB1; | ||
| 1561 | state->m_InitEQ = DRXD_InitEQB1; | ||
| 1562 | state->m_InitEC = DRXD_InitECB1; | ||
| 1563 | if (load_firmware(state, DRX_FW_FILENAME_B1)) | ||
| 1564 | return -EIO; | ||
| 1565 | } | ||
| 1566 | if (state->diversity) { | ||
| 1567 | state->m_InitDiversityFront = DRXD_InitDiversityFront; | ||
| 1568 | state->m_InitDiversityEnd = DRXD_InitDiversityEnd; | ||
| 1569 | state->m_DisableDiversity = DRXD_DisableDiversity; | ||
| 1570 | state->m_StartDiversityFront = DRXD_StartDiversityFront; | ||
| 1571 | state->m_StartDiversityEnd = DRXD_StartDiversityEnd; | ||
| 1572 | state->m_DiversityDelay8MHZ = DRXD_DiversityDelay8MHZ; | ||
| 1573 | state->m_DiversityDelay6MHZ = DRXD_DiversityDelay6MHZ; | ||
| 1574 | } else { | ||
| 1575 | state->m_InitDiversityFront = NULL; | ||
| 1576 | state->m_InitDiversityEnd = NULL; | ||
| 1577 | state->m_DisableDiversity = NULL; | ||
| 1578 | state->m_StartDiversityFront = NULL; | ||
| 1579 | state->m_StartDiversityEnd = NULL; | ||
| 1580 | state->m_DiversityDelay8MHZ = NULL; | ||
| 1581 | state->m_DiversityDelay6MHZ = NULL; | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | return status; | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | static int CorrectSysClockDeviation(struct drxd_state *state) | ||
| 1588 | { | ||
| 1589 | int status; | ||
| 1590 | s32 incr = 0; | ||
| 1591 | s32 nomincr = 0; | ||
| 1592 | u32 bandwidth = 0; | ||
| 1593 | u32 sysClockInHz = 0; | ||
| 1594 | u32 sysClockFreq = 0; /* in kHz */ | ||
| 1595 | s16 oscClockDeviation; | ||
| 1596 | s16 Diff; | ||
| 1597 | |||
| 1598 | do { | ||
| 1599 | /* Retrieve bandwidth and incr, sanity check */ | ||
| 1600 | |||
| 1601 | /* These accesses should be AtomicReadReg32, but that | ||
| 1602 | causes trouble (at least for diversity */ | ||
| 1603 | status = Read32(state, LC_RA_RAM_IFINCR_NOM_L__A, ((u32 *) &nomincr), 0); | ||
| 1604 | if (status < 0) | ||
| 1605 | break; | ||
| 1606 | status = Read32(state, FE_IF_REG_INCR0__A, (u32 *) &incr, 0); | ||
| 1607 | if (status < 0) | ||
| 1608 | break; | ||
| 1609 | |||
| 1610 | if (state->type_A) { | ||
| 1611 | if ((nomincr - incr < -500) || (nomincr - incr > 500)) | ||
| 1612 | break; | ||
| 1613 | } else { | ||
| 1614 | if ((nomincr - incr < -2000) || (nomincr - incr > 2000)) | ||
| 1615 | break; | ||
| 1616 | } | ||
| 1617 | |||
| 1618 | switch (state->param.u.ofdm.bandwidth) { | ||
| 1619 | case BANDWIDTH_8_MHZ: | ||
| 1620 | bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; | ||
| 1621 | break; | ||
| 1622 | case BANDWIDTH_7_MHZ: | ||
| 1623 | bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; | ||
| 1624 | break; | ||
| 1625 | case BANDWIDTH_6_MHZ: | ||
| 1626 | bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; | ||
| 1627 | break; | ||
| 1628 | default: | ||
| 1629 | return -1; | ||
| 1630 | break; | ||
| 1631 | } | ||
| 1632 | |||
| 1633 | /* Compute new sysclock value | ||
| 1634 | sysClockFreq = (((incr + 2^23)*bandwidth)/2^21)/1000 */ | ||
| 1635 | incr += (1 << 23); | ||
| 1636 | sysClockInHz = MulDiv32(incr, bandwidth, 1 << 21); | ||
| 1637 | sysClockFreq = (u32) (sysClockInHz / 1000); | ||
| 1638 | /* rounding */ | ||
| 1639 | if ((sysClockInHz % 1000) > 500) | ||
| 1640 | sysClockFreq++; | ||
| 1641 | |||
| 1642 | /* Compute clock deviation in ppm */ | ||
| 1643 | oscClockDeviation = (u16) ((((s32) (sysClockFreq) - | ||
| 1644 | (s32) | ||
| 1645 | (state->expected_sys_clock_freq)) * | ||
| 1646 | 1000000L) / | ||
| 1647 | (s32) | ||
| 1648 | (state->expected_sys_clock_freq)); | ||
| 1649 | |||
| 1650 | Diff = oscClockDeviation - state->osc_clock_deviation; | ||
| 1651 | /*printk(KERN_INFO "sysclockdiff=%d\n", Diff); */ | ||
| 1652 | if (Diff >= -200 && Diff <= 200) { | ||
| 1653 | state->sys_clock_freq = (u16) sysClockFreq; | ||
| 1654 | if (oscClockDeviation != state->osc_clock_deviation) { | ||
| 1655 | if (state->config.osc_deviation) { | ||
| 1656 | state->config.osc_deviation(state->priv, | ||
| 1657 | oscClockDeviation, | ||
| 1658 | 1); | ||
| 1659 | state->osc_clock_deviation = | ||
| 1660 | oscClockDeviation; | ||
| 1661 | } | ||
| 1662 | } | ||
| 1663 | /* switch OFF SRMM scan in SC */ | ||
| 1664 | status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DONT_SCAN, 0); | ||
| 1665 | if (status < 0) | ||
| 1666 | break; | ||
| 1667 | /* overrule FE_IF internal value for | ||
| 1668 | proper re-locking */ | ||
| 1669 | status = Write16(state, SC_RA_RAM_IF_SAVE__AX, state->current_fe_if_incr, 0); | ||
| 1670 | if (status < 0) | ||
| 1671 | break; | ||
| 1672 | state->cscd_state = CSCD_SAVED; | ||
| 1673 | } | ||
| 1674 | } while (0); | ||
| 1675 | |||
| 1676 | return status; | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | static int DRX_Stop(struct drxd_state *state) | ||
| 1680 | { | ||
| 1681 | int status; | ||
| 1682 | |||
| 1683 | if (state->drxd_state != DRXD_STARTED) | ||
| 1684 | return 0; | ||
| 1685 | |||
| 1686 | do { | ||
| 1687 | if (state->cscd_state != CSCD_SAVED) { | ||
| 1688 | u32 lock; | ||
| 1689 | status = DRX_GetLockStatus(state, &lock); | ||
| 1690 | if (status < 0) | ||
| 1691 | break; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | status = StopOC(state); | ||
| 1695 | if (status < 0) | ||
| 1696 | break; | ||
| 1697 | |||
| 1698 | state->drxd_state = DRXD_STOPPED; | ||
| 1699 | |||
| 1700 | status = ConfigureMPEGOutput(state, 0); | ||
| 1701 | if (status < 0) | ||
| 1702 | break; | ||
| 1703 | |||
| 1704 | if (state->type_A) { | ||
| 1705 | /* Stop relevant processors off the device */ | ||
| 1706 | status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0x0000); | ||
| 1707 | if (status < 0) | ||
| 1708 | break; | ||
| 1709 | |||
| 1710 | status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1711 | if (status < 0) | ||
| 1712 | break; | ||
| 1713 | status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1714 | if (status < 0) | ||
| 1715 | break; | ||
| 1716 | } else { | ||
| 1717 | /* Stop all processors except HI & CC & FE */ | ||
| 1718 | status = Write16(state, B_SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1719 | if (status < 0) | ||
| 1720 | break; | ||
| 1721 | status = Write16(state, B_LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1722 | if (status < 0) | ||
| 1723 | break; | ||
| 1724 | status = Write16(state, B_FT_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1725 | if (status < 0) | ||
| 1726 | break; | ||
| 1727 | status = Write16(state, B_CP_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1728 | if (status < 0) | ||
| 1729 | break; | ||
| 1730 | status = Write16(state, B_CE_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1731 | if (status < 0) | ||
| 1732 | break; | ||
| 1733 | status = Write16(state, B_EQ_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 1734 | if (status < 0) | ||
| 1735 | break; | ||
| 1736 | status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0); | ||
| 1737 | if (status < 0) | ||
| 1738 | break; | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | } while (0); | ||
| 1742 | return status; | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | int SetOperationMode(struct drxd_state *state, int oMode) | ||
| 1746 | { | ||
| 1747 | int status; | ||
| 1748 | |||
| 1749 | do { | ||
| 1750 | if (state->drxd_state != DRXD_STOPPED) { | ||
| 1751 | status = -1; | ||
| 1752 | break; | ||
| 1753 | } | ||
| 1754 | |||
| 1755 | if (oMode == state->operation_mode) { | ||
| 1756 | status = 0; | ||
| 1757 | break; | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | if (oMode != OM_Default && !state->diversity) { | ||
| 1761 | status = -1; | ||
| 1762 | break; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | switch (oMode) { | ||
| 1766 | case OM_DVBT_Diversity_Front: | ||
| 1767 | status = WriteTable(state, state->m_InitDiversityFront); | ||
| 1768 | break; | ||
| 1769 | case OM_DVBT_Diversity_End: | ||
| 1770 | status = WriteTable(state, state->m_InitDiversityEnd); | ||
| 1771 | break; | ||
| 1772 | case OM_Default: | ||
| 1773 | /* We need to check how to | ||
| 1774 | get DRXD out of diversity */ | ||
| 1775 | default: | ||
| 1776 | status = WriteTable(state, state->m_DisableDiversity); | ||
| 1777 | break; | ||
| 1778 | } | ||
| 1779 | } while (0); | ||
| 1780 | |||
| 1781 | if (!status) | ||
| 1782 | state->operation_mode = oMode; | ||
| 1783 | return status; | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | static int StartDiversity(struct drxd_state *state) | ||
| 1787 | { | ||
| 1788 | int status = 0; | ||
| 1789 | u16 rcControl; | ||
| 1790 | |||
| 1791 | do { | ||
| 1792 | if (state->operation_mode == OM_DVBT_Diversity_Front) { | ||
| 1793 | status = WriteTable(state, state->m_StartDiversityFront); | ||
| 1794 | if (status < 0) | ||
| 1795 | break; | ||
| 1796 | } else if (state->operation_mode == OM_DVBT_Diversity_End) { | ||
| 1797 | status = WriteTable(state, state->m_StartDiversityEnd); | ||
| 1798 | if (status < 0) | ||
| 1799 | break; | ||
| 1800 | if (state->param.u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { | ||
| 1801 | status = WriteTable(state, state->m_DiversityDelay8MHZ); | ||
| 1802 | if (status < 0) | ||
| 1803 | break; | ||
| 1804 | } else { | ||
| 1805 | status = WriteTable(state, state->m_DiversityDelay6MHZ); | ||
| 1806 | if (status < 0) | ||
| 1807 | break; | ||
| 1808 | } | ||
| 1809 | |||
| 1810 | status = Read16(state, B_EQ_REG_RC_SEL_CAR__A, &rcControl, 0); | ||
| 1811 | if (status < 0) | ||
| 1812 | break; | ||
| 1813 | rcControl &= ~(B_EQ_REG_RC_SEL_CAR_FFTMODE__M); | ||
| 1814 | rcControl |= B_EQ_REG_RC_SEL_CAR_DIV_ON | | ||
| 1815 | /* combining enabled */ | ||
| 1816 | B_EQ_REG_RC_SEL_CAR_MEAS_A_CC | | ||
| 1817 | B_EQ_REG_RC_SEL_CAR_PASS_A_CC | | ||
| 1818 | B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC; | ||
| 1819 | status = Write16(state, B_EQ_REG_RC_SEL_CAR__A, rcControl, 0); | ||
| 1820 | if (status < 0) | ||
| 1821 | break; | ||
| 1822 | } | ||
| 1823 | } while (0); | ||
| 1824 | return status; | ||
| 1825 | } | ||
| 1826 | |||
| 1827 | static int SetFrequencyShift(struct drxd_state *state, | ||
| 1828 | u32 offsetFreq, int channelMirrored) | ||
| 1829 | { | ||
| 1830 | int negativeShift = (state->tuner_mirrors == channelMirrored); | ||
| 1831 | |||
| 1832 | /* Handle all mirroring | ||
| 1833 | * | ||
| 1834 | * Note: ADC mirroring (aliasing) is implictly handled by limiting | ||
| 1835 | * feFsRegAddInc to 28 bits below | ||
| 1836 | * (if the result before masking is more than 28 bits, this means | ||
| 1837 | * that the ADC is mirroring. | ||
| 1838 | * The masking is in fact the aliasing of the ADC) | ||
| 1839 | * | ||
| 1840 | */ | ||
| 1841 | |||
| 1842 | /* Compute register value, unsigned computation */ | ||
| 1843 | state->fe_fs_add_incr = MulDiv32(state->intermediate_freq + | ||
| 1844 | offsetFreq, | ||
| 1845 | 1 << 28, state->sys_clock_freq); | ||
| 1846 | /* Remove integer part */ | ||
| 1847 | state->fe_fs_add_incr &= 0x0FFFFFFFL; | ||
| 1848 | if (negativeShift) | ||
| 1849 | state->fe_fs_add_incr = ((1 << 28) - state->fe_fs_add_incr); | ||
| 1850 | |||
| 1851 | /* Save the frequency shift without tunerOffset compensation | ||
| 1852 | for CtrlGetChannel. */ | ||
| 1853 | state->org_fe_fs_add_incr = MulDiv32(state->intermediate_freq, | ||
| 1854 | 1 << 28, state->sys_clock_freq); | ||
| 1855 | /* Remove integer part */ | ||
| 1856 | state->org_fe_fs_add_incr &= 0x0FFFFFFFL; | ||
| 1857 | if (negativeShift) | ||
| 1858 | state->org_fe_fs_add_incr = ((1L << 28) - | ||
| 1859 | state->org_fe_fs_add_incr); | ||
| 1860 | |||
| 1861 | return Write32(state, FE_FS_REG_ADD_INC_LOP__A, | ||
| 1862 | state->fe_fs_add_incr, 0); | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | static int SetCfgNoiseCalibration(struct drxd_state *state, | ||
| 1866 | struct SNoiseCal *noiseCal) | ||
| 1867 | { | ||
| 1868 | u16 beOptEna; | ||
| 1869 | int status = 0; | ||
| 1870 | |||
| 1871 | do { | ||
| 1872 | status = Read16(state, SC_RA_RAM_BE_OPT_ENA__A, &beOptEna, 0); | ||
| 1873 | if (status < 0) | ||
| 1874 | break; | ||
| 1875 | if (noiseCal->cpOpt) { | ||
| 1876 | beOptEna |= (1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); | ||
| 1877 | } else { | ||
| 1878 | beOptEna &= ~(1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); | ||
| 1879 | status = Write16(state, CP_REG_AC_NEXP_OFFS__A, noiseCal->cpNexpOfs, 0); | ||
| 1880 | if (status < 0) | ||
| 1881 | break; | ||
| 1882 | } | ||
| 1883 | status = Write16(state, SC_RA_RAM_BE_OPT_ENA__A, beOptEna, 0); | ||
| 1884 | if (status < 0) | ||
| 1885 | break; | ||
| 1886 | |||
| 1887 | if (!state->type_A) { | ||
| 1888 | status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_2K__A, noiseCal->tdCal2k, 0); | ||
| 1889 | if (status < 0) | ||
| 1890 | break; | ||
| 1891 | status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_8K__A, noiseCal->tdCal8k, 0); | ||
| 1892 | if (status < 0) | ||
| 1893 | break; | ||
| 1894 | } | ||
| 1895 | } while (0); | ||
| 1896 | |||
| 1897 | return status; | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | static int DRX_Start(struct drxd_state *state, s32 off) | ||
| 1901 | { | ||
| 1902 | struct dvb_ofdm_parameters *p = &state->param.u.ofdm; | ||
| 1903 | int status; | ||
| 1904 | |||
| 1905 | u16 transmissionParams = 0; | ||
| 1906 | u16 operationMode = 0; | ||
| 1907 | u16 qpskTdTpsPwr = 0; | ||
| 1908 | u16 qam16TdTpsPwr = 0; | ||
| 1909 | u16 qam64TdTpsPwr = 0; | ||
| 1910 | u32 feIfIncr = 0; | ||
| 1911 | u32 bandwidth = 0; | ||
| 1912 | int mirrorFreqSpect; | ||
| 1913 | |||
| 1914 | u16 qpskSnCeGain = 0; | ||
| 1915 | u16 qam16SnCeGain = 0; | ||
| 1916 | u16 qam64SnCeGain = 0; | ||
| 1917 | u16 qpskIsGainMan = 0; | ||
| 1918 | u16 qam16IsGainMan = 0; | ||
| 1919 | u16 qam64IsGainMan = 0; | ||
| 1920 | u16 qpskIsGainExp = 0; | ||
| 1921 | u16 qam16IsGainExp = 0; | ||
| 1922 | u16 qam64IsGainExp = 0; | ||
| 1923 | u16 bandwidthParam = 0; | ||
| 1924 | |||
| 1925 | if (off < 0) | ||
| 1926 | off = (off - 500) / 1000; | ||
| 1927 | else | ||
| 1928 | off = (off + 500) / 1000; | ||
| 1929 | |||
| 1930 | do { | ||
| 1931 | if (state->drxd_state != DRXD_STOPPED) | ||
| 1932 | return -1; | ||
| 1933 | status = ResetECOD(state); | ||
| 1934 | if (status < 0) | ||
| 1935 | break; | ||
| 1936 | if (state->type_A) { | ||
| 1937 | status = InitSC(state); | ||
| 1938 | if (status < 0) | ||
| 1939 | break; | ||
| 1940 | } else { | ||
| 1941 | status = InitFT(state); | ||
| 1942 | if (status < 0) | ||
| 1943 | break; | ||
| 1944 | status = InitCP(state); | ||
| 1945 | if (status < 0) | ||
| 1946 | break; | ||
| 1947 | status = InitCE(state); | ||
| 1948 | if (status < 0) | ||
| 1949 | break; | ||
| 1950 | status = InitEQ(state); | ||
| 1951 | if (status < 0) | ||
| 1952 | break; | ||
| 1953 | status = InitSC(state); | ||
| 1954 | if (status < 0) | ||
| 1955 | break; | ||
| 1956 | } | ||
| 1957 | |||
| 1958 | /* Restore current IF & RF AGC settings */ | ||
| 1959 | |||
| 1960 | status = SetCfgIfAgc(state, &state->if_agc_cfg); | ||
| 1961 | if (status < 0) | ||
| 1962 | break; | ||
| 1963 | status = SetCfgRfAgc(state, &state->rf_agc_cfg); | ||
| 1964 | if (status < 0) | ||
| 1965 | break; | ||
| 1966 | |||
| 1967 | mirrorFreqSpect = (state->param.inversion == INVERSION_ON); | ||
| 1968 | |||
| 1969 | switch (p->transmission_mode) { | ||
| 1970 | default: /* Not set, detect it automatically */ | ||
| 1971 | operationMode |= SC_RA_RAM_OP_AUTO_MODE__M; | ||
| 1972 | /* fall through , try first guess DRX_FFTMODE_8K */ | ||
| 1973 | case TRANSMISSION_MODE_8K: | ||
| 1974 | transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K; | ||
| 1975 | if (state->type_A) { | ||
| 1976 | status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_8K, 0x0000); | ||
| 1977 | if (status < 0) | ||
| 1978 | break; | ||
| 1979 | qpskSnCeGain = 99; | ||
| 1980 | qam16SnCeGain = 83; | ||
| 1981 | qam64SnCeGain = 67; | ||
| 1982 | } | ||
| 1983 | break; | ||
| 1984 | case TRANSMISSION_MODE_2K: | ||
| 1985 | transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_2K; | ||
| 1986 | if (state->type_A) { | ||
| 1987 | status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_2K, 0x0000); | ||
| 1988 | if (status < 0) | ||
| 1989 | break; | ||
| 1990 | qpskSnCeGain = 97; | ||
| 1991 | qam16SnCeGain = 71; | ||
| 1992 | qam64SnCeGain = 65; | ||
| 1993 | } | ||
| 1994 | break; | ||
| 1995 | } | ||
| 1996 | |||
| 1997 | switch (p->guard_interval) { | ||
| 1998 | case GUARD_INTERVAL_1_4: | ||
| 1999 | transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; | ||
| 2000 | break; | ||
| 2001 | case GUARD_INTERVAL_1_8: | ||
| 2002 | transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_8; | ||
| 2003 | break; | ||
| 2004 | case GUARD_INTERVAL_1_16: | ||
| 2005 | transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_16; | ||
| 2006 | break; | ||
| 2007 | case GUARD_INTERVAL_1_32: | ||
| 2008 | transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_32; | ||
| 2009 | break; | ||
| 2010 | default: /* Not set, detect it automatically */ | ||
| 2011 | operationMode |= SC_RA_RAM_OP_AUTO_GUARD__M; | ||
| 2012 | /* try first guess 1/4 */ | ||
| 2013 | transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; | ||
| 2014 | break; | ||
| 2015 | } | ||
| 2016 | |||
| 2017 | switch (p->hierarchy_information) { | ||
| 2018 | case HIERARCHY_1: | ||
| 2019 | transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1; | ||
| 2020 | if (state->type_A) { | ||
| 2021 | status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0001, 0x0000); | ||
| 2022 | if (status < 0) | ||
| 2023 | break; | ||
| 2024 | status = Write16(state, EC_SB_REG_ALPHA__A, 0x0001, 0x0000); | ||
| 2025 | if (status < 0) | ||
| 2026 | break; | ||
| 2027 | |||
| 2028 | qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; | ||
| 2029 | qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA1; | ||
| 2030 | qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA1; | ||
| 2031 | |||
| 2032 | qpskIsGainMan = | ||
| 2033 | SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; | ||
| 2034 | qam16IsGainMan = | ||
| 2035 | SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; | ||
| 2036 | qam64IsGainMan = | ||
| 2037 | SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; | ||
| 2038 | |||
| 2039 | qpskIsGainExp = | ||
| 2040 | SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; | ||
| 2041 | qam16IsGainExp = | ||
| 2042 | SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; | ||
| 2043 | qam64IsGainExp = | ||
| 2044 | SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; | ||
| 2045 | } | ||
| 2046 | break; | ||
| 2047 | |||
| 2048 | case HIERARCHY_2: | ||
| 2049 | transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A2; | ||
| 2050 | if (state->type_A) { | ||
| 2051 | status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0002, 0x0000); | ||
| 2052 | if (status < 0) | ||
| 2053 | break; | ||
| 2054 | status = Write16(state, EC_SB_REG_ALPHA__A, 0x0002, 0x0000); | ||
| 2055 | if (status < 0) | ||
| 2056 | break; | ||
| 2057 | |||
| 2058 | qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; | ||
| 2059 | qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA2; | ||
| 2060 | qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA2; | ||
| 2061 | |||
| 2062 | qpskIsGainMan = | ||
| 2063 | SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; | ||
| 2064 | qam16IsGainMan = | ||
| 2065 | SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE; | ||
| 2066 | qam64IsGainMan = | ||
| 2067 | SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE; | ||
| 2068 | |||
| 2069 | qpskIsGainExp = | ||
| 2070 | SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; | ||
| 2071 | qam16IsGainExp = | ||
| 2072 | SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE; | ||
| 2073 | qam64IsGainExp = | ||
| 2074 | SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE; | ||
| 2075 | } | ||
| 2076 | break; | ||
| 2077 | case HIERARCHY_4: | ||
| 2078 | transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A4; | ||
| 2079 | if (state->type_A) { | ||
| 2080 | status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0003, 0x0000); | ||
| 2081 | if (status < 0) | ||
| 2082 | break; | ||
| 2083 | status = Write16(state, EC_SB_REG_ALPHA__A, 0x0003, 0x0000); | ||
| 2084 | if (status < 0) | ||
| 2085 | break; | ||
| 2086 | |||
| 2087 | qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; | ||
| 2088 | qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA4; | ||
| 2089 | qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA4; | ||
| 2090 | |||
| 2091 | qpskIsGainMan = | ||
| 2092 | SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; | ||
| 2093 | qam16IsGainMan = | ||
| 2094 | SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE; | ||
| 2095 | qam64IsGainMan = | ||
| 2096 | SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE; | ||
| 2097 | |||
| 2098 | qpskIsGainExp = | ||
| 2099 | SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; | ||
| 2100 | qam16IsGainExp = | ||
| 2101 | SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE; | ||
| 2102 | qam64IsGainExp = | ||
| 2103 | SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE; | ||
| 2104 | } | ||
| 2105 | break; | ||
| 2106 | case HIERARCHY_AUTO: | ||
| 2107 | default: | ||
| 2108 | /* Not set, detect it automatically, start with none */ | ||
| 2109 | operationMode |= SC_RA_RAM_OP_AUTO_HIER__M; | ||
| 2110 | transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_NO; | ||
| 2111 | if (state->type_A) { | ||
| 2112 | status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0000, 0x0000); | ||
| 2113 | if (status < 0) | ||
| 2114 | break; | ||
| 2115 | status = Write16(state, EC_SB_REG_ALPHA__A, 0x0000, 0x0000); | ||
| 2116 | if (status < 0) | ||
| 2117 | break; | ||
| 2118 | |||
| 2119 | qpskTdTpsPwr = EQ_TD_TPS_PWR_QPSK; | ||
| 2120 | qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHAN; | ||
| 2121 | qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHAN; | ||
| 2122 | |||
| 2123 | qpskIsGainMan = | ||
| 2124 | SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE; | ||
| 2125 | qam16IsGainMan = | ||
| 2126 | SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; | ||
| 2127 | qam64IsGainMan = | ||
| 2128 | SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; | ||
| 2129 | |||
| 2130 | qpskIsGainExp = | ||
| 2131 | SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE; | ||
| 2132 | qam16IsGainExp = | ||
| 2133 | SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; | ||
| 2134 | qam64IsGainExp = | ||
| 2135 | SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; | ||
| 2136 | } | ||
| 2137 | break; | ||
| 2138 | } | ||
| 2139 | status = status; | ||
| 2140 | if (status < 0) | ||
| 2141 | break; | ||
| 2142 | |||
| 2143 | switch (p->constellation) { | ||
| 2144 | default: | ||
| 2145 | operationMode |= SC_RA_RAM_OP_AUTO_CONST__M; | ||
| 2146 | /* fall through , try first guess | ||
| 2147 | DRX_CONSTELLATION_QAM64 */ | ||
| 2148 | case QAM_64: | ||
| 2149 | transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64; | ||
| 2150 | if (state->type_A) { | ||
| 2151 | status = Write16(state, EQ_REG_OT_CONST__A, 0x0002, 0x0000); | ||
| 2152 | if (status < 0) | ||
| 2153 | break; | ||
| 2154 | status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_64QAM, 0x0000); | ||
| 2155 | if (status < 0) | ||
| 2156 | break; | ||
| 2157 | status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0020, 0x0000); | ||
| 2158 | if (status < 0) | ||
| 2159 | break; | ||
| 2160 | status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0008, 0x0000); | ||
| 2161 | if (status < 0) | ||
| 2162 | break; | ||
| 2163 | status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0002, 0x0000); | ||
| 2164 | if (status < 0) | ||
| 2165 | break; | ||
| 2166 | |||
| 2167 | status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam64TdTpsPwr, 0x0000); | ||
| 2168 | if (status < 0) | ||
| 2169 | break; | ||
| 2170 | status = Write16(state, EQ_REG_SN_CEGAIN__A, qam64SnCeGain, 0x0000); | ||
| 2171 | if (status < 0) | ||
| 2172 | break; | ||
| 2173 | status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam64IsGainMan, 0x0000); | ||
| 2174 | if (status < 0) | ||
| 2175 | break; | ||
| 2176 | status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam64IsGainExp, 0x0000); | ||
| 2177 | if (status < 0) | ||
| 2178 | break; | ||
| 2179 | } | ||
| 2180 | break; | ||
| 2181 | case QPSK: | ||
| 2182 | transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QPSK; | ||
| 2183 | if (state->type_A) { | ||
| 2184 | status = Write16(state, EQ_REG_OT_CONST__A, 0x0000, 0x0000); | ||
| 2185 | if (status < 0) | ||
| 2186 | break; | ||
| 2187 | status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_QPSK, 0x0000); | ||
| 2188 | if (status < 0) | ||
| 2189 | break; | ||
| 2190 | status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); | ||
| 2191 | if (status < 0) | ||
| 2192 | break; | ||
| 2193 | status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0000, 0x0000); | ||
| 2194 | if (status < 0) | ||
| 2195 | break; | ||
| 2196 | status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); | ||
| 2197 | if (status < 0) | ||
| 2198 | break; | ||
| 2199 | |||
| 2200 | status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qpskTdTpsPwr, 0x0000); | ||
| 2201 | if (status < 0) | ||
| 2202 | break; | ||
| 2203 | status = Write16(state, EQ_REG_SN_CEGAIN__A, qpskSnCeGain, 0x0000); | ||
| 2204 | if (status < 0) | ||
| 2205 | break; | ||
| 2206 | status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qpskIsGainMan, 0x0000); | ||
| 2207 | if (status < 0) | ||
| 2208 | break; | ||
| 2209 | status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qpskIsGainExp, 0x0000); | ||
| 2210 | if (status < 0) | ||
| 2211 | break; | ||
| 2212 | } | ||
| 2213 | break; | ||
| 2214 | |||
| 2215 | case QAM_16: | ||
| 2216 | transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM16; | ||
| 2217 | if (state->type_A) { | ||
| 2218 | status = Write16(state, EQ_REG_OT_CONST__A, 0x0001, 0x0000); | ||
| 2219 | if (status < 0) | ||
| 2220 | break; | ||
| 2221 | status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_16QAM, 0x0000); | ||
| 2222 | if (status < 0) | ||
| 2223 | break; | ||
| 2224 | status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); | ||
| 2225 | if (status < 0) | ||
| 2226 | break; | ||
| 2227 | status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0004, 0x0000); | ||
| 2228 | if (status < 0) | ||
| 2229 | break; | ||
| 2230 | status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); | ||
| 2231 | if (status < 0) | ||
| 2232 | break; | ||
| 2233 | |||
| 2234 | status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam16TdTpsPwr, 0x0000); | ||
| 2235 | if (status < 0) | ||
| 2236 | break; | ||
| 2237 | status = Write16(state, EQ_REG_SN_CEGAIN__A, qam16SnCeGain, 0x0000); | ||
| 2238 | if (status < 0) | ||
| 2239 | break; | ||
| 2240 | status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam16IsGainMan, 0x0000); | ||
| 2241 | if (status < 0) | ||
| 2242 | break; | ||
| 2243 | status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam16IsGainExp, 0x0000); | ||
| 2244 | if (status < 0) | ||
| 2245 | break; | ||
| 2246 | } | ||
| 2247 | break; | ||
| 2248 | |||
| 2249 | } | ||
| 2250 | status = status; | ||
| 2251 | if (status < 0) | ||
| 2252 | break; | ||
| 2253 | |||
| 2254 | switch (DRX_CHANNEL_HIGH) { | ||
| 2255 | default: | ||
| 2256 | case DRX_CHANNEL_AUTO: | ||
| 2257 | case DRX_CHANNEL_LOW: | ||
| 2258 | transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO; | ||
| 2259 | status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000); | ||
| 2260 | if (status < 0) | ||
| 2261 | break; | ||
| 2262 | break; | ||
| 2263 | case DRX_CHANNEL_HIGH: | ||
| 2264 | transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI; | ||
| 2265 | status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000); | ||
| 2266 | if (status < 0) | ||
| 2267 | break; | ||
| 2268 | break; | ||
| 2269 | |||
| 2270 | } | ||
| 2271 | |||
| 2272 | switch (p->code_rate_HP) { | ||
| 2273 | case FEC_1_2: | ||
| 2274 | transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2; | ||
| 2275 | if (state->type_A) { | ||
| 2276 | status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000); | ||
| 2277 | if (status < 0) | ||
| 2278 | break; | ||
| 2279 | } | ||
| 2280 | break; | ||
| 2281 | default: | ||
| 2282 | operationMode |= SC_RA_RAM_OP_AUTO_RATE__M; | ||
| 2283 | case FEC_2_3: | ||
| 2284 | transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3; | ||
| 2285 | if (state->type_A) { | ||
| 2286 | status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000); | ||
| 2287 | if (status < 0) | ||
| 2288 | break; | ||
| 2289 | } | ||
| 2290 | break; | ||
| 2291 | case FEC_3_4: | ||
| 2292 | transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4; | ||
| 2293 | if (state->type_A) { | ||
| 2294 | status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000); | ||
| 2295 | if (status < 0) | ||
| 2296 | break; | ||
| 2297 | } | ||
| 2298 | break; | ||
| 2299 | case FEC_5_6: | ||
| 2300 | transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6; | ||
| 2301 | if (state->type_A) { | ||
| 2302 | status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000); | ||
| 2303 | if (status < 0) | ||
| 2304 | break; | ||
| 2305 | } | ||
| 2306 | break; | ||
| 2307 | case FEC_7_8: | ||
| 2308 | transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8; | ||
| 2309 | if (state->type_A) { | ||
| 2310 | status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000); | ||
| 2311 | if (status < 0) | ||
| 2312 | break; | ||
| 2313 | } | ||
| 2314 | break; | ||
| 2315 | } | ||
| 2316 | status = status; | ||
| 2317 | if (status < 0) | ||
| 2318 | break; | ||
| 2319 | |||
| 2320 | /* First determine real bandwidth (Hz) */ | ||
| 2321 | /* Also set delay for impulse noise cruncher (only A2) */ | ||
| 2322 | /* Also set parameters for EC_OC fix, note | ||
| 2323 | EC_OC_REG_TMD_HIL_MAR is changed | ||
| 2324 | by SC for fix for some 8K,1/8 guard but is restored by | ||
| 2325 | InitEC and ResetEC | ||
| 2326 | functions */ | ||
| 2327 | switch (p->bandwidth) { | ||
| 2328 | case BANDWIDTH_AUTO: | ||
| 2329 | case BANDWIDTH_8_MHZ: | ||
| 2330 | /* (64/7)*(8/8)*1000000 */ | ||
| 2331 | bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; | ||
| 2332 | |||
| 2333 | bandwidthParam = 0; | ||
| 2334 | status = Write16(state, | ||
| 2335 | FE_AG_REG_IND_DEL__A, 50, 0x0000); | ||
| 2336 | break; | ||
| 2337 | case BANDWIDTH_7_MHZ: | ||
| 2338 | /* (64/7)*(7/8)*1000000 */ | ||
| 2339 | bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; | ||
| 2340 | bandwidthParam = 0x4807; /*binary:0100 1000 0000 0111 */ | ||
| 2341 | status = Write16(state, | ||
| 2342 | FE_AG_REG_IND_DEL__A, 59, 0x0000); | ||
| 2343 | break; | ||
| 2344 | case BANDWIDTH_6_MHZ: | ||
| 2345 | /* (64/7)*(6/8)*1000000 */ | ||
| 2346 | bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; | ||
| 2347 | bandwidthParam = 0x0F07; /*binary: 0000 1111 0000 0111 */ | ||
| 2348 | status = Write16(state, | ||
| 2349 | FE_AG_REG_IND_DEL__A, 71, 0x0000); | ||
| 2350 | break; | ||
| 2351 | default: | ||
| 2352 | status = -EINVAL; | ||
| 2353 | } | ||
| 2354 | if (status < 0) | ||
| 2355 | break; | ||
| 2356 | |||
| 2357 | status = Write16(state, SC_RA_RAM_BAND__A, bandwidthParam, 0x0000); | ||
| 2358 | if (status < 0) | ||
| 2359 | break; | ||
| 2360 | |||
| 2361 | { | ||
| 2362 | u16 sc_config; | ||
| 2363 | status = Read16(state, SC_RA_RAM_CONFIG__A, &sc_config, 0); | ||
| 2364 | if (status < 0) | ||
| 2365 | break; | ||
| 2366 | |||
| 2367 | /* enable SLAVE mode in 2k 1/32 to | ||
| 2368 | prevent timing change glitches */ | ||
| 2369 | if ((p->transmission_mode == TRANSMISSION_MODE_2K) && | ||
| 2370 | (p->guard_interval == GUARD_INTERVAL_1_32)) { | ||
| 2371 | /* enable slave */ | ||
| 2372 | sc_config |= SC_RA_RAM_CONFIG_SLAVE__M; | ||
| 2373 | } else { | ||
| 2374 | /* disable slave */ | ||
| 2375 | sc_config &= ~SC_RA_RAM_CONFIG_SLAVE__M; | ||
| 2376 | } | ||
| 2377 | status = Write16(state, SC_RA_RAM_CONFIG__A, sc_config, 0); | ||
| 2378 | if (status < 0) | ||
| 2379 | break; | ||
| 2380 | } | ||
| 2381 | |||
| 2382 | status = SetCfgNoiseCalibration(state, &state->noise_cal); | ||
| 2383 | if (status < 0) | ||
| 2384 | break; | ||
| 2385 | |||
| 2386 | if (state->cscd_state == CSCD_INIT) { | ||
| 2387 | /* switch on SRMM scan in SC */ | ||
| 2388 | status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DO_SCAN, 0x0000); | ||
| 2389 | if (status < 0) | ||
| 2390 | break; | ||
| 2391 | /* CHK_ERROR(Write16(SC_RA_RAM_SAMPLE_RATE_STEP__A, DRXD_OSCDEV_STEP, 0x0000));*/ | ||
| 2392 | state->cscd_state = CSCD_SET; | ||
| 2393 | } | ||
| 2394 | |||
| 2395 | /* Now compute FE_IF_REG_INCR */ | ||
| 2396 | /*((( SysFreq/BandWidth)/2)/2) -1) * 2^23) => | ||
| 2397 | ((SysFreq / BandWidth) * (2^21) ) - (2^23) */ | ||
| 2398 | feIfIncr = MulDiv32(state->sys_clock_freq * 1000, | ||
| 2399 | (1ULL << 21), bandwidth) - (1 << 23); | ||
| 2400 | status = Write16(state, FE_IF_REG_INCR0__A, (u16) (feIfIncr & FE_IF_REG_INCR0__M), 0x0000); | ||
| 2401 | if (status < 0) | ||
| 2402 | break; | ||
| 2403 | status = Write16(state, FE_IF_REG_INCR1__A, (u16) ((feIfIncr >> FE_IF_REG_INCR0__W) & FE_IF_REG_INCR1__M), 0x0000); | ||
| 2404 | if (status < 0) | ||
| 2405 | break; | ||
| 2406 | /* Bandwidth setting done */ | ||
| 2407 | |||
| 2408 | /* Mirror & frequency offset */ | ||
| 2409 | SetFrequencyShift(state, off, mirrorFreqSpect); | ||
| 2410 | |||
| 2411 | /* Start SC, write channel settings to SC */ | ||
| 2412 | |||
| 2413 | /* Enable SC after setting all other parameters */ | ||
| 2414 | status = Write16(state, SC_COMM_STATE__A, 0, 0x0000); | ||
| 2415 | if (status < 0) | ||
| 2416 | break; | ||
| 2417 | status = Write16(state, SC_COMM_EXEC__A, 1, 0x0000); | ||
| 2418 | if (status < 0) | ||
| 2419 | break; | ||
| 2420 | |||
| 2421 | /* Write SC parameter registers, operation mode */ | ||
| 2422 | #if 1 | ||
| 2423 | operationMode = (SC_RA_RAM_OP_AUTO_MODE__M | | ||
| 2424 | SC_RA_RAM_OP_AUTO_GUARD__M | | ||
| 2425 | SC_RA_RAM_OP_AUTO_CONST__M | | ||
| 2426 | SC_RA_RAM_OP_AUTO_HIER__M | | ||
| 2427 | SC_RA_RAM_OP_AUTO_RATE__M); | ||
| 2428 | #endif | ||
| 2429 | status = SC_SetPrefParamCommand(state, 0x0000, transmissionParams, operationMode); | ||
| 2430 | if (status < 0) | ||
| 2431 | break; | ||
| 2432 | |||
| 2433 | /* Start correct processes to get in lock */ | ||
| 2434 | status = SC_ProcStartCommand(state, SC_RA_RAM_PROC_LOCKTRACK, SC_RA_RAM_SW_EVENT_RUN_NMASK__M, SC_RA_RAM_LOCKTRACK_MIN); | ||
| 2435 | if (status < 0) | ||
| 2436 | break; | ||
| 2437 | |||
| 2438 | status = StartOC(state); | ||
| 2439 | if (status < 0) | ||
| 2440 | break; | ||
| 2441 | |||
| 2442 | if (state->operation_mode != OM_Default) { | ||
| 2443 | status = StartDiversity(state); | ||
| 2444 | if (status < 0) | ||
| 2445 | break; | ||
| 2446 | } | ||
| 2447 | |||
| 2448 | state->drxd_state = DRXD_STARTED; | ||
| 2449 | } while (0); | ||
| 2450 | |||
| 2451 | return status; | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | static int CDRXD(struct drxd_state *state, u32 IntermediateFrequency) | ||
| 2455 | { | ||
| 2456 | u32 ulRfAgcOutputLevel = 0xffffffff; | ||
| 2457 | u32 ulRfAgcSettleLevel = 528; /* Optimum value for MT2060 */ | ||
| 2458 | u32 ulRfAgcMinLevel = 0; /* Currently unused */ | ||
| 2459 | u32 ulRfAgcMaxLevel = DRXD_FE_CTRL_MAX; /* Currently unused */ | ||
| 2460 | u32 ulRfAgcSpeed = 0; /* Currently unused */ | ||
| 2461 | u32 ulRfAgcMode = 0; /*2; Off */ | ||
| 2462 | u32 ulRfAgcR1 = 820; | ||
| 2463 | u32 ulRfAgcR2 = 2200; | ||
| 2464 | u32 ulRfAgcR3 = 150; | ||
| 2465 | u32 ulIfAgcMode = 0; /* Auto */ | ||
| 2466 | u32 ulIfAgcOutputLevel = 0xffffffff; | ||
| 2467 | u32 ulIfAgcSettleLevel = 0xffffffff; | ||
| 2468 | u32 ulIfAgcMinLevel = 0xffffffff; | ||
| 2469 | u32 ulIfAgcMaxLevel = 0xffffffff; | ||
| 2470 | u32 ulIfAgcSpeed = 0xffffffff; | ||
| 2471 | u32 ulIfAgcR1 = 820; | ||
| 2472 | u32 ulIfAgcR2 = 2200; | ||
| 2473 | u32 ulIfAgcR3 = 150; | ||
| 2474 | u32 ulClock = state->config.clock; | ||
| 2475 | u32 ulSerialMode = 0; | ||
| 2476 | u32 ulEcOcRegOcModeLop = 4; /* Dynamic DTO source */ | ||
| 2477 | u32 ulHiI2cDelay = HI_I2C_DELAY; | ||
| 2478 | u32 ulHiI2cBridgeDelay = HI_I2C_BRIDGE_DELAY; | ||
| 2479 | u32 ulHiI2cPatch = 0; | ||
| 2480 | u32 ulEnvironment = APPENV_PORTABLE; | ||
| 2481 | u32 ulEnvironmentDiversity = APPENV_MOBILE; | ||
| 2482 | u32 ulIFFilter = IFFILTER_SAW; | ||
| 2483 | |||
| 2484 | state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | ||
| 2485 | state->if_agc_cfg.outputLevel = 0; | ||
| 2486 | state->if_agc_cfg.settleLevel = 140; | ||
| 2487 | state->if_agc_cfg.minOutputLevel = 0; | ||
| 2488 | state->if_agc_cfg.maxOutputLevel = 1023; | ||
| 2489 | state->if_agc_cfg.speed = 904; | ||
| 2490 | |||
| 2491 | if (ulIfAgcMode == 1 && ulIfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { | ||
| 2492 | state->if_agc_cfg.ctrlMode = AGC_CTRL_USER; | ||
| 2493 | state->if_agc_cfg.outputLevel = (u16) (ulIfAgcOutputLevel); | ||
| 2494 | } | ||
| 2495 | |||
| 2496 | if (ulIfAgcMode == 0 && | ||
| 2497 | ulIfAgcSettleLevel <= DRXD_FE_CTRL_MAX && | ||
| 2498 | ulIfAgcMinLevel <= DRXD_FE_CTRL_MAX && | ||
| 2499 | ulIfAgcMaxLevel <= DRXD_FE_CTRL_MAX && | ||
| 2500 | ulIfAgcSpeed <= DRXD_FE_CTRL_MAX) { | ||
| 2501 | state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | ||
| 2502 | state->if_agc_cfg.settleLevel = (u16) (ulIfAgcSettleLevel); | ||
| 2503 | state->if_agc_cfg.minOutputLevel = (u16) (ulIfAgcMinLevel); | ||
| 2504 | state->if_agc_cfg.maxOutputLevel = (u16) (ulIfAgcMaxLevel); | ||
| 2505 | state->if_agc_cfg.speed = (u16) (ulIfAgcSpeed); | ||
| 2506 | } | ||
| 2507 | |||
| 2508 | state->if_agc_cfg.R1 = (u16) (ulIfAgcR1); | ||
| 2509 | state->if_agc_cfg.R2 = (u16) (ulIfAgcR2); | ||
| 2510 | state->if_agc_cfg.R3 = (u16) (ulIfAgcR3); | ||
| 2511 | |||
| 2512 | state->rf_agc_cfg.R1 = (u16) (ulRfAgcR1); | ||
| 2513 | state->rf_agc_cfg.R2 = (u16) (ulRfAgcR2); | ||
| 2514 | state->rf_agc_cfg.R3 = (u16) (ulRfAgcR3); | ||
| 2515 | |||
| 2516 | state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | ||
| 2517 | /* rest of the RFAgcCfg structure currently unused */ | ||
| 2518 | if (ulRfAgcMode == 1 && ulRfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { | ||
| 2519 | state->rf_agc_cfg.ctrlMode = AGC_CTRL_USER; | ||
| 2520 | state->rf_agc_cfg.outputLevel = (u16) (ulRfAgcOutputLevel); | ||
| 2521 | } | ||
| 2522 | |||
| 2523 | if (ulRfAgcMode == 0 && | ||
| 2524 | ulRfAgcSettleLevel <= DRXD_FE_CTRL_MAX && | ||
| 2525 | ulRfAgcMinLevel <= DRXD_FE_CTRL_MAX && | ||
| 2526 | ulRfAgcMaxLevel <= DRXD_FE_CTRL_MAX && | ||
| 2527 | ulRfAgcSpeed <= DRXD_FE_CTRL_MAX) { | ||
| 2528 | state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | ||
| 2529 | state->rf_agc_cfg.settleLevel = (u16) (ulRfAgcSettleLevel); | ||
| 2530 | state->rf_agc_cfg.minOutputLevel = (u16) (ulRfAgcMinLevel); | ||
| 2531 | state->rf_agc_cfg.maxOutputLevel = (u16) (ulRfAgcMaxLevel); | ||
| 2532 | state->rf_agc_cfg.speed = (u16) (ulRfAgcSpeed); | ||
| 2533 | } | ||
| 2534 | |||
| 2535 | if (ulRfAgcMode == 2) | ||
| 2536 | state->rf_agc_cfg.ctrlMode = AGC_CTRL_OFF; | ||
| 2537 | |||
| 2538 | if (ulEnvironment <= 2) | ||
| 2539 | state->app_env_default = (enum app_env) | ||
| 2540 | (ulEnvironment); | ||
| 2541 | if (ulEnvironmentDiversity <= 2) | ||
| 2542 | state->app_env_diversity = (enum app_env) | ||
| 2543 | (ulEnvironmentDiversity); | ||
| 2544 | |||
| 2545 | if (ulIFFilter == IFFILTER_DISCRETE) { | ||
| 2546 | /* discrete filter */ | ||
| 2547 | state->noise_cal.cpOpt = 0; | ||
| 2548 | state->noise_cal.cpNexpOfs = 40; | ||
| 2549 | state->noise_cal.tdCal2k = -40; | ||
| 2550 | state->noise_cal.tdCal8k = -24; | ||
| 2551 | } else { | ||
| 2552 | /* SAW filter */ | ||
| 2553 | state->noise_cal.cpOpt = 1; | ||
| 2554 | state->noise_cal.cpNexpOfs = 0; | ||
| 2555 | state->noise_cal.tdCal2k = -21; | ||
| 2556 | state->noise_cal.tdCal8k = -24; | ||
| 2557 | } | ||
| 2558 | state->m_EcOcRegOcModeLop = (u16) (ulEcOcRegOcModeLop); | ||
| 2559 | |||
| 2560 | state->chip_adr = (state->config.demod_address << 1) | 1; | ||
| 2561 | switch (ulHiI2cPatch) { | ||
| 2562 | case 1: | ||
| 2563 | state->m_HiI2cPatch = DRXD_HiI2cPatch_1; | ||
| 2564 | break; | ||
| 2565 | case 3: | ||
| 2566 | state->m_HiI2cPatch = DRXD_HiI2cPatch_3; | ||
| 2567 | break; | ||
| 2568 | default: | ||
| 2569 | state->m_HiI2cPatch = NULL; | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | /* modify tuner and clock attributes */ | ||
| 2573 | state->intermediate_freq = (u16) (IntermediateFrequency / 1000); | ||
| 2574 | /* expected system clock frequency in kHz */ | ||
| 2575 | state->expected_sys_clock_freq = 48000; | ||
| 2576 | /* real system clock frequency in kHz */ | ||
| 2577 | state->sys_clock_freq = 48000; | ||
| 2578 | state->osc_clock_freq = (u16) ulClock; | ||
| 2579 | state->osc_clock_deviation = 0; | ||
| 2580 | state->cscd_state = CSCD_INIT; | ||
| 2581 | state->drxd_state = DRXD_UNINITIALIZED; | ||
| 2582 | |||
| 2583 | state->PGA = 0; | ||
| 2584 | state->type_A = 0; | ||
| 2585 | state->tuner_mirrors = 0; | ||
| 2586 | |||
| 2587 | /* modify MPEG output attributes */ | ||
| 2588 | state->insert_rs_byte = state->config.insert_rs_byte; | ||
| 2589 | state->enable_parallel = (ulSerialMode != 1); | ||
| 2590 | |||
| 2591 | /* Timing div, 250ns/Psys */ | ||
| 2592 | /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */ | ||
| 2593 | |||
| 2594 | state->hi_cfg_timing_div = (u16) ((state->sys_clock_freq / 1000) * | ||
| 2595 | ulHiI2cDelay) / 1000; | ||
| 2596 | /* Bridge delay, uses oscilator clock */ | ||
| 2597 | /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */ | ||
| 2598 | state->hi_cfg_bridge_delay = (u16) ((state->osc_clock_freq / 1000) * | ||
| 2599 | ulHiI2cBridgeDelay) / 1000; | ||
| 2600 | |||
| 2601 | state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; | ||
| 2602 | /* state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; */ | ||
| 2603 | state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; | ||
| 2604 | return 0; | ||
| 2605 | } | ||
| 2606 | |||
| 2607 | int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size) | ||
| 2608 | { | ||
| 2609 | int status = 0; | ||
| 2610 | u32 driverVersion; | ||
| 2611 | |||
| 2612 | if (state->init_done) | ||
| 2613 | return 0; | ||
| 2614 | |||
| 2615 | CDRXD(state, state->config.IF ? state->config.IF : 36000000); | ||
| 2616 | |||
| 2617 | do { | ||
| 2618 | state->operation_mode = OM_Default; | ||
| 2619 | |||
| 2620 | status = SetDeviceTypeId(state); | ||
| 2621 | if (status < 0) | ||
| 2622 | break; | ||
| 2623 | |||
| 2624 | /* Apply I2c address patch to B1 */ | ||
| 2625 | if (!state->type_A && state->m_HiI2cPatch != NULL) | ||
| 2626 | status = WriteTable(state, state->m_HiI2cPatch); | ||
| 2627 | if (status < 0) | ||
| 2628 | break; | ||
| 2629 | |||
| 2630 | if (state->type_A) { | ||
| 2631 | /* HI firmware patch for UIO readout, | ||
| 2632 | avoid clearing of result register */ | ||
| 2633 | status = Write16(state, 0x43012D, 0x047f, 0); | ||
| 2634 | if (status < 0) | ||
| 2635 | break; | ||
| 2636 | } | ||
| 2637 | |||
| 2638 | status = HI_ResetCommand(state); | ||
| 2639 | if (status < 0) | ||
| 2640 | break; | ||
| 2641 | |||
| 2642 | status = StopAllProcessors(state); | ||
| 2643 | if (status < 0) | ||
| 2644 | break; | ||
| 2645 | status = InitCC(state); | ||
| 2646 | if (status < 0) | ||
| 2647 | break; | ||
| 2648 | |||
| 2649 | state->osc_clock_deviation = 0; | ||
| 2650 | |||
| 2651 | if (state->config.osc_deviation) | ||
| 2652 | state->osc_clock_deviation = | ||
| 2653 | state->config.osc_deviation(state->priv, 0, 0); | ||
| 2654 | { | ||
| 2655 | /* Handle clock deviation */ | ||
| 2656 | s32 devB; | ||
| 2657 | s32 devA = (s32) (state->osc_clock_deviation) * | ||
| 2658 | (s32) (state->expected_sys_clock_freq); | ||
| 2659 | /* deviation in kHz */ | ||
| 2660 | s32 deviation = (devA / (1000000L)); | ||
| 2661 | /* rounding, signed */ | ||
| 2662 | if (devA > 0) | ||
| 2663 | devB = (2); | ||
| 2664 | else | ||
| 2665 | devB = (-2); | ||
| 2666 | if ((devB * (devA % 1000000L) > 1000000L)) { | ||
| 2667 | /* add +1 or -1 */ | ||
| 2668 | deviation += (devB / 2); | ||
| 2669 | } | ||
| 2670 | |||
| 2671 | state->sys_clock_freq = | ||
| 2672 | (u16) ((state->expected_sys_clock_freq) + | ||
| 2673 | deviation); | ||
| 2674 | } | ||
| 2675 | status = InitHI(state); | ||
| 2676 | if (status < 0) | ||
| 2677 | break; | ||
| 2678 | status = InitAtomicRead(state); | ||
| 2679 | if (status < 0) | ||
| 2680 | break; | ||
| 2681 | |||
| 2682 | status = EnableAndResetMB(state); | ||
| 2683 | if (status < 0) | ||
| 2684 | break; | ||
| 2685 | if (state->type_A) | ||
| 2686 | status = ResetCEFR(state); | ||
| 2687 | if (status < 0) | ||
| 2688 | break; | ||
| 2689 | |||
| 2690 | if (fw) { | ||
| 2691 | status = DownloadMicrocode(state, fw, fw_size); | ||
| 2692 | if (status < 0) | ||
| 2693 | break; | ||
| 2694 | } else { | ||
| 2695 | status = DownloadMicrocode(state, state->microcode, state->microcode_length); | ||
| 2696 | if (status < 0) | ||
| 2697 | break; | ||
| 2698 | } | ||
| 2699 | |||
| 2700 | if (state->PGA) { | ||
| 2701 | state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; | ||
| 2702 | SetCfgPga(state, 0); /* PGA = 0 dB */ | ||
| 2703 | } else { | ||
| 2704 | state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; | ||
| 2705 | } | ||
| 2706 | |||
| 2707 | state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; | ||
| 2708 | |||
| 2709 | status = InitFE(state); | ||
| 2710 | if (status < 0) | ||
| 2711 | break; | ||
| 2712 | status = InitFT(state); | ||
| 2713 | if (status < 0) | ||
| 2714 | break; | ||
| 2715 | status = InitCP(state); | ||
| 2716 | if (status < 0) | ||
| 2717 | break; | ||
| 2718 | status = InitCE(state); | ||
| 2719 | if (status < 0) | ||
| 2720 | break; | ||
| 2721 | status = InitEQ(state); | ||
| 2722 | if (status < 0) | ||
| 2723 | break; | ||
| 2724 | status = InitEC(state); | ||
| 2725 | if (status < 0) | ||
| 2726 | break; | ||
| 2727 | status = InitSC(state); | ||
| 2728 | if (status < 0) | ||
| 2729 | break; | ||
| 2730 | |||
| 2731 | status = SetCfgIfAgc(state, &state->if_agc_cfg); | ||
| 2732 | if (status < 0) | ||
| 2733 | break; | ||
| 2734 | status = SetCfgRfAgc(state, &state->rf_agc_cfg); | ||
| 2735 | if (status < 0) | ||
| 2736 | break; | ||
| 2737 | |||
| 2738 | state->cscd_state = CSCD_INIT; | ||
| 2739 | status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 2740 | if (status < 0) | ||
| 2741 | break; | ||
| 2742 | status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | ||
| 2743 | if (status < 0) | ||
| 2744 | break; | ||
| 2745 | |||
| 2746 | driverVersion = (((VERSION_MAJOR / 10) << 4) + | ||
| 2747 | (VERSION_MAJOR % 10)) << 24; | ||
| 2748 | driverVersion += (((VERSION_MINOR / 10) << 4) + | ||
| 2749 | (VERSION_MINOR % 10)) << 16; | ||
| 2750 | driverVersion += ((VERSION_PATCH / 1000) << 12) + | ||
| 2751 | ((VERSION_PATCH / 100) << 8) + | ||
| 2752 | ((VERSION_PATCH / 10) << 4) + (VERSION_PATCH % 10); | ||
| 2753 | |||
| 2754 | status = Write32(state, SC_RA_RAM_DRIVER_VERSION__AX, driverVersion, 0); | ||
| 2755 | if (status < 0) | ||
| 2756 | break; | ||
| 2757 | |||
| 2758 | status = StopOC(state); | ||
| 2759 | if (status < 0) | ||
| 2760 | break; | ||
| 2761 | |||
| 2762 | state->drxd_state = DRXD_STOPPED; | ||
| 2763 | state->init_done = 1; | ||
| 2764 | status = 0; | ||
| 2765 | } while (0); | ||
| 2766 | return status; | ||
| 2767 | } | ||
| 2768 | |||
| 2769 | int DRXD_status(struct drxd_state *state, u32 * pLockStatus) | ||
| 2770 | { | ||
| 2771 | DRX_GetLockStatus(state, pLockStatus); | ||
| 2772 | |||
| 2773 | /*if (*pLockStatus&DRX_LOCK_MPEG) */ | ||
| 2774 | if (*pLockStatus & DRX_LOCK_FEC) { | ||
| 2775 | ConfigureMPEGOutput(state, 1); | ||
| 2776 | /* Get status again, in case we have MPEG lock now */ | ||
| 2777 | /*DRX_GetLockStatus(state, pLockStatus); */ | ||
| 2778 | } | ||
| 2779 | |||
| 2780 | return 0; | ||
| 2781 | } | ||
| 2782 | |||
| 2783 | /****************************************************************************/ | ||
| 2784 | /****************************************************************************/ | ||
| 2785 | /****************************************************************************/ | ||
| 2786 | |||
| 2787 | static int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | ||
| 2788 | { | ||
| 2789 | struct drxd_state *state = fe->demodulator_priv; | ||
| 2790 | u32 value; | ||
| 2791 | int res; | ||
| 2792 | |||
| 2793 | res = ReadIFAgc(state, &value); | ||
| 2794 | if (res < 0) | ||
| 2795 | *strength = 0; | ||
| 2796 | else | ||
| 2797 | *strength = 0xffff - (value << 4); | ||
| 2798 | return 0; | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status) | ||
| 2802 | { | ||
| 2803 | struct drxd_state *state = fe->demodulator_priv; | ||
| 2804 | u32 lock; | ||
| 2805 | |||
| 2806 | DRXD_status(state, &lock); | ||
| 2807 | *status = 0; | ||
| 2808 | /* No MPEG lock in V255 firmware, bug ? */ | ||
| 2809 | #if 1 | ||
| 2810 | if (lock & DRX_LOCK_MPEG) | ||
| 2811 | *status |= FE_HAS_LOCK; | ||
| 2812 | #else | ||
| 2813 | if (lock & DRX_LOCK_FEC) | ||
| 2814 | *status |= FE_HAS_LOCK; | ||
| 2815 | #endif | ||
| 2816 | if (lock & DRX_LOCK_FEC) | ||
| 2817 | *status |= FE_HAS_VITERBI | FE_HAS_SYNC; | ||
| 2818 | if (lock & DRX_LOCK_DEMOD) | ||
| 2819 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||
| 2820 | |||
| 2821 | return 0; | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | static int drxd_init(struct dvb_frontend *fe) | ||
| 2825 | { | ||
| 2826 | struct drxd_state *state = fe->demodulator_priv; | ||
| 2827 | int err = 0; | ||
| 2828 | |||
| 2829 | /* if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */ | ||
| 2830 | return DRXD_init(state, 0, 0); | ||
| 2831 | |||
| 2832 | err = DRXD_init(state, state->fw->data, state->fw->size); | ||
| 2833 | release_firmware(state->fw); | ||
| 2834 | return err; | ||
| 2835 | } | ||
| 2836 | |||
| 2837 | int drxd_config_i2c(struct dvb_frontend *fe, int onoff) | ||
| 2838 | { | ||
| 2839 | struct drxd_state *state = fe->demodulator_priv; | ||
| 2840 | |||
| 2841 | if (state->config.disable_i2c_gate_ctrl == 1) | ||
| 2842 | return 0; | ||
| 2843 | |||
| 2844 | return DRX_ConfigureI2CBridge(state, onoff); | ||
| 2845 | } | ||
| 2846 | EXPORT_SYMBOL(drxd_config_i2c); | ||
| 2847 | |||
| 2848 | static int drxd_get_tune_settings(struct dvb_frontend *fe, | ||
| 2849 | struct dvb_frontend_tune_settings *sets) | ||
| 2850 | { | ||
| 2851 | sets->min_delay_ms = 10000; | ||
| 2852 | sets->max_drift = 0; | ||
| 2853 | sets->step_size = 0; | ||
| 2854 | return 0; | ||
| 2855 | } | ||
| 2856 | |||
| 2857 | static int drxd_read_ber(struct dvb_frontend *fe, u32 * ber) | ||
| 2858 | { | ||
| 2859 | *ber = 0; | ||
| 2860 | return 0; | ||
| 2861 | } | ||
| 2862 | |||
| 2863 | static int drxd_read_snr(struct dvb_frontend *fe, u16 * snr) | ||
| 2864 | { | ||
| 2865 | *snr = 0; | ||
| 2866 | return 0; | ||
| 2867 | } | ||
| 2868 | |||
| 2869 | static int drxd_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) | ||
| 2870 | { | ||
| 2871 | *ucblocks = 0; | ||
| 2872 | return 0; | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | static int drxd_sleep(struct dvb_frontend *fe) | ||
| 2876 | { | ||
| 2877 | struct drxd_state *state = fe->demodulator_priv; | ||
| 2878 | |||
| 2879 | ConfigureMPEGOutput(state, 0); | ||
| 2880 | return 0; | ||
| 2881 | } | ||
| 2882 | |||
| 2883 | static int drxd_get_frontend(struct dvb_frontend *fe, | ||
| 2884 | struct dvb_frontend_parameters *param) | ||
| 2885 | { | ||
| 2886 | return 0; | ||
| 2887 | } | ||
| 2888 | |||
| 2889 | static int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
| 2890 | { | ||
| 2891 | return drxd_config_i2c(fe, enable); | ||
| 2892 | } | ||
| 2893 | |||
| 2894 | static int drxd_set_frontend(struct dvb_frontend *fe, | ||
| 2895 | struct dvb_frontend_parameters *param) | ||
| 2896 | { | ||
| 2897 | struct drxd_state *state = fe->demodulator_priv; | ||
| 2898 | s32 off = 0; | ||
| 2899 | |||
| 2900 | state->param = *param; | ||
| 2901 | DRX_Stop(state); | ||
| 2902 | |||
| 2903 | if (fe->ops.tuner_ops.set_params) { | ||
| 2904 | fe->ops.tuner_ops.set_params(fe, param); | ||
| 2905 | if (fe->ops.i2c_gate_ctrl) | ||
| 2906 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 2907 | } | ||
| 2908 | |||
| 2909 | /* FIXME: move PLL drivers */ | ||
| 2910 | if (state->config.pll_set && | ||
| 2911 | state->config.pll_set(state->priv, param, | ||
| 2912 | state->config.pll_address, | ||
| 2913 | state->config.demoda_address, &off) < 0) { | ||
| 2914 | printk(KERN_ERR "Error in pll_set\n"); | ||
| 2915 | return -1; | ||
| 2916 | } | ||
| 2917 | |||
| 2918 | msleep(200); | ||
| 2919 | |||
| 2920 | return DRX_Start(state, off); | ||
| 2921 | } | ||
| 2922 | |||
| 2923 | static void drxd_release(struct dvb_frontend *fe) | ||
| 2924 | { | ||
| 2925 | struct drxd_state *state = fe->demodulator_priv; | ||
| 2926 | |||
| 2927 | kfree(state); | ||
| 2928 | } | ||
| 2929 | |||
| 2930 | static struct dvb_frontend_ops drxd_ops = { | ||
| 2931 | |||
| 2932 | .info = { | ||
| 2933 | .name = "Micronas DRXD DVB-T", | ||
| 2934 | .type = FE_OFDM, | ||
| 2935 | .frequency_min = 47125000, | ||
| 2936 | .frequency_max = 855250000, | ||
| 2937 | .frequency_stepsize = 166667, | ||
| 2938 | .frequency_tolerance = 0, | ||
| 2939 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | ||
| 2940 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | ||
| 2941 | FE_CAN_FEC_AUTO | | ||
| 2942 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||
| 2943 | FE_CAN_QAM_AUTO | | ||
| 2944 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 2945 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 2946 | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS}, | ||
| 2947 | |||
| 2948 | .release = drxd_release, | ||
| 2949 | .init = drxd_init, | ||
| 2950 | .sleep = drxd_sleep, | ||
| 2951 | .i2c_gate_ctrl = drxd_i2c_gate_ctrl, | ||
| 2952 | |||
| 2953 | .set_frontend = drxd_set_frontend, | ||
| 2954 | .get_frontend = drxd_get_frontend, | ||
| 2955 | .get_tune_settings = drxd_get_tune_settings, | ||
| 2956 | |||
| 2957 | .read_status = drxd_read_status, | ||
| 2958 | .read_ber = drxd_read_ber, | ||
| 2959 | .read_signal_strength = drxd_read_signal_strength, | ||
| 2960 | .read_snr = drxd_read_snr, | ||
| 2961 | .read_ucblocks = drxd_read_ucblocks, | ||
| 2962 | }; | ||
| 2963 | |||
| 2964 | struct dvb_frontend *drxd_attach(const struct drxd_config *config, | ||
| 2965 | void *priv, struct i2c_adapter *i2c, | ||
| 2966 | struct device *dev) | ||
| 2967 | { | ||
| 2968 | struct drxd_state *state = NULL; | ||
| 2969 | |||
| 2970 | state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL); | ||
| 2971 | if (!state) | ||
| 2972 | return NULL; | ||
| 2973 | memset(state, 0, sizeof(*state)); | ||
| 2974 | |||
| 2975 | memcpy(&state->ops, &drxd_ops, sizeof(struct dvb_frontend_ops)); | ||
| 2976 | state->dev = dev; | ||
| 2977 | state->config = *config; | ||
| 2978 | state->i2c = i2c; | ||
| 2979 | state->priv = priv; | ||
| 2980 | |||
| 2981 | mutex_init(&state->mutex); | ||
| 2982 | |||
| 2983 | if (Read16(state, 0, 0, 0) < 0) | ||
| 2984 | goto error; | ||
| 2985 | |||
| 2986 | memcpy(&state->frontend.ops, &drxd_ops, | ||
| 2987 | sizeof(struct dvb_frontend_ops)); | ||
| 2988 | state->frontend.demodulator_priv = state; | ||
| 2989 | ConfigureMPEGOutput(state, 0); | ||
| 2990 | return &state->frontend; | ||
| 2991 | |||
| 2992 | error: | ||
| 2993 | printk(KERN_ERR "drxd: not found\n"); | ||
| 2994 | kfree(state); | ||
| 2995 | return NULL; | ||
| 2996 | } | ||
| 2997 | EXPORT_SYMBOL(drxd_attach); | ||
| 2998 | |||
| 2999 | MODULE_DESCRIPTION("DRXD driver"); | ||
| 3000 | MODULE_AUTHOR("Micronas"); | ||
| 3001 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/drxd_map_firm.h b/drivers/media/dvb/frontends/drxd_map_firm.h new file mode 100644 index 000000000000..6bc553abf215 --- /dev/null +++ b/drivers/media/dvb/frontends/drxd_map_firm.h | |||
| @@ -0,0 +1,1013 @@ | |||
| 1 | /* | ||
| 2 | * drx3973d_map_firm.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006-2007 Micronas | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 only, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 20 | * 02110-1301, USA | ||
| 21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef __DRX3973D_MAP__H__ | ||
| 25 | #define __DRX3973D_MAP__H__ | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Note: originally, this file contained 12000+ lines of data | ||
| 29 | * Probably a few lines for every firwmare assembler instruction. However, | ||
| 30 | * only a few defines were actually used. So, removed all uneeded lines. | ||
| 31 | * If ever needed, the other lines can be easily obtained via git history. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define HI_COMM_EXEC__A 0x400000 | ||
| 35 | #define HI_COMM_MB__A 0x400002 | ||
| 36 | #define HI_CT_REG_COMM_STATE__A 0x410001 | ||
| 37 | #define HI_RA_RAM_SRV_RES__A 0x420031 | ||
| 38 | #define HI_RA_RAM_SRV_CMD__A 0x420032 | ||
| 39 | #define HI_RA_RAM_SRV_CMD_RESET 0x2 | ||
| 40 | #define HI_RA_RAM_SRV_CMD_CONFIG 0x3 | ||
| 41 | #define HI_RA_RAM_SRV_CMD_EXECUTE 0x6 | ||
| 42 | #define HI_RA_RAM_SRV_RST_KEY__A 0x420033 | ||
| 43 | #define HI_RA_RAM_SRV_RST_KEY_ACT 0x3973 | ||
| 44 | #define HI_RA_RAM_SRV_CFG_KEY__A 0x420033 | ||
| 45 | #define HI_RA_RAM_SRV_CFG_DIV__A 0x420034 | ||
| 46 | #define HI_RA_RAM_SRV_CFG_BDL__A 0x420035 | ||
| 47 | #define HI_RA_RAM_SRV_CFG_WUP__A 0x420036 | ||
| 48 | #define HI_RA_RAM_SRV_CFG_ACT__A 0x420037 | ||
| 49 | #define HI_RA_RAM_SRV_CFG_ACT_SLV0_ON 0x1 | ||
| 50 | #define HI_RA_RAM_SRV_CFG_ACT_BRD__M 0x4 | ||
| 51 | #define HI_RA_RAM_SRV_CFG_ACT_BRD_OFF 0x0 | ||
| 52 | #define HI_RA_RAM_SRV_CFG_ACT_BRD_ON 0x4 | ||
| 53 | #define HI_RA_RAM_SRV_CFG_ACT_PWD_EXE 0x8 | ||
| 54 | #define HI_RA_RAM_USR_BEGIN__A 0x420040 | ||
| 55 | #define HI_IF_RAM_TRP_BPT0__AX 0x430000 | ||
| 56 | #define HI_IF_RAM_USR_BEGIN__A 0x430200 | ||
| 57 | #define SC_COMM_EXEC__A 0x800000 | ||
| 58 | #define SC_COMM_EXEC_CTL_STOP 0x0 | ||
| 59 | #define SC_COMM_STATE__A 0x800001 | ||
| 60 | #define SC_RA_RAM_PARAM0__A 0x820040 | ||
| 61 | #define SC_RA_RAM_PARAM1__A 0x820041 | ||
| 62 | #define SC_RA_RAM_CMD_ADDR__A 0x820042 | ||
| 63 | #define SC_RA_RAM_CMD__A 0x820043 | ||
| 64 | #define SC_RA_RAM_CMD_PROC_START 0x1 | ||
| 65 | #define SC_RA_RAM_CMD_SET_PREF_PARAM 0x3 | ||
| 66 | #define SC_RA_RAM_CMD_GET_OP_PARAM 0x5 | ||
| 67 | #define SC_RA_RAM_SW_EVENT_RUN_NMASK__M 0x1 | ||
| 68 | #define SC_RA_RAM_LOCKTRACK_MIN 0x1 | ||
| 69 | #define SC_RA_RAM_OP_PARAM_MODE_2K 0x0 | ||
| 70 | #define SC_RA_RAM_OP_PARAM_MODE_8K 0x1 | ||
| 71 | #define SC_RA_RAM_OP_PARAM_GUARD_32 0x0 | ||
| 72 | #define SC_RA_RAM_OP_PARAM_GUARD_16 0x4 | ||
| 73 | #define SC_RA_RAM_OP_PARAM_GUARD_8 0x8 | ||
| 74 | #define SC_RA_RAM_OP_PARAM_GUARD_4 0xC | ||
| 75 | #define SC_RA_RAM_OP_PARAM_CONST_QPSK 0x0 | ||
| 76 | #define SC_RA_RAM_OP_PARAM_CONST_QAM16 0x10 | ||
| 77 | #define SC_RA_RAM_OP_PARAM_CONST_QAM64 0x20 | ||
| 78 | #define SC_RA_RAM_OP_PARAM_HIER_NO 0x0 | ||
| 79 | #define SC_RA_RAM_OP_PARAM_HIER_A1 0x40 | ||
| 80 | #define SC_RA_RAM_OP_PARAM_HIER_A2 0x80 | ||
| 81 | #define SC_RA_RAM_OP_PARAM_HIER_A4 0xC0 | ||
| 82 | #define SC_RA_RAM_OP_PARAM_RATE_1_2 0x0 | ||
| 83 | #define SC_RA_RAM_OP_PARAM_RATE_2_3 0x200 | ||
| 84 | #define SC_RA_RAM_OP_PARAM_RATE_3_4 0x400 | ||
| 85 | #define SC_RA_RAM_OP_PARAM_RATE_5_6 0x600 | ||
| 86 | #define SC_RA_RAM_OP_PARAM_RATE_7_8 0x800 | ||
| 87 | #define SC_RA_RAM_OP_PARAM_PRIO_HI 0x0 | ||
| 88 | #define SC_RA_RAM_OP_PARAM_PRIO_LO 0x1000 | ||
| 89 | #define SC_RA_RAM_OP_AUTO_MODE__M 0x1 | ||
| 90 | #define SC_RA_RAM_OP_AUTO_GUARD__M 0x2 | ||
| 91 | #define SC_RA_RAM_OP_AUTO_CONST__M 0x4 | ||
| 92 | #define SC_RA_RAM_OP_AUTO_HIER__M 0x8 | ||
| 93 | #define SC_RA_RAM_OP_AUTO_RATE__M 0x10 | ||
| 94 | #define SC_RA_RAM_LOCK__A 0x82004B | ||
| 95 | #define SC_RA_RAM_LOCK_DEMOD__M 0x1 | ||
| 96 | #define SC_RA_RAM_LOCK_FEC__M 0x2 | ||
| 97 | #define SC_RA_RAM_LOCK_MPEG__M 0x4 | ||
| 98 | #define SC_RA_RAM_BE_OPT_ENA__A 0x82004C | ||
| 99 | #define SC_RA_RAM_BE_OPT_ENA_CP_OPT 0x1 | ||
| 100 | #define SC_RA_RAM_BE_OPT_DELAY__A 0x82004D | ||
| 101 | #define SC_RA_RAM_CONFIG__A 0x820050 | ||
| 102 | #define SC_RA_RAM_CONFIG_FR_ENABLE__M 0x4 | ||
| 103 | #define SC_RA_RAM_CONFIG_FREQSCAN__M 0x10 | ||
| 104 | #define SC_RA_RAM_CONFIG_SLAVE__M 0x20 | ||
| 105 | #define SC_RA_RAM_IF_SAVE__AX 0x82008E | ||
| 106 | #define SC_RA_RAM_IR_COARSE_2K_LENGTH__A 0x8200D1 | ||
| 107 | #define SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE 0x9 | ||
| 108 | #define SC_RA_RAM_IR_COARSE_2K_FREQINC__A 0x8200D2 | ||
| 109 | #define SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE 0x4 | ||
| 110 | #define SC_RA_RAM_IR_COARSE_2K_KAISINC__A 0x8200D3 | ||
| 111 | #define SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE 0x100 | ||
| 112 | #define SC_RA_RAM_IR_COARSE_8K_LENGTH__A 0x8200D4 | ||
| 113 | #define SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE 0x8 | ||
| 114 | #define SC_RA_RAM_IR_COARSE_8K_FREQINC__A 0x8200D5 | ||
| 115 | #define SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE 0x8 | ||
| 116 | #define SC_RA_RAM_IR_COARSE_8K_KAISINC__A 0x8200D6 | ||
| 117 | #define SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE 0x200 | ||
| 118 | #define SC_RA_RAM_IR_FINE_2K_LENGTH__A 0x8200D7 | ||
| 119 | #define SC_RA_RAM_IR_FINE_2K_LENGTH__PRE 0x9 | ||
| 120 | #define SC_RA_RAM_IR_FINE_2K_FREQINC__A 0x8200D8 | ||
| 121 | #define SC_RA_RAM_IR_FINE_2K_FREQINC__PRE 0x4 | ||
| 122 | #define SC_RA_RAM_IR_FINE_2K_KAISINC__A 0x8200D9 | ||
| 123 | #define SC_RA_RAM_IR_FINE_2K_KAISINC__PRE 0x100 | ||
| 124 | #define SC_RA_RAM_IR_FINE_8K_LENGTH__A 0x8200DA | ||
| 125 | #define SC_RA_RAM_IR_FINE_8K_LENGTH__PRE 0xB | ||
| 126 | #define SC_RA_RAM_IR_FINE_8K_FREQINC__A 0x8200DB | ||
| 127 | #define SC_RA_RAM_IR_FINE_8K_FREQINC__PRE 0x1 | ||
| 128 | #define SC_RA_RAM_IR_FINE_8K_KAISINC__A 0x8200DC | ||
| 129 | #define SC_RA_RAM_IR_FINE_8K_KAISINC__PRE 0x40 | ||
| 130 | #define SC_RA_RAM_ECHO_SHIFT_LIM__A 0x8200DD | ||
| 131 | #define SC_RA_RAM_SAMPLE_RATE_COUNT__A 0x8200E8 | ||
| 132 | #define SC_RA_RAM_SAMPLE_RATE_STEP__A 0x8200E9 | ||
| 133 | #define SC_RA_RAM_BAND__A 0x8200EC | ||
| 134 | #define SC_RA_RAM_LC_ABS_2K__A 0x8200F4 | ||
| 135 | #define SC_RA_RAM_LC_ABS_2K__PRE 0x1F | ||
| 136 | #define SC_RA_RAM_LC_ABS_8K__A 0x8200F5 | ||
| 137 | #define SC_RA_RAM_LC_ABS_8K__PRE 0x1F | ||
| 138 | #define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE 0x1D6 | ||
| 139 | #define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE 0x4 | ||
| 140 | #define SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE 0x1BB | ||
| 141 | #define SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE 0x5 | ||
| 142 | #define SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE 0x1EF | ||
| 143 | #define SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE 0x5 | ||
| 144 | #define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE 0x15E | ||
| 145 | #define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE 0x5 | ||
| 146 | #define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE 0x11A | ||
| 147 | #define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE 0x6 | ||
| 148 | #define SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE 0x1FB | ||
| 149 | #define SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE 0x5 | ||
| 150 | #define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE 0x12F | ||
| 151 | #define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE 0x5 | ||
| 152 | #define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE 0x197 | ||
| 153 | #define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE 0x5 | ||
| 154 | #define SC_RA_RAM_DRIVER_VERSION__AX 0x8201FE | ||
| 155 | #define SC_RA_RAM_PROC_LOCKTRACK 0x0 | ||
| 156 | #define FE_COMM_EXEC__A 0xC00000 | ||
| 157 | #define FE_AD_REG_COMM_EXEC__A 0xC10000 | ||
| 158 | #define FE_AD_REG_FDB_IN__A 0xC10012 | ||
| 159 | #define FE_AD_REG_PD__A 0xC10013 | ||
| 160 | #define FE_AD_REG_INVEXT__A 0xC10014 | ||
| 161 | #define FE_AD_REG_CLKNEG__A 0xC10015 | ||
| 162 | #define FE_AG_REG_COMM_EXEC__A 0xC20000 | ||
| 163 | #define FE_AG_REG_AG_MODE_LOP__A 0xC20010 | ||
| 164 | #define FE_AG_REG_AG_MODE_LOP_MODE_4__M 0x10 | ||
| 165 | #define FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC 0x0 | ||
| 166 | #define FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC 0x10 | ||
| 167 | #define FE_AG_REG_AG_MODE_LOP_MODE_5__M 0x20 | ||
| 168 | #define FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC 0x0 | ||
| 169 | #define FE_AG_REG_AG_MODE_LOP_MODE_C__M 0x1000 | ||
| 170 | #define FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC 0x0 | ||
| 171 | #define FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC 0x1000 | ||
| 172 | #define FE_AG_REG_AG_MODE_LOP_MODE_E__M 0x4000 | ||
| 173 | #define FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC 0x0 | ||
| 174 | #define FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC 0x4000 | ||
| 175 | #define FE_AG_REG_AG_MODE_HIP__A 0xC20011 | ||
| 176 | #define FE_AG_REG_AG_PGA_MODE__A 0xC20012 | ||
| 177 | #define FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN 0x0 | ||
| 178 | #define FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN 0x1 | ||
| 179 | #define FE_AG_REG_AG_AGC_SIO__A 0xC20013 | ||
| 180 | #define FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M 0x2 | ||
| 181 | #define FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT 0x0 | ||
| 182 | #define FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT 0x2 | ||
| 183 | #define FE_AG_REG_AG_PWD__A 0xC20015 | ||
| 184 | #define FE_AG_REG_AG_PWD_PWD_PD2__M 0x2 | ||
| 185 | #define FE_AG_REG_AG_PWD_PWD_PD2_DISABLE 0x0 | ||
| 186 | #define FE_AG_REG_AG_PWD_PWD_PD2_ENABLE 0x2 | ||
| 187 | #define FE_AG_REG_DCE_AUR_CNT__A 0xC20016 | ||
| 188 | #define FE_AG_REG_DCE_RUR_CNT__A 0xC20017 | ||
| 189 | #define FE_AG_REG_ACE_AUR_CNT__A 0xC2001A | ||
| 190 | #define FE_AG_REG_ACE_RUR_CNT__A 0xC2001B | ||
| 191 | #define FE_AG_REG_CDR_RUR_CNT__A 0xC20020 | ||
| 192 | #define FE_AG_REG_EGC_RUR_CNT__A 0xC20024 | ||
| 193 | #define FE_AG_REG_EGC_SET_LVL__A 0xC20025 | ||
| 194 | #define FE_AG_REG_EGC_SET_LVL__M 0x1FF | ||
| 195 | #define FE_AG_REG_EGC_FLA_RGN__A 0xC20026 | ||
| 196 | #define FE_AG_REG_EGC_SLO_RGN__A 0xC20027 | ||
| 197 | #define FE_AG_REG_EGC_JMP_PSN__A 0xC20028 | ||
| 198 | #define FE_AG_REG_EGC_FLA_INC__A 0xC20029 | ||
| 199 | #define FE_AG_REG_EGC_FLA_DEC__A 0xC2002A | ||
| 200 | #define FE_AG_REG_EGC_SLO_INC__A 0xC2002B | ||
| 201 | #define FE_AG_REG_EGC_SLO_DEC__A 0xC2002C | ||
| 202 | #define FE_AG_REG_EGC_FAS_INC__A 0xC2002D | ||
| 203 | #define FE_AG_REG_EGC_FAS_DEC__A 0xC2002E | ||
| 204 | #define FE_AG_REG_PM1_AGC_WRI__A 0xC20030 | ||
| 205 | #define FE_AG_REG_PM1_AGC_WRI__M 0x7FF | ||
| 206 | #define FE_AG_REG_GC1_AGC_RIC__A 0xC20031 | ||
| 207 | #define FE_AG_REG_GC1_AGC_OFF__A 0xC20032 | ||
| 208 | #define FE_AG_REG_GC1_AGC_MAX__A 0xC20033 | ||
| 209 | #define FE_AG_REG_GC1_AGC_MIN__A 0xC20034 | ||
| 210 | #define FE_AG_REG_GC1_AGC_DAT__A 0xC20035 | ||
| 211 | #define FE_AG_REG_GC1_AGC_DAT__M 0x3FF | ||
| 212 | #define FE_AG_REG_PM2_AGC_WRI__A 0xC20036 | ||
| 213 | #define FE_AG_REG_IND_WIN__A 0xC2003C | ||
| 214 | #define FE_AG_REG_IND_THD_LOL__A 0xC2003D | ||
| 215 | #define FE_AG_REG_IND_THD_HIL__A 0xC2003E | ||
| 216 | #define FE_AG_REG_IND_DEL__A 0xC2003F | ||
| 217 | #define FE_AG_REG_IND_PD1_WRI__A 0xC20040 | ||
| 218 | #define FE_AG_REG_PDA_AUR_CNT__A 0xC20041 | ||
| 219 | #define FE_AG_REG_PDA_RUR_CNT__A 0xC20042 | ||
| 220 | #define FE_AG_REG_PDA_AVE_DAT__A 0xC20043 | ||
| 221 | #define FE_AG_REG_PDC_RUR_CNT__A 0xC20044 | ||
| 222 | #define FE_AG_REG_PDC_SET_LVL__A 0xC20045 | ||
| 223 | #define FE_AG_REG_PDC_FLA_RGN__A 0xC20046 | ||
| 224 | #define FE_AG_REG_PDC_JMP_PSN__A 0xC20047 | ||
| 225 | #define FE_AG_REG_PDC_FLA_STP__A 0xC20048 | ||
| 226 | #define FE_AG_REG_PDC_SLO_STP__A 0xC20049 | ||
| 227 | #define FE_AG_REG_PDC_PD2_WRI__A 0xC2004A | ||
| 228 | #define FE_AG_REG_PDC_MAP_DAT__A 0xC2004B | ||
| 229 | #define FE_AG_REG_PDC_MAX__A 0xC2004C | ||
| 230 | #define FE_AG_REG_TGA_AUR_CNT__A 0xC2004D | ||
| 231 | #define FE_AG_REG_TGA_RUR_CNT__A 0xC2004E | ||
| 232 | #define FE_AG_REG_TGA_AVE_DAT__A 0xC2004F | ||
| 233 | #define FE_AG_REG_TGC_RUR_CNT__A 0xC20050 | ||
| 234 | #define FE_AG_REG_TGC_SET_LVL__A 0xC20051 | ||
| 235 | #define FE_AG_REG_TGC_SET_LVL__M 0x3F | ||
| 236 | #define FE_AG_REG_TGC_FLA_RGN__A 0xC20052 | ||
| 237 | #define FE_AG_REG_TGC_JMP_PSN__A 0xC20053 | ||
| 238 | #define FE_AG_REG_TGC_FLA_STP__A 0xC20054 | ||
| 239 | #define FE_AG_REG_TGC_SLO_STP__A 0xC20055 | ||
| 240 | #define FE_AG_REG_TGC_MAP_DAT__A 0xC20056 | ||
| 241 | #define FE_AG_REG_FGA_AUR_CNT__A 0xC20057 | ||
| 242 | #define FE_AG_REG_FGA_RUR_CNT__A 0xC20058 | ||
| 243 | #define FE_AG_REG_FGM_WRI__A 0xC20061 | ||
| 244 | #define FE_AG_REG_BGC_FGC_WRI__A 0xC20068 | ||
| 245 | #define FE_AG_REG_BGC_CGC_WRI__A 0xC20069 | ||
| 246 | #define FE_FS_REG_COMM_EXEC__A 0xC30000 | ||
| 247 | #define FE_FS_REG_ADD_INC_LOP__A 0xC30010 | ||
| 248 | #define FE_FD_REG_COMM_EXEC__A 0xC40000 | ||
| 249 | #define FE_FD_REG_SCL__A 0xC40010 | ||
| 250 | #define FE_FD_REG_MAX_LEV__A 0xC40011 | ||
| 251 | #define FE_FD_REG_NR__A 0xC40012 | ||
| 252 | #define FE_FD_REG_MEAS_VAL__A 0xC40014 | ||
| 253 | #define FE_IF_REG_COMM_EXEC__A 0xC50000 | ||
| 254 | #define FE_IF_REG_INCR0__A 0xC50010 | ||
| 255 | #define FE_IF_REG_INCR0__W 16 | ||
| 256 | #define FE_IF_REG_INCR0__M 0xFFFF | ||
| 257 | #define FE_IF_REG_INCR1__A 0xC50011 | ||
| 258 | #define FE_IF_REG_INCR1__M 0xFF | ||
| 259 | #define FE_CF_REG_COMM_EXEC__A 0xC60000 | ||
| 260 | #define FE_CF_REG_SCL__A 0xC60010 | ||
| 261 | #define FE_CF_REG_MAX_LEV__A 0xC60011 | ||
| 262 | #define FE_CF_REG_NR__A 0xC60012 | ||
| 263 | #define FE_CF_REG_IMP_VAL__A 0xC60013 | ||
| 264 | #define FE_CF_REG_MEAS_VAL__A 0xC60014 | ||
| 265 | #define FE_CU_REG_COMM_EXEC__A 0xC70000 | ||
| 266 | #define FE_CU_REG_FRM_CNT_RST__A 0xC70011 | ||
| 267 | #define FE_CU_REG_FRM_CNT_STR__A 0xC70012 | ||
| 268 | #define FT_COMM_EXEC__A 0x1000000 | ||
| 269 | #define FT_REG_COMM_EXEC__A 0x1010000 | ||
| 270 | #define CP_COMM_EXEC__A 0x1400000 | ||
| 271 | #define CP_REG_COMM_EXEC__A 0x1410000 | ||
| 272 | #define CP_REG_INTERVAL__A 0x1410011 | ||
| 273 | #define CP_REG_BR_SPL_OFFSET__A 0x1410023 | ||
| 274 | #define CP_REG_BR_STR_DEL__A 0x1410024 | ||
| 275 | #define CP_REG_RT_ANG_INC0__A 0x1410030 | ||
| 276 | #define CP_REG_RT_ANG_INC1__A 0x1410031 | ||
| 277 | #define CP_REG_RT_DETECT_ENA__A 0x1410032 | ||
| 278 | #define CP_REG_RT_DETECT_TRH__A 0x1410033 | ||
| 279 | #define CP_REG_RT_EXP_MARG__A 0x141003E | ||
| 280 | #define CP_REG_AC_NEXP_OFFS__A 0x1410040 | ||
| 281 | #define CP_REG_AC_AVER_POW__A 0x1410041 | ||
| 282 | #define CP_REG_AC_MAX_POW__A 0x1410042 | ||
| 283 | #define CP_REG_AC_WEIGHT_MAN__A 0x1410043 | ||
| 284 | #define CP_REG_AC_WEIGHT_EXP__A 0x1410044 | ||
| 285 | #define CP_REG_AC_AMP_MODE__A 0x1410047 | ||
| 286 | #define CP_REG_AC_AMP_FIX__A 0x1410048 | ||
| 287 | #define CP_REG_AC_ANG_MODE__A 0x141004A | ||
| 288 | #define CE_COMM_EXEC__A 0x1800000 | ||
| 289 | #define CE_REG_COMM_EXEC__A 0x1810000 | ||
| 290 | #define CE_REG_TAPSET__A 0x1810011 | ||
| 291 | #define CE_REG_AVG_POW__A 0x1810012 | ||
| 292 | #define CE_REG_MAX_POW__A 0x1810013 | ||
| 293 | #define CE_REG_ATT__A 0x1810014 | ||
| 294 | #define CE_REG_NRED__A 0x1810015 | ||
| 295 | #define CE_REG_NE_ERR_SELECT__A 0x1810043 | ||
| 296 | #define CE_REG_NE_TD_CAL__A 0x1810044 | ||
| 297 | #define CE_REG_NE_MIXAVG__A 0x1810046 | ||
| 298 | #define CE_REG_NE_NUPD_OFS__A 0x1810047 | ||
| 299 | #define CE_REG_PE_NEXP_OFFS__A 0x1810050 | ||
| 300 | #define CE_REG_PE_TIMESHIFT__A 0x1810051 | ||
| 301 | #define CE_REG_TP_A0_TAP_NEW__A 0x1810064 | ||
| 302 | #define CE_REG_TP_A0_TAP_NEW_VALID__A 0x1810065 | ||
| 303 | #define CE_REG_TP_A0_MU_LMS_STEP__A 0x1810066 | ||
| 304 | #define CE_REG_TP_A1_TAP_NEW__A 0x1810068 | ||
| 305 | #define CE_REG_TP_A1_TAP_NEW_VALID__A 0x1810069 | ||
| 306 | #define CE_REG_TP_A1_MU_LMS_STEP__A 0x181006A | ||
| 307 | #define CE_REG_TI_NEXP_OFFS__A 0x1810070 | ||
| 308 | #define CE_REG_FI_SHT_INCR__A 0x1810090 | ||
| 309 | #define CE_REG_FI_EXP_NORM__A 0x1810091 | ||
| 310 | #define CE_REG_IR_INPUTSEL__A 0x18100A0 | ||
| 311 | #define CE_REG_IR_STARTPOS__A 0x18100A1 | ||
| 312 | #define CE_REG_IR_NEXP_THRES__A 0x18100A2 | ||
| 313 | #define CE_REG_FR_TREAL00__A 0x1820010 | ||
| 314 | #define CE_REG_FR_TIMAG00__A 0x1820011 | ||
| 315 | #define CE_REG_FR_TREAL01__A 0x1820012 | ||
| 316 | #define CE_REG_FR_TIMAG01__A 0x1820013 | ||
| 317 | #define CE_REG_FR_TREAL02__A 0x1820014 | ||
| 318 | #define CE_REG_FR_TIMAG02__A 0x1820015 | ||
| 319 | #define CE_REG_FR_TREAL03__A 0x1820016 | ||
| 320 | #define CE_REG_FR_TIMAG03__A 0x1820017 | ||
| 321 | #define CE_REG_FR_TREAL04__A 0x1820018 | ||
| 322 | #define CE_REG_FR_TIMAG04__A 0x1820019 | ||
| 323 | #define CE_REG_FR_TREAL05__A 0x182001A | ||
| 324 | #define CE_REG_FR_TIMAG05__A 0x182001B | ||
| 325 | #define CE_REG_FR_TREAL06__A 0x182001C | ||
| 326 | #define CE_REG_FR_TIMAG06__A 0x182001D | ||
| 327 | #define CE_REG_FR_TREAL07__A 0x182001E | ||
| 328 | #define CE_REG_FR_TIMAG07__A 0x182001F | ||
| 329 | #define CE_REG_FR_TREAL08__A 0x1820020 | ||
| 330 | #define CE_REG_FR_TIMAG08__A 0x1820021 | ||
| 331 | #define CE_REG_FR_TREAL09__A 0x1820022 | ||
| 332 | #define CE_REG_FR_TIMAG09__A 0x1820023 | ||
| 333 | #define CE_REG_FR_TREAL10__A 0x1820024 | ||
| 334 | #define CE_REG_FR_TIMAG10__A 0x1820025 | ||
| 335 | #define CE_REG_FR_TREAL11__A 0x1820026 | ||
| 336 | #define CE_REG_FR_TIMAG11__A 0x1820027 | ||
| 337 | #define CE_REG_FR_MID_TAP__A 0x1820028 | ||
| 338 | #define CE_REG_FR_SQS_G00__A 0x1820029 | ||
| 339 | #define CE_REG_FR_SQS_G01__A 0x182002A | ||
| 340 | #define CE_REG_FR_SQS_G02__A 0x182002B | ||
| 341 | #define CE_REG_FR_SQS_G03__A 0x182002C | ||
| 342 | #define CE_REG_FR_SQS_G04__A 0x182002D | ||
| 343 | #define CE_REG_FR_SQS_G05__A 0x182002E | ||
| 344 | #define CE_REG_FR_SQS_G06__A 0x182002F | ||
| 345 | #define CE_REG_FR_SQS_G07__A 0x1820030 | ||
| 346 | #define CE_REG_FR_SQS_G08__A 0x1820031 | ||
| 347 | #define CE_REG_FR_SQS_G09__A 0x1820032 | ||
| 348 | #define CE_REG_FR_SQS_G10__A 0x1820033 | ||
| 349 | #define CE_REG_FR_SQS_G11__A 0x1820034 | ||
| 350 | #define CE_REG_FR_SQS_G12__A 0x1820035 | ||
| 351 | #define CE_REG_FR_RIO_G00__A 0x1820036 | ||
| 352 | #define CE_REG_FR_RIO_G01__A 0x1820037 | ||
| 353 | #define CE_REG_FR_RIO_G02__A 0x1820038 | ||
| 354 | #define CE_REG_FR_RIO_G03__A 0x1820039 | ||
| 355 | #define CE_REG_FR_RIO_G04__A 0x182003A | ||
| 356 | #define CE_REG_FR_RIO_G05__A 0x182003B | ||
| 357 | #define CE_REG_FR_RIO_G06__A 0x182003C | ||
| 358 | #define CE_REG_FR_RIO_G07__A 0x182003D | ||
| 359 | #define CE_REG_FR_RIO_G08__A 0x182003E | ||
| 360 | #define CE_REG_FR_RIO_G09__A 0x182003F | ||
| 361 | #define CE_REG_FR_RIO_G10__A 0x1820040 | ||
| 362 | #define CE_REG_FR_MODE__A 0x1820041 | ||
| 363 | #define CE_REG_FR_SQS_TRH__A 0x1820042 | ||
| 364 | #define CE_REG_FR_RIO_GAIN__A 0x1820043 | ||
| 365 | #define CE_REG_FR_BYPASS__A 0x1820044 | ||
| 366 | #define CE_REG_FR_PM_SET__A 0x1820045 | ||
| 367 | #define CE_REG_FR_ERR_SH__A 0x1820046 | ||
| 368 | #define CE_REG_FR_MAN_SH__A 0x1820047 | ||
| 369 | #define CE_REG_FR_TAP_SH__A 0x1820048 | ||
| 370 | #define EQ_COMM_EXEC__A 0x1C00000 | ||
| 371 | #define EQ_REG_COMM_EXEC__A 0x1C10000 | ||
| 372 | #define EQ_REG_COMM_MB__A 0x1C10002 | ||
| 373 | #define EQ_REG_IS_GAIN_MAN__A 0x1C10015 | ||
| 374 | #define EQ_REG_IS_GAIN_EXP__A 0x1C10016 | ||
| 375 | #define EQ_REG_IS_CLIP_EXP__A 0x1C10017 | ||
| 376 | #define EQ_REG_SN_CEGAIN__A 0x1C1002A | ||
| 377 | #define EQ_REG_SN_OFFSET__A 0x1C1002B | ||
| 378 | #define EQ_REG_RC_SEL_CAR__A 0x1C10032 | ||
| 379 | #define EQ_REG_RC_SEL_CAR_INIT 0x0 | ||
| 380 | #define EQ_REG_RC_SEL_CAR_DIV_ON 0x1 | ||
| 381 | #define EQ_REG_RC_SEL_CAR_PASS_A_CC 0x0 | ||
| 382 | #define EQ_REG_RC_SEL_CAR_PASS_B_CE 0x2 | ||
| 383 | #define EQ_REG_RC_SEL_CAR_LOCAL_A_CC 0x0 | ||
| 384 | #define EQ_REG_RC_SEL_CAR_LOCAL_B_CE 0x8 | ||
| 385 | #define EQ_REG_RC_SEL_CAR_MEAS_A_CC 0x0 | ||
| 386 | #define EQ_REG_RC_SEL_CAR_MEAS_B_CE 0x20 | ||
| 387 | #define EQ_REG_OT_CONST__A 0x1C10046 | ||
| 388 | #define EQ_REG_OT_ALPHA__A 0x1C10047 | ||
| 389 | #define EQ_REG_OT_QNT_THRES0__A 0x1C10048 | ||
| 390 | #define EQ_REG_OT_QNT_THRES1__A 0x1C10049 | ||
| 391 | #define EQ_REG_OT_CSI_STEP__A 0x1C1004A | ||
| 392 | #define EQ_REG_OT_CSI_OFFSET__A 0x1C1004B | ||
| 393 | #define EQ_REG_TD_REQ_SMB_CNT__A 0x1C10061 | ||
| 394 | #define EQ_REG_TD_TPS_PWR_OFS__A 0x1C10062 | ||
| 395 | #define EC_SB_REG_COMM_EXEC__A 0x2010000 | ||
| 396 | #define EC_SB_REG_TR_MODE__A 0x2010010 | ||
| 397 | #define EC_SB_REG_TR_MODE_8K 0x0 | ||
| 398 | #define EC_SB_REG_TR_MODE_2K 0x1 | ||
| 399 | #define EC_SB_REG_CONST__A 0x2010011 | ||
| 400 | #define EC_SB_REG_CONST_QPSK 0x0 | ||
| 401 | #define EC_SB_REG_CONST_16QAM 0x1 | ||
| 402 | #define EC_SB_REG_CONST_64QAM 0x2 | ||
| 403 | #define EC_SB_REG_ALPHA__A 0x2010012 | ||
| 404 | #define EC_SB_REG_PRIOR__A 0x2010013 | ||
| 405 | #define EC_SB_REG_PRIOR_HI 0x0 | ||
| 406 | #define EC_SB_REG_PRIOR_LO 0x1 | ||
| 407 | #define EC_SB_REG_CSI_HI__A 0x2010014 | ||
| 408 | #define EC_SB_REG_CSI_LO__A 0x2010015 | ||
| 409 | #define EC_SB_REG_SMB_TGL__A 0x2010016 | ||
| 410 | #define EC_SB_REG_SNR_HI__A 0x2010017 | ||
| 411 | #define EC_SB_REG_SNR_MID__A 0x2010018 | ||
| 412 | #define EC_SB_REG_SNR_LO__A 0x2010019 | ||
| 413 | #define EC_SB_REG_SCALE_MSB__A 0x201001A | ||
| 414 | #define EC_SB_REG_SCALE_BIT2__A 0x201001B | ||
| 415 | #define EC_SB_REG_SCALE_LSB__A 0x201001C | ||
| 416 | #define EC_SB_REG_CSI_OFS__A 0x201001D | ||
| 417 | #define EC_VD_REG_COMM_EXEC__A 0x2090000 | ||
| 418 | #define EC_VD_REG_FORCE__A 0x2090010 | ||
| 419 | #define EC_VD_REG_SET_CODERATE__A 0x2090011 | ||
| 420 | #define EC_VD_REG_SET_CODERATE_C1_2 0x0 | ||
| 421 | #define EC_VD_REG_SET_CODERATE_C2_3 0x1 | ||
| 422 | #define EC_VD_REG_SET_CODERATE_C3_4 0x2 | ||
| 423 | #define EC_VD_REG_SET_CODERATE_C5_6 0x3 | ||
| 424 | #define EC_VD_REG_SET_CODERATE_C7_8 0x4 | ||
| 425 | #define EC_VD_REG_REQ_SMB_CNT__A 0x2090012 | ||
| 426 | #define EC_VD_REG_RLK_ENA__A 0x2090014 | ||
| 427 | #define EC_OD_REG_COMM_EXEC__A 0x2110000 | ||
| 428 | #define EC_OD_REG_SYNC__A 0x2110010 | ||
| 429 | #define EC_OD_DEINT_RAM__A 0x2120000 | ||
| 430 | #define EC_RS_REG_COMM_EXEC__A 0x2130000 | ||
| 431 | #define EC_RS_REG_REQ_PCK_CNT__A 0x2130010 | ||
| 432 | #define EC_RS_REG_VAL__A 0x2130011 | ||
| 433 | #define EC_RS_REG_VAL_PCK 0x1 | ||
| 434 | #define EC_RS_EC_RAM__A 0x2140000 | ||
| 435 | #define EC_OC_REG_COMM_EXEC__A 0x2150000 | ||
| 436 | #define EC_OC_REG_COMM_EXEC_CTL_ACTIVE 0x1 | ||
| 437 | #define EC_OC_REG_COMM_EXEC_CTL_HOLD 0x2 | ||
| 438 | #define EC_OC_REG_COMM_INT_STA__A 0x2150007 | ||
| 439 | #define EC_OC_REG_OC_MODE_LOP__A 0x2150010 | ||
| 440 | #define EC_OC_REG_OC_MODE_LOP_PAR_ENA__M 0x1 | ||
| 441 | #define EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE 0x0 | ||
| 442 | #define EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE 0x1 | ||
| 443 | #define EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M 0x4 | ||
| 444 | #define EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC 0x0 | ||
| 445 | #define EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M 0x80 | ||
| 446 | #define EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL 0x80 | ||
| 447 | #define EC_OC_REG_OC_MODE_HIP__A 0x2150011 | ||
| 448 | #define EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR 0x10 | ||
| 449 | #define EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M 0x200 | ||
| 450 | #define EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE 0x0 | ||
| 451 | #define EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE 0x200 | ||
| 452 | #define EC_OC_REG_OC_MPG_SIO__A 0x2150012 | ||
| 453 | #define EC_OC_REG_OC_MPG_SIO__M 0xFFF | ||
| 454 | #define EC_OC_REG_OC_MON_SIO__A 0x2150013 | ||
| 455 | #define EC_OC_REG_DTO_INC_LOP__A 0x2150014 | ||
| 456 | #define EC_OC_REG_DTO_INC_HIP__A 0x2150015 | ||
| 457 | #define EC_OC_REG_SNC_ISC_LVL__A 0x2150016 | ||
| 458 | #define EC_OC_REG_SNC_ISC_LVL_OSC__M 0xF0 | ||
| 459 | #define EC_OC_REG_TMD_TOP_MODE__A 0x215001D | ||
| 460 | #define EC_OC_REG_TMD_TOP_CNT__A 0x215001E | ||
| 461 | #define EC_OC_REG_TMD_HIL_MAR__A 0x215001F | ||
| 462 | #define EC_OC_REG_TMD_LOL_MAR__A 0x2150020 | ||
| 463 | #define EC_OC_REG_TMD_CUR_CNT__A 0x2150021 | ||
| 464 | #define EC_OC_REG_AVR_ASH_CNT__A 0x2150023 | ||
| 465 | #define EC_OC_REG_AVR_BSH_CNT__A 0x2150024 | ||
| 466 | #define EC_OC_REG_RCN_MODE__A 0x2150027 | ||
| 467 | #define EC_OC_REG_RCN_CRA_LOP__A 0x2150028 | ||
| 468 | #define EC_OC_REG_RCN_CRA_HIP__A 0x2150029 | ||
| 469 | #define EC_OC_REG_RCN_CST_LOP__A 0x215002A | ||
| 470 | #define EC_OC_REG_RCN_CST_HIP__A 0x215002B | ||
| 471 | #define EC_OC_REG_RCN_SET_LVL__A 0x215002C | ||
| 472 | #define EC_OC_REG_RCN_GAI_LVL__A 0x215002D | ||
| 473 | #define EC_OC_REG_RCN_CLP_LOP__A 0x2150032 | ||
| 474 | #define EC_OC_REG_RCN_CLP_HIP__A 0x2150033 | ||
| 475 | #define EC_OC_REG_RCN_MAP_LOP__A 0x2150034 | ||
| 476 | #define EC_OC_REG_RCN_MAP_HIP__A 0x2150035 | ||
| 477 | #define EC_OC_REG_OCR_MPG_UOS__A 0x2150036 | ||
| 478 | #define EC_OC_REG_OCR_MPG_UOS__M 0xFFF | ||
| 479 | #define EC_OC_REG_OCR_MPG_UOS_INIT 0x0 | ||
| 480 | #define EC_OC_REG_OCR_MPG_USR_DAT__A 0x2150038 | ||
| 481 | #define EC_OC_REG_OCR_MON_UOS__A 0x2150039 | ||
| 482 | #define EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE 0x1 | ||
| 483 | #define EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE 0x2 | ||
| 484 | #define EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE 0x4 | ||
| 485 | #define EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE 0x8 | ||
| 486 | #define EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE 0x10 | ||
| 487 | #define EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE 0x20 | ||
| 488 | #define EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE 0x40 | ||
| 489 | #define EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE 0x80 | ||
| 490 | #define EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE 0x100 | ||
| 491 | #define EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE 0x200 | ||
| 492 | #define EC_OC_REG_OCR_MON_UOS_VAL_ENABLE 0x400 | ||
| 493 | #define EC_OC_REG_OCR_MON_UOS_CLK_ENABLE 0x800 | ||
| 494 | #define EC_OC_REG_OCR_MON_WRI__A 0x215003A | ||
| 495 | #define EC_OC_REG_OCR_MON_WRI_INIT 0x0 | ||
| 496 | #define EC_OC_REG_IPR_INV_MPG__A 0x2150045 | ||
| 497 | #define CC_REG_OSC_MODE__A 0x2410010 | ||
| 498 | #define CC_REG_OSC_MODE_M20 0x1 | ||
| 499 | #define CC_REG_PLL_MODE__A 0x2410011 | ||
| 500 | #define CC_REG_PLL_MODE_BYPASS_PLL 0x1 | ||
| 501 | #define CC_REG_PLL_MODE_PUMP_CUR_12 0x14 | ||
| 502 | #define CC_REG_REF_DIVIDE__A 0x2410012 | ||
| 503 | #define CC_REG_PWD_MODE__A 0x2410015 | ||
| 504 | #define CC_REG_PWD_MODE_DOWN_PLL 0x2 | ||
| 505 | #define CC_REG_UPDATE__A 0x2410017 | ||
| 506 | #define CC_REG_UPDATE_KEY 0x3973 | ||
| 507 | #define CC_REG_JTAGID_L__A 0x2410019 | ||
| 508 | #define LC_COMM_EXEC__A 0x2800000 | ||
| 509 | #define LC_RA_RAM_IFINCR_NOM_L__A 0x282000C | ||
| 510 | #define LC_RA_RAM_FILTER_SYM_SET__A 0x282001A | ||
| 511 | #define LC_RA_RAM_FILTER_SYM_SET__PRE 0x3E8 | ||
| 512 | #define LC_RA_RAM_FILTER_CRMM_A__A 0x2820060 | ||
| 513 | #define LC_RA_RAM_FILTER_CRMM_A__PRE 0x4 | ||
| 514 | #define LC_RA_RAM_FILTER_CRMM_B__A 0x2820061 | ||
| 515 | #define LC_RA_RAM_FILTER_CRMM_B__PRE 0x1 | ||
| 516 | #define LC_RA_RAM_FILTER_SRMM_A__A 0x2820068 | ||
| 517 | #define LC_RA_RAM_FILTER_SRMM_A__PRE 0x4 | ||
| 518 | #define LC_RA_RAM_FILTER_SRMM_B__A 0x2820069 | ||
| 519 | #define LC_RA_RAM_FILTER_SRMM_B__PRE 0x1 | ||
| 520 | #define B_HI_COMM_EXEC__A 0x400000 | ||
| 521 | #define B_HI_COMM_MB__A 0x400002 | ||
| 522 | #define B_HI_CT_REG_COMM_STATE__A 0x410001 | ||
| 523 | #define B_HI_RA_RAM_SRV_RES__A 0x420031 | ||
| 524 | #define B_HI_RA_RAM_SRV_CMD__A 0x420032 | ||
| 525 | #define B_HI_RA_RAM_SRV_CMD_RESET 0x2 | ||
| 526 | #define B_HI_RA_RAM_SRV_CMD_CONFIG 0x3 | ||
| 527 | #define B_HI_RA_RAM_SRV_CMD_EXECUTE 0x6 | ||
| 528 | #define B_HI_RA_RAM_SRV_RST_KEY__A 0x420033 | ||
| 529 | #define B_HI_RA_RAM_SRV_RST_KEY_ACT 0x3973 | ||
| 530 | #define B_HI_RA_RAM_SRV_CFG_KEY__A 0x420033 | ||
| 531 | #define B_HI_RA_RAM_SRV_CFG_DIV__A 0x420034 | ||
| 532 | #define B_HI_RA_RAM_SRV_CFG_BDL__A 0x420035 | ||
| 533 | #define B_HI_RA_RAM_SRV_CFG_WUP__A 0x420036 | ||
| 534 | #define B_HI_RA_RAM_SRV_CFG_ACT__A 0x420037 | ||
| 535 | #define B_HI_RA_RAM_SRV_CFG_ACT_SLV0_ON 0x1 | ||
| 536 | #define B_HI_RA_RAM_SRV_CFG_ACT_BRD__M 0x4 | ||
| 537 | #define B_HI_RA_RAM_SRV_CFG_ACT_BRD_OFF 0x0 | ||
| 538 | #define B_HI_RA_RAM_SRV_CFG_ACT_BRD_ON 0x4 | ||
| 539 | #define B_HI_RA_RAM_SRV_CFG_ACT_PWD_EXE 0x8 | ||
| 540 | #define B_HI_RA_RAM_USR_BEGIN__A 0x420040 | ||
| 541 | #define B_HI_IF_RAM_TRP_BPT0__AX 0x430000 | ||
| 542 | #define B_HI_IF_RAM_USR_BEGIN__A 0x430200 | ||
| 543 | #define B_SC_COMM_EXEC__A 0x800000 | ||
| 544 | #define B_SC_COMM_EXEC_CTL_STOP 0x0 | ||
| 545 | #define B_SC_COMM_STATE__A 0x800001 | ||
| 546 | #define B_SC_RA_RAM_PARAM0__A 0x820040 | ||
| 547 | #define B_SC_RA_RAM_PARAM1__A 0x820041 | ||
| 548 | #define B_SC_RA_RAM_CMD_ADDR__A 0x820042 | ||
| 549 | #define B_SC_RA_RAM_CMD__A 0x820043 | ||
| 550 | #define B_SC_RA_RAM_CMD_PROC_START 0x1 | ||
| 551 | #define B_SC_RA_RAM_CMD_SET_PREF_PARAM 0x3 | ||
| 552 | #define B_SC_RA_RAM_CMD_GET_OP_PARAM 0x5 | ||
| 553 | #define B_SC_RA_RAM_SW_EVENT_RUN_NMASK__M 0x1 | ||
| 554 | #define B_SC_RA_RAM_LOCKTRACK_MIN 0x1 | ||
| 555 | #define B_SC_RA_RAM_OP_PARAM_MODE_2K 0x0 | ||
| 556 | #define B_SC_RA_RAM_OP_PARAM_MODE_8K 0x1 | ||
| 557 | #define B_SC_RA_RAM_OP_PARAM_GUARD_32 0x0 | ||
| 558 | #define B_SC_RA_RAM_OP_PARAM_GUARD_16 0x4 | ||
| 559 | #define B_SC_RA_RAM_OP_PARAM_GUARD_8 0x8 | ||
| 560 | #define B_SC_RA_RAM_OP_PARAM_GUARD_4 0xC | ||
| 561 | #define B_SC_RA_RAM_OP_PARAM_CONST_QPSK 0x0 | ||
| 562 | #define B_SC_RA_RAM_OP_PARAM_CONST_QAM16 0x10 | ||
| 563 | #define B_SC_RA_RAM_OP_PARAM_CONST_QAM64 0x20 | ||
| 564 | #define B_SC_RA_RAM_OP_PARAM_HIER_NO 0x0 | ||
| 565 | #define B_SC_RA_RAM_OP_PARAM_HIER_A1 0x40 | ||
| 566 | #define B_SC_RA_RAM_OP_PARAM_HIER_A2 0x80 | ||
| 567 | #define B_SC_RA_RAM_OP_PARAM_HIER_A4 0xC0 | ||
| 568 | #define B_SC_RA_RAM_OP_PARAM_RATE_1_2 0x0 | ||
| 569 | #define B_SC_RA_RAM_OP_PARAM_RATE_2_3 0x200 | ||
| 570 | #define B_SC_RA_RAM_OP_PARAM_RATE_3_4 0x400 | ||
| 571 | #define B_SC_RA_RAM_OP_PARAM_RATE_5_6 0x600 | ||
| 572 | #define B_SC_RA_RAM_OP_PARAM_RATE_7_8 0x800 | ||
| 573 | #define B_SC_RA_RAM_OP_PARAM_PRIO_HI 0x0 | ||
| 574 | #define B_SC_RA_RAM_OP_PARAM_PRIO_LO 0x1000 | ||
| 575 | #define B_SC_RA_RAM_OP_AUTO_MODE__M 0x1 | ||
| 576 | #define B_SC_RA_RAM_OP_AUTO_GUARD__M 0x2 | ||
| 577 | #define B_SC_RA_RAM_OP_AUTO_CONST__M 0x4 | ||
| 578 | #define B_SC_RA_RAM_OP_AUTO_HIER__M 0x8 | ||
| 579 | #define B_SC_RA_RAM_OP_AUTO_RATE__M 0x10 | ||
| 580 | #define B_SC_RA_RAM_LOCK__A 0x82004B | ||
| 581 | #define B_SC_RA_RAM_LOCK_DEMOD__M 0x1 | ||
| 582 | #define B_SC_RA_RAM_LOCK_FEC__M 0x2 | ||
| 583 | #define B_SC_RA_RAM_LOCK_MPEG__M 0x4 | ||
| 584 | #define B_SC_RA_RAM_BE_OPT_ENA__A 0x82004C | ||
| 585 | #define B_SC_RA_RAM_BE_OPT_ENA_CP_OPT 0x1 | ||
| 586 | #define B_SC_RA_RAM_BE_OPT_DELAY__A 0x82004D | ||
| 587 | #define B_SC_RA_RAM_CONFIG__A 0x820050 | ||
| 588 | #define B_SC_RA_RAM_CONFIG_FR_ENABLE__M 0x4 | ||
| 589 | #define B_SC_RA_RAM_CONFIG_FREQSCAN__M 0x10 | ||
| 590 | #define B_SC_RA_RAM_CONFIG_SLAVE__M 0x20 | ||
| 591 | #define B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M 0x200 | ||
| 592 | #define B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M 0x400 | ||
| 593 | #define B_SC_RA_RAM_CO_TD_CAL_2K__A 0x82005D | ||
| 594 | #define B_SC_RA_RAM_CO_TD_CAL_8K__A 0x82005E | ||
| 595 | #define B_SC_RA_RAM_IF_SAVE__AX 0x82008E | ||
| 596 | #define B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A 0x820098 | ||
| 597 | #define B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A 0x820099 | ||
| 598 | #define B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A 0x82009A | ||
| 599 | #define B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A 0x82009B | ||
| 600 | #define B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A 0x82009C | ||
| 601 | #define B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A 0x82009D | ||
| 602 | #define B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A 0x82009E | ||
| 603 | #define B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A 0x82009F | ||
| 604 | #define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A 0x8200D1 | ||
| 605 | #define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE 0x9 | ||
| 606 | #define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A 0x8200D2 | ||
| 607 | #define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE 0x4 | ||
| 608 | #define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A 0x8200D3 | ||
| 609 | #define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE 0x100 | ||
| 610 | #define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A 0x8200D4 | ||
| 611 | #define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE 0x8 | ||
| 612 | #define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A 0x8200D5 | ||
| 613 | #define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE 0x8 | ||
| 614 | #define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A 0x8200D6 | ||
| 615 | #define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE 0x200 | ||
| 616 | #define B_SC_RA_RAM_IR_FINE_2K_LENGTH__A 0x8200D7 | ||
| 617 | #define B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE 0x9 | ||
| 618 | #define B_SC_RA_RAM_IR_FINE_2K_FREQINC__A 0x8200D8 | ||
| 619 | #define B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE 0x4 | ||
| 620 | #define B_SC_RA_RAM_IR_FINE_2K_KAISINC__A 0x8200D9 | ||
| 621 | #define B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE 0x100 | ||
| 622 | #define B_SC_RA_RAM_IR_FINE_8K_LENGTH__A 0x8200DA | ||
| 623 | #define B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE 0xB | ||
| 624 | #define B_SC_RA_RAM_IR_FINE_8K_FREQINC__A 0x8200DB | ||
| 625 | #define B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE 0x1 | ||
| 626 | #define B_SC_RA_RAM_IR_FINE_8K_KAISINC__A 0x8200DC | ||
| 627 | #define B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE 0x40 | ||
| 628 | #define B_SC_RA_RAM_ECHO_SHIFT_LIM__A 0x8200DD | ||
| 629 | #define B_SC_RA_RAM_SAMPLE_RATE_COUNT__A 0x8200E8 | ||
| 630 | #define B_SC_RA_RAM_SAMPLE_RATE_STEP__A 0x8200E9 | ||
| 631 | #define B_SC_RA_RAM_BAND__A 0x8200EC | ||
| 632 | #define B_SC_RA_RAM_LC_ABS_2K__A 0x8200F4 | ||
| 633 | #define B_SC_RA_RAM_LC_ABS_2K__PRE 0x1F | ||
| 634 | #define B_SC_RA_RAM_LC_ABS_8K__A 0x8200F5 | ||
| 635 | #define B_SC_RA_RAM_LC_ABS_8K__PRE 0x1F | ||
| 636 | #define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE 0x100 | ||
| 637 | #define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE 0x4 | ||
| 638 | #define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE 0x1E2 | ||
| 639 | #define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE 0x4 | ||
| 640 | #define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE 0x10D | ||
| 641 | #define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE 0x5 | ||
| 642 | #define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE 0x17D | ||
| 643 | #define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE 0x4 | ||
| 644 | #define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE 0x133 | ||
| 645 | #define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE 0x5 | ||
| 646 | #define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE 0x114 | ||
| 647 | #define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE 0x5 | ||
| 648 | #define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE 0x14A | ||
| 649 | #define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE 0x4 | ||
| 650 | #define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE 0x1BB | ||
| 651 | #define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE 0x4 | ||
| 652 | #define B_SC_RA_RAM_DRIVER_VERSION__AX 0x8201FE | ||
| 653 | #define B_SC_RA_RAM_PROC_LOCKTRACK 0x0 | ||
| 654 | #define B_FE_COMM_EXEC__A 0xC00000 | ||
| 655 | #define B_FE_AD_REG_COMM_EXEC__A 0xC10000 | ||
| 656 | #define B_FE_AD_REG_FDB_IN__A 0xC10012 | ||
| 657 | #define B_FE_AD_REG_PD__A 0xC10013 | ||
| 658 | #define B_FE_AD_REG_INVEXT__A 0xC10014 | ||
| 659 | #define B_FE_AD_REG_CLKNEG__A 0xC10015 | ||
| 660 | #define B_FE_AG_REG_COMM_EXEC__A 0xC20000 | ||
| 661 | #define B_FE_AG_REG_AG_MODE_LOP__A 0xC20010 | ||
| 662 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_4__M 0x10 | ||
| 663 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC 0x0 | ||
| 664 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC 0x10 | ||
| 665 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_5__M 0x20 | ||
| 666 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC 0x0 | ||
| 667 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_C__M 0x1000 | ||
| 668 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC 0x0 | ||
| 669 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC 0x1000 | ||
| 670 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_E__M 0x4000 | ||
| 671 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC 0x0 | ||
| 672 | #define B_FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC 0x4000 | ||
| 673 | #define B_FE_AG_REG_AG_MODE_HIP__A 0xC20011 | ||
| 674 | #define B_FE_AG_REG_AG_MODE_HIP_MODE_J__M 0x8 | ||
| 675 | #define B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC 0x0 | ||
| 676 | #define B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC 0x8 | ||
| 677 | #define B_FE_AG_REG_AG_PGA_MODE__A 0xC20012 | ||
| 678 | #define B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN 0x0 | ||
| 679 | #define B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN 0x1 | ||
| 680 | #define B_FE_AG_REG_AG_AGC_SIO__A 0xC20013 | ||
| 681 | #define B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M 0x2 | ||
| 682 | #define B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT 0x0 | ||
| 683 | #define B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT 0x2 | ||
| 684 | #define B_FE_AG_REG_AG_PWD__A 0xC20015 | ||
| 685 | #define B_FE_AG_REG_AG_PWD_PWD_PD2__M 0x2 | ||
| 686 | #define B_FE_AG_REG_AG_PWD_PWD_PD2_DISABLE 0x0 | ||
| 687 | #define B_FE_AG_REG_AG_PWD_PWD_PD2_ENABLE 0x2 | ||
| 688 | #define B_FE_AG_REG_DCE_AUR_CNT__A 0xC20016 | ||
| 689 | #define B_FE_AG_REG_DCE_RUR_CNT__A 0xC20017 | ||
| 690 | #define B_FE_AG_REG_ACE_AUR_CNT__A 0xC2001A | ||
| 691 | #define B_FE_AG_REG_ACE_RUR_CNT__A 0xC2001B | ||
| 692 | #define B_FE_AG_REG_CDR_RUR_CNT__A 0xC20020 | ||
| 693 | #define B_FE_AG_REG_EGC_RUR_CNT__A 0xC20024 | ||
| 694 | #define B_FE_AG_REG_EGC_SET_LVL__A 0xC20025 | ||
| 695 | #define B_FE_AG_REG_EGC_SET_LVL__M 0x1FF | ||
| 696 | #define B_FE_AG_REG_EGC_FLA_RGN__A 0xC20026 | ||
| 697 | #define B_FE_AG_REG_EGC_SLO_RGN__A 0xC20027 | ||
| 698 | #define B_FE_AG_REG_EGC_JMP_PSN__A 0xC20028 | ||
| 699 | #define B_FE_AG_REG_EGC_FLA_INC__A 0xC20029 | ||
| 700 | #define B_FE_AG_REG_EGC_FLA_DEC__A 0xC2002A | ||
| 701 | #define B_FE_AG_REG_EGC_SLO_INC__A 0xC2002B | ||
| 702 | #define B_FE_AG_REG_EGC_SLO_DEC__A 0xC2002C | ||
| 703 | #define B_FE_AG_REG_EGC_FAS_INC__A 0xC2002D | ||
| 704 | #define B_FE_AG_REG_EGC_FAS_DEC__A 0xC2002E | ||
| 705 | #define B_FE_AG_REG_PM1_AGC_WRI__A 0xC20030 | ||
| 706 | #define B_FE_AG_REG_PM1_AGC_WRI__M 0x7FF | ||
| 707 | #define B_FE_AG_REG_GC1_AGC_RIC__A 0xC20031 | ||
| 708 | #define B_FE_AG_REG_GC1_AGC_OFF__A 0xC20032 | ||
| 709 | #define B_FE_AG_REG_GC1_AGC_MAX__A 0xC20033 | ||
| 710 | #define B_FE_AG_REG_GC1_AGC_MIN__A 0xC20034 | ||
| 711 | #define B_FE_AG_REG_GC1_AGC_DAT__A 0xC20035 | ||
| 712 | #define B_FE_AG_REG_GC1_AGC_DAT__M 0x3FF | ||
| 713 | #define B_FE_AG_REG_PM2_AGC_WRI__A 0xC20036 | ||
| 714 | #define B_FE_AG_REG_IND_WIN__A 0xC2003C | ||
| 715 | #define B_FE_AG_REG_IND_THD_LOL__A 0xC2003D | ||
| 716 | #define B_FE_AG_REG_IND_THD_HIL__A 0xC2003E | ||
| 717 | #define B_FE_AG_REG_IND_DEL__A 0xC2003F | ||
| 718 | #define B_FE_AG_REG_IND_PD1_WRI__A 0xC20040 | ||
| 719 | #define B_FE_AG_REG_PDA_AUR_CNT__A 0xC20041 | ||
| 720 | #define B_FE_AG_REG_PDA_RUR_CNT__A 0xC20042 | ||
| 721 | #define B_FE_AG_REG_PDA_AVE_DAT__A 0xC20043 | ||
| 722 | #define B_FE_AG_REG_PDC_RUR_CNT__A 0xC20044 | ||
| 723 | #define B_FE_AG_REG_PDC_SET_LVL__A 0xC20045 | ||
| 724 | #define B_FE_AG_REG_PDC_FLA_RGN__A 0xC20046 | ||
| 725 | #define B_FE_AG_REG_PDC_JMP_PSN__A 0xC20047 | ||
| 726 | #define B_FE_AG_REG_PDC_FLA_STP__A 0xC20048 | ||
| 727 | #define B_FE_AG_REG_PDC_SLO_STP__A 0xC20049 | ||
| 728 | #define B_FE_AG_REG_PDC_PD2_WRI__A 0xC2004A | ||
| 729 | #define B_FE_AG_REG_PDC_MAP_DAT__A 0xC2004B | ||
| 730 | #define B_FE_AG_REG_PDC_MAX__A 0xC2004C | ||
| 731 | #define B_FE_AG_REG_TGA_AUR_CNT__A 0xC2004D | ||
| 732 | #define B_FE_AG_REG_TGA_RUR_CNT__A 0xC2004E | ||
| 733 | #define B_FE_AG_REG_TGA_AVE_DAT__A 0xC2004F | ||
| 734 | #define B_FE_AG_REG_TGC_RUR_CNT__A 0xC20050 | ||
| 735 | #define B_FE_AG_REG_TGC_SET_LVL__A 0xC20051 | ||
| 736 | #define B_FE_AG_REG_TGC_SET_LVL__M 0x3F | ||
| 737 | #define B_FE_AG_REG_TGC_FLA_RGN__A 0xC20052 | ||
| 738 | #define B_FE_AG_REG_TGC_JMP_PSN__A 0xC20053 | ||
| 739 | #define B_FE_AG_REG_TGC_FLA_STP__A 0xC20054 | ||
| 740 | #define B_FE_AG_REG_TGC_SLO_STP__A 0xC20055 | ||
| 741 | #define B_FE_AG_REG_TGC_MAP_DAT__A 0xC20056 | ||
| 742 | #define B_FE_AG_REG_FGM_WRI__A 0xC20061 | ||
| 743 | #define B_FE_AG_REG_BGC_FGC_WRI__A 0xC20068 | ||
| 744 | #define B_FE_AG_REG_BGC_CGC_WRI__A 0xC20069 | ||
| 745 | #define B_FE_FS_REG_COMM_EXEC__A 0xC30000 | ||
| 746 | #define B_FE_FS_REG_ADD_INC_LOP__A 0xC30010 | ||
| 747 | #define B_FE_FD_REG_COMM_EXEC__A 0xC40000 | ||
| 748 | #define B_FE_FD_REG_SCL__A 0xC40010 | ||
| 749 | #define B_FE_FD_REG_MAX_LEV__A 0xC40011 | ||
| 750 | #define B_FE_FD_REG_NR__A 0xC40012 | ||
| 751 | #define B_FE_FD_REG_MEAS_VAL__A 0xC40014 | ||
| 752 | #define B_FE_IF_REG_COMM_EXEC__A 0xC50000 | ||
| 753 | #define B_FE_IF_REG_INCR0__A 0xC50010 | ||
| 754 | #define B_FE_IF_REG_INCR0__W 16 | ||
| 755 | #define B_FE_IF_REG_INCR0__M 0xFFFF | ||
| 756 | #define B_FE_IF_REG_INCR1__A 0xC50011 | ||
| 757 | #define B_FE_IF_REG_INCR1__M 0xFF | ||
| 758 | #define B_FE_CF_REG_COMM_EXEC__A 0xC60000 | ||
| 759 | #define B_FE_CF_REG_SCL__A 0xC60010 | ||
| 760 | #define B_FE_CF_REG_MAX_LEV__A 0xC60011 | ||
| 761 | #define B_FE_CF_REG_NR__A 0xC60012 | ||
| 762 | #define B_FE_CF_REG_IMP_VAL__A 0xC60013 | ||
| 763 | #define B_FE_CF_REG_MEAS_VAL__A 0xC60014 | ||
| 764 | #define B_FE_CU_REG_COMM_EXEC__A 0xC70000 | ||
| 765 | #define B_FE_CU_REG_FRM_CNT_RST__A 0xC70011 | ||
| 766 | #define B_FE_CU_REG_FRM_CNT_STR__A 0xC70012 | ||
| 767 | #define B_FE_CU_REG_CTR_NFC_ICR__A 0xC70020 | ||
| 768 | #define B_FE_CU_REG_CTR_NFC_OCR__A 0xC70021 | ||
| 769 | #define B_FE_CU_REG_DIV_NFC_CLP__A 0xC70027 | ||
| 770 | #define B_FT_COMM_EXEC__A 0x1000000 | ||
| 771 | #define B_FT_REG_COMM_EXEC__A 0x1010000 | ||
| 772 | #define B_CP_COMM_EXEC__A 0x1400000 | ||
| 773 | #define B_CP_REG_COMM_EXEC__A 0x1410000 | ||
| 774 | #define B_CP_REG_INTERVAL__A 0x1410011 | ||
| 775 | #define B_CP_REG_BR_SPL_OFFSET__A 0x1410023 | ||
| 776 | #define B_CP_REG_BR_STR_DEL__A 0x1410024 | ||
| 777 | #define B_CP_REG_RT_ANG_INC0__A 0x1410030 | ||
| 778 | #define B_CP_REG_RT_ANG_INC1__A 0x1410031 | ||
| 779 | #define B_CP_REG_RT_DETECT_TRH__A 0x1410033 | ||
| 780 | #define B_CP_REG_AC_NEXP_OFFS__A 0x1410040 | ||
| 781 | #define B_CP_REG_AC_AVER_POW__A 0x1410041 | ||
| 782 | #define B_CP_REG_AC_MAX_POW__A 0x1410042 | ||
| 783 | #define B_CP_REG_AC_WEIGHT_MAN__A 0x1410043 | ||
| 784 | #define B_CP_REG_AC_WEIGHT_EXP__A 0x1410044 | ||
| 785 | #define B_CP_REG_AC_AMP_MODE__A 0x1410047 | ||
| 786 | #define B_CP_REG_AC_AMP_FIX__A 0x1410048 | ||
| 787 | #define B_CP_REG_AC_ANG_MODE__A 0x141004A | ||
| 788 | #define B_CE_COMM_EXEC__A 0x1800000 | ||
| 789 | #define B_CE_REG_COMM_EXEC__A 0x1810000 | ||
| 790 | #define B_CE_REG_TAPSET__A 0x1810011 | ||
| 791 | #define B_CE_REG_AVG_POW__A 0x1810012 | ||
| 792 | #define B_CE_REG_MAX_POW__A 0x1810013 | ||
| 793 | #define B_CE_REG_ATT__A 0x1810014 | ||
| 794 | #define B_CE_REG_NRED__A 0x1810015 | ||
| 795 | #define B_CE_REG_NE_ERR_SELECT__A 0x1810043 | ||
| 796 | #define B_CE_REG_NE_TD_CAL__A 0x1810044 | ||
| 797 | #define B_CE_REG_NE_MIXAVG__A 0x1810046 | ||
| 798 | #define B_CE_REG_NE_NUPD_OFS__A 0x1810047 | ||
| 799 | #define B_CE_REG_PE_NEXP_OFFS__A 0x1810050 | ||
| 800 | #define B_CE_REG_PE_TIMESHIFT__A 0x1810051 | ||
| 801 | #define B_CE_REG_TP_A0_TAP_NEW__A 0x1810064 | ||
| 802 | #define B_CE_REG_TP_A0_TAP_NEW_VALID__A 0x1810065 | ||
| 803 | #define B_CE_REG_TP_A0_MU_LMS_STEP__A 0x1810066 | ||
| 804 | #define B_CE_REG_TP_A1_TAP_NEW__A 0x1810068 | ||
| 805 | #define B_CE_REG_TP_A1_TAP_NEW_VALID__A 0x1810069 | ||
| 806 | #define B_CE_REG_TP_A1_MU_LMS_STEP__A 0x181006A | ||
| 807 | #define B_CE_REG_TI_PHN_ENABLE__A 0x1810073 | ||
| 808 | #define B_CE_REG_FI_SHT_INCR__A 0x1810090 | ||
| 809 | #define B_CE_REG_FI_EXP_NORM__A 0x1810091 | ||
| 810 | #define B_CE_REG_IR_INPUTSEL__A 0x18100A0 | ||
| 811 | #define B_CE_REG_IR_STARTPOS__A 0x18100A1 | ||
| 812 | #define B_CE_REG_IR_NEXP_THRES__A 0x18100A2 | ||
| 813 | #define B_CE_REG_FR_TREAL00__A 0x1820010 | ||
| 814 | #define B_CE_REG_FR_TIMAG00__A 0x1820011 | ||
| 815 | #define B_CE_REG_FR_TREAL01__A 0x1820012 | ||
| 816 | #define B_CE_REG_FR_TIMAG01__A 0x1820013 | ||
| 817 | #define B_CE_REG_FR_TREAL02__A 0x1820014 | ||
| 818 | #define B_CE_REG_FR_TIMAG02__A 0x1820015 | ||
| 819 | #define B_CE_REG_FR_TREAL03__A 0x1820016 | ||
| 820 | #define B_CE_REG_FR_TIMAG03__A 0x1820017 | ||
| 821 | #define B_CE_REG_FR_TREAL04__A 0x1820018 | ||
| 822 | #define B_CE_REG_FR_TIMAG04__A 0x1820019 | ||
| 823 | #define B_CE_REG_FR_TREAL05__A 0x182001A | ||
| 824 | #define B_CE_REG_FR_TIMAG05__A 0x182001B | ||
| 825 | #define B_CE_REG_FR_TREAL06__A 0x182001C | ||
| 826 | #define B_CE_REG_FR_TIMAG06__A 0x182001D | ||
| 827 | #define B_CE_REG_FR_TREAL07__A 0x182001E | ||
| 828 | #define B_CE_REG_FR_TIMAG07__A 0x182001F | ||
| 829 | #define B_CE_REG_FR_TREAL08__A 0x1820020 | ||
| 830 | #define B_CE_REG_FR_TIMAG08__A 0x1820021 | ||
| 831 | #define B_CE_REG_FR_TREAL09__A 0x1820022 | ||
| 832 | #define B_CE_REG_FR_TIMAG09__A 0x1820023 | ||
| 833 | #define B_CE_REG_FR_TREAL10__A 0x1820024 | ||
| 834 | #define B_CE_REG_FR_TIMAG10__A 0x1820025 | ||
| 835 | #define B_CE_REG_FR_TREAL11__A 0x1820026 | ||
| 836 | #define B_CE_REG_FR_TIMAG11__A 0x1820027 | ||
| 837 | #define B_CE_REG_FR_MID_TAP__A 0x1820028 | ||
| 838 | #define B_CE_REG_FR_SQS_G00__A 0x1820029 | ||
| 839 | #define B_CE_REG_FR_SQS_G01__A 0x182002A | ||
| 840 | #define B_CE_REG_FR_SQS_G02__A 0x182002B | ||
| 841 | #define B_CE_REG_FR_SQS_G03__A 0x182002C | ||
| 842 | #define B_CE_REG_FR_SQS_G04__A 0x182002D | ||
| 843 | #define B_CE_REG_FR_SQS_G05__A 0x182002E | ||
| 844 | #define B_CE_REG_FR_SQS_G06__A 0x182002F | ||
| 845 | #define B_CE_REG_FR_SQS_G07__A 0x1820030 | ||
| 846 | #define B_CE_REG_FR_SQS_G08__A 0x1820031 | ||
| 847 | #define B_CE_REG_FR_SQS_G09__A 0x1820032 | ||
| 848 | #define B_CE_REG_FR_SQS_G10__A 0x1820033 | ||
| 849 | #define B_CE_REG_FR_SQS_G11__A 0x1820034 | ||
| 850 | #define B_CE_REG_FR_SQS_G12__A 0x1820035 | ||
| 851 | #define B_CE_REG_FR_RIO_G00__A 0x1820036 | ||
| 852 | #define B_CE_REG_FR_RIO_G01__A 0x1820037 | ||
| 853 | #define B_CE_REG_FR_RIO_G02__A 0x1820038 | ||
| 854 | #define B_CE_REG_FR_RIO_G03__A 0x1820039 | ||
| 855 | #define B_CE_REG_FR_RIO_G04__A 0x182003A | ||
| 856 | #define B_CE_REG_FR_RIO_G05__A 0x182003B | ||
| 857 | #define B_CE_REG_FR_RIO_G06__A 0x182003C | ||
| 858 | #define B_CE_REG_FR_RIO_G07__A 0x182003D | ||
| 859 | #define B_CE_REG_FR_RIO_G08__A 0x182003E | ||
| 860 | #define B_CE_REG_FR_RIO_G09__A 0x182003F | ||
| 861 | #define B_CE_REG_FR_RIO_G10__A 0x1820040 | ||
| 862 | #define B_CE_REG_FR_MODE__A 0x1820041 | ||
| 863 | #define B_CE_REG_FR_SQS_TRH__A 0x1820042 | ||
| 864 | #define B_CE_REG_FR_RIO_GAIN__A 0x1820043 | ||
| 865 | #define B_CE_REG_FR_BYPASS__A 0x1820044 | ||
| 866 | #define B_CE_REG_FR_PM_SET__A 0x1820045 | ||
| 867 | #define B_CE_REG_FR_ERR_SH__A 0x1820046 | ||
| 868 | #define B_CE_REG_FR_MAN_SH__A 0x1820047 | ||
| 869 | #define B_CE_REG_FR_TAP_SH__A 0x1820048 | ||
| 870 | #define B_EQ_COMM_EXEC__A 0x1C00000 | ||
| 871 | #define B_EQ_REG_COMM_EXEC__A 0x1C10000 | ||
| 872 | #define B_EQ_REG_COMM_MB__A 0x1C10002 | ||
| 873 | #define B_EQ_REG_IS_GAIN_MAN__A 0x1C10015 | ||
| 874 | #define B_EQ_REG_IS_GAIN_EXP__A 0x1C10016 | ||
| 875 | #define B_EQ_REG_IS_CLIP_EXP__A 0x1C10017 | ||
| 876 | #define B_EQ_REG_SN_CEGAIN__A 0x1C1002A | ||
| 877 | #define B_EQ_REG_SN_OFFSET__A 0x1C1002B | ||
| 878 | #define B_EQ_REG_RC_SEL_CAR__A 0x1C10032 | ||
| 879 | #define B_EQ_REG_RC_SEL_CAR_INIT 0x2 | ||
| 880 | #define B_EQ_REG_RC_SEL_CAR_DIV_ON 0x1 | ||
| 881 | #define B_EQ_REG_RC_SEL_CAR_PASS_A_CC 0x0 | ||
| 882 | #define B_EQ_REG_RC_SEL_CAR_PASS_B_CE 0x2 | ||
| 883 | #define B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC 0x0 | ||
| 884 | #define B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE 0x8 | ||
| 885 | #define B_EQ_REG_RC_SEL_CAR_MEAS_A_CC 0x0 | ||
| 886 | #define B_EQ_REG_RC_SEL_CAR_MEAS_B_CE 0x20 | ||
| 887 | #define B_EQ_REG_RC_SEL_CAR_FFTMODE__M 0x80 | ||
| 888 | #define B_EQ_REG_OT_CONST__A 0x1C10046 | ||
| 889 | #define B_EQ_REG_OT_ALPHA__A 0x1C10047 | ||
| 890 | #define B_EQ_REG_OT_QNT_THRES0__A 0x1C10048 | ||
| 891 | #define B_EQ_REG_OT_QNT_THRES1__A 0x1C10049 | ||
| 892 | #define B_EQ_REG_OT_CSI_STEP__A 0x1C1004A | ||
| 893 | #define B_EQ_REG_OT_CSI_OFFSET__A 0x1C1004B | ||
| 894 | #define B_EQ_REG_TD_REQ_SMB_CNT__A 0x1C10061 | ||
| 895 | #define B_EQ_REG_TD_TPS_PWR_OFS__A 0x1C10062 | ||
| 896 | #define B_EC_SB_REG_COMM_EXEC__A 0x2010000 | ||
| 897 | #define B_EC_SB_REG_TR_MODE__A 0x2010010 | ||
| 898 | #define B_EC_SB_REG_TR_MODE_8K 0x0 | ||
| 899 | #define B_EC_SB_REG_TR_MODE_2K 0x1 | ||
| 900 | #define B_EC_SB_REG_CONST__A 0x2010011 | ||
| 901 | #define B_EC_SB_REG_CONST_QPSK 0x0 | ||
| 902 | #define B_EC_SB_REG_CONST_16QAM 0x1 | ||
| 903 | #define B_EC_SB_REG_CONST_64QAM 0x2 | ||
| 904 | #define B_EC_SB_REG_ALPHA__A 0x2010012 | ||
| 905 | #define B_EC_SB_REG_PRIOR__A 0x2010013 | ||
| 906 | #define B_EC_SB_REG_PRIOR_HI 0x0 | ||
| 907 | #define B_EC_SB_REG_PRIOR_LO 0x1 | ||
| 908 | #define B_EC_SB_REG_CSI_HI__A 0x2010014 | ||
| 909 | #define B_EC_SB_REG_CSI_LO__A 0x2010015 | ||
| 910 | #define B_EC_SB_REG_SMB_TGL__A 0x2010016 | ||
| 911 | #define B_EC_SB_REG_SNR_HI__A 0x2010017 | ||
| 912 | #define B_EC_SB_REG_SNR_MID__A 0x2010018 | ||
| 913 | #define B_EC_SB_REG_SNR_LO__A 0x2010019 | ||
| 914 | #define B_EC_SB_REG_SCALE_MSB__A 0x201001A | ||
| 915 | #define B_EC_SB_REG_SCALE_BIT2__A 0x201001B | ||
| 916 | #define B_EC_SB_REG_SCALE_LSB__A 0x201001C | ||
| 917 | #define B_EC_SB_REG_CSI_OFS0__A 0x201001D | ||
| 918 | #define B_EC_SB_REG_CSI_OFS1__A 0x201001E | ||
| 919 | #define B_EC_SB_REG_CSI_OFS2__A 0x201001F | ||
| 920 | #define B_EC_VD_REG_COMM_EXEC__A 0x2090000 | ||
| 921 | #define B_EC_VD_REG_FORCE__A 0x2090010 | ||
| 922 | #define B_EC_VD_REG_SET_CODERATE__A 0x2090011 | ||
| 923 | #define B_EC_VD_REG_SET_CODERATE_C1_2 0x0 | ||
| 924 | #define B_EC_VD_REG_SET_CODERATE_C2_3 0x1 | ||
| 925 | #define B_EC_VD_REG_SET_CODERATE_C3_4 0x2 | ||
| 926 | #define B_EC_VD_REG_SET_CODERATE_C5_6 0x3 | ||
| 927 | #define B_EC_VD_REG_SET_CODERATE_C7_8 0x4 | ||
| 928 | #define B_EC_VD_REG_REQ_SMB_CNT__A 0x2090012 | ||
| 929 | #define B_EC_VD_REG_RLK_ENA__A 0x2090014 | ||
| 930 | #define B_EC_OD_REG_COMM_EXEC__A 0x2110000 | ||
| 931 | #define B_EC_OD_REG_SYNC__A 0x2110664 | ||
| 932 | #define B_EC_OD_DEINT_RAM__A 0x2120000 | ||
| 933 | #define B_EC_RS_REG_COMM_EXEC__A 0x2130000 | ||
| 934 | #define B_EC_RS_REG_REQ_PCK_CNT__A 0x2130010 | ||
| 935 | #define B_EC_RS_REG_VAL__A 0x2130011 | ||
| 936 | #define B_EC_RS_REG_VAL_PCK 0x1 | ||
| 937 | #define B_EC_RS_EC_RAM__A 0x2140000 | ||
| 938 | #define B_EC_OC_REG_COMM_EXEC__A 0x2150000 | ||
| 939 | #define B_EC_OC_REG_COMM_EXEC_CTL_ACTIVE 0x1 | ||
| 940 | #define B_EC_OC_REG_COMM_EXEC_CTL_HOLD 0x2 | ||
| 941 | #define B_EC_OC_REG_COMM_INT_STA__A 0x2150007 | ||
| 942 | #define B_EC_OC_REG_OC_MODE_LOP__A 0x2150010 | ||
| 943 | #define B_EC_OC_REG_OC_MODE_LOP_PAR_ENA__M 0x1 | ||
| 944 | #define B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE 0x0 | ||
| 945 | #define B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE 0x1 | ||
| 946 | #define B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M 0x4 | ||
| 947 | #define B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC 0x0 | ||
| 948 | #define B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M 0x80 | ||
| 949 | #define B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL 0x80 | ||
| 950 | #define B_EC_OC_REG_OC_MODE_HIP__A 0x2150011 | ||
| 951 | #define B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR 0x10 | ||
| 952 | #define B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M 0x200 | ||
| 953 | #define B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE 0x0 | ||
| 954 | #define B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE 0x200 | ||
| 955 | #define B_EC_OC_REG_OC_MPG_SIO__A 0x2150012 | ||
| 956 | #define B_EC_OC_REG_OC_MPG_SIO__M 0xFFF | ||
| 957 | #define B_EC_OC_REG_DTO_INC_LOP__A 0x2150014 | ||
| 958 | #define B_EC_OC_REG_DTO_INC_HIP__A 0x2150015 | ||
| 959 | #define B_EC_OC_REG_SNC_ISC_LVL__A 0x2150016 | ||
| 960 | #define B_EC_OC_REG_SNC_ISC_LVL_OSC__M 0xF0 | ||
| 961 | #define B_EC_OC_REG_TMD_TOP_MODE__A 0x215001D | ||
| 962 | #define B_EC_OC_REG_TMD_TOP_CNT__A 0x215001E | ||
| 963 | #define B_EC_OC_REG_TMD_HIL_MAR__A 0x215001F | ||
| 964 | #define B_EC_OC_REG_TMD_LOL_MAR__A 0x2150020 | ||
| 965 | #define B_EC_OC_REG_TMD_CUR_CNT__A 0x2150021 | ||
| 966 | #define B_EC_OC_REG_AVR_ASH_CNT__A 0x2150023 | ||
| 967 | #define B_EC_OC_REG_AVR_BSH_CNT__A 0x2150024 | ||
| 968 | #define B_EC_OC_REG_RCN_MODE__A 0x2150027 | ||
| 969 | #define B_EC_OC_REG_RCN_CRA_LOP__A 0x2150028 | ||
| 970 | #define B_EC_OC_REG_RCN_CRA_HIP__A 0x2150029 | ||
| 971 | #define B_EC_OC_REG_RCN_CST_LOP__A 0x215002A | ||
| 972 | #define B_EC_OC_REG_RCN_CST_HIP__A 0x215002B | ||
| 973 | #define B_EC_OC_REG_RCN_SET_LVL__A 0x215002C | ||
| 974 | #define B_EC_OC_REG_RCN_GAI_LVL__A 0x215002D | ||
| 975 | #define B_EC_OC_REG_RCN_CLP_LOP__A 0x2150032 | ||
| 976 | #define B_EC_OC_REG_RCN_CLP_HIP__A 0x2150033 | ||
| 977 | #define B_EC_OC_REG_RCN_MAP_LOP__A 0x2150034 | ||
| 978 | #define B_EC_OC_REG_RCN_MAP_HIP__A 0x2150035 | ||
| 979 | #define B_EC_OC_REG_OCR_MPG_UOS__A 0x2150036 | ||
| 980 | #define B_EC_OC_REG_OCR_MPG_UOS__M 0xFFF | ||
| 981 | #define B_EC_OC_REG_OCR_MPG_UOS_INIT 0x0 | ||
| 982 | #define B_EC_OC_REG_OCR_MPG_USR_DAT__A 0x2150038 | ||
| 983 | #define B_EC_OC_REG_IPR_INV_MPG__A 0x2150045 | ||
| 984 | #define B_EC_OC_REG_DTO_CLKMODE__A 0x2150047 | ||
| 985 | #define B_EC_OC_REG_DTO_PER__A 0x2150048 | ||
| 986 | #define B_EC_OC_REG_DTO_BUR__A 0x2150049 | ||
| 987 | #define B_EC_OC_REG_RCR_CLKMODE__A 0x215004A | ||
| 988 | #define B_CC_REG_OSC_MODE__A 0x2410010 | ||
| 989 | #define B_CC_REG_OSC_MODE_M20 0x1 | ||
| 990 | #define B_CC_REG_PLL_MODE__A 0x2410011 | ||
| 991 | #define B_CC_REG_PLL_MODE_BYPASS_PLL 0x1 | ||
| 992 | #define B_CC_REG_PLL_MODE_PUMP_CUR_12 0x14 | ||
| 993 | #define B_CC_REG_REF_DIVIDE__A 0x2410012 | ||
| 994 | #define B_CC_REG_PWD_MODE__A 0x2410015 | ||
| 995 | #define B_CC_REG_PWD_MODE_DOWN_PLL 0x2 | ||
| 996 | #define B_CC_REG_UPDATE__A 0x2410017 | ||
| 997 | #define B_CC_REG_UPDATE_KEY 0x3973 | ||
| 998 | #define B_CC_REG_JTAGID_L__A 0x2410019 | ||
| 999 | #define B_CC_REG_DIVERSITY__A 0x241001B | ||
| 1000 | #define B_LC_COMM_EXEC__A 0x2800000 | ||
| 1001 | #define B_LC_RA_RAM_IFINCR_NOM_L__A 0x282000C | ||
| 1002 | #define B_LC_RA_RAM_FILTER_SYM_SET__A 0x282001A | ||
| 1003 | #define B_LC_RA_RAM_FILTER_SYM_SET__PRE 0x3E8 | ||
| 1004 | #define B_LC_RA_RAM_FILTER_CRMM_A__A 0x2820060 | ||
| 1005 | #define B_LC_RA_RAM_FILTER_CRMM_A__PRE 0x4 | ||
| 1006 | #define B_LC_RA_RAM_FILTER_CRMM_B__A 0x2820061 | ||
| 1007 | #define B_LC_RA_RAM_FILTER_CRMM_B__PRE 0x1 | ||
| 1008 | #define B_LC_RA_RAM_FILTER_SRMM_A__A 0x2820068 | ||
| 1009 | #define B_LC_RA_RAM_FILTER_SRMM_A__PRE 0x4 | ||
| 1010 | #define B_LC_RA_RAM_FILTER_SRMM_B__A 0x2820069 | ||
| 1011 | #define B_LC_RA_RAM_FILTER_SRMM_B__PRE 0x1 | ||
| 1012 | |||
| 1013 | #endif | ||
diff --git a/drivers/media/dvb/frontends/eds1547.h b/drivers/media/dvb/frontends/eds1547.h index fa79b7c83dd2..c983f2f85802 100644 --- a/drivers/media/dvb/frontends/eds1547.h +++ b/drivers/media/dvb/frontends/eds1547.h | |||
| @@ -61,7 +61,7 @@ static u8 stv0288_earda_inittab[] = { | |||
| 61 | 0x3d, 0x30, | 61 | 0x3d, 0x30, |
| 62 | 0x40, 0x63, | 62 | 0x40, 0x63, |
| 63 | 0x41, 0x04, | 63 | 0x41, 0x04, |
| 64 | 0x42, 0x60, | 64 | 0x42, 0x20, |
| 65 | 0x43, 0x00, | 65 | 0x43, 0x00, |
| 66 | 0x44, 0x00, | 66 | 0x44, 0x00, |
| 67 | 0x45, 0x00, | 67 | 0x45, 0x00, |
diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c index 6c2e929bd79f..9a517a4bf96d 100644 --- a/drivers/media/dvb/frontends/ix2505v.c +++ b/drivers/media/dvb/frontends/ix2505v.c | |||
| @@ -218,11 +218,13 @@ static int ix2505v_set_params(struct dvb_frontend *fe, | |||
| 218 | fe->ops.i2c_gate_ctrl(fe, 1); | 218 | fe->ops.i2c_gate_ctrl(fe, 1); |
| 219 | 219 | ||
| 220 | len = sizeof(data); | 220 | len = sizeof(data); |
| 221 | |||
| 222 | ret |= ix2505v_write(state, data, len); | 221 | ret |= ix2505v_write(state, data, len); |
| 223 | 222 | ||
| 224 | data[2] |= 0x4; /* set TM = 1 other bits same */ | 223 | data[2] |= 0x4; /* set TM = 1 other bits same */ |
| 225 | 224 | ||
| 225 | if (fe->ops.i2c_gate_ctrl) | ||
| 226 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 227 | |||
| 226 | len = 1; | 228 | len = 1; |
| 227 | ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */ | 229 | ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */ |
| 228 | 230 | ||
| @@ -233,12 +235,12 @@ static int ix2505v_set_params(struct dvb_frontend *fe, | |||
| 233 | 235 | ||
| 234 | deb_info("Data 2=[%x%x]\n", data[2], data[3]); | 236 | deb_info("Data 2=[%x%x]\n", data[2], data[3]); |
| 235 | 237 | ||
| 238 | if (fe->ops.i2c_gate_ctrl) | ||
| 239 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 240 | |||
| 236 | len = 2; | 241 | len = 2; |
| 237 | ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */ | 242 | ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */ |
| 238 | 243 | ||
| 239 | if (fe->ops.i2c_gate_ctrl) | ||
| 240 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 241 | |||
| 242 | if (state->config->min_delay_ms) | 244 | if (state->config->min_delay_ms) |
| 243 | msleep(state->config->min_delay_ms); | 245 | msleep(state->config->min_delay_ms); |
| 244 | 246 | ||
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c index e3fe17fd96fb..8e0cfadba688 100644 --- a/drivers/media/dvb/frontends/stv0288.c +++ b/drivers/media/dvb/frontends/stv0288.c | |||
| @@ -253,7 +253,7 @@ static u8 stv0288_inittab[] = { | |||
| 253 | 0x3d, 0x30, | 253 | 0x3d, 0x30, |
| 254 | 0x40, 0x63, | 254 | 0x40, 0x63, |
| 255 | 0x41, 0x04, | 255 | 0x41, 0x04, |
| 256 | 0x42, 0x60, | 256 | 0x42, 0x20, |
| 257 | 0x43, 0x00, | 257 | 0x43, 0x00, |
| 258 | 0x44, 0x00, | 258 | 0x44, 0x00, |
| 259 | 0x45, 0x00, | 259 | 0x45, 0x00, |
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 4e3db3a42e06..42684bec8883 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c | |||
| @@ -64,6 +64,7 @@ struct stv0299_state { | |||
| 64 | fe_code_rate_t fec_inner; | 64 | fe_code_rate_t fec_inner; |
| 65 | int errmode; | 65 | int errmode; |
| 66 | u32 ucblocks; | 66 | u32 ucblocks; |
| 67 | u8 mcr_reg; | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | #define STATUS_BER 0 | 70 | #define STATUS_BER 0 |
| @@ -457,6 +458,9 @@ static int stv0299_init (struct dvb_frontend* fe) | |||
| 457 | 458 | ||
| 458 | dprintk("stv0299: init chip\n"); | 459 | dprintk("stv0299: init chip\n"); |
| 459 | 460 | ||
| 461 | stv0299_writeregI(state, 0x02, 0x30 | state->mcr_reg); | ||
| 462 | msleep(50); | ||
| 463 | |||
| 460 | for (i = 0; ; i += 2) { | 464 | for (i = 0; ; i += 2) { |
| 461 | reg = state->config->inittab[i]; | 465 | reg = state->config->inittab[i]; |
| 462 | val = state->config->inittab[i+1]; | 466 | val = state->config->inittab[i+1]; |
| @@ -464,6 +468,8 @@ static int stv0299_init (struct dvb_frontend* fe) | |||
| 464 | break; | 468 | break; |
| 465 | if (reg == 0x0c && state->config->op0_off) | 469 | if (reg == 0x0c && state->config->op0_off) |
| 466 | val &= ~0x10; | 470 | val &= ~0x10; |
| 471 | if (reg == 0x2) | ||
| 472 | state->mcr_reg = val & 0xf; | ||
| 467 | stv0299_writeregI(state, reg, val); | 473 | stv0299_writeregI(state, reg, val); |
| 468 | } | 474 | } |
| 469 | 475 | ||
| @@ -618,7 +624,7 @@ static int stv0299_sleep(struct dvb_frontend* fe) | |||
| 618 | { | 624 | { |
| 619 | struct stv0299_state* state = fe->demodulator_priv; | 625 | struct stv0299_state* state = fe->demodulator_priv; |
| 620 | 626 | ||
| 621 | stv0299_writeregI(state, 0x02, 0x80); | 627 | stv0299_writeregI(state, 0x02, 0xb0 | state->mcr_reg); |
| 622 | state->initialised = 0; | 628 | state->initialised = 0; |
| 623 | 629 | ||
| 624 | return 0; | 630 | return 0; |
| @@ -680,7 +686,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, | |||
| 680 | state->errmode = STATUS_BER; | 686 | state->errmode = STATUS_BER; |
| 681 | 687 | ||
| 682 | /* check if the demod is there */ | 688 | /* check if the demod is there */ |
| 683 | stv0299_writeregI(state, 0x02, 0x34); /* standby off */ | 689 | stv0299_writeregI(state, 0x02, 0x30); /* standby off */ |
| 684 | msleep(200); | 690 | msleep(200); |
| 685 | id = stv0299_readreg(state, 0x00); | 691 | id = stv0299_readreg(state, 0x00); |
| 686 | 692 | ||
diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb/frontends/z0194a.h index 07f3fc0998f6..96d86d6eb473 100644 --- a/drivers/media/dvb/frontends/z0194a.h +++ b/drivers/media/dvb/frontends/z0194a.h | |||
| @@ -42,7 +42,7 @@ static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe, | |||
| 42 | 42 | ||
| 43 | static u8 sharp_z0194a_inittab[] = { | 43 | static u8 sharp_z0194a_inittab[] = { |
| 44 | 0x01, 0x15, | 44 | 0x01, 0x15, |
| 45 | 0x02, 0x00, | 45 | 0x02, 0x30, |
| 46 | 0x03, 0x00, | 46 | 0x03, 0x00, |
| 47 | 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ | 47 | 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ |
| 48 | 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ | 48 | 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ |
diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 70e73afefb3d..1402062f2c89 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c | |||
| @@ -44,7 +44,7 @@ | |||
| 44 | 44 | ||
| 45 | static unsigned int verbose; | 45 | static unsigned int verbose; |
| 46 | module_param(verbose, int, 0644); | 46 | module_param(verbose, int, 0644); |
| 47 | MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); | 47 | MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)"); |
| 48 | 48 | ||
| 49 | #define DRIVER_NAME "Hopper" | 49 | #define DRIVER_NAME "Hopper" |
| 50 | 50 | ||
diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index 40da225098cc..05cbb9d95727 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | 52 | ||
| 53 | static unsigned int verbose; | 53 | static unsigned int verbose; |
| 54 | module_param(verbose, int, 0644); | 54 | module_param(verbose, int, 0644); |
| 55 | MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); | 55 | MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)"); |
| 56 | 56 | ||
| 57 | static int devs; | 57 | static int devs; |
| 58 | 58 | ||
diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 10a432a79d00..371558af2d96 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c | |||
| @@ -48,7 +48,7 @@ | |||
| 48 | 48 | ||
| 49 | int __devinit mantis_pci_init(struct mantis_pci *mantis) | 49 | int __devinit mantis_pci_init(struct mantis_pci *mantis) |
| 50 | { | 50 | { |
| 51 | u8 revision, latency; | 51 | u8 latency; |
| 52 | struct mantis_hwconfig *config = mantis->hwconfig; | 52 | struct mantis_hwconfig *config = mantis->hwconfig; |
| 53 | struct pci_dev *pdev = mantis->pdev; | 53 | struct pci_dev *pdev = mantis->pdev; |
| 54 | int err, ret = 0; | 54 | int err, ret = 0; |
| @@ -95,9 +95,8 @@ int __devinit mantis_pci_init(struct mantis_pci *mantis) | |||
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); | 97 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); |
| 98 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); | ||
| 99 | mantis->latency = latency; | 98 | mantis->latency = latency; |
| 100 | mantis->revision = revision; | 99 | mantis->revision = pdev->revision; |
| 101 | 100 | ||
| 102 | dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", | 101 | dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", |
| 103 | mantis->revision, | 102 | mantis->revision, |
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index deec927c7f7a..2ae0afa7756b 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | 37 | ||
| 38 | u8 lgtdqcs001f_inittab[] = { | 38 | u8 lgtdqcs001f_inittab[] = { |
| 39 | 0x01, 0x15, | 39 | 0x01, 0x15, |
| 40 | 0x02, 0x00, | 40 | 0x02, 0x30, |
| 41 | 0x03, 0x00, | 41 | 0x03, 0x00, |
| 42 | 0x04, 0x2a, | 42 | 0x04, 0x2a, |
| 43 | 0x05, 0x85, | 43 | 0x05, 0x85, |
diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index 0486919c1d0f..b81df5fafe26 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c | |||
| @@ -1090,6 +1090,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1090 | i2c_adap->algo = &pt1_i2c_algo; | 1090 | i2c_adap->algo = &pt1_i2c_algo; |
| 1091 | i2c_adap->algo_data = NULL; | 1091 | i2c_adap->algo_data = NULL; |
| 1092 | i2c_adap->dev.parent = &pdev->dev; | 1092 | i2c_adap->dev.parent = &pdev->dev; |
| 1093 | strcpy(i2c_adap->name, DRIVER_NAME); | ||
| 1093 | i2c_set_adapdata(i2c_adap, pt1); | 1094 | i2c_set_adapdata(i2c_adap, pt1); |
| 1094 | ret = i2c_add_adapter(i2c_adap); | 1095 | ret = i2c_add_adapter(i2c_adap); |
| 1095 | if (ret < 0) | 1096 | if (ret < 0) |
| @@ -1156,10 +1157,10 @@ err_pt1_disable_ram: | |||
| 1156 | pt1->power = 0; | 1157 | pt1->power = 0; |
| 1157 | pt1->reset = 1; | 1158 | pt1->reset = 1; |
| 1158 | pt1_update_power(pt1); | 1159 | pt1_update_power(pt1); |
| 1159 | err_pt1_cleanup_adapters: | ||
| 1160 | pt1_cleanup_adapters(pt1); | ||
| 1161 | err_i2c_del_adapter: | 1160 | err_i2c_del_adapter: |
| 1162 | i2c_del_adapter(i2c_adap); | 1161 | i2c_del_adapter(i2c_adap); |
| 1162 | err_pt1_cleanup_adapters: | ||
| 1163 | pt1_cleanup_adapters(pt1); | ||
| 1163 | err_kfree: | 1164 | err_kfree: |
| 1164 | pci_set_drvdata(pdev, NULL); | 1165 | pci_set_drvdata(pdev, NULL); |
| 1165 | kfree(pt1); | 1166 | kfree(pt1); |
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 0b8da57cf4c3..0c8164a2cc36 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c | |||
| @@ -297,9 +297,8 @@ static void smsusb_term_device(struct usb_interface *intf) | |||
| 297 | if (dev->coredev) | 297 | if (dev->coredev) |
| 298 | smscore_unregister_device(dev->coredev); | 298 | smscore_unregister_device(dev->coredev); |
| 299 | 299 | ||
| 300 | kfree(dev); | ||
| 301 | |||
| 302 | sms_info("device %p destroyed", dev); | 300 | sms_info("device %p destroyed", dev); |
| 301 | kfree(dev); | ||
| 303 | } | 302 | } |
| 304 | 303 | ||
| 305 | usb_set_intfdata(intf, NULL); | 304 | usb_set_intfdata(intf, NULL); |
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 44afab2fdc2d..9d83ced69dd6 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
| @@ -95,6 +95,8 @@ config DVB_BUDGET_CI | |||
| 95 | select DVB_STB0899 if !DVB_FE_CUSTOMISE | 95 | select DVB_STB0899 if !DVB_FE_CUSTOMISE |
| 96 | select DVB_STB6100 if !DVB_FE_CUSTOMISE | 96 | select DVB_STB6100 if !DVB_FE_CUSTOMISE |
| 97 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 97 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
| 98 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
| 99 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | ||
| 98 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | 100 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE |
| 99 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE | 101 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE |
| 100 | depends on RC_CORE | 102 | depends on RC_CORE |
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 1d79ada864d6..926f299b5225 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include "bsru6.h" | 52 | #include "bsru6.h" |
| 53 | #include "tda1002x.h" | 53 | #include "tda1002x.h" |
| 54 | #include "tda827x.h" | 54 | #include "tda827x.h" |
| 55 | #include "bsbe1-d01a.h" | ||
| 55 | 56 | ||
| 56 | #define MODULE_NAME "budget_ci" | 57 | #define MODULE_NAME "budget_ci" |
| 57 | 58 | ||
| @@ -224,6 +225,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
| 224 | case 0x1017: | 225 | case 0x1017: |
| 225 | case 0x1019: | 226 | case 0x1019: |
| 226 | case 0x101a: | 227 | case 0x101a: |
| 228 | case 0x101b: | ||
| 227 | /* for the Technotrend 1500 bundled remote */ | 229 | /* for the Technotrend 1500 bundled remote */ |
| 228 | dev->map_name = RC_MAP_TT_1500; | 230 | dev->map_name = RC_MAP_TT_1500; |
| 229 | break; | 231 | break; |
| @@ -1388,6 +1390,23 @@ static void frontend_init(struct budget_ci *budget_ci) | |||
| 1388 | } | 1390 | } |
| 1389 | break; | 1391 | break; |
| 1390 | 1392 | ||
| 1393 | case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */ | ||
| 1394 | budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap); | ||
| 1395 | if (budget_ci->budget.dvb_frontend) { | ||
| 1396 | if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) { | ||
| 1397 | if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) { | ||
| 1398 | printk(KERN_ERR "%s: No LNBP21 found!\n", __func__); | ||
| 1399 | dvb_frontend_detach(budget_ci->budget.dvb_frontend); | ||
| 1400 | budget_ci->budget.dvb_frontend = NULL; | ||
| 1401 | } | ||
| 1402 | } else { | ||
| 1403 | printk(KERN_ERR "%s: No STB6000 found!\n", __func__); | ||
| 1404 | dvb_frontend_detach(budget_ci->budget.dvb_frontend); | ||
| 1405 | budget_ci->budget.dvb_frontend = NULL; | ||
| 1406 | } | ||
| 1407 | } | ||
| 1408 | break; | ||
| 1409 | |||
| 1391 | case 0x1019: // TT S2-3200 PCI | 1410 | case 0x1019: // TT S2-3200 PCI |
| 1392 | /* | 1411 | /* |
| 1393 | * NOTE! on some STB0899 versions, the internal PLL takes a longer time | 1412 | * NOTE! on some STB0899 versions, the internal PLL takes a longer time |
| @@ -1518,6 +1537,7 @@ MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT); | |||
| 1518 | MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT); | 1537 | MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT); |
| 1519 | MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT); | 1538 | MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT); |
| 1520 | MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT); | 1539 | MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT); |
| 1540 | MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT); | ||
| 1521 | 1541 | ||
| 1522 | static struct pci_device_id pci_tbl[] = { | 1542 | static struct pci_device_id pci_tbl[] = { |
| 1523 | MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), | 1543 | MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), |
| @@ -1528,6 +1548,7 @@ static struct pci_device_id pci_tbl[] = { | |||
| 1528 | MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), | 1548 | MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), |
| 1529 | MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a), | 1549 | MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a), |
| 1530 | MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019), | 1550 | MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019), |
| 1551 | MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b), | ||
| 1531 | { | 1552 | { |
| 1532 | .vendor = 0, | 1553 | .vendor = 0, |
| 1533 | } | 1554 | } |
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index cbe2f0de1442..420bb42d5233 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | my TTUSB, so let it undef'd unless you want to implement another | 52 | my TTUSB, so let it undef'd unless you want to implement another |
| 53 | frontend. never tested. | 53 | frontend. never tested. |
| 54 | 54 | ||
| 55 | DEBUG: | 55 | debug: |
| 56 | define it to > 3 for really hardcore debugging. you probably don't want | 56 | define it to > 3 for really hardcore debugging. you probably don't want |
| 57 | this unless the device doesn't load at all. > 2 for bandwidth statistics. | 57 | this unless the device doesn't load at all. > 2 for bandwidth statistics. |
| 58 | */ | 58 | */ |
| @@ -134,20 +134,19 @@ struct ttusb { | |||
| 134 | /* ugly workaround ... don't know why it's necessary to read */ | 134 | /* ugly workaround ... don't know why it's necessary to read */ |
| 135 | /* all result codes. */ | 135 | /* all result codes. */ |
| 136 | 136 | ||
| 137 | #define DEBUG 0 | ||
| 138 | static int ttusb_cmd(struct ttusb *ttusb, | 137 | static int ttusb_cmd(struct ttusb *ttusb, |
| 139 | const u8 * data, int len, int needresult) | 138 | const u8 * data, int len, int needresult) |
| 140 | { | 139 | { |
| 141 | int actual_len; | 140 | int actual_len; |
| 142 | int err; | 141 | int err; |
| 143 | #if DEBUG >= 3 | ||
| 144 | int i; | 142 | int i; |
| 145 | 143 | ||
| 146 | printk(">"); | 144 | if (debug >= 3) { |
| 147 | for (i = 0; i < len; ++i) | 145 | printk(KERN_DEBUG ">"); |
| 148 | printk(" %02x", data[i]); | 146 | for (i = 0; i < len; ++i) |
| 149 | printk("\n"); | 147 | printk(KERN_CONT " %02x", data[i]); |
| 150 | #endif | 148 | printk(KERN_CONT "\n"); |
| 149 | } | ||
| 151 | 150 | ||
| 152 | if (mutex_lock_interruptible(&ttusb->semusb) < 0) | 151 | if (mutex_lock_interruptible(&ttusb->semusb) < 0) |
| 153 | return -EAGAIN; | 152 | return -EAGAIN; |
| @@ -176,13 +175,15 @@ static int ttusb_cmd(struct ttusb *ttusb, | |||
| 176 | mutex_unlock(&ttusb->semusb); | 175 | mutex_unlock(&ttusb->semusb); |
| 177 | return err; | 176 | return err; |
| 178 | } | 177 | } |
| 179 | #if DEBUG >= 3 | 178 | |
| 180 | actual_len = ttusb->last_result[3] + 4; | 179 | if (debug >= 3) { |
| 181 | printk("<"); | 180 | actual_len = ttusb->last_result[3] + 4; |
| 182 | for (i = 0; i < actual_len; ++i) | 181 | printk(KERN_DEBUG "<"); |
| 183 | printk(" %02x", ttusb->last_result[i]); | 182 | for (i = 0; i < actual_len; ++i) |
| 184 | printk("\n"); | 183 | printk(KERN_CONT " %02x", ttusb->last_result[i]); |
| 185 | #endif | 184 | printk(KERN_CONT "\n"); |
| 185 | } | ||
| 186 | |||
| 186 | if (!needresult) | 187 | if (!needresult) |
| 187 | mutex_unlock(&ttusb->semusb); | 188 | mutex_unlock(&ttusb->semusb); |
| 188 | return 0; | 189 | return 0; |
| @@ -636,16 +637,13 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) | |||
| 636 | ++ttusb->mux_state; | 637 | ++ttusb->mux_state; |
| 637 | else { | 638 | else { |
| 638 | ttusb->mux_state = 0; | 639 | ttusb->mux_state = 0; |
| 639 | #if DEBUG > 3 | ||
| 640 | if (ttusb->insync) | ||
| 641 | printk("%02x ", data[-1]); | ||
| 642 | #else | ||
| 643 | if (ttusb->insync) { | 640 | if (ttusb->insync) { |
| 644 | printk("%s: lost sync.\n", | 641 | dprintk("%s: %02x\n", |
| 642 | __func__, data[-1]); | ||
| 643 | printk(KERN_INFO "%s: lost sync.\n", | ||
| 645 | __func__); | 644 | __func__); |
| 646 | ttusb->insync = 0; | 645 | ttusb->insync = 0; |
| 647 | } | 646 | } |
| 648 | #endif | ||
| 649 | } | 647 | } |
| 650 | break; | 648 | break; |
| 651 | case 3: | 649 | case 3: |
| @@ -744,6 +742,9 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) | |||
| 744 | static void ttusb_iso_irq(struct urb *urb) | 742 | static void ttusb_iso_irq(struct urb *urb) |
| 745 | { | 743 | { |
| 746 | struct ttusb *ttusb = urb->context; | 744 | struct ttusb *ttusb = urb->context; |
| 745 | struct usb_iso_packet_descriptor *d; | ||
| 746 | u8 *data; | ||
| 747 | int len, i; | ||
| 747 | 748 | ||
| 748 | if (!ttusb->iso_streaming) | 749 | if (!ttusb->iso_streaming) |
| 749 | return; | 750 | return; |
| @@ -755,21 +756,14 @@ static void ttusb_iso_irq(struct urb *urb) | |||
| 755 | #endif | 756 | #endif |
| 756 | 757 | ||
| 757 | if (!urb->status) { | 758 | if (!urb->status) { |
| 758 | int i; | ||
| 759 | for (i = 0; i < urb->number_of_packets; ++i) { | 759 | for (i = 0; i < urb->number_of_packets; ++i) { |
| 760 | struct usb_iso_packet_descriptor *d; | ||
| 761 | u8 *data; | ||
| 762 | int len; | ||
| 763 | numpkt++; | 760 | numpkt++; |
| 764 | if (time_after_eq(jiffies, lastj + HZ)) { | 761 | if (time_after_eq(jiffies, lastj + HZ)) { |
| 765 | #if DEBUG > 2 | 762 | dprintk("frames/s: %lu (ts: %d, stuff %d, " |
| 766 | printk | 763 | "sec: %d, invalid: %d, all: %d)\n", |
| 767 | ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n", | 764 | numpkt * HZ / (jiffies - lastj), |
| 768 | numpkt * HZ / (jiffies - lastj), | 765 | numts, numstuff, numsec, numinvalid, |
| 769 | numts, numstuff, numsec, numinvalid, | 766 | numts + numstuff + numsec + numinvalid); |
| 770 | numts + numstuff + numsec + | ||
| 771 | numinvalid); | ||
| 772 | #endif | ||
| 773 | numts = numstuff = numsec = numinvalid = 0; | 767 | numts = numstuff = numsec = numinvalid = 0; |
| 774 | lastj = jiffies; | 768 | lastj = jiffies; |
| 775 | numpkt = 0; | 769 | numpkt = 0; |
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 38ae6cd65790..0e740c98786c 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c | |||
| @@ -174,15 +174,27 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) | |||
| 174 | if (retval < 0) | 174 | if (retval < 0) |
| 175 | goto done; | 175 | goto done; |
| 176 | 176 | ||
| 177 | /* wait till tune operation has completed */ | 177 | /* currently I2C driver only uses interrupt way to tune */ |
| 178 | timeout = jiffies + msecs_to_jiffies(tune_timeout); | 178 | if (radio->stci_enabled) { |
| 179 | do { | 179 | INIT_COMPLETION(radio->completion); |
| 180 | retval = si470x_get_register(radio, STATUSRSSI); | 180 | |
| 181 | if (retval < 0) | 181 | /* wait till tune operation has completed */ |
| 182 | goto stop; | 182 | retval = wait_for_completion_timeout(&radio->completion, |
| 183 | timed_out = time_after(jiffies, timeout); | 183 | msecs_to_jiffies(tune_timeout)); |
| 184 | } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && | 184 | if (!retval) |
| 185 | (!timed_out)); | 185 | timed_out = true; |
| 186 | } else { | ||
| 187 | /* wait till tune operation has completed */ | ||
| 188 | timeout = jiffies + msecs_to_jiffies(tune_timeout); | ||
| 189 | do { | ||
| 190 | retval = si470x_get_register(radio, STATUSRSSI); | ||
| 191 | if (retval < 0) | ||
| 192 | goto stop; | ||
| 193 | timed_out = time_after(jiffies, timeout); | ||
| 194 | } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) | ||
| 195 | && (!timed_out)); | ||
| 196 | } | ||
| 197 | |||
| 186 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) | 198 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) |
| 187 | dev_warn(&radio->videodev->dev, "tune does not complete\n"); | 199 | dev_warn(&radio->videodev->dev, "tune does not complete\n"); |
| 188 | if (timed_out) | 200 | if (timed_out) |
| @@ -310,15 +322,27 @@ static int si470x_set_seek(struct si470x_device *radio, | |||
| 310 | if (retval < 0) | 322 | if (retval < 0) |
| 311 | goto done; | 323 | goto done; |
| 312 | 324 | ||
| 313 | /* wait till seek operation has completed */ | 325 | /* currently I2C driver only uses interrupt way to seek */ |
| 314 | timeout = jiffies + msecs_to_jiffies(seek_timeout); | 326 | if (radio->stci_enabled) { |
| 315 | do { | 327 | INIT_COMPLETION(radio->completion); |
| 316 | retval = si470x_get_register(radio, STATUSRSSI); | 328 | |
| 317 | if (retval < 0) | 329 | /* wait till seek operation has completed */ |
| 318 | goto stop; | 330 | retval = wait_for_completion_timeout(&radio->completion, |
| 319 | timed_out = time_after(jiffies, timeout); | 331 | msecs_to_jiffies(seek_timeout)); |
| 320 | } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && | 332 | if (!retval) |
| 321 | (!timed_out)); | 333 | timed_out = true; |
| 334 | } else { | ||
| 335 | /* wait till seek operation has completed */ | ||
| 336 | timeout = jiffies + msecs_to_jiffies(seek_timeout); | ||
| 337 | do { | ||
| 338 | retval = si470x_get_register(radio, STATUSRSSI); | ||
| 339 | if (retval < 0) | ||
| 340 | goto stop; | ||
| 341 | timed_out = time_after(jiffies, timeout); | ||
| 342 | } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) | ||
| 343 | && (!timed_out)); | ||
| 344 | } | ||
| 345 | |||
| 322 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) | 346 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) |
| 323 | dev_warn(&radio->videodev->dev, "seek does not complete\n"); | 347 | dev_warn(&radio->videodev->dev, "seek does not complete\n"); |
| 324 | if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) | 348 | if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) |
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 4ce541a5eb47..a2a67772c42c 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c | |||
| @@ -197,8 +197,9 @@ int si470x_fops_open(struct file *file) | |||
| 197 | if (retval < 0) | 197 | if (retval < 0) |
| 198 | goto done; | 198 | goto done; |
| 199 | 199 | ||
| 200 | /* enable RDS interrupt */ | 200 | /* enable RDS / STC interrupt */ |
| 201 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN; | 201 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN; |
| 202 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN; | ||
| 202 | radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2; | 203 | radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2; |
| 203 | radio->registers[SYSCONFIG1] |= 0x1 << 2; | 204 | radio->registers[SYSCONFIG1] |= 0x1 << 2; |
| 204 | retval = si470x_set_register(radio, SYSCONFIG1); | 205 | retval = si470x_set_register(radio, SYSCONFIG1); |
| @@ -261,12 +262,11 @@ int si470x_vidioc_querycap(struct file *file, void *priv, | |||
| 261 | **************************************************************************/ | 262 | **************************************************************************/ |
| 262 | 263 | ||
| 263 | /* | 264 | /* |
| 264 | * si470x_i2c_interrupt_work - rds processing function | 265 | * si470x_i2c_interrupt - interrupt handler |
| 265 | */ | 266 | */ |
| 266 | static void si470x_i2c_interrupt_work(struct work_struct *work) | 267 | static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) |
| 267 | { | 268 | { |
| 268 | struct si470x_device *radio = container_of(work, | 269 | struct si470x_device *radio = dev_id; |
| 269 | struct si470x_device, radio_work); | ||
| 270 | unsigned char regnr; | 270 | unsigned char regnr; |
| 271 | unsigned char blocknum; | 271 | unsigned char blocknum; |
| 272 | unsigned short bler; /* rds block errors */ | 272 | unsigned short bler; /* rds block errors */ |
| @@ -274,21 +274,29 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) | |||
| 274 | unsigned char tmpbuf[3]; | 274 | unsigned char tmpbuf[3]; |
| 275 | int retval = 0; | 275 | int retval = 0; |
| 276 | 276 | ||
| 277 | /* check Seek/Tune Complete */ | ||
| 278 | retval = si470x_get_register(radio, STATUSRSSI); | ||
| 279 | if (retval < 0) | ||
| 280 | goto end; | ||
| 281 | |||
| 282 | if (radio->registers[STATUSRSSI] & STATUSRSSI_STC) | ||
| 283 | complete(&radio->completion); | ||
| 284 | |||
| 277 | /* safety checks */ | 285 | /* safety checks */ |
| 278 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | 286 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) |
| 279 | return; | 287 | goto end; |
| 280 | 288 | ||
| 281 | /* Update RDS registers */ | 289 | /* Update RDS registers */ |
| 282 | for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) { | 290 | for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) { |
| 283 | retval = si470x_get_register(radio, STATUSRSSI + regnr); | 291 | retval = si470x_get_register(radio, STATUSRSSI + regnr); |
| 284 | if (retval < 0) | 292 | if (retval < 0) |
| 285 | return; | 293 | goto end; |
| 286 | } | 294 | } |
| 287 | 295 | ||
| 288 | /* get rds blocks */ | 296 | /* get rds blocks */ |
| 289 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) | 297 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) |
| 290 | /* No RDS group ready, better luck next time */ | 298 | /* No RDS group ready, better luck next time */ |
| 291 | return; | 299 | goto end; |
| 292 | 300 | ||
| 293 | for (blocknum = 0; blocknum < 4; blocknum++) { | 301 | for (blocknum = 0; blocknum < 4; blocknum++) { |
| 294 | switch (blocknum) { | 302 | switch (blocknum) { |
| @@ -342,19 +350,8 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) | |||
| 342 | 350 | ||
| 343 | if (radio->wr_index != radio->rd_index) | 351 | if (radio->wr_index != radio->rd_index) |
| 344 | wake_up_interruptible(&radio->read_queue); | 352 | wake_up_interruptible(&radio->read_queue); |
| 345 | } | ||
| 346 | |||
| 347 | |||
| 348 | /* | ||
| 349 | * si470x_i2c_interrupt - interrupt handler | ||
| 350 | */ | ||
| 351 | static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) | ||
| 352 | { | ||
| 353 | struct si470x_device *radio = dev_id; | ||
| 354 | |||
| 355 | if (!work_pending(&radio->radio_work)) | ||
| 356 | schedule_work(&radio->radio_work); | ||
| 357 | 353 | ||
| 354 | end: | ||
| 358 | return IRQ_HANDLED; | 355 | return IRQ_HANDLED; |
| 359 | } | 356 | } |
| 360 | 357 | ||
| @@ -376,7 +373,6 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, | |||
| 376 | goto err_initial; | 373 | goto err_initial; |
| 377 | } | 374 | } |
| 378 | 375 | ||
| 379 | INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work); | ||
| 380 | radio->users = 0; | 376 | radio->users = 0; |
| 381 | radio->client = client; | 377 | radio->client = client; |
| 382 | mutex_init(&radio->lock); | 378 | mutex_init(&radio->lock); |
| @@ -441,7 +437,11 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, | |||
| 441 | radio->rd_index = 0; | 437 | radio->rd_index = 0; |
| 442 | init_waitqueue_head(&radio->read_queue); | 438 | init_waitqueue_head(&radio->read_queue); |
| 443 | 439 | ||
| 444 | retval = request_irq(client->irq, si470x_i2c_interrupt, | 440 | /* mark Seek/Tune Complete Interrupt enabled */ |
| 441 | radio->stci_enabled = true; | ||
| 442 | init_completion(&radio->completion); | ||
| 443 | |||
| 444 | retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt, | ||
| 445 | IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); | 445 | IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); |
| 446 | if (retval) { | 446 | if (retval) { |
| 447 | dev_err(&client->dev, "Failed to register interrupt\n"); | 447 | dev_err(&client->dev, "Failed to register interrupt\n"); |
| @@ -479,7 +479,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) | |||
| 479 | struct si470x_device *radio = i2c_get_clientdata(client); | 479 | struct si470x_device *radio = i2c_get_clientdata(client); |
| 480 | 480 | ||
| 481 | free_irq(client->irq, radio); | 481 | free_irq(client->irq, radio); |
| 482 | cancel_work_sync(&radio->radio_work); | ||
| 483 | video_unregister_device(radio->videodev); | 482 | video_unregister_device(radio->videodev); |
| 484 | kfree(radio); | 483 | kfree(radio); |
| 485 | 484 | ||
| @@ -491,8 +490,9 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) | |||
| 491 | /* | 490 | /* |
| 492 | * si470x_i2c_suspend - suspend the device | 491 | * si470x_i2c_suspend - suspend the device |
| 493 | */ | 492 | */ |
| 494 | static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | 493 | static int si470x_i2c_suspend(struct device *dev) |
| 495 | { | 494 | { |
| 495 | struct i2c_client *client = to_i2c_client(dev); | ||
| 496 | struct si470x_device *radio = i2c_get_clientdata(client); | 496 | struct si470x_device *radio = i2c_get_clientdata(client); |
| 497 | 497 | ||
| 498 | /* power down */ | 498 | /* power down */ |
| @@ -507,8 +507,9 @@ static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | |||
| 507 | /* | 507 | /* |
| 508 | * si470x_i2c_resume - resume the device | 508 | * si470x_i2c_resume - resume the device |
| 509 | */ | 509 | */ |
| 510 | static int si470x_i2c_resume(struct i2c_client *client) | 510 | static int si470x_i2c_resume(struct device *dev) |
| 511 | { | 511 | { |
| 512 | struct i2c_client *client = to_i2c_client(dev); | ||
| 512 | struct si470x_device *radio = i2c_get_clientdata(client); | 513 | struct si470x_device *radio = i2c_get_clientdata(client); |
| 513 | 514 | ||
| 514 | /* power up : need 110ms */ | 515 | /* power up : need 110ms */ |
| @@ -519,9 +520,8 @@ static int si470x_i2c_resume(struct i2c_client *client) | |||
| 519 | 520 | ||
| 520 | return 0; | 521 | return 0; |
| 521 | } | 522 | } |
| 522 | #else | 523 | |
| 523 | #define si470x_i2c_suspend NULL | 524 | static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume); |
| 524 | #define si470x_i2c_resume NULL | ||
| 525 | #endif | 525 | #endif |
| 526 | 526 | ||
| 527 | 527 | ||
| @@ -532,11 +532,12 @@ static struct i2c_driver si470x_i2c_driver = { | |||
| 532 | .driver = { | 532 | .driver = { |
| 533 | .name = "si470x", | 533 | .name = "si470x", |
| 534 | .owner = THIS_MODULE, | 534 | .owner = THIS_MODULE, |
| 535 | #ifdef CONFIG_PM | ||
| 536 | .pm = &si470x_i2c_pm, | ||
| 537 | #endif | ||
| 535 | }, | 538 | }, |
| 536 | .probe = si470x_i2c_probe, | 539 | .probe = si470x_i2c_probe, |
| 537 | .remove = __devexit_p(si470x_i2c_remove), | 540 | .remove = __devexit_p(si470x_i2c_remove), |
| 538 | .suspend = si470x_i2c_suspend, | ||
| 539 | .resume = si470x_i2c_resume, | ||
| 540 | .id_table = si470x_i2c_id, | 541 | .id_table = si470x_i2c_id, |
| 541 | }; | 542 | }; |
| 542 | 543 | ||
diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index 4a4e908db04c..68da001b09dc 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h | |||
| @@ -158,6 +158,9 @@ struct si470x_device { | |||
| 158 | unsigned int rd_index; | 158 | unsigned int rd_index; |
| 159 | unsigned int wr_index; | 159 | unsigned int wr_index; |
| 160 | 160 | ||
| 161 | struct completion completion; | ||
| 162 | bool stci_enabled; /* Seek/Tune Complete Interrupt */ | ||
| 163 | |||
| 161 | #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) | 164 | #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) |
| 162 | /* reference to USB and video device */ | 165 | /* reference to USB and video device */ |
| 163 | struct usb_device *usbdev; | 166 | struct usb_device *usbdev; |
| @@ -179,7 +182,6 @@ struct si470x_device { | |||
| 179 | 182 | ||
| 180 | #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) | 183 | #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) |
| 181 | struct i2c_client *client; | 184 | struct i2c_client *client; |
| 182 | struct work_struct radio_work; | ||
| 183 | #endif | 185 | #endif |
| 184 | }; | 186 | }; |
| 185 | 187 | ||
diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h index 5db6fd14cf3c..1a45a5d847b0 100644 --- a/drivers/media/radio/wl128x/fmdrv.h +++ b/drivers/media/radio/wl128x/fmdrv.h | |||
| @@ -55,8 +55,6 @@ | |||
| 55 | #define FM_DRV_TX_TIMEOUT (5*HZ) /* 5 seconds */ | 55 | #define FM_DRV_TX_TIMEOUT (5*HZ) /* 5 seconds */ |
| 56 | #define FM_DRV_RX_SEEK_TIMEOUT (20*HZ) /* 20 seconds */ | 56 | #define FM_DRV_RX_SEEK_TIMEOUT (20*HZ) /* 20 seconds */ |
| 57 | 57 | ||
| 58 | #define NO_OF_ENTRIES_IN_ARRAY(array) (sizeof(array) / sizeof(array[0])) | ||
| 59 | |||
| 60 | #define fmerr(format, ...) \ | 58 | #define fmerr(format, ...) \ |
| 61 | printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__) | 59 | printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__) |
| 62 | #define fmwarn(format, ...) \ | 60 | #define fmwarn(format, ...) \ |
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 7f03142a329f..154c337f00fd 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
| @@ -161,6 +161,17 @@ config IR_NUVOTON | |||
| 161 | To compile this driver as a module, choose M here: the | 161 | To compile this driver as a module, choose M here: the |
| 162 | module will be called nuvoton-cir. | 162 | module will be called nuvoton-cir. |
| 163 | 163 | ||
| 164 | config IR_REDRAT3 | ||
| 165 | tristate "RedRat3 IR Transceiver" | ||
| 166 | depends on USB_ARCH_HAS_HCD | ||
| 167 | depends on RC_CORE | ||
| 168 | select USB | ||
| 169 | ---help--- | ||
| 170 | Say Y here if you want to use a RedRat3 Infrared Transceiver. | ||
| 171 | |||
| 172 | To compile this driver as a module, choose M here: the | ||
| 173 | module will be called redrat3. | ||
| 174 | |||
| 164 | config IR_STREAMZAP | 175 | config IR_STREAMZAP |
| 165 | tristate "Streamzap PC Remote IR Receiver" | 176 | tristate "Streamzap PC Remote IR Receiver" |
| 166 | depends on USB_ARCH_HAS_HCD | 177 | depends on USB_ARCH_HAS_HCD |
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index c6cfe70d862f..1f90a219a162 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile | |||
| @@ -18,6 +18,7 @@ obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o | |||
| 18 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o | 18 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o |
| 19 | obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o | 19 | obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o |
| 20 | obj-$(CONFIG_IR_ENE) += ene_ir.o | 20 | obj-$(CONFIG_IR_ENE) += ene_ir.o |
| 21 | obj-$(CONFIG_IR_REDRAT3) += redrat3.o | ||
| 21 | obj-$(CONFIG_IR_STREAMZAP) += streamzap.o | 22 | obj-$(CONFIG_IR_STREAMZAP) += streamzap.o |
| 22 | obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o | 23 | obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o |
| 23 | obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o | 24 | obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o |
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 8fc0f081b470..3f3c70716268 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c | |||
| @@ -443,16 +443,6 @@ static int display_close(struct inode *inode, struct file *file) | |||
| 443 | } else { | 443 | } else { |
| 444 | ictx->display_isopen = false; | 444 | ictx->display_isopen = false; |
| 445 | dev_dbg(ictx->dev, "display port closed\n"); | 445 | dev_dbg(ictx->dev, "display port closed\n"); |
| 446 | if (!ictx->dev_present_intf0) { | ||
| 447 | /* | ||
| 448 | * Device disconnected before close and IR port is not | ||
| 449 | * open. If IR port is open, context will be deleted by | ||
| 450 | * ir_close. | ||
| 451 | */ | ||
| 452 | mutex_unlock(&ictx->lock); | ||
| 453 | free_imon_context(ictx); | ||
| 454 | return retval; | ||
| 455 | } | ||
| 456 | } | 446 | } |
| 457 | 447 | ||
| 458 | mutex_unlock(&ictx->lock); | 448 | mutex_unlock(&ictx->lock); |
| @@ -1492,7 +1482,6 @@ static void imon_incoming_packet(struct imon_context *ictx, | |||
| 1492 | struct device *dev = ictx->dev; | 1482 | struct device *dev = ictx->dev; |
| 1493 | unsigned long flags; | 1483 | unsigned long flags; |
| 1494 | u32 kc; | 1484 | u32 kc; |
| 1495 | bool norelease = false; | ||
| 1496 | int i; | 1485 | int i; |
| 1497 | u64 scancode; | 1486 | u64 scancode; |
| 1498 | int press_type = 0; | 1487 | int press_type = 0; |
| @@ -1560,7 +1549,6 @@ static void imon_incoming_packet(struct imon_context *ictx, | |||
| 1560 | !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { | 1549 | !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { |
| 1561 | len = 8; | 1550 | len = 8; |
| 1562 | imon_pad_to_keys(ictx, buf); | 1551 | imon_pad_to_keys(ictx, buf); |
| 1563 | norelease = true; | ||
| 1564 | } | 1552 | } |
| 1565 | 1553 | ||
| 1566 | if (debug) { | 1554 | if (debug) { |
| @@ -1982,7 +1970,7 @@ static struct input_dev *imon_init_touch(struct imon_context *ictx) | |||
| 1982 | return touch; | 1970 | return touch; |
| 1983 | 1971 | ||
| 1984 | touch_register_failed: | 1972 | touch_register_failed: |
| 1985 | input_free_device(ictx->touch); | 1973 | input_free_device(touch); |
| 1986 | 1974 | ||
| 1987 | touch_alloc_failed: | 1975 | touch_alloc_failed: |
| 1988 | return NULL; | 1976 | return NULL; |
| @@ -2274,14 +2262,12 @@ static int __devinit imon_probe(struct usb_interface *interface, | |||
| 2274 | struct usb_host_interface *iface_desc = NULL; | 2262 | struct usb_host_interface *iface_desc = NULL; |
| 2275 | struct usb_interface *first_if; | 2263 | struct usb_interface *first_if; |
| 2276 | struct device *dev = &interface->dev; | 2264 | struct device *dev = &interface->dev; |
| 2277 | int ifnum, code_length, sysfs_err; | 2265 | int ifnum, sysfs_err; |
| 2278 | int ret = 0; | 2266 | int ret = 0; |
| 2279 | struct imon_context *ictx = NULL; | 2267 | struct imon_context *ictx = NULL; |
| 2280 | struct imon_context *first_if_ctx = NULL; | 2268 | struct imon_context *first_if_ctx = NULL; |
| 2281 | u16 vendor, product; | 2269 | u16 vendor, product; |
| 2282 | 2270 | ||
| 2283 | code_length = BUF_CHUNK_SIZE * 8; | ||
| 2284 | |||
| 2285 | usbdev = usb_get_dev(interface_to_usbdev(interface)); | 2271 | usbdev = usb_get_dev(interface_to_usbdev(interface)); |
| 2286 | iface_desc = interface->cur_altsetting; | 2272 | iface_desc = interface->cur_altsetting; |
| 2287 | ifnum = iface_desc->desc.bInterfaceNumber; | 2273 | ifnum = iface_desc->desc.bInterfaceNumber; |
| @@ -2366,8 +2352,6 @@ static void __devexit imon_disconnect(struct usb_interface *interface) | |||
| 2366 | dev = ictx->dev; | 2352 | dev = ictx->dev; |
| 2367 | ifnum = interface->cur_altsetting->desc.bInterfaceNumber; | 2353 | ifnum = interface->cur_altsetting->desc.bInterfaceNumber; |
| 2368 | 2354 | ||
| 2369 | mutex_lock(&ictx->lock); | ||
| 2370 | |||
| 2371 | /* | 2355 | /* |
| 2372 | * sysfs_remove_group is safe to call even if sysfs_create_group | 2356 | * sysfs_remove_group is safe to call even if sysfs_create_group |
| 2373 | * hasn't been called | 2357 | * hasn't been called |
| @@ -2391,24 +2375,20 @@ static void __devexit imon_disconnect(struct usb_interface *interface) | |||
| 2391 | if (ictx->display_supported) { | 2375 | if (ictx->display_supported) { |
| 2392 | if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) | 2376 | if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) |
| 2393 | usb_deregister_dev(interface, &imon_lcd_class); | 2377 | usb_deregister_dev(interface, &imon_lcd_class); |
| 2394 | else | 2378 | else if (ictx->display_type == IMON_DISPLAY_TYPE_VFD) |
| 2395 | usb_deregister_dev(interface, &imon_vfd_class); | 2379 | usb_deregister_dev(interface, &imon_vfd_class); |
| 2396 | } | 2380 | } |
| 2397 | } else { | 2381 | } else { |
| 2398 | ictx->dev_present_intf1 = false; | 2382 | ictx->dev_present_intf1 = false; |
| 2399 | usb_kill_urb(ictx->rx_urb_intf1); | 2383 | usb_kill_urb(ictx->rx_urb_intf1); |
| 2400 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) | 2384 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { |
| 2401 | input_unregister_device(ictx->touch); | 2385 | input_unregister_device(ictx->touch); |
| 2386 | del_timer_sync(&ictx->ttimer); | ||
| 2387 | } | ||
| 2402 | } | 2388 | } |
| 2403 | 2389 | ||
| 2404 | if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) { | 2390 | if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) |
| 2405 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) | 2391 | free_imon_context(ictx); |
| 2406 | del_timer_sync(&ictx->ttimer); | ||
| 2407 | mutex_unlock(&ictx->lock); | ||
| 2408 | if (!ictx->display_isopen) | ||
| 2409 | free_imon_context(ictx); | ||
| 2410 | } else | ||
| 2411 | mutex_unlock(&ictx->lock); | ||
| 2412 | 2392 | ||
| 2413 | mutex_unlock(&driver_lock); | 2393 | mutex_unlock(&driver_lock); |
| 2414 | 2394 | ||
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 43908a70bd8b..e716b931cf7e 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c | |||
| @@ -1250,11 +1250,9 @@ static void it8709_disable(struct ite_dev *dev) | |||
| 1250 | ite_dbg("%s called", __func__); | 1250 | ite_dbg("%s called", __func__); |
| 1251 | 1251 | ||
| 1252 | /* clear out all interrupt enable flags */ | 1252 | /* clear out all interrupt enable flags */ |
| 1253 | it8709_wr(dev, | 1253 | it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & |
| 1254 | it8709_rr(dev, | 1254 | ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), |
| 1255 | IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | | 1255 | IT85_C0IER); |
| 1256 | IT85_RDAIE | | ||
| 1257 | IT85_TLDLIE), IT85_C0IER); | ||
| 1258 | 1256 | ||
| 1259 | /* disable the receiver */ | 1257 | /* disable the receiver */ |
| 1260 | it8709_disable_rx(dev); | 1258 | it8709_disable_rx(dev); |
| @@ -1270,11 +1268,9 @@ static void it8709_init_hardware(struct ite_dev *dev) | |||
| 1270 | ite_dbg("%s called", __func__); | 1268 | ite_dbg("%s called", __func__); |
| 1271 | 1269 | ||
| 1272 | /* disable all the interrupts */ | 1270 | /* disable all the interrupts */ |
| 1273 | it8709_wr(dev, | 1271 | it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & |
| 1274 | it8709_rr(dev, | 1272 | ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), |
| 1275 | IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | | 1273 | IT85_C0IER); |
| 1276 | IT85_RDAIE | | ||
| 1277 | IT85_TLDLIE), IT85_C0IER); | ||
| 1278 | 1274 | ||
| 1279 | /* program the baud rate divisor */ | 1275 | /* program the baud rate divisor */ |
| 1280 | it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR); | 1276 | it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR); |
| @@ -1282,28 +1278,22 @@ static void it8709_init_hardware(struct ite_dev *dev) | |||
| 1282 | IT85_C0BDHR); | 1278 | IT85_C0BDHR); |
| 1283 | 1279 | ||
| 1284 | /* program the C0MSTCR register defaults */ | 1280 | /* program the C0MSTCR register defaults */ |
| 1285 | it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL | | 1281 | it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & |
| 1286 | IT85_ILE | 1282 | ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL |
| 1287 | | IT85_FIFOTL | 1283 | | IT85_FIFOCLR | IT85_RESET)) | IT85_FIFOTL_DEFAULT, |
| 1288 | | | 1284 | IT85_C0MSTCR); |
| 1289 | IT85_FIFOCLR | ||
| 1290 | | | ||
| 1291 | IT85_RESET)) | ||
| 1292 | | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR); | ||
| 1293 | 1285 | ||
| 1294 | /* program the C0RCR register defaults */ | 1286 | /* program the C0RCR register defaults */ |
| 1295 | it8709_wr(dev, | 1287 | it8709_wr(dev, (it8709_rr(dev, IT85_C0RCR) & |
| 1296 | (it8709_rr(dev, IT85_C0RCR) & | 1288 | ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | IT85_RXACT |
| 1297 | ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | 1289 | | IT85_RXDCR)) | ITE_RXDCR_DEFAULT, |
| 1298 | | IT85_RXACT | IT85_RXDCR)) | | 1290 | IT85_C0RCR); |
| 1299 | ITE_RXDCR_DEFAULT, IT85_C0RCR); | ||
| 1300 | 1291 | ||
| 1301 | /* program the C0TCR register defaults */ | 1292 | /* program the C0TCR register defaults */ |
| 1302 | it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) | 1293 | it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) & ~(IT85_TXMPM | IT85_TXMPW)) |
| 1303 | &~(IT85_TXMPM | IT85_TXMPW)) | 1294 | | IT85_TXRLE | IT85_TXENDF | IT85_TXMPM_DEFAULT |
| 1304 | |IT85_TXRLE | IT85_TXENDF | | 1295 | | IT85_TXMPW_DEFAULT, |
| 1305 | IT85_TXMPM_DEFAULT | | 1296 | IT85_C0TCR); |
| 1306 | IT85_TXMPW_DEFAULT, IT85_C0TCR); | ||
| 1307 | 1297 | ||
| 1308 | /* program the carrier parameters */ | 1298 | /* program the carrier parameters */ |
| 1309 | ite_set_carrier_params(dev); | 1299 | ite_set_carrier_params(dev); |
| @@ -1660,6 +1650,9 @@ static int ite_suspend(struct pnp_dev *pdev, pm_message_t state) | |||
| 1660 | 1650 | ||
| 1661 | ite_dbg("%s called", __func__); | 1651 | ite_dbg("%s called", __func__); |
| 1662 | 1652 | ||
| 1653 | /* wait for any transmission to end */ | ||
| 1654 | wait_event_interruptible(dev->tx_ended, !dev->transmitting); | ||
| 1655 | |||
| 1663 | spin_lock_irqsave(&dev->lock, flags); | 1656 | spin_lock_irqsave(&dev->lock, flags); |
| 1664 | 1657 | ||
| 1665 | /* disable all interrupts */ | 1658 | /* disable all interrupts */ |
| @@ -1680,13 +1673,10 @@ static int ite_resume(struct pnp_dev *pdev) | |||
| 1680 | 1673 | ||
| 1681 | spin_lock_irqsave(&dev->lock, flags); | 1674 | spin_lock_irqsave(&dev->lock, flags); |
| 1682 | 1675 | ||
| 1683 | if (dev->transmitting) { | 1676 | /* reinitialize hardware config registers */ |
| 1684 | /* wake up the transmitter */ | 1677 | dev->params.init_hardware(dev); |
| 1685 | wake_up_interruptible(&dev->tx_queue); | 1678 | /* enable the receiver */ |
| 1686 | } else { | 1679 | dev->params.enable_rx(dev); |
| 1687 | /* enable the receiver */ | ||
| 1688 | dev->params.enable_rx(dev); | ||
| 1689 | } | ||
| 1690 | 1680 | ||
| 1691 | spin_unlock_irqrestore(&dev->lock, flags); | 1681 | spin_unlock_irqrestore(&dev->lock, flags); |
| 1692 | 1682 | ||
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 85cac7ddbcec..b57fc83fb4d2 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile | |||
| @@ -77,6 +77,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ | |||
| 77 | rc-terratec-slim.o \ | 77 | rc-terratec-slim.o \ |
| 78 | rc-terratec-slim-2.o \ | 78 | rc-terratec-slim-2.o \ |
| 79 | rc-tevii-nec.o \ | 79 | rc-tevii-nec.o \ |
| 80 | rc-tivo.o \ | ||
| 80 | rc-total-media-in-hand.o \ | 81 | rc-total-media-in-hand.o \ |
| 81 | rc-trekstor.o \ | 82 | rc-trekstor.o \ |
| 82 | rc-tt-1500.o \ | 83 | rc-tt-1500.o \ |
diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c index bdf97b74cf90..22f54d413a35 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c +++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c | |||
| @@ -52,7 +52,7 @@ static struct rc_map_table avermedia_cardbus[] = { | |||
| 52 | { 0x28, KEY_SELECT }, /* Select */ | 52 | { 0x28, KEY_SELECT }, /* Select */ |
| 53 | { 0x29, KEY_BLUE }, /* Blue/Picture */ | 53 | { 0x29, KEY_BLUE }, /* Blue/Picture */ |
| 54 | { 0x2a, KEY_BACKSPACE }, /* Back */ | 54 | { 0x2a, KEY_BACKSPACE }, /* Back */ |
| 55 | { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ | 55 | { 0x2b, KEY_VIDEO }, /* PIP (Picture-in-picture) */ |
| 56 | { 0x2c, KEY_DOWN }, | 56 | { 0x2c, KEY_DOWN }, |
| 57 | { 0x2e, KEY_DOT }, | 57 | { 0x2e, KEY_DOT }, |
| 58 | { 0x2f, KEY_TV }, /* Live TV */ | 58 | { 0x2f, KEY_TV }, /* Live TV */ |
diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c index 937a81989f00..0ea2aa190d81 100644 --- a/drivers/media/rc/keymaps/rc-imon-mce.c +++ b/drivers/media/rc/keymaps/rc-imon-mce.c | |||
| @@ -111,7 +111,7 @@ static struct rc_map_table imon_mce[] = { | |||
| 111 | { 0x800ff44d, KEY_TITLE }, | 111 | { 0x800ff44d, KEY_TITLE }, |
| 112 | 112 | ||
| 113 | { 0x800ff40c, KEY_POWER }, | 113 | { 0x800ff40c, KEY_POWER }, |
| 114 | { 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */ | 114 | { 0x800ff40d, KEY_MEDIA }, /* Windows MCE button */ |
| 115 | 115 | ||
| 116 | }; | 116 | }; |
| 117 | 117 | ||
diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c index 63d42bd24c9e..75d3843fdc30 100644 --- a/drivers/media/rc/keymaps/rc-imon-pad.c +++ b/drivers/media/rc/keymaps/rc-imon-pad.c | |||
| @@ -87,7 +87,7 @@ static struct rc_map_table imon_pad[] = { | |||
| 87 | 87 | ||
| 88 | { 0x2b8515b7, KEY_VIDEO }, | 88 | { 0x2b8515b7, KEY_VIDEO }, |
| 89 | { 0x299195b7, KEY_AUDIO }, | 89 | { 0x299195b7, KEY_AUDIO }, |
| 90 | { 0x2ba115b7, KEY_CAMERA }, | 90 | { 0x2ba115b7, KEY_IMAGES }, |
| 91 | { 0x28a515b7, KEY_TV }, | 91 | { 0x28a515b7, KEY_TV }, |
| 92 | { 0x29a395b7, KEY_DVD }, | 92 | { 0x29a395b7, KEY_DVD }, |
| 93 | { 0x29a295b7, KEY_DVD }, | 93 | { 0x29a295b7, KEY_DVD }, |
| @@ -97,7 +97,7 @@ static struct rc_map_table imon_pad[] = { | |||
| 97 | { 0x2ba395b7, KEY_MENU }, | 97 | { 0x2ba395b7, KEY_MENU }, |
| 98 | 98 | ||
| 99 | { 0x288515b7, KEY_BOOKMARKS }, | 99 | { 0x288515b7, KEY_BOOKMARKS }, |
| 100 | { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ | 100 | { 0x2ab715b7, KEY_CAMERA }, /* Thumbnail */ |
| 101 | { 0x298595b7, KEY_SUBTITLE }, | 101 | { 0x298595b7, KEY_SUBTITLE }, |
| 102 | { 0x2b8595b7, KEY_LANGUAGE }, | 102 | { 0x2b8595b7, KEY_LANGUAGE }, |
| 103 | 103 | ||
| @@ -125,7 +125,7 @@ static struct rc_map_table imon_pad[] = { | |||
| 125 | { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ | 125 | { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ |
| 126 | { 0x02000065, KEY_COMPOSE }, /* RightMenu */ | 126 | { 0x02000065, KEY_COMPOSE }, /* RightMenu */ |
| 127 | { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ | 127 | { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ |
| 128 | { 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */ | 128 | { 0x2ab195b7, KEY_MEDIA }, /* Go or MultiMon */ |
| 129 | { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ | 129 | { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ |
| 130 | }; | 130 | }; |
| 131 | 131 | ||
diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c index 08d183120e41..7fa17a369f2d 100644 --- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | static struct rc_map_table kworld_plus_tv_analog[] = { | 19 | static struct rc_map_table kworld_plus_tv_analog[] = { |
| 20 | { 0x0c, KEY_LEFTMETA }, /* Kworld key */ | 20 | { 0x0c, KEY_MEDIA }, /* Kworld key */ |
| 21 | { 0x16, KEY_CLOSECD }, /* -> ) */ | 21 | { 0x16, KEY_CLOSECD }, /* -> ) */ |
| 22 | { 0x1d, KEY_POWER2 }, | 22 | { 0x1d, KEY_POWER2 }, |
| 23 | 23 | ||
diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c index 8dd519ecc58e..01b69bcc8666 100644 --- a/drivers/media/rc/keymaps/rc-rc6-mce.c +++ b/drivers/media/rc/keymaps/rc-rc6-mce.c | |||
| @@ -30,7 +30,7 @@ static struct rc_map_table rc6_mce[] = { | |||
| 30 | { 0x800f040a, KEY_DELETE }, | 30 | { 0x800f040a, KEY_DELETE }, |
| 31 | { 0x800f040b, KEY_ENTER }, | 31 | { 0x800f040b, KEY_ENTER }, |
| 32 | { 0x800f040c, KEY_POWER }, /* PC Power */ | 32 | { 0x800f040c, KEY_POWER }, /* PC Power */ |
| 33 | { 0x800f040d, KEY_LEFTMETA }, /* Windows MCE button */ | 33 | { 0x800f040d, KEY_MEDIA }, /* Windows MCE button */ |
| 34 | { 0x800f040e, KEY_MUTE }, | 34 | { 0x800f040e, KEY_MUTE }, |
| 35 | { 0x800f040f, KEY_INFO }, | 35 | { 0x800f040f, KEY_INFO }, |
| 36 | 36 | ||
| @@ -87,7 +87,7 @@ static struct rc_map_table rc6_mce[] = { | |||
| 87 | 87 | ||
| 88 | { 0x800f0465, KEY_POWER2 }, /* TV Power */ | 88 | { 0x800f0465, KEY_POWER2 }, /* TV Power */ |
| 89 | { 0x800f046e, KEY_PLAYPAUSE }, | 89 | { 0x800f046e, KEY_PLAYPAUSE }, |
| 90 | { 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */ | 90 | { 0x800f046f, KEY_PLAYER }, /* Start media application (NEW) */ |
| 91 | 91 | ||
| 92 | { 0x800f0480, KEY_BRIGHTNESSDOWN }, | 92 | { 0x800f0480, KEY_BRIGHTNESSDOWN }, |
| 93 | { 0x800f0481, KEY_PLAYPAUSE }, | 93 | { 0x800f0481, KEY_PLAYPAUSE }, |
diff --git a/drivers/media/rc/keymaps/rc-tivo.c b/drivers/media/rc/keymaps/rc-tivo.c new file mode 100644 index 000000000000..98ad085531fd --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tivo.c | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | /* rc-tivo.c - Keytable for TiVo remotes | ||
| 2 | * | ||
| 3 | * Copyright (c) 2011 by Jarod Wilson <jarod@redhat.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <media/rc-map.h> | ||
| 12 | |||
| 13 | /* | ||
| 14 | * Initial mapping is for the TiVo remote included in the Nero LiquidTV bundle, | ||
| 15 | * which also ships with a TiVo-branded IR transceiver, supported by the mceusb | ||
| 16 | * driver. Note that the remote uses an NEC-ish protocol, but instead of having | ||
| 17 | * a command/not_command pair, it has a vendor ID of 0xa10c, but some keys, the | ||
| 18 | * NEC extended checksums do pass, so the table presently has the intended | ||
| 19 | * values and the checksum-passed versions for those keys. | ||
| 20 | */ | ||
| 21 | static struct rc_map_table tivo[] = { | ||
| 22 | { 0xa10c900f, KEY_MEDIA }, /* TiVo Button */ | ||
| 23 | { 0xa10c0807, KEY_POWER2 }, /* TV Power */ | ||
| 24 | { 0xa10c8807, KEY_TV }, /* Live TV/Swap */ | ||
| 25 | { 0xa10c2c03, KEY_VIDEO_NEXT }, /* TV Input */ | ||
| 26 | { 0xa10cc807, KEY_INFO }, | ||
| 27 | { 0xa10cfa05, KEY_CYCLEWINDOWS }, /* Window */ | ||
| 28 | { 0x0085305f, KEY_CYCLEWINDOWS }, | ||
| 29 | { 0xa10c6c03, KEY_EPG }, /* Guide */ | ||
| 30 | |||
| 31 | { 0xa10c2807, KEY_UP }, | ||
| 32 | { 0xa10c6807, KEY_DOWN }, | ||
| 33 | { 0xa10ce807, KEY_LEFT }, | ||
| 34 | { 0xa10ca807, KEY_RIGHT }, | ||
| 35 | |||
| 36 | { 0xa10c1807, KEY_SCROLLDOWN }, /* Red Thumbs Down */ | ||
| 37 | { 0xa10c9807, KEY_SELECT }, | ||
| 38 | { 0xa10c5807, KEY_SCROLLUP }, /* Green Thumbs Up */ | ||
| 39 | |||
| 40 | { 0xa10c3807, KEY_VOLUMEUP }, | ||
| 41 | { 0xa10cb807, KEY_VOLUMEDOWN }, | ||
| 42 | { 0xa10cd807, KEY_MUTE }, | ||
| 43 | { 0xa10c040b, KEY_RECORD }, | ||
| 44 | { 0xa10c7807, KEY_CHANNELUP }, | ||
| 45 | { 0xa10cf807, KEY_CHANNELDOWN }, | ||
| 46 | { 0x0085301f, KEY_CHANNELDOWN }, | ||
| 47 | |||
| 48 | { 0xa10c840b, KEY_PLAY }, | ||
| 49 | { 0xa10cc40b, KEY_PAUSE }, | ||
| 50 | { 0xa10ca40b, KEY_SLOW }, | ||
| 51 | { 0xa10c440b, KEY_REWIND }, | ||
| 52 | { 0xa10c240b, KEY_FASTFORWARD }, | ||
| 53 | { 0xa10c640b, KEY_PREVIOUS }, | ||
| 54 | { 0xa10ce40b, KEY_NEXT }, /* ->| */ | ||
| 55 | |||
| 56 | { 0xa10c220d, KEY_ZOOM }, /* Aspect */ | ||
| 57 | { 0xa10c120d, KEY_STOP }, | ||
| 58 | { 0xa10c520d, KEY_DVD }, /* DVD Menu */ | ||
| 59 | |||
| 60 | { 0xa10c140b, KEY_NUMERIC_1 }, | ||
| 61 | { 0xa10c940b, KEY_NUMERIC_2 }, | ||
| 62 | { 0xa10c540b, KEY_NUMERIC_3 }, | ||
| 63 | { 0xa10cd40b, KEY_NUMERIC_4 }, | ||
| 64 | { 0xa10c340b, KEY_NUMERIC_5 }, | ||
| 65 | { 0xa10cb40b, KEY_NUMERIC_6 }, | ||
| 66 | { 0xa10c740b, KEY_NUMERIC_7 }, | ||
| 67 | { 0xa10cf40b, KEY_NUMERIC_8 }, | ||
| 68 | { 0x0085302f, KEY_NUMERIC_8 }, | ||
| 69 | { 0xa10c0c03, KEY_NUMERIC_9 }, | ||
| 70 | { 0xa10c8c03, KEY_NUMERIC_0 }, | ||
| 71 | { 0xa10ccc03, KEY_ENTER }, | ||
| 72 | { 0xa10c4c03, KEY_CLEAR }, | ||
| 73 | }; | ||
| 74 | |||
| 75 | static struct rc_map_list tivo_map = { | ||
| 76 | .map = { | ||
| 77 | .scan = tivo, | ||
| 78 | .size = ARRAY_SIZE(tivo), | ||
| 79 | .rc_type = RC_TYPE_NEC, | ||
| 80 | .name = RC_MAP_TIVO, | ||
| 81 | } | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int __init init_rc_map_tivo(void) | ||
| 85 | { | ||
| 86 | return rc_map_register(&tivo_map); | ||
| 87 | } | ||
| 88 | |||
| 89 | static void __exit exit_rc_map_tivo(void) | ||
| 90 | { | ||
| 91 | rc_map_unregister(&tivo_map); | ||
| 92 | } | ||
| 93 | |||
| 94 | module_init(init_rc_map_tivo) | ||
| 95 | module_exit(exit_rc_map_tivo) | ||
| 96 | |||
| 97 | MODULE_LICENSE("GPL"); | ||
| 98 | MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | ||
diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c index 0062ca291959..d8a34c14676a 100644 --- a/drivers/media/rc/keymaps/rc-winfast.c +++ b/drivers/media/rc/keymaps/rc-winfast.c | |||
| @@ -32,8 +32,8 @@ static struct rc_map_table winfast[] = { | |||
| 32 | { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ | 32 | { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ |
| 33 | { 0x1e, KEY_VIDEO }, /* Video Source */ | 33 | { 0x1e, KEY_VIDEO }, /* Video Source */ |
| 34 | { 0x16, KEY_INFO }, /* Display information */ | 34 | { 0x16, KEY_INFO }, /* Display information */ |
| 35 | { 0x04, KEY_LEFT }, | 35 | { 0x04, KEY_RIGHT }, |
| 36 | { 0x08, KEY_RIGHT }, | 36 | { 0x08, KEY_LEFT }, |
| 37 | { 0x0c, KEY_UP }, | 37 | { 0x0c, KEY_UP }, |
| 38 | { 0x10, KEY_DOWN }, | 38 | { 0x10, KEY_DOWN }, |
| 39 | { 0x03, KEY_ZOOM }, /* fullscreen */ | 39 | { 0x03, KEY_ZOOM }, /* fullscreen */ |
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 0c273ec465c9..ad927fcaa020 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c | |||
| @@ -149,6 +149,8 @@ enum mceusb_model_type { | |||
| 149 | POLARIS_EVK, | 149 | POLARIS_EVK, |
| 150 | CX_HYBRID_TV, | 150 | CX_HYBRID_TV, |
| 151 | MULTIFUNCTION, | 151 | MULTIFUNCTION, |
| 152 | TIVO_KIT, | ||
| 153 | MCE_GEN2_NO_TX, | ||
| 152 | }; | 154 | }; |
| 153 | 155 | ||
| 154 | struct mceusb_model { | 156 | struct mceusb_model { |
| @@ -172,6 +174,10 @@ static const struct mceusb_model mceusb_model[] = { | |||
| 172 | [MCE_GEN2] = { | 174 | [MCE_GEN2] = { |
| 173 | .mce_gen2 = 1, | 175 | .mce_gen2 = 1, |
| 174 | }, | 176 | }, |
| 177 | [MCE_GEN2_NO_TX] = { | ||
| 178 | .mce_gen2 = 1, | ||
| 179 | .no_tx = 1, | ||
| 180 | }, | ||
| 175 | [MCE_GEN2_TX_INV] = { | 181 | [MCE_GEN2_TX_INV] = { |
| 176 | .mce_gen2 = 1, | 182 | .mce_gen2 = 1, |
| 177 | .tx_mask_normal = 1, | 183 | .tx_mask_normal = 1, |
| @@ -197,6 +203,10 @@ static const struct mceusb_model mceusb_model[] = { | |||
| 197 | .mce_gen2 = 1, | 203 | .mce_gen2 = 1, |
| 198 | .ir_intfnum = 2, | 204 | .ir_intfnum = 2, |
| 199 | }, | 205 | }, |
| 206 | [TIVO_KIT] = { | ||
| 207 | .mce_gen2 = 1, | ||
| 208 | .rc_map = RC_MAP_TIVO, | ||
| 209 | }, | ||
| 200 | }; | 210 | }; |
| 201 | 211 | ||
| 202 | static struct usb_device_id mceusb_dev_table[] = { | 212 | static struct usb_device_id mceusb_dev_table[] = { |
| @@ -279,7 +289,8 @@ static struct usb_device_id mceusb_dev_table[] = { | |||
| 279 | /* Formosa21 / eHome Infrared Receiver */ | 289 | /* Formosa21 / eHome Infrared Receiver */ |
| 280 | { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, | 290 | { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, |
| 281 | /* Formosa aim / Trust MCE Infrared Receiver */ | 291 | /* Formosa aim / Trust MCE Infrared Receiver */ |
| 282 | { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, | 292 | { USB_DEVICE(VENDOR_FORMOSA, 0xe017), |
| 293 | .driver_info = MCE_GEN2_NO_TX }, | ||
| 283 | /* Formosa Industrial Computing / Beanbag Emulation Device */ | 294 | /* Formosa Industrial Computing / Beanbag Emulation Device */ |
| 284 | { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, | 295 | { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, |
| 285 | /* Formosa21 / eHome Infrared Receiver */ | 296 | /* Formosa21 / eHome Infrared Receiver */ |
| @@ -308,7 +319,8 @@ static struct usb_device_id mceusb_dev_table[] = { | |||
| 308 | /* Northstar Systems, Inc. eHome Infrared Transceiver */ | 319 | /* Northstar Systems, Inc. eHome Infrared Transceiver */ |
| 309 | { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, | 320 | { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, |
| 310 | /* TiVo PC IR Receiver */ | 321 | /* TiVo PC IR Receiver */ |
| 311 | { USB_DEVICE(VENDOR_TIVO, 0x2000) }, | 322 | { USB_DEVICE(VENDOR_TIVO, 0x2000), |
| 323 | .driver_info = TIVO_KIT }, | ||
| 312 | /* Conexant Hybrid TV "Shelby" Polaris SDK */ | 324 | /* Conexant Hybrid TV "Shelby" Polaris SDK */ |
| 313 | { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), | 325 | { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), |
| 314 | .driver_info = POLARIS_EVK }, | 326 | .driver_info = POLARIS_EVK }, |
| @@ -603,11 +615,10 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs) | |||
| 603 | } | 615 | } |
| 604 | 616 | ||
| 605 | /* request incoming or send outgoing usb packet - used to initialize remote */ | 617 | /* request incoming or send outgoing usb packet - used to initialize remote */ |
| 606 | static void mce_request_packet(struct mceusb_dev *ir, | 618 | static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, |
| 607 | struct usb_endpoint_descriptor *ep, | 619 | int size, int urb_type) |
| 608 | unsigned char *data, int size, int urb_type) | ||
| 609 | { | 620 | { |
| 610 | int res; | 621 | int res, pipe; |
| 611 | struct urb *async_urb; | 622 | struct urb *async_urb; |
| 612 | struct device *dev = ir->dev; | 623 | struct device *dev = ir->dev; |
| 613 | unsigned char *async_buf; | 624 | unsigned char *async_buf; |
| @@ -627,10 +638,11 @@ static void mce_request_packet(struct mceusb_dev *ir, | |||
| 627 | } | 638 | } |
| 628 | 639 | ||
| 629 | /* outbound data */ | 640 | /* outbound data */ |
| 630 | usb_fill_int_urb(async_urb, ir->usbdev, | 641 | pipe = usb_sndintpipe(ir->usbdev, |
| 631 | usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), | 642 | ir->usb_ep_out->bEndpointAddress); |
| 643 | usb_fill_int_urb(async_urb, ir->usbdev, pipe, | ||
| 632 | async_buf, size, (usb_complete_t)mce_async_callback, | 644 | async_buf, size, (usb_complete_t)mce_async_callback, |
| 633 | ir, ep->bInterval); | 645 | ir, ir->usb_ep_out->bInterval); |
| 634 | memcpy(async_buf, data, size); | 646 | memcpy(async_buf, data, size); |
| 635 | 647 | ||
| 636 | } else if (urb_type == MCEUSB_RX) { | 648 | } else if (urb_type == MCEUSB_RX) { |
| @@ -658,12 +670,12 @@ static void mce_request_packet(struct mceusb_dev *ir, | |||
| 658 | 670 | ||
| 659 | static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) | 671 | static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) |
| 660 | { | 672 | { |
| 661 | mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX); | 673 | mce_request_packet(ir, data, size, MCEUSB_TX); |
| 662 | } | 674 | } |
| 663 | 675 | ||
| 664 | static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) | 676 | static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) |
| 665 | { | 677 | { |
| 666 | mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); | 678 | mce_request_packet(ir, data, size, MCEUSB_RX); |
| 667 | } | 679 | } |
| 668 | 680 | ||
| 669 | /* Send data out the IR blaster port(s) */ | 681 | /* Send data out the IR blaster port(s) */ |
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index d4d64492a057..bf3060ea6107 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c | |||
| @@ -37,8 +37,6 @@ | |||
| 37 | 37 | ||
| 38 | #include "nuvoton-cir.h" | 38 | #include "nuvoton-cir.h" |
| 39 | 39 | ||
| 40 | static char *chip_id = "w836x7hg"; | ||
| 41 | |||
| 42 | /* write val to config reg */ | 40 | /* write val to config reg */ |
| 43 | static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) | 41 | static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) |
| 44 | { | 42 | { |
| @@ -233,6 +231,8 @@ static int nvt_hw_detect(struct nvt_dev *nvt) | |||
| 233 | unsigned long flags; | 231 | unsigned long flags; |
| 234 | u8 chip_major, chip_minor; | 232 | u8 chip_major, chip_minor; |
| 235 | int ret = 0; | 233 | int ret = 0; |
| 234 | char chip_id[12]; | ||
| 235 | bool chip_unknown = false; | ||
| 236 | 236 | ||
| 237 | nvt_efm_enable(nvt); | 237 | nvt_efm_enable(nvt); |
| 238 | 238 | ||
| @@ -246,15 +246,39 @@ static int nvt_hw_detect(struct nvt_dev *nvt) | |||
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); | 248 | chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); |
| 249 | nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); | ||
| 250 | 249 | ||
| 251 | if (chip_major != CHIP_ID_HIGH || | 250 | /* these are the known working chip revisions... */ |
| 252 | (chip_minor != CHIP_ID_LOW && chip_minor != CHIP_ID_LOW2)) { | 251 | switch (chip_major) { |
| 253 | nvt_pr(KERN_ERR, "%s: unsupported chip, id: 0x%02x 0x%02x", | 252 | case CHIP_ID_HIGH_667: |
| 254 | chip_id, chip_major, chip_minor); | 253 | strcpy(chip_id, "w83667hg\0"); |
| 255 | ret = -ENODEV; | 254 | if (chip_minor != CHIP_ID_LOW_667) |
| 255 | chip_unknown = true; | ||
| 256 | break; | ||
| 257 | case CHIP_ID_HIGH_677B: | ||
| 258 | strcpy(chip_id, "w83677hg\0"); | ||
| 259 | if (chip_minor != CHIP_ID_LOW_677B2 && | ||
| 260 | chip_minor != CHIP_ID_LOW_677B3) | ||
| 261 | chip_unknown = true; | ||
| 262 | break; | ||
| 263 | case CHIP_ID_HIGH_677C: | ||
| 264 | strcpy(chip_id, "w83677hg-c\0"); | ||
| 265 | if (chip_minor != CHIP_ID_LOW_677C) | ||
| 266 | chip_unknown = true; | ||
| 267 | break; | ||
| 268 | default: | ||
| 269 | strcpy(chip_id, "w836x7hg\0"); | ||
| 270 | chip_unknown = true; | ||
| 271 | break; | ||
| 256 | } | 272 | } |
| 257 | 273 | ||
| 274 | /* warn, but still let the driver load, if we don't know this chip */ | ||
| 275 | if (chip_unknown) | ||
| 276 | nvt_pr(KERN_WARNING, "%s: unknown chip, id: 0x%02x 0x%02x, " | ||
| 277 | "it may not work...", chip_id, chip_major, chip_minor); | ||
| 278 | else | ||
| 279 | nvt_dbg("%s: chip id: 0x%02x 0x%02x", | ||
| 280 | chip_id, chip_major, chip_minor); | ||
| 281 | |||
| 258 | nvt_efm_disable(nvt); | 282 | nvt_efm_disable(nvt); |
| 259 | 283 | ||
| 260 | spin_lock_irqsave(&nvt->nvt_lock, flags); | 284 | spin_lock_irqsave(&nvt->nvt_lock, flags); |
| @@ -267,13 +291,23 @@ static int nvt_hw_detect(struct nvt_dev *nvt) | |||
| 267 | 291 | ||
| 268 | static void nvt_cir_ldev_init(struct nvt_dev *nvt) | 292 | static void nvt_cir_ldev_init(struct nvt_dev *nvt) |
| 269 | { | 293 | { |
| 270 | u8 val; | 294 | u8 val, psreg, psmask, psval; |
| 295 | |||
| 296 | if (nvt->chip_major == CHIP_ID_HIGH_667) { | ||
| 297 | psreg = CR_MULTIFUNC_PIN_SEL; | ||
| 298 | psmask = MULTIFUNC_PIN_SEL_MASK; | ||
| 299 | psval = MULTIFUNC_ENABLE_CIR | MULTIFUNC_ENABLE_CIRWB; | ||
| 300 | } else { | ||
| 301 | psreg = CR_OUTPUT_PIN_SEL; | ||
| 302 | psmask = OUTPUT_PIN_SEL_MASK; | ||
| 303 | psval = OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB; | ||
| 304 | } | ||
| 271 | 305 | ||
| 272 | /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ | 306 | /* output pin selection: enable CIR, with WB sensor enabled */ |
| 273 | val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); | 307 | val = nvt_cr_read(nvt, psreg); |
| 274 | val &= OUTPUT_PIN_SEL_MASK; | 308 | val &= psmask; |
| 275 | val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); | 309 | val |= psval; |
| 276 | nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); | 310 | nvt_cr_write(nvt, val, psreg); |
| 277 | 311 | ||
| 278 | /* Select CIR logical device and enable */ | 312 | /* Select CIR logical device and enable */ |
| 279 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | 313 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); |
| @@ -640,7 +674,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) | |||
| 640 | rawir.pulse ? "pulse" : "space", | 674 | rawir.pulse ? "pulse" : "space", |
| 641 | rawir.duration); | 675 | rawir.duration); |
| 642 | 676 | ||
| 643 | ir_raw_event_store(nvt->rdev, &rawir); | 677 | ir_raw_event_store_with_filter(nvt->rdev, &rawir); |
| 644 | } | 678 | } |
| 645 | 679 | ||
| 646 | /* | 680 | /* |
| @@ -1070,18 +1104,20 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) | |||
| 1070 | rdev->tx_ir = nvt_tx_ir; | 1104 | rdev->tx_ir = nvt_tx_ir; |
| 1071 | rdev->s_tx_carrier = nvt_set_tx_carrier; | 1105 | rdev->s_tx_carrier = nvt_set_tx_carrier; |
| 1072 | rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver"; | 1106 | rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver"; |
| 1107 | rdev->input_phys = "nuvoton/cir0"; | ||
| 1073 | rdev->input_id.bustype = BUS_HOST; | 1108 | rdev->input_id.bustype = BUS_HOST; |
| 1074 | rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2; | 1109 | rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2; |
| 1075 | rdev->input_id.product = nvt->chip_major; | 1110 | rdev->input_id.product = nvt->chip_major; |
| 1076 | rdev->input_id.version = nvt->chip_minor; | 1111 | rdev->input_id.version = nvt->chip_minor; |
| 1112 | rdev->dev.parent = &pdev->dev; | ||
| 1077 | rdev->driver_name = NVT_DRIVER_NAME; | 1113 | rdev->driver_name = NVT_DRIVER_NAME; |
| 1078 | rdev->map_name = RC_MAP_RC6_MCE; | 1114 | rdev->map_name = RC_MAP_RC6_MCE; |
| 1115 | rdev->timeout = US_TO_NS(1000); | ||
| 1116 | /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ | ||
| 1117 | rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); | ||
| 1079 | #if 0 | 1118 | #if 0 |
| 1080 | rdev->min_timeout = XYZ; | 1119 | rdev->min_timeout = XYZ; |
| 1081 | rdev->max_timeout = XYZ; | 1120 | rdev->max_timeout = XYZ; |
| 1082 | rdev->timeout = XYZ; | ||
| 1083 | /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ | ||
| 1084 | rdev->rx_resolution = XYZ; | ||
| 1085 | /* tx bits */ | 1121 | /* tx bits */ |
| 1086 | rdev->tx_resolution = XYZ; | 1122 | rdev->tx_resolution = XYZ; |
| 1087 | #endif | 1123 | #endif |
| @@ -1090,8 +1126,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) | |||
| 1090 | if (ret) | 1126 | if (ret) |
| 1091 | goto failure; | 1127 | goto failure; |
| 1092 | 1128 | ||
| 1093 | device_set_wakeup_capable(&pdev->dev, 1); | 1129 | device_init_wakeup(&pdev->dev, true); |
| 1094 | device_set_wakeup_enable(&pdev->dev, 1); | ||
| 1095 | nvt->rdev = rdev; | 1130 | nvt->rdev = rdev; |
| 1096 | nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); | 1131 | nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); |
| 1097 | if (debug) { | 1132 | if (debug) { |
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 048135eea702..379795d61ea7 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h | |||
| @@ -330,9 +330,13 @@ struct nvt_dev { | |||
| 330 | #define EFER_EFM_DISABLE 0xaa | 330 | #define EFER_EFM_DISABLE 0xaa |
| 331 | 331 | ||
| 332 | /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ | 332 | /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ |
| 333 | #define CHIP_ID_HIGH 0xb4 | 333 | #define CHIP_ID_HIGH_667 0xa5 |
| 334 | #define CHIP_ID_LOW 0x72 | 334 | #define CHIP_ID_HIGH_677B 0xb4 |
| 335 | #define CHIP_ID_LOW2 0x73 | 335 | #define CHIP_ID_HIGH_677C 0xc3 |
| 336 | #define CHIP_ID_LOW_667 0x13 | ||
| 337 | #define CHIP_ID_LOW_677B2 0x72 | ||
| 338 | #define CHIP_ID_LOW_677B3 0x73 | ||
| 339 | #define CHIP_ID_LOW_677C 0x33 | ||
| 336 | 340 | ||
| 337 | /* Config regs we need to care about */ | 341 | /* Config regs we need to care about */ |
| 338 | #define CR_SOFTWARE_RESET 0x02 | 342 | #define CR_SOFTWARE_RESET 0x02 |
| @@ -341,6 +345,7 @@ struct nvt_dev { | |||
| 341 | #define CR_CHIP_ID_LO 0x21 | 345 | #define CR_CHIP_ID_LO 0x21 |
| 342 | #define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ | 346 | #define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ |
| 343 | #define CR_OUTPUT_PIN_SEL 0x27 | 347 | #define CR_OUTPUT_PIN_SEL 0x27 |
| 348 | #define CR_MULTIFUNC_PIN_SEL 0x2c | ||
| 344 | #define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ | 349 | #define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ |
| 345 | /* next three regs valid for both the CIR and CIR_WAKE logical devices */ | 350 | /* next three regs valid for both the CIR and CIR_WAKE logical devices */ |
| 346 | #define CR_CIR_BASE_ADDR_HI 0x60 | 351 | #define CR_CIR_BASE_ADDR_HI 0x60 |
| @@ -364,10 +369,16 @@ struct nvt_dev { | |||
| 364 | #define CIR_INTR_MOUSE_IRQ_BIT 0x80 | 369 | #define CIR_INTR_MOUSE_IRQ_BIT 0x80 |
| 365 | #define PME_INTR_CIR_PASS_BIT 0x08 | 370 | #define PME_INTR_CIR_PASS_BIT 0x08 |
| 366 | 371 | ||
| 372 | /* w83677hg CIR pin config */ | ||
| 367 | #define OUTPUT_PIN_SEL_MASK 0xbc | 373 | #define OUTPUT_PIN_SEL_MASK 0xbc |
| 368 | #define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ | 374 | #define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ |
| 369 | #define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ | 375 | #define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ |
| 370 | 376 | ||
| 377 | /* w83667hg CIR pin config */ | ||
| 378 | #define MULTIFUNC_PIN_SEL_MASK 0x1f | ||
| 379 | #define MULTIFUNC_ENABLE_CIR 0x80 /* Pin75=CIRRX, Pin76=CIRTX1 */ | ||
| 380 | #define MULTIFUNC_ENABLE_CIRWB 0x20 /* enable wide-band sensor */ | ||
| 381 | |||
| 371 | /* MCE CIR signal length, related on sample period */ | 382 | /* MCE CIR signal length, related on sample period */ |
| 372 | 383 | ||
| 373 | /* MCE CIR controller signal length: about 43ms | 384 | /* MCE CIR controller signal length: about 43ms |
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c index 49cee61d79c6..cc846b2619cf 100644 --- a/drivers/media/rc/rc-loopback.c +++ b/drivers/media/rc/rc-loopback.c | |||
| @@ -146,6 +146,12 @@ static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) | |||
| 146 | if (rawir.duration) | 146 | if (rawir.duration) |
| 147 | ir_raw_event_store_with_filter(dev, &rawir); | 147 | ir_raw_event_store_with_filter(dev, &rawir); |
| 148 | } | 148 | } |
| 149 | |||
| 150 | /* Fake a silence long enough to cause us to go idle */ | ||
| 151 | rawir.pulse = false; | ||
| 152 | rawir.duration = dev->timeout; | ||
| 153 | ir_raw_event_store_with_filter(dev, &rawir); | ||
| 154 | |||
| 149 | ir_raw_event_handle(dev); | 155 | ir_raw_event_handle(dev); |
| 150 | 156 | ||
| 151 | out: | 157 | out: |
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index a2706648e365..f57cd5677ac2 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
| @@ -749,6 +749,9 @@ static struct { | |||
| 749 | * it is trigged by reading /sys/class/rc/rc?/protocols. | 749 | * it is trigged by reading /sys/class/rc/rc?/protocols. |
| 750 | * It returns the protocol names of supported protocols. | 750 | * It returns the protocol names of supported protocols. |
| 751 | * Enabled protocols are printed in brackets. | 751 | * Enabled protocols are printed in brackets. |
| 752 | * | ||
| 753 | * dev->lock is taken to guard against races between device | ||
| 754 | * registration, store_protocols and show_protocols. | ||
| 752 | */ | 755 | */ |
| 753 | static ssize_t show_protocols(struct device *device, | 756 | static ssize_t show_protocols(struct device *device, |
| 754 | struct device_attribute *mattr, char *buf) | 757 | struct device_attribute *mattr, char *buf) |
| @@ -762,6 +765,8 @@ static ssize_t show_protocols(struct device *device, | |||
| 762 | if (!dev) | 765 | if (!dev) |
| 763 | return -EINVAL; | 766 | return -EINVAL; |
| 764 | 767 | ||
| 768 | mutex_lock(&dev->lock); | ||
| 769 | |||
| 765 | if (dev->driver_type == RC_DRIVER_SCANCODE) { | 770 | if (dev->driver_type == RC_DRIVER_SCANCODE) { |
| 766 | enabled = dev->rc_map.rc_type; | 771 | enabled = dev->rc_map.rc_type; |
| 767 | allowed = dev->allowed_protos; | 772 | allowed = dev->allowed_protos; |
| @@ -784,6 +789,9 @@ static ssize_t show_protocols(struct device *device, | |||
| 784 | if (tmp != buf) | 789 | if (tmp != buf) |
| 785 | tmp--; | 790 | tmp--; |
| 786 | *tmp = '\n'; | 791 | *tmp = '\n'; |
| 792 | |||
| 793 | mutex_unlock(&dev->lock); | ||
| 794 | |||
| 787 | return tmp + 1 - buf; | 795 | return tmp + 1 - buf; |
| 788 | } | 796 | } |
| 789 | 797 | ||
| @@ -802,6 +810,9 @@ static ssize_t show_protocols(struct device *device, | |||
| 802 | * Writing "none" will disable all protocols. | 810 | * Writing "none" will disable all protocols. |
| 803 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name | 811 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name |
| 804 | * is used, otherwise @len. | 812 | * is used, otherwise @len. |
| 813 | * | ||
| 814 | * dev->lock is taken to guard against races between device | ||
| 815 | * registration, store_protocols and show_protocols. | ||
| 805 | */ | 816 | */ |
| 806 | static ssize_t store_protocols(struct device *device, | 817 | static ssize_t store_protocols(struct device *device, |
| 807 | struct device_attribute *mattr, | 818 | struct device_attribute *mattr, |
| @@ -815,18 +826,22 @@ static ssize_t store_protocols(struct device *device, | |||
| 815 | u64 mask; | 826 | u64 mask; |
| 816 | int rc, i, count = 0; | 827 | int rc, i, count = 0; |
| 817 | unsigned long flags; | 828 | unsigned long flags; |
| 829 | ssize_t ret; | ||
| 818 | 830 | ||
| 819 | /* Device is being removed */ | 831 | /* Device is being removed */ |
| 820 | if (!dev) | 832 | if (!dev) |
| 821 | return -EINVAL; | 833 | return -EINVAL; |
| 822 | 834 | ||
| 835 | mutex_lock(&dev->lock); | ||
| 836 | |||
| 823 | if (dev->driver_type == RC_DRIVER_SCANCODE) | 837 | if (dev->driver_type == RC_DRIVER_SCANCODE) |
| 824 | type = dev->rc_map.rc_type; | 838 | type = dev->rc_map.rc_type; |
| 825 | else if (dev->raw) | 839 | else if (dev->raw) |
| 826 | type = dev->raw->enabled_protocols; | 840 | type = dev->raw->enabled_protocols; |
| 827 | else { | 841 | else { |
| 828 | IR_dprintk(1, "Protocol switching not supported\n"); | 842 | IR_dprintk(1, "Protocol switching not supported\n"); |
| 829 | return -EINVAL; | 843 | ret = -EINVAL; |
| 844 | goto out; | ||
| 830 | } | 845 | } |
| 831 | 846 | ||
| 832 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { | 847 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { |
| @@ -860,7 +875,8 @@ static ssize_t store_protocols(struct device *device, | |||
| 860 | } | 875 | } |
| 861 | if (i == ARRAY_SIZE(proto_names)) { | 876 | if (i == ARRAY_SIZE(proto_names)) { |
| 862 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); | 877 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); |
| 863 | return -EINVAL; | 878 | ret = -EINVAL; |
| 879 | goto out; | ||
| 864 | } | 880 | } |
| 865 | count++; | 881 | count++; |
| 866 | } | 882 | } |
| @@ -875,7 +891,8 @@ static ssize_t store_protocols(struct device *device, | |||
| 875 | 891 | ||
| 876 | if (!count) { | 892 | if (!count) { |
| 877 | IR_dprintk(1, "Protocol not specified\n"); | 893 | IR_dprintk(1, "Protocol not specified\n"); |
| 878 | return -EINVAL; | 894 | ret = -EINVAL; |
| 895 | goto out; | ||
| 879 | } | 896 | } |
| 880 | 897 | ||
| 881 | if (dev->change_protocol) { | 898 | if (dev->change_protocol) { |
| @@ -883,7 +900,8 @@ static ssize_t store_protocols(struct device *device, | |||
| 883 | if (rc < 0) { | 900 | if (rc < 0) { |
| 884 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", | 901 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", |
| 885 | (long long)type); | 902 | (long long)type); |
| 886 | return -EINVAL; | 903 | ret = -EINVAL; |
| 904 | goto out; | ||
| 887 | } | 905 | } |
| 888 | } | 906 | } |
| 889 | 907 | ||
| @@ -898,7 +916,11 @@ static ssize_t store_protocols(struct device *device, | |||
| 898 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", | 916 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", |
| 899 | (long long)type); | 917 | (long long)type); |
| 900 | 918 | ||
| 901 | return len; | 919 | ret = len; |
| 920 | |||
| 921 | out: | ||
| 922 | mutex_unlock(&dev->lock); | ||
| 923 | return ret; | ||
| 902 | } | 924 | } |
| 903 | 925 | ||
| 904 | static void rc_dev_release(struct device *device) | 926 | static void rc_dev_release(struct device *device) |
| @@ -974,6 +996,7 @@ struct rc_dev *rc_allocate_device(void) | |||
| 974 | 996 | ||
| 975 | spin_lock_init(&dev->rc_map.lock); | 997 | spin_lock_init(&dev->rc_map.lock); |
| 976 | spin_lock_init(&dev->keylock); | 998 | spin_lock_init(&dev->keylock); |
| 999 | mutex_init(&dev->lock); | ||
| 977 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); | 1000 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); |
| 978 | 1001 | ||
| 979 | dev->dev.type = &rc_dev_type; | 1002 | dev->dev.type = &rc_dev_type; |
| @@ -1019,12 +1042,21 @@ int rc_register_device(struct rc_dev *dev) | |||
| 1019 | if (dev->close) | 1042 | if (dev->close) |
| 1020 | dev->input_dev->close = ir_close; | 1043 | dev->input_dev->close = ir_close; |
| 1021 | 1044 | ||
| 1045 | /* | ||
| 1046 | * Take the lock here, as the device sysfs node will appear | ||
| 1047 | * when device_add() is called, which may trigger an ir-keytable udev | ||
| 1048 | * rule, which will in turn call show_protocols and access either | ||
| 1049 | * dev->rc_map.rc_type or dev->raw->enabled_protocols before it has | ||
| 1050 | * been initialized. | ||
| 1051 | */ | ||
| 1052 | mutex_lock(&dev->lock); | ||
| 1053 | |||
| 1022 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); | 1054 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); |
| 1023 | dev_set_name(&dev->dev, "rc%ld", dev->devno); | 1055 | dev_set_name(&dev->dev, "rc%ld", dev->devno); |
| 1024 | dev_set_drvdata(&dev->dev, dev); | 1056 | dev_set_drvdata(&dev->dev, dev); |
| 1025 | rc = device_add(&dev->dev); | 1057 | rc = device_add(&dev->dev); |
| 1026 | if (rc) | 1058 | if (rc) |
| 1027 | return rc; | 1059 | goto out_unlock; |
| 1028 | 1060 | ||
| 1029 | rc = ir_setkeytable(dev, rc_map); | 1061 | rc = ir_setkeytable(dev, rc_map); |
| 1030 | if (rc) | 1062 | if (rc) |
| @@ -1046,6 +1078,13 @@ int rc_register_device(struct rc_dev *dev) | |||
| 1046 | */ | 1078 | */ |
| 1047 | dev->input_dev->rep[REP_DELAY] = 500; | 1079 | dev->input_dev->rep[REP_DELAY] = 500; |
| 1048 | 1080 | ||
| 1081 | /* | ||
| 1082 | * As a repeat event on protocols like RC-5 and NEC take as long as | ||
| 1083 | * 110/114ms, using 33ms as a repeat period is not the right thing | ||
| 1084 | * to do. | ||
| 1085 | */ | ||
| 1086 | dev->input_dev->rep[REP_PERIOD] = 125; | ||
| 1087 | |||
| 1049 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); | 1088 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); |
| 1050 | printk(KERN_INFO "%s: %s as %s\n", | 1089 | printk(KERN_INFO "%s: %s as %s\n", |
| 1051 | dev_name(&dev->dev), | 1090 | dev_name(&dev->dev), |
| @@ -1058,6 +1097,7 @@ int rc_register_device(struct rc_dev *dev) | |||
| 1058 | if (rc < 0) | 1097 | if (rc < 0) |
| 1059 | goto out_input; | 1098 | goto out_input; |
| 1060 | } | 1099 | } |
| 1100 | mutex_unlock(&dev->lock); | ||
| 1061 | 1101 | ||
| 1062 | if (dev->change_protocol) { | 1102 | if (dev->change_protocol) { |
| 1063 | rc = dev->change_protocol(dev, rc_map->rc_type); | 1103 | rc = dev->change_protocol(dev, rc_map->rc_type); |
| @@ -1083,6 +1123,8 @@ out_table: | |||
| 1083 | ir_free_table(&dev->rc_map); | 1123 | ir_free_table(&dev->rc_map); |
| 1084 | out_dev: | 1124 | out_dev: |
| 1085 | device_del(&dev->dev); | 1125 | device_del(&dev->dev); |
| 1126 | out_unlock: | ||
| 1127 | mutex_unlock(&dev->lock); | ||
| 1086 | return rc; | 1128 | return rc; |
| 1087 | } | 1129 | } |
| 1088 | EXPORT_SYMBOL_GPL(rc_register_device); | 1130 | EXPORT_SYMBOL_GPL(rc_register_device); |
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c new file mode 100644 index 000000000000..5147767ccb78 --- /dev/null +++ b/drivers/media/rc/redrat3.c | |||
| @@ -0,0 +1,1344 @@ | |||
| 1 | /* | ||
| 2 | * USB RedRat3 IR Transceiver rc-core driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011 by Jarod Wilson <jarod@redhat.com> | ||
| 5 | * based heavily on the work of Stephen Cox, with additional | ||
| 6 | * help from RedRat Ltd. | ||
| 7 | * | ||
| 8 | * This driver began life based an an old version of the first-generation | ||
| 9 | * lirc_mceusb driver from the lirc 0.7.2 distribution. It was then | ||
| 10 | * significantly rewritten by Stephen Cox with the aid of RedRat Ltd's | ||
| 11 | * Chris Dodge. | ||
| 12 | * | ||
| 13 | * The driver was then ported to rc-core and significantly rewritten again, | ||
| 14 | * by Jarod, using the in-kernel mceusb driver as a guide, after an initial | ||
| 15 | * port effort was started by Stephen. | ||
| 16 | * | ||
| 17 | * TODO LIST: | ||
| 18 | * - fix lirc not showing repeats properly | ||
| 19 | * -- | ||
| 20 | * | ||
| 21 | * The RedRat3 is a USB transceiver with both send & receive, | ||
| 22 | * with 2 separate sensors available for receive to enable | ||
| 23 | * both good long range reception for general use, and good | ||
| 24 | * short range reception when required for learning a signal. | ||
| 25 | * | ||
| 26 | * http://www.redrat.co.uk/ | ||
| 27 | * | ||
| 28 | * It uses its own little protocol to communicate, the required | ||
| 29 | * parts of which are embedded within this driver. | ||
| 30 | * -- | ||
| 31 | * | ||
| 32 | * This program is free software; you can redistribute it and/or modify | ||
| 33 | * it under the terms of the GNU General Public License as published by | ||
| 34 | * the Free Software Foundation; either version 2 of the License, or | ||
| 35 | * (at your option) any later version. | ||
| 36 | * | ||
| 37 | * This program is distributed in the hope that it will be useful, | ||
| 38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 40 | * GNU General Public License for more details. | ||
| 41 | * | ||
| 42 | * You should have received a copy of the GNU General Public License | ||
| 43 | * along with this program; if not, write to the Free Software | ||
| 44 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 45 | * | ||
| 46 | */ | ||
| 47 | |||
| 48 | #include <linux/device.h> | ||
| 49 | #include <linux/module.h> | ||
| 50 | #include <linux/slab.h> | ||
| 51 | #include <linux/usb.h> | ||
| 52 | #include <linux/usb/input.h> | ||
| 53 | #include <media/rc-core.h> | ||
| 54 | |||
| 55 | /* Driver Information */ | ||
| 56 | #define DRIVER_VERSION "0.70" | ||
| 57 | #define DRIVER_AUTHOR "Jarod Wilson <jarod@redhat.com>" | ||
| 58 | #define DRIVER_AUTHOR2 "The Dweller, Stephen Cox" | ||
| 59 | #define DRIVER_DESC "RedRat3 USB IR Transceiver Driver" | ||
| 60 | #define DRIVER_NAME "redrat3" | ||
| 61 | |||
| 62 | /* module parameters */ | ||
| 63 | #ifdef CONFIG_USB_DEBUG | ||
| 64 | static int debug = 1; | ||
| 65 | #else | ||
| 66 | static int debug; | ||
| 67 | #endif | ||
| 68 | |||
| 69 | #define RR3_DEBUG_STANDARD 0x1 | ||
| 70 | #define RR3_DEBUG_FUNCTION_TRACE 0x2 | ||
| 71 | |||
| 72 | #define rr3_dbg(dev, fmt, ...) \ | ||
| 73 | do { \ | ||
| 74 | if (debug & RR3_DEBUG_STANDARD) \ | ||
| 75 | dev_info(dev, fmt, ## __VA_ARGS__); \ | ||
| 76 | } while (0) | ||
| 77 | |||
| 78 | #define rr3_ftr(dev, fmt, ...) \ | ||
| 79 | do { \ | ||
| 80 | if (debug & RR3_DEBUG_FUNCTION_TRACE) \ | ||
| 81 | dev_info(dev, fmt, ## __VA_ARGS__); \ | ||
| 82 | } while (0) | ||
| 83 | |||
| 84 | /* bulk data transfer types */ | ||
| 85 | #define RR3_ERROR 0x01 | ||
| 86 | #define RR3_MOD_SIGNAL_IN 0x20 | ||
| 87 | #define RR3_MOD_SIGNAL_OUT 0x21 | ||
| 88 | |||
| 89 | /* Get the RR firmware version */ | ||
| 90 | #define RR3_FW_VERSION 0xb1 | ||
| 91 | #define RR3_FW_VERSION_LEN 64 | ||
| 92 | /* Send encoded signal bulk-sent earlier*/ | ||
| 93 | #define RR3_TX_SEND_SIGNAL 0xb3 | ||
| 94 | #define RR3_SET_IR_PARAM 0xb7 | ||
| 95 | #define RR3_GET_IR_PARAM 0xb8 | ||
| 96 | /* Blink the red LED on the device */ | ||
| 97 | #define RR3_BLINK_LED 0xb9 | ||
| 98 | /* Read serial number of device */ | ||
| 99 | #define RR3_READ_SER_NO 0xba | ||
| 100 | #define RR3_SER_NO_LEN 4 | ||
| 101 | /* Start capture with the RC receiver */ | ||
| 102 | #define RR3_RC_DET_ENABLE 0xbb | ||
| 103 | /* Stop capture with the RC receiver */ | ||
| 104 | #define RR3_RC_DET_DISABLE 0xbc | ||
| 105 | /* Return the status of RC detector capture */ | ||
| 106 | #define RR3_RC_DET_STATUS 0xbd | ||
| 107 | /* Reset redrat */ | ||
| 108 | #define RR3_RESET 0xa0 | ||
| 109 | |||
| 110 | /* Max number of lengths in the signal. */ | ||
| 111 | #define RR3_IR_IO_MAX_LENGTHS 0x01 | ||
| 112 | /* Periods to measure mod. freq. */ | ||
| 113 | #define RR3_IR_IO_PERIODS_MF 0x02 | ||
| 114 | /* Size of memory for main signal data */ | ||
| 115 | #define RR3_IR_IO_SIG_MEM_SIZE 0x03 | ||
| 116 | /* Delta value when measuring lengths */ | ||
| 117 | #define RR3_IR_IO_LENGTH_FUZZ 0x04 | ||
| 118 | /* Timeout for end of signal detection */ | ||
| 119 | #define RR3_IR_IO_SIG_TIMEOUT 0x05 | ||
| 120 | /* Minumum value for pause recognition. */ | ||
| 121 | #define RR3_IR_IO_MIN_PAUSE 0x06 | ||
| 122 | |||
| 123 | /* Clock freq. of EZ-USB chip */ | ||
| 124 | #define RR3_CLK 24000000 | ||
| 125 | /* Clock periods per timer count */ | ||
| 126 | #define RR3_CLK_PER_COUNT 12 | ||
| 127 | /* (RR3_CLK / RR3_CLK_PER_COUNT) */ | ||
| 128 | #define RR3_CLK_CONV_FACTOR 2000000 | ||
| 129 | /* USB bulk-in IR data endpoint address */ | ||
| 130 | #define RR3_BULK_IN_EP_ADDR 0x82 | ||
| 131 | |||
| 132 | /* Raw Modulated signal data value offsets */ | ||
| 133 | #define RR3_PAUSE_OFFSET 0 | ||
| 134 | #define RR3_FREQ_COUNT_OFFSET 4 | ||
| 135 | #define RR3_NUM_PERIOD_OFFSET 6 | ||
| 136 | #define RR3_MAX_LENGTHS_OFFSET 8 | ||
| 137 | #define RR3_NUM_LENGTHS_OFFSET 9 | ||
| 138 | #define RR3_MAX_SIGS_OFFSET 10 | ||
| 139 | #define RR3_NUM_SIGS_OFFSET 12 | ||
| 140 | #define RR3_REPEATS_OFFSET 14 | ||
| 141 | |||
| 142 | /* Size of the fixed-length portion of the signal */ | ||
| 143 | #define RR3_HEADER_LENGTH 15 | ||
| 144 | #define RR3_DRIVER_MAXLENS 128 | ||
| 145 | #define RR3_MAX_SIG_SIZE 512 | ||
| 146 | #define RR3_MAX_BUF_SIZE \ | ||
| 147 | ((2 * RR3_HEADER_LENGTH) + RR3_DRIVER_MAXLENS + RR3_MAX_SIG_SIZE) | ||
| 148 | #define RR3_TIME_UNIT 50 | ||
| 149 | #define RR3_END_OF_SIGNAL 0x7f | ||
| 150 | #define RR3_TX_HEADER_OFFSET 4 | ||
| 151 | #define RR3_TX_TRAILER_LEN 2 | ||
| 152 | #define RR3_RX_MIN_TIMEOUT 5 | ||
| 153 | #define RR3_RX_MAX_TIMEOUT 2000 | ||
| 154 | |||
| 155 | /* The 8051's CPUCS Register address */ | ||
| 156 | #define RR3_CPUCS_REG_ADDR 0x7f92 | ||
| 157 | |||
| 158 | #define USB_RR3USB_VENDOR_ID 0x112a | ||
| 159 | #define USB_RR3USB_PRODUCT_ID 0x0001 | ||
| 160 | #define USB_RR3IIUSB_PRODUCT_ID 0x0005 | ||
| 161 | |||
| 162 | /* table of devices that work with this driver */ | ||
| 163 | static struct usb_device_id redrat3_dev_table[] = { | ||
| 164 | /* Original version of the RedRat3 */ | ||
| 165 | {USB_DEVICE(USB_RR3USB_VENDOR_ID, USB_RR3USB_PRODUCT_ID)}, | ||
| 166 | /* Second Version/release of the RedRat3 - RetRat3-II */ | ||
| 167 | {USB_DEVICE(USB_RR3USB_VENDOR_ID, USB_RR3IIUSB_PRODUCT_ID)}, | ||
| 168 | {} /* Terminating entry */ | ||
| 169 | }; | ||
| 170 | |||
| 171 | /* Structure to hold all of our device specific stuff */ | ||
| 172 | struct redrat3_dev { | ||
| 173 | /* core device bits */ | ||
| 174 | struct rc_dev *rc; | ||
| 175 | struct device *dev; | ||
| 176 | |||
| 177 | /* save off the usb device pointer */ | ||
| 178 | struct usb_device *udev; | ||
| 179 | |||
| 180 | /* the receive endpoint */ | ||
| 181 | struct usb_endpoint_descriptor *ep_in; | ||
| 182 | /* the buffer to receive data */ | ||
| 183 | unsigned char *bulk_in_buf; | ||
| 184 | /* urb used to read ir data */ | ||
| 185 | struct urb *read_urb; | ||
| 186 | |||
| 187 | /* the send endpoint */ | ||
| 188 | struct usb_endpoint_descriptor *ep_out; | ||
| 189 | /* the buffer to send data */ | ||
| 190 | unsigned char *bulk_out_buf; | ||
| 191 | /* the urb used to send data */ | ||
| 192 | struct urb *write_urb; | ||
| 193 | |||
| 194 | /* usb dma */ | ||
| 195 | dma_addr_t dma_in; | ||
| 196 | dma_addr_t dma_out; | ||
| 197 | |||
| 198 | /* true if write urb is busy */ | ||
| 199 | bool write_busy; | ||
| 200 | /* wait for the write to finish */ | ||
| 201 | struct completion write_finished; | ||
| 202 | |||
| 203 | /* locks this structure */ | ||
| 204 | struct mutex lock; | ||
| 205 | |||
| 206 | /* rx signal timeout timer */ | ||
| 207 | struct timer_list rx_timeout; | ||
| 208 | |||
| 209 | /* Is the device currently receiving? */ | ||
| 210 | bool recv_in_progress; | ||
| 211 | /* is the detector enabled*/ | ||
| 212 | bool det_enabled; | ||
| 213 | /* Is the device currently transmitting?*/ | ||
| 214 | bool transmitting; | ||
| 215 | |||
| 216 | /* store for current packet */ | ||
| 217 | char pbuf[RR3_MAX_BUF_SIZE]; | ||
| 218 | u16 pktlen; | ||
| 219 | u16 pkttype; | ||
| 220 | u16 bytes_read; | ||
| 221 | /* indicate whether we are going to reprocess | ||
| 222 | * the USB callback with a bigger buffer */ | ||
| 223 | int buftoosmall; | ||
| 224 | char *datap; | ||
| 225 | |||
| 226 | u32 carrier; | ||
| 227 | |||
| 228 | char name[128]; | ||
| 229 | char phys[64]; | ||
| 230 | }; | ||
| 231 | |||
| 232 | /* All incoming data buffers adhere to a very specific data format */ | ||
| 233 | struct redrat3_signal_header { | ||
| 234 | u16 length; /* Length of data being transferred */ | ||
| 235 | u16 transfer_type; /* Type of data transferred */ | ||
| 236 | u32 pause; /* Pause between main and repeat signals */ | ||
| 237 | u16 mod_freq_count; /* Value of timer on mod. freq. measurement */ | ||
| 238 | u16 no_periods; /* No. of periods over which mod. freq. is measured */ | ||
| 239 | u8 max_lengths; /* Max no. of lengths (i.e. size of array) */ | ||
| 240 | u8 no_lengths; /* Actual no. of elements in lengths array */ | ||
| 241 | u16 max_sig_size; /* Max no. of values in signal data array */ | ||
| 242 | u16 sig_size; /* Acuto no. of values in signal data array */ | ||
| 243 | u8 no_repeats; /* No. of repeats of repeat signal section */ | ||
| 244 | /* Here forward is the lengths and signal data */ | ||
| 245 | }; | ||
| 246 | |||
| 247 | static void redrat3_dump_signal_header(struct redrat3_signal_header *header) | ||
| 248 | { | ||
| 249 | pr_info("%s:\n", __func__); | ||
| 250 | pr_info(" * length: %u, transfer_type: 0x%02x\n", | ||
| 251 | header->length, header->transfer_type); | ||
| 252 | pr_info(" * pause: %u, freq_count: %u, no_periods: %u\n", | ||
| 253 | header->pause, header->mod_freq_count, header->no_periods); | ||
| 254 | pr_info(" * lengths: %u (max: %u)\n", | ||
| 255 | header->no_lengths, header->max_lengths); | ||
| 256 | pr_info(" * sig_size: %u (max: %u)\n", | ||
| 257 | header->sig_size, header->max_sig_size); | ||
| 258 | pr_info(" * repeats: %u\n", header->no_repeats); | ||
| 259 | } | ||
| 260 | |||
| 261 | static void redrat3_dump_signal_data(char *buffer, u16 len) | ||
| 262 | { | ||
| 263 | int offset, i; | ||
| 264 | char *data_vals; | ||
| 265 | |||
| 266 | pr_info("%s:", __func__); | ||
| 267 | |||
| 268 | offset = RR3_TX_HEADER_OFFSET + RR3_HEADER_LENGTH | ||
| 269 | + (RR3_DRIVER_MAXLENS * sizeof(u16)); | ||
| 270 | |||
| 271 | /* read RR3_DRIVER_MAXLENS from ctrl msg */ | ||
| 272 | data_vals = buffer + offset; | ||
| 273 | |||
| 274 | for (i = 0; i < len; i++) { | ||
| 275 | if (i % 10 == 0) | ||
| 276 | pr_cont("\n * "); | ||
| 277 | pr_cont("%02x ", *data_vals++); | ||
| 278 | } | ||
| 279 | |||
| 280 | pr_cont("\n"); | ||
| 281 | } | ||
| 282 | |||
| 283 | /* | ||
| 284 | * redrat3_issue_async | ||
| 285 | * | ||
| 286 | * Issues an async read to the ir data in port.. | ||
| 287 | * sets the callback to be redrat3_handle_async | ||
| 288 | */ | ||
| 289 | static void redrat3_issue_async(struct redrat3_dev *rr3) | ||
| 290 | { | ||
| 291 | int res; | ||
| 292 | |||
| 293 | rr3_ftr(rr3->dev, "Entering %s\n", __func__); | ||
| 294 | |||
| 295 | if (!rr3->det_enabled) { | ||
| 296 | dev_warn(rr3->dev, "not issuing async read, " | ||
| 297 | "detector not enabled\n"); | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | |||
| 301 | memset(rr3->bulk_in_buf, 0, rr3->ep_in->wMaxPacketSize); | ||
| 302 | res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC); | ||
| 303 | if (res) | ||
| 304 | rr3_dbg(rr3->dev, "%s: receive request FAILED! " | ||
| 305 | "(res %d, len %d)\n", __func__, res, | ||
| 306 | rr3->read_urb->transfer_buffer_length); | ||
| 307 | } | ||
| 308 | |||
| 309 | static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code) | ||
| 310 | { | ||
| 311 | if (!rr3->transmitting && (code != 0x40)) | ||
| 312 | dev_info(rr3->dev, "fw error code 0x%02x: ", code); | ||
| 313 | |||
| 314 | switch (code) { | ||
| 315 | case 0x00: | ||
| 316 | pr_cont("No Error\n"); | ||
| 317 | break; | ||
| 318 | |||
| 319 | /* Codes 0x20 through 0x2f are IR Firmware Errors */ | ||
| 320 | case 0x20: | ||
| 321 | pr_cont("Initial signal pulse not long enough " | ||
| 322 | "to measure carrier frequency\n"); | ||
| 323 | break; | ||
| 324 | case 0x21: | ||
| 325 | pr_cont("Not enough length values allocated for signal\n"); | ||
| 326 | break; | ||
| 327 | case 0x22: | ||
| 328 | pr_cont("Not enough memory allocated for signal data\n"); | ||
| 329 | break; | ||
| 330 | case 0x23: | ||
| 331 | pr_cont("Too many signal repeats\n"); | ||
| 332 | break; | ||
| 333 | case 0x28: | ||
| 334 | pr_cont("Insufficient memory available for IR signal " | ||
| 335 | "data memory allocation\n"); | ||
| 336 | break; | ||
| 337 | case 0x29: | ||
| 338 | pr_cont("Insufficient memory available " | ||
| 339 | "for IrDa signal data memory allocation\n"); | ||
| 340 | break; | ||
| 341 | |||
| 342 | /* Codes 0x30 through 0x3f are USB Firmware Errors */ | ||
| 343 | case 0x30: | ||
| 344 | pr_cont("Insufficient memory available for bulk " | ||
| 345 | "transfer structure\n"); | ||
| 346 | break; | ||
| 347 | |||
| 348 | /* | ||
| 349 | * Other error codes... These are primarily errors that can occur in | ||
| 350 | * the control messages sent to the redrat | ||
| 351 | */ | ||
| 352 | case 0x40: | ||
| 353 | if (!rr3->transmitting) | ||
| 354 | pr_cont("Signal capture has been terminated\n"); | ||
| 355 | break; | ||
| 356 | case 0x41: | ||
| 357 | pr_cont("Attempt to set/get and unknown signal I/O " | ||
| 358 | "algorithm parameter\n"); | ||
| 359 | break; | ||
| 360 | case 0x42: | ||
| 361 | pr_cont("Signal capture already started\n"); | ||
| 362 | break; | ||
| 363 | |||
| 364 | default: | ||
| 365 | pr_cont("Unknown Error\n"); | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 | static u32 redrat3_val_to_mod_freq(struct redrat3_signal_header *ph) | ||
| 371 | { | ||
| 372 | u32 mod_freq = 0; | ||
| 373 | |||
| 374 | if (ph->mod_freq_count != 0) | ||
| 375 | mod_freq = (RR3_CLK * ph->no_periods) / | ||
| 376 | (ph->mod_freq_count * RR3_CLK_PER_COUNT); | ||
| 377 | |||
| 378 | return mod_freq; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* this function scales down the figures for the same result... */ | ||
| 382 | static u32 redrat3_len_to_us(u32 length) | ||
| 383 | { | ||
| 384 | u32 biglen = length * 1000; | ||
| 385 | u32 divisor = (RR3_CLK_CONV_FACTOR) / 1000; | ||
| 386 | u32 result = (u32) (biglen / divisor); | ||
| 387 | |||
| 388 | /* don't allow zero lengths to go back, breaks lirc */ | ||
| 389 | return result ? result : 1; | ||
| 390 | } | ||
| 391 | |||
| 392 | /* | ||
| 393 | * convert us back into redrat3 lengths | ||
| 394 | * | ||
| 395 | * length * 1000 length * 1000000 | ||
| 396 | * ------------- = ---------------- = micro | ||
| 397 | * rr3clk / 1000 rr3clk | ||
| 398 | |||
| 399 | * 6 * 2 4 * 3 micro * rr3clk micro * rr3clk / 1000 | ||
| 400 | * ----- = 4 ----- = 6 -------------- = len --------------------- | ||
| 401 | * 3 2 1000000 1000 | ||
| 402 | */ | ||
| 403 | static u32 redrat3_us_to_len(u32 microsec) | ||
| 404 | { | ||
| 405 | u32 result; | ||
| 406 | u32 divisor; | ||
| 407 | |||
| 408 | microsec &= IR_MAX_DURATION; | ||
| 409 | divisor = (RR3_CLK_CONV_FACTOR / 1000); | ||
| 410 | result = (u32)(microsec * divisor) / 1000; | ||
| 411 | |||
| 412 | /* don't allow zero lengths to go back, breaks lirc */ | ||
| 413 | return result ? result : 1; | ||
| 414 | |||
| 415 | } | ||
| 416 | |||
| 417 | /* timer callback to send long trailing space on receive timeout */ | ||
| 418 | static void redrat3_rx_timeout(unsigned long data) | ||
| 419 | { | ||
| 420 | struct redrat3_dev *rr3 = (struct redrat3_dev *)data; | ||
| 421 | DEFINE_IR_RAW_EVENT(rawir); | ||
| 422 | |||
| 423 | rawir.pulse = false; | ||
| 424 | rawir.duration = rr3->rc->timeout; | ||
| 425 | rr3_dbg(rr3->dev, "storing trailing space with duration %d\n", | ||
| 426 | rawir.duration); | ||
| 427 | ir_raw_event_store_with_filter(rr3->rc, &rawir); | ||
| 428 | |||
| 429 | rr3_dbg(rr3->dev, "calling ir_raw_event_handle\n"); | ||
| 430 | ir_raw_event_handle(rr3->rc); | ||
| 431 | |||
| 432 | rr3_dbg(rr3->dev, "calling ir_raw_event_reset\n"); | ||
| 433 | ir_raw_event_reset(rr3->rc); | ||
| 434 | } | ||
| 435 | |||
| 436 | static void redrat3_process_ir_data(struct redrat3_dev *rr3) | ||
| 437 | { | ||
| 438 | DEFINE_IR_RAW_EVENT(rawir); | ||
| 439 | struct redrat3_signal_header header; | ||
| 440 | struct device *dev; | ||
| 441 | int i; | ||
| 442 | unsigned long delay; | ||
| 443 | u32 mod_freq, single_len; | ||
| 444 | u16 *len_vals; | ||
| 445 | u8 *data_vals; | ||
| 446 | u32 tmp32; | ||
| 447 | u16 tmp16; | ||
| 448 | char *sig_data; | ||
| 449 | |||
| 450 | if (!rr3) { | ||
| 451 | pr_err("%s called with no context!\n", __func__); | ||
| 452 | return; | ||
| 453 | } | ||
| 454 | |||
| 455 | rr3_ftr(rr3->dev, "Entered %s\n", __func__); | ||
| 456 | |||
| 457 | dev = rr3->dev; | ||
| 458 | sig_data = rr3->pbuf; | ||
| 459 | |||
| 460 | header.length = rr3->pktlen; | ||
| 461 | header.transfer_type = rr3->pkttype; | ||
| 462 | |||
| 463 | /* Sanity check */ | ||
| 464 | if (!(header.length >= RR3_HEADER_LENGTH)) | ||
| 465 | dev_warn(dev, "read returned less than rr3 header len\n"); | ||
| 466 | |||
| 467 | delay = usecs_to_jiffies(rr3->rc->timeout / 1000); | ||
| 468 | mod_timer(&rr3->rx_timeout, jiffies + delay); | ||
| 469 | |||
| 470 | memcpy(&tmp32, sig_data + RR3_PAUSE_OFFSET, sizeof(tmp32)); | ||
| 471 | header.pause = be32_to_cpu(tmp32); | ||
| 472 | |||
| 473 | memcpy(&tmp16, sig_data + RR3_FREQ_COUNT_OFFSET, sizeof(tmp16)); | ||
| 474 | header.mod_freq_count = be16_to_cpu(tmp16); | ||
| 475 | |||
| 476 | memcpy(&tmp16, sig_data + RR3_NUM_PERIOD_OFFSET, sizeof(tmp16)); | ||
| 477 | header.no_periods = be16_to_cpu(tmp16); | ||
| 478 | |||
| 479 | header.max_lengths = sig_data[RR3_MAX_LENGTHS_OFFSET]; | ||
| 480 | header.no_lengths = sig_data[RR3_NUM_LENGTHS_OFFSET]; | ||
| 481 | |||
| 482 | memcpy(&tmp16, sig_data + RR3_MAX_SIGS_OFFSET, sizeof(tmp16)); | ||
| 483 | header.max_sig_size = be16_to_cpu(tmp16); | ||
| 484 | |||
| 485 | memcpy(&tmp16, sig_data + RR3_NUM_SIGS_OFFSET, sizeof(tmp16)); | ||
| 486 | header.sig_size = be16_to_cpu(tmp16); | ||
| 487 | |||
| 488 | header.no_repeats= sig_data[RR3_REPEATS_OFFSET]; | ||
| 489 | |||
| 490 | if (debug) { | ||
| 491 | redrat3_dump_signal_header(&header); | ||
| 492 | redrat3_dump_signal_data(sig_data, header.sig_size); | ||
| 493 | } | ||
| 494 | |||
| 495 | mod_freq = redrat3_val_to_mod_freq(&header); | ||
| 496 | rr3_dbg(dev, "Got mod_freq of %u\n", mod_freq); | ||
| 497 | |||
| 498 | /* Here we pull out the 'length' values from the signal */ | ||
| 499 | len_vals = (u16 *)(sig_data + RR3_HEADER_LENGTH); | ||
| 500 | |||
| 501 | data_vals = sig_data + RR3_HEADER_LENGTH + | ||
| 502 | (header.max_lengths * sizeof(u16)); | ||
| 503 | |||
| 504 | /* process each rr3 encoded byte into an int */ | ||
| 505 | for (i = 0; i < header.sig_size; i++) { | ||
| 506 | u16 val = len_vals[data_vals[i]]; | ||
| 507 | single_len = redrat3_len_to_us((u32)be16_to_cpu(val)); | ||
| 508 | |||
| 509 | /* cap the value to IR_MAX_DURATION */ | ||
| 510 | single_len &= IR_MAX_DURATION; | ||
| 511 | |||
| 512 | /* we should always get pulse/space/pulse/space samples */ | ||
| 513 | if (i % 2) | ||
| 514 | rawir.pulse = false; | ||
| 515 | else | ||
| 516 | rawir.pulse = true; | ||
| 517 | |||
| 518 | rawir.duration = US_TO_NS(single_len); | ||
| 519 | rr3_dbg(dev, "storing %s with duration %d (i: %d)\n", | ||
| 520 | rawir.pulse ? "pulse" : "space", rawir.duration, i); | ||
| 521 | ir_raw_event_store_with_filter(rr3->rc, &rawir); | ||
| 522 | } | ||
| 523 | |||
| 524 | /* add a trailing space, if need be */ | ||
| 525 | if (i % 2) { | ||
| 526 | rawir.pulse = false; | ||
| 527 | /* this duration is made up, and may not be ideal... */ | ||
| 528 | rawir.duration = rr3->rc->timeout / 2; | ||
| 529 | rr3_dbg(dev, "storing trailing space with duration %d\n", | ||
| 530 | rawir.duration); | ||
| 531 | ir_raw_event_store_with_filter(rr3->rc, &rawir); | ||
| 532 | } | ||
| 533 | |||
| 534 | rr3_dbg(dev, "calling ir_raw_event_handle\n"); | ||
| 535 | ir_raw_event_handle(rr3->rc); | ||
| 536 | |||
| 537 | return; | ||
| 538 | } | ||
| 539 | |||
| 540 | /* Util fn to send rr3 cmds */ | ||
| 541 | static u8 redrat3_send_cmd(int cmd, struct redrat3_dev *rr3) | ||
| 542 | { | ||
| 543 | struct usb_device *udev; | ||
| 544 | u8 *data; | ||
| 545 | int res; | ||
| 546 | |||
| 547 | data = kzalloc(sizeof(u8), GFP_KERNEL); | ||
| 548 | if (!data) | ||
| 549 | return -ENOMEM; | ||
| 550 | |||
| 551 | udev = rr3->udev; | ||
| 552 | res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), cmd, | ||
| 553 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 554 | 0x0000, 0x0000, data, sizeof(u8), HZ * 10); | ||
| 555 | |||
| 556 | if (res < 0) { | ||
| 557 | dev_err(rr3->dev, "%s: Error sending rr3 cmd res %d, data %d", | ||
| 558 | __func__, res, *data); | ||
| 559 | res = -EIO; | ||
| 560 | } else | ||
| 561 | res = (u8)data[0]; | ||
| 562 | |||
| 563 | kfree(data); | ||
| 564 | |||
| 565 | return res; | ||
| 566 | } | ||
| 567 | |||
| 568 | /* Enables the long range detector and starts async receive */ | ||
| 569 | static int redrat3_enable_detector(struct redrat3_dev *rr3) | ||
| 570 | { | ||
| 571 | struct device *dev = rr3->dev; | ||
| 572 | u8 ret; | ||
| 573 | |||
| 574 | rr3_ftr(dev, "Entering %s\n", __func__); | ||
| 575 | |||
| 576 | ret = redrat3_send_cmd(RR3_RC_DET_ENABLE, rr3); | ||
| 577 | if (ret != 0) | ||
| 578 | dev_dbg(dev, "%s: unexpected ret of %d\n", | ||
| 579 | __func__, ret); | ||
| 580 | |||
| 581 | ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3); | ||
| 582 | if (ret != 1) { | ||
| 583 | dev_err(dev, "%s: detector status: %d, should be 1\n", | ||
| 584 | __func__, ret); | ||
| 585 | return -EIO; | ||
| 586 | } | ||
| 587 | |||
| 588 | rr3->det_enabled = true; | ||
| 589 | redrat3_issue_async(rr3); | ||
| 590 | |||
| 591 | return 0; | ||
| 592 | } | ||
| 593 | |||
| 594 | /* Disables the rr3 long range detector */ | ||
| 595 | static void redrat3_disable_detector(struct redrat3_dev *rr3) | ||
| 596 | { | ||
| 597 | struct device *dev = rr3->dev; | ||
| 598 | u8 ret; | ||
| 599 | |||
| 600 | rr3_ftr(dev, "Entering %s\n", __func__); | ||
| 601 | |||
| 602 | ret = redrat3_send_cmd(RR3_RC_DET_DISABLE, rr3); | ||
| 603 | if (ret != 0) | ||
| 604 | dev_err(dev, "%s: failure!\n", __func__); | ||
| 605 | |||
| 606 | ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3); | ||
| 607 | if (ret != 0) | ||
| 608 | dev_warn(dev, "%s: detector status: %d, should be 0\n", | ||
| 609 | __func__, ret); | ||
| 610 | |||
| 611 | rr3->det_enabled = false; | ||
| 612 | } | ||
| 613 | |||
| 614 | static inline void redrat3_delete(struct redrat3_dev *rr3, | ||
| 615 | struct usb_device *udev) | ||
| 616 | { | ||
| 617 | rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); | ||
| 618 | usb_kill_urb(rr3->read_urb); | ||
| 619 | usb_kill_urb(rr3->write_urb); | ||
| 620 | |||
| 621 | usb_free_urb(rr3->read_urb); | ||
| 622 | usb_free_urb(rr3->write_urb); | ||
| 623 | |||
| 624 | usb_free_coherent(udev, rr3->ep_in->wMaxPacketSize, | ||
| 625 | rr3->bulk_in_buf, rr3->dma_in); | ||
| 626 | usb_free_coherent(udev, rr3->ep_out->wMaxPacketSize, | ||
| 627 | rr3->bulk_out_buf, rr3->dma_out); | ||
| 628 | |||
| 629 | kfree(rr3); | ||
| 630 | } | ||
| 631 | |||
| 632 | static u32 redrat3_get_timeout(struct device *dev, | ||
| 633 | struct rc_dev *rc, struct usb_device *udev) | ||
| 634 | { | ||
| 635 | u32 *tmp; | ||
| 636 | u32 timeout = MS_TO_NS(150); /* a sane default, if things go haywire */ | ||
| 637 | int len, ret, pipe; | ||
| 638 | |||
| 639 | len = sizeof(*tmp); | ||
| 640 | tmp = kzalloc(len, GFP_KERNEL); | ||
| 641 | if (!tmp) { | ||
| 642 | dev_warn(dev, "Memory allocation faillure\n"); | ||
| 643 | return timeout; | ||
| 644 | } | ||
| 645 | |||
| 646 | pipe = usb_rcvctrlpipe(udev, 0); | ||
| 647 | ret = usb_control_msg(udev, pipe, RR3_GET_IR_PARAM, | ||
| 648 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 649 | RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5); | ||
| 650 | if (ret != len) { | ||
| 651 | dev_warn(dev, "Failed to read timeout from hardware\n"); | ||
| 652 | return timeout; | ||
| 653 | } | ||
| 654 | |||
| 655 | timeout = US_TO_NS(redrat3_len_to_us(be32_to_cpu(*tmp))); | ||
| 656 | if (timeout < rc->min_timeout) | ||
| 657 | timeout = rc->min_timeout; | ||
| 658 | else if (timeout > rc->max_timeout) | ||
| 659 | timeout = rc->max_timeout; | ||
| 660 | |||
| 661 | rr3_dbg(dev, "Got timeout of %d ms\n", timeout / (1000 * 1000)); | ||
| 662 | return timeout; | ||
| 663 | } | ||
| 664 | |||
| 665 | static void redrat3_reset(struct redrat3_dev *rr3) | ||
| 666 | { | ||
| 667 | struct usb_device *udev = rr3->udev; | ||
| 668 | struct device *dev = rr3->dev; | ||
| 669 | int rc, rxpipe, txpipe; | ||
| 670 | u8 *val; | ||
| 671 | int len = sizeof(u8); | ||
| 672 | |||
| 673 | rr3_ftr(dev, "Entering %s\n", __func__); | ||
| 674 | |||
| 675 | rxpipe = usb_rcvctrlpipe(udev, 0); | ||
| 676 | txpipe = usb_sndctrlpipe(udev, 0); | ||
| 677 | |||
| 678 | val = kzalloc(len, GFP_KERNEL); | ||
| 679 | if (!val) { | ||
| 680 | dev_err(dev, "Memory allocation failure\n"); | ||
| 681 | return; | ||
| 682 | } | ||
| 683 | |||
| 684 | *val = 0x01; | ||
| 685 | rc = usb_control_msg(udev, rxpipe, RR3_RESET, | ||
| 686 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 687 | RR3_CPUCS_REG_ADDR, 0, val, len, HZ * 25); | ||
| 688 | rr3_dbg(dev, "reset returned 0x%02x\n", rc); | ||
| 689 | |||
| 690 | *val = 5; | ||
| 691 | rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, | ||
| 692 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
| 693 | RR3_IR_IO_LENGTH_FUZZ, 0, val, len, HZ * 25); | ||
| 694 | rr3_dbg(dev, "set ir parm len fuzz %d rc 0x%02x\n", *val, rc); | ||
| 695 | |||
| 696 | *val = RR3_DRIVER_MAXLENS; | ||
| 697 | rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, | ||
| 698 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
| 699 | RR3_IR_IO_MAX_LENGTHS, 0, val, len, HZ * 25); | ||
| 700 | rr3_dbg(dev, "set ir parm max lens %d rc 0x%02x\n", *val, rc); | ||
| 701 | |||
| 702 | kfree(val); | ||
| 703 | } | ||
| 704 | |||
| 705 | static void redrat3_get_firmware_rev(struct redrat3_dev *rr3) | ||
| 706 | { | ||
| 707 | int rc = 0; | ||
| 708 | char *buffer; | ||
| 709 | |||
| 710 | rr3_ftr(rr3->dev, "Entering %s\n", __func__); | ||
| 711 | |||
| 712 | buffer = kzalloc(sizeof(char) * (RR3_FW_VERSION_LEN + 1), GFP_KERNEL); | ||
| 713 | if (!buffer) { | ||
| 714 | dev_err(rr3->dev, "Memory allocation failure\n"); | ||
| 715 | return; | ||
| 716 | } | ||
| 717 | |||
| 718 | rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0), | ||
| 719 | RR3_FW_VERSION, | ||
| 720 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 721 | 0, 0, buffer, RR3_FW_VERSION_LEN, HZ * 5); | ||
| 722 | |||
| 723 | if (rc >= 0) | ||
| 724 | dev_info(rr3->dev, "Firmware rev: %s", buffer); | ||
| 725 | else | ||
| 726 | dev_err(rr3->dev, "Problem fetching firmware ID\n"); | ||
| 727 | |||
| 728 | kfree(buffer); | ||
| 729 | rr3_ftr(rr3->dev, "Exiting %s\n", __func__); | ||
| 730 | } | ||
| 731 | |||
| 732 | static void redrat3_read_packet_start(struct redrat3_dev *rr3, int len) | ||
| 733 | { | ||
| 734 | u16 tx_error; | ||
| 735 | u16 hdrlen; | ||
| 736 | |||
| 737 | rr3_ftr(rr3->dev, "Entering %s\n", __func__); | ||
| 738 | |||
| 739 | /* grab the Length and type of transfer */ | ||
| 740 | memcpy(&(rr3->pktlen), (unsigned char *) rr3->bulk_in_buf, | ||
| 741 | sizeof(rr3->pktlen)); | ||
| 742 | memcpy(&(rr3->pkttype), ((unsigned char *) rr3->bulk_in_buf + | ||
| 743 | sizeof(rr3->pktlen)), | ||
| 744 | sizeof(rr3->pkttype)); | ||
| 745 | |||
| 746 | /*data needs conversion to know what its real values are*/ | ||
| 747 | rr3->pktlen = be16_to_cpu(rr3->pktlen); | ||
| 748 | rr3->pkttype = be16_to_cpu(rr3->pkttype); | ||
| 749 | |||
| 750 | switch (rr3->pkttype) { | ||
| 751 | case RR3_ERROR: | ||
| 752 | memcpy(&tx_error, ((unsigned char *)rr3->bulk_in_buf | ||
| 753 | + (sizeof(rr3->pktlen) + sizeof(rr3->pkttype))), | ||
| 754 | sizeof(tx_error)); | ||
| 755 | tx_error = be16_to_cpu(tx_error); | ||
| 756 | redrat3_dump_fw_error(rr3, tx_error); | ||
| 757 | break; | ||
| 758 | |||
| 759 | case RR3_MOD_SIGNAL_IN: | ||
| 760 | hdrlen = sizeof(rr3->pktlen) + sizeof(rr3->pkttype); | ||
| 761 | rr3->bytes_read = len; | ||
| 762 | rr3->bytes_read -= hdrlen; | ||
| 763 | rr3->datap = &(rr3->pbuf[0]); | ||
| 764 | |||
| 765 | memcpy(rr3->datap, ((unsigned char *)rr3->bulk_in_buf + hdrlen), | ||
| 766 | rr3->bytes_read); | ||
| 767 | rr3->datap += rr3->bytes_read; | ||
| 768 | rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", | ||
| 769 | rr3->bytes_read, rr3->pktlen); | ||
| 770 | break; | ||
| 771 | |||
| 772 | default: | ||
| 773 | rr3_dbg(rr3->dev, "ignoring packet with type 0x%02x, " | ||
| 774 | "len of %d, 0x%02x\n", rr3->pkttype, len, rr3->pktlen); | ||
| 775 | break; | ||
| 776 | } | ||
| 777 | } | ||
| 778 | |||
| 779 | static void redrat3_read_packet_continue(struct redrat3_dev *rr3, int len) | ||
| 780 | { | ||
| 781 | |||
| 782 | rr3_ftr(rr3->dev, "Entering %s\n", __func__); | ||
| 783 | |||
| 784 | memcpy(rr3->datap, (unsigned char *)rr3->bulk_in_buf, len); | ||
| 785 | rr3->datap += len; | ||
| 786 | |||
| 787 | rr3->bytes_read += len; | ||
| 788 | rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", | ||
| 789 | rr3->bytes_read, rr3->pktlen); | ||
| 790 | } | ||
| 791 | |||
| 792 | /* gather IR data from incoming urb, process it when we have enough */ | ||
| 793 | static int redrat3_get_ir_data(struct redrat3_dev *rr3, int len) | ||
| 794 | { | ||
| 795 | struct device *dev = rr3->dev; | ||
| 796 | int ret = 0; | ||
| 797 | |||
| 798 | rr3_ftr(dev, "Entering %s\n", __func__); | ||
| 799 | |||
| 800 | if (rr3->pktlen > RR3_MAX_BUF_SIZE) { | ||
| 801 | dev_err(rr3->dev, "error: packet larger than buffer\n"); | ||
| 802 | ret = -EINVAL; | ||
| 803 | goto out; | ||
| 804 | } | ||
| 805 | |||
| 806 | if ((rr3->bytes_read == 0) && | ||
| 807 | (len >= (sizeof(rr3->pkttype) + sizeof(rr3->pktlen)))) { | ||
| 808 | redrat3_read_packet_start(rr3, len); | ||
| 809 | } else if (rr3->bytes_read != 0) { | ||
| 810 | redrat3_read_packet_continue(rr3, len); | ||
| 811 | } else if (rr3->bytes_read == 0) { | ||
| 812 | dev_err(dev, "error: no packet data read\n"); | ||
| 813 | ret = -ENODATA; | ||
| 814 | goto out; | ||
| 815 | } | ||
| 816 | |||
| 817 | if (rr3->bytes_read > rr3->pktlen) { | ||
| 818 | dev_err(dev, "bytes_read (%d) greater than pktlen (%d)\n", | ||
| 819 | rr3->bytes_read, rr3->pktlen); | ||
| 820 | ret = -EINVAL; | ||
| 821 | goto out; | ||
| 822 | } else if (rr3->bytes_read < rr3->pktlen) | ||
| 823 | /* we're still accumulating data */ | ||
| 824 | return 0; | ||
| 825 | |||
| 826 | /* if we get here, we've got IR data to decode */ | ||
| 827 | if (rr3->pkttype == RR3_MOD_SIGNAL_IN) | ||
| 828 | redrat3_process_ir_data(rr3); | ||
| 829 | else | ||
| 830 | rr3_dbg(dev, "discarding non-signal data packet " | ||
| 831 | "(type 0x%02x)\n", rr3->pkttype); | ||
| 832 | |||
| 833 | out: | ||
| 834 | rr3->bytes_read = 0; | ||
| 835 | rr3->pktlen = 0; | ||
| 836 | rr3->pkttype = 0; | ||
| 837 | return ret; | ||
| 838 | } | ||
| 839 | |||
| 840 | /* callback function from USB when async USB request has completed */ | ||
| 841 | static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs) | ||
| 842 | { | ||
| 843 | struct redrat3_dev *rr3; | ||
| 844 | |||
| 845 | if (!urb) | ||
| 846 | return; | ||
| 847 | |||
| 848 | rr3 = urb->context; | ||
| 849 | if (!rr3) { | ||
| 850 | pr_err("%s called with invalid context!\n", __func__); | ||
| 851 | usb_unlink_urb(urb); | ||
| 852 | return; | ||
| 853 | } | ||
| 854 | |||
| 855 | rr3_ftr(rr3->dev, "Entering %s\n", __func__); | ||
| 856 | |||
| 857 | if (!rr3->det_enabled) { | ||
| 858 | rr3_dbg(rr3->dev, "received a read callback but detector " | ||
| 859 | "disabled - ignoring\n"); | ||
| 860 | return; | ||
| 861 | } | ||
| 862 | |||
| 863 | switch (urb->status) { | ||
| 864 | case 0: | ||
| 865 | redrat3_get_ir_data(rr3, urb->actual_length); | ||
| 866 | break; | ||
| 867 | |||
| 868 | case -ECONNRESET: | ||
| 869 | case -ENOENT: | ||
| 870 | case -ESHUTDOWN: | ||
| 871 | usb_unlink_urb(urb); | ||
| 872 | return; | ||
| 873 | |||
| 874 | case -EPIPE: | ||
| 875 | default: | ||
| 876 | dev_warn(rr3->dev, "Error: urb status = %d\n", urb->status); | ||
| 877 | rr3->bytes_read = 0; | ||
| 878 | rr3->pktlen = 0; | ||
| 879 | rr3->pkttype = 0; | ||
| 880 | break; | ||
| 881 | } | ||
| 882 | |||
| 883 | if (!rr3->transmitting) | ||
| 884 | redrat3_issue_async(rr3); | ||
| 885 | else | ||
| 886 | rr3_dbg(rr3->dev, "IR transmit in progress\n"); | ||
| 887 | } | ||
| 888 | |||
| 889 | static void redrat3_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | ||
| 890 | { | ||
| 891 | struct redrat3_dev *rr3; | ||
| 892 | int len; | ||
| 893 | |||
| 894 | if (!urb) | ||
| 895 | return; | ||
| 896 | |||
| 897 | rr3 = urb->context; | ||
| 898 | if (rr3) { | ||
| 899 | len = urb->actual_length; | ||
| 900 | rr3_ftr(rr3->dev, "%s: called (status=%d len=%d)\n", | ||
| 901 | __func__, urb->status, len); | ||
| 902 | } | ||
| 903 | } | ||
| 904 | |||
| 905 | static u16 mod_freq_to_val(unsigned int mod_freq) | ||
| 906 | { | ||
| 907 | int mult = 6000000; | ||
| 908 | |||
| 909 | /* Clk used in mod. freq. generation is CLK24/4. */ | ||
| 910 | return (u16)(65536 - (mult / mod_freq)); | ||
| 911 | } | ||
| 912 | |||
| 913 | static int redrat3_set_tx_carrier(struct rc_dev *dev, u32 carrier) | ||
| 914 | { | ||
| 915 | struct redrat3_dev *rr3 = dev->priv; | ||
| 916 | |||
| 917 | rr3->carrier = carrier; | ||
| 918 | |||
| 919 | return carrier; | ||
| 920 | } | ||
| 921 | |||
| 922 | static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n) | ||
| 923 | { | ||
| 924 | struct redrat3_dev *rr3 = rcdev->priv; | ||
| 925 | struct device *dev = rr3->dev; | ||
| 926 | struct redrat3_signal_header header; | ||
| 927 | int i, j, count, ret, ret_len, offset; | ||
| 928 | int lencheck, cur_sample_len, pipe; | ||
| 929 | char *buffer = NULL, *sigdata = NULL; | ||
| 930 | int *sample_lens = NULL; | ||
| 931 | u32 tmpi; | ||
| 932 | u16 tmps; | ||
| 933 | u8 *datap; | ||
| 934 | u8 curlencheck = 0; | ||
| 935 | u16 *lengths_ptr; | ||
| 936 | int sendbuf_len; | ||
| 937 | |||
| 938 | rr3_ftr(dev, "Entering %s\n", __func__); | ||
| 939 | |||
| 940 | if (rr3->transmitting) { | ||
| 941 | dev_warn(dev, "%s: transmitter already in use\n", __func__); | ||
| 942 | return -EAGAIN; | ||
| 943 | } | ||
| 944 | |||
| 945 | count = n / sizeof(int); | ||
| 946 | if (count > (RR3_DRIVER_MAXLENS * 2)) | ||
| 947 | return -EINVAL; | ||
| 948 | |||
| 949 | rr3->transmitting = true; | ||
| 950 | |||
| 951 | redrat3_disable_detector(rr3); | ||
| 952 | |||
| 953 | if (rr3->det_enabled) { | ||
| 954 | dev_err(dev, "%s: cannot tx while rx is enabled\n", __func__); | ||
| 955 | ret = -EIO; | ||
| 956 | goto out; | ||
| 957 | } | ||
| 958 | |||
| 959 | sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); | ||
| 960 | if (!sample_lens) { | ||
| 961 | ret = -ENOMEM; | ||
| 962 | goto out; | ||
| 963 | } | ||
| 964 | |||
| 965 | for (i = 0; i < count; i++) { | ||
| 966 | for (lencheck = 0; lencheck < curlencheck; lencheck++) { | ||
| 967 | cur_sample_len = redrat3_us_to_len(txbuf[i]); | ||
| 968 | if (sample_lens[lencheck] == cur_sample_len) | ||
| 969 | break; | ||
| 970 | } | ||
| 971 | if (lencheck == curlencheck) { | ||
| 972 | cur_sample_len = redrat3_us_to_len(txbuf[i]); | ||
| 973 | rr3_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n", | ||
| 974 | i, txbuf[i], curlencheck, cur_sample_len); | ||
| 975 | if (curlencheck < 255) { | ||
| 976 | /* now convert the value to a proper | ||
| 977 | * rr3 value.. */ | ||
| 978 | sample_lens[curlencheck] = cur_sample_len; | ||
| 979 | curlencheck++; | ||
| 980 | } else { | ||
| 981 | dev_err(dev, "signal too long\n"); | ||
| 982 | ret = -EINVAL; | ||
| 983 | goto out; | ||
| 984 | } | ||
| 985 | } | ||
| 986 | } | ||
| 987 | |||
| 988 | sigdata = kzalloc((count + RR3_TX_TRAILER_LEN), GFP_KERNEL); | ||
| 989 | if (!sigdata) { | ||
| 990 | ret = -ENOMEM; | ||
| 991 | goto out; | ||
| 992 | } | ||
| 993 | |||
| 994 | sigdata[count] = RR3_END_OF_SIGNAL; | ||
| 995 | sigdata[count + 1] = RR3_END_OF_SIGNAL; | ||
| 996 | for (i = 0; i < count; i++) { | ||
| 997 | for (j = 0; j < curlencheck; j++) { | ||
| 998 | if (sample_lens[j] == redrat3_us_to_len(txbuf[i])) | ||
| 999 | sigdata[i] = j; | ||
| 1000 | } | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | offset = RR3_TX_HEADER_OFFSET; | ||
| 1004 | sendbuf_len = RR3_HEADER_LENGTH + (sizeof(u16) * RR3_DRIVER_MAXLENS) | ||
| 1005 | + count + RR3_TX_TRAILER_LEN + offset; | ||
| 1006 | |||
| 1007 | buffer = kzalloc(sendbuf_len, GFP_KERNEL); | ||
| 1008 | if (!buffer) { | ||
| 1009 | ret = -ENOMEM; | ||
| 1010 | goto out; | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | /* fill in our packet header */ | ||
| 1014 | header.length = sendbuf_len - offset; | ||
| 1015 | header.transfer_type = RR3_MOD_SIGNAL_OUT; | ||
| 1016 | header.pause = redrat3_len_to_us(100); | ||
| 1017 | header.mod_freq_count = mod_freq_to_val(rr3->carrier); | ||
| 1018 | header.no_periods = 0; /* n/a to transmit */ | ||
| 1019 | header.max_lengths = RR3_DRIVER_MAXLENS; | ||
| 1020 | header.no_lengths = curlencheck; | ||
| 1021 | header.max_sig_size = RR3_MAX_SIG_SIZE; | ||
| 1022 | header.sig_size = count + RR3_TX_TRAILER_LEN; | ||
| 1023 | /* we currently rely on repeat handling in the IR encoding source */ | ||
| 1024 | header.no_repeats = 0; | ||
| 1025 | |||
| 1026 | tmps = cpu_to_be16(header.length); | ||
| 1027 | memcpy(buffer, &tmps, 2); | ||
| 1028 | |||
| 1029 | tmps = cpu_to_be16(header.transfer_type); | ||
| 1030 | memcpy(buffer + 2, &tmps, 2); | ||
| 1031 | |||
| 1032 | tmpi = cpu_to_be32(header.pause); | ||
| 1033 | memcpy(buffer + offset, &tmpi, sizeof(tmpi)); | ||
| 1034 | |||
| 1035 | tmps = cpu_to_be16(header.mod_freq_count); | ||
| 1036 | memcpy(buffer + offset + RR3_FREQ_COUNT_OFFSET, &tmps, 2); | ||
| 1037 | |||
| 1038 | buffer[offset + RR3_NUM_LENGTHS_OFFSET] = header.no_lengths; | ||
| 1039 | |||
| 1040 | tmps = cpu_to_be16(header.sig_size); | ||
| 1041 | memcpy(buffer + offset + RR3_NUM_SIGS_OFFSET, &tmps, 2); | ||
| 1042 | |||
| 1043 | buffer[offset + RR3_REPEATS_OFFSET] = header.no_repeats; | ||
| 1044 | |||
| 1045 | lengths_ptr = (u16 *)(buffer + offset + RR3_HEADER_LENGTH); | ||
| 1046 | for (i = 0; i < curlencheck; ++i) | ||
| 1047 | lengths_ptr[i] = cpu_to_be16(sample_lens[i]); | ||
| 1048 | |||
| 1049 | datap = (u8 *)(buffer + offset + RR3_HEADER_LENGTH + | ||
| 1050 | (sizeof(u16) * RR3_DRIVER_MAXLENS)); | ||
| 1051 | memcpy(datap, sigdata, (count + RR3_TX_TRAILER_LEN)); | ||
| 1052 | |||
| 1053 | if (debug) { | ||
| 1054 | redrat3_dump_signal_header(&header); | ||
| 1055 | redrat3_dump_signal_data(buffer, header.sig_size); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress); | ||
| 1059 | tmps = usb_bulk_msg(rr3->udev, pipe, buffer, | ||
| 1060 | sendbuf_len, &ret_len, 10 * HZ); | ||
| 1061 | rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, tmps); | ||
| 1062 | |||
| 1063 | /* now tell the hardware to transmit what we sent it */ | ||
| 1064 | pipe = usb_rcvctrlpipe(rr3->udev, 0); | ||
| 1065 | ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL, | ||
| 1066 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 1067 | 0, 0, buffer, 2, HZ * 10); | ||
| 1068 | |||
| 1069 | if (ret < 0) | ||
| 1070 | dev_err(dev, "Error: control msg send failed, rc %d\n", ret); | ||
| 1071 | else | ||
| 1072 | ret = n; | ||
| 1073 | |||
| 1074 | out: | ||
| 1075 | kfree(sample_lens); | ||
| 1076 | kfree(buffer); | ||
| 1077 | kfree(sigdata); | ||
| 1078 | |||
| 1079 | rr3->transmitting = false; | ||
| 1080 | |||
| 1081 | redrat3_enable_detector(rr3); | ||
| 1082 | |||
| 1083 | return ret; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) | ||
| 1087 | { | ||
| 1088 | struct device *dev = rr3->dev; | ||
| 1089 | struct rc_dev *rc; | ||
| 1090 | int ret = -ENODEV; | ||
| 1091 | u16 prod = le16_to_cpu(rr3->udev->descriptor.idProduct); | ||
| 1092 | |||
| 1093 | rc = rc_allocate_device(); | ||
| 1094 | if (!rc) { | ||
| 1095 | dev_err(dev, "remote input dev allocation failed\n"); | ||
| 1096 | goto out; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | snprintf(rr3->name, sizeof(rr3->name), "RedRat3%s " | ||
| 1100 | "Infrared Remote Transceiver (%04x:%04x)", | ||
| 1101 | prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "", | ||
| 1102 | le16_to_cpu(rr3->udev->descriptor.idVendor), prod); | ||
| 1103 | |||
| 1104 | usb_make_path(rr3->udev, rr3->phys, sizeof(rr3->phys)); | ||
| 1105 | |||
| 1106 | rc->input_name = rr3->name; | ||
| 1107 | rc->input_phys = rr3->phys; | ||
| 1108 | usb_to_input_id(rr3->udev, &rc->input_id); | ||
| 1109 | rc->dev.parent = dev; | ||
| 1110 | rc->priv = rr3; | ||
| 1111 | rc->driver_type = RC_DRIVER_IR_RAW; | ||
| 1112 | rc->allowed_protos = RC_TYPE_ALL; | ||
| 1113 | rc->min_timeout = MS_TO_NS(RR3_RX_MIN_TIMEOUT); | ||
| 1114 | rc->max_timeout = MS_TO_NS(RR3_RX_MAX_TIMEOUT); | ||
| 1115 | rc->timeout = redrat3_get_timeout(dev, rc, rr3->udev); | ||
| 1116 | rc->tx_ir = redrat3_transmit_ir; | ||
| 1117 | rc->s_tx_carrier = redrat3_set_tx_carrier; | ||
| 1118 | rc->driver_name = DRIVER_NAME; | ||
| 1119 | rc->map_name = RC_MAP_HAUPPAUGE; | ||
| 1120 | |||
| 1121 | ret = rc_register_device(rc); | ||
| 1122 | if (ret < 0) { | ||
| 1123 | dev_err(dev, "remote dev registration failed\n"); | ||
| 1124 | goto out; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | return rc; | ||
| 1128 | |||
| 1129 | out: | ||
| 1130 | rc_free_device(rc); | ||
| 1131 | return NULL; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | static int __devinit redrat3_dev_probe(struct usb_interface *intf, | ||
| 1135 | const struct usb_device_id *id) | ||
| 1136 | { | ||
| 1137 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1138 | struct device *dev = &intf->dev; | ||
| 1139 | struct usb_host_interface *uhi; | ||
| 1140 | struct redrat3_dev *rr3; | ||
| 1141 | struct usb_endpoint_descriptor *ep; | ||
| 1142 | struct usb_endpoint_descriptor *ep_in = NULL; | ||
| 1143 | struct usb_endpoint_descriptor *ep_out = NULL; | ||
| 1144 | u8 addr, attrs; | ||
| 1145 | int pipe, i; | ||
| 1146 | int retval = -ENOMEM; | ||
| 1147 | |||
| 1148 | rr3_ftr(dev, "%s called\n", __func__); | ||
| 1149 | |||
| 1150 | uhi = intf->cur_altsetting; | ||
| 1151 | |||
| 1152 | /* find our bulk-in and bulk-out endpoints */ | ||
| 1153 | for (i = 0; i < uhi->desc.bNumEndpoints; ++i) { | ||
| 1154 | ep = &uhi->endpoint[i].desc; | ||
| 1155 | addr = ep->bEndpointAddress; | ||
| 1156 | attrs = ep->bmAttributes; | ||
| 1157 | |||
| 1158 | if ((ep_in == NULL) && | ||
| 1159 | ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && | ||
| 1160 | ((attrs & USB_ENDPOINT_XFERTYPE_MASK) == | ||
| 1161 | USB_ENDPOINT_XFER_BULK)) { | ||
| 1162 | rr3_dbg(dev, "found bulk-in endpoint at 0x%02x\n", | ||
| 1163 | ep->bEndpointAddress); | ||
| 1164 | /* data comes in on 0x82, 0x81 is for other data... */ | ||
| 1165 | if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR) | ||
| 1166 | ep_in = ep; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | if ((ep_out == NULL) && | ||
| 1170 | ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && | ||
| 1171 | ((attrs & USB_ENDPOINT_XFERTYPE_MASK) == | ||
| 1172 | USB_ENDPOINT_XFER_BULK)) { | ||
| 1173 | rr3_dbg(dev, "found bulk-out endpoint at 0x%02x\n", | ||
| 1174 | ep->bEndpointAddress); | ||
| 1175 | ep_out = ep; | ||
| 1176 | } | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | if (!ep_in || !ep_out) { | ||
| 1180 | dev_err(dev, "Couldn't find both in and out endpoints\n"); | ||
| 1181 | retval = -ENODEV; | ||
| 1182 | goto no_endpoints; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | /* allocate memory for our device state and initialize it */ | ||
| 1186 | rr3 = kzalloc(sizeof(*rr3), GFP_KERNEL); | ||
| 1187 | if (rr3 == NULL) { | ||
| 1188 | dev_err(dev, "Memory allocation failure\n"); | ||
| 1189 | goto error; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | rr3->dev = &intf->dev; | ||
| 1193 | |||
| 1194 | /* set up bulk-in endpoint */ | ||
| 1195 | rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1196 | if (!rr3->read_urb) { | ||
| 1197 | dev_err(dev, "Read urb allocation failure\n"); | ||
| 1198 | goto error; | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | rr3->ep_in = ep_in; | ||
| 1202 | rr3->bulk_in_buf = usb_alloc_coherent(udev, ep_in->wMaxPacketSize, | ||
| 1203 | GFP_ATOMIC, &rr3->dma_in); | ||
| 1204 | if (!rr3->bulk_in_buf) { | ||
| 1205 | dev_err(dev, "Read buffer allocation failure\n"); | ||
| 1206 | goto error; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress); | ||
| 1210 | usb_fill_bulk_urb(rr3->read_urb, udev, pipe, | ||
| 1211 | rr3->bulk_in_buf, ep_in->wMaxPacketSize, | ||
| 1212 | (usb_complete_t)redrat3_handle_async, rr3); | ||
| 1213 | |||
| 1214 | /* set up bulk-out endpoint*/ | ||
| 1215 | rr3->write_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1216 | if (!rr3->write_urb) { | ||
| 1217 | dev_err(dev, "Write urb allocation failure\n"); | ||
| 1218 | goto error; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | rr3->ep_out = ep_out; | ||
| 1222 | rr3->bulk_out_buf = usb_alloc_coherent(udev, ep_out->wMaxPacketSize, | ||
| 1223 | GFP_ATOMIC, &rr3->dma_out); | ||
| 1224 | if (!rr3->bulk_out_buf) { | ||
| 1225 | dev_err(dev, "Write buffer allocation failure\n"); | ||
| 1226 | goto error; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | pipe = usb_sndbulkpipe(udev, ep_out->bEndpointAddress); | ||
| 1230 | usb_fill_bulk_urb(rr3->write_urb, udev, pipe, | ||
| 1231 | rr3->bulk_out_buf, ep_out->wMaxPacketSize, | ||
| 1232 | (usb_complete_t)redrat3_write_bulk_callback, rr3); | ||
| 1233 | |||
| 1234 | mutex_init(&rr3->lock); | ||
| 1235 | rr3->udev = udev; | ||
| 1236 | |||
| 1237 | redrat3_reset(rr3); | ||
| 1238 | redrat3_get_firmware_rev(rr3); | ||
| 1239 | |||
| 1240 | /* might be all we need to do? */ | ||
| 1241 | retval = redrat3_enable_detector(rr3); | ||
| 1242 | if (retval < 0) | ||
| 1243 | goto error; | ||
| 1244 | |||
| 1245 | /* default.. will get overridden by any sends with a freq defined */ | ||
| 1246 | rr3->carrier = 38000; | ||
| 1247 | |||
| 1248 | rr3->rc = redrat3_init_rc_dev(rr3); | ||
| 1249 | if (!rr3->rc) | ||
| 1250 | goto error; | ||
| 1251 | |||
| 1252 | setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); | ||
| 1253 | |||
| 1254 | /* we can register the device now, as it is ready */ | ||
| 1255 | usb_set_intfdata(intf, rr3); | ||
| 1256 | |||
| 1257 | rr3_ftr(dev, "Exiting %s\n", __func__); | ||
| 1258 | return 0; | ||
| 1259 | |||
| 1260 | error: | ||
| 1261 | redrat3_delete(rr3, rr3->udev); | ||
| 1262 | |||
| 1263 | no_endpoints: | ||
| 1264 | dev_err(dev, "%s: retval = %x", __func__, retval); | ||
| 1265 | |||
| 1266 | return retval; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static void __devexit redrat3_dev_disconnect(struct usb_interface *intf) | ||
| 1270 | { | ||
| 1271 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1272 | struct redrat3_dev *rr3 = usb_get_intfdata(intf); | ||
| 1273 | |||
| 1274 | rr3_ftr(&intf->dev, "Entering %s\n", __func__); | ||
| 1275 | |||
| 1276 | if (!rr3) | ||
| 1277 | return; | ||
| 1278 | |||
| 1279 | redrat3_disable_detector(rr3); | ||
| 1280 | |||
| 1281 | usb_set_intfdata(intf, NULL); | ||
| 1282 | rc_unregister_device(rr3->rc); | ||
| 1283 | redrat3_delete(rr3, udev); | ||
| 1284 | |||
| 1285 | rr3_ftr(&intf->dev, "RedRat3 IR Transceiver now disconnected\n"); | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message) | ||
| 1289 | { | ||
| 1290 | struct redrat3_dev *rr3 = usb_get_intfdata(intf); | ||
| 1291 | rr3_ftr(rr3->dev, "suspend\n"); | ||
| 1292 | usb_kill_urb(rr3->read_urb); | ||
| 1293 | return 0; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | static int redrat3_dev_resume(struct usb_interface *intf) | ||
| 1297 | { | ||
| 1298 | struct redrat3_dev *rr3 = usb_get_intfdata(intf); | ||
| 1299 | rr3_ftr(rr3->dev, "resume\n"); | ||
| 1300 | if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) | ||
| 1301 | return -EIO; | ||
| 1302 | return 0; | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | static struct usb_driver redrat3_dev_driver = { | ||
| 1306 | .name = DRIVER_NAME, | ||
| 1307 | .probe = redrat3_dev_probe, | ||
| 1308 | .disconnect = redrat3_dev_disconnect, | ||
| 1309 | .suspend = redrat3_dev_suspend, | ||
| 1310 | .resume = redrat3_dev_resume, | ||
| 1311 | .reset_resume = redrat3_dev_resume, | ||
| 1312 | .id_table = redrat3_dev_table | ||
| 1313 | }; | ||
| 1314 | |||
| 1315 | static int __init redrat3_dev_init(void) | ||
| 1316 | { | ||
| 1317 | int ret; | ||
| 1318 | |||
| 1319 | ret = usb_register(&redrat3_dev_driver); | ||
| 1320 | if (ret < 0) | ||
| 1321 | pr_err(DRIVER_NAME | ||
| 1322 | ": usb register failed, result = %d\n", ret); | ||
| 1323 | |||
| 1324 | return ret; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | static void __exit redrat3_dev_exit(void) | ||
| 1328 | { | ||
| 1329 | usb_deregister(&redrat3_dev_driver); | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | module_init(redrat3_dev_init); | ||
| 1333 | module_exit(redrat3_dev_exit); | ||
| 1334 | |||
| 1335 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 1336 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 1337 | MODULE_AUTHOR(DRIVER_AUTHOR2); | ||
| 1338 | MODULE_LICENSE("GPL"); | ||
| 1339 | MODULE_DEVICE_TABLE(usb, redrat3_dev_table); | ||
| 1340 | |||
| 1341 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
| 1342 | MODULE_PARM_DESC(debug, "Enable module debug spew. 0 = no debugging (default) " | ||
| 1343 | "0x1 = standard debug messages, 0x2 = function tracing debug. " | ||
| 1344 | "Flag bits are addative (i.e., 0x3 for both debug types)."); | ||
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 186de5522001..5d06b899e859 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c | |||
| @@ -19,11 +19,12 @@ | |||
| 19 | * o DSDT dumps | 19 | * o DSDT dumps |
| 20 | * | 20 | * |
| 21 | * Supported features: | 21 | * Supported features: |
| 22 | * o IR Receive | ||
| 23 | * o IR Transmit | ||
| 22 | * o Wake-On-CIR functionality | 24 | * o Wake-On-CIR functionality |
| 23 | * | 25 | * |
| 24 | * To do: | 26 | * To do: |
| 25 | * o Learning | 27 | * o Learning |
| 26 | * o IR Transmit | ||
| 27 | * | 28 | * |
| 28 | * This program is free software; you can redistribute it and/or modify | 29 | * This program is free software; you can redistribute it and/or modify |
| 29 | * it under the terms of the GNU General Public License as published by | 30 | * it under the terms of the GNU General Public License as published by |
| @@ -50,6 +51,8 @@ | |||
| 50 | #include <linux/io.h> | 51 | #include <linux/io.h> |
| 51 | #include <linux/bitrev.h> | 52 | #include <linux/bitrev.h> |
| 52 | #include <linux/slab.h> | 53 | #include <linux/slab.h> |
| 54 | #include <linux/wait.h> | ||
| 55 | #include <linux/sched.h> | ||
| 53 | #include <media/rc-core.h> | 56 | #include <media/rc-core.h> |
| 54 | 57 | ||
| 55 | #define DRVNAME "winbond-cir" | 58 | #define DRVNAME "winbond-cir" |
| @@ -118,14 +121,24 @@ | |||
| 118 | #define WBCIR_IRQ_NONE 0x00 | 121 | #define WBCIR_IRQ_NONE 0x00 |
| 119 | /* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | 122 | /* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ |
| 120 | #define WBCIR_IRQ_RX 0x01 | 123 | #define WBCIR_IRQ_RX 0x01 |
| 124 | /* TX data low bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
| 125 | #define WBCIR_IRQ_TX_LOW 0x02 | ||
| 121 | /* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | 126 | /* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ |
| 122 | #define WBCIR_IRQ_ERR 0x04 | 127 | #define WBCIR_IRQ_ERR 0x04 |
| 128 | /* TX data empty bit for WBCEIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
| 129 | #define WBCIR_IRQ_TX_EMPTY 0x20 | ||
| 123 | /* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ | 130 | /* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ |
| 124 | #define WBCIR_LED_ENABLE 0x80 | 131 | #define WBCIR_LED_ENABLE 0x80 |
| 125 | /* RX data available bit for WBCIR_REG_SP3_LSR */ | 132 | /* RX data available bit for WBCIR_REG_SP3_LSR */ |
| 126 | #define WBCIR_RX_AVAIL 0x01 | 133 | #define WBCIR_RX_AVAIL 0x01 |
| 134 | /* RX data overrun error bit for WBCIR_REG_SP3_LSR */ | ||
| 135 | #define WBCIR_RX_OVERRUN 0x02 | ||
| 136 | /* TX End-Of-Transmission bit for WBCIR_REG_SP3_ASCR */ | ||
| 137 | #define WBCIR_TX_EOT 0x04 | ||
| 127 | /* RX disable bit for WBCIR_REG_SP3_ASCR */ | 138 | /* RX disable bit for WBCIR_REG_SP3_ASCR */ |
| 128 | #define WBCIR_RX_DISABLE 0x20 | 139 | #define WBCIR_RX_DISABLE 0x20 |
| 140 | /* TX data underrun error bit for WBCIR_REG_SP3_ASCR */ | ||
| 141 | #define WBCIR_TX_UNDERRUN 0x40 | ||
| 129 | /* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ | 142 | /* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ |
| 130 | #define WBCIR_EXT_ENABLE 0x01 | 143 | #define WBCIR_EXT_ENABLE 0x01 |
| 131 | /* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ | 144 | /* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ |
| @@ -154,6 +167,21 @@ enum wbcir_protocol { | |||
| 154 | IR_PROTOCOL_RC6 = 0x2, | 167 | IR_PROTOCOL_RC6 = 0x2, |
| 155 | }; | 168 | }; |
| 156 | 169 | ||
| 170 | /* Possible states for IR reception */ | ||
| 171 | enum wbcir_rxstate { | ||
| 172 | WBCIR_RXSTATE_INACTIVE = 0, | ||
| 173 | WBCIR_RXSTATE_ACTIVE, | ||
| 174 | WBCIR_RXSTATE_ERROR | ||
| 175 | }; | ||
| 176 | |||
| 177 | /* Possible states for IR transmission */ | ||
| 178 | enum wbcir_txstate { | ||
| 179 | WBCIR_TXSTATE_INACTIVE = 0, | ||
| 180 | WBCIR_TXSTATE_ACTIVE, | ||
| 181 | WBCIR_TXSTATE_DONE, | ||
| 182 | WBCIR_TXSTATE_ERROR | ||
| 183 | }; | ||
| 184 | |||
| 157 | /* Misc */ | 185 | /* Misc */ |
| 158 | #define WBCIR_NAME "Winbond CIR" | 186 | #define WBCIR_NAME "Winbond CIR" |
| 159 | #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ | 187 | #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ |
| @@ -166,22 +194,29 @@ enum wbcir_protocol { | |||
| 166 | /* Per-device data */ | 194 | /* Per-device data */ |
| 167 | struct wbcir_data { | 195 | struct wbcir_data { |
| 168 | spinlock_t spinlock; | 196 | spinlock_t spinlock; |
| 197 | struct rc_dev *dev; | ||
| 198 | struct led_classdev led; | ||
| 169 | 199 | ||
| 170 | unsigned long wbase; /* Wake-Up Baseaddr */ | 200 | unsigned long wbase; /* Wake-Up Baseaddr */ |
| 171 | unsigned long ebase; /* Enhanced Func. Baseaddr */ | 201 | unsigned long ebase; /* Enhanced Func. Baseaddr */ |
| 172 | unsigned long sbase; /* Serial Port Baseaddr */ | 202 | unsigned long sbase; /* Serial Port Baseaddr */ |
| 173 | unsigned int irq; /* Serial Port IRQ */ | 203 | unsigned int irq; /* Serial Port IRQ */ |
| 204 | u8 irqmask; | ||
| 174 | 205 | ||
| 175 | struct rc_dev *dev; | 206 | /* RX state */ |
| 176 | 207 | enum wbcir_rxstate rxstate; | |
| 177 | struct led_trigger *rxtrigger; | 208 | struct led_trigger *rxtrigger; |
| 178 | struct led_trigger *txtrigger; | 209 | struct ir_raw_event rxev; |
| 179 | struct led_classdev led; | ||
| 180 | 210 | ||
| 181 | /* RX irdata state */ | 211 | /* TX state */ |
| 182 | bool irdata_active; | 212 | enum wbcir_txstate txstate; |
| 183 | bool irdata_error; | 213 | struct led_trigger *txtrigger; |
| 184 | struct ir_raw_event ev; | 214 | u32 txlen; |
| 215 | u32 txoff; | ||
| 216 | u32 *txbuf; | ||
| 217 | wait_queue_head_t txwaitq; | ||
| 218 | u8 txmask; | ||
| 219 | u32 txcarrier; | ||
| 185 | }; | 220 | }; |
| 186 | 221 | ||
| 187 | static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; | 222 | static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; |
| @@ -193,6 +228,10 @@ static int invert; /* default = 0 */ | |||
| 193 | module_param(invert, bool, 0444); | 228 | module_param(invert, bool, 0444); |
| 194 | MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); | 229 | MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); |
| 195 | 230 | ||
| 231 | static int txandrx; /* default = 0 */ | ||
| 232 | module_param(txandrx, bool, 0444); | ||
| 233 | MODULE_PARM_DESC(invert, "Allow simultaneous TX and RX"); | ||
| 234 | |||
| 196 | static unsigned int wake_sc = 0x800F040C; | 235 | static unsigned int wake_sc = 0x800F040C; |
| 197 | module_param(wake_sc, uint, 0644); | 236 | module_param(wake_sc, uint, 0644); |
| 198 | MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); | 237 | MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); |
| @@ -228,6 +267,17 @@ wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) | |||
| 228 | outb(bank, data->sbase + WBCIR_REG_SP3_BSR); | 267 | outb(bank, data->sbase + WBCIR_REG_SP3_BSR); |
| 229 | } | 268 | } |
| 230 | 269 | ||
| 270 | static inline void | ||
| 271 | wbcir_set_irqmask(struct wbcir_data *data, u8 irqmask) | ||
| 272 | { | ||
| 273 | if (data->irqmask == irqmask) | ||
| 274 | return; | ||
| 275 | |||
| 276 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 277 | outb(irqmask, data->sbase + WBCIR_REG_SP3_IER); | ||
| 278 | data->irqmask = irqmask; | ||
| 279 | } | ||
| 280 | |||
| 231 | static enum led_brightness | 281 | static enum led_brightness |
| 232 | wbcir_led_brightness_get(struct led_classdev *led_cdev) | 282 | wbcir_led_brightness_get(struct led_classdev *led_cdev) |
| 233 | { | 283 | { |
| @@ -279,97 +329,297 @@ wbcir_to_rc6cells(u8 val) | |||
| 279 | * | 329 | * |
| 280 | *****************************************************************************/ | 330 | *****************************************************************************/ |
| 281 | 331 | ||
| 332 | static void | ||
| 333 | wbcir_idle_rx(struct rc_dev *dev, bool idle) | ||
| 334 | { | ||
| 335 | struct wbcir_data *data = dev->priv; | ||
| 336 | |||
| 337 | if (!idle && data->rxstate == WBCIR_RXSTATE_INACTIVE) { | ||
| 338 | data->rxstate = WBCIR_RXSTATE_ACTIVE; | ||
| 339 | led_trigger_event(data->rxtrigger, LED_FULL); | ||
| 340 | } | ||
| 341 | |||
| 342 | if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) | ||
| 343 | /* Tell hardware to go idle by setting RXINACTIVE */ | ||
| 344 | outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); | ||
| 345 | } | ||
| 346 | |||
| 347 | static void | ||
| 348 | wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device) | ||
| 349 | { | ||
| 350 | u8 irdata; | ||
| 351 | DEFINE_IR_RAW_EVENT(rawir); | ||
| 352 | |||
| 353 | /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ | ||
| 354 | while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) { | ||
| 355 | irdata = inb(data->sbase + WBCIR_REG_SP3_RXDATA); | ||
| 356 | if (data->rxstate == WBCIR_RXSTATE_ERROR) | ||
| 357 | continue; | ||
| 358 | rawir.pulse = irdata & 0x80 ? false : true; | ||
| 359 | rawir.duration = US_TO_NS((irdata & 0x7F) * 10); | ||
| 360 | ir_raw_event_store_with_filter(data->dev, &rawir); | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Check if we should go idle */ | ||
| 364 | if (data->dev->idle) { | ||
| 365 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
| 366 | data->rxstate = WBCIR_RXSTATE_INACTIVE; | ||
| 367 | } | ||
| 368 | |||
| 369 | ir_raw_event_handle(data->dev); | ||
| 370 | } | ||
| 371 | |||
| 372 | static void | ||
| 373 | wbcir_irq_tx(struct wbcir_data *data) | ||
| 374 | { | ||
| 375 | unsigned int space; | ||
| 376 | unsigned int used; | ||
| 377 | u8 bytes[16]; | ||
| 378 | u8 byte; | ||
| 379 | |||
| 380 | if (!data->txbuf) | ||
| 381 | return; | ||
| 382 | |||
| 383 | switch (data->txstate) { | ||
| 384 | case WBCIR_TXSTATE_INACTIVE: | ||
| 385 | /* TX FIFO empty */ | ||
| 386 | space = 16; | ||
| 387 | led_trigger_event(data->txtrigger, LED_FULL); | ||
| 388 | break; | ||
| 389 | case WBCIR_TXSTATE_ACTIVE: | ||
| 390 | /* TX FIFO low (3 bytes or less) */ | ||
| 391 | space = 13; | ||
| 392 | break; | ||
| 393 | case WBCIR_TXSTATE_ERROR: | ||
| 394 | space = 0; | ||
| 395 | break; | ||
| 396 | default: | ||
| 397 | return; | ||
| 398 | } | ||
| 399 | |||
| 400 | /* | ||
| 401 | * TX data is run-length coded in bytes: YXXXXXXX | ||
| 402 | * Y = space (1) or pulse (0) | ||
| 403 | * X = duration, encoded as (X + 1) * 10us (i.e 10 to 1280 us) | ||
| 404 | */ | ||
| 405 | for (used = 0; used < space && data->txoff != data->txlen; used++) { | ||
| 406 | if (data->txbuf[data->txoff] == 0) { | ||
| 407 | data->txoff++; | ||
| 408 | continue; | ||
| 409 | } | ||
| 410 | byte = min((u32)0x80, data->txbuf[data->txoff]); | ||
| 411 | data->txbuf[data->txoff] -= byte; | ||
| 412 | byte--; | ||
| 413 | byte |= (data->txoff % 2 ? 0x80 : 0x00); /* pulse/space */ | ||
| 414 | bytes[used] = byte; | ||
| 415 | } | ||
| 416 | |||
| 417 | while (data->txbuf[data->txoff] == 0 && data->txoff != data->txlen) | ||
| 418 | data->txoff++; | ||
| 419 | |||
| 420 | if (used == 0) { | ||
| 421 | /* Finished */ | ||
| 422 | if (data->txstate == WBCIR_TXSTATE_ERROR) | ||
| 423 | /* Clear TX underrun bit */ | ||
| 424 | outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR); | ||
| 425 | else | ||
| 426 | data->txstate = WBCIR_TXSTATE_DONE; | ||
| 427 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); | ||
| 428 | led_trigger_event(data->txtrigger, LED_OFF); | ||
| 429 | wake_up(&data->txwaitq); | ||
| 430 | } else if (data->txoff == data->txlen) { | ||
| 431 | /* At the end of transmission, tell the hw before last byte */ | ||
| 432 | outsb(data->sbase + WBCIR_REG_SP3_TXDATA, bytes, used - 1); | ||
| 433 | outb(WBCIR_TX_EOT, data->sbase + WBCIR_REG_SP3_ASCR); | ||
| 434 | outb(bytes[used - 1], data->sbase + WBCIR_REG_SP3_TXDATA); | ||
| 435 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR | | ||
| 436 | WBCIR_IRQ_TX_EMPTY); | ||
| 437 | } else { | ||
| 438 | /* More data to follow... */ | ||
| 439 | outsb(data->sbase + WBCIR_REG_SP3_RXDATA, bytes, used); | ||
| 440 | if (data->txstate == WBCIR_TXSTATE_INACTIVE) { | ||
| 441 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR | | ||
| 442 | WBCIR_IRQ_TX_LOW); | ||
| 443 | data->txstate = WBCIR_TXSTATE_ACTIVE; | ||
| 444 | } | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 282 | static irqreturn_t | 448 | static irqreturn_t |
| 283 | wbcir_irq_handler(int irqno, void *cookie) | 449 | wbcir_irq_handler(int irqno, void *cookie) |
| 284 | { | 450 | { |
| 285 | struct pnp_dev *device = cookie; | 451 | struct pnp_dev *device = cookie; |
| 286 | struct wbcir_data *data = pnp_get_drvdata(device); | 452 | struct wbcir_data *data = pnp_get_drvdata(device); |
| 287 | unsigned long flags; | 453 | unsigned long flags; |
| 288 | u8 irdata[8]; | ||
| 289 | u8 disable = true; | ||
| 290 | u8 status; | 454 | u8 status; |
| 291 | int i; | ||
| 292 | 455 | ||
| 293 | spin_lock_irqsave(&data->spinlock, flags); | 456 | spin_lock_irqsave(&data->spinlock, flags); |
| 294 | |||
| 295 | wbcir_select_bank(data, WBCIR_BANK_0); | 457 | wbcir_select_bank(data, WBCIR_BANK_0); |
| 296 | |||
| 297 | status = inb(data->sbase + WBCIR_REG_SP3_EIR); | 458 | status = inb(data->sbase + WBCIR_REG_SP3_EIR); |
| 459 | status &= data->irqmask; | ||
| 298 | 460 | ||
| 299 | if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) { | 461 | if (!status) { |
| 300 | spin_unlock_irqrestore(&data->spinlock, flags); | 462 | spin_unlock_irqrestore(&data->spinlock, flags); |
| 301 | return IRQ_NONE; | 463 | return IRQ_NONE; |
| 302 | } | 464 | } |
| 303 | 465 | ||
| 304 | /* Check for e.g. buffer overflow */ | ||
| 305 | if (status & WBCIR_IRQ_ERR) { | 466 | if (status & WBCIR_IRQ_ERR) { |
| 306 | data->irdata_error = true; | 467 | /* RX overflow? (read clears bit) */ |
| 307 | ir_raw_event_reset(data->dev); | 468 | if (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_OVERRUN) { |
| 308 | } | 469 | data->rxstate = WBCIR_RXSTATE_ERROR; |
| 309 | 470 | ir_raw_event_reset(data->dev); | |
| 310 | if (!(status & WBCIR_IRQ_RX)) | 471 | } |
| 311 | goto out; | ||
| 312 | 472 | ||
| 313 | if (!data->irdata_active) { | 473 | /* TX underflow? */ |
| 314 | data->irdata_active = true; | 474 | if (inb(data->sbase + WBCIR_REG_SP3_ASCR) & WBCIR_TX_UNDERRUN) |
| 315 | led_trigger_event(data->rxtrigger, LED_FULL); | 475 | data->txstate = WBCIR_TXSTATE_ERROR; |
| 316 | } | 476 | } |
| 317 | 477 | ||
| 318 | /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ | 478 | if (status & WBCIR_IRQ_RX) |
| 319 | insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8); | 479 | wbcir_irq_rx(data, device); |
| 320 | 480 | ||
| 321 | for (i = 0; i < 8; i++) { | 481 | if (status & (WBCIR_IRQ_TX_LOW | WBCIR_IRQ_TX_EMPTY)) |
| 322 | u8 pulse; | 482 | wbcir_irq_tx(data); |
| 323 | u32 duration; | ||
| 324 | 483 | ||
| 325 | if (irdata[i] != 0xFF && irdata[i] != 0x00) | 484 | spin_unlock_irqrestore(&data->spinlock, flags); |
| 326 | disable = false; | 485 | return IRQ_HANDLED; |
| 327 | 486 | } | |
| 328 | if (data->irdata_error) | ||
| 329 | continue; | ||
| 330 | 487 | ||
| 331 | pulse = irdata[i] & 0x80 ? false : true; | 488 | /***************************************************************************** |
| 332 | duration = (irdata[i] & 0x7F) * 10000; /* ns */ | 489 | * |
| 490 | * RC-CORE INTERFACE FUNCTIONS | ||
| 491 | * | ||
| 492 | *****************************************************************************/ | ||
| 333 | 493 | ||
| 334 | if (data->ev.pulse != pulse) { | 494 | static int |
| 335 | if (data->ev.duration != 0) { | 495 | wbcir_txcarrier(struct rc_dev *dev, u32 carrier) |
| 336 | ir_raw_event_store(data->dev, &data->ev); | 496 | { |
| 337 | data->ev.duration = 0; | 497 | struct wbcir_data *data = dev->priv; |
| 338 | } | 498 | unsigned long flags; |
| 499 | u8 val; | ||
| 500 | u32 freq; | ||
| 501 | |||
| 502 | freq = DIV_ROUND_CLOSEST(carrier, 1000); | ||
| 503 | if (freq < 30 || freq > 60) | ||
| 504 | return -EINVAL; | ||
| 505 | |||
| 506 | switch (freq) { | ||
| 507 | case 58: | ||
| 508 | case 59: | ||
| 509 | case 60: | ||
| 510 | val = freq - 58; | ||
| 511 | freq *= 1000; | ||
| 512 | break; | ||
| 513 | case 57: | ||
| 514 | val = freq - 27; | ||
| 515 | freq = 56900; | ||
| 516 | break; | ||
| 517 | default: | ||
| 518 | val = freq - 27; | ||
| 519 | freq *= 1000; | ||
| 520 | break; | ||
| 521 | } | ||
| 339 | 522 | ||
| 340 | data->ev.pulse = pulse; | 523 | spin_lock_irqsave(&data->spinlock, flags); |
| 341 | } | 524 | if (data->txstate != WBCIR_TXSTATE_INACTIVE) { |
| 525 | spin_unlock_irqrestore(&data->spinlock, flags); | ||
| 526 | return -EBUSY; | ||
| 527 | } | ||
| 342 | 528 | ||
| 343 | data->ev.duration += duration; | 529 | if (data->txcarrier != freq) { |
| 530 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 531 | wbcir_set_bits(data->sbase + WBCIR_REG_SP3_IRTXMC, val, 0x1F); | ||
| 532 | data->txcarrier = freq; | ||
| 344 | } | 533 | } |
| 345 | 534 | ||
| 346 | if (disable) { | 535 | spin_unlock_irqrestore(&data->spinlock, flags); |
| 347 | if (data->ev.duration != 0 && !data->irdata_error) { | 536 | return 0; |
| 348 | ir_raw_event_store(data->dev, &data->ev); | 537 | } |
| 349 | data->ev.duration = 0; | ||
| 350 | } | ||
| 351 | 538 | ||
| 352 | /* Set RXINACTIVE */ | 539 | static int |
| 353 | outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); | 540 | wbcir_txmask(struct rc_dev *dev, u32 mask) |
| 541 | { | ||
| 542 | struct wbcir_data *data = dev->priv; | ||
| 543 | unsigned long flags; | ||
| 544 | u8 val; | ||
| 354 | 545 | ||
| 355 | /* Drain the FIFO */ | 546 | /* Four outputs, only one output can be enabled at a time */ |
| 356 | while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) | 547 | switch (mask) { |
| 357 | inb(data->sbase + WBCIR_REG_SP3_RXDATA); | 548 | case 0x1: |
| 549 | val = 0x0; | ||
| 550 | break; | ||
| 551 | case 0x2: | ||
| 552 | val = 0x1; | ||
| 553 | break; | ||
| 554 | case 0x4: | ||
| 555 | val = 0x2; | ||
| 556 | break; | ||
| 557 | case 0x8: | ||
| 558 | val = 0x3; | ||
| 559 | break; | ||
| 560 | default: | ||
| 561 | return -EINVAL; | ||
| 562 | } | ||
| 358 | 563 | ||
| 359 | ir_raw_event_reset(data->dev); | 564 | spin_lock_irqsave(&data->spinlock, flags); |
| 360 | data->irdata_error = false; | 565 | if (data->txstate != WBCIR_TXSTATE_INACTIVE) { |
| 361 | data->irdata_active = false; | 566 | spin_unlock_irqrestore(&data->spinlock, flags); |
| 362 | led_trigger_event(data->rxtrigger, LED_OFF); | 567 | return -EBUSY; |
| 363 | } | 568 | } |
| 364 | 569 | ||
| 365 | ir_raw_event_handle(data->dev); | 570 | if (data->txmask != mask) { |
| 571 | wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, val, 0x0c); | ||
| 572 | data->txmask = mask; | ||
| 573 | } | ||
| 366 | 574 | ||
| 367 | out: | ||
| 368 | spin_unlock_irqrestore(&data->spinlock, flags); | 575 | spin_unlock_irqrestore(&data->spinlock, flags); |
| 369 | return IRQ_HANDLED; | 576 | return 0; |
| 370 | } | 577 | } |
| 371 | 578 | ||
| 579 | static int | ||
| 580 | wbcir_tx(struct rc_dev *dev, int *buf, u32 bufsize) | ||
| 581 | { | ||
| 582 | struct wbcir_data *data = dev->priv; | ||
| 583 | u32 count; | ||
| 584 | unsigned i; | ||
| 585 | unsigned long flags; | ||
| 586 | |||
| 587 | /* bufsize has been sanity checked by the caller */ | ||
| 588 | count = bufsize / sizeof(int); | ||
| 372 | 589 | ||
| 590 | /* Not sure if this is possible, but better safe than sorry */ | ||
| 591 | spin_lock_irqsave(&data->spinlock, flags); | ||
| 592 | if (data->txstate != WBCIR_TXSTATE_INACTIVE) { | ||
| 593 | spin_unlock_irqrestore(&data->spinlock, flags); | ||
| 594 | return -EBUSY; | ||
| 595 | } | ||
| 596 | |||
| 597 | /* Convert values to multiples of 10us */ | ||
| 598 | for (i = 0; i < count; i++) | ||
| 599 | buf[i] = DIV_ROUND_CLOSEST(buf[i], 10); | ||
| 600 | |||
| 601 | /* Fill the TX fifo once, the irq handler will do the rest */ | ||
| 602 | data->txbuf = buf; | ||
| 603 | data->txlen = count; | ||
| 604 | data->txoff = 0; | ||
| 605 | wbcir_irq_tx(data); | ||
| 606 | |||
| 607 | /* Wait for the TX to complete */ | ||
| 608 | while (data->txstate == WBCIR_TXSTATE_ACTIVE) { | ||
| 609 | spin_unlock_irqrestore(&data->spinlock, flags); | ||
| 610 | wait_event(data->txwaitq, data->txstate != WBCIR_TXSTATE_ACTIVE); | ||
| 611 | spin_lock_irqsave(&data->spinlock, flags); | ||
| 612 | } | ||
| 613 | |||
| 614 | /* We're done */ | ||
| 615 | if (data->txstate == WBCIR_TXSTATE_ERROR) | ||
| 616 | count = -EAGAIN; | ||
| 617 | data->txstate = WBCIR_TXSTATE_INACTIVE; | ||
| 618 | data->txbuf = NULL; | ||
| 619 | spin_unlock_irqrestore(&data->spinlock, flags); | ||
| 620 | |||
| 621 | return count; | ||
| 622 | } | ||
| 373 | 623 | ||
| 374 | /***************************************************************************** | 624 | /***************************************************************************** |
| 375 | * | 625 | * |
| @@ -382,7 +632,7 @@ wbcir_shutdown(struct pnp_dev *device) | |||
| 382 | { | 632 | { |
| 383 | struct device *dev = &device->dev; | 633 | struct device *dev = &device->dev; |
| 384 | struct wbcir_data *data = pnp_get_drvdata(device); | 634 | struct wbcir_data *data = pnp_get_drvdata(device); |
| 385 | int do_wake = 1; | 635 | bool do_wake = true; |
| 386 | u8 match[11]; | 636 | u8 match[11]; |
| 387 | u8 mask[11]; | 637 | u8 mask[11]; |
| 388 | u8 rc6_csl = 0; | 638 | u8 rc6_csl = 0; |
| @@ -392,14 +642,14 @@ wbcir_shutdown(struct pnp_dev *device) | |||
| 392 | memset(mask, 0, sizeof(mask)); | 642 | memset(mask, 0, sizeof(mask)); |
| 393 | 643 | ||
| 394 | if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { | 644 | if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { |
| 395 | do_wake = 0; | 645 | do_wake = false; |
| 396 | goto finish; | 646 | goto finish; |
| 397 | } | 647 | } |
| 398 | 648 | ||
| 399 | switch (protocol) { | 649 | switch (protocol) { |
| 400 | case IR_PROTOCOL_RC5: | 650 | case IR_PROTOCOL_RC5: |
| 401 | if (wake_sc > 0xFFF) { | 651 | if (wake_sc > 0xFFF) { |
| 402 | do_wake = 0; | 652 | do_wake = false; |
| 403 | dev_err(dev, "RC5 - Invalid wake scancode\n"); | 653 | dev_err(dev, "RC5 - Invalid wake scancode\n"); |
| 404 | break; | 654 | break; |
| 405 | } | 655 | } |
| @@ -418,7 +668,7 @@ wbcir_shutdown(struct pnp_dev *device) | |||
| 418 | 668 | ||
| 419 | case IR_PROTOCOL_NEC: | 669 | case IR_PROTOCOL_NEC: |
| 420 | if (wake_sc > 0xFFFFFF) { | 670 | if (wake_sc > 0xFFFFFF) { |
| 421 | do_wake = 0; | 671 | do_wake = false; |
| 422 | dev_err(dev, "NEC - Invalid wake scancode\n"); | 672 | dev_err(dev, "NEC - Invalid wake scancode\n"); |
| 423 | break; | 673 | break; |
| 424 | } | 674 | } |
| @@ -440,7 +690,7 @@ wbcir_shutdown(struct pnp_dev *device) | |||
| 440 | 690 | ||
| 441 | if (wake_rc6mode == 0) { | 691 | if (wake_rc6mode == 0) { |
| 442 | if (wake_sc > 0xFFFF) { | 692 | if (wake_sc > 0xFFFF) { |
| 443 | do_wake = 0; | 693 | do_wake = false; |
| 444 | dev_err(dev, "RC6 - Invalid wake scancode\n"); | 694 | dev_err(dev, "RC6 - Invalid wake scancode\n"); |
| 445 | break; | 695 | break; |
| 446 | } | 696 | } |
| @@ -496,7 +746,7 @@ wbcir_shutdown(struct pnp_dev *device) | |||
| 496 | } else if (wake_sc <= 0x007FFFFF) { | 746 | } else if (wake_sc <= 0x007FFFFF) { |
| 497 | rc6_csl = 60; | 747 | rc6_csl = 60; |
| 498 | } else { | 748 | } else { |
| 499 | do_wake = 0; | 749 | do_wake = false; |
| 500 | dev_err(dev, "RC6 - Invalid wake scancode\n"); | 750 | dev_err(dev, "RC6 - Invalid wake scancode\n"); |
| 501 | break; | 751 | break; |
| 502 | } | 752 | } |
| @@ -508,14 +758,14 @@ wbcir_shutdown(struct pnp_dev *device) | |||
| 508 | mask[i++] = 0x0F; | 758 | mask[i++] = 0x0F; |
| 509 | 759 | ||
| 510 | } else { | 760 | } else { |
| 511 | do_wake = 0; | 761 | do_wake = false; |
| 512 | dev_err(dev, "RC6 - Invalid wake mode\n"); | 762 | dev_err(dev, "RC6 - Invalid wake mode\n"); |
| 513 | } | 763 | } |
| 514 | 764 | ||
| 515 | break; | 765 | break; |
| 516 | 766 | ||
| 517 | default: | 767 | default: |
| 518 | do_wake = 0; | 768 | do_wake = false; |
| 519 | break; | 769 | break; |
| 520 | } | 770 | } |
| 521 | 771 | ||
| @@ -551,21 +801,18 @@ finish: | |||
| 551 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | 801 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); |
| 552 | } | 802 | } |
| 553 | 803 | ||
| 554 | /* Disable interrupts */ | ||
| 555 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 556 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
| 557 | |||
| 558 | /* Disable LED */ | ||
| 559 | data->irdata_active = false; | ||
| 560 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
| 561 | |||
| 562 | /* | 804 | /* |
| 563 | * ACPI will set the HW disable bit for SP3 which means that the | 805 | * ACPI will set the HW disable bit for SP3 which means that the |
| 564 | * output signals are left in an undefined state which may cause | 806 | * output signals are left in an undefined state which may cause |
| 565 | * spurious interrupts which we need to ignore until the hardware | 807 | * spurious interrupts which we need to ignore until the hardware |
| 566 | * is reinitialized. | 808 | * is reinitialized. |
| 567 | */ | 809 | */ |
| 810 | wbcir_set_irqmask(data, WBCIR_IRQ_NONE); | ||
| 568 | disable_irq(data->irq); | 811 | disable_irq(data->irq); |
| 812 | |||
| 813 | /* Disable LED */ | ||
| 814 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
| 815 | led_trigger_event(data->txtrigger, LED_OFF); | ||
| 569 | } | 816 | } |
| 570 | 817 | ||
| 571 | static int | 818 | static int |
| @@ -581,8 +828,7 @@ wbcir_init_hw(struct wbcir_data *data) | |||
| 581 | u8 tmp; | 828 | u8 tmp; |
| 582 | 829 | ||
| 583 | /* Disable interrupts */ | 830 | /* Disable interrupts */ |
| 584 | wbcir_select_bank(data, WBCIR_BANK_0); | 831 | wbcir_set_irqmask(data, WBCIR_IRQ_NONE); |
| 585 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
| 586 | 832 | ||
| 587 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ | 833 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ |
| 588 | tmp = protocol << 4; | 834 | tmp = protocol << 4; |
| @@ -606,10 +852,11 @@ wbcir_init_hw(struct wbcir_data *data) | |||
| 606 | outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); | 852 | outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); |
| 607 | 853 | ||
| 608 | /* | 854 | /* |
| 609 | * Clear IR LED, set SP3 clock to 24Mhz | 855 | * Clear IR LED, set SP3 clock to 24Mhz, set TX mask to IRTX1, |
| 610 | * set SP3_IRRX_SW to binary 01, helpfully not documented | 856 | * set SP3_IRRX_SW to binary 01, helpfully not documented |
| 611 | */ | 857 | */ |
| 612 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); | 858 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); |
| 859 | data->txmask = 0x1; | ||
| 613 | 860 | ||
| 614 | /* Enable extended mode */ | 861 | /* Enable extended mode */ |
| 615 | wbcir_select_bank(data, WBCIR_BANK_2); | 862 | wbcir_select_bank(data, WBCIR_BANK_2); |
| @@ -657,18 +904,21 @@ wbcir_init_hw(struct wbcir_data *data) | |||
| 657 | wbcir_select_bank(data, WBCIR_BANK_4); | 904 | wbcir_select_bank(data, WBCIR_BANK_4); |
| 658 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); | 905 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); |
| 659 | 906 | ||
| 660 | /* Enable MSR interrupt, Clear AUX_IRX */ | 907 | /* Disable MSR interrupt, clear AUX_IRX, mask RX during TX? */ |
| 661 | wbcir_select_bank(data, WBCIR_BANK_5); | 908 | wbcir_select_bank(data, WBCIR_BANK_5); |
| 662 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | 909 | outb(txandrx ? 0x03 : 0x02, data->sbase + WBCIR_REG_SP3_IRCR2); |
| 663 | 910 | ||
| 664 | /* Disable CRC */ | 911 | /* Disable CRC */ |
| 665 | wbcir_select_bank(data, WBCIR_BANK_6); | 912 | wbcir_select_bank(data, WBCIR_BANK_6); |
| 666 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); | 913 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); |
| 667 | 914 | ||
| 668 | /* Set RX/TX (de)modulation freq, not really used */ | 915 | /* Set RX demodulation freq, not really used */ |
| 669 | wbcir_select_bank(data, WBCIR_BANK_7); | 916 | wbcir_select_bank(data, WBCIR_BANK_7); |
| 670 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); | 917 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); |
| 918 | |||
| 919 | /* Set TX modulation, 36kHz, 7us pulse width */ | ||
| 671 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); | 920 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); |
| 921 | data->txcarrier = 36000; | ||
| 672 | 922 | ||
| 673 | /* Set invert and pin direction */ | 923 | /* Set invert and pin direction */ |
| 674 | if (invert) | 924 | if (invert) |
| @@ -683,16 +933,23 @@ wbcir_init_hw(struct wbcir_data *data) | |||
| 683 | /* Clear AUX status bits */ | 933 | /* Clear AUX status bits */ |
| 684 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); | 934 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); |
| 685 | 935 | ||
| 686 | /* Clear IR decoding state */ | 936 | /* Clear RX state */ |
| 687 | data->irdata_active = false; | 937 | data->rxstate = WBCIR_RXSTATE_INACTIVE; |
| 688 | led_trigger_event(data->rxtrigger, LED_OFF); | 938 | data->rxev.duration = 0; |
| 689 | data->irdata_error = false; | ||
| 690 | data->ev.duration = 0; | ||
| 691 | ir_raw_event_reset(data->dev); | 939 | ir_raw_event_reset(data->dev); |
| 692 | ir_raw_event_handle(data->dev); | 940 | ir_raw_event_handle(data->dev); |
| 693 | 941 | ||
| 942 | /* | ||
| 943 | * Check TX state, if we did a suspend/resume cycle while TX was | ||
| 944 | * active, we will have a process waiting in txwaitq. | ||
| 945 | */ | ||
| 946 | if (data->txstate == WBCIR_TXSTATE_ACTIVE) { | ||
| 947 | data->txstate = WBCIR_TXSTATE_ERROR; | ||
| 948 | wake_up(&data->txwaitq); | ||
| 949 | } | ||
| 950 | |||
| 694 | /* Enable interrupts */ | 951 | /* Enable interrupts */ |
| 695 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | 952 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); |
| 696 | } | 953 | } |
| 697 | 954 | ||
| 698 | static int | 955 | static int |
| @@ -729,6 +986,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
| 729 | pnp_set_drvdata(device, data); | 986 | pnp_set_drvdata(device, data); |
| 730 | 987 | ||
| 731 | spin_lock_init(&data->spinlock); | 988 | spin_lock_init(&data->spinlock); |
| 989 | init_waitqueue_head(&data->txwaitq); | ||
| 732 | data->ebase = pnp_port_start(device, 0); | 990 | data->ebase = pnp_port_start(device, 0); |
| 733 | data->wbase = pnp_port_start(device, 1); | 991 | data->wbase = pnp_port_start(device, 1); |
| 734 | data->sbase = pnp_port_start(device, 2); | 992 | data->sbase = pnp_port_start(device, 2); |
| @@ -807,6 +1065,11 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
| 807 | data->dev->input_id.vendor = PCI_VENDOR_ID_WINBOND; | 1065 | data->dev->input_id.vendor = PCI_VENDOR_ID_WINBOND; |
| 808 | data->dev->input_id.product = WBCIR_ID_FAMILY; | 1066 | data->dev->input_id.product = WBCIR_ID_FAMILY; |
| 809 | data->dev->input_id.version = WBCIR_ID_CHIP; | 1067 | data->dev->input_id.version = WBCIR_ID_CHIP; |
| 1068 | data->dev->map_name = RC_MAP_RC6_MCE; | ||
| 1069 | data->dev->s_idle = wbcir_idle_rx; | ||
| 1070 | data->dev->s_tx_mask = wbcir_txmask; | ||
| 1071 | data->dev->s_tx_carrier = wbcir_txcarrier; | ||
| 1072 | data->dev->tx_ir = wbcir_tx; | ||
| 810 | data->dev->priv = data; | 1073 | data->dev->priv = data; |
| 811 | data->dev->dev.parent = &device->dev; | 1074 | data->dev->dev.parent = &device->dev; |
| 812 | 1075 | ||
| @@ -849,9 +1112,7 @@ wbcir_remove(struct pnp_dev *device) | |||
| 849 | struct wbcir_data *data = pnp_get_drvdata(device); | 1112 | struct wbcir_data *data = pnp_get_drvdata(device); |
| 850 | 1113 | ||
| 851 | /* Disable interrupts */ | 1114 | /* Disable interrupts */ |
| 852 | wbcir_select_bank(data, WBCIR_BANK_0); | 1115 | wbcir_set_irqmask(data, WBCIR_IRQ_NONE); |
| 853 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
| 854 | |||
| 855 | free_irq(data->irq, device); | 1116 | free_irq(data->irq, device); |
| 856 | 1117 | ||
| 857 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ | 1118 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 00f51dd121f3..3be180b3ba27 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
| @@ -128,10 +128,10 @@ config VIDEO_IR_I2C | |||
| 128 | # Encoder / Decoder module configuration | 128 | # Encoder / Decoder module configuration |
| 129 | # | 129 | # |
| 130 | 130 | ||
| 131 | menu "Encoders/decoders and other helper chips" | 131 | menu "Encoders, decoders, sensors and other helper chips" |
| 132 | visible if !VIDEO_HELPER_CHIPS_AUTO | 132 | visible if !VIDEO_HELPER_CHIPS_AUTO |
| 133 | 133 | ||
| 134 | comment "Audio decoders" | 134 | comment "Audio decoders, processors and mixers" |
| 135 | 135 | ||
| 136 | config VIDEO_TVAUDIO | 136 | config VIDEO_TVAUDIO |
| 137 | tristate "Simple audio decoder chips" | 137 | tristate "Simple audio decoder chips" |
| @@ -210,15 +210,6 @@ config VIDEO_CS53L32A | |||
| 210 | To compile this driver as a module, choose M here: the | 210 | To compile this driver as a module, choose M here: the |
| 211 | module will be called cs53l32a. | 211 | module will be called cs53l32a. |
| 212 | 212 | ||
| 213 | config VIDEO_M52790 | ||
| 214 | tristate "Mitsubishi M52790 A/V switch" | ||
| 215 | depends on VIDEO_V4L2 && I2C | ||
| 216 | ---help--- | ||
| 217 | Support for the Mitsubishi M52790 A/V switch. | ||
| 218 | |||
| 219 | To compile this driver as a module, choose M here: the | ||
| 220 | module will be called m52790. | ||
| 221 | |||
| 222 | config VIDEO_TLV320AIC23B | 213 | config VIDEO_TLV320AIC23B |
| 223 | tristate "Texas Instruments TLV320AIC23B audio codec" | 214 | tristate "Texas Instruments TLV320AIC23B audio codec" |
| 224 | depends on VIDEO_V4L2 && I2C && EXPERIMENTAL | 215 | depends on VIDEO_V4L2 && I2C && EXPERIMENTAL |
| @@ -321,29 +312,6 @@ config VIDEO_KS0127 | |||
| 321 | To compile this driver as a module, choose M here: the | 312 | To compile this driver as a module, choose M here: the |
| 322 | module will be called ks0127. | 313 | module will be called ks0127. |
| 323 | 314 | ||
| 324 | config VIDEO_OV7670 | ||
| 325 | tristate "OmniVision OV7670 sensor support" | ||
| 326 | depends on I2C && VIDEO_V4L2 | ||
| 327 | ---help--- | ||
| 328 | This is a Video4Linux2 sensor-level driver for the OmniVision | ||
| 329 | OV7670 VGA camera. It currently only works with the M88ALP01 | ||
| 330 | controller. | ||
| 331 | |||
| 332 | config VIDEO_MT9V011 | ||
| 333 | tristate "Micron mt9v011 sensor support" | ||
| 334 | depends on I2C && VIDEO_V4L2 | ||
| 335 | ---help--- | ||
| 336 | This is a Video4Linux2 sensor-level driver for the Micron | ||
| 337 | mt0v011 1.3 Mpixel camera. It currently only works with the | ||
| 338 | em28xx driver. | ||
| 339 | |||
| 340 | config VIDEO_TCM825X | ||
| 341 | tristate "TCM825x camera sensor support" | ||
| 342 | depends on I2C && VIDEO_V4L2 | ||
| 343 | ---help--- | ||
| 344 | This is a driver for the Toshiba TCM825x VGA camera sensor. | ||
| 345 | It is used for example in Nokia N800. | ||
| 346 | |||
| 347 | config VIDEO_SAA7110 | 315 | config VIDEO_SAA7110 |
| 348 | tristate "Philips SAA7110 video decoder" | 316 | tristate "Philips SAA7110 video decoder" |
| 349 | depends on VIDEO_V4L2 && I2C | 317 | depends on VIDEO_V4L2 && I2C |
| @@ -362,15 +330,6 @@ config VIDEO_SAA711X | |||
| 362 | To compile this driver as a module, choose M here: the | 330 | To compile this driver as a module, choose M here: the |
| 363 | module will be called saa7115. | 331 | module will be called saa7115. |
| 364 | 332 | ||
| 365 | config VIDEO_SAA717X | ||
| 366 | tristate "Philips SAA7171/3/4 audio/video decoders" | ||
| 367 | depends on VIDEO_V4L2 && I2C | ||
| 368 | ---help--- | ||
| 369 | Support for the Philips SAA7171/3/4 audio/video decoders. | ||
| 370 | |||
| 371 | To compile this driver as a module, choose M here: the | ||
| 372 | module will be called saa717x. | ||
| 373 | |||
| 374 | config VIDEO_SAA7191 | 333 | config VIDEO_SAA7191 |
| 375 | tristate "Philips SAA7191 video decoder" | 334 | tristate "Philips SAA7191 video decoder" |
| 376 | depends on VIDEO_V4L2 && I2C | 335 | depends on VIDEO_V4L2 && I2C |
| @@ -420,6 +379,15 @@ config VIDEO_VPX3220 | |||
| 420 | 379 | ||
| 421 | comment "Video and audio decoders" | 380 | comment "Video and audio decoders" |
| 422 | 381 | ||
| 382 | config VIDEO_SAA717X | ||
| 383 | tristate "Philips SAA7171/3/4 audio/video decoders" | ||
| 384 | depends on VIDEO_V4L2 && I2C | ||
| 385 | ---help--- | ||
| 386 | Support for the Philips SAA7171/3/4 audio/video decoders. | ||
| 387 | |||
| 388 | To compile this driver as a module, choose M here: the | ||
| 389 | module will be called saa717x. | ||
| 390 | |||
| 423 | source "drivers/media/video/cx25840/Kconfig" | 391 | source "drivers/media/video/cx25840/Kconfig" |
| 424 | 392 | ||
| 425 | comment "MPEG video encoders" | 393 | comment "MPEG video encoders" |
| @@ -474,15 +442,6 @@ config VIDEO_ADV7175 | |||
| 474 | To compile this driver as a module, choose M here: the | 442 | To compile this driver as a module, choose M here: the |
| 475 | module will be called adv7175. | 443 | module will be called adv7175. |
| 476 | 444 | ||
| 477 | config VIDEO_THS7303 | ||
| 478 | tristate "THS7303 Video Amplifier" | ||
| 479 | depends on I2C | ||
| 480 | help | ||
| 481 | Support for TI THS7303 video amplifier | ||
| 482 | |||
| 483 | To compile this driver as a module, choose M here: the | ||
| 484 | module will be called ths7303. | ||
| 485 | |||
| 486 | config VIDEO_ADV7343 | 445 | config VIDEO_ADV7343 |
| 487 | tristate "ADV7343 video encoder" | 446 | tristate "ADV7343 video encoder" |
| 488 | depends on I2C | 447 | depends on I2C |
| @@ -498,6 +457,38 @@ config VIDEO_AK881X | |||
| 498 | help | 457 | help |
| 499 | Video output driver for AKM AK8813 and AK8814 TV encoders | 458 | Video output driver for AKM AK8813 and AK8814 TV encoders |
| 500 | 459 | ||
| 460 | comment "Camera sensor devices" | ||
| 461 | |||
| 462 | config VIDEO_OV7670 | ||
| 463 | tristate "OmniVision OV7670 sensor support" | ||
| 464 | depends on I2C && VIDEO_V4L2 | ||
| 465 | ---help--- | ||
| 466 | This is a Video4Linux2 sensor-level driver for the OmniVision | ||
| 467 | OV7670 VGA camera. It currently only works with the M88ALP01 | ||
| 468 | controller. | ||
| 469 | |||
| 470 | config VIDEO_MT9V011 | ||
| 471 | tristate "Micron mt9v011 sensor support" | ||
| 472 | depends on I2C && VIDEO_V4L2 | ||
| 473 | ---help--- | ||
| 474 | This is a Video4Linux2 sensor-level driver for the Micron | ||
| 475 | mt0v011 1.3 Mpixel camera. It currently only works with the | ||
| 476 | em28xx driver. | ||
| 477 | |||
| 478 | config VIDEO_MT9V032 | ||
| 479 | tristate "Micron MT9V032 sensor support" | ||
| 480 | depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API | ||
| 481 | ---help--- | ||
| 482 | This is a Video4Linux2 sensor-level driver for the Micron | ||
| 483 | MT9V032 752x480 CMOS sensor. | ||
| 484 | |||
| 485 | config VIDEO_TCM825X | ||
| 486 | tristate "TCM825x camera sensor support" | ||
| 487 | depends on I2C && VIDEO_V4L2 | ||
| 488 | ---help--- | ||
| 489 | This is a driver for the Toshiba TCM825x VGA camera sensor. | ||
| 490 | It is used for example in Nokia N800. | ||
| 491 | |||
| 501 | comment "Video improvement chips" | 492 | comment "Video improvement chips" |
| 502 | 493 | ||
| 503 | config VIDEO_UPD64031A | 494 | config VIDEO_UPD64031A |
| @@ -523,6 +514,26 @@ config VIDEO_UPD64083 | |||
| 523 | To compile this driver as a module, choose M here: the | 514 | To compile this driver as a module, choose M here: the |
| 524 | module will be called upd64083. | 515 | module will be called upd64083. |
| 525 | 516 | ||
| 517 | comment "Miscelaneous helper chips" | ||
| 518 | |||
| 519 | config VIDEO_THS7303 | ||
| 520 | tristate "THS7303 Video Amplifier" | ||
| 521 | depends on I2C | ||
| 522 | help | ||
| 523 | Support for TI THS7303 video amplifier | ||
| 524 | |||
| 525 | To compile this driver as a module, choose M here: the | ||
| 526 | module will be called ths7303. | ||
| 527 | |||
| 528 | config VIDEO_M52790 | ||
| 529 | tristate "Mitsubishi M52790 A/V switch" | ||
| 530 | depends on VIDEO_V4L2 && I2C | ||
| 531 | ---help--- | ||
| 532 | Support for the Mitsubishi M52790 A/V switch. | ||
| 533 | |||
| 534 | To compile this driver as a module, choose M here: the | ||
| 535 | module will be called m52790. | ||
| 536 | |||
| 526 | endmenu # encoder / decoder chips | 537 | endmenu # encoder / decoder chips |
| 527 | 538 | ||
| 528 | config VIDEO_SH_VOU | 539 | config VIDEO_SH_VOU |
| @@ -682,7 +693,7 @@ config VIDEO_TIMBERDALE | |||
| 682 | select VIDEO_ADV7180 | 693 | select VIDEO_ADV7180 |
| 683 | select VIDEOBUF_DMA_CONTIG | 694 | select VIDEOBUF_DMA_CONTIG |
| 684 | ---help--- | 695 | ---help--- |
| 685 | Add support for the Video In peripherial of the timberdale FPGA. | 696 | Add support for the Video In peripherial of the timberdale FPGA. |
| 686 | 697 | ||
| 687 | source "drivers/media/video/cx88/Kconfig" | 698 | source "drivers/media/video/cx88/Kconfig" |
| 688 | 699 | ||
| @@ -916,7 +927,7 @@ config VIDEO_OMAP2 | |||
| 916 | This is a v4l2 driver for the TI OMAP2 camera capture interface | 927 | This is a v4l2 driver for the TI OMAP2 camera capture interface |
| 917 | 928 | ||
| 918 | config VIDEO_MX2_HOSTSUPPORT | 929 | config VIDEO_MX2_HOSTSUPPORT |
| 919 | bool | 930 | bool |
| 920 | 931 | ||
| 921 | config VIDEO_MX2 | 932 | config VIDEO_MX2 |
| 922 | tristate "i.MX27/i.MX25 Camera Sensor Interface driver" | 933 | tristate "i.MX27/i.MX25 Camera Sensor Interface driver" |
| @@ -927,6 +938,26 @@ config VIDEO_MX2 | |||
| 927 | This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor | 938 | This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor |
| 928 | Interface | 939 | Interface |
| 929 | 940 | ||
| 941 | config VIDEO_SAMSUNG_S5P_FIMC | ||
| 942 | tristate "Samsung S5P and EXYNOS4 camera host interface driver" | ||
| 943 | depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P | ||
| 944 | select VIDEOBUF2_DMA_CONTIG | ||
| 945 | select V4L2_MEM2MEM_DEV | ||
| 946 | ---help--- | ||
| 947 | This is a v4l2 driver for Samsung S5P and EXYNOS4 camera | ||
| 948 | host interface and video postprocessor. | ||
| 949 | |||
| 950 | To compile this driver as a module, choose M here: the | ||
| 951 | module will be called s5p-fimc. | ||
| 952 | |||
| 953 | config VIDEO_S5P_MIPI_CSIS | ||
| 954 | tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" | ||
| 955 | depends on VIDEO_V4L2 && PM_RUNTIME && VIDEO_V4L2_SUBDEV_API | ||
| 956 | ---help--- | ||
| 957 | This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. | ||
| 958 | |||
| 959 | To compile this driver as a module, choose M here: the | ||
| 960 | module will be called s5p-csis. | ||
| 930 | 961 | ||
| 931 | # | 962 | # |
| 932 | # USB Multimedia device configuration | 963 | # USB Multimedia device configuration |
| @@ -983,7 +1014,7 @@ config USB_STKWEBCAM | |||
| 983 | Supported devices are typically found in some Asus laptops, | 1014 | Supported devices are typically found in some Asus laptops, |
| 984 | with USB id 174f:a311 and 05e1:0501. Other Syntek cameras | 1015 | with USB id 174f:a311 and 05e1:0501. Other Syntek cameras |
| 985 | may be supported by the stk11xx driver, from which this is | 1016 | may be supported by the stk11xx driver, from which this is |
| 986 | derived, see <http://sourceforge.net/projects/syntekdriver/> | 1017 | derived, see <http://sourceforge.net/projects/syntekdriver/> |
| 987 | 1018 | ||
| 988 | To compile this driver as a module, choose M here: the | 1019 | To compile this driver as a module, choose M here: the |
| 989 | module will be called stkwebcam. | 1020 | module will be called stkwebcam. |
| @@ -1022,13 +1053,5 @@ config VIDEO_MEM2MEM_TESTDEV | |||
| 1022 | This is a virtual test device for the memory-to-memory driver | 1053 | This is a virtual test device for the memory-to-memory driver |
| 1023 | framework. | 1054 | framework. |
| 1024 | 1055 | ||
| 1025 | config VIDEO_SAMSUNG_S5P_FIMC | ||
| 1026 | tristate "Samsung S5P FIMC (video postprocessor) driver" | ||
| 1027 | depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P | ||
| 1028 | select VIDEOBUF2_DMA_CONTIG | ||
| 1029 | select V4L2_MEM2MEM_DEV | ||
| 1030 | help | ||
| 1031 | This is a v4l2 driver for the S5P camera interface | ||
| 1032 | (video postprocessor) | ||
| 1033 | 1056 | ||
| 1034 | endif # V4L_MEM2MEM_DRIVERS | 1057 | endif # V4L_MEM2MEM_DRIVERS |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ace5d8b57221..9519160c2e01 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
| @@ -66,6 +66,7 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | |||
| 66 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | 66 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o |
| 67 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | 67 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
| 68 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | 68 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o |
| 69 | obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o | ||
| 69 | obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o | 70 | obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o |
| 70 | obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o | 71 | obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o |
| 71 | 72 | ||
| @@ -164,6 +165,7 @@ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | |||
| 164 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o | 165 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o |
| 165 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 166 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
| 166 | obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o | 167 | obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o |
| 168 | |||
| 167 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ | 169 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ |
| 168 | 170 | ||
| 169 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | 171 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 91399c94cd18..a97cf2750bd9 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
| @@ -4303,7 +4303,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, | |||
| 4303 | goto fail0; | 4303 | goto fail0; |
| 4304 | } | 4304 | } |
| 4305 | 4305 | ||
| 4306 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); | 4306 | btv->revision = dev->revision; |
| 4307 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); | 4307 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
| 4308 | printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", | 4308 | printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", |
| 4309 | bttv_num,btv->id, btv->revision, pci_name(dev)); | 4309 | bttv_num,btv->id, btv->revision, pci_name(dev)); |
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 5111bbcefad5..0073a8c55336 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
| @@ -1313,7 +1313,7 @@ static int cpia2_g_priority(struct file *file, void *_fh, enum v4l2_priority *p) | |||
| 1313 | static int cpia2_s_priority(struct file *file, void *_fh, enum v4l2_priority prio) | 1313 | static int cpia2_s_priority(struct file *file, void *_fh, enum v4l2_priority prio) |
| 1314 | { | 1314 | { |
| 1315 | struct camera_data *cam = video_drvdata(file); | 1315 | struct camera_data *cam = video_drvdata(file); |
| 1316 | struct cpia2_fh *fh = fh; | 1316 | struct cpia2_fh *fh = _fh; |
| 1317 | 1317 | ||
| 1318 | if (cam->streaming && prio != fh->prio && | 1318 | if (cam->streaming && prio != fh->prio && |
| 1319 | fh->prio == V4L2_PRIORITY_RECORD) | 1319 | fh->prio == V4L2_PRIORITY_RECORD) |
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index d9d2f6ad6ffb..53b3c7702573 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
| @@ -2,6 +2,7 @@ config VIDEO_CX18 | |||
| 2 | tristate "Conexant cx23418 MPEG encoder support" | 2 | tristate "Conexant cx23418 MPEG encoder support" |
| 3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL | 3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL |
| 4 | select I2C_ALGOBIT | 4 | select I2C_ALGOBIT |
| 5 | select VIDEOBUF_VMALLOC | ||
| 5 | depends on RC_CORE | 6 | depends on RC_CORE |
| 6 | select VIDEO_TUNER | 7 | select VIDEO_TUNER |
| 7 | select VIDEO_TVEEPROM | 8 | select VIDEO_TVEEPROM |
| @@ -9,6 +10,9 @@ config VIDEO_CX18 | |||
| 9 | select VIDEO_CS5345 | 10 | select VIDEO_CS5345 |
| 10 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | 11 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
| 11 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | 12 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE |
| 13 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | ||
| 14 | select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE | ||
| 15 | select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE | ||
| 12 | ---help--- | 16 | ---help--- |
| 13 | This is a video4linux driver for Conexant cx23418 based | 17 | This is a video4linux driver for Conexant cx23418 based |
| 14 | PCI combo video recorder devices. | 18 | PCI combo video recorder devices. |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 68ad1963f421..c07c849b1aaf 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
| @@ -39,6 +39,16 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { | |||
| 39 | .tv = { 0x61, 0x60, I2C_CLIENT_END }, | 39 | .tv = { 0x61, 0x60, I2C_CLIENT_END }, |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | /* | ||
| 43 | * usual i2c tuner addresses to probe with additional demod address for | ||
| 44 | * an NXP TDA8295 at 0x42 (N.B. it can possibly be at 0x4b or 0x4c too). | ||
| 45 | */ | ||
| 46 | static struct cx18_card_tuner_i2c cx18_i2c_nxp = { | ||
| 47 | .radio = { I2C_CLIENT_END }, | ||
| 48 | .demod = { 0x42, 0x43, I2C_CLIENT_END }, | ||
| 49 | .tv = { 0x61, 0x60, I2C_CLIENT_END }, | ||
| 50 | }; | ||
| 51 | |||
| 42 | /* Please add new PCI IDs to: http://pci-ids.ucw.cz/ | 52 | /* Please add new PCI IDs to: http://pci-ids.ucw.cz/ |
| 43 | This keeps the PCI ID database up to date. Note that the entries | 53 | This keeps the PCI ID database up to date. Note that the entries |
| 44 | must be added under vendor 0x4444 (Conexant) as subsystem IDs. | 54 | must be added under vendor 0x4444 (Conexant) as subsystem IDs. |
| @@ -131,15 +141,15 @@ static const struct cx18_card cx18_card_hvr1600_s5h1411 = { | |||
| 131 | .tune_lane = 0, | 141 | .tune_lane = 0, |
| 132 | .initial_emrs = 0, | 142 | .initial_emrs = 0, |
| 133 | }, | 143 | }, |
| 134 | .gpio_init.initial_value = 0x3001, | 144 | .gpio_init.initial_value = 0x3801, |
| 135 | .gpio_init.direction = 0x3001, | 145 | .gpio_init.direction = 0x3801, |
| 136 | .gpio_i2c_slave_reset = { | 146 | .gpio_i2c_slave_reset = { |
| 137 | .active_lo_mask = 0x3001, | 147 | .active_lo_mask = 0x3801, |
| 138 | .msecs_asserted = 10, | 148 | .msecs_asserted = 10, |
| 139 | .msecs_recovery = 40, | 149 | .msecs_recovery = 40, |
| 140 | .ir_reset_mask = 0x0001, | 150 | .ir_reset_mask = 0x0001, |
| 141 | }, | 151 | }, |
| 142 | .i2c = &cx18_i2c_std, | 152 | .i2c = &cx18_i2c_nxp, |
| 143 | }; | 153 | }; |
| 144 | 154 | ||
| 145 | static const struct cx18_card cx18_card_hvr1600_samsung = { | 155 | static const struct cx18_card cx18_card_hvr1600_samsung = { |
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index 3e750068f275..add7391ecaba 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h | |||
| @@ -109,7 +109,7 @@ struct cx18_card_tuner { | |||
| 109 | 109 | ||
| 110 | struct cx18_card_tuner_i2c { | 110 | struct cx18_card_tuner_i2c { |
| 111 | unsigned short radio[2];/* radio tuner i2c address to probe */ | 111 | unsigned short radio[2];/* radio tuner i2c address to probe */ |
| 112 | unsigned short demod[2];/* demodulator i2c address to probe */ | 112 | unsigned short demod[3];/* demodulator i2c address to probe */ |
| 113 | unsigned short tv[4]; /* tv tuner i2c addresses to probe */ | 113 | unsigned short tv[4]; /* tv tuner i2c addresses to probe */ |
| 114 | }; | 114 | }; |
| 115 | 115 | ||
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 321c1b79794c..9e2f870f4258 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
| @@ -423,7 +423,16 @@ static void cx18_process_eeprom(struct cx18 *cx) | |||
| 423 | return; | 423 | return; |
| 424 | 424 | ||
| 425 | /* autodetect tuner standard */ | 425 | /* autodetect tuner standard */ |
| 426 | if (tv.tuner_formats & V4L2_STD_PAL) { | 426 | #define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B | V4L2_STD_GH | \ |
| 427 | V4L2_STD_MN | \ | ||
| 428 | V4L2_STD_PAL_I | \ | ||
| 429 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \ | ||
| 430 | V4L2_STD_DK) | ||
| 431 | if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL) | ||
| 432 | == TVEEPROM_TUNER_FORMAT_ALL) { | ||
| 433 | CX18_DEBUG_INFO("Worldwide tuner detected\n"); | ||
| 434 | cx->std = V4L2_STD_ALL; | ||
| 435 | } else if (tv.tuner_formats & V4L2_STD_PAL) { | ||
| 427 | CX18_DEBUG_INFO("PAL tuner detected\n"); | 436 | CX18_DEBUG_INFO("PAL tuner detected\n"); |
| 428 | cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; | 437 | cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; |
| 429 | } else if (tv.tuner_formats & V4L2_STD_NTSC) { | 438 | } else if (tv.tuner_formats & V4L2_STD_NTSC) { |
| @@ -818,7 +827,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, | |||
| 818 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | 827 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; |
| 819 | pci_write_config_word(pci_dev, PCI_COMMAND, cmd); | 828 | pci_write_config_word(pci_dev, PCI_COMMAND, cmd); |
| 820 | 829 | ||
| 821 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cx->card_rev); | 830 | cx->card_rev = pci_dev->revision; |
| 822 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); | 831 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); |
| 823 | 832 | ||
| 824 | if (pci_latency < 64 && cx18_pci_latency) { | 833 | if (pci_latency < 64 && cx18_pci_latency) { |
| @@ -1001,7 +1010,15 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, | |||
| 1001 | if (cx->card->hw_all & CX18_HW_TVEEPROM) { | 1010 | if (cx->card->hw_all & CX18_HW_TVEEPROM) { |
| 1002 | /* Based on the model number the cardtype may be changed. | 1011 | /* Based on the model number the cardtype may be changed. |
| 1003 | The PCI IDs are not always reliable. */ | 1012 | The PCI IDs are not always reliable. */ |
| 1013 | const struct cx18_card *orig_card = cx->card; | ||
| 1004 | cx18_process_eeprom(cx); | 1014 | cx18_process_eeprom(cx); |
| 1015 | |||
| 1016 | if (cx->card != orig_card) { | ||
| 1017 | /* Changed the cardtype; re-reset the I2C chips */ | ||
| 1018 | cx18_gpio_init(cx); | ||
| 1019 | cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, | ||
| 1020 | core, reset, (u32) CX18_GPIO_RESET_I2C); | ||
| 1021 | } | ||
| 1005 | } | 1022 | } |
| 1006 | if (cx->card->comment) | 1023 | if (cx->card->comment) |
| 1007 | CX18_INFO("%s", cx->card->comment); | 1024 | CX18_INFO("%s", cx->card->comment); |
| @@ -1087,6 +1104,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, | |||
| 1087 | /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) | 1104 | /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) |
| 1088 | are not. */ | 1105 | are not. */ |
| 1089 | cx->tuner_std = cx->std; | 1106 | cx->tuner_std = cx->std; |
| 1107 | if (cx->std == V4L2_STD_ALL) | ||
| 1108 | cx->std = V4L2_STD_NTSC_M; | ||
| 1090 | 1109 | ||
| 1091 | retval = cx18_streams_setup(cx); | 1110 | retval = cx18_streams_setup(cx); |
| 1092 | if (retval) { | 1111 | if (retval) { |
| @@ -1133,6 +1152,7 @@ int cx18_init_on_first_open(struct cx18 *cx) | |||
| 1133 | int fw_retry_count = 3; | 1152 | int fw_retry_count = 3; |
| 1134 | struct v4l2_frequency vf; | 1153 | struct v4l2_frequency vf; |
| 1135 | struct cx18_open_id fh; | 1154 | struct cx18_open_id fh; |
| 1155 | v4l2_std_id std; | ||
| 1136 | 1156 | ||
| 1137 | fh.cx = cx; | 1157 | fh.cx = cx; |
| 1138 | 1158 | ||
| @@ -1220,7 +1240,8 @@ int cx18_init_on_first_open(struct cx18 *cx) | |||
| 1220 | /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code | 1240 | /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code |
| 1221 | in one place. */ | 1241 | in one place. */ |
| 1222 | cx->std++; /* Force full standard initialization */ | 1242 | cx->std++; /* Force full standard initialization */ |
| 1223 | cx18_s_std(NULL, &fh, &cx->tuner_std); | 1243 | std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std; |
| 1244 | cx18_s_std(NULL, &fh, &std); | ||
| 1224 | cx18_s_frequency(NULL, &fh, &vf); | 1245 | cx18_s_frequency(NULL, &fh, &vf); |
| 1225 | return 0; | 1246 | return 0; |
| 1226 | } | 1247 | } |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index b86a740c68df..086427288de8 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
| @@ -65,6 +65,10 @@ | |||
| 65 | #include "dvb_net.h" | 65 | #include "dvb_net.h" |
| 66 | #include "dvbdev.h" | 66 | #include "dvbdev.h" |
| 67 | 67 | ||
| 68 | /* Videobuf / YUV support */ | ||
| 69 | #include <media/videobuf-core.h> | ||
| 70 | #include <media/videobuf-vmalloc.h> | ||
| 71 | |||
| 68 | #ifndef CONFIG_PCI | 72 | #ifndef CONFIG_PCI |
| 69 | # error "This driver requires kernel PCI support." | 73 | # error "This driver requires kernel PCI support." |
| 70 | #endif | 74 | #endif |
| @@ -403,6 +407,23 @@ struct cx18_stream { | |||
| 403 | struct cx18_queue q_idle; /* idle - not in rotation */ | 407 | struct cx18_queue q_idle; /* idle - not in rotation */ |
| 404 | 408 | ||
| 405 | struct work_struct out_work_order; | 409 | struct work_struct out_work_order; |
| 410 | |||
| 411 | /* Videobuf for YUV video */ | ||
| 412 | u32 pixelformat; | ||
| 413 | struct list_head vb_capture; /* video capture queue */ | ||
| 414 | spinlock_t vb_lock; | ||
| 415 | struct timer_list vb_timeout; | ||
| 416 | |||
| 417 | struct videobuf_queue vbuf_q; | ||
| 418 | spinlock_t vbuf_q_lock; /* Protect vbuf_q */ | ||
| 419 | enum v4l2_buf_type vb_type; | ||
| 420 | }; | ||
| 421 | |||
| 422 | struct cx18_videobuf_buffer { | ||
| 423 | /* Common video buffer sub-system struct */ | ||
| 424 | struct videobuf_buffer vb; | ||
| 425 | v4l2_std_id tvnorm; /* selected tv norm */ | ||
| 426 | u32 bytes_used; | ||
| 406 | }; | 427 | }; |
| 407 | 428 | ||
| 408 | struct cx18_open_id { | 429 | struct cx18_open_id { |
| @@ -410,6 +431,10 @@ struct cx18_open_id { | |||
| 410 | u32 open_id; | 431 | u32 open_id; |
| 411 | int type; | 432 | int type; |
| 412 | struct cx18 *cx; | 433 | struct cx18 *cx; |
| 434 | |||
| 435 | struct videobuf_queue vbuf_q; | ||
| 436 | spinlock_t s_lock; /* Protect vbuf_q */ | ||
| 437 | enum v4l2_buf_type vb_type; | ||
| 413 | }; | 438 | }; |
| 414 | 439 | ||
| 415 | static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh) | 440 | static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh) |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index e9802d99439b..07411f34885a 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
| @@ -597,6 +597,13 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, | |||
| 597 | mutex_unlock(&cx->serialize_lock); | 597 | mutex_unlock(&cx->serialize_lock); |
| 598 | if (rc) | 598 | if (rc) |
| 599 | return rc; | 599 | return rc; |
| 600 | |||
| 601 | if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 602 | (id->type == CX18_ENC_STREAM_TYPE_YUV)) { | ||
| 603 | return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0, | ||
| 604 | filp->f_flags & O_NONBLOCK); | ||
| 605 | } | ||
| 606 | |||
| 600 | return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); | 607 | return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); |
| 601 | } | 608 | } |
| 602 | 609 | ||
| @@ -622,6 +629,15 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) | |||
| 622 | CX18_DEBUG_FILE("Encoder poll started capture\n"); | 629 | CX18_DEBUG_FILE("Encoder poll started capture\n"); |
| 623 | } | 630 | } |
| 624 | 631 | ||
| 632 | if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 633 | (id->type == CX18_ENC_STREAM_TYPE_YUV)) { | ||
| 634 | int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait); | ||
| 635 | if (eof && videobuf_poll == POLLERR) | ||
| 636 | return POLLHUP; | ||
| 637 | else | ||
| 638 | return videobuf_poll; | ||
| 639 | } | ||
| 640 | |||
| 625 | /* add stream's waitq to the poll list */ | 641 | /* add stream's waitq to the poll list */ |
| 626 | CX18_DEBUG_HI_FILE("Encoder poll\n"); | 642 | CX18_DEBUG_HI_FILE("Encoder poll\n"); |
| 627 | poll_wait(filp, &s->waitq, wait); | 643 | poll_wait(filp, &s->waitq, wait); |
| @@ -633,6 +649,58 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) | |||
| 633 | return 0; | 649 | return 0; |
| 634 | } | 650 | } |
| 635 | 651 | ||
| 652 | int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 653 | { | ||
| 654 | struct cx18_open_id *id = file->private_data; | ||
| 655 | struct cx18 *cx = id->cx; | ||
| 656 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 657 | int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags); | ||
| 658 | |||
| 659 | if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 660 | (id->type == CX18_ENC_STREAM_TYPE_YUV)) { | ||
| 661 | |||
| 662 | /* Start a capture if there is none */ | ||
| 663 | if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) { | ||
| 664 | int rc; | ||
| 665 | |||
| 666 | mutex_lock(&cx->serialize_lock); | ||
| 667 | rc = cx18_start_capture(id); | ||
| 668 | mutex_unlock(&cx->serialize_lock); | ||
| 669 | if (rc) { | ||
| 670 | CX18_DEBUG_INFO( | ||
| 671 | "Could not start capture for %s (%d)\n", | ||
| 672 | s->name, rc); | ||
| 673 | return -EINVAL; | ||
| 674 | } | ||
| 675 | CX18_DEBUG_FILE("Encoder mmap started capture\n"); | ||
| 676 | } | ||
| 677 | |||
| 678 | return videobuf_mmap_mapper(&s->vbuf_q, vma); | ||
| 679 | } | ||
| 680 | |||
| 681 | return -EINVAL; | ||
| 682 | } | ||
| 683 | |||
| 684 | void cx18_vb_timeout(unsigned long data) | ||
| 685 | { | ||
| 686 | struct cx18_stream *s = (struct cx18_stream *)data; | ||
| 687 | struct cx18_videobuf_buffer *buf; | ||
| 688 | unsigned long flags; | ||
| 689 | |||
| 690 | /* Return all of the buffers in error state, so the vbi/vid inode | ||
| 691 | * can return from blocking. | ||
| 692 | */ | ||
| 693 | spin_lock_irqsave(&s->vb_lock, flags); | ||
| 694 | while (!list_empty(&s->vb_capture)) { | ||
| 695 | buf = list_entry(s->vb_capture.next, | ||
| 696 | struct cx18_videobuf_buffer, vb.queue); | ||
| 697 | list_del(&buf->vb.queue); | ||
| 698 | buf->vb.state = VIDEOBUF_ERROR; | ||
| 699 | wake_up(&buf->vb.done); | ||
| 700 | } | ||
| 701 | spin_unlock_irqrestore(&s->vb_lock, flags); | ||
| 702 | } | ||
| 703 | |||
| 636 | void cx18_stop_capture(struct cx18_open_id *id, int gop_end) | 704 | void cx18_stop_capture(struct cx18_open_id *id, int gop_end) |
| 637 | { | 705 | { |
| 638 | struct cx18 *cx = id->cx; | 706 | struct cx18 *cx = id->cx; |
| @@ -716,6 +784,8 @@ int cx18_v4l2_close(struct file *filp) | |||
| 716 | cx18_release_stream(s); | 784 | cx18_release_stream(s); |
| 717 | } else { | 785 | } else { |
| 718 | cx18_stop_capture(id, 0); | 786 | cx18_stop_capture(id, 0); |
| 787 | if (id->type == CX18_ENC_STREAM_TYPE_YUV) | ||
| 788 | videobuf_mmap_free(&id->vbuf_q); | ||
| 719 | } | 789 | } |
| 720 | kfree(id); | 790 | kfree(id); |
| 721 | mutex_unlock(&cx->serialize_lock); | 791 | mutex_unlock(&cx->serialize_lock); |
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h index 5c8fcb884f0a..b9e5110ad043 100644 --- a/drivers/media/video/cx18/cx18-fileops.h +++ b/drivers/media/video/cx18/cx18-fileops.h | |||
| @@ -33,6 +33,8 @@ int cx18_start_capture(struct cx18_open_id *id); | |||
| 33 | void cx18_stop_capture(struct cx18_open_id *id, int gop_end); | 33 | void cx18_stop_capture(struct cx18_open_id *id, int gop_end); |
| 34 | void cx18_mute(struct cx18 *cx); | 34 | void cx18_mute(struct cx18 *cx); |
| 35 | void cx18_unmute(struct cx18 *cx); | 35 | void cx18_unmute(struct cx18 *cx); |
| 36 | int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma); | ||
| 37 | void cx18_vb_timeout(unsigned long data); | ||
| 36 | 38 | ||
| 37 | /* Shared with cx18-alsa module */ | 39 | /* Shared with cx18-alsa module */ |
| 38 | int cx18_claim_stream(struct cx18_open_id *id, int type); | 40 | int cx18_claim_stream(struct cx18_open_id *id, int type); |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 4f041c033c54..1933d4d11bf2 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
| @@ -150,6 +150,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh, | |||
| 150 | { | 150 | { |
| 151 | struct cx18_open_id *id = fh2id(fh); | 151 | struct cx18_open_id *id = fh2id(fh); |
| 152 | struct cx18 *cx = id->cx; | 152 | struct cx18 *cx = id->cx; |
| 153 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 153 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | 154 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
| 154 | 155 | ||
| 155 | pixfmt->width = cx->cxhdl.width; | 156 | pixfmt->width = cx->cxhdl.width; |
| @@ -158,9 +159,13 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh, | |||
| 158 | pixfmt->field = V4L2_FIELD_INTERLACED; | 159 | pixfmt->field = V4L2_FIELD_INTERLACED; |
| 159 | pixfmt->priv = 0; | 160 | pixfmt->priv = 0; |
| 160 | if (id->type == CX18_ENC_STREAM_TYPE_YUV) { | 161 | if (id->type == CX18_ENC_STREAM_TYPE_YUV) { |
| 161 | pixfmt->pixelformat = V4L2_PIX_FMT_HM12; | 162 | pixfmt->pixelformat = s->pixelformat; |
| 162 | /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ | 163 | /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) |
| 163 | pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; | 164 | UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ |
| 165 | if (s->pixelformat == V4L2_PIX_FMT_HM12) | ||
| 166 | pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; | ||
| 167 | else | ||
| 168 | pixfmt->sizeimage = pixfmt->height * 720 * 2; | ||
| 164 | pixfmt->bytesperline = 720; | 169 | pixfmt->bytesperline = 720; |
| 165 | } else { | 170 | } else { |
| 166 | pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; | 171 | pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; |
| @@ -237,7 +242,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, | |||
| 237 | h = min(h, cx->is_50hz ? 576 : 480); | 242 | h = min(h, cx->is_50hz ? 576 : 480); |
| 238 | h = max(h, min_h); | 243 | h = max(h, min_h); |
| 239 | 244 | ||
| 240 | cx18_g_fmt_vid_cap(file, fh, fmt); | ||
| 241 | fmt->fmt.pix.width = w; | 245 | fmt->fmt.pix.width = w; |
| 242 | fmt->fmt.pix.height = h; | 246 | fmt->fmt.pix.height = h; |
| 243 | return 0; | 247 | return 0; |
| @@ -274,6 +278,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | |||
| 274 | struct cx18_open_id *id = fh2id(fh); | 278 | struct cx18_open_id *id = fh2id(fh); |
| 275 | struct cx18 *cx = id->cx; | 279 | struct cx18 *cx = id->cx; |
| 276 | struct v4l2_mbus_framefmt mbus_fmt; | 280 | struct v4l2_mbus_framefmt mbus_fmt; |
| 281 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 277 | int ret; | 282 | int ret; |
| 278 | int w, h; | 283 | int w, h; |
| 279 | 284 | ||
| @@ -283,12 +288,15 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | |||
| 283 | w = fmt->fmt.pix.width; | 288 | w = fmt->fmt.pix.width; |
| 284 | h = fmt->fmt.pix.height; | 289 | h = fmt->fmt.pix.height; |
| 285 | 290 | ||
| 286 | if (cx->cxhdl.width == w && cx->cxhdl.height == h) | 291 | if (cx->cxhdl.width == w && cx->cxhdl.height == h && |
| 292 | s->pixelformat == fmt->fmt.pix.pixelformat) | ||
| 287 | return 0; | 293 | return 0; |
| 288 | 294 | ||
| 289 | if (atomic_read(&cx->ana_capturing) > 0) | 295 | if (atomic_read(&cx->ana_capturing) > 0) |
| 290 | return -EBUSY; | 296 | return -EBUSY; |
| 291 | 297 | ||
| 298 | s->pixelformat = fmt->fmt.pix.pixelformat; | ||
| 299 | |||
| 292 | mbus_fmt.width = cx->cxhdl.width = w; | 300 | mbus_fmt.width = cx->cxhdl.width = w; |
| 293 | mbus_fmt.height = cx->cxhdl.height = h; | 301 | mbus_fmt.height = cx->cxhdl.height = h; |
| 294 | mbus_fmt.code = V4L2_MBUS_FMT_FIXED; | 302 | mbus_fmt.code = V4L2_MBUS_FMT_FIXED; |
| @@ -540,16 +548,19 @@ static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) | |||
| 540 | static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, | 548 | static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, |
| 541 | struct v4l2_fmtdesc *fmt) | 549 | struct v4l2_fmtdesc *fmt) |
| 542 | { | 550 | { |
| 543 | static struct v4l2_fmtdesc formats[] = { | 551 | static const struct v4l2_fmtdesc formats[] = { |
| 544 | { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, | 552 | { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, |
| 545 | "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 } | 553 | "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 } |
| 546 | }, | 554 | }, |
| 547 | { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED, | 555 | { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED, |
| 548 | "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 } | 556 | "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 } |
| 549 | } | 557 | }, |
| 558 | { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, | ||
| 559 | "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 } | ||
| 560 | }, | ||
| 550 | }; | 561 | }; |
| 551 | 562 | ||
| 552 | if (fmt->index > 1) | 563 | if (fmt->index > ARRAY_SIZE(formats) - 1) |
| 553 | return -EINVAL; | 564 | return -EINVAL; |
| 554 | *fmt = formats[fmt->index]; | 565 | *fmt = formats[fmt->index]; |
| 555 | return 0; | 566 | return 0; |
| @@ -863,6 +874,117 @@ static int cx18_g_enc_index(struct file *file, void *fh, | |||
| 863 | return 0; | 874 | return 0; |
| 864 | } | 875 | } |
| 865 | 876 | ||
| 877 | static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id) | ||
| 878 | { | ||
| 879 | struct videobuf_queue *q = NULL; | ||
| 880 | struct cx18 *cx = id->cx; | ||
| 881 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 882 | |||
| 883 | switch (s->vb_type) { | ||
| 884 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
| 885 | q = &s->vbuf_q; | ||
| 886 | break; | ||
| 887 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
| 888 | break; | ||
| 889 | default: | ||
| 890 | break; | ||
| 891 | } | ||
| 892 | return q; | ||
| 893 | } | ||
| 894 | |||
| 895 | static int cx18_streamon(struct file *file, void *priv, | ||
| 896 | enum v4l2_buf_type type) | ||
| 897 | { | ||
| 898 | struct cx18_open_id *id = file->private_data; | ||
| 899 | struct cx18 *cx = id->cx; | ||
| 900 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 901 | |||
| 902 | /* Start the hardware only if we're the video device */ | ||
| 903 | if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 904 | (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
| 905 | return -EINVAL; | ||
| 906 | |||
| 907 | if (id->type != CX18_ENC_STREAM_TYPE_YUV) | ||
| 908 | return -EINVAL; | ||
| 909 | |||
| 910 | /* Establish a buffer timeout */ | ||
| 911 | mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies); | ||
| 912 | |||
| 913 | return videobuf_streamon(cx18_vb_queue(id)); | ||
| 914 | } | ||
| 915 | |||
| 916 | static int cx18_streamoff(struct file *file, void *priv, | ||
| 917 | enum v4l2_buf_type type) | ||
| 918 | { | ||
| 919 | struct cx18_open_id *id = file->private_data; | ||
| 920 | struct cx18 *cx = id->cx; | ||
| 921 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 922 | |||
| 923 | /* Start the hardware only if we're the video device */ | ||
| 924 | if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 925 | (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
| 926 | return -EINVAL; | ||
| 927 | |||
| 928 | if (id->type != CX18_ENC_STREAM_TYPE_YUV) | ||
| 929 | return -EINVAL; | ||
| 930 | |||
| 931 | return videobuf_streamoff(cx18_vb_queue(id)); | ||
| 932 | } | ||
| 933 | |||
| 934 | static int cx18_reqbufs(struct file *file, void *priv, | ||
| 935 | struct v4l2_requestbuffers *rb) | ||
| 936 | { | ||
| 937 | struct cx18_open_id *id = file->private_data; | ||
| 938 | struct cx18 *cx = id->cx; | ||
| 939 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 940 | |||
| 941 | if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 942 | (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
| 943 | return -EINVAL; | ||
| 944 | |||
| 945 | return videobuf_reqbufs(cx18_vb_queue(id), rb); | ||
| 946 | } | ||
| 947 | |||
| 948 | static int cx18_querybuf(struct file *file, void *priv, | ||
| 949 | struct v4l2_buffer *b) | ||
| 950 | { | ||
| 951 | struct cx18_open_id *id = file->private_data; | ||
| 952 | struct cx18 *cx = id->cx; | ||
| 953 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 954 | |||
| 955 | if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 956 | (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
| 957 | return -EINVAL; | ||
| 958 | |||
| 959 | return videobuf_querybuf(cx18_vb_queue(id), b); | ||
| 960 | } | ||
| 961 | |||
| 962 | static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
| 963 | { | ||
| 964 | struct cx18_open_id *id = file->private_data; | ||
| 965 | struct cx18 *cx = id->cx; | ||
| 966 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 967 | |||
| 968 | if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 969 | (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
| 970 | return -EINVAL; | ||
| 971 | |||
| 972 | return videobuf_qbuf(cx18_vb_queue(id), b); | ||
| 973 | } | ||
| 974 | |||
| 975 | static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
| 976 | { | ||
| 977 | struct cx18_open_id *id = file->private_data; | ||
| 978 | struct cx18 *cx = id->cx; | ||
| 979 | struct cx18_stream *s = &cx->streams[id->type]; | ||
| 980 | |||
| 981 | if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 982 | (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
| 983 | return -EINVAL; | ||
| 984 | |||
| 985 | return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK); | ||
| 986 | } | ||
| 987 | |||
| 866 | static int cx18_encoder_cmd(struct file *file, void *fh, | 988 | static int cx18_encoder_cmd(struct file *file, void *fh, |
| 867 | struct v4l2_encoder_cmd *enc) | 989 | struct v4l2_encoder_cmd *enc) |
| 868 | { | 990 | { |
| @@ -1081,6 +1203,12 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = { | |||
| 1081 | .vidioc_s_register = cx18_s_register, | 1203 | .vidioc_s_register = cx18_s_register, |
| 1082 | #endif | 1204 | #endif |
| 1083 | .vidioc_default = cx18_default, | 1205 | .vidioc_default = cx18_default, |
| 1206 | .vidioc_streamon = cx18_streamon, | ||
| 1207 | .vidioc_streamoff = cx18_streamoff, | ||
| 1208 | .vidioc_reqbufs = cx18_reqbufs, | ||
| 1209 | .vidioc_querybuf = cx18_querybuf, | ||
| 1210 | .vidioc_qbuf = cx18_qbuf, | ||
| 1211 | .vidioc_dqbuf = cx18_dqbuf, | ||
| 1084 | }; | 1212 | }; |
| 1085 | 1213 | ||
| 1086 | void cx18_set_funcs(struct video_device *vdev) | 1214 | void cx18_set_funcs(struct video_device *vdev) |
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 9605d54bd083..c07191e09fcb 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
| @@ -81,6 +81,7 @@ static const struct cx18_api_info api_info[] = { | |||
| 81 | API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM, 0), | 81 | API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM, 0), |
| 82 | API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER, 0), | 82 | API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER, 0), |
| 83 | API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0), | 83 | API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0), |
| 84 | API_ENTRY(CPU, CX18_CPU_SET_VFC_PARAM, 0), | ||
| 84 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), | 85 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), |
| 85 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), | 86 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), |
| 86 | API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), | 87 | API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), |
| @@ -158,6 +159,60 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) | |||
| 158 | } | 159 | } |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 162 | static void cx18_mdl_send_to_videobuf(struct cx18_stream *s, | ||
| 163 | struct cx18_mdl *mdl) | ||
| 164 | { | ||
| 165 | struct cx18_videobuf_buffer *vb_buf; | ||
| 166 | struct cx18_buffer *buf; | ||
| 167 | u8 *p; | ||
| 168 | u32 offset = 0; | ||
| 169 | int dispatch = 0; | ||
| 170 | |||
| 171 | if (mdl->bytesused == 0) | ||
| 172 | return; | ||
| 173 | |||
| 174 | /* Acquire a videobuf buffer, clone to and and release it */ | ||
| 175 | spin_lock(&s->vb_lock); | ||
| 176 | if (list_empty(&s->vb_capture)) | ||
| 177 | goto out; | ||
| 178 | |||
| 179 | vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer, | ||
| 180 | vb.queue); | ||
| 181 | |||
| 182 | p = videobuf_to_vmalloc(&vb_buf->vb); | ||
| 183 | if (!p) | ||
| 184 | goto out; | ||
| 185 | |||
| 186 | offset = vb_buf->bytes_used; | ||
| 187 | list_for_each_entry(buf, &mdl->buf_list, list) { | ||
| 188 | if (buf->bytesused == 0) | ||
| 189 | break; | ||
| 190 | |||
| 191 | if ((offset + buf->bytesused) <= vb_buf->vb.bsize) { | ||
| 192 | memcpy(p + offset, buf->buf, buf->bytesused); | ||
| 193 | offset += buf->bytesused; | ||
| 194 | vb_buf->bytes_used += buf->bytesused; | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | /* If we've filled the buffer as per the callers res then dispatch it */ | ||
| 199 | if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) { | ||
| 200 | dispatch = 1; | ||
| 201 | vb_buf->bytes_used = 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | if (dispatch) { | ||
| 205 | vb_buf->vb.ts = ktime_to_timeval(ktime_get()); | ||
| 206 | list_del(&vb_buf->vb.queue); | ||
| 207 | vb_buf->vb.state = VIDEOBUF_DONE; | ||
| 208 | wake_up(&vb_buf->vb.done); | ||
| 209 | } | ||
| 210 | |||
| 211 | mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies); | ||
| 212 | |||
| 213 | out: | ||
| 214 | spin_unlock(&s->vb_lock); | ||
| 215 | } | ||
| 161 | 216 | ||
| 162 | static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s, | 217 | static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s, |
| 163 | struct cx18_mdl *mdl) | 218 | struct cx18_mdl *mdl) |
| @@ -263,6 +318,9 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | |||
| 263 | } else { | 318 | } else { |
| 264 | cx18_enqueue(s, mdl, &s->q_full); | 319 | cx18_enqueue(s, mdl, &s->q_full); |
| 265 | } | 320 | } |
| 321 | } else if (s->type == CX18_ENC_STREAM_TYPE_YUV) { | ||
| 322 | cx18_mdl_send_to_videobuf(s, mdl); | ||
| 323 | cx18_enqueue(s, mdl, &s->q_free); | ||
| 266 | } else { | 324 | } else { |
| 267 | cx18_enqueue(s, mdl, &s->q_full); | 325 | cx18_enqueue(s, mdl, &s->q_full); |
| 268 | if (s->type == CX18_ENC_STREAM_TYPE_IDX) | 326 | if (s->type == CX18_ENC_STREAM_TYPE_IDX) |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 6fbc356113c1..852f420fd271 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
| @@ -44,6 +44,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = { | |||
| 44 | .unlocked_ioctl = cx18_v4l2_ioctl, | 44 | .unlocked_ioctl = cx18_v4l2_ioctl, |
| 45 | .release = cx18_v4l2_close, | 45 | .release = cx18_v4l2_close, |
| 46 | .poll = cx18_v4l2_enc_poll, | 46 | .poll = cx18_v4l2_enc_poll, |
| 47 | .mmap = cx18_v4l2_mmap, | ||
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 49 | /* offset from 0 to register ts v4l2 minors on */ | 50 | /* offset from 0 to register ts v4l2 minors on */ |
| @@ -97,6 +98,141 @@ static struct { | |||
| 97 | }, | 98 | }, |
| 98 | }; | 99 | }; |
| 99 | 100 | ||
| 101 | |||
| 102 | void cx18_dma_free(struct videobuf_queue *q, | ||
| 103 | struct cx18_stream *s, struct cx18_videobuf_buffer *buf) | ||
| 104 | { | ||
| 105 | videobuf_waiton(q, &buf->vb, 0, 0); | ||
| 106 | videobuf_vmalloc_free(&buf->vb); | ||
| 107 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int cx18_prepare_buffer(struct videobuf_queue *q, | ||
| 111 | struct cx18_stream *s, | ||
| 112 | struct cx18_videobuf_buffer *buf, | ||
| 113 | u32 pixelformat, | ||
| 114 | unsigned int width, unsigned int height, | ||
| 115 | enum v4l2_field field) | ||
| 116 | { | ||
| 117 | struct cx18 *cx = s->cx; | ||
| 118 | int rc = 0; | ||
| 119 | |||
| 120 | /* check settings */ | ||
| 121 | buf->bytes_used = 0; | ||
| 122 | |||
| 123 | if ((width < 48) || (height < 32)) | ||
| 124 | return -EINVAL; | ||
| 125 | |||
| 126 | buf->vb.size = (width * height * 2); | ||
| 127 | if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size)) | ||
| 128 | return -EINVAL; | ||
| 129 | |||
| 130 | /* alloc + fill struct (if changed) */ | ||
| 131 | if (buf->vb.width != width || buf->vb.height != height || | ||
| 132 | buf->vb.field != field || s->pixelformat != pixelformat || | ||
| 133 | buf->tvnorm != cx->std) { | ||
| 134 | |||
| 135 | buf->vb.width = width; | ||
| 136 | buf->vb.height = height; | ||
| 137 | buf->vb.field = field; | ||
| 138 | buf->tvnorm = cx->std; | ||
| 139 | s->pixelformat = pixelformat; | ||
| 140 | |||
| 141 | cx18_dma_free(q, s, buf); | ||
| 142 | } | ||
| 143 | |||
| 144 | if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size)) | ||
| 145 | return -EINVAL; | ||
| 146 | |||
| 147 | if (buf->vb.field == 0) | ||
| 148 | buf->vb.field = V4L2_FIELD_INTERLACED; | ||
| 149 | |||
| 150 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
| 151 | buf->vb.width = width; | ||
| 152 | buf->vb.height = height; | ||
| 153 | buf->vb.field = field; | ||
| 154 | buf->tvnorm = cx->std; | ||
| 155 | s->pixelformat = pixelformat; | ||
| 156 | |||
| 157 | rc = videobuf_iolock(q, &buf->vb, NULL); | ||
| 158 | if (rc != 0) | ||
| 159 | goto fail; | ||
| 160 | } | ||
| 161 | buf->vb.state = VIDEOBUF_PREPARED; | ||
| 162 | return 0; | ||
| 163 | |||
| 164 | fail: | ||
| 165 | cx18_dma_free(q, s, buf); | ||
| 166 | return rc; | ||
| 167 | |||
| 168 | } | ||
| 169 | |||
| 170 | /* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576) | ||
| 171 | 1440 is a single line of 4:2:2 YUV at 720 luma samples wide | ||
| 172 | */ | ||
| 173 | #define VB_MIN_BUFFERS 32 | ||
| 174 | #define VB_MIN_BUFSIZE 4147200 | ||
| 175 | |||
| 176 | static int buffer_setup(struct videobuf_queue *q, | ||
| 177 | unsigned int *count, unsigned int *size) | ||
| 178 | { | ||
| 179 | struct cx18_stream *s = q->priv_data; | ||
| 180 | struct cx18 *cx = s->cx; | ||
| 181 | |||
| 182 | *size = 2 * cx->cxhdl.width * cx->cxhdl.height; | ||
| 183 | if (*count == 0) | ||
| 184 | *count = VB_MIN_BUFFERS; | ||
| 185 | |||
| 186 | while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE) | ||
| 187 | (*count)--; | ||
| 188 | |||
| 189 | q->field = V4L2_FIELD_INTERLACED; | ||
| 190 | q->last = V4L2_FIELD_INTERLACED; | ||
| 191 | |||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int buffer_prepare(struct videobuf_queue *q, | ||
| 196 | struct videobuf_buffer *vb, | ||
| 197 | enum v4l2_field field) | ||
| 198 | { | ||
| 199 | struct cx18_videobuf_buffer *buf = | ||
| 200 | container_of(vb, struct cx18_videobuf_buffer, vb); | ||
| 201 | struct cx18_stream *s = q->priv_data; | ||
| 202 | struct cx18 *cx = s->cx; | ||
| 203 | |||
| 204 | return cx18_prepare_buffer(q, s, buf, s->pixelformat, | ||
| 205 | cx->cxhdl.width, cx->cxhdl.height, field); | ||
| 206 | } | ||
| 207 | |||
| 208 | static void buffer_release(struct videobuf_queue *q, | ||
| 209 | struct videobuf_buffer *vb) | ||
| 210 | { | ||
| 211 | struct cx18_videobuf_buffer *buf = | ||
| 212 | container_of(vb, struct cx18_videobuf_buffer, vb); | ||
| 213 | struct cx18_stream *s = q->priv_data; | ||
| 214 | |||
| 215 | cx18_dma_free(q, s, buf); | ||
| 216 | } | ||
| 217 | |||
| 218 | static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
| 219 | { | ||
| 220 | struct cx18_videobuf_buffer *buf = | ||
| 221 | container_of(vb, struct cx18_videobuf_buffer, vb); | ||
| 222 | struct cx18_stream *s = q->priv_data; | ||
| 223 | |||
| 224 | buf->vb.state = VIDEOBUF_QUEUED; | ||
| 225 | |||
| 226 | list_add_tail(&buf->vb.queue, &s->vb_capture); | ||
| 227 | } | ||
| 228 | |||
| 229 | static struct videobuf_queue_ops cx18_videobuf_qops = { | ||
| 230 | .buf_setup = buffer_setup, | ||
| 231 | .buf_prepare = buffer_prepare, | ||
| 232 | .buf_queue = buffer_queue, | ||
| 233 | .buf_release = buffer_release, | ||
| 234 | }; | ||
| 235 | |||
| 100 | static void cx18_stream_init(struct cx18 *cx, int type) | 236 | static void cx18_stream_init(struct cx18 *cx, int type) |
| 101 | { | 237 | { |
| 102 | struct cx18_stream *s = &cx->streams[type]; | 238 | struct cx18_stream *s = &cx->streams[type]; |
| @@ -132,6 +268,26 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
| 132 | cx18_queue_init(&s->q_idle); | 268 | cx18_queue_init(&s->q_idle); |
| 133 | 269 | ||
| 134 | INIT_WORK(&s->out_work_order, cx18_out_work_handler); | 270 | INIT_WORK(&s->out_work_order, cx18_out_work_handler); |
| 271 | |||
| 272 | INIT_LIST_HEAD(&s->vb_capture); | ||
| 273 | s->vb_timeout.function = cx18_vb_timeout; | ||
| 274 | s->vb_timeout.data = (unsigned long)s; | ||
| 275 | init_timer(&s->vb_timeout); | ||
| 276 | spin_lock_init(&s->vb_lock); | ||
| 277 | if (type == CX18_ENC_STREAM_TYPE_YUV) { | ||
| 278 | spin_lock_init(&s->vbuf_q_lock); | ||
| 279 | |||
| 280 | s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 281 | videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops, | ||
| 282 | &cx->pci_dev->dev, &s->vbuf_q_lock, | ||
| 283 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
| 284 | V4L2_FIELD_INTERLACED, | ||
| 285 | sizeof(struct cx18_videobuf_buffer), | ||
| 286 | s, &cx->serialize_lock); | ||
| 287 | |||
| 288 | /* Assume the previous pixel default */ | ||
| 289 | s->pixelformat = V4L2_PIX_FMT_HM12; | ||
| 290 | } | ||
| 135 | } | 291 | } |
| 136 | 292 | ||
| 137 | static int cx18_prep_dev(struct cx18 *cx, int type) | 293 | static int cx18_prep_dev(struct cx18 *cx, int type) |
| @@ -372,6 +528,9 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) | |||
| 372 | if (vdev == NULL) | 528 | if (vdev == NULL) |
| 373 | continue; | 529 | continue; |
| 374 | 530 | ||
| 531 | if (type == CX18_ENC_STREAM_TYPE_YUV) | ||
| 532 | videobuf_mmap_free(&cx->streams[type].vbuf_q); | ||
| 533 | |||
| 375 | cx18_stream_free(&cx->streams[type]); | 534 | cx18_stream_free(&cx->streams[type]); |
| 376 | 535 | ||
| 377 | /* Unregister or release device */ | 536 | /* Unregister or release device */ |
| @@ -581,7 +740,10 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s) | |||
| 581 | * Set the MDL size to the exact size needed for one frame. | 740 | * Set the MDL size to the exact size needed for one frame. |
| 582 | * Use enough buffers per MDL to cover the MDL size | 741 | * Use enough buffers per MDL to cover the MDL size |
| 583 | */ | 742 | */ |
| 584 | s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2; | 743 | if (s->pixelformat == V4L2_PIX_FMT_HM12) |
| 744 | s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2; | ||
| 745 | else | ||
| 746 | s->mdl_size = 720 * s->cx->cxhdl.height * 2; | ||
| 585 | s->bufs_per_mdl = s->mdl_size / s->buf_size; | 747 | s->bufs_per_mdl = s->mdl_size / s->buf_size; |
| 586 | if (s->mdl_size % s->buf_size) | 748 | if (s->mdl_size % s->buf_size) |
| 587 | s->bufs_per_mdl++; | 749 | s->bufs_per_mdl++; |
| @@ -729,6 +891,19 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
| 729 | test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) | 891 | test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) |
| 730 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, | 892 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, |
| 731 | (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1); | 893 | (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1); |
| 894 | |||
| 895 | /* Enable the Video Format Converter for UYVY 4:2:2 support, | ||
| 896 | * rather than the default HM12 Macroblovk 4:2:0 support. | ||
| 897 | */ | ||
| 898 | if (captype == CAPTURE_CHANNEL_TYPE_YUV) { | ||
| 899 | if (s->pixelformat == V4L2_PIX_FMT_UYVY) | ||
| 900 | cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2, | ||
| 901 | s->handle, 1); | ||
| 902 | else | ||
| 903 | /* If in doubt, default to HM12 */ | ||
| 904 | cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2, | ||
| 905 | s->handle, 0); | ||
| 906 | } | ||
| 732 | } | 907 | } |
| 733 | 908 | ||
| 734 | if (atomic_read(&cx->tot_capturing) == 0) { | 909 | if (atomic_read(&cx->tot_capturing) == 0) { |
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index 3e1aec4bcfde..cd189b6bbe20 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | #define CX18_DRIVER_NAME "cx18" | 25 | #define CX18_DRIVER_NAME "cx18" |
| 26 | #define CX18_DRIVER_VERSION_MAJOR 1 | 26 | #define CX18_DRIVER_VERSION_MAJOR 1 |
| 27 | #define CX18_DRIVER_VERSION_MINOR 4 | 27 | #define CX18_DRIVER_VERSION_MINOR 5 |
| 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 | 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 |
| 29 | 29 | ||
| 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) | 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) |
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index 935f557acbd0..767a8d23e3f2 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h | |||
| @@ -342,6 +342,12 @@ | |||
| 342 | ReturnCode */ | 342 | ReturnCode */ |
| 343 | #define CX18_CPU_GET_ENC_PTS (CPU_CMD_MASK_CAPTURE | 0x0022) | 343 | #define CX18_CPU_GET_ENC_PTS (CPU_CMD_MASK_CAPTURE | 0x0022) |
| 344 | 344 | ||
| 345 | /* Description: Set VFC parameters | ||
| 346 | IN[0] - task handle | ||
| 347 | IN[1] - VFC enable flag, 1 - enable, 0 - disable | ||
| 348 | */ | ||
| 349 | #define CX18_CPU_SET_VFC_PARAM (CPU_CMD_MASK_CAPTURE | 0x0023) | ||
| 350 | |||
| 345 | /* Below is the list of commands related to the data exchange */ | 351 | /* Below is the list of commands related to the data exchange */ |
| 346 | #define CPU_CMD_MASK_DE (CPU_CMD_MASK | 0x040000) | 352 | #define CPU_CMD_MASK_DE (CPU_CMD_MASK | 0x040000) |
| 347 | 353 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index f49230d170e6..22703815a31f 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c | |||
| @@ -401,6 +401,44 @@ struct cx231xx_board cx231xx_boards[] = { | |||
| 401 | .gpio = NULL, | 401 | .gpio = NULL, |
| 402 | } }, | 402 | } }, |
| 403 | }, | 403 | }, |
| 404 | [CX231XX_BOARD_KWORLD_UB430_USB_HYBRID] = { | ||
| 405 | .name = "Kworld UB430 USB Hybrid", | ||
| 406 | .tuner_type = TUNER_NXP_TDA18271, | ||
| 407 | .tuner_addr = 0x60, | ||
| 408 | .decoder = CX231XX_AVDECODER, | ||
| 409 | .output_mode = OUT_MODE_VIP11, | ||
| 410 | .demod_xfer_mode = 0, | ||
| 411 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
| 412 | .agc_analog_digital_select_gpio = 0x11, /* According with PV cxPolaris.inf file */ | ||
| 413 | .tuner_sif_gpio = -1, | ||
| 414 | .tuner_scl_gpio = -1, | ||
| 415 | .tuner_sda_gpio = -1, | ||
| 416 | .gpio_pin_status_mask = 0x4001000, | ||
| 417 | .tuner_i2c_master = 2, | ||
| 418 | .demod_i2c_master = 1, | ||
| 419 | .ir_i2c_master = 2, | ||
| 420 | .has_dvb = 1, | ||
| 421 | .demod_addr = 0x10, | ||
| 422 | .norm = V4L2_STD_PAL_M, | ||
| 423 | .input = {{ | ||
| 424 | .type = CX231XX_VMUX_TELEVISION, | ||
| 425 | .vmux = CX231XX_VIN_3_1, | ||
| 426 | .amux = CX231XX_AMUX_VIDEO, | ||
| 427 | .gpio = NULL, | ||
| 428 | }, { | ||
| 429 | .type = CX231XX_VMUX_COMPOSITE1, | ||
| 430 | .vmux = CX231XX_VIN_2_1, | ||
| 431 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 432 | .gpio = NULL, | ||
| 433 | }, { | ||
| 434 | .type = CX231XX_VMUX_SVIDEO, | ||
| 435 | .vmux = CX231XX_VIN_1_1 | | ||
| 436 | (CX231XX_VIN_1_2 << 8) | | ||
| 437 | CX25840_SVIDEO_ON, | ||
| 438 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 439 | .gpio = NULL, | ||
| 440 | } }, | ||
| 441 | }, | ||
| 404 | [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { | 442 | [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { |
| 405 | .name = "Pixelview PlayTV USB Hybrid", | 443 | .name = "Pixelview PlayTV USB Hybrid", |
| 406 | .tuner_type = TUNER_NXP_TDA18271, | 444 | .tuner_type = TUNER_NXP_TDA18271, |
| @@ -469,6 +507,31 @@ struct cx231xx_board cx231xx_boards[] = { | |||
| 469 | } | 507 | } |
| 470 | }, | 508 | }, |
| 471 | }, | 509 | }, |
| 510 | |||
| 511 | [CX231XX_BOARD_ICONBIT_U100] = { | ||
| 512 | .name = "Iconbit Analog Stick U100 FM", | ||
| 513 | .tuner_type = TUNER_ABSENT, | ||
| 514 | .decoder = CX231XX_AVDECODER, | ||
| 515 | .output_mode = OUT_MODE_VIP11, | ||
| 516 | .demod_xfer_mode = 0, | ||
| 517 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
| 518 | .agc_analog_digital_select_gpio = 0x1C, | ||
| 519 | .gpio_pin_status_mask = 0x4001000, | ||
| 520 | |||
| 521 | .input = {{ | ||
| 522 | .type = CX231XX_VMUX_COMPOSITE1, | ||
| 523 | .vmux = CX231XX_VIN_2_1, | ||
| 524 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 525 | .gpio = NULL, | ||
| 526 | }, { | ||
| 527 | .type = CX231XX_VMUX_SVIDEO, | ||
| 528 | .vmux = CX231XX_VIN_1_1 | | ||
| 529 | (CX231XX_VIN_1_2 << 8) | | ||
| 530 | CX25840_SVIDEO_ON, | ||
| 531 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 532 | .gpio = NULL, | ||
| 533 | } }, | ||
| 534 | }, | ||
| 472 | }; | 535 | }; |
| 473 | const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); | 536 | const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); |
| 474 | 537 | ||
| @@ -500,6 +563,10 @@ struct usb_device_id cx231xx_id_table[] = { | |||
| 500 | .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, | 563 | .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, |
| 501 | {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014), | 564 | {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014), |
| 502 | .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, | 565 | .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, |
| 566 | {USB_DEVICE(0x1b80, 0xe424), | ||
| 567 | .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID}, | ||
| 568 | {USB_DEVICE(0x1f4d, 0x0237), | ||
| 569 | .driver_info = CX231XX_BOARD_ICONBIT_U100}, | ||
| 503 | {}, | 570 | {}, |
| 504 | }; | 571 | }; |
| 505 | 572 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index 363aa6004221..da9a4a0aab79 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c | |||
| @@ -704,6 +704,7 @@ static int dvb_init(struct cx231xx *dev) | |||
| 704 | break; | 704 | break; |
| 705 | 705 | ||
| 706 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: | 706 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: |
| 707 | case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: | ||
| 707 | 708 | ||
| 708 | printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n", | 709 | printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n", |
| 709 | __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap)); | 710 | __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap)); |
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index bd4a9cf29577..46dd84067816 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h | |||
| @@ -65,6 +65,8 @@ | |||
| 65 | #define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9 | 65 | #define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9 |
| 66 | #define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10 | 66 | #define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10 |
| 67 | #define CX231XX_BOARD_PV_XCAPTURE_USB 11 | 67 | #define CX231XX_BOARD_PV_XCAPTURE_USB 11 |
| 68 | #define CX231XX_BOARD_KWORLD_UB430_USB_HYBRID 12 | ||
| 69 | #define CX231XX_BOARD_ICONBIT_U100 13 | ||
| 68 | 70 | ||
| 69 | /* Limits minimum and default number of buffers */ | 71 | /* Limits minimum and default number of buffers */ |
| 70 | #define CX231XX_MIN_BUF 4 | 72 | #define CX231XX_MIN_BUF 4 |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index ea88722cb4ab..2354336862cf 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
| @@ -1399,6 +1399,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
| 1399 | else | 1399 | else |
| 1400 | altera_init(&netup_config, fw); | 1400 | altera_init(&netup_config, fw); |
| 1401 | 1401 | ||
| 1402 | release_firmware(fw); | ||
| 1402 | break; | 1403 | break; |
| 1403 | } | 1404 | } |
| 1404 | } | 1405 | } |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 9933810b4e33..64d9b2136ff6 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
| @@ -2045,7 +2045,7 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, | |||
| 2045 | } | 2045 | } |
| 2046 | 2046 | ||
| 2047 | /* print pci info */ | 2047 | /* print pci info */ |
| 2048 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); | 2048 | dev->pci_rev = pci_dev->revision; |
| 2049 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); | 2049 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); |
| 2050 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " | 2050 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " |
| 2051 | "latency: %d, mmio: 0x%llx\n", dev->name, | 2051 | "latency: %d, mmio: 0x%llx\n", dev->name, |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index bca307eb1e24..11e49bbc4a66 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
| @@ -1060,18 +1060,21 @@ static int mpeg_open(struct file *file) | |||
| 1060 | 1060 | ||
| 1061 | /* Make sure we can acquire the hardware */ | 1061 | /* Make sure we can acquire the hardware */ |
| 1062 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | 1062 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); |
| 1063 | if (drv) { | 1063 | if (!drv) { |
| 1064 | err = drv->request_acquire(drv); | 1064 | dprintk(1, "%s: blackbird driver is not loaded\n", __func__); |
| 1065 | if(err != 0) { | 1065 | mutex_unlock(&dev->core->lock); |
| 1066 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); | 1066 | return -ENODEV; |
| 1067 | mutex_unlock(&dev->core->lock); | 1067 | } |
| 1068 | return err; | 1068 | |
| 1069 | } | 1069 | err = drv->request_acquire(drv); |
| 1070 | if (err != 0) { | ||
| 1071 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); | ||
| 1072 | mutex_unlock(&dev->core->lock); | ||
| 1073 | return err; | ||
| 1070 | } | 1074 | } |
| 1071 | 1075 | ||
| 1072 | if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) { | 1076 | if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) { |
| 1073 | if (drv) | 1077 | drv->request_release(drv); |
| 1074 | drv->request_release(drv); | ||
| 1075 | mutex_unlock(&dev->core->lock); | 1078 | mutex_unlock(&dev->core->lock); |
| 1076 | return -EINVAL; | 1079 | return -EINVAL; |
| 1077 | } | 1080 | } |
| @@ -1080,8 +1083,7 @@ static int mpeg_open(struct file *file) | |||
| 1080 | /* allocate + initialize per filehandle data */ | 1083 | /* allocate + initialize per filehandle data */ |
| 1081 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 1084 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
| 1082 | if (NULL == fh) { | 1085 | if (NULL == fh) { |
| 1083 | if (drv) | 1086 | drv->request_release(drv); |
| 1084 | drv->request_release(drv); | ||
| 1085 | mutex_unlock(&dev->core->lock); | 1087 | mutex_unlock(&dev->core->lock); |
| 1086 | return -ENOMEM; | 1088 | return -ENOMEM; |
| 1087 | } | 1089 | } |
| @@ -1099,7 +1101,7 @@ static int mpeg_open(struct file *file) | |||
| 1099 | cx88_set_scale(dev->core, dev->width, dev->height, | 1101 | cx88_set_scale(dev->core, dev->width, dev->height, |
| 1100 | fh->mpegq.field); | 1102 | fh->mpegq.field); |
| 1101 | 1103 | ||
| 1102 | atomic_inc(&dev->core->mpeg_users); | 1104 | dev->core->mpeg_users++; |
| 1103 | mutex_unlock(&dev->core->lock); | 1105 | mutex_unlock(&dev->core->lock); |
| 1104 | return 0; | 1106 | return 0; |
| 1105 | } | 1107 | } |
| @@ -1110,7 +1112,9 @@ static int mpeg_release(struct file *file) | |||
| 1110 | struct cx8802_dev *dev = fh->dev; | 1112 | struct cx8802_dev *dev = fh->dev; |
| 1111 | struct cx8802_driver *drv = NULL; | 1113 | struct cx8802_driver *drv = NULL; |
| 1112 | 1114 | ||
| 1113 | if (dev->mpeg_active && atomic_read(&dev->core->mpeg_users) == 1) | 1115 | mutex_lock(&dev->core->lock); |
| 1116 | |||
| 1117 | if (dev->mpeg_active && dev->core->mpeg_users == 1) | ||
| 1114 | blackbird_stop_codec(dev); | 1118 | blackbird_stop_codec(dev); |
| 1115 | 1119 | ||
| 1116 | cx8802_cancel_buffers(fh->dev); | 1120 | cx8802_cancel_buffers(fh->dev); |
| @@ -1119,17 +1123,18 @@ static int mpeg_release(struct file *file) | |||
| 1119 | 1123 | ||
| 1120 | videobuf_mmap_free(&fh->mpegq); | 1124 | videobuf_mmap_free(&fh->mpegq); |
| 1121 | 1125 | ||
| 1122 | mutex_lock(&dev->core->lock); | ||
| 1123 | file->private_data = NULL; | 1126 | file->private_data = NULL; |
| 1124 | kfree(fh); | 1127 | kfree(fh); |
| 1125 | mutex_unlock(&dev->core->lock); | ||
| 1126 | 1128 | ||
| 1127 | /* Make sure we release the hardware */ | 1129 | /* Make sure we release the hardware */ |
| 1128 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | 1130 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); |
| 1131 | WARN_ON(!drv); | ||
| 1129 | if (drv) | 1132 | if (drv) |
| 1130 | drv->request_release(drv); | 1133 | drv->request_release(drv); |
| 1131 | 1134 | ||
| 1132 | atomic_dec(&dev->core->mpeg_users); | 1135 | dev->core->mpeg_users--; |
| 1136 | |||
| 1137 | mutex_unlock(&dev->core->lock); | ||
| 1133 | 1138 | ||
| 1134 | return 0; | 1139 | return 0; |
| 1135 | } | 1140 | } |
| @@ -1334,11 +1339,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
| 1334 | blackbird_register_video(dev); | 1339 | blackbird_register_video(dev); |
| 1335 | 1340 | ||
| 1336 | /* initial device configuration: needed ? */ | 1341 | /* initial device configuration: needed ? */ |
| 1337 | mutex_lock(&dev->core->lock); | ||
| 1338 | // init_controls(core); | 1342 | // init_controls(core); |
| 1339 | cx88_set_tvnorm(core,core->tvnorm); | 1343 | cx88_set_tvnorm(core,core->tvnorm); |
| 1340 | cx88_video_mux(core,0); | 1344 | cx88_video_mux(core,0); |
| 1341 | mutex_unlock(&dev->core->lock); | ||
| 1342 | 1345 | ||
| 1343 | return 0; | 1346 | return 0; |
| 1344 | 1347 | ||
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 7b8c9d3b6efc..c69df7ebb6a7 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
| @@ -133,6 +133,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | |||
| 133 | return -EINVAL; | 133 | return -EINVAL; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | mutex_lock(&dev->core->lock); | ||
| 136 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); | 137 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); |
| 137 | if (drv) { | 138 | if (drv) { |
| 138 | if (acquire){ | 139 | if (acquire){ |
| @@ -143,6 +144,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | |||
| 143 | dev->frontends.active_fe_id = 0; | 144 | dev->frontends.active_fe_id = 0; |
| 144 | } | 145 | } |
| 145 | } | 146 | } |
| 147 | mutex_unlock(&dev->core->lock); | ||
| 146 | 148 | ||
| 147 | return ret; | 149 | return ret; |
| 148 | } | 150 | } |
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index addf9545e9bf..1a7b983f8297 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
| @@ -78,6 +78,7 @@ static void flush_request_modules(struct cx8802_dev *dev) | |||
| 78 | 78 | ||
| 79 | 79 | ||
| 80 | static LIST_HEAD(cx8802_devlist); | 80 | static LIST_HEAD(cx8802_devlist); |
| 81 | static DEFINE_MUTEX(cx8802_mutex); | ||
| 81 | /* ------------------------------------------------------------------ */ | 82 | /* ------------------------------------------------------------------ */ |
| 82 | 83 | ||
| 83 | static int cx8802_start_dma(struct cx8802_dev *dev, | 84 | static int cx8802_start_dma(struct cx8802_dev *dev, |
| @@ -474,7 +475,7 @@ static int cx8802_init_common(struct cx8802_dev *dev) | |||
| 474 | return -EIO; | 475 | return -EIO; |
| 475 | } | 476 | } |
| 476 | 477 | ||
| 477 | pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev); | 478 | dev->pci_rev = dev->pci->revision; |
| 478 | pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); | 479 | pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); |
| 479 | printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " | 480 | printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " |
| 480 | "latency: %d, mmio: 0x%llx\n", dev->core->name, | 481 | "latency: %d, mmio: 0x%llx\n", dev->core->name, |
| @@ -624,13 +625,11 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) | |||
| 624 | 625 | ||
| 625 | if (drv->advise_acquire) | 626 | if (drv->advise_acquire) |
| 626 | { | 627 | { |
| 627 | mutex_lock(&drv->core->lock); | ||
| 628 | core->active_ref++; | 628 | core->active_ref++; |
| 629 | if (core->active_type_id == CX88_BOARD_NONE) { | 629 | if (core->active_type_id == CX88_BOARD_NONE) { |
| 630 | core->active_type_id = drv->type_id; | 630 | core->active_type_id = drv->type_id; |
| 631 | drv->advise_acquire(drv); | 631 | drv->advise_acquire(drv); |
| 632 | } | 632 | } |
| 633 | mutex_unlock(&drv->core->lock); | ||
| 634 | 633 | ||
| 635 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); | 634 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); |
| 636 | } | 635 | } |
| @@ -643,14 +642,12 @@ static int cx8802_request_release(struct cx8802_driver *drv) | |||
| 643 | { | 642 | { |
| 644 | struct cx88_core *core = drv->core; | 643 | struct cx88_core *core = drv->core; |
| 645 | 644 | ||
| 646 | mutex_lock(&drv->core->lock); | ||
| 647 | if (drv->advise_release && --core->active_ref == 0) | 645 | if (drv->advise_release && --core->active_ref == 0) |
| 648 | { | 646 | { |
| 649 | drv->advise_release(drv); | 647 | drv->advise_release(drv); |
| 650 | core->active_type_id = CX88_BOARD_NONE; | 648 | core->active_type_id = CX88_BOARD_NONE; |
| 651 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); | 649 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); |
| 652 | } | 650 | } |
| 653 | mutex_unlock(&drv->core->lock); | ||
| 654 | 651 | ||
| 655 | return 0; | 652 | return 0; |
| 656 | } | 653 | } |
| @@ -693,6 +690,8 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
| 693 | return err; | 690 | return err; |
| 694 | } | 691 | } |
| 695 | 692 | ||
| 693 | mutex_lock(&cx8802_mutex); | ||
| 694 | |||
| 696 | list_for_each_entry(dev, &cx8802_devlist, devlist) { | 695 | list_for_each_entry(dev, &cx8802_devlist, devlist) { |
| 697 | printk(KERN_INFO | 696 | printk(KERN_INFO |
| 698 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", | 697 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", |
| @@ -702,8 +701,10 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
| 702 | 701 | ||
| 703 | /* Bring up a new struct for each driver instance */ | 702 | /* Bring up a new struct for each driver instance */ |
| 704 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); | 703 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); |
| 705 | if (driver == NULL) | 704 | if (driver == NULL) { |
| 706 | return -ENOMEM; | 705 | err = -ENOMEM; |
| 706 | goto out; | ||
| 707 | } | ||
| 707 | 708 | ||
| 708 | /* Snapshot of the driver registration data */ | 709 | /* Snapshot of the driver registration data */ |
| 709 | drv->core = dev->core; | 710 | drv->core = dev->core; |
| @@ -713,21 +714,23 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
| 713 | drv->request_release = cx8802_request_release; | 714 | drv->request_release = cx8802_request_release; |
| 714 | memcpy(driver, drv, sizeof(*driver)); | 715 | memcpy(driver, drv, sizeof(*driver)); |
| 715 | 716 | ||
| 717 | mutex_lock(&drv->core->lock); | ||
| 716 | err = drv->probe(driver); | 718 | err = drv->probe(driver); |
| 717 | if (err == 0) { | 719 | if (err == 0) { |
| 718 | i++; | 720 | i++; |
| 719 | mutex_lock(&drv->core->lock); | ||
| 720 | list_add_tail(&driver->drvlist, &dev->drvlist); | 721 | list_add_tail(&driver->drvlist, &dev->drvlist); |
| 721 | mutex_unlock(&drv->core->lock); | ||
| 722 | } else { | 722 | } else { |
| 723 | printk(KERN_ERR | 723 | printk(KERN_ERR |
| 724 | "%s/2: cx8802 probe failed, err = %d\n", | 724 | "%s/2: cx8802 probe failed, err = %d\n", |
| 725 | dev->core->name, err); | 725 | dev->core->name, err); |
| 726 | } | 726 | } |
| 727 | 727 | mutex_unlock(&drv->core->lock); | |
| 728 | } | 728 | } |
| 729 | 729 | ||
| 730 | return i ? 0 : -ENODEV; | 730 | err = i ? 0 : -ENODEV; |
| 731 | out: | ||
| 732 | mutex_unlock(&cx8802_mutex); | ||
| 733 | return err; | ||
| 731 | } | 734 | } |
| 732 | 735 | ||
| 733 | int cx8802_unregister_driver(struct cx8802_driver *drv) | 736 | int cx8802_unregister_driver(struct cx8802_driver *drv) |
| @@ -741,6 +744,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
| 741 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", | 744 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", |
| 742 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | 745 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); |
| 743 | 746 | ||
| 747 | mutex_lock(&cx8802_mutex); | ||
| 748 | |||
| 744 | list_for_each_entry(dev, &cx8802_devlist, devlist) { | 749 | list_for_each_entry(dev, &cx8802_devlist, devlist) { |
| 745 | printk(KERN_INFO | 750 | printk(KERN_INFO |
| 746 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", | 751 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", |
| @@ -748,6 +753,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
| 748 | dev->pci->subsystem_device, dev->core->board.name, | 753 | dev->pci->subsystem_device, dev->core->board.name, |
| 749 | dev->core->boardnr); | 754 | dev->core->boardnr); |
| 750 | 755 | ||
| 756 | mutex_lock(&dev->core->lock); | ||
| 757 | |||
| 751 | list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) { | 758 | list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) { |
| 752 | /* only unregister the correct driver type */ | 759 | /* only unregister the correct driver type */ |
| 753 | if (d->type_id != drv->type_id) | 760 | if (d->type_id != drv->type_id) |
| @@ -755,17 +762,18 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
| 755 | 762 | ||
| 756 | err = d->remove(d); | 763 | err = d->remove(d); |
| 757 | if (err == 0) { | 764 | if (err == 0) { |
| 758 | mutex_lock(&drv->core->lock); | ||
| 759 | list_del(&d->drvlist); | 765 | list_del(&d->drvlist); |
| 760 | mutex_unlock(&drv->core->lock); | ||
| 761 | kfree(d); | 766 | kfree(d); |
| 762 | } else | 767 | } else |
| 763 | printk(KERN_ERR "%s/2: cx8802 driver remove " | 768 | printk(KERN_ERR "%s/2: cx8802 driver remove " |
| 764 | "failed (%d)\n", dev->core->name, err); | 769 | "failed (%d)\n", dev->core->name, err); |
| 765 | } | 770 | } |
| 766 | 771 | ||
| 772 | mutex_unlock(&dev->core->lock); | ||
| 767 | } | 773 | } |
| 768 | 774 | ||
| 775 | mutex_unlock(&cx8802_mutex); | ||
| 776 | |||
| 769 | return err; | 777 | return err; |
| 770 | } | 778 | } |
| 771 | 779 | ||
| @@ -803,7 +811,9 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, | |||
| 803 | goto fail_free; | 811 | goto fail_free; |
| 804 | 812 | ||
| 805 | INIT_LIST_HEAD(&dev->drvlist); | 813 | INIT_LIST_HEAD(&dev->drvlist); |
| 814 | mutex_lock(&cx8802_mutex); | ||
| 806 | list_add_tail(&dev->devlist,&cx8802_devlist); | 815 | list_add_tail(&dev->devlist,&cx8802_devlist); |
| 816 | mutex_unlock(&cx8802_mutex); | ||
| 807 | 817 | ||
| 808 | /* now autoload cx88-dvb or cx88-blackbird */ | 818 | /* now autoload cx88-dvb or cx88-blackbird */ |
| 809 | request_modules(dev); | 819 | request_modules(dev); |
| @@ -827,6 +837,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) | |||
| 827 | 837 | ||
| 828 | flush_request_modules(dev); | 838 | flush_request_modules(dev); |
| 829 | 839 | ||
| 840 | mutex_lock(&dev->core->lock); | ||
| 841 | |||
| 830 | if (!list_empty(&dev->drvlist)) { | 842 | if (!list_empty(&dev->drvlist)) { |
| 831 | struct cx8802_driver *drv, *tmp; | 843 | struct cx8802_driver *drv, *tmp; |
| 832 | int err; | 844 | int err; |
| @@ -838,9 +850,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) | |||
| 838 | list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) { | 850 | list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) { |
| 839 | err = drv->remove(drv); | 851 | err = drv->remove(drv); |
| 840 | if (err == 0) { | 852 | if (err == 0) { |
| 841 | mutex_lock(&drv->core->lock); | ||
| 842 | list_del(&drv->drvlist); | 853 | list_del(&drv->drvlist); |
| 843 | mutex_unlock(&drv->core->lock); | ||
| 844 | } else | 854 | } else |
| 845 | printk(KERN_ERR "%s/2: cx8802 driver remove " | 855 | printk(KERN_ERR "%s/2: cx8802 driver remove " |
| 846 | "failed (%d)\n", dev->core->name, err); | 856 | "failed (%d)\n", dev->core->name, err); |
| @@ -848,6 +858,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) | |||
| 848 | } | 858 | } |
| 849 | } | 859 | } |
| 850 | 860 | ||
| 861 | mutex_unlock(&dev->core->lock); | ||
| 862 | |||
| 851 | /* Destroy any 8802 reference. */ | 863 | /* Destroy any 8802 reference. */ |
| 852 | dev->core->dvbdev = NULL; | 864 | dev->core->dvbdev = NULL; |
| 853 | 865 | ||
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 287a41ee1c4f..cef4f282e5aa 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
| @@ -824,7 +824,7 @@ static int video_open(struct file *file) | |||
| 824 | call_all(core, tuner, s_radio); | 824 | call_all(core, tuner, s_radio); |
| 825 | } | 825 | } |
| 826 | 826 | ||
| 827 | atomic_inc(&core->users); | 827 | core->users++; |
| 828 | mutex_unlock(&core->lock); | 828 | mutex_unlock(&core->lock); |
| 829 | 829 | ||
| 830 | return 0; | 830 | return 0; |
| @@ -922,7 +922,8 @@ static int video_release(struct file *file) | |||
| 922 | file->private_data = NULL; | 922 | file->private_data = NULL; |
| 923 | kfree(fh); | 923 | kfree(fh); |
| 924 | 924 | ||
| 925 | if(atomic_dec_and_test(&dev->core->users)) | 925 | dev->core->users--; |
| 926 | if (!dev->core->users) | ||
| 926 | call_all(dev->core, core, s_power, 0); | 927 | call_all(dev->core, core, s_power, 0); |
| 927 | mutex_unlock(&dev->core->lock); | 928 | mutex_unlock(&dev->core->lock); |
| 928 | 929 | ||
| @@ -1832,7 +1833,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
| 1832 | dev->core = core; | 1833 | dev->core = core; |
| 1833 | 1834 | ||
| 1834 | /* print pci info */ | 1835 | /* print pci info */ |
| 1835 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); | 1836 | dev->pci_rev = pci_dev->revision; |
| 1836 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); | 1837 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); |
| 1837 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " | 1838 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " |
| 1838 | "latency: %d, mmio: 0x%llx\n", core->name, | 1839 | "latency: %d, mmio: 0x%llx\n", core->name, |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 9b3742a7746c..a399a8b086ba 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
| @@ -389,8 +389,8 @@ struct cx88_core { | |||
| 389 | struct mutex lock; | 389 | struct mutex lock; |
| 390 | /* various v4l controls */ | 390 | /* various v4l controls */ |
| 391 | u32 freq; | 391 | u32 freq; |
| 392 | atomic_t users; | 392 | int users; |
| 393 | atomic_t mpeg_users; | 393 | int mpeg_users; |
| 394 | 394 | ||
| 395 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 395 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ |
| 396 | struct cx8802_dev *dvbdev; | 396 | struct cx8802_dev *dvbdev; |
| @@ -505,6 +505,8 @@ struct cx8802_driver { | |||
| 505 | int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); | 505 | int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); |
| 506 | int (*resume)(struct pci_dev *pci_dev); | 506 | int (*resume)(struct pci_dev *pci_dev); |
| 507 | 507 | ||
| 508 | /* Callers to the following functions must hold core->lock */ | ||
| 509 | |||
| 508 | /* MPEG 8802 -> mini driver - Driver probe and configuration */ | 510 | /* MPEG 8802 -> mini driver - Driver probe and configuration */ |
| 509 | int (*probe)(struct cx8802_driver *drv); | 511 | int (*probe)(struct cx8802_driver *drv); |
| 510 | int (*remove)(struct cx8802_driver *drv); | 512 | int (*remove)(struct cx8802_driver *drv); |
| @@ -561,8 +563,9 @@ struct cx8802_dev { | |||
| 561 | /* for switching modulation types */ | 563 | /* for switching modulation types */ |
| 562 | unsigned char ts_gen_cntrl; | 564 | unsigned char ts_gen_cntrl; |
| 563 | 565 | ||
| 564 | /* List of attached drivers */ | 566 | /* List of attached drivers; must hold core->lock to access */ |
| 565 | struct list_head drvlist; | 567 | struct list_head drvlist; |
| 568 | |||
| 566 | struct work_struct request_module_wk; | 569 | struct work_struct request_module_wk; |
| 567 | }; | 570 | }; |
| 568 | 571 | ||
| @@ -685,6 +688,8 @@ int cx88_audio_thread(void *data); | |||
| 685 | 688 | ||
| 686 | int cx8802_register_driver(struct cx8802_driver *drv); | 689 | int cx8802_register_driver(struct cx8802_driver *drv); |
| 687 | int cx8802_unregister_driver(struct cx8802_driver *drv); | 690 | int cx8802_unregister_driver(struct cx8802_driver *drv); |
| 691 | |||
| 692 | /* Caller must hold core->lock */ | ||
| 688 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); | 693 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); |
| 689 | 694 | ||
| 690 | /* ----------------------------------------------------------- */ | 695 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 985100ea17a4..3cb78f26df90 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig | |||
| @@ -38,6 +38,8 @@ config VIDEO_EM28XX_DVB | |||
| 38 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 38 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
| 39 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | 39 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE |
| 40 | select DVB_S921 if !DVB_FE_CUSTOMISE | 40 | select DVB_S921 if !DVB_FE_CUSTOMISE |
| 41 | select DVB_DRXD if !DVB_FE_CUSTOMISE | ||
| 42 | select DVB_CXD2820R if !DVB_FE_CUSTOMISE | ||
| 41 | select VIDEOBUF_DVB | 43 | select VIDEOBUF_DVB |
| 42 | ---help--- | 44 | ---help--- |
| 43 | This adds support for DVB cards based on the | 45 | This adds support for DVB cards based on the |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 69fcea82d01c..4e37375decf5 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
| @@ -100,6 +100,13 @@ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { | |||
| 100 | { -1, -1, -1, -1}, | 100 | { -1, -1, -1, -1}, |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | /* Board Hauppauge WinTV HVR 900 (R2) digital */ | ||
| 104 | static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = { | ||
| 105 | {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, | ||
| 106 | {EM2880_R04_GPO, 0x0c, 0x0f, 10}, | ||
| 107 | { -1, -1, -1, -1}, | ||
| 108 | }; | ||
| 109 | |||
| 103 | /* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ | 110 | /* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ |
| 104 | static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { | 111 | static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { |
| 105 | {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, | 112 | {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, |
| @@ -282,6 +289,16 @@ static struct em28xx_reg_seq leadership_reset[] = { | |||
| 282 | { -1, -1, -1, -1}, | 289 | { -1, -1, -1, -1}, |
| 283 | }; | 290 | }; |
| 284 | 291 | ||
| 292 | /* 2013:024f PCTV Systems nanoStick T2 290e | ||
| 293 | * GPIO_6 - demod reset | ||
| 294 | * GPIO_7 - LED | ||
| 295 | */ | ||
| 296 | static struct em28xx_reg_seq pctv_290e[] = { | ||
| 297 | {EM2874_R80_GPIO, 0x00, 0xff, 80}, | ||
| 298 | {EM2874_R80_GPIO, 0x40, 0xff, 80}, /* GPIO_6 = 1 */ | ||
| 299 | {EM2874_R80_GPIO, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */ | ||
| 300 | {-1, -1, -1, -1}, | ||
| 301 | }; | ||
| 285 | 302 | ||
| 286 | /* | 303 | /* |
| 287 | * Board definitions | 304 | * Board definitions |
| @@ -859,6 +876,8 @@ struct em28xx_board em28xx_boards[] = { | |||
| 859 | .tuner_type = TUNER_XC2028, | 876 | .tuner_type = TUNER_XC2028, |
| 860 | .tuner_gpio = default_tuner_gpio, | 877 | .tuner_gpio = default_tuner_gpio, |
| 861 | .mts_firmware = 1, | 878 | .mts_firmware = 1, |
| 879 | .has_dvb = 1, | ||
| 880 | .dvb_gpio = hauppauge_wintv_hvr_900R2_digital, | ||
| 862 | .ir_codes = RC_MAP_HAUPPAUGE, | 881 | .ir_codes = RC_MAP_HAUPPAUGE, |
| 863 | .decoder = EM28XX_TVP5150, | 882 | .decoder = EM28XX_TVP5150, |
| 864 | .input = { { | 883 | .input = { { |
| @@ -1448,12 +1467,14 @@ struct em28xx_board em28xx_boards[] = { | |||
| 1448 | .gpio = pinnacle_hybrid_pro_analog, | 1467 | .gpio = pinnacle_hybrid_pro_analog, |
| 1449 | } }, | 1468 | } }, |
| 1450 | }, | 1469 | }, |
| 1451 | [EM2882_BOARD_PINNACLE_HYBRID_PRO] = { | 1470 | [EM2882_BOARD_PINNACLE_HYBRID_PRO_330E] = { |
| 1452 | .name = "Pinnacle Hybrid Pro (2)", | 1471 | .name = "Pinnacle Hybrid Pro (330e)", |
| 1453 | .valid = EM28XX_BOARD_NOT_VALIDATED, | ||
| 1454 | .tuner_type = TUNER_XC2028, | 1472 | .tuner_type = TUNER_XC2028, |
| 1455 | .tuner_gpio = default_tuner_gpio, | 1473 | .tuner_gpio = default_tuner_gpio, |
| 1456 | .mts_firmware = 1, | 1474 | .mts_firmware = 1, |
| 1475 | .has_dvb = 1, | ||
| 1476 | .dvb_gpio = hauppauge_wintv_hvr_900R2_digital, | ||
| 1477 | .ir_codes = RC_MAP_PINNACLE_PCTV_HD, | ||
| 1457 | .decoder = EM28XX_TVP5150, | 1478 | .decoder = EM28XX_TVP5150, |
| 1458 | .input = { { | 1479 | .input = { { |
| 1459 | .type = EM28XX_VMUX_TELEVISION, | 1480 | .type = EM28XX_VMUX_TELEVISION, |
| @@ -1749,6 +1770,17 @@ struct em28xx_board em28xx_boards[] = { | |||
| 1749 | .dvb_gpio = kworld_a340_digital, | 1770 | .dvb_gpio = kworld_a340_digital, |
| 1750 | .tuner_gpio = default_tuner_gpio, | 1771 | .tuner_gpio = default_tuner_gpio, |
| 1751 | }, | 1772 | }, |
| 1773 | /* 2013:024f PCTV Systems nanoStick T2 290e. | ||
| 1774 | * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */ | ||
| 1775 | [EM28174_BOARD_PCTV_290E] = { | ||
| 1776 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | | ||
| 1777 | EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ, | ||
| 1778 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | ||
| 1779 | .name = "PCTV Systems nanoStick T2 290e", | ||
| 1780 | .tuner_type = TUNER_ABSENT, | ||
| 1781 | .tuner_gpio = pctv_290e, | ||
| 1782 | .has_dvb = 1, | ||
| 1783 | }, | ||
| 1752 | }; | 1784 | }; |
| 1753 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); | 1785 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); |
| 1754 | 1786 | ||
| @@ -1863,7 +1895,7 @@ struct usb_device_id em28xx_id_table[] = { | |||
| 1863 | { USB_DEVICE(0x2304, 0x021a), | 1895 | { USB_DEVICE(0x2304, 0x021a), |
| 1864 | .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, | 1896 | .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, |
| 1865 | { USB_DEVICE(0x2304, 0x0226), | 1897 | { USB_DEVICE(0x2304, 0x0226), |
| 1866 | .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO }, | 1898 | .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO_330E }, |
| 1867 | { USB_DEVICE(0x2304, 0x0227), | 1899 | { USB_DEVICE(0x2304, 0x0227), |
| 1868 | .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, | 1900 | .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, |
| 1869 | { USB_DEVICE(0x0413, 0x6023), | 1901 | { USB_DEVICE(0x0413, 0x6023), |
| @@ -1876,6 +1908,8 @@ struct usb_device_id em28xx_id_table[] = { | |||
| 1876 | .driver_info = EM2860_BOARD_GADMEI_UTV330 }, | 1908 | .driver_info = EM2860_BOARD_GADMEI_UTV330 }, |
| 1877 | { USB_DEVICE(0x1b80, 0xa340), | 1909 | { USB_DEVICE(0x1b80, 0xa340), |
| 1878 | .driver_info = EM2870_BOARD_KWORLD_A340 }, | 1910 | .driver_info = EM2870_BOARD_KWORLD_A340 }, |
| 1911 | { USB_DEVICE(0x2013, 0x024f), | ||
| 1912 | .driver_info = EM28174_BOARD_PCTV_290E }, | ||
| 1879 | { }, | 1913 | { }, |
| 1880 | }; | 1914 | }; |
| 1881 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); | 1915 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); |
| @@ -2229,7 +2263,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
| 2229 | ctl->demod = XC3028_FE_ZARLINK456; | 2263 | ctl->demod = XC3028_FE_ZARLINK456; |
| 2230 | break; | 2264 | break; |
| 2231 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: | 2265 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: |
| 2232 | /* djh - Not sure which demod we need here */ | 2266 | case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: |
| 2233 | ctl->demod = XC3028_FE_DEFAULT; | 2267 | ctl->demod = XC3028_FE_DEFAULT; |
| 2234 | break; | 2268 | break; |
| 2235 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: | 2269 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: |
| @@ -2799,6 +2833,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 2799 | dev->reg_gpio_num = EM2874_R80_GPIO; | 2833 | dev->reg_gpio_num = EM2874_R80_GPIO; |
| 2800 | dev->wait_after_write = 0; | 2834 | dev->wait_after_write = 0; |
| 2801 | break; | 2835 | break; |
| 2836 | case CHIP_ID_EM28174: | ||
| 2837 | em28xx_info("chip ID is em28174\n"); | ||
| 2838 | dev->reg_gpio_num = EM2874_R80_GPIO; | ||
| 2839 | dev->wait_after_write = 0; | ||
| 2840 | break; | ||
| 2802 | case CHIP_ID_EM2883: | 2841 | case CHIP_ID_EM2883: |
| 2803 | em28xx_info("chip ID is em2882/em2883\n"); | 2842 | em28xx_info("chip ID is em2882/em2883\n"); |
| 2804 | dev->wait_after_write = 0; | 2843 | dev->wait_after_write = 0; |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 44c63cbd6dda..e33f145d867a 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
| @@ -489,7 +489,8 @@ int em28xx_audio_setup(struct em28xx *dev) | |||
| 489 | int vid1, vid2, feat, cfg; | 489 | int vid1, vid2, feat, cfg; |
| 490 | u32 vid; | 490 | u32 vid; |
| 491 | 491 | ||
| 492 | if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874) { | 492 | if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874 |
| 493 | || dev->chip_id == CHIP_ID_EM28174) { | ||
| 493 | /* Digital only device - don't load any alsa module */ | 494 | /* Digital only device - don't load any alsa module */ |
| 494 | dev->audio_mode.has_audio = 0; | 495 | dev->audio_mode.has_audio = 0; |
| 495 | dev->has_audio_class = 0; | 496 | dev->has_audio_class = 0; |
| @@ -614,7 +615,7 @@ int em28xx_capture_start(struct em28xx *dev, int start) | |||
| 614 | { | 615 | { |
| 615 | int rc; | 616 | int rc; |
| 616 | 617 | ||
| 617 | if (dev->chip_id == CHIP_ID_EM2874) { | 618 | if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) { |
| 618 | /* The Transport Stream Enable Register moved in em2874 */ | 619 | /* The Transport Stream Enable Register moved in em2874 */ |
| 619 | if (!start) { | 620 | if (!start) { |
| 620 | rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, | 621 | rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, |
| @@ -1111,6 +1112,10 @@ int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev) | |||
| 1111 | /* FIXME - for now assume 564 like it was before, but the | 1112 | /* FIXME - for now assume 564 like it was before, but the |
| 1112 | em2874 code should be added to return the proper value... */ | 1113 | em2874 code should be added to return the proper value... */ |
| 1113 | packet_size = 564; | 1114 | packet_size = 564; |
| 1115 | } else if (dev->chip_id == CHIP_ID_EM28174) { | ||
| 1116 | /* FIXME same as em2874. 564 was enough for 22 Mbit DVB-T | ||
| 1117 | but too much for 44 Mbit DVB-C. */ | ||
| 1118 | packet_size = 752; | ||
| 1114 | } else { | 1119 | } else { |
| 1115 | /* TS max packet size stored in bits 1-0 of R01 */ | 1120 | /* TS max packet size stored in bits 1-0 of R01 */ |
| 1116 | chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); | 1121 | chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index c7c04bf712aa..7904ca4b6913 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | #include "tda1002x.h" | 38 | #include "tda1002x.h" |
| 39 | #include "tda18271.h" | 39 | #include "tda18271.h" |
| 40 | #include "s921.h" | 40 | #include "s921.h" |
| 41 | #include "drxd.h" | ||
| 42 | #include "cxd2820r.h" | ||
| 41 | 43 | ||
| 42 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); | 44 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); |
| 43 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 45 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
| @@ -58,7 +60,7 @@ if (debug >= level) \ | |||
| 58 | #define EM28XX_DVB_MAX_PACKETS 64 | 60 | #define EM28XX_DVB_MAX_PACKETS 64 |
| 59 | 61 | ||
| 60 | struct em28xx_dvb { | 62 | struct em28xx_dvb { |
| 61 | struct dvb_frontend *frontend; | 63 | struct dvb_frontend *fe[2]; |
| 62 | 64 | ||
| 63 | /* feed count management */ | 65 | /* feed count management */ |
| 64 | struct mutex lock; | 66 | struct mutex lock; |
| @@ -285,12 +287,13 @@ static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { | |||
| 285 | .if2 = 45600, | 287 | .if2 = 45600, |
| 286 | }; | 288 | }; |
| 287 | 289 | ||
| 288 | #ifdef EM28XX_DRX397XD_SUPPORT | 290 | static struct drxd_config em28xx_drxd = { |
| 289 | /* [TODO] djh - not sure yet what the device config needs to contain */ | 291 | .index = 0, .demod_address = 0x70, .demod_revision = 0xa2, |
| 290 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { | 292 | .demoda_address = 0x00, .pll_address = 0x00, |
| 291 | .demod_address = (0xe0 >> 1), | 293 | .pll_type = DRXD_PLL_NONE, .clock = 12000, .insert_rs_byte = 1, |
| 294 | .pll_set = NULL, .osc_deviation = NULL, .IF = 42800000, | ||
| 295 | .disable_i2c_gate_ctrl = 1, | ||
| 292 | }; | 296 | }; |
| 293 | #endif | ||
| 294 | 297 | ||
| 295 | static int mt352_terratec_xs_init(struct dvb_frontend *fe) | 298 | static int mt352_terratec_xs_init(struct dvb_frontend *fe) |
| 296 | { | 299 | { |
| @@ -332,6 +335,26 @@ static struct tda10023_config em28xx_tda10023_config = { | |||
| 332 | .invert = 1, | 335 | .invert = 1, |
| 333 | }; | 336 | }; |
| 334 | 337 | ||
| 338 | static struct cxd2820r_config em28xx_cxd2820r_config = { | ||
| 339 | .i2c_address = (0xd8 >> 1), | ||
| 340 | .ts_mode = CXD2820R_TS_SERIAL, | ||
| 341 | .if_dvbt_6 = 3300, | ||
| 342 | .if_dvbt_7 = 3500, | ||
| 343 | .if_dvbt_8 = 4000, | ||
| 344 | .if_dvbt2_6 = 3300, | ||
| 345 | .if_dvbt2_7 = 3500, | ||
| 346 | .if_dvbt2_8 = 4000, | ||
| 347 | .if_dvbc = 5000, | ||
| 348 | |||
| 349 | /* enable LNA for DVB-T2 and DVB-C */ | ||
| 350 | .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, | ||
| 351 | .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, | ||
| 352 | }; | ||
| 353 | |||
| 354 | static struct tda18271_config em28xx_cxd2820r_tda18271_config = { | ||
| 355 | .output_opt = TDA18271_OUTPUT_LT_OFF, | ||
| 356 | }; | ||
| 357 | |||
| 335 | /* ------------------------------------------------------------------ */ | 358 | /* ------------------------------------------------------------------ */ |
| 336 | 359 | ||
| 337 | static int attach_xc3028(u8 addr, struct em28xx *dev) | 360 | static int attach_xc3028(u8 addr, struct em28xx *dev) |
| @@ -343,17 +366,17 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
| 343 | cfg.i2c_adap = &dev->i2c_adap; | 366 | cfg.i2c_adap = &dev->i2c_adap; |
| 344 | cfg.i2c_addr = addr; | 367 | cfg.i2c_addr = addr; |
| 345 | 368 | ||
| 346 | if (!dev->dvb->frontend) { | 369 | if (!dev->dvb->fe[0]) { |
| 347 | em28xx_errdev("/2: dvb frontend not attached. " | 370 | em28xx_errdev("/2: dvb frontend not attached. " |
| 348 | "Can't attach xc3028\n"); | 371 | "Can't attach xc3028\n"); |
| 349 | return -EINVAL; | 372 | return -EINVAL; |
| 350 | } | 373 | } |
| 351 | 374 | ||
| 352 | fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); | 375 | fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); |
| 353 | if (!fe) { | 376 | if (!fe) { |
| 354 | em28xx_errdev("/2: xc3028 attach failed\n"); | 377 | em28xx_errdev("/2: xc3028 attach failed\n"); |
| 355 | dvb_frontend_detach(dev->dvb->frontend); | 378 | dvb_frontend_detach(dev->dvb->fe[0]); |
| 356 | dev->dvb->frontend = NULL; | 379 | dev->dvb->fe[0] = NULL; |
| 357 | return -EINVAL; | 380 | return -EINVAL; |
| 358 | } | 381 | } |
| 359 | 382 | ||
| @@ -383,16 +406,28 @@ static int register_dvb(struct em28xx_dvb *dvb, | |||
| 383 | } | 406 | } |
| 384 | 407 | ||
| 385 | /* Ensure all frontends negotiate bus access */ | 408 | /* Ensure all frontends negotiate bus access */ |
| 386 | dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; | 409 | dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; |
| 410 | if (dvb->fe[1]) | ||
| 411 | dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; | ||
| 387 | 412 | ||
| 388 | dvb->adapter.priv = dev; | 413 | dvb->adapter.priv = dev; |
| 389 | 414 | ||
| 390 | /* register frontend */ | 415 | /* register frontend */ |
| 391 | result = dvb_register_frontend(&dvb->adapter, dvb->frontend); | 416 | result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]); |
| 392 | if (result < 0) { | 417 | if (result < 0) { |
| 393 | printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", | 418 | printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", |
| 394 | dev->name, result); | 419 | dev->name, result); |
| 395 | goto fail_frontend; | 420 | goto fail_frontend0; |
| 421 | } | ||
| 422 | |||
| 423 | /* register 2nd frontend */ | ||
| 424 | if (dvb->fe[1]) { | ||
| 425 | result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]); | ||
| 426 | if (result < 0) { | ||
| 427 | printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n", | ||
| 428 | dev->name, result); | ||
| 429 | goto fail_frontend1; | ||
| 430 | } | ||
| 396 | } | 431 | } |
| 397 | 432 | ||
| 398 | /* register demux stuff */ | 433 | /* register demux stuff */ |
| @@ -458,9 +493,14 @@ fail_fe_hw: | |||
| 458 | fail_dmxdev: | 493 | fail_dmxdev: |
| 459 | dvb_dmx_release(&dvb->demux); | 494 | dvb_dmx_release(&dvb->demux); |
| 460 | fail_dmx: | 495 | fail_dmx: |
| 461 | dvb_unregister_frontend(dvb->frontend); | 496 | if (dvb->fe[1]) |
| 462 | fail_frontend: | 497 | dvb_unregister_frontend(dvb->fe[1]); |
| 463 | dvb_frontend_detach(dvb->frontend); | 498 | dvb_unregister_frontend(dvb->fe[0]); |
| 499 | fail_frontend1: | ||
| 500 | if (dvb->fe[1]) | ||
| 501 | dvb_frontend_detach(dvb->fe[1]); | ||
| 502 | fail_frontend0: | ||
| 503 | dvb_frontend_detach(dvb->fe[0]); | ||
| 464 | dvb_unregister_adapter(&dvb->adapter); | 504 | dvb_unregister_adapter(&dvb->adapter); |
| 465 | fail_adapter: | 505 | fail_adapter: |
| 466 | return result; | 506 | return result; |
| @@ -473,12 +513,15 @@ static void unregister_dvb(struct em28xx_dvb *dvb) | |||
| 473 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); | 513 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); |
| 474 | dvb_dmxdev_release(&dvb->dmxdev); | 514 | dvb_dmxdev_release(&dvb->dmxdev); |
| 475 | dvb_dmx_release(&dvb->demux); | 515 | dvb_dmx_release(&dvb->demux); |
| 476 | dvb_unregister_frontend(dvb->frontend); | 516 | if (dvb->fe[1]) |
| 477 | dvb_frontend_detach(dvb->frontend); | 517 | dvb_unregister_frontend(dvb->fe[1]); |
| 518 | dvb_unregister_frontend(dvb->fe[0]); | ||
| 519 | if (dvb->fe[1]) | ||
| 520 | dvb_frontend_detach(dvb->fe[1]); | ||
| 521 | dvb_frontend_detach(dvb->fe[0]); | ||
| 478 | dvb_unregister_adapter(&dvb->adapter); | 522 | dvb_unregister_adapter(&dvb->adapter); |
| 479 | } | 523 | } |
| 480 | 524 | ||
| 481 | |||
| 482 | static int dvb_init(struct em28xx *dev) | 525 | static int dvb_init(struct em28xx *dev) |
| 483 | { | 526 | { |
| 484 | int result = 0; | 527 | int result = 0; |
| @@ -497,16 +540,17 @@ static int dvb_init(struct em28xx *dev) | |||
| 497 | return -ENOMEM; | 540 | return -ENOMEM; |
| 498 | } | 541 | } |
| 499 | dev->dvb = dvb; | 542 | dev->dvb = dvb; |
| 543 | dvb->fe[0] = dvb->fe[1] = NULL; | ||
| 500 | 544 | ||
| 501 | mutex_lock(&dev->lock); | 545 | mutex_lock(&dev->lock); |
| 502 | em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); | 546 | em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); |
| 503 | /* init frontend */ | 547 | /* init frontend */ |
| 504 | switch (dev->model) { | 548 | switch (dev->model) { |
| 505 | case EM2874_LEADERSHIP_ISDBT: | 549 | case EM2874_LEADERSHIP_ISDBT: |
| 506 | dvb->frontend = dvb_attach(s921_attach, | 550 | dvb->fe[0] = dvb_attach(s921_attach, |
| 507 | &sharp_isdbt, &dev->i2c_adap); | 551 | &sharp_isdbt, &dev->i2c_adap); |
| 508 | 552 | ||
| 509 | if (!dvb->frontend) { | 553 | if (!dvb->fe[0]) { |
| 510 | result = -EINVAL; | 554 | result = -EINVAL; |
| 511 | goto out_free; | 555 | goto out_free; |
| 512 | } | 556 | } |
| @@ -516,7 +560,7 @@ static int dvb_init(struct em28xx *dev) | |||
| 516 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: | 560 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: |
| 517 | case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: | 561 | case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: |
| 518 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: | 562 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: |
| 519 | dvb->frontend = dvb_attach(lgdt330x_attach, | 563 | dvb->fe[0] = dvb_attach(lgdt330x_attach, |
| 520 | &em2880_lgdt3303_dev, | 564 | &em2880_lgdt3303_dev, |
| 521 | &dev->i2c_adap); | 565 | &dev->i2c_adap); |
| 522 | if (attach_xc3028(0x61, dev) < 0) { | 566 | if (attach_xc3028(0x61, dev) < 0) { |
| @@ -525,7 +569,7 @@ static int dvb_init(struct em28xx *dev) | |||
| 525 | } | 569 | } |
| 526 | break; | 570 | break; |
| 527 | case EM2880_BOARD_KWORLD_DVB_310U: | 571 | case EM2880_BOARD_KWORLD_DVB_310U: |
| 528 | dvb->frontend = dvb_attach(zl10353_attach, | 572 | dvb->fe[0] = dvb_attach(zl10353_attach, |
| 529 | &em28xx_zl10353_with_xc3028, | 573 | &em28xx_zl10353_with_xc3028, |
| 530 | &dev->i2c_adap); | 574 | &dev->i2c_adap); |
| 531 | if (attach_xc3028(0x61, dev) < 0) { | 575 | if (attach_xc3028(0x61, dev) < 0) { |
| @@ -536,7 +580,7 @@ static int dvb_init(struct em28xx *dev) | |||
| 536 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 580 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
| 537 | case EM2882_BOARD_TERRATEC_HYBRID_XS: | 581 | case EM2882_BOARD_TERRATEC_HYBRID_XS: |
| 538 | case EM2880_BOARD_EMPIRE_DUAL_TV: | 582 | case EM2880_BOARD_EMPIRE_DUAL_TV: |
| 539 | dvb->frontend = dvb_attach(zl10353_attach, | 583 | dvb->fe[0] = dvb_attach(zl10353_attach, |
| 540 | &em28xx_zl10353_xc3028_no_i2c_gate, | 584 | &em28xx_zl10353_xc3028_no_i2c_gate, |
| 541 | &dev->i2c_adap); | 585 | &dev->i2c_adap); |
| 542 | if (attach_xc3028(0x61, dev) < 0) { | 586 | if (attach_xc3028(0x61, dev) < 0) { |
| @@ -549,13 +593,13 @@ static int dvb_init(struct em28xx *dev) | |||
| 549 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: | 593 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: |
| 550 | case EM2882_BOARD_DIKOM_DK300: | 594 | case EM2882_BOARD_DIKOM_DK300: |
| 551 | case EM2882_BOARD_KWORLD_VS_DVBT: | 595 | case EM2882_BOARD_KWORLD_VS_DVBT: |
| 552 | dvb->frontend = dvb_attach(zl10353_attach, | 596 | dvb->fe[0] = dvb_attach(zl10353_attach, |
| 553 | &em28xx_zl10353_xc3028_no_i2c_gate, | 597 | &em28xx_zl10353_xc3028_no_i2c_gate, |
| 554 | &dev->i2c_adap); | 598 | &dev->i2c_adap); |
| 555 | if (dvb->frontend == NULL) { | 599 | if (dvb->fe[0] == NULL) { |
| 556 | /* This board could have either a zl10353 or a mt352. | 600 | /* This board could have either a zl10353 or a mt352. |
| 557 | If the chip id isn't for zl10353, try mt352 */ | 601 | If the chip id isn't for zl10353, try mt352 */ |
| 558 | dvb->frontend = dvb_attach(mt352_attach, | 602 | dvb->fe[0] = dvb_attach(mt352_attach, |
| 559 | &terratec_xs_mt352_cfg, | 603 | &terratec_xs_mt352_cfg, |
| 560 | &dev->i2c_adap); | 604 | &dev->i2c_adap); |
| 561 | } | 605 | } |
| @@ -567,7 +611,7 @@ static int dvb_init(struct em28xx *dev) | |||
| 567 | break; | 611 | break; |
| 568 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 612 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
| 569 | case EM2882_BOARD_EVGA_INDTUBE: | 613 | case EM2882_BOARD_EVGA_INDTUBE: |
| 570 | dvb->frontend = dvb_attach(s5h1409_attach, | 614 | dvb->fe[0] = dvb_attach(s5h1409_attach, |
| 571 | &em28xx_s5h1409_with_xc3028, | 615 | &em28xx_s5h1409_with_xc3028, |
| 572 | &dev->i2c_adap); | 616 | &dev->i2c_adap); |
| 573 | if (attach_xc3028(0x61, dev) < 0) { | 617 | if (attach_xc3028(0x61, dev) < 0) { |
| @@ -576,11 +620,11 @@ static int dvb_init(struct em28xx *dev) | |||
| 576 | } | 620 | } |
| 577 | break; | 621 | break; |
| 578 | case EM2882_BOARD_KWORLD_ATSC_315U: | 622 | case EM2882_BOARD_KWORLD_ATSC_315U: |
| 579 | dvb->frontend = dvb_attach(lgdt330x_attach, | 623 | dvb->fe[0] = dvb_attach(lgdt330x_attach, |
| 580 | &em2880_lgdt3303_dev, | 624 | &em2880_lgdt3303_dev, |
| 581 | &dev->i2c_adap); | 625 | &dev->i2c_adap); |
| 582 | if (dvb->frontend != NULL) { | 626 | if (dvb->fe[0] != NULL) { |
| 583 | if (!dvb_attach(simple_tuner_attach, dvb->frontend, | 627 | if (!dvb_attach(simple_tuner_attach, dvb->fe[0], |
| 584 | &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { | 628 | &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { |
| 585 | result = -EINVAL; | 629 | result = -EINVAL; |
| 586 | goto out_free; | 630 | goto out_free; |
| @@ -588,25 +632,21 @@ static int dvb_init(struct em28xx *dev) | |||
| 588 | } | 632 | } |
| 589 | break; | 633 | break; |
| 590 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: | 634 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: |
| 591 | #ifdef EM28XX_DRX397XD_SUPPORT | 635 | case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: |
| 592 | /* We don't have the config structure properly populated, so | 636 | dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, |
| 593 | this is commented out for now */ | 637 | &dev->i2c_adap, &dev->udev->dev); |
| 594 | dvb->frontend = dvb_attach(drx397xD_attach, | ||
| 595 | &em28xx_drx397xD_with_xc3028, | ||
| 596 | &dev->i2c_adap); | ||
| 597 | if (attach_xc3028(0x61, dev) < 0) { | 638 | if (attach_xc3028(0x61, dev) < 0) { |
| 598 | result = -EINVAL; | 639 | result = -EINVAL; |
| 599 | goto out_free; | 640 | goto out_free; |
| 600 | } | 641 | } |
| 601 | break; | 642 | break; |
| 602 | #endif | ||
| 603 | case EM2870_BOARD_REDDO_DVB_C_USB_BOX: | 643 | case EM2870_BOARD_REDDO_DVB_C_USB_BOX: |
| 604 | /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ | 644 | /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ |
| 605 | dvb->frontend = dvb_attach(tda10023_attach, | 645 | dvb->fe[0] = dvb_attach(tda10023_attach, |
| 606 | &em28xx_tda10023_config, | 646 | &em28xx_tda10023_config, |
| 607 | &dev->i2c_adap, 0x48); | 647 | &dev->i2c_adap, 0x48); |
| 608 | if (dvb->frontend) { | 648 | if (dvb->fe[0]) { |
| 609 | if (!dvb_attach(simple_tuner_attach, dvb->frontend, | 649 | if (!dvb_attach(simple_tuner_attach, dvb->fe[0], |
| 610 | &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { | 650 | &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { |
| 611 | result = -EINVAL; | 651 | result = -EINVAL; |
| 612 | goto out_free; | 652 | goto out_free; |
| @@ -614,25 +654,53 @@ static int dvb_init(struct em28xx *dev) | |||
| 614 | } | 654 | } |
| 615 | break; | 655 | break; |
| 616 | case EM2870_BOARD_KWORLD_A340: | 656 | case EM2870_BOARD_KWORLD_A340: |
| 617 | dvb->frontend = dvb_attach(lgdt3305_attach, | 657 | dvb->fe[0] = dvb_attach(lgdt3305_attach, |
| 618 | &em2870_lgdt3304_dev, | 658 | &em2870_lgdt3304_dev, |
| 619 | &dev->i2c_adap); | 659 | &dev->i2c_adap); |
| 620 | if (dvb->frontend != NULL) | 660 | if (dvb->fe[0] != NULL) |
| 621 | dvb_attach(tda18271_attach, dvb->frontend, 0x60, | 661 | dvb_attach(tda18271_attach, dvb->fe[0], 0x60, |
| 622 | &dev->i2c_adap, &kworld_a340_config); | 662 | &dev->i2c_adap, &kworld_a340_config); |
| 623 | break; | 663 | break; |
| 664 | case EM28174_BOARD_PCTV_290E: | ||
| 665 | /* MFE | ||
| 666 | * FE 0 = DVB-T/T2 + FE 1 = DVB-C, both sharing same tuner. */ | ||
| 667 | /* FE 0 */ | ||
| 668 | dvb->fe[0] = dvb_attach(cxd2820r_attach, | ||
| 669 | &em28xx_cxd2820r_config, &dev->i2c_adap, NULL); | ||
| 670 | if (dvb->fe[0]) { | ||
| 671 | struct i2c_adapter *i2c_tuner; | ||
| 672 | i2c_tuner = cxd2820r_get_tuner_i2c_adapter(dvb->fe[0]); | ||
| 673 | /* FE 0 attach tuner */ | ||
| 674 | if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, | ||
| 675 | i2c_tuner, &em28xx_cxd2820r_tda18271_config)) { | ||
| 676 | dvb_frontend_detach(dvb->fe[0]); | ||
| 677 | result = -EINVAL; | ||
| 678 | goto out_free; | ||
| 679 | } | ||
| 680 | /* FE 1. This dvb_attach() cannot fail. */ | ||
| 681 | dvb->fe[1] = dvb_attach(cxd2820r_attach, NULL, NULL, | ||
| 682 | dvb->fe[0]); | ||
| 683 | dvb->fe[1]->id = 1; | ||
| 684 | /* FE 1 attach tuner */ | ||
| 685 | if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60, | ||
| 686 | i2c_tuner, &em28xx_cxd2820r_tda18271_config)) { | ||
| 687 | dvb_frontend_detach(dvb->fe[1]); | ||
| 688 | /* leave FE 0 still active */ | ||
| 689 | } | ||
| 690 | } | ||
| 691 | break; | ||
| 624 | default: | 692 | default: |
| 625 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" | 693 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" |
| 626 | " isn't supported yet\n"); | 694 | " isn't supported yet\n"); |
| 627 | break; | 695 | break; |
| 628 | } | 696 | } |
| 629 | if (NULL == dvb->frontend) { | 697 | if (NULL == dvb->fe[0]) { |
| 630 | em28xx_errdev("/2: frontend initialization failed\n"); | 698 | em28xx_errdev("/2: frontend initialization failed\n"); |
| 631 | result = -EINVAL; | 699 | result = -EINVAL; |
| 632 | goto out_free; | 700 | goto out_free; |
| 633 | } | 701 | } |
| 634 | /* define general-purpose callback pointer */ | 702 | /* define general-purpose callback pointer */ |
| 635 | dvb->frontend->callback = em28xx_tuner_callback; | 703 | dvb->fe[0]->callback = em28xx_tuner_callback; |
| 636 | 704 | ||
| 637 | /* register everything */ | 705 | /* register everything */ |
| 638 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); | 706 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 71474d31e155..4739fc7e6eb3 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
| @@ -332,7 +332,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
| 332 | struct em28xx_eeprom *em_eeprom = (void *)eedata; | 332 | struct em28xx_eeprom *em_eeprom = (void *)eedata; |
| 333 | int i, err, size = len, block; | 333 | int i, err, size = len, block; |
| 334 | 334 | ||
| 335 | if (dev->chip_id == CHIP_ID_EM2874) { | 335 | if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) { |
| 336 | /* Empia switched to a 16-bit addressable eeprom in newer | 336 | /* Empia switched to a 16-bit addressable eeprom in newer |
| 337 | devices. While we could certainly write a routine to read | 337 | devices. While we could certainly write a routine to read |
| 338 | the eeprom, there is nothing of use in there that cannot be | 338 | the eeprom, there is nothing of use in there that cannot be |
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 91e90559642b..e92a28ede434 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
| @@ -201,6 +201,7 @@ enum em28xx_chip_id { | |||
| 201 | CHIP_ID_EM2870 = 35, | 201 | CHIP_ID_EM2870 = 35, |
| 202 | CHIP_ID_EM2883 = 36, | 202 | CHIP_ID_EM2883 = 36, |
| 203 | CHIP_ID_EM2874 = 65, | 203 | CHIP_ID_EM2874 = 65, |
| 204 | CHIP_ID_EM28174 = 113, | ||
| 204 | }; | 205 | }; |
| 205 | 206 | ||
| 206 | /* | 207 | /* |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6f2795a3d4b7..3cca33122450 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
| @@ -97,7 +97,7 @@ | |||
| 97 | #define EM2881_BOARD_PINNACLE_HYBRID_PRO 53 | 97 | #define EM2881_BOARD_PINNACLE_HYBRID_PRO 53 |
| 98 | #define EM2882_BOARD_KWORLD_VS_DVBT 54 | 98 | #define EM2882_BOARD_KWORLD_VS_DVBT 54 |
| 99 | #define EM2882_BOARD_TERRATEC_HYBRID_XS 55 | 99 | #define EM2882_BOARD_TERRATEC_HYBRID_XS 55 |
| 100 | #define EM2882_BOARD_PINNACLE_HYBRID_PRO 56 | 100 | #define EM2882_BOARD_PINNACLE_HYBRID_PRO_330E 56 |
| 101 | #define EM2883_BOARD_KWORLD_HYBRID_330U 57 | 101 | #define EM2883_BOARD_KWORLD_HYBRID_330U 57 |
| 102 | #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 | 102 | #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 |
| 103 | #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 | 103 | #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 |
| @@ -118,6 +118,7 @@ | |||
| 118 | #define EM2882_BOARD_DIKOM_DK300 75 | 118 | #define EM2882_BOARD_DIKOM_DK300 75 |
| 119 | #define EM2870_BOARD_KWORLD_A340 76 | 119 | #define EM2870_BOARD_KWORLD_A340 76 |
| 120 | #define EM2874_LEADERSHIP_ISDBT 77 | 120 | #define EM2874_LEADERSHIP_ISDBT 77 |
| 121 | #define EM28174_BOARD_PCTV_290E 78 | ||
| 121 | 122 | ||
| 122 | 123 | ||
| 123 | /* Limits minimum and default number of buffers */ | 124 | /* Limits minimum and default number of buffers */ |
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 031af1610154..908d7012c3f2 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c | |||
| @@ -766,7 +766,7 @@ inline void viu_activate_overlay(struct viu_reg *viu_reg) | |||
| 766 | out_be32(&vr->picture_count, reg_val.picture_count); | 766 | out_be32(&vr->picture_count, reg_val.picture_count); |
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | static int viu_start_preview(struct viu_dev *dev, struct viu_fh *fh) | 769 | static int viu_setup_preview(struct viu_dev *dev, struct viu_fh *fh) |
| 770 | { | 770 | { |
| 771 | int bpp; | 771 | int bpp; |
| 772 | 772 | ||
| @@ -805,11 +805,6 @@ static int viu_start_preview(struct viu_dev *dev, struct viu_fh *fh) | |||
| 805 | /* setup the base address of the overlay buffer */ | 805 | /* setup the base address of the overlay buffer */ |
| 806 | reg_val.field_base_addr = (u32)dev->ovbuf.base; | 806 | reg_val.field_base_addr = (u32)dev->ovbuf.base; |
| 807 | 807 | ||
| 808 | dev->ovenable = 1; | ||
| 809 | viu_activate_overlay(dev->vr); | ||
| 810 | |||
| 811 | /* start dma */ | ||
| 812 | viu_start_dma(dev); | ||
| 813 | return 0; | 808 | return 0; |
| 814 | } | 809 | } |
| 815 | 810 | ||
| @@ -825,13 +820,11 @@ static int vidioc_s_fmt_overlay(struct file *file, void *priv, | |||
| 825 | if (err) | 820 | if (err) |
| 826 | return err; | 821 | return err; |
| 827 | 822 | ||
| 828 | mutex_lock(&dev->lock); | ||
| 829 | fh->win = f->fmt.win; | 823 | fh->win = f->fmt.win; |
| 830 | 824 | ||
| 831 | spin_lock_irqsave(&dev->slock, flags); | 825 | spin_lock_irqsave(&dev->slock, flags); |
| 832 | viu_start_preview(dev, fh); | 826 | viu_setup_preview(dev, fh); |
| 833 | spin_unlock_irqrestore(&dev->slock, flags); | 827 | spin_unlock_irqrestore(&dev->slock, flags); |
| 834 | mutex_unlock(&dev->lock); | ||
| 835 | return 0; | 828 | return 0; |
| 836 | } | 829 | } |
| 837 | 830 | ||
| @@ -841,6 +834,28 @@ static int vidioc_try_fmt_overlay(struct file *file, void *priv, | |||
| 841 | return 0; | 834 | return 0; |
| 842 | } | 835 | } |
| 843 | 836 | ||
| 837 | static int vidioc_overlay(struct file *file, void *priv, unsigned int on) | ||
| 838 | { | ||
| 839 | struct viu_fh *fh = priv; | ||
| 840 | struct viu_dev *dev = (struct viu_dev *)fh->dev; | ||
| 841 | unsigned long flags; | ||
| 842 | |||
| 843 | if (on) { | ||
| 844 | spin_lock_irqsave(&dev->slock, flags); | ||
| 845 | viu_activate_overlay(dev->vr); | ||
| 846 | dev->ovenable = 1; | ||
| 847 | |||
| 848 | /* start dma */ | ||
| 849 | viu_start_dma(dev); | ||
| 850 | spin_unlock_irqrestore(&dev->slock, flags); | ||
| 851 | } else { | ||
| 852 | viu_stop_dma(dev); | ||
| 853 | dev->ovenable = 0; | ||
| 854 | } | ||
| 855 | |||
| 856 | return 0; | ||
| 857 | } | ||
| 858 | |||
| 844 | int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg) | 859 | int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg) |
| 845 | { | 860 | { |
| 846 | struct viu_fh *fh = priv; | 861 | struct viu_fh *fh = priv; |
| @@ -911,12 +926,16 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | |||
| 911 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 926 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
| 912 | { | 927 | { |
| 913 | struct viu_fh *fh = priv; | 928 | struct viu_fh *fh = priv; |
| 929 | struct viu_dev *dev = fh->dev; | ||
| 914 | 930 | ||
| 915 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 931 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
| 916 | return -EINVAL; | 932 | return -EINVAL; |
| 917 | if (fh->type != i) | 933 | if (fh->type != i) |
| 918 | return -EINVAL; | 934 | return -EINVAL; |
| 919 | 935 | ||
| 936 | if (dev->ovenable) | ||
| 937 | dev->ovenable = 0; | ||
| 938 | |||
| 920 | viu_start_dma(fh->dev); | 939 | viu_start_dma(fh->dev); |
| 921 | 940 | ||
| 922 | return videobuf_streamon(&fh->vb_vidq); | 941 | return videobuf_streamon(&fh->vb_vidq); |
| @@ -1311,7 +1330,8 @@ static int viu_open(struct file *file) | |||
| 1311 | videobuf_queue_dma_contig_init(&fh->vb_vidq, &viu_video_qops, | 1330 | videobuf_queue_dma_contig_init(&fh->vb_vidq, &viu_video_qops, |
| 1312 | dev->dev, &fh->vbq_lock, | 1331 | dev->dev, &fh->vbq_lock, |
| 1313 | fh->type, V4L2_FIELD_INTERLACED, | 1332 | fh->type, V4L2_FIELD_INTERLACED, |
| 1314 | sizeof(struct viu_buf), fh, NULL); | 1333 | sizeof(struct viu_buf), fh, |
| 1334 | &fh->dev->lock); | ||
| 1315 | return 0; | 1335 | return 0; |
| 1316 | } | 1336 | } |
| 1317 | 1337 | ||
| @@ -1401,7 +1421,7 @@ static struct v4l2_file_operations viu_fops = { | |||
| 1401 | .release = viu_release, | 1421 | .release = viu_release, |
| 1402 | .read = viu_read, | 1422 | .read = viu_read, |
| 1403 | .poll = viu_poll, | 1423 | .poll = viu_poll, |
| 1404 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ | 1424 | .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ |
| 1405 | .mmap = viu_mmap, | 1425 | .mmap = viu_mmap, |
| 1406 | }; | 1426 | }; |
| 1407 | 1427 | ||
| @@ -1415,6 +1435,7 @@ static const struct v4l2_ioctl_ops viu_ioctl_ops = { | |||
| 1415 | .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_overlay, | 1435 | .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_overlay, |
| 1416 | .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_overlay, | 1436 | .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_overlay, |
| 1417 | .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_overlay, | 1437 | .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_overlay, |
| 1438 | .vidioc_overlay = vidioc_overlay, | ||
| 1418 | .vidioc_g_fbuf = vidioc_g_fbuf, | 1439 | .vidioc_g_fbuf = vidioc_g_fbuf, |
| 1419 | .vidioc_s_fbuf = vidioc_s_fbuf, | 1440 | .vidioc_s_fbuf = vidioc_s_fbuf, |
| 1420 | .vidioc_reqbufs = vidioc_reqbufs, | 1441 | .vidioc_reqbufs = vidioc_reqbufs, |
| @@ -1498,9 +1519,6 @@ static int __devinit viu_of_probe(struct platform_device *op) | |||
| 1498 | INIT_LIST_HEAD(&viu_dev->vidq.active); | 1519 | INIT_LIST_HEAD(&viu_dev->vidq.active); |
| 1499 | INIT_LIST_HEAD(&viu_dev->vidq.queued); | 1520 | INIT_LIST_HEAD(&viu_dev->vidq.queued); |
| 1500 | 1521 | ||
| 1501 | /* initialize locks */ | ||
| 1502 | mutex_init(&viu_dev->lock); | ||
| 1503 | |||
| 1504 | snprintf(viu_dev->v4l2_dev.name, | 1522 | snprintf(viu_dev->v4l2_dev.name, |
| 1505 | sizeof(viu_dev->v4l2_dev.name), "%s", "VIU"); | 1523 | sizeof(viu_dev->v4l2_dev.name), "%s", "VIU"); |
| 1506 | ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev); | 1524 | ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev); |
| @@ -1531,8 +1549,15 @@ static int __devinit viu_of_probe(struct platform_device *op) | |||
| 1531 | 1549 | ||
| 1532 | viu_dev->vdev = vdev; | 1550 | viu_dev->vdev = vdev; |
| 1533 | 1551 | ||
| 1552 | /* initialize locks */ | ||
| 1553 | mutex_init(&viu_dev->lock); | ||
| 1554 | viu_dev->vdev->lock = &viu_dev->lock; | ||
| 1555 | spin_lock_init(&viu_dev->slock); | ||
| 1556 | |||
| 1534 | video_set_drvdata(viu_dev->vdev, viu_dev); | 1557 | video_set_drvdata(viu_dev->vdev, viu_dev); |
| 1535 | 1558 | ||
| 1559 | mutex_lock(&viu_dev->lock); | ||
| 1560 | |||
| 1536 | ret = video_register_device(viu_dev->vdev, VFL_TYPE_GRABBER, -1); | 1561 | ret = video_register_device(viu_dev->vdev, VFL_TYPE_GRABBER, -1); |
| 1537 | if (ret < 0) { | 1562 | if (ret < 0) { |
| 1538 | video_device_release(viu_dev->vdev); | 1563 | video_device_release(viu_dev->vdev); |
| @@ -1559,6 +1584,8 @@ static int __devinit viu_of_probe(struct platform_device *op) | |||
| 1559 | goto err_irq; | 1584 | goto err_irq; |
| 1560 | } | 1585 | } |
| 1561 | 1586 | ||
| 1587 | mutex_unlock(&viu_dev->lock); | ||
| 1588 | |||
| 1562 | dev_info(&op->dev, "Freescale VIU Video Capture Board\n"); | 1589 | dev_info(&op->dev, "Freescale VIU Video Capture Board\n"); |
| 1563 | return ret; | 1590 | return ret; |
| 1564 | 1591 | ||
| @@ -1568,6 +1595,7 @@ err_irq: | |||
| 1568 | err_clk: | 1595 | err_clk: |
| 1569 | video_unregister_device(viu_dev->vdev); | 1596 | video_unregister_device(viu_dev->vdev); |
| 1570 | err_vdev: | 1597 | err_vdev: |
| 1598 | mutex_unlock(&viu_dev->lock); | ||
| 1571 | i2c_put_adapter(ad); | 1599 | i2c_put_adapter(ad); |
| 1572 | v4l2_device_unregister(&viu_dev->v4l2_dev); | 1600 | v4l2_device_unregister(&viu_dev->v4l2_dev); |
| 1573 | err: | 1601 | err: |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index eb04e8b59989..34ae2c299799 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
| @@ -77,6 +77,15 @@ config USB_GSPCA_JEILINJ | |||
| 77 | To compile this driver as a module, choose M here: the | 77 | To compile this driver as a module, choose M here: the |
| 78 | module will be called gspca_jeilinj. | 78 | module will be called gspca_jeilinj. |
| 79 | 79 | ||
| 80 | config USB_GSPCA_KINECT | ||
| 81 | tristate "Kinect sensor device USB Camera Driver" | ||
| 82 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 83 | help | ||
| 84 | Say Y here if you want support for the Microsoft Kinect sensor device. | ||
| 85 | |||
| 86 | To compile this driver as a module, choose M here: the | ||
| 87 | module will be called gspca_kinect. | ||
| 88 | |||
| 80 | config USB_GSPCA_KONICA | 89 | config USB_GSPCA_KONICA |
| 81 | tristate "Konica USB Camera V4L2 driver" | 90 | tristate "Konica USB Camera V4L2 driver" |
| 82 | depends on VIDEO_V4L2 && USB_GSPCA | 91 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index 855fbc8c9c47..802fbe1bff4a 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
| @@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o | |||
| 5 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o | 5 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
| 6 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o | 6 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
| 7 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o | 7 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o |
| 8 | obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o | ||
| 8 | obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o | 9 | obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o |
| 9 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o | 10 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o |
| 10 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o | 11 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o |
| @@ -46,6 +47,7 @@ gspca_cpia1-objs := cpia1.o | |||
| 46 | gspca_etoms-objs := etoms.o | 47 | gspca_etoms-objs := etoms.o |
| 47 | gspca_finepix-objs := finepix.o | 48 | gspca_finepix-objs := finepix.o |
| 48 | gspca_jeilinj-objs := jeilinj.o | 49 | gspca_jeilinj-objs := jeilinj.o |
| 50 | gspca_kinect-objs := kinect.o | ||
| 49 | gspca_konica-objs := konica.o | 51 | gspca_konica-objs := konica.o |
| 50 | gspca_mars-objs := mars.o | 52 | gspca_mars-objs := mars.o |
| 51 | gspca_mr97310a-objs := mr97310a.o | 53 | gspca_mr97310a-objs := mr97310a.o |
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 9ddbac680663..f2a9451eea19 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c | |||
| @@ -1262,7 +1262,7 @@ static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) | |||
| 1262 | static void monitor_exposure(struct gspca_dev *gspca_dev) | 1262 | static void monitor_exposure(struct gspca_dev *gspca_dev) |
| 1263 | { | 1263 | { |
| 1264 | struct sd *sd = (struct sd *) gspca_dev; | 1264 | struct sd *sd = (struct sd *) gspca_dev; |
| 1265 | u8 exp_acc, bcomp, gain, coarseL, cmd[8]; | 1265 | u8 exp_acc, bcomp, cmd[8]; |
| 1266 | int ret, light_exp, dark_exp, very_dark_exp; | 1266 | int ret, light_exp, dark_exp, very_dark_exp; |
| 1267 | int old_exposure, new_exposure, framerate; | 1267 | int old_exposure, new_exposure, framerate; |
| 1268 | int setfps = 0, setexp = 0, setflicker = 0; | 1268 | int setfps = 0, setexp = 0, setflicker = 0; |
| @@ -1284,8 +1284,6 @@ static void monitor_exposure(struct gspca_dev *gspca_dev) | |||
| 1284 | } | 1284 | } |
| 1285 | exp_acc = gspca_dev->usb_buf[0]; | 1285 | exp_acc = gspca_dev->usb_buf[0]; |
| 1286 | bcomp = gspca_dev->usb_buf[1]; | 1286 | bcomp = gspca_dev->usb_buf[1]; |
| 1287 | gain = gspca_dev->usb_buf[2]; | ||
| 1288 | coarseL = gspca_dev->usb_buf[3]; | ||
| 1289 | 1287 | ||
| 1290 | light_exp = sd->params.colourParams.brightness + | 1288 | light_exp = sd->params.colourParams.brightness + |
| 1291 | TC - 50 + EXP_ACC_LIGHT; | 1289 | TC - 50 + EXP_ACC_LIGHT; |
| @@ -1772,9 +1770,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
| 1772 | /* this function is called at probe and resume time */ | 1770 | /* this function is called at probe and resume time */ |
| 1773 | static int sd_init(struct gspca_dev *gspca_dev) | 1771 | static int sd_init(struct gspca_dev *gspca_dev) |
| 1774 | { | 1772 | { |
| 1775 | #ifdef GSPCA_DEBUG | ||
| 1776 | struct sd *sd = (struct sd *) gspca_dev; | 1773 | struct sd *sd = (struct sd *) gspca_dev; |
| 1777 | #endif | ||
| 1778 | int ret; | 1774 | int ret; |
| 1779 | 1775 | ||
| 1780 | /* Start / Stop the camera to make sure we are talking to | 1776 | /* Start / Stop the camera to make sure we are talking to |
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index 99083038cec3..e8e071aa212f 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c | |||
| @@ -499,21 +499,8 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
| 499 | static int sd_probe(struct usb_interface *intf, | 499 | static int sd_probe(struct usb_interface *intf, |
| 500 | const struct usb_device_id *id) | 500 | const struct usb_device_id *id) |
| 501 | { | 501 | { |
| 502 | struct gspca_dev *gspca_dev; | 502 | return gspca_dev_probe(intf, id, |
| 503 | s32 ret; | ||
| 504 | |||
| 505 | ret = gspca_dev_probe(intf, id, | ||
| 506 | &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE); | 503 | &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE); |
| 507 | |||
| 508 | if (ret >= 0) { | ||
| 509 | gspca_dev = usb_get_intfdata(intf); | ||
| 510 | |||
| 511 | PDEBUG(D_PROBE, | ||
| 512 | "Camera is now controlling video device %s", | ||
| 513 | video_device_node_name(&gspca_dev->vdev)); | ||
| 514 | } | ||
| 515 | |||
| 516 | return ret; | ||
| 517 | } | 504 | } |
| 518 | 505 | ||
| 519 | static void sd_disconnect(struct usb_interface *intf) | 506 | static void sd_disconnect(struct usb_interface *intf) |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e526aa3dedaf..08ce9948d99b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
| @@ -55,7 +55,7 @@ MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); | |||
| 55 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 55 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
| 56 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
| 57 | 57 | ||
| 58 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 12, 0) | 58 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 13, 0) |
| 59 | 59 | ||
| 60 | #ifdef GSPCA_DEBUG | 60 | #ifdef GSPCA_DEBUG |
| 61 | int gspca_debug = D_ERR | D_PROBE; | 61 | int gspca_debug = D_ERR | D_PROBE; |
| @@ -2495,6 +2495,6 @@ module_exit(gspca_exit); | |||
| 2495 | module_param_named(debug, gspca_debug, int, 0644); | 2495 | module_param_named(debug, gspca_debug, int, 0644); |
| 2496 | MODULE_PARM_DESC(debug, | 2496 | MODULE_PARM_DESC(debug, |
| 2497 | "Debug (bit) 0x01:error 0x02:probe 0x04:config" | 2497 | "Debug (bit) 0x01:error 0x02:probe 0x04:config" |
| 2498 | " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout" | 2498 | " 0x08:stream 0x10:frame 0x20:packet" |
| 2499 | " 0x0100: v4l2"); | 2499 | " 0x0100: v4l2"); |
| 2500 | #endif | 2500 | #endif |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 41755226d389..49e2fcbe81fb 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include <linux/mutex.h> | 9 | #include <linux/mutex.h> |
| 10 | 10 | ||
| 11 | /* compilation option */ | 11 | /* compilation option */ |
| 12 | #define GSPCA_DEBUG 1 | 12 | /*#define GSPCA_DEBUG 1*/ |
| 13 | 13 | ||
| 14 | #ifdef GSPCA_DEBUG | 14 | #ifdef GSPCA_DEBUG |
| 15 | /* GSPCA our debug messages */ | 15 | /* GSPCA our debug messages */ |
| @@ -25,8 +25,8 @@ extern int gspca_debug; | |||
| 25 | #define D_STREAM 0x08 | 25 | #define D_STREAM 0x08 |
| 26 | #define D_FRAM 0x10 | 26 | #define D_FRAM 0x10 |
| 27 | #define D_PACK 0x20 | 27 | #define D_PACK 0x20 |
| 28 | #define D_USBI 0x40 | 28 | #define D_USBI 0x00 |
| 29 | #define D_USBO 0x80 | 29 | #define D_USBO 0x00 |
| 30 | #define D_V4L2 0x0100 | 30 | #define D_V4L2 0x0100 |
| 31 | #else | 31 | #else |
| 32 | #define PDEBUG(level, fmt, args...) | 32 | #define PDEBUG(level, fmt, args...) |
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c index 36dae38b1e38..1bd9c4b542dd 100644 --- a/drivers/media/video/gspca/jeilinj.c +++ b/drivers/media/video/gspca/jeilinj.c | |||
| @@ -6,6 +6,9 @@ | |||
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2009 Theodore Kilgore | 7 | * Copyright (C) 2009 Theodore Kilgore |
| 8 | * | 8 | * |
| 9 | * Sportscam DV15 support and control settings are | ||
| 10 | * Copyright (C) 2011 Patrice Chotard | ||
| 11 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
| 11 | * the Free Software Foundation; either version 2 of the License, or | 14 | * the Free Software Foundation; either version 2 of the License, or |
| @@ -23,7 +26,6 @@ | |||
| 23 | 26 | ||
| 24 | #define MODULE_NAME "jeilinj" | 27 | #define MODULE_NAME "jeilinj" |
| 25 | 28 | ||
| 26 | #include <linux/workqueue.h> | ||
| 27 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 28 | #include "gspca.h" | 30 | #include "gspca.h" |
| 29 | #include "jpeg.h" | 31 | #include "jpeg.h" |
| @@ -34,29 +36,51 @@ MODULE_LICENSE("GPL"); | |||
| 34 | 36 | ||
| 35 | /* Default timeouts, in ms */ | 37 | /* Default timeouts, in ms */ |
| 36 | #define JEILINJ_CMD_TIMEOUT 500 | 38 | #define JEILINJ_CMD_TIMEOUT 500 |
| 39 | #define JEILINJ_CMD_DELAY 160 | ||
| 37 | #define JEILINJ_DATA_TIMEOUT 1000 | 40 | #define JEILINJ_DATA_TIMEOUT 1000 |
| 38 | 41 | ||
| 39 | /* Maximum transfer size to use. */ | 42 | /* Maximum transfer size to use. */ |
| 40 | #define JEILINJ_MAX_TRANSFER 0x200 | 43 | #define JEILINJ_MAX_TRANSFER 0x200 |
| 41 | |||
| 42 | #define FRAME_HEADER_LEN 0x10 | 44 | #define FRAME_HEADER_LEN 0x10 |
| 45 | #define FRAME_START 0xFFFFFFFF | ||
| 46 | |||
| 47 | enum { | ||
| 48 | SAKAR_57379, | ||
| 49 | SPORTSCAM_DV15, | ||
| 50 | }; | ||
| 51 | |||
| 52 | #define CAMQUALITY_MIN 0 /* highest cam quality */ | ||
| 53 | #define CAMQUALITY_MAX 97 /* lowest cam quality */ | ||
| 54 | |||
| 55 | enum e_ctrl { | ||
| 56 | LIGHTFREQ, | ||
| 57 | AUTOGAIN, | ||
| 58 | RED, | ||
| 59 | GREEN, | ||
| 60 | BLUE, | ||
| 61 | NCTRLS /* number of controls */ | ||
| 62 | }; | ||
| 43 | 63 | ||
| 44 | /* Structure to hold all of our device specific stuff */ | 64 | /* Structure to hold all of our device specific stuff */ |
| 45 | struct sd { | 65 | struct sd { |
| 46 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 66 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
| 67 | struct gspca_ctrl ctrls[NCTRLS]; | ||
| 68 | int blocks_left; | ||
| 47 | const struct v4l2_pix_format *cap_mode; | 69 | const struct v4l2_pix_format *cap_mode; |
| 48 | /* Driver stuff */ | 70 | /* Driver stuff */ |
| 49 | struct work_struct work_struct; | 71 | u8 type; |
| 50 | struct workqueue_struct *work_thread; | ||
| 51 | u8 quality; /* image quality */ | 72 | u8 quality; /* image quality */ |
| 52 | u8 jpegqual; /* webcam quality */ | 73 | #define QUALITY_MIN 35 |
| 74 | #define QUALITY_MAX 85 | ||
| 75 | #define QUALITY_DEF 85 | ||
| 53 | u8 jpeg_hdr[JPEG_HDR_SZ]; | 76 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
| 54 | }; | 77 | }; |
| 55 | 78 | ||
| 56 | struct jlj_command { | 79 | struct jlj_command { |
| 57 | unsigned char instruction[2]; | 80 | unsigned char instruction[2]; |
| 58 | unsigned char ack_wanted; | 81 | unsigned char ack_wanted; |
| 59 | }; | 82 | unsigned char delay; |
| 83 | }; | ||
| 60 | 84 | ||
| 61 | /* AFAICT these cameras will only do 320x240. */ | 85 | /* AFAICT these cameras will only do 320x240. */ |
| 62 | static struct v4l2_pix_format jlj_mode[] = { | 86 | static struct v4l2_pix_format jlj_mode[] = { |
| @@ -64,6 +88,11 @@ static struct v4l2_pix_format jlj_mode[] = { | |||
| 64 | .bytesperline = 320, | 88 | .bytesperline = 320, |
| 65 | .sizeimage = 320 * 240, | 89 | .sizeimage = 320 * 240, |
| 66 | .colorspace = V4L2_COLORSPACE_JPEG, | 90 | .colorspace = V4L2_COLORSPACE_JPEG, |
| 91 | .priv = 0}, | ||
| 92 | { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
| 93 | .bytesperline = 640, | ||
| 94 | .sizeimage = 640 * 480, | ||
| 95 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
| 67 | .priv = 0} | 96 | .priv = 0} |
| 68 | }; | 97 | }; |
| 69 | 98 | ||
| @@ -73,178 +102,295 @@ static struct v4l2_pix_format jlj_mode[] = { | |||
| 73 | */ | 102 | */ |
| 74 | 103 | ||
| 75 | /* All commands are two bytes only */ | 104 | /* All commands are two bytes only */ |
| 76 | static int jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command) | 105 | static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command) |
| 77 | { | 106 | { |
| 78 | int retval; | 107 | int retval; |
| 79 | 108 | ||
| 109 | if (gspca_dev->usb_err < 0) | ||
| 110 | return; | ||
| 80 | memcpy(gspca_dev->usb_buf, command, 2); | 111 | memcpy(gspca_dev->usb_buf, command, 2); |
| 81 | retval = usb_bulk_msg(gspca_dev->dev, | 112 | retval = usb_bulk_msg(gspca_dev->dev, |
| 82 | usb_sndbulkpipe(gspca_dev->dev, 3), | 113 | usb_sndbulkpipe(gspca_dev->dev, 3), |
| 83 | gspca_dev->usb_buf, 2, NULL, 500); | 114 | gspca_dev->usb_buf, 2, NULL, 500); |
| 84 | if (retval < 0) | 115 | if (retval < 0) { |
| 85 | err("command write [%02x] error %d", | 116 | err("command write [%02x] error %d", |
| 86 | gspca_dev->usb_buf[0], retval); | 117 | gspca_dev->usb_buf[0], retval); |
| 87 | return retval; | 118 | gspca_dev->usb_err = retval; |
| 119 | } | ||
| 88 | } | 120 | } |
| 89 | 121 | ||
| 90 | /* Responses are one byte only */ | 122 | /* Responses are one byte only */ |
| 91 | static int jlj_read1(struct gspca_dev *gspca_dev, unsigned char response) | 123 | static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response) |
| 92 | { | 124 | { |
| 93 | int retval; | 125 | int retval; |
| 94 | 126 | ||
| 127 | if (gspca_dev->usb_err < 0) | ||
| 128 | return; | ||
| 95 | retval = usb_bulk_msg(gspca_dev->dev, | 129 | retval = usb_bulk_msg(gspca_dev->dev, |
| 96 | usb_rcvbulkpipe(gspca_dev->dev, 0x84), | 130 | usb_rcvbulkpipe(gspca_dev->dev, 0x84), |
| 97 | gspca_dev->usb_buf, 1, NULL, 500); | 131 | gspca_dev->usb_buf, 1, NULL, 500); |
| 98 | response = gspca_dev->usb_buf[0]; | 132 | response = gspca_dev->usb_buf[0]; |
| 99 | if (retval < 0) | 133 | if (retval < 0) { |
| 100 | err("read command [%02x] error %d", | 134 | err("read command [%02x] error %d", |
| 101 | gspca_dev->usb_buf[0], retval); | 135 | gspca_dev->usb_buf[0], retval); |
| 102 | return retval; | 136 | gspca_dev->usb_err = retval; |
| 137 | } | ||
| 103 | } | 138 | } |
| 104 | 139 | ||
| 105 | static int jlj_start(struct gspca_dev *gspca_dev) | 140 | static void setfreq(struct gspca_dev *gspca_dev) |
| 106 | { | 141 | { |
| 107 | int i; | 142 | struct sd *sd = (struct sd *) gspca_dev; |
| 108 | int retval = -1; | 143 | u8 freq_commands[][2] = { |
| 109 | u8 response = 0xff; | 144 | {0x71, 0x80}, |
| 110 | struct jlj_command start_commands[] = { | 145 | {0x70, 0x07} |
| 111 | {{0x71, 0x81}, 0}, | ||
| 112 | {{0x70, 0x05}, 0}, | ||
| 113 | {{0x95, 0x70}, 1}, | ||
| 114 | {{0x71, 0x81}, 0}, | ||
| 115 | {{0x70, 0x04}, 0}, | ||
| 116 | {{0x95, 0x70}, 1}, | ||
| 117 | {{0x71, 0x00}, 0}, | ||
| 118 | {{0x70, 0x08}, 0}, | ||
| 119 | {{0x95, 0x70}, 1}, | ||
| 120 | {{0x94, 0x02}, 0}, | ||
| 121 | {{0xde, 0x24}, 0}, | ||
| 122 | {{0x94, 0x02}, 0}, | ||
| 123 | {{0xdd, 0xf0}, 0}, | ||
| 124 | {{0x94, 0x02}, 0}, | ||
| 125 | {{0xe3, 0x2c}, 0}, | ||
| 126 | {{0x94, 0x02}, 0}, | ||
| 127 | {{0xe4, 0x00}, 0}, | ||
| 128 | {{0x94, 0x02}, 0}, | ||
| 129 | {{0xe5, 0x00}, 0}, | ||
| 130 | {{0x94, 0x02}, 0}, | ||
| 131 | {{0xe6, 0x2c}, 0}, | ||
| 132 | {{0x94, 0x03}, 0}, | ||
| 133 | {{0xaa, 0x00}, 0}, | ||
| 134 | {{0x71, 0x1e}, 0}, | ||
| 135 | {{0x70, 0x06}, 0}, | ||
| 136 | {{0x71, 0x80}, 0}, | ||
| 137 | {{0x70, 0x07}, 0} | ||
| 138 | }; | 146 | }; |
| 139 | for (i = 0; i < ARRAY_SIZE(start_commands); i++) { | 147 | |
| 140 | retval = jlj_write2(gspca_dev, start_commands[i].instruction); | 148 | freq_commands[0][1] |= (sd->ctrls[LIGHTFREQ].val >> 1); |
| 141 | if (retval < 0) | 149 | |
| 142 | return retval; | 150 | jlj_write2(gspca_dev, freq_commands[0]); |
| 143 | if (start_commands[i].ack_wanted) | 151 | jlj_write2(gspca_dev, freq_commands[1]); |
| 144 | retval = jlj_read1(gspca_dev, response); | ||
| 145 | if (retval < 0) | ||
| 146 | return retval; | ||
| 147 | } | ||
| 148 | PDEBUG(D_ERR, "jlj_start retval is %d", retval); | ||
| 149 | return retval; | ||
| 150 | } | 152 | } |
| 151 | 153 | ||
| 152 | static int jlj_stop(struct gspca_dev *gspca_dev) | 154 | static void setcamquality(struct gspca_dev *gspca_dev) |
| 155 | { | ||
| 156 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 157 | u8 quality_commands[][2] = { | ||
| 158 | {0x71, 0x1E}, | ||
| 159 | {0x70, 0x06} | ||
| 160 | }; | ||
| 161 | u8 camquality; | ||
| 162 | |||
| 163 | /* adapt camera quality from jpeg quality */ | ||
| 164 | camquality = ((QUALITY_MAX - sd->quality) * CAMQUALITY_MAX) | ||
| 165 | / (QUALITY_MAX - QUALITY_MIN); | ||
| 166 | quality_commands[0][1] += camquality; | ||
| 167 | |||
| 168 | jlj_write2(gspca_dev, quality_commands[0]); | ||
| 169 | jlj_write2(gspca_dev, quality_commands[1]); | ||
| 170 | } | ||
| 171 | |||
| 172 | static void setautogain(struct gspca_dev *gspca_dev) | ||
| 173 | { | ||
| 174 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 175 | u8 autogain_commands[][2] = { | ||
| 176 | {0x94, 0x02}, | ||
| 177 | {0xcf, 0x00} | ||
| 178 | }; | ||
| 179 | |||
| 180 | autogain_commands[1][1] = (sd->ctrls[AUTOGAIN].val << 4); | ||
| 181 | |||
| 182 | jlj_write2(gspca_dev, autogain_commands[0]); | ||
| 183 | jlj_write2(gspca_dev, autogain_commands[1]); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void setred(struct gspca_dev *gspca_dev) | ||
| 187 | { | ||
| 188 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 189 | u8 setred_commands[][2] = { | ||
| 190 | {0x94, 0x02}, | ||
| 191 | {0xe6, 0x00} | ||
| 192 | }; | ||
| 193 | |||
| 194 | setred_commands[1][1] = sd->ctrls[RED].val; | ||
| 195 | |||
| 196 | jlj_write2(gspca_dev, setred_commands[0]); | ||
| 197 | jlj_write2(gspca_dev, setred_commands[1]); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void setgreen(struct gspca_dev *gspca_dev) | ||
| 201 | { | ||
| 202 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 203 | u8 setgreen_commands[][2] = { | ||
| 204 | {0x94, 0x02}, | ||
| 205 | {0xe7, 0x00} | ||
| 206 | }; | ||
| 207 | |||
| 208 | setgreen_commands[1][1] = sd->ctrls[GREEN].val; | ||
| 209 | |||
| 210 | jlj_write2(gspca_dev, setgreen_commands[0]); | ||
| 211 | jlj_write2(gspca_dev, setgreen_commands[1]); | ||
| 212 | } | ||
| 213 | |||
| 214 | static void setblue(struct gspca_dev *gspca_dev) | ||
| 215 | { | ||
| 216 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 217 | u8 setblue_commands[][2] = { | ||
| 218 | {0x94, 0x02}, | ||
| 219 | {0xe9, 0x00} | ||
| 220 | }; | ||
| 221 | |||
| 222 | setblue_commands[1][1] = sd->ctrls[BLUE].val; | ||
| 223 | |||
| 224 | jlj_write2(gspca_dev, setblue_commands[0]); | ||
| 225 | jlj_write2(gspca_dev, setblue_commands[1]); | ||
| 226 | } | ||
| 227 | |||
| 228 | static const struct ctrl sd_ctrls[NCTRLS] = { | ||
| 229 | [LIGHTFREQ] = { | ||
| 230 | { | ||
| 231 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
| 232 | .type = V4L2_CTRL_TYPE_MENU, | ||
| 233 | .name = "Light frequency filter", | ||
| 234 | .minimum = V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, /* 1 */ | ||
| 235 | .maximum = V4L2_CID_POWER_LINE_FREQUENCY_60HZ, /* 2 */ | ||
| 236 | .step = 1, | ||
| 237 | .default_value = V4L2_CID_POWER_LINE_FREQUENCY_60HZ, | ||
| 238 | }, | ||
| 239 | .set_control = setfreq | ||
| 240 | }, | ||
| 241 | [AUTOGAIN] = { | ||
| 242 | { | ||
| 243 | .id = V4L2_CID_AUTOGAIN, | ||
| 244 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 245 | .name = "Automatic Gain (and Exposure)", | ||
| 246 | .minimum = 0, | ||
| 247 | .maximum = 3, | ||
| 248 | .step = 1, | ||
| 249 | #define AUTOGAIN_DEF 0 | ||
| 250 | .default_value = AUTOGAIN_DEF, | ||
| 251 | }, | ||
| 252 | .set_control = setautogain | ||
| 253 | }, | ||
| 254 | [RED] = { | ||
| 255 | { | ||
| 256 | .id = V4L2_CID_RED_BALANCE, | ||
| 257 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 258 | .name = "red balance", | ||
| 259 | .minimum = 0, | ||
| 260 | .maximum = 3, | ||
| 261 | .step = 1, | ||
| 262 | #define RED_BALANCE_DEF 2 | ||
| 263 | .default_value = RED_BALANCE_DEF, | ||
| 264 | }, | ||
| 265 | .set_control = setred | ||
| 266 | }, | ||
| 267 | |||
| 268 | [GREEN] = { | ||
| 269 | { | ||
| 270 | .id = V4L2_CID_GAIN, | ||
| 271 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 272 | .name = "green balance", | ||
| 273 | .minimum = 0, | ||
| 274 | .maximum = 3, | ||
| 275 | .step = 1, | ||
| 276 | #define GREEN_BALANCE_DEF 2 | ||
| 277 | .default_value = GREEN_BALANCE_DEF, | ||
| 278 | }, | ||
| 279 | .set_control = setgreen | ||
| 280 | }, | ||
| 281 | [BLUE] = { | ||
| 282 | { | ||
| 283 | .id = V4L2_CID_BLUE_BALANCE, | ||
| 284 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 285 | .name = "blue balance", | ||
| 286 | .minimum = 0, | ||
| 287 | .maximum = 3, | ||
| 288 | .step = 1, | ||
| 289 | #define BLUE_BALANCE_DEF 2 | ||
| 290 | .default_value = BLUE_BALANCE_DEF, | ||
| 291 | }, | ||
| 292 | .set_control = setblue | ||
| 293 | }, | ||
| 294 | }; | ||
| 295 | |||
| 296 | static int jlj_start(struct gspca_dev *gspca_dev) | ||
| 153 | { | 297 | { |
| 154 | int i; | 298 | int i; |
| 155 | int retval; | 299 | int start_commands_size; |
| 156 | struct jlj_command stop_commands[] = { | 300 | u8 response = 0xff; |
| 157 | {{0x71, 0x00}, 0}, | 301 | struct sd *sd = (struct sd *) gspca_dev; |
| 158 | {{0x70, 0x09}, 0}, | 302 | struct jlj_command start_commands[] = { |
| 159 | {{0x71, 0x80}, 0}, | 303 | {{0x71, 0x81}, 0, 0}, |
| 160 | {{0x70, 0x05}, 0} | 304 | {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY}, |
| 305 | {{0x95, 0x70}, 1, 0}, | ||
| 306 | {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0}, | ||
| 307 | {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY}, | ||
| 308 | {{0x95, 0x70}, 1, 0}, | ||
| 309 | {{0x71, 0x00}, 0, 0}, /* start streaming ??*/ | ||
| 310 | {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY}, | ||
| 311 | {{0x95, 0x70}, 1, 0}, | ||
| 312 | #define SPORTSCAM_DV15_CMD_SIZE 9 | ||
| 313 | {{0x94, 0x02}, 0, 0}, | ||
| 314 | {{0xde, 0x24}, 0, 0}, | ||
| 315 | {{0x94, 0x02}, 0, 0}, | ||
| 316 | {{0xdd, 0xf0}, 0, 0}, | ||
| 317 | {{0x94, 0x02}, 0, 0}, | ||
| 318 | {{0xe3, 0x2c}, 0, 0}, | ||
| 319 | {{0x94, 0x02}, 0, 0}, | ||
| 320 | {{0xe4, 0x00}, 0, 0}, | ||
| 321 | {{0x94, 0x02}, 0, 0}, | ||
| 322 | {{0xe5, 0x00}, 0, 0}, | ||
| 323 | {{0x94, 0x02}, 0, 0}, | ||
| 324 | {{0xe6, 0x2c}, 0, 0}, | ||
| 325 | {{0x94, 0x03}, 0, 0}, | ||
| 326 | {{0xaa, 0x00}, 0, 0} | ||
| 161 | }; | 327 | }; |
| 162 | for (i = 0; i < ARRAY_SIZE(stop_commands); i++) { | 328 | |
| 163 | retval = jlj_write2(gspca_dev, stop_commands[i].instruction); | 329 | sd->blocks_left = 0; |
| 164 | if (retval < 0) | 330 | /* Under Windows, USB spy shows that only the 9 first start |
| 165 | return retval; | 331 | * commands are used for SPORTSCAM_DV15 webcam |
| 332 | */ | ||
| 333 | if (sd->type == SPORTSCAM_DV15) | ||
| 334 | start_commands_size = SPORTSCAM_DV15_CMD_SIZE; | ||
| 335 | else | ||
| 336 | start_commands_size = ARRAY_SIZE(start_commands); | ||
| 337 | |||
| 338 | for (i = 0; i < start_commands_size; i++) { | ||
| 339 | jlj_write2(gspca_dev, start_commands[i].instruction); | ||
| 340 | if (start_commands[i].delay) | ||
| 341 | msleep(start_commands[i].delay); | ||
| 342 | if (start_commands[i].ack_wanted) | ||
| 343 | jlj_read1(gspca_dev, response); | ||
| 166 | } | 344 | } |
| 167 | return retval; | 345 | setcamquality(gspca_dev); |
| 346 | msleep(2); | ||
| 347 | setfreq(gspca_dev); | ||
| 348 | if (gspca_dev->usb_err < 0) | ||
| 349 | PDEBUG(D_ERR, "Start streaming command failed"); | ||
| 350 | return gspca_dev->usb_err; | ||
| 168 | } | 351 | } |
| 169 | 352 | ||
| 170 | /* This function is called as a workqueue function and runs whenever the camera | 353 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
| 171 | * is streaming data. Because it is a workqueue function it is allowed to sleep | 354 | u8 *data, int len) |
| 172 | * so we can use synchronous USB calls. To avoid possible collisions with other | ||
| 173 | * threads attempting to use the camera's USB interface the gspca usb_lock is | ||
| 174 | * used when performing the one USB control operation inside the workqueue, | ||
| 175 | * which tells the camera to close the stream. In practice the only thing | ||
| 176 | * which needs to be protected against is the usb_set_interface call that | ||
| 177 | * gspca makes during stream_off. Otherwise the camera doesn't provide any | ||
| 178 | * controls that the user could try to change. | ||
| 179 | */ | ||
| 180 | |||
| 181 | static void jlj_dostream(struct work_struct *work) | ||
| 182 | { | 355 | { |
| 183 | struct sd *dev = container_of(work, struct sd, work_struct); | 356 | struct sd *sd = (struct sd *) gspca_dev; |
| 184 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | ||
| 185 | int blocks_left; /* 0x200-sized blocks remaining in current frame. */ | ||
| 186 | int act_len; | ||
| 187 | int packet_type; | 357 | int packet_type; |
| 188 | int ret; | 358 | u32 header_marker; |
| 189 | u8 *buffer; | ||
| 190 | 359 | ||
| 191 | buffer = kmalloc(JEILINJ_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); | 360 | PDEBUG(D_STREAM, "Got %d bytes out of %d for Block 0", |
| 192 | if (!buffer) { | 361 | len, JEILINJ_MAX_TRANSFER); |
| 193 | err("Couldn't allocate USB buffer"); | 362 | if (len != JEILINJ_MAX_TRANSFER) { |
| 194 | goto quit_stream; | 363 | PDEBUG(D_PACK, "bad length"); |
| 364 | goto discard; | ||
| 195 | } | 365 | } |
| 196 | while (gspca_dev->present && gspca_dev->streaming) { | 366 | /* check if it's start of frame */ |
| 197 | /* | 367 | header_marker = ((u32 *)data)[0]; |
| 198 | * Now request data block 0. Line 0 reports the size | 368 | if (header_marker == FRAME_START) { |
| 199 | * to download, in blocks of size 0x200, and also tells the | 369 | sd->blocks_left = data[0x0a] - 1; |
| 200 | * "actual" data size, in bytes, which seems best to ignore. | 370 | PDEBUG(D_STREAM, "blocks_left = 0x%x", sd->blocks_left); |
| 201 | */ | ||
| 202 | ret = usb_bulk_msg(gspca_dev->dev, | ||
| 203 | usb_rcvbulkpipe(gspca_dev->dev, 0x82), | ||
| 204 | buffer, JEILINJ_MAX_TRANSFER, &act_len, | ||
| 205 | JEILINJ_DATA_TIMEOUT); | ||
| 206 | PDEBUG(D_STREAM, | ||
| 207 | "Got %d bytes out of %d for Block 0", | ||
| 208 | act_len, JEILINJ_MAX_TRANSFER); | ||
| 209 | if (ret < 0 || act_len < FRAME_HEADER_LEN) | ||
| 210 | goto quit_stream; | ||
| 211 | blocks_left = buffer[0x0a] - 1; | ||
| 212 | PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left); | ||
| 213 | |||
| 214 | /* Start a new frame, and add the JPEG header, first thing */ | 371 | /* Start a new frame, and add the JPEG header, first thing */ |
| 215 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 372 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
| 216 | dev->jpeg_hdr, JPEG_HDR_SZ); | 373 | sd->jpeg_hdr, JPEG_HDR_SZ); |
| 217 | /* Toss line 0 of data block 0, keep the rest. */ | 374 | /* Toss line 0 of data block 0, keep the rest. */ |
| 218 | gspca_frame_add(gspca_dev, INTER_PACKET, | 375 | gspca_frame_add(gspca_dev, INTER_PACKET, |
| 219 | buffer + FRAME_HEADER_LEN, | 376 | data + FRAME_HEADER_LEN, |
| 220 | JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); | 377 | JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); |
| 221 | 378 | } else if (sd->blocks_left > 0) { | |
| 222 | while (blocks_left > 0) { | 379 | PDEBUG(D_STREAM, "%d blocks remaining for frame", |
| 223 | if (!gspca_dev->present) | 380 | sd->blocks_left); |
| 224 | goto quit_stream; | 381 | sd->blocks_left -= 1; |
| 225 | ret = usb_bulk_msg(gspca_dev->dev, | 382 | if (sd->blocks_left == 0) |
| 226 | usb_rcvbulkpipe(gspca_dev->dev, 0x82), | 383 | packet_type = LAST_PACKET; |
| 227 | buffer, JEILINJ_MAX_TRANSFER, &act_len, | 384 | else |
| 228 | JEILINJ_DATA_TIMEOUT); | 385 | packet_type = INTER_PACKET; |
| 229 | if (ret < 0 || act_len < JEILINJ_MAX_TRANSFER) | 386 | gspca_frame_add(gspca_dev, packet_type, |
| 230 | goto quit_stream; | 387 | data, JEILINJ_MAX_TRANSFER); |
| 231 | PDEBUG(D_STREAM, | 388 | } else |
| 232 | "%d blocks remaining for frame", blocks_left); | 389 | goto discard; |
| 233 | blocks_left -= 1; | 390 | return; |
| 234 | if (blocks_left == 0) | 391 | discard: |
| 235 | packet_type = LAST_PACKET; | 392 | /* Discard data until a new frame starts. */ |
| 236 | else | 393 | gspca_dev->last_packet_type = DISCARD_PACKET; |
| 237 | packet_type = INTER_PACKET; | ||
| 238 | gspca_frame_add(gspca_dev, packet_type, | ||
| 239 | buffer, JEILINJ_MAX_TRANSFER); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | quit_stream: | ||
| 243 | mutex_lock(&gspca_dev->usb_lock); | ||
| 244 | if (gspca_dev->present) | ||
| 245 | jlj_stop(gspca_dev); | ||
| 246 | mutex_unlock(&gspca_dev->usb_lock); | ||
| 247 | kfree(buffer); | ||
| 248 | } | 394 | } |
| 249 | 395 | ||
| 250 | /* This function is called at probe time just before sd_init */ | 396 | /* This function is called at probe time just before sd_init */ |
| @@ -254,78 +400,169 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 254 | struct cam *cam = &gspca_dev->cam; | 400 | struct cam *cam = &gspca_dev->cam; |
| 255 | struct sd *dev = (struct sd *) gspca_dev; | 401 | struct sd *dev = (struct sd *) gspca_dev; |
| 256 | 402 | ||
| 257 | dev->quality = 85; | 403 | dev->type = id->driver_info; |
| 258 | dev->jpegqual = 85; | 404 | gspca_dev->cam.ctrls = dev->ctrls; |
| 405 | dev->quality = QUALITY_DEF; | ||
| 406 | dev->ctrls[LIGHTFREQ].def = V4L2_CID_POWER_LINE_FREQUENCY_60HZ; | ||
| 407 | dev->ctrls[RED].def = RED_BALANCE_DEF; | ||
| 408 | dev->ctrls[GREEN].def = GREEN_BALANCE_DEF; | ||
| 409 | dev->ctrls[BLUE].def = BLUE_BALANCE_DEF; | ||
| 259 | PDEBUG(D_PROBE, | 410 | PDEBUG(D_PROBE, |
| 260 | "JEILINJ camera detected" | 411 | "JEILINJ camera detected" |
| 261 | " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); | 412 | " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); |
| 262 | cam->cam_mode = jlj_mode; | 413 | cam->cam_mode = jlj_mode; |
| 263 | cam->nmodes = 1; | 414 | cam->nmodes = ARRAY_SIZE(jlj_mode); |
| 264 | cam->bulk = 1; | 415 | cam->bulk = 1; |
| 265 | /* We don't use the buffer gspca allocates so make it small. */ | 416 | cam->bulk_nurbs = 1; |
| 266 | cam->bulk_size = 32; | 417 | cam->bulk_size = JEILINJ_MAX_TRANSFER; |
| 267 | INIT_WORK(&dev->work_struct, jlj_dostream); | ||
| 268 | return 0; | 418 | return 0; |
| 269 | } | 419 | } |
| 270 | 420 | ||
| 271 | /* called on streamoff with alt==0 and on disconnect */ | 421 | static void sd_stopN(struct gspca_dev *gspca_dev) |
| 272 | /* the usb_lock is held at entry - restore on exit */ | ||
| 273 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
| 274 | { | 422 | { |
| 275 | struct sd *dev = (struct sd *) gspca_dev; | 423 | int i; |
| 424 | u8 *buf; | ||
| 425 | u8 stop_commands[][2] = { | ||
| 426 | {0x71, 0x00}, | ||
| 427 | {0x70, 0x09}, | ||
| 428 | {0x71, 0x80}, | ||
| 429 | {0x70, 0x05} | ||
| 430 | }; | ||
| 431 | |||
| 432 | for (;;) { | ||
| 433 | /* get the image remaining blocks */ | ||
| 434 | usb_bulk_msg(gspca_dev->dev, | ||
| 435 | gspca_dev->urb[0]->pipe, | ||
| 436 | gspca_dev->urb[0]->transfer_buffer, | ||
| 437 | JEILINJ_MAX_TRANSFER, NULL, | ||
| 438 | JEILINJ_DATA_TIMEOUT); | ||
| 439 | |||
| 440 | /* search for 0xff 0xd9 (EOF for JPEG) */ | ||
| 441 | i = 0; | ||
| 442 | buf = gspca_dev->urb[0]->transfer_buffer; | ||
| 443 | while ((i < (JEILINJ_MAX_TRANSFER - 1)) && | ||
| 444 | ((buf[i] != 0xff) || (buf[i+1] != 0xd9))) | ||
| 445 | i++; | ||
| 276 | 446 | ||
| 277 | /* wait for the work queue to terminate */ | 447 | if (i != (JEILINJ_MAX_TRANSFER - 1)) |
| 278 | mutex_unlock(&gspca_dev->usb_lock); | 448 | /* last remaining block found */ |
| 279 | /* This waits for jlj_dostream to finish */ | 449 | break; |
| 280 | destroy_workqueue(dev->work_thread); | 450 | } |
| 281 | dev->work_thread = NULL; | 451 | |
| 282 | mutex_lock(&gspca_dev->usb_lock); | 452 | for (i = 0; i < ARRAY_SIZE(stop_commands); i++) |
| 453 | jlj_write2(gspca_dev, stop_commands[i]); | ||
| 283 | } | 454 | } |
| 284 | 455 | ||
| 285 | /* this function is called at probe and resume time */ | 456 | /* this function is called at probe and resume time */ |
| 286 | static int sd_init(struct gspca_dev *gspca_dev) | 457 | static int sd_init(struct gspca_dev *gspca_dev) |
| 287 | { | 458 | { |
| 288 | return 0; | 459 | return gspca_dev->usb_err; |
| 289 | } | 460 | } |
| 290 | 461 | ||
| 291 | /* Set up for getting frames. */ | 462 | /* Set up for getting frames. */ |
| 292 | static int sd_start(struct gspca_dev *gspca_dev) | 463 | static int sd_start(struct gspca_dev *gspca_dev) |
| 293 | { | 464 | { |
| 294 | struct sd *dev = (struct sd *) gspca_dev; | 465 | struct sd *dev = (struct sd *) gspca_dev; |
| 295 | int ret; | ||
| 296 | 466 | ||
| 297 | /* create the JPEG header */ | 467 | /* create the JPEG header */ |
| 298 | jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 468 | jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
| 299 | 0x21); /* JPEG 422 */ | 469 | 0x21); /* JPEG 422 */ |
| 300 | jpeg_set_qual(dev->jpeg_hdr, dev->quality); | 470 | jpeg_set_qual(dev->jpeg_hdr, dev->quality); |
| 301 | PDEBUG(D_STREAM, "Start streaming at 320x240"); | 471 | PDEBUG(D_STREAM, "Start streaming at %dx%d", |
| 302 | ret = jlj_start(gspca_dev); | 472 | gspca_dev->height, gspca_dev->width); |
| 303 | if (ret < 0) { | 473 | jlj_start(gspca_dev); |
| 304 | PDEBUG(D_ERR, "Start streaming command failed"); | 474 | return gspca_dev->usb_err; |
| 305 | return ret; | ||
| 306 | } | ||
| 307 | /* Start the workqueue function to do the streaming */ | ||
| 308 | dev->work_thread = create_singlethread_workqueue(MODULE_NAME); | ||
| 309 | queue_work(dev->work_thread, &dev->work_struct); | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | } | 475 | } |
| 313 | 476 | ||
| 314 | /* Table of supported USB devices */ | 477 | /* Table of supported USB devices */ |
| 315 | static const struct usb_device_id device_table[] = { | 478 | static const struct usb_device_id device_table[] = { |
| 316 | {USB_DEVICE(0x0979, 0x0280)}, | 479 | {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379}, |
| 480 | {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15}, | ||
| 317 | {} | 481 | {} |
| 318 | }; | 482 | }; |
| 319 | 483 | ||
| 320 | MODULE_DEVICE_TABLE(usb, device_table); | 484 | MODULE_DEVICE_TABLE(usb, device_table); |
| 321 | 485 | ||
| 486 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
| 487 | struct v4l2_querymenu *menu) | ||
| 488 | { | ||
| 489 | switch (menu->id) { | ||
| 490 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
| 491 | switch (menu->index) { | ||
| 492 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
| 493 | strcpy((char *) menu->name, "disable"); | ||
| 494 | return 0; | ||
| 495 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
| 496 | strcpy((char *) menu->name, "50 Hz"); | ||
| 497 | return 0; | ||
| 498 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
| 499 | strcpy((char *) menu->name, "60 Hz"); | ||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | break; | ||
| 503 | } | ||
| 504 | return -EINVAL; | ||
| 505 | } | ||
| 506 | |||
| 507 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | ||
| 508 | struct v4l2_jpegcompression *jcomp) | ||
| 509 | { | ||
| 510 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 511 | |||
| 512 | if (jcomp->quality < QUALITY_MIN) | ||
| 513 | sd->quality = QUALITY_MIN; | ||
| 514 | else if (jcomp->quality > QUALITY_MAX) | ||
| 515 | sd->quality = QUALITY_MAX; | ||
| 516 | else | ||
| 517 | sd->quality = jcomp->quality; | ||
| 518 | if (gspca_dev->streaming) { | ||
| 519 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
| 520 | setcamquality(gspca_dev); | ||
| 521 | } | ||
| 522 | return 0; | ||
| 523 | } | ||
| 524 | |||
| 525 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | ||
| 526 | struct v4l2_jpegcompression *jcomp) | ||
| 527 | { | ||
| 528 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 529 | |||
| 530 | memset(jcomp, 0, sizeof *jcomp); | ||
| 531 | jcomp->quality = sd->quality; | ||
| 532 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | ||
| 533 | | V4L2_JPEG_MARKER_DQT; | ||
| 534 | return 0; | ||
| 535 | } | ||
| 536 | |||
| 537 | |||
| 322 | /* sub-driver description */ | 538 | /* sub-driver description */ |
| 323 | static const struct sd_desc sd_desc = { | 539 | static const struct sd_desc sd_desc_sakar_57379 = { |
| 324 | .name = MODULE_NAME, | 540 | .name = MODULE_NAME, |
| 325 | .config = sd_config, | 541 | .config = sd_config, |
| 326 | .init = sd_init, | 542 | .init = sd_init, |
| 327 | .start = sd_start, | 543 | .start = sd_start, |
| 328 | .stop0 = sd_stop0, | 544 | .stopN = sd_stopN, |
| 545 | .pkt_scan = sd_pkt_scan, | ||
| 546 | }; | ||
| 547 | |||
| 548 | /* sub-driver description */ | ||
| 549 | static const struct sd_desc sd_desc_sportscam_dv15 = { | ||
| 550 | .name = MODULE_NAME, | ||
| 551 | .config = sd_config, | ||
| 552 | .init = sd_init, | ||
| 553 | .start = sd_start, | ||
| 554 | .stopN = sd_stopN, | ||
| 555 | .pkt_scan = sd_pkt_scan, | ||
| 556 | .ctrls = sd_ctrls, | ||
| 557 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
| 558 | .querymenu = sd_querymenu, | ||
| 559 | .get_jcomp = sd_get_jcomp, | ||
| 560 | .set_jcomp = sd_set_jcomp, | ||
| 561 | }; | ||
| 562 | |||
| 563 | static const struct sd_desc *sd_desc[2] = { | ||
| 564 | &sd_desc_sakar_57379, | ||
| 565 | &sd_desc_sportscam_dv15 | ||
| 329 | }; | 566 | }; |
| 330 | 567 | ||
| 331 | /* -- device connect -- */ | 568 | /* -- device connect -- */ |
| @@ -333,7 +570,7 @@ static int sd_probe(struct usb_interface *intf, | |||
| 333 | const struct usb_device_id *id) | 570 | const struct usb_device_id *id) |
| 334 | { | 571 | { |
| 335 | return gspca_dev_probe(intf, id, | 572 | return gspca_dev_probe(intf, id, |
| 336 | &sd_desc, | 573 | sd_desc[id->driver_info], |
| 337 | sizeof(struct sd), | 574 | sizeof(struct sd), |
| 338 | THIS_MODULE); | 575 | THIS_MODULE); |
| 339 | } | 576 | } |
diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c new file mode 100644 index 000000000000..66671a4092e4 --- /dev/null +++ b/drivers/media/video/gspca/kinect.c | |||
| @@ -0,0 +1,429 @@ | |||
| 1 | /* | ||
| 2 | * kinect sensor device camera, gspca driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it> | ||
| 5 | * | ||
| 6 | * Based on the OpenKinect project and libfreenect | ||
| 7 | * http://openkinect.org/wiki/Init_Analysis | ||
| 8 | * | ||
| 9 | * Special thanks to Steven Toth and kernellabs.com for sponsoring a Kinect | ||
| 10 | * sensor device which I tested the driver on. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2 of the License, or | ||
| 15 | * any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 25 | */ | ||
| 26 | |||
| 27 | #define MODULE_NAME "kinect" | ||
| 28 | |||
| 29 | #include "gspca.h" | ||
| 30 | |||
| 31 | #define CTRL_TIMEOUT 500 | ||
| 32 | |||
| 33 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | ||
| 34 | MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); | ||
| 35 | MODULE_LICENSE("GPL"); | ||
| 36 | |||
| 37 | #ifdef DEBUG | ||
| 38 | int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK | | ||
| 39 | D_USBI | D_USBO | D_V4L2; | ||
| 40 | #endif | ||
| 41 | |||
| 42 | struct pkt_hdr { | ||
| 43 | uint8_t magic[2]; | ||
| 44 | uint8_t pad; | ||
| 45 | uint8_t flag; | ||
| 46 | uint8_t unk1; | ||
| 47 | uint8_t seq; | ||
| 48 | uint8_t unk2; | ||
| 49 | uint8_t unk3; | ||
| 50 | uint32_t timestamp; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct cam_hdr { | ||
| 54 | uint8_t magic[2]; | ||
| 55 | uint16_t len; | ||
| 56 | uint16_t cmd; | ||
| 57 | uint16_t tag; | ||
| 58 | }; | ||
| 59 | |||
| 60 | /* specific webcam descriptor */ | ||
| 61 | struct sd { | ||
| 62 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
| 63 | uint16_t cam_tag; /* a sequence number for packets */ | ||
| 64 | uint8_t stream_flag; /* to identify different stream types */ | ||
| 65 | uint8_t obuf[0x400]; /* output buffer for control commands */ | ||
| 66 | uint8_t ibuf[0x200]; /* input buffer for control commands */ | ||
| 67 | }; | ||
| 68 | |||
| 69 | /* V4L2 controls supported by the driver */ | ||
| 70 | /* controls prototypes here */ | ||
| 71 | |||
| 72 | static const struct ctrl sd_ctrls[] = { | ||
| 73 | }; | ||
| 74 | |||
| 75 | #define MODE_640x480 0x0001 | ||
| 76 | #define MODE_640x488 0x0002 | ||
| 77 | #define MODE_1280x1024 0x0004 | ||
| 78 | |||
| 79 | #define FORMAT_BAYER 0x0010 | ||
| 80 | #define FORMAT_UYVY 0x0020 | ||
| 81 | #define FORMAT_Y10B 0x0040 | ||
| 82 | |||
| 83 | #define FPS_HIGH 0x0100 | ||
| 84 | |||
| 85 | static const struct v4l2_pix_format video_camera_mode[] = { | ||
| 86 | {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, | ||
| 87 | .bytesperline = 640, | ||
| 88 | .sizeimage = 640 * 480, | ||
| 89 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 90 | .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH}, | ||
| 91 | {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
| 92 | .bytesperline = 640 * 2, | ||
| 93 | .sizeimage = 640 * 480 * 2, | ||
| 94 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 95 | .priv = MODE_640x480 | FORMAT_UYVY}, | ||
| 96 | {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, | ||
| 97 | .bytesperline = 1280, | ||
| 98 | .sizeimage = 1280 * 1024, | ||
| 99 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 100 | .priv = MODE_1280x1024 | FORMAT_BAYER}, | ||
| 101 | {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE, | ||
| 102 | .bytesperline = 640 * 10 / 8, | ||
| 103 | .sizeimage = 640 * 488 * 10 / 8, | ||
| 104 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 105 | .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH}, | ||
| 106 | {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE, | ||
| 107 | .bytesperline = 1280 * 10 / 8, | ||
| 108 | .sizeimage = 1280 * 1024 * 10 / 8, | ||
| 109 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 110 | .priv = MODE_1280x1024 | FORMAT_Y10B}, | ||
| 111 | }; | ||
| 112 | |||
| 113 | static int kinect_write(struct usb_device *udev, uint8_t *data, | ||
| 114 | uint16_t wLength) | ||
| 115 | { | ||
| 116 | return usb_control_msg(udev, | ||
| 117 | usb_sndctrlpipe(udev, 0), | ||
| 118 | 0x00, | ||
| 119 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 120 | 0, 0, data, wLength, CTRL_TIMEOUT); | ||
| 121 | } | ||
| 122 | |||
| 123 | static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength) | ||
| 124 | { | ||
| 125 | return usb_control_msg(udev, | ||
| 126 | usb_rcvctrlpipe(udev, 0), | ||
| 127 | 0x00, | ||
| 128 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 129 | 0, 0, data, wLength, CTRL_TIMEOUT); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf, | ||
| 133 | unsigned int cmd_len, void *replybuf, unsigned int reply_len) | ||
| 134 | { | ||
| 135 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 136 | struct usb_device *udev = gspca_dev->dev; | ||
| 137 | int res, actual_len; | ||
| 138 | uint8_t *obuf = sd->obuf; | ||
| 139 | uint8_t *ibuf = sd->ibuf; | ||
| 140 | struct cam_hdr *chdr = (void *)obuf; | ||
| 141 | struct cam_hdr *rhdr = (void *)ibuf; | ||
| 142 | |||
| 143 | if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) { | ||
| 144 | err("send_cmd: Invalid command length (0x%x)", cmd_len); | ||
| 145 | return -1; | ||
| 146 | } | ||
| 147 | |||
| 148 | chdr->magic[0] = 0x47; | ||
| 149 | chdr->magic[1] = 0x4d; | ||
| 150 | chdr->cmd = cpu_to_le16(cmd); | ||
| 151 | chdr->tag = cpu_to_le16(sd->cam_tag); | ||
| 152 | chdr->len = cpu_to_le16(cmd_len / 2); | ||
| 153 | |||
| 154 | memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len); | ||
| 155 | |||
| 156 | res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr)); | ||
| 157 | PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd, | ||
| 158 | sd->cam_tag, cmd_len, res); | ||
| 159 | if (res < 0) { | ||
| 160 | err("send_cmd: Output control transfer failed (%d)", res); | ||
| 161 | return res; | ||
| 162 | } | ||
| 163 | |||
| 164 | do { | ||
| 165 | actual_len = kinect_read(udev, ibuf, 0x200); | ||
| 166 | } while (actual_len == 0); | ||
| 167 | PDEBUG(D_USBO, "Control reply: %d", res); | ||
| 168 | if (actual_len < sizeof(*rhdr)) { | ||
| 169 | err("send_cmd: Input control transfer failed (%d)", res); | ||
| 170 | return res; | ||
| 171 | } | ||
| 172 | actual_len -= sizeof(*rhdr); | ||
| 173 | |||
| 174 | if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) { | ||
| 175 | err("send_cmd: Bad magic %02x %02x", rhdr->magic[0], | ||
| 176 | rhdr->magic[1]); | ||
| 177 | return -1; | ||
| 178 | } | ||
| 179 | if (rhdr->cmd != chdr->cmd) { | ||
| 180 | err("send_cmd: Bad cmd %02x != %02x", rhdr->cmd, chdr->cmd); | ||
| 181 | return -1; | ||
| 182 | } | ||
| 183 | if (rhdr->tag != chdr->tag) { | ||
| 184 | err("send_cmd: Bad tag %04x != %04x", rhdr->tag, chdr->tag); | ||
| 185 | return -1; | ||
| 186 | } | ||
| 187 | if (cpu_to_le16(rhdr->len) != (actual_len/2)) { | ||
| 188 | err("send_cmd: Bad len %04x != %04x", | ||
| 189 | cpu_to_le16(rhdr->len), (int)(actual_len/2)); | ||
| 190 | return -1; | ||
| 191 | } | ||
| 192 | |||
| 193 | if (actual_len > reply_len) { | ||
| 194 | warn("send_cmd: Data buffer is %d bytes long, but got %d bytes", | ||
| 195 | reply_len, actual_len); | ||
| 196 | memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len); | ||
| 197 | } else { | ||
| 198 | memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len); | ||
| 199 | } | ||
| 200 | |||
| 201 | sd->cam_tag++; | ||
| 202 | |||
| 203 | return actual_len; | ||
| 204 | } | ||
| 205 | |||
| 206 | static int write_register(struct gspca_dev *gspca_dev, uint16_t reg, | ||
| 207 | uint16_t data) | ||
| 208 | { | ||
| 209 | uint16_t reply[2]; | ||
| 210 | uint16_t cmd[2]; | ||
| 211 | int res; | ||
| 212 | |||
| 213 | cmd[0] = cpu_to_le16(reg); | ||
| 214 | cmd[1] = cpu_to_le16(data); | ||
| 215 | |||
| 216 | PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data); | ||
| 217 | res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4); | ||
| 218 | if (res < 0) | ||
| 219 | return res; | ||
| 220 | if (res != 2) { | ||
| 221 | warn("send_cmd returned %d [%04x %04x], 0000 expected", | ||
| 222 | res, reply[0], reply[1]); | ||
| 223 | } | ||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | /* this function is called at probe time */ | ||
| 228 | static int sd_config(struct gspca_dev *gspca_dev, | ||
| 229 | const struct usb_device_id *id) | ||
| 230 | { | ||
| 231 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 232 | struct cam *cam; | ||
| 233 | |||
| 234 | sd->cam_tag = 0; | ||
| 235 | |||
| 236 | /* Only video stream is supported for now, | ||
| 237 | * which has stream flag = 0x80 */ | ||
| 238 | sd->stream_flag = 0x80; | ||
| 239 | |||
| 240 | cam = &gspca_dev->cam; | ||
| 241 | |||
| 242 | cam->cam_mode = video_camera_mode; | ||
| 243 | cam->nmodes = ARRAY_SIZE(video_camera_mode); | ||
| 244 | |||
| 245 | #if 0 | ||
| 246 | /* Setting those values is not needed for video stream */ | ||
| 247 | cam->npkt = 15; | ||
| 248 | gspca_dev->pkt_size = 960 * 2; | ||
| 249 | #endif | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* this function is called at probe and resume time */ | ||
| 255 | static int sd_init(struct gspca_dev *gspca_dev) | ||
| 256 | { | ||
| 257 | PDEBUG(D_PROBE, "Kinect Camera device."); | ||
| 258 | |||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 262 | static int sd_start(struct gspca_dev *gspca_dev) | ||
| 263 | { | ||
| 264 | int mode; | ||
| 265 | uint8_t fmt_reg, fmt_val; | ||
| 266 | uint8_t res_reg, res_val; | ||
| 267 | uint8_t fps_reg, fps_val; | ||
| 268 | uint8_t mode_val; | ||
| 269 | |||
| 270 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
| 271 | |||
| 272 | if (mode & FORMAT_Y10B) { | ||
| 273 | fmt_reg = 0x19; | ||
| 274 | res_reg = 0x1a; | ||
| 275 | fps_reg = 0x1b; | ||
| 276 | mode_val = 0x03; | ||
| 277 | } else { | ||
| 278 | fmt_reg = 0x0c; | ||
| 279 | res_reg = 0x0d; | ||
| 280 | fps_reg = 0x0e; | ||
| 281 | mode_val = 0x01; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* format */ | ||
| 285 | if (mode & FORMAT_UYVY) | ||
| 286 | fmt_val = 0x05; | ||
| 287 | else | ||
| 288 | fmt_val = 0x00; | ||
| 289 | |||
| 290 | if (mode & MODE_1280x1024) | ||
| 291 | res_val = 0x02; | ||
| 292 | else | ||
| 293 | res_val = 0x01; | ||
| 294 | |||
| 295 | if (mode & FPS_HIGH) | ||
| 296 | fps_val = 0x1e; | ||
| 297 | else | ||
| 298 | fps_val = 0x0f; | ||
| 299 | |||
| 300 | |||
| 301 | /* turn off IR-reset function */ | ||
| 302 | write_register(gspca_dev, 0x105, 0x00); | ||
| 303 | |||
| 304 | /* Reset video stream */ | ||
| 305 | write_register(gspca_dev, 0x05, 0x00); | ||
| 306 | |||
| 307 | /* Due to some ridiculous condition in the firmware, we have to start | ||
| 308 | * and stop the depth stream before the camera will hand us 1280x1024 | ||
| 309 | * IR. This is a stupid workaround, but we've yet to find a better | ||
| 310 | * solution. | ||
| 311 | * | ||
| 312 | * Thanks to Drew Fisher for figuring this out. | ||
| 313 | */ | ||
| 314 | if (mode & (FORMAT_Y10B | MODE_1280x1024)) { | ||
| 315 | write_register(gspca_dev, 0x13, 0x01); | ||
| 316 | write_register(gspca_dev, 0x14, 0x1e); | ||
| 317 | write_register(gspca_dev, 0x06, 0x02); | ||
| 318 | write_register(gspca_dev, 0x06, 0x00); | ||
| 319 | } | ||
| 320 | |||
| 321 | write_register(gspca_dev, fmt_reg, fmt_val); | ||
| 322 | write_register(gspca_dev, res_reg, res_val); | ||
| 323 | write_register(gspca_dev, fps_reg, fps_val); | ||
| 324 | |||
| 325 | /* Start video stream */ | ||
| 326 | write_register(gspca_dev, 0x05, mode_val); | ||
| 327 | |||
| 328 | /* disable Hflip */ | ||
| 329 | write_register(gspca_dev, 0x47, 0x00); | ||
| 330 | |||
| 331 | return 0; | ||
| 332 | } | ||
| 333 | |||
| 334 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
| 335 | { | ||
| 336 | /* reset video stream */ | ||
| 337 | write_register(gspca_dev, 0x05, 0x00); | ||
| 338 | } | ||
| 339 | |||
| 340 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len) | ||
| 341 | { | ||
| 342 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 343 | |||
| 344 | struct pkt_hdr *hdr = (void *)__data; | ||
| 345 | uint8_t *data = __data + sizeof(*hdr); | ||
| 346 | int datalen = len - sizeof(*hdr); | ||
| 347 | |||
| 348 | uint8_t sof = sd->stream_flag | 1; | ||
| 349 | uint8_t mof = sd->stream_flag | 2; | ||
| 350 | uint8_t eof = sd->stream_flag | 5; | ||
| 351 | |||
| 352 | if (len < 12) | ||
| 353 | return; | ||
| 354 | |||
| 355 | if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') { | ||
| 356 | warn("[Stream %02x] Invalid magic %02x%02x", sd->stream_flag, | ||
| 357 | hdr->magic[0], hdr->magic[1]); | ||
| 358 | return; | ||
| 359 | } | ||
| 360 | |||
| 361 | if (hdr->flag == sof) | ||
| 362 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen); | ||
| 363 | |||
| 364 | else if (hdr->flag == mof) | ||
| 365 | gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen); | ||
| 366 | |||
| 367 | else if (hdr->flag == eof) | ||
| 368 | gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen); | ||
| 369 | |||
| 370 | else | ||
| 371 | warn("Packet type not recognized..."); | ||
| 372 | } | ||
| 373 | |||
| 374 | /* sub-driver description */ | ||
| 375 | static const struct sd_desc sd_desc = { | ||
| 376 | .name = MODULE_NAME, | ||
| 377 | .ctrls = sd_ctrls, | ||
| 378 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
| 379 | .config = sd_config, | ||
| 380 | .init = sd_init, | ||
| 381 | .start = sd_start, | ||
| 382 | .stopN = sd_stopN, | ||
| 383 | .pkt_scan = sd_pkt_scan, | ||
| 384 | /* | ||
| 385 | .querymenu = sd_querymenu, | ||
| 386 | .get_streamparm = sd_get_streamparm, | ||
| 387 | .set_streamparm = sd_set_streamparm, | ||
| 388 | */ | ||
| 389 | }; | ||
| 390 | |||
| 391 | /* -- module initialisation -- */ | ||
| 392 | static const struct usb_device_id device_table[] = { | ||
| 393 | {USB_DEVICE(0x045e, 0x02ae)}, | ||
| 394 | {} | ||
| 395 | }; | ||
| 396 | |||
| 397 | MODULE_DEVICE_TABLE(usb, device_table); | ||
| 398 | |||
| 399 | /* -- device connect -- */ | ||
| 400 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
| 401 | { | ||
| 402 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
| 403 | THIS_MODULE); | ||
| 404 | } | ||
| 405 | |||
| 406 | static struct usb_driver sd_driver = { | ||
| 407 | .name = MODULE_NAME, | ||
| 408 | .id_table = device_table, | ||
| 409 | .probe = sd_probe, | ||
| 410 | .disconnect = gspca_disconnect, | ||
| 411 | #ifdef CONFIG_PM | ||
| 412 | .suspend = gspca_suspend, | ||
| 413 | .resume = gspca_resume, | ||
| 414 | #endif | ||
| 415 | }; | ||
| 416 | |||
| 417 | /* -- module insert / remove -- */ | ||
| 418 | static int __init sd_mod_init(void) | ||
| 419 | { | ||
| 420 | return usb_register(&sd_driver); | ||
| 421 | } | ||
| 422 | |||
| 423 | static void __exit sd_mod_exit(void) | ||
| 424 | { | ||
| 425 | usb_deregister(&sd_driver); | ||
| 426 | } | ||
| 427 | |||
| 428 | module_init(sd_mod_init); | ||
| 429 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 41dce49fb43d..9d0b46027b93 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c | |||
| @@ -1375,7 +1375,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 1375 | { | 1375 | { |
| 1376 | struct sd *sd = (struct sd *) gspca_dev; | 1376 | struct sd *sd = (struct sd *) gspca_dev; |
| 1377 | struct cam *cam; | 1377 | struct cam *cam; |
| 1378 | int data1, data2; | ||
| 1379 | const u16 (*init_data)[2]; | 1378 | const u16 (*init_data)[2]; |
| 1380 | static const u16 (*(init_data_tb[]))[2] = { | 1379 | static const u16 (*(init_data_tb[]))[2] = { |
| 1381 | spca508_vista_init_data, /* CreativeVista 0 */ | 1380 | spca508_vista_init_data, /* CreativeVista 0 */ |
| @@ -1386,6 +1385,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 1386 | spca508_init_data, /* ViewQuestVQ110 5 */ | 1385 | spca508_init_data, /* ViewQuestVQ110 5 */ |
| 1387 | }; | 1386 | }; |
| 1388 | 1387 | ||
| 1388 | #ifdef GSPCA_DEBUG | ||
| 1389 | int data1, data2; | ||
| 1390 | |||
| 1389 | /* Read from global register the USB product and vendor IDs, just to | 1391 | /* Read from global register the USB product and vendor IDs, just to |
| 1390 | * prove that we can communicate with the device. This works, which | 1392 | * prove that we can communicate with the device. This works, which |
| 1391 | * confirms at we are communicating properly and that the device | 1393 | * confirms at we are communicating properly and that the device |
| @@ -1400,6 +1402,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 1400 | 1402 | ||
| 1401 | data1 = reg_read(gspca_dev, 0x8621); | 1403 | data1 = reg_read(gspca_dev, 0x8621); |
| 1402 | PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1); | 1404 | PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1); |
| 1405 | #endif | ||
| 1403 | 1406 | ||
| 1404 | cam = &gspca_dev->cam; | 1407 | cam = &gspca_dev->cam; |
| 1405 | cam->cam_mode = sif_mode; | 1408 | cam->cam_mode = sif_mode; |
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 87be52b5e1e3..763747700f10 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
| @@ -436,17 +436,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
| 436 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 436 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
| 437 | struct v4l2_querymenu *menu) | 437 | struct v4l2_querymenu *menu) |
| 438 | { | 438 | { |
| 439 | static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"}; | ||
| 440 | |||
| 439 | switch (menu->id) { | 441 | switch (menu->id) { |
| 440 | case V4L2_CID_POWER_LINE_FREQUENCY: | 442 | case V4L2_CID_POWER_LINE_FREQUENCY: |
| 441 | switch (menu->index) { | 443 | if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm)) |
| 442 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | 444 | break; |
| 443 | strcpy((char *) menu->name, "50 Hz"); | 445 | strcpy((char *) menu->name, freq_nm[menu->index]); |
| 444 | return 0; | 446 | return 0; |
| 445 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
| 446 | strcpy((char *) menu->name, "60 Hz"); | ||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | break; | ||
| 450 | } | 447 | } |
| 451 | return -EINVAL; | 448 | return -EINVAL; |
| 452 | } | 449 | } |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c index ac47b4c94388..75a5b9c2f15f 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c | |||
| @@ -217,6 +217,8 @@ static int pb0100_start(struct sd *sd) | |||
| 217 | 217 | ||
| 218 | intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); | 218 | intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); |
| 219 | alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); | 219 | alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); |
| 220 | if (!alt) | ||
| 221 | return -ENODEV; | ||
| 220 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | 222 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
| 221 | 223 | ||
| 222 | /* If we don't have enough bandwidth use a lower framerate */ | 224 | /* If we don't have enough bandwidth use a lower framerate */ |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 543542af2720..b089c0d3ee9f 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
| @@ -396,57 +396,6 @@ static void reg_w_riv(struct gspca_dev *gspca_dev, | |||
| 396 | req, index, value); | 396 | req, index, value); |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | /* read 1 byte */ | ||
| 400 | static u8 reg_r_1(struct gspca_dev *gspca_dev, | ||
| 401 | u16 value) /* wValue */ | ||
| 402 | { | ||
| 403 | int ret; | ||
| 404 | |||
| 405 | if (gspca_dev->usb_err < 0) | ||
| 406 | return 0; | ||
| 407 | ret = usb_control_msg(gspca_dev->dev, | ||
| 408 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
| 409 | 0x20, /* request */ | ||
| 410 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 411 | value, | ||
| 412 | 0, /* index */ | ||
| 413 | gspca_dev->usb_buf, 1, | ||
| 414 | 500); /* timeout */ | ||
| 415 | if (ret < 0) { | ||
| 416 | err("reg_r_1 err %d", ret); | ||
| 417 | gspca_dev->usb_err = ret; | ||
| 418 | return 0; | ||
| 419 | } | ||
| 420 | return gspca_dev->usb_buf[0]; | ||
| 421 | } | ||
| 422 | |||
| 423 | /* read 1 or 2 bytes */ | ||
| 424 | static u16 reg_r_12(struct gspca_dev *gspca_dev, | ||
| 425 | u8 req, /* bRequest */ | ||
| 426 | u16 index, /* wIndex */ | ||
| 427 | u16 length) /* wLength (1 or 2 only) */ | ||
| 428 | { | ||
| 429 | int ret; | ||
| 430 | |||
| 431 | if (gspca_dev->usb_err < 0) | ||
| 432 | return 0; | ||
| 433 | gspca_dev->usb_buf[1] = 0; | ||
| 434 | ret = usb_control_msg(gspca_dev->dev, | ||
| 435 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
| 436 | req, | ||
| 437 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 438 | 0, /* value */ | ||
| 439 | index, | ||
| 440 | gspca_dev->usb_buf, length, | ||
| 441 | 500); | ||
| 442 | if (ret < 0) { | ||
| 443 | err("reg_r_12 err %d", ret); | ||
| 444 | gspca_dev->usb_err = ret; | ||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; | ||
| 448 | } | ||
| 449 | |||
| 450 | static void write_vector(struct gspca_dev *gspca_dev, | 399 | static void write_vector(struct gspca_dev *gspca_dev, |
| 451 | const struct cmd *data, int ncmds) | 400 | const struct cmd *data, int ncmds) |
| 452 | { | 401 | { |
| @@ -473,44 +422,46 @@ static void setup_qtable(struct gspca_dev *gspca_dev, | |||
| 473 | static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, | 422 | static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, |
| 474 | u8 req, u16 idx, u16 val) | 423 | u8 req, u16 idx, u16 val) |
| 475 | { | 424 | { |
| 476 | u16 notdone; | ||
| 477 | |||
| 478 | reg_w_riv(gspca_dev, req, idx, val); | 425 | reg_w_riv(gspca_dev, req, idx, val); |
| 479 | notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); | 426 | reg_r(gspca_dev, 0x01, 0x0001, 1); |
| 427 | PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]); | ||
| 480 | reg_w_riv(gspca_dev, req, idx, val); | 428 | reg_w_riv(gspca_dev, req, idx, val); |
| 481 | 429 | ||
| 482 | PDEBUG(D_FRAM, "before wait 0x%04x", notdone); | ||
| 483 | |||
| 484 | msleep(200); | 430 | msleep(200); |
| 485 | notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); | 431 | reg_r(gspca_dev, 0x01, 0x0001, 1); |
| 486 | PDEBUG(D_FRAM, "after wait 0x%04x", notdone); | 432 | PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]); |
| 487 | } | 433 | } |
| 488 | 434 | ||
| 435 | #ifdef GSPCA_DEBUG | ||
| 489 | static void spca504_read_info(struct gspca_dev *gspca_dev) | 436 | static void spca504_read_info(struct gspca_dev *gspca_dev) |
| 490 | { | 437 | { |
| 491 | int i; | 438 | int i; |
| 492 | u8 info[6]; | 439 | u8 info[6]; |
| 493 | 440 | ||
| 494 | for (i = 0; i < 6; i++) | 441 | for (i = 0; i < 6; i++) { |
| 495 | info[i] = reg_r_1(gspca_dev, i); | 442 | reg_r(gspca_dev, 0, i, 1); |
| 443 | info[i] = gspca_dev->usb_buf[0]; | ||
| 444 | } | ||
| 496 | PDEBUG(D_STREAM, | 445 | PDEBUG(D_STREAM, |
| 497 | "Read info: %d %d %d %d %d %d." | 446 | "Read info: %d %d %d %d %d %d." |
| 498 | " Should be 1,0,2,2,0,0", | 447 | " Should be 1,0,2,2,0,0", |
| 499 | info[0], info[1], info[2], | 448 | info[0], info[1], info[2], |
| 500 | info[3], info[4], info[5]); | 449 | info[3], info[4], info[5]); |
| 501 | } | 450 | } |
| 451 | #endif | ||
| 502 | 452 | ||
| 503 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, | 453 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, |
| 504 | u8 req, | 454 | u8 req, |
| 505 | u16 idx, u16 val, u16 endcode, u8 count) | 455 | u16 idx, u16 val, u8 endcode, u8 count) |
| 506 | { | 456 | { |
| 507 | u16 status; | 457 | u16 status; |
| 508 | 458 | ||
| 509 | reg_w_riv(gspca_dev, req, idx, val); | 459 | reg_w_riv(gspca_dev, req, idx, val); |
| 510 | status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); | 460 | reg_r(gspca_dev, 0x01, 0x0001, 1); |
| 511 | if (gspca_dev->usb_err < 0) | 461 | if (gspca_dev->usb_err < 0) |
| 512 | return; | 462 | return; |
| 513 | PDEBUG(D_FRAM, "Status 0x%04x Need 0x%04x", status, endcode); | 463 | PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x", |
| 464 | gspca_dev->usb_buf[0], endcode); | ||
| 514 | if (!count) | 465 | if (!count) |
| 515 | return; | 466 | return; |
| 516 | count = 200; | 467 | count = 200; |
| @@ -518,7 +469,8 @@ static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, | |||
| 518 | msleep(10); | 469 | msleep(10); |
| 519 | /* gsmart mini2 write a each wait setting 1 ms is enough */ | 470 | /* gsmart mini2 write a each wait setting 1 ms is enough */ |
| 520 | /* reg_w_riv(gspca_dev, req, idx, val); */ | 471 | /* reg_w_riv(gspca_dev, req, idx, val); */ |
| 521 | status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); | 472 | reg_r(gspca_dev, 0x01, 0x0001, 1); |
| 473 | status = gspca_dev->usb_buf[0]; | ||
| 522 | if (status == endcode) { | 474 | if (status == endcode) { |
| 523 | PDEBUG(D_FRAM, "status 0x%04x after wait %d", | 475 | PDEBUG(D_FRAM, "status 0x%04x after wait %d", |
| 524 | status, 200 - count); | 476 | status, 200 - count); |
| @@ -555,17 +507,19 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) | |||
| 555 | } | 507 | } |
| 556 | } | 508 | } |
| 557 | 509 | ||
| 510 | #ifdef GSPCA_DEBUG | ||
| 558 | static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) | 511 | static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) |
| 559 | { | 512 | { |
| 560 | u8 *data; | 513 | u8 *data; |
| 561 | 514 | ||
| 562 | data = gspca_dev->usb_buf; | 515 | data = gspca_dev->usb_buf; |
| 563 | reg_r(gspca_dev, 0x20, 0, 5); | 516 | reg_r(gspca_dev, 0x20, 0, 5); |
| 564 | PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ", | 517 | PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d", |
| 565 | data[0], data[1], data[2], data[3], data[4]); | 518 | data[0], data[1], data[2], data[3], data[4]); |
| 566 | reg_r(gspca_dev, 0x23, 0, 64); | 519 | reg_r(gspca_dev, 0x23, 0, 64); |
| 567 | reg_r(gspca_dev, 0x23, 1, 64); | 520 | reg_r(gspca_dev, 0x23, 1, 64); |
| 568 | } | 521 | } |
| 522 | #endif | ||
| 569 | 523 | ||
| 570 | static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) | 524 | static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) |
| 571 | { | 525 | { |
| @@ -578,7 +532,9 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) | |||
| 578 | reg_w_riv(gspca_dev, 0x31, 0, 0); | 532 | reg_w_riv(gspca_dev, 0x31, 0, 0); |
| 579 | spca504B_WaitCmdStatus(gspca_dev); | 533 | spca504B_WaitCmdStatus(gspca_dev); |
| 580 | spca504B_PollingDataReady(gspca_dev); | 534 | spca504B_PollingDataReady(gspca_dev); |
| 535 | #ifdef GSPCA_DEBUG | ||
| 581 | spca50x_GetFirmware(gspca_dev); | 536 | spca50x_GetFirmware(gspca_dev); |
| 537 | #endif | ||
| 582 | reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ | 538 | reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ |
| 583 | reg_r(gspca_dev, 0x24, 8, 1); | 539 | reg_r(gspca_dev, 0x24, 8, 1); |
| 584 | 540 | ||
| @@ -628,7 +584,8 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev) | |||
| 628 | cnt = 256; | 584 | cnt = 256; |
| 629 | while (--cnt > 0) { | 585 | while (--cnt > 0) { |
| 630 | /* With this we get the status, when return 0 it's all ok */ | 586 | /* With this we get the status, when return 0 it's all ok */ |
| 631 | if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0) | 587 | reg_r(gspca_dev, 0x06, 0x00, 1); |
| 588 | if (gspca_dev->usb_buf[0] == 0) | ||
| 632 | return; | 589 | return; |
| 633 | msleep(10); | 590 | msleep(10); |
| 634 | } | 591 | } |
| @@ -772,10 +729,14 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 772 | /* fall thru */ | 729 | /* fall thru */ |
| 773 | case BRIDGE_SPCA533: | 730 | case BRIDGE_SPCA533: |
| 774 | spca504B_PollingDataReady(gspca_dev); | 731 | spca504B_PollingDataReady(gspca_dev); |
| 732 | #ifdef GSPCA_DEBUG | ||
| 775 | spca50x_GetFirmware(gspca_dev); | 733 | spca50x_GetFirmware(gspca_dev); |
| 734 | #endif | ||
| 776 | break; | 735 | break; |
| 777 | case BRIDGE_SPCA536: | 736 | case BRIDGE_SPCA536: |
| 737 | #ifdef GSPCA_DEBUG | ||
| 778 | spca50x_GetFirmware(gspca_dev); | 738 | spca50x_GetFirmware(gspca_dev); |
| 739 | #endif | ||
| 779 | reg_r(gspca_dev, 0x00, 0x5002, 1); | 740 | reg_r(gspca_dev, 0x00, 0x5002, 1); |
| 780 | reg_w_1(gspca_dev, 0x24, 0, 0, 0); | 741 | reg_w_1(gspca_dev, 0x24, 0, 0, 0); |
| 781 | reg_r(gspca_dev, 0x24, 0, 1); | 742 | reg_r(gspca_dev, 0x24, 0, 1); |
| @@ -801,7 +762,9 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 801 | /* case BRIDGE_SPCA504: */ | 762 | /* case BRIDGE_SPCA504: */ |
| 802 | PDEBUG(D_STREAM, "Opening SPCA504"); | 763 | PDEBUG(D_STREAM, "Opening SPCA504"); |
| 803 | if (sd->subtype == AiptekMiniPenCam13) { | 764 | if (sd->subtype == AiptekMiniPenCam13) { |
| 765 | #ifdef GSPCA_DEBUG | ||
| 804 | spca504_read_info(gspca_dev); | 766 | spca504_read_info(gspca_dev); |
| 767 | #endif | ||
| 805 | 768 | ||
| 806 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ | 769 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ |
| 807 | spca504A_acknowledged_command(gspca_dev, 0x24, | 770 | spca504A_acknowledged_command(gspca_dev, 0x24, |
| @@ -873,7 +836,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
| 873 | break; | 836 | break; |
| 874 | case BRIDGE_SPCA504: | 837 | case BRIDGE_SPCA504: |
| 875 | if (sd->subtype == AiptekMiniPenCam13) { | 838 | if (sd->subtype == AiptekMiniPenCam13) { |
| 839 | #ifdef GSPCA_DEBUG | ||
| 876 | spca504_read_info(gspca_dev); | 840 | spca504_read_info(gspca_dev); |
| 841 | #endif | ||
| 877 | 842 | ||
| 878 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ | 843 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ |
| 879 | spca504A_acknowledged_command(gspca_dev, 0x24, | 844 | spca504A_acknowledged_command(gspca_dev, 0x24, |
| @@ -885,7 +850,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
| 885 | 0, 0, 0x9d, 1); | 850 | 0, 0, 0x9d, 1); |
| 886 | } else { | 851 | } else { |
| 887 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); | 852 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); |
| 853 | #ifdef GSPCA_DEBUG | ||
| 888 | spca504_read_info(gspca_dev); | 854 | spca504_read_info(gspca_dev); |
| 855 | #endif | ||
| 889 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); | 856 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); |
| 890 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); | 857 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); |
| 891 | } | 858 | } |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index a3eccd815766..7e762d551099 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
| @@ -92,8 +92,6 @@ static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val); | |||
| 92 | static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val); | 92 | static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val); |
| 93 | static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); | 93 | static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); |
| 94 | static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); | 94 | static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); |
| 95 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
| 96 | struct v4l2_querymenu *menu); | ||
| 97 | 95 | ||
| 98 | static const struct ctrl sd_ctrls[] = { | 96 | static const struct ctrl sd_ctrls[] = { |
| 99 | { | 97 | { |
| @@ -1379,17 +1377,14 @@ static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val) | |||
| 1379 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 1377 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
| 1380 | struct v4l2_querymenu *menu) | 1378 | struct v4l2_querymenu *menu) |
| 1381 | { | 1379 | { |
| 1380 | static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"}; | ||
| 1381 | |||
| 1382 | switch (menu->id) { | 1382 | switch (menu->id) { |
| 1383 | case V4L2_CID_POWER_LINE_FREQUENCY: | 1383 | case V4L2_CID_POWER_LINE_FREQUENCY: |
| 1384 | switch (menu->index) { | 1384 | if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm)) |
| 1385 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | 1385 | break; |
| 1386 | strcpy((char *) menu->name, "50 Hz"); | 1386 | strcpy((char *) menu->name, freq_nm[menu->index]); |
| 1387 | return 0; | 1387 | return 0; |
| 1388 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
| 1389 | strcpy((char *) menu->name, "60 Hz"); | ||
| 1390 | return 0; | ||
| 1391 | } | ||
| 1392 | break; | ||
| 1393 | case V4L2_CID_EFFECTS: | 1388 | case V4L2_CID_EFFECTS: |
| 1394 | if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) { | 1389 | if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) { |
| 1395 | strncpy((char *) menu->name, | 1390 | strncpy((char *) menu->name, |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index fa164e861cde..61cdd56a74a9 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
| @@ -3065,15 +3065,10 @@ static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */ | |||
| 3065 | {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */ | 3065 | {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */ |
| 3066 | {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */ | 3066 | {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */ |
| 3067 | {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */ | 3067 | {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */ |
| 3068 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | ||
| 3069 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | ||
| 3070 | {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ | ||
| 3071 | {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */ | ||
| 3072 | {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */ | ||
| 3073 | {} | 3068 | {} |
| 3074 | }; | 3069 | }; |
| 3075 | 3070 | ||
| 3076 | static const struct usb_action mc501cb_50HZScale[] = { | 3071 | static const struct usb_action mc501cb_50HZ[] = { |
| 3077 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3072 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
| 3078 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3073 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
| 3079 | {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ | 3074 | {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ |
| @@ -3082,15 +3077,10 @@ static const struct usb_action mc501cb_50HZScale[] = { | |||
| 3082 | {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */ | 3077 | {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */ |
| 3083 | {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */ | 3078 | {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */ |
| 3084 | {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */ | 3079 | {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */ |
| 3085 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | ||
| 3086 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | ||
| 3087 | {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ | ||
| 3088 | {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */ | ||
| 3089 | {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */ | ||
| 3090 | {} | 3080 | {} |
| 3091 | }; | 3081 | }; |
| 3092 | 3082 | ||
| 3093 | static const struct usb_action mc501cb_50HZ[] = { | 3083 | static const struct usb_action mc501cb_50HZScale[] = { |
| 3094 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3084 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
| 3095 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3085 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
| 3096 | {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ | 3086 | {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ |
| @@ -3099,15 +3089,10 @@ static const struct usb_action mc501cb_50HZ[] = { | |||
| 3099 | {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */ | 3089 | {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */ |
| 3100 | {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */ | 3090 | {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */ |
| 3101 | {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */ | 3091 | {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */ |
| 3102 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | ||
| 3103 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | ||
| 3104 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | ||
| 3105 | {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */ | ||
| 3106 | {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */ | ||
| 3107 | {} | 3092 | {} |
| 3108 | }; | 3093 | }; |
| 3109 | 3094 | ||
| 3110 | static const struct usb_action mc501cb_60HZScale[] = { | 3095 | static const struct usb_action mc501cb_60HZ[] = { |
| 3111 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3096 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
| 3112 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3097 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
| 3113 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | 3098 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ |
| @@ -3116,15 +3101,10 @@ static const struct usb_action mc501cb_60HZScale[] = { | |||
| 3116 | {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */ | 3101 | {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */ |
| 3117 | {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */ | 3102 | {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */ |
| 3118 | {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */ | 3103 | {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */ |
| 3119 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | ||
| 3120 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | ||
| 3121 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | ||
| 3122 | {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */ | ||
| 3123 | {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */ | ||
| 3124 | {} | 3104 | {} |
| 3125 | }; | 3105 | }; |
| 3126 | 3106 | ||
| 3127 | static const struct usb_action mc501cb_60HZ[] = { | 3107 | static const struct usb_action mc501cb_60HZScale[] = { |
| 3128 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3108 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
| 3129 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3109 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
| 3130 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | 3110 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ |
| @@ -3133,15 +3113,10 @@ static const struct usb_action mc501cb_60HZ[] = { | |||
| 3133 | {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */ | 3113 | {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */ |
| 3134 | {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */ | 3114 | {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */ |
| 3135 | {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */ | 3115 | {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */ |
| 3136 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | ||
| 3137 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | ||
| 3138 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | ||
| 3139 | {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */ | ||
| 3140 | {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */ | ||
| 3141 | {} | 3116 | {} |
| 3142 | }; | 3117 | }; |
| 3143 | 3118 | ||
| 3144 | static const struct usb_action mc501cb_NoFlikerScale[] = { | 3119 | static const struct usb_action mc501cb_NoFliker[] = { |
| 3145 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3120 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
| 3146 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3121 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
| 3147 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | 3122 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ |
| @@ -3150,15 +3125,10 @@ static const struct usb_action mc501cb_NoFlikerScale[] = { | |||
| 3150 | {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */ | 3125 | {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */ |
| 3151 | {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */ | 3126 | {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */ |
| 3152 | {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */ | 3127 | {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */ |
| 3153 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | ||
| 3154 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | ||
| 3155 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | ||
| 3156 | {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */ | ||
| 3157 | {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */ | ||
| 3158 | {} | 3128 | {} |
| 3159 | }; | 3129 | }; |
| 3160 | 3130 | ||
| 3161 | static const struct usb_action mc501cb_NoFliker[] = { | 3131 | static const struct usb_action mc501cb_NoFlikerScale[] = { |
| 3162 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3132 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
| 3163 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3133 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
| 3164 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | 3134 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ |
| @@ -6296,7 +6266,6 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
| 6296 | { | 6266 | { |
| 6297 | struct sd *sd = (struct sd *) gspca_dev; | 6267 | struct sd *sd = (struct sd *) gspca_dev; |
| 6298 | int i; | 6268 | int i; |
| 6299 | u8 retbyte; | ||
| 6300 | u16 retword; | 6269 | u16 retword; |
| 6301 | 6270 | ||
| 6302 | /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ | 6271 | /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ |
| @@ -6389,8 +6358,12 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
| 6389 | retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */ | 6358 | retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */ |
| 6390 | PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword); | 6359 | PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword); |
| 6391 | if (retword == 0x2030) { | 6360 | if (retword == 0x2030) { |
| 6361 | #ifdef GSPCA_DEBUG | ||
| 6362 | u8 retbyte; | ||
| 6363 | |||
| 6392 | retbyte = i2c_read(gspca_dev, 0x02); /* revision number */ | 6364 | retbyte = i2c_read(gspca_dev, 0x02); /* revision number */ |
| 6393 | PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte); | 6365 | PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte); |
| 6366 | #endif | ||
| 6394 | send_unknown(gspca_dev, SENSOR_PO2030); | 6367 | send_unknown(gspca_dev, SENSOR_PO2030); |
| 6395 | return retword; | 6368 | return retword; |
| 6396 | } | 6369 | } |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 39946420b301..a4e4dfdbc2f2 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
| @@ -810,7 +810,6 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, | |||
| 810 | const struct pci_device_id *pci_id) | 810 | const struct pci_device_id *pci_id) |
| 811 | { | 811 | { |
| 812 | u16 cmd; | 812 | u16 cmd; |
| 813 | u8 card_rev; | ||
| 814 | unsigned char pci_latency; | 813 | unsigned char pci_latency; |
| 815 | 814 | ||
| 816 | IVTV_DEBUG_INFO("Enabling pci device\n"); | 815 | IVTV_DEBUG_INFO("Enabling pci device\n"); |
| @@ -857,7 +856,6 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, | |||
| 857 | } | 856 | } |
| 858 | IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); | 857 | IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); |
| 859 | 858 | ||
| 860 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &card_rev); | ||
| 861 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); | 859 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); |
| 862 | 860 | ||
| 863 | if (pci_latency < 64 && ivtv_pci_latency) { | 861 | if (pci_latency < 64 && ivtv_pci_latency) { |
| @@ -874,7 +872,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, | |||
| 874 | 872 | ||
| 875 | IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " | 873 | IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " |
| 876 | "irq: %d, latency: %d, memory: 0x%lx\n", | 874 | "irq: %d, latency: %d, memory: 0x%lx\n", |
| 877 | pdev->device, card_rev, pdev->bus->number, | 875 | pdev->device, pdev->revision, pdev->bus->number, |
| 878 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | 876 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), |
| 879 | pdev->irq, pci_latency, (unsigned long)itv->base_addr); | 877 | pdev->irq, pci_latency, (unsigned long)itv->base_addr); |
| 880 | 878 | ||
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 53fa2a7bf156..ebebed929627 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c | |||
| @@ -315,10 +315,20 @@ static int mt9m111_setup_rect(struct i2c_client *client, | |||
| 315 | static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt) | 315 | static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt) |
| 316 | { | 316 | { |
| 317 | int ret; | 317 | int ret; |
| 318 | u16 mask = MT9M111_OUTFMT_PROCESSED_BAYER | MT9M111_OUTFMT_RGB | | ||
| 319 | MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_SWAP_RGB_EVEN | | ||
| 320 | MT9M111_OUTFMT_RGB565 | MT9M111_OUTFMT_RGB555 | | ||
| 321 | MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr | | ||
| 322 | MT9M111_OUTFMT_SWAP_YCbCr_C_Y; | ||
| 318 | 323 | ||
| 319 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); | 324 | ret = reg_read(OUTPUT_FORMAT_CTRL2_A); |
| 325 | if (ret >= 0) | ||
| 326 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, (ret & ~mask) | outfmt); | ||
| 320 | if (!ret) | 327 | if (!ret) |
| 321 | ret = reg_write(OUTPUT_FORMAT_CTRL2_B, outfmt); | 328 | ret = reg_read(OUTPUT_FORMAT_CTRL2_B); |
| 329 | if (ret >= 0) | ||
| 330 | ret = reg_write(OUTPUT_FORMAT_CTRL2_B, (ret & ~mask) | outfmt); | ||
| 331 | |||
| 322 | return ret; | 332 | return ret; |
| 323 | } | 333 | } |
| 324 | 334 | ||
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index e313d8390092..fc76ed1c08e5 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
| @@ -228,7 +228,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, | |||
| 228 | 228 | ||
| 229 | flags = soc_camera_apply_sensor_flags(icl, flags); | 229 | flags = soc_camera_apply_sensor_flags(icl, flags); |
| 230 | 230 | ||
| 231 | if (flags & SOCAM_PCLK_SAMPLE_RISING) | 231 | if (flags & SOCAM_PCLK_SAMPLE_FALLING) |
| 232 | pixclk |= 0x10; | 232 | pixclk |= 0x10; |
| 233 | 233 | ||
| 234 | if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH)) | 234 | if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH)) |
diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c new file mode 100644 index 000000000000..1319c2c48aff --- /dev/null +++ b/drivers/media/video/mt9v032.c | |||
| @@ -0,0 +1,773 @@ | |||
| 1 | /* | ||
| 2 | * Driver for MT9V032 CMOS Image Sensor from Micron | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
| 5 | * | ||
| 6 | * Based on the MT9M001 driver, | ||
| 7 | * | ||
| 8 | * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/i2c.h> | ||
| 17 | #include <linux/log2.h> | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/videodev2.h> | ||
| 21 | #include <linux/v4l2-mediabus.h> | ||
| 22 | |||
| 23 | #include <media/mt9v032.h> | ||
| 24 | #include <media/v4l2-ctrls.h> | ||
| 25 | #include <media/v4l2-device.h> | ||
| 26 | #include <media/v4l2-subdev.h> | ||
| 27 | |||
| 28 | #define MT9V032_PIXEL_ARRAY_HEIGHT 492 | ||
| 29 | #define MT9V032_PIXEL_ARRAY_WIDTH 782 | ||
| 30 | |||
| 31 | #define MT9V032_CHIP_VERSION 0x00 | ||
| 32 | #define MT9V032_CHIP_ID_REV1 0x1311 | ||
| 33 | #define MT9V032_CHIP_ID_REV3 0x1313 | ||
| 34 | #define MT9V032_ROW_START 0x01 | ||
| 35 | #define MT9V032_ROW_START_MIN 4 | ||
| 36 | #define MT9V032_ROW_START_DEF 10 | ||
| 37 | #define MT9V032_ROW_START_MAX 482 | ||
| 38 | #define MT9V032_COLUMN_START 0x02 | ||
| 39 | #define MT9V032_COLUMN_START_MIN 1 | ||
| 40 | #define MT9V032_COLUMN_START_DEF 2 | ||
| 41 | #define MT9V032_COLUMN_START_MAX 752 | ||
| 42 | #define MT9V032_WINDOW_HEIGHT 0x03 | ||
| 43 | #define MT9V032_WINDOW_HEIGHT_MIN 1 | ||
| 44 | #define MT9V032_WINDOW_HEIGHT_DEF 480 | ||
| 45 | #define MT9V032_WINDOW_HEIGHT_MAX 480 | ||
| 46 | #define MT9V032_WINDOW_WIDTH 0x04 | ||
| 47 | #define MT9V032_WINDOW_WIDTH_MIN 1 | ||
| 48 | #define MT9V032_WINDOW_WIDTH_DEF 752 | ||
| 49 | #define MT9V032_WINDOW_WIDTH_MAX 752 | ||
| 50 | #define MT9V032_HORIZONTAL_BLANKING 0x05 | ||
| 51 | #define MT9V032_HORIZONTAL_BLANKING_MIN 43 | ||
| 52 | #define MT9V032_HORIZONTAL_BLANKING_MAX 1023 | ||
| 53 | #define MT9V032_VERTICAL_BLANKING 0x06 | ||
| 54 | #define MT9V032_VERTICAL_BLANKING_MIN 4 | ||
| 55 | #define MT9V032_VERTICAL_BLANKING_MAX 3000 | ||
| 56 | #define MT9V032_CHIP_CONTROL 0x07 | ||
| 57 | #define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3) | ||
| 58 | #define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7) | ||
| 59 | #define MT9V032_CHIP_CONTROL_SEQUENTIAL (1 << 8) | ||
| 60 | #define MT9V032_SHUTTER_WIDTH1 0x08 | ||
| 61 | #define MT9V032_SHUTTER_WIDTH2 0x09 | ||
| 62 | #define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a | ||
| 63 | #define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b | ||
| 64 | #define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1 | ||
| 65 | #define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480 | ||
| 66 | #define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767 | ||
| 67 | #define MT9V032_RESET 0x0c | ||
| 68 | #define MT9V032_READ_MODE 0x0d | ||
| 69 | #define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0) | ||
| 70 | #define MT9V032_READ_MODE_ROW_BIN_SHIFT 0 | ||
| 71 | #define MT9V032_READ_MODE_COLUMN_BIN_MASK (3 << 2) | ||
| 72 | #define MT9V032_READ_MODE_COLUMN_BIN_SHIFT 2 | ||
| 73 | #define MT9V032_READ_MODE_ROW_FLIP (1 << 4) | ||
| 74 | #define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5) | ||
| 75 | #define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6) | ||
| 76 | #define MT9V032_READ_MODE_DARK_ROWS (1 << 7) | ||
| 77 | #define MT9V032_PIXEL_OPERATION_MODE 0x0f | ||
| 78 | #define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2) | ||
| 79 | #define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6) | ||
| 80 | #define MT9V032_ANALOG_GAIN 0x35 | ||
| 81 | #define MT9V032_ANALOG_GAIN_MIN 16 | ||
| 82 | #define MT9V032_ANALOG_GAIN_DEF 16 | ||
| 83 | #define MT9V032_ANALOG_GAIN_MAX 64 | ||
| 84 | #define MT9V032_MAX_ANALOG_GAIN 0x36 | ||
| 85 | #define MT9V032_MAX_ANALOG_GAIN_MAX 127 | ||
| 86 | #define MT9V032_FRAME_DARK_AVERAGE 0x42 | ||
| 87 | #define MT9V032_DARK_AVG_THRESH 0x46 | ||
| 88 | #define MT9V032_DARK_AVG_LOW_THRESH_MASK (255 << 0) | ||
| 89 | #define MT9V032_DARK_AVG_LOW_THRESH_SHIFT 0 | ||
| 90 | #define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8) | ||
| 91 | #define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8 | ||
| 92 | #define MT9V032_ROW_NOISE_CORR_CONTROL 0x70 | ||
| 93 | #define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5) | ||
| 94 | #define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7) | ||
| 95 | #define MT9V032_PIXEL_CLOCK 0x74 | ||
| 96 | #define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0) | ||
| 97 | #define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1) | ||
| 98 | #define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2) | ||
| 99 | #define MT9V032_PIXEL_CLOCK_CONT_LINE (1 << 3) | ||
| 100 | #define MT9V032_PIXEL_CLOCK_INV_PXL_CLK (1 << 4) | ||
| 101 | #define MT9V032_TEST_PATTERN 0x7f | ||
| 102 | #define MT9V032_TEST_PATTERN_DATA_MASK (1023 << 0) | ||
| 103 | #define MT9V032_TEST_PATTERN_DATA_SHIFT 0 | ||
| 104 | #define MT9V032_TEST_PATTERN_USE_DATA (1 << 10) | ||
| 105 | #define MT9V032_TEST_PATTERN_GRAY_MASK (3 << 11) | ||
| 106 | #define MT9V032_TEST_PATTERN_GRAY_NONE (0 << 11) | ||
| 107 | #define MT9V032_TEST_PATTERN_GRAY_VERTICAL (1 << 11) | ||
| 108 | #define MT9V032_TEST_PATTERN_GRAY_HORIZONTAL (2 << 11) | ||
| 109 | #define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11) | ||
| 110 | #define MT9V032_TEST_PATTERN_ENABLE (1 << 13) | ||
| 111 | #define MT9V032_TEST_PATTERN_FLIP (1 << 14) | ||
| 112 | #define MT9V032_AEC_AGC_ENABLE 0xaf | ||
| 113 | #define MT9V032_AEC_ENABLE (1 << 0) | ||
| 114 | #define MT9V032_AGC_ENABLE (1 << 1) | ||
| 115 | #define MT9V032_THERMAL_INFO 0xc1 | ||
| 116 | |||
| 117 | struct mt9v032 { | ||
| 118 | struct v4l2_subdev subdev; | ||
| 119 | struct media_pad pad; | ||
| 120 | |||
| 121 | struct v4l2_mbus_framefmt format; | ||
| 122 | struct v4l2_rect crop; | ||
| 123 | |||
| 124 | struct v4l2_ctrl_handler ctrls; | ||
| 125 | |||
| 126 | struct mutex power_lock; | ||
| 127 | int power_count; | ||
| 128 | |||
| 129 | struct mt9v032_platform_data *pdata; | ||
| 130 | u16 chip_control; | ||
| 131 | u16 aec_agc; | ||
| 132 | }; | ||
| 133 | |||
| 134 | static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd) | ||
| 135 | { | ||
| 136 | return container_of(sd, struct mt9v032, subdev); | ||
| 137 | } | ||
| 138 | |||
| 139 | static int mt9v032_read(struct i2c_client *client, const u8 reg) | ||
| 140 | { | ||
| 141 | s32 data = i2c_smbus_read_word_data(client, reg); | ||
| 142 | dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__, | ||
| 143 | swab16(data), reg); | ||
| 144 | return data < 0 ? data : swab16(data); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int mt9v032_write(struct i2c_client *client, const u8 reg, | ||
| 148 | const u16 data) | ||
| 149 | { | ||
| 150 | dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__, | ||
| 151 | data, reg); | ||
| 152 | return i2c_smbus_write_word_data(client, reg, swab16(data)); | ||
| 153 | } | ||
| 154 | |||
| 155 | static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set) | ||
| 156 | { | ||
| 157 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
| 158 | u16 value = (mt9v032->chip_control & ~clear) | set; | ||
| 159 | int ret; | ||
| 160 | |||
| 161 | ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value); | ||
| 162 | if (ret < 0) | ||
| 163 | return ret; | ||
| 164 | |||
| 165 | mt9v032->chip_control = value; | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int | ||
| 170 | mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable) | ||
| 171 | { | ||
| 172 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
| 173 | u16 value = mt9v032->aec_agc; | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | if (enable) | ||
| 177 | value |= which; | ||
| 178 | else | ||
| 179 | value &= ~which; | ||
| 180 | |||
| 181 | ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value); | ||
| 182 | if (ret < 0) | ||
| 183 | return ret; | ||
| 184 | |||
| 185 | mt9v032->aec_agc = value; | ||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | static int mt9v032_power_on(struct mt9v032 *mt9v032) | ||
| 190 | { | ||
| 191 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
| 192 | int ret; | ||
| 193 | |||
| 194 | if (mt9v032->pdata->set_clock) { | ||
| 195 | mt9v032->pdata->set_clock(&mt9v032->subdev, 25000000); | ||
| 196 | udelay(1); | ||
| 197 | } | ||
| 198 | |||
| 199 | /* Reset the chip and stop data read out */ | ||
| 200 | ret = mt9v032_write(client, MT9V032_RESET, 1); | ||
| 201 | if (ret < 0) | ||
| 202 | return ret; | ||
| 203 | |||
| 204 | ret = mt9v032_write(client, MT9V032_RESET, 0); | ||
| 205 | if (ret < 0) | ||
| 206 | return ret; | ||
| 207 | |||
| 208 | return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0); | ||
| 209 | } | ||
| 210 | |||
| 211 | static void mt9v032_power_off(struct mt9v032 *mt9v032) | ||
| 212 | { | ||
| 213 | if (mt9v032->pdata->set_clock) | ||
| 214 | mt9v032->pdata->set_clock(&mt9v032->subdev, 0); | ||
| 215 | } | ||
| 216 | |||
| 217 | static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) | ||
| 218 | { | ||
| 219 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
| 220 | int ret; | ||
| 221 | |||
| 222 | if (!on) { | ||
| 223 | mt9v032_power_off(mt9v032); | ||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | ret = mt9v032_power_on(mt9v032); | ||
| 228 | if (ret < 0) | ||
| 229 | return ret; | ||
| 230 | |||
| 231 | /* Configure the pixel clock polarity */ | ||
| 232 | if (mt9v032->pdata && mt9v032->pdata->clk_pol) { | ||
| 233 | ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK, | ||
| 234 | MT9V032_PIXEL_CLOCK_INV_PXL_CLK); | ||
| 235 | if (ret < 0) | ||
| 236 | return ret; | ||
| 237 | } | ||
| 238 | |||
| 239 | /* Disable the noise correction algorithm and restore the controls. */ | ||
| 240 | ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0); | ||
| 241 | if (ret < 0) | ||
| 242 | return ret; | ||
| 243 | |||
| 244 | return v4l2_ctrl_handler_setup(&mt9v032->ctrls); | ||
| 245 | } | ||
| 246 | |||
| 247 | /* ----------------------------------------------------------------------------- | ||
| 248 | * V4L2 subdev video operations | ||
| 249 | */ | ||
| 250 | |||
| 251 | static struct v4l2_mbus_framefmt * | ||
| 252 | __mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh, | ||
| 253 | unsigned int pad, enum v4l2_subdev_format_whence which) | ||
| 254 | { | ||
| 255 | switch (which) { | ||
| 256 | case V4L2_SUBDEV_FORMAT_TRY: | ||
| 257 | return v4l2_subdev_get_try_format(fh, pad); | ||
| 258 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
| 259 | return &mt9v032->format; | ||
| 260 | default: | ||
| 261 | return NULL; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | static struct v4l2_rect * | ||
| 266 | __mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh, | ||
| 267 | unsigned int pad, enum v4l2_subdev_format_whence which) | ||
| 268 | { | ||
| 269 | switch (which) { | ||
| 270 | case V4L2_SUBDEV_FORMAT_TRY: | ||
| 271 | return v4l2_subdev_get_try_crop(fh, pad); | ||
| 272 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
| 273 | return &mt9v032->crop; | ||
| 274 | default: | ||
| 275 | return NULL; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable) | ||
| 280 | { | ||
| 281 | const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE | ||
| 282 | | MT9V032_CHIP_CONTROL_DOUT_ENABLE | ||
| 283 | | MT9V032_CHIP_CONTROL_SEQUENTIAL; | ||
| 284 | struct i2c_client *client = v4l2_get_subdevdata(subdev); | ||
| 285 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 286 | struct v4l2_mbus_framefmt *format = &mt9v032->format; | ||
| 287 | struct v4l2_rect *crop = &mt9v032->crop; | ||
| 288 | unsigned int hratio; | ||
| 289 | unsigned int vratio; | ||
| 290 | int ret; | ||
| 291 | |||
| 292 | if (!enable) | ||
| 293 | return mt9v032_set_chip_control(mt9v032, mode, 0); | ||
| 294 | |||
| 295 | /* Configure the window size and row/column bin */ | ||
| 296 | hratio = DIV_ROUND_CLOSEST(crop->width, format->width); | ||
| 297 | vratio = DIV_ROUND_CLOSEST(crop->height, format->height); | ||
| 298 | |||
| 299 | ret = mt9v032_write(client, MT9V032_READ_MODE, | ||
| 300 | (hratio - 1) << MT9V032_READ_MODE_ROW_BIN_SHIFT | | ||
| 301 | (vratio - 1) << MT9V032_READ_MODE_COLUMN_BIN_SHIFT); | ||
| 302 | if (ret < 0) | ||
| 303 | return ret; | ||
| 304 | |||
| 305 | ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left); | ||
| 306 | if (ret < 0) | ||
| 307 | return ret; | ||
| 308 | |||
| 309 | ret = mt9v032_write(client, MT9V032_ROW_START, crop->top); | ||
| 310 | if (ret < 0) | ||
| 311 | return ret; | ||
| 312 | |||
| 313 | ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width); | ||
| 314 | if (ret < 0) | ||
| 315 | return ret; | ||
| 316 | |||
| 317 | ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height); | ||
| 318 | if (ret < 0) | ||
| 319 | return ret; | ||
| 320 | |||
| 321 | ret = mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, | ||
| 322 | max(43, 660 - crop->width)); | ||
| 323 | if (ret < 0) | ||
| 324 | return ret; | ||
| 325 | |||
| 326 | /* Switch to master "normal" mode */ | ||
| 327 | return mt9v032_set_chip_control(mt9v032, 0, mode); | ||
| 328 | } | ||
| 329 | |||
| 330 | static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, | ||
| 331 | struct v4l2_subdev_fh *fh, | ||
| 332 | struct v4l2_subdev_mbus_code_enum *code) | ||
| 333 | { | ||
| 334 | if (code->index > 0) | ||
| 335 | return -EINVAL; | ||
| 336 | |||
| 337 | code->code = V4L2_MBUS_FMT_SGRBG10_1X10; | ||
| 338 | return 0; | ||
| 339 | } | ||
| 340 | |||
| 341 | static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, | ||
| 342 | struct v4l2_subdev_fh *fh, | ||
| 343 | struct v4l2_subdev_frame_size_enum *fse) | ||
| 344 | { | ||
| 345 | if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10) | ||
| 346 | return -EINVAL; | ||
| 347 | |||
| 348 | fse->min_width = MT9V032_WINDOW_WIDTH_DEF / fse->index; | ||
| 349 | fse->max_width = fse->min_width; | ||
| 350 | fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / fse->index; | ||
| 351 | fse->max_height = fse->min_height; | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | static int mt9v032_get_format(struct v4l2_subdev *subdev, | ||
| 357 | struct v4l2_subdev_fh *fh, | ||
| 358 | struct v4l2_subdev_format *format) | ||
| 359 | { | ||
| 360 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 361 | |||
| 362 | format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad, | ||
| 363 | format->which); | ||
| 364 | return 0; | ||
| 365 | } | ||
| 366 | |||
| 367 | static int mt9v032_set_format(struct v4l2_subdev *subdev, | ||
| 368 | struct v4l2_subdev_fh *fh, | ||
| 369 | struct v4l2_subdev_format *format) | ||
| 370 | { | ||
| 371 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 372 | struct v4l2_mbus_framefmt *__format; | ||
| 373 | struct v4l2_rect *__crop; | ||
| 374 | unsigned int width; | ||
| 375 | unsigned int height; | ||
| 376 | unsigned int hratio; | ||
| 377 | unsigned int vratio; | ||
| 378 | |||
| 379 | __crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad, | ||
| 380 | format->which); | ||
| 381 | |||
| 382 | /* Clamp the width and height to avoid dividing by zero. */ | ||
| 383 | width = clamp_t(unsigned int, ALIGN(format->format.width, 2), | ||
| 384 | max(__crop->width / 8, MT9V032_WINDOW_WIDTH_MIN), | ||
| 385 | __crop->width); | ||
| 386 | height = clamp_t(unsigned int, ALIGN(format->format.height, 2), | ||
| 387 | max(__crop->height / 8, MT9V032_WINDOW_HEIGHT_MIN), | ||
| 388 | __crop->height); | ||
| 389 | |||
| 390 | hratio = DIV_ROUND_CLOSEST(__crop->width, width); | ||
| 391 | vratio = DIV_ROUND_CLOSEST(__crop->height, height); | ||
| 392 | |||
| 393 | __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad, | ||
| 394 | format->which); | ||
| 395 | __format->width = __crop->width / hratio; | ||
| 396 | __format->height = __crop->height / vratio; | ||
| 397 | |||
| 398 | format->format = *__format; | ||
| 399 | |||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int mt9v032_get_crop(struct v4l2_subdev *subdev, | ||
| 404 | struct v4l2_subdev_fh *fh, | ||
| 405 | struct v4l2_subdev_crop *crop) | ||
| 406 | { | ||
| 407 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 408 | |||
| 409 | crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad, | ||
| 410 | crop->which); | ||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | |||
| 414 | static int mt9v032_set_crop(struct v4l2_subdev *subdev, | ||
| 415 | struct v4l2_subdev_fh *fh, | ||
| 416 | struct v4l2_subdev_crop *crop) | ||
| 417 | { | ||
| 418 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 419 | struct v4l2_mbus_framefmt *__format; | ||
| 420 | struct v4l2_rect *__crop; | ||
| 421 | struct v4l2_rect rect; | ||
| 422 | |||
| 423 | /* Clamp the crop rectangle boundaries and align them to a multiple of 2 | ||
| 424 | * pixels. | ||
| 425 | */ | ||
| 426 | rect.left = clamp(ALIGN(crop->rect.left, 2), | ||
| 427 | MT9V032_COLUMN_START_MIN, | ||
| 428 | MT9V032_COLUMN_START_MAX); | ||
| 429 | rect.top = clamp(ALIGN(crop->rect.top, 2), | ||
| 430 | MT9V032_ROW_START_MIN, | ||
| 431 | MT9V032_ROW_START_MAX); | ||
| 432 | rect.width = clamp(ALIGN(crop->rect.width, 2), | ||
| 433 | MT9V032_WINDOW_WIDTH_MIN, | ||
| 434 | MT9V032_WINDOW_WIDTH_MAX); | ||
| 435 | rect.height = clamp(ALIGN(crop->rect.height, 2), | ||
| 436 | MT9V032_WINDOW_HEIGHT_MIN, | ||
| 437 | MT9V032_WINDOW_HEIGHT_MAX); | ||
| 438 | |||
| 439 | rect.width = min(rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left); | ||
| 440 | rect.height = min(rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top); | ||
| 441 | |||
| 442 | __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which); | ||
| 443 | |||
| 444 | if (rect.width != __crop->width || rect.height != __crop->height) { | ||
| 445 | /* Reset the output image size if the crop rectangle size has | ||
| 446 | * been modified. | ||
| 447 | */ | ||
| 448 | __format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad, | ||
| 449 | crop->which); | ||
| 450 | __format->width = rect.width; | ||
| 451 | __format->height = rect.height; | ||
| 452 | } | ||
| 453 | |||
| 454 | *__crop = rect; | ||
| 455 | crop->rect = rect; | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | |||
| 460 | /* ----------------------------------------------------------------------------- | ||
| 461 | * V4L2 subdev control operations | ||
| 462 | */ | ||
| 463 | |||
| 464 | #define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001) | ||
| 465 | |||
| 466 | static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 467 | { | ||
| 468 | struct mt9v032 *mt9v032 = | ||
| 469 | container_of(ctrl->handler, struct mt9v032, ctrls); | ||
| 470 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
| 471 | u16 data; | ||
| 472 | |||
| 473 | switch (ctrl->id) { | ||
| 474 | case V4L2_CID_AUTOGAIN: | ||
| 475 | return mt9v032_update_aec_agc(mt9v032, MT9V032_AGC_ENABLE, | ||
| 476 | ctrl->val); | ||
| 477 | |||
| 478 | case V4L2_CID_GAIN: | ||
| 479 | return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val); | ||
| 480 | |||
| 481 | case V4L2_CID_EXPOSURE_AUTO: | ||
| 482 | return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE, | ||
| 483 | ctrl->val); | ||
| 484 | |||
| 485 | case V4L2_CID_EXPOSURE: | ||
| 486 | return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH, | ||
| 487 | ctrl->val); | ||
| 488 | |||
| 489 | case V4L2_CID_TEST_PATTERN: | ||
| 490 | switch (ctrl->val) { | ||
| 491 | case 0: | ||
| 492 | data = 0; | ||
| 493 | break; | ||
| 494 | case 1: | ||
| 495 | data = MT9V032_TEST_PATTERN_GRAY_VERTICAL | ||
| 496 | | MT9V032_TEST_PATTERN_ENABLE; | ||
| 497 | break; | ||
| 498 | case 2: | ||
| 499 | data = MT9V032_TEST_PATTERN_GRAY_HORIZONTAL | ||
| 500 | | MT9V032_TEST_PATTERN_ENABLE; | ||
| 501 | break; | ||
| 502 | case 3: | ||
| 503 | data = MT9V032_TEST_PATTERN_GRAY_DIAGONAL | ||
| 504 | | MT9V032_TEST_PATTERN_ENABLE; | ||
| 505 | break; | ||
| 506 | default: | ||
| 507 | data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT) | ||
| 508 | | MT9V032_TEST_PATTERN_USE_DATA | ||
| 509 | | MT9V032_TEST_PATTERN_ENABLE | ||
| 510 | | MT9V032_TEST_PATTERN_FLIP; | ||
| 511 | break; | ||
| 512 | } | ||
| 513 | |||
| 514 | return mt9v032_write(client, MT9V032_TEST_PATTERN, data); | ||
| 515 | } | ||
| 516 | |||
| 517 | return 0; | ||
| 518 | } | ||
| 519 | |||
| 520 | static struct v4l2_ctrl_ops mt9v032_ctrl_ops = { | ||
| 521 | .s_ctrl = mt9v032_s_ctrl, | ||
| 522 | }; | ||
| 523 | |||
| 524 | static const struct v4l2_ctrl_config mt9v032_ctrls[] = { | ||
| 525 | { | ||
| 526 | .ops = &mt9v032_ctrl_ops, | ||
| 527 | .id = V4L2_CID_TEST_PATTERN, | ||
| 528 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 529 | .name = "Test pattern", | ||
| 530 | .min = 0, | ||
| 531 | .max = 1023, | ||
| 532 | .step = 1, | ||
| 533 | .def = 0, | ||
| 534 | .flags = 0, | ||
| 535 | } | ||
| 536 | }; | ||
| 537 | |||
| 538 | /* ----------------------------------------------------------------------------- | ||
| 539 | * V4L2 subdev core operations | ||
| 540 | */ | ||
| 541 | |||
| 542 | static int mt9v032_set_power(struct v4l2_subdev *subdev, int on) | ||
| 543 | { | ||
| 544 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 545 | int ret = 0; | ||
| 546 | |||
| 547 | mutex_lock(&mt9v032->power_lock); | ||
| 548 | |||
| 549 | /* If the power count is modified from 0 to != 0 or from != 0 to 0, | ||
| 550 | * update the power state. | ||
| 551 | */ | ||
| 552 | if (mt9v032->power_count == !on) { | ||
| 553 | ret = __mt9v032_set_power(mt9v032, !!on); | ||
| 554 | if (ret < 0) | ||
| 555 | goto done; | ||
| 556 | } | ||
| 557 | |||
| 558 | /* Update the power count. */ | ||
| 559 | mt9v032->power_count += on ? 1 : -1; | ||
| 560 | WARN_ON(mt9v032->power_count < 0); | ||
| 561 | |||
| 562 | done: | ||
| 563 | mutex_unlock(&mt9v032->power_lock); | ||
| 564 | return ret; | ||
| 565 | } | ||
| 566 | |||
| 567 | /* ----------------------------------------------------------------------------- | ||
| 568 | * V4L2 subdev internal operations | ||
| 569 | */ | ||
| 570 | |||
| 571 | static int mt9v032_registered(struct v4l2_subdev *subdev) | ||
| 572 | { | ||
| 573 | struct i2c_client *client = v4l2_get_subdevdata(subdev); | ||
| 574 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 575 | s32 data; | ||
| 576 | int ret; | ||
| 577 | |||
| 578 | dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", | ||
| 579 | client->addr); | ||
| 580 | |||
| 581 | ret = mt9v032_power_on(mt9v032); | ||
| 582 | if (ret < 0) { | ||
| 583 | dev_err(&client->dev, "MT9V032 power up failed\n"); | ||
| 584 | return ret; | ||
| 585 | } | ||
| 586 | |||
| 587 | /* Read and check the sensor version */ | ||
| 588 | data = mt9v032_read(client, MT9V032_CHIP_VERSION); | ||
| 589 | if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) { | ||
| 590 | dev_err(&client->dev, "MT9V032 not detected, wrong version " | ||
| 591 | "0x%04x\n", data); | ||
| 592 | return -ENODEV; | ||
| 593 | } | ||
| 594 | |||
| 595 | mt9v032_power_off(mt9v032); | ||
| 596 | |||
| 597 | dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n", | ||
| 598 | client->addr); | ||
| 599 | |||
| 600 | return ret; | ||
| 601 | } | ||
| 602 | |||
| 603 | static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) | ||
| 604 | { | ||
| 605 | struct v4l2_mbus_framefmt *format; | ||
| 606 | struct v4l2_rect *crop; | ||
| 607 | |||
| 608 | crop = v4l2_subdev_get_try_crop(fh, 0); | ||
| 609 | crop->left = MT9V032_COLUMN_START_DEF; | ||
| 610 | crop->top = MT9V032_ROW_START_DEF; | ||
| 611 | crop->width = MT9V032_WINDOW_WIDTH_DEF; | ||
| 612 | crop->height = MT9V032_WINDOW_HEIGHT_DEF; | ||
| 613 | |||
| 614 | format = v4l2_subdev_get_try_format(fh, 0); | ||
| 615 | format->code = V4L2_MBUS_FMT_SGRBG10_1X10; | ||
| 616 | format->width = MT9V032_WINDOW_WIDTH_DEF; | ||
| 617 | format->height = MT9V032_WINDOW_HEIGHT_DEF; | ||
| 618 | format->field = V4L2_FIELD_NONE; | ||
| 619 | format->colorspace = V4L2_COLORSPACE_SRGB; | ||
| 620 | |||
| 621 | return mt9v032_set_power(subdev, 1); | ||
| 622 | } | ||
| 623 | |||
| 624 | static int mt9v032_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) | ||
| 625 | { | ||
| 626 | return mt9v032_set_power(subdev, 0); | ||
| 627 | } | ||
| 628 | |||
| 629 | static struct v4l2_subdev_core_ops mt9v032_subdev_core_ops = { | ||
| 630 | .s_power = mt9v032_set_power, | ||
| 631 | }; | ||
| 632 | |||
| 633 | static struct v4l2_subdev_video_ops mt9v032_subdev_video_ops = { | ||
| 634 | .s_stream = mt9v032_s_stream, | ||
| 635 | }; | ||
| 636 | |||
| 637 | static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = { | ||
| 638 | .enum_mbus_code = mt9v032_enum_mbus_code, | ||
| 639 | .enum_frame_size = mt9v032_enum_frame_size, | ||
| 640 | .get_fmt = mt9v032_get_format, | ||
| 641 | .set_fmt = mt9v032_set_format, | ||
| 642 | .get_crop = mt9v032_get_crop, | ||
| 643 | .set_crop = mt9v032_set_crop, | ||
| 644 | }; | ||
| 645 | |||
| 646 | static struct v4l2_subdev_ops mt9v032_subdev_ops = { | ||
| 647 | .core = &mt9v032_subdev_core_ops, | ||
| 648 | .video = &mt9v032_subdev_video_ops, | ||
| 649 | .pad = &mt9v032_subdev_pad_ops, | ||
| 650 | }; | ||
| 651 | |||
| 652 | static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = { | ||
| 653 | .registered = mt9v032_registered, | ||
| 654 | .open = mt9v032_open, | ||
| 655 | .close = mt9v032_close, | ||
| 656 | }; | ||
| 657 | |||
| 658 | /* ----------------------------------------------------------------------------- | ||
| 659 | * Driver initialization and probing | ||
| 660 | */ | ||
| 661 | |||
| 662 | static int mt9v032_probe(struct i2c_client *client, | ||
| 663 | const struct i2c_device_id *did) | ||
| 664 | { | ||
| 665 | struct mt9v032 *mt9v032; | ||
| 666 | unsigned int i; | ||
| 667 | int ret; | ||
| 668 | |||
| 669 | if (!i2c_check_functionality(client->adapter, | ||
| 670 | I2C_FUNC_SMBUS_WORD_DATA)) { | ||
| 671 | dev_warn(&client->adapter->dev, | ||
| 672 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
| 673 | return -EIO; | ||
| 674 | } | ||
| 675 | |||
| 676 | mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL); | ||
| 677 | if (!mt9v032) | ||
| 678 | return -ENOMEM; | ||
| 679 | |||
| 680 | mutex_init(&mt9v032->power_lock); | ||
| 681 | mt9v032->pdata = client->dev.platform_data; | ||
| 682 | |||
| 683 | v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 4); | ||
| 684 | |||
| 685 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
| 686 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
| 687 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
| 688 | V4L2_CID_GAIN, MT9V032_ANALOG_GAIN_MIN, | ||
| 689 | MT9V032_ANALOG_GAIN_MAX, 1, MT9V032_ANALOG_GAIN_DEF); | ||
| 690 | v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
| 691 | V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0, | ||
| 692 | V4L2_EXPOSURE_AUTO); | ||
| 693 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
| 694 | V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN, | ||
| 695 | MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1, | ||
| 696 | MT9V032_TOTAL_SHUTTER_WIDTH_DEF); | ||
| 697 | |||
| 698 | for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i) | ||
| 699 | v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL); | ||
| 700 | |||
| 701 | mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; | ||
| 702 | |||
| 703 | if (mt9v032->ctrls.error) | ||
| 704 | printk(KERN_INFO "%s: control initialization error %d\n", | ||
| 705 | __func__, mt9v032->ctrls.error); | ||
| 706 | |||
| 707 | mt9v032->crop.left = MT9V032_COLUMN_START_DEF; | ||
| 708 | mt9v032->crop.top = MT9V032_ROW_START_DEF; | ||
| 709 | mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF; | ||
| 710 | mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF; | ||
| 711 | |||
| 712 | mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10; | ||
| 713 | mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF; | ||
| 714 | mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF; | ||
| 715 | mt9v032->format.field = V4L2_FIELD_NONE; | ||
| 716 | mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; | ||
| 717 | |||
| 718 | mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; | ||
| 719 | |||
| 720 | v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops); | ||
| 721 | mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops; | ||
| 722 | mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 723 | |||
| 724 | mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
| 725 | ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); | ||
| 726 | if (ret < 0) | ||
| 727 | kfree(mt9v032); | ||
| 728 | |||
| 729 | return ret; | ||
| 730 | } | ||
| 731 | |||
| 732 | static int mt9v032_remove(struct i2c_client *client) | ||
| 733 | { | ||
| 734 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
| 735 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
| 736 | |||
| 737 | v4l2_device_unregister_subdev(subdev); | ||
| 738 | media_entity_cleanup(&subdev->entity); | ||
| 739 | kfree(mt9v032); | ||
| 740 | return 0; | ||
| 741 | } | ||
| 742 | |||
| 743 | static const struct i2c_device_id mt9v032_id[] = { | ||
| 744 | { "mt9v032", 0 }, | ||
| 745 | { } | ||
| 746 | }; | ||
| 747 | MODULE_DEVICE_TABLE(i2c, mt9v032_id); | ||
| 748 | |||
| 749 | static struct i2c_driver mt9v032_driver = { | ||
| 750 | .driver = { | ||
| 751 | .name = "mt9v032", | ||
| 752 | }, | ||
| 753 | .probe = mt9v032_probe, | ||
| 754 | .remove = mt9v032_remove, | ||
| 755 | .id_table = mt9v032_id, | ||
| 756 | }; | ||
| 757 | |||
| 758 | static int __init mt9v032_init(void) | ||
| 759 | { | ||
| 760 | return i2c_add_driver(&mt9v032_driver); | ||
| 761 | } | ||
| 762 | |||
| 763 | static void __exit mt9v032_exit(void) | ||
| 764 | { | ||
| 765 | i2c_del_driver(&mt9v032_driver); | ||
| 766 | } | ||
| 767 | |||
| 768 | module_init(mt9v032_init); | ||
| 769 | module_exit(mt9v032_exit); | ||
| 770 | |||
| 771 | MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); | ||
| 772 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
| 773 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 502e2a40964c..c7680eb83664 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
| @@ -400,6 +400,35 @@ static int mx3_videobuf_init(struct vb2_buffer *vb) | |||
| 400 | return 0; | 400 | return 0; |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | static int mx3_stop_streaming(struct vb2_queue *q) | ||
| 404 | { | ||
| 405 | struct soc_camera_device *icd = soc_camera_from_vb2q(q); | ||
| 406 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
| 407 | struct mx3_camera_dev *mx3_cam = ici->priv; | ||
| 408 | struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; | ||
| 409 | struct dma_chan *chan; | ||
| 410 | struct mx3_camera_buffer *buf, *tmp; | ||
| 411 | unsigned long flags; | ||
| 412 | |||
| 413 | if (ichan) { | ||
| 414 | chan = &ichan->dma_chan; | ||
| 415 | chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); | ||
| 416 | } | ||
| 417 | |||
| 418 | spin_lock_irqsave(&mx3_cam->lock, flags); | ||
| 419 | |||
| 420 | mx3_cam->active = NULL; | ||
| 421 | |||
| 422 | list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) { | ||
| 423 | buf->state = CSI_BUF_NEEDS_INIT; | ||
| 424 | list_del_init(&buf->queue); | ||
| 425 | } | ||
| 426 | |||
| 427 | spin_unlock_irqrestore(&mx3_cam->lock, flags); | ||
| 428 | |||
| 429 | return 0; | ||
| 430 | } | ||
| 431 | |||
| 403 | static struct vb2_ops mx3_videobuf_ops = { | 432 | static struct vb2_ops mx3_videobuf_ops = { |
| 404 | .queue_setup = mx3_videobuf_setup, | 433 | .queue_setup = mx3_videobuf_setup, |
| 405 | .buf_prepare = mx3_videobuf_prepare, | 434 | .buf_prepare = mx3_videobuf_prepare, |
| @@ -408,6 +437,7 @@ static struct vb2_ops mx3_videobuf_ops = { | |||
| 408 | .buf_init = mx3_videobuf_init, | 437 | .buf_init = mx3_videobuf_init, |
| 409 | .wait_prepare = soc_camera_unlock, | 438 | .wait_prepare = soc_camera_unlock, |
| 410 | .wait_finish = soc_camera_lock, | 439 | .wait_finish = soc_camera_lock, |
| 440 | .stop_streaming = mx3_stop_streaming, | ||
| 411 | }; | 441 | }; |
| 412 | 442 | ||
| 413 | static int mx3_camera_init_videobuf(struct vb2_queue *q, | 443 | static int mx3_camera_init_videobuf(struct vb2_queue *q, |
| @@ -658,8 +688,8 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
| 658 | 688 | ||
| 659 | fmt = soc_mbus_get_fmtdesc(code); | 689 | fmt = soc_mbus_get_fmtdesc(code); |
| 660 | if (!fmt) { | 690 | if (!fmt) { |
| 661 | dev_err(icd->dev.parent, | 691 | dev_warn(icd->dev.parent, |
| 662 | "Invalid format code #%u: %d\n", idx, code); | 692 | "Unsupported format code #%u: %d\n", idx, code); |
| 663 | return 0; | 693 | return 0; |
| 664 | } | 694 | } |
| 665 | 695 | ||
| @@ -712,13 +742,9 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
| 712 | 742 | ||
| 713 | static void configure_geometry(struct mx3_camera_dev *mx3_cam, | 743 | static void configure_geometry(struct mx3_camera_dev *mx3_cam, |
| 714 | unsigned int width, unsigned int height, | 744 | unsigned int width, unsigned int height, |
| 715 | enum v4l2_mbus_pixelcode code) | 745 | const struct soc_mbus_pixelfmt *fmt) |
| 716 | { | 746 | { |
| 717 | u32 ctrl, width_field, height_field; | 747 | u32 ctrl, width_field, height_field; |
| 718 | const struct soc_mbus_pixelfmt *fmt; | ||
| 719 | |||
| 720 | fmt = soc_mbus_get_fmtdesc(code); | ||
| 721 | BUG_ON(!fmt); | ||
| 722 | 748 | ||
| 723 | if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) { | 749 | if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) { |
| 724 | /* | 750 | /* |
| @@ -726,8 +752,10 @@ static void configure_geometry(struct mx3_camera_dev *mx3_cam, | |||
| 726 | * the width parameter count the number of samples to | 752 | * the width parameter count the number of samples to |
| 727 | * capture to complete the whole image width. | 753 | * capture to complete the whole image width. |
| 728 | */ | 754 | */ |
| 729 | width *= soc_mbus_samples_per_pixel(fmt); | 755 | unsigned int num, den; |
| 730 | BUG_ON(width < 0); | 756 | int ret = soc_mbus_samples_per_pixel(fmt, &num, &den); |
| 757 | BUG_ON(ret < 0); | ||
| 758 | width = width * num / den; | ||
| 731 | } | 759 | } |
| 732 | 760 | ||
| 733 | /* Setup frame size - this cannot be changed on-the-fly... */ | 761 | /* Setup frame size - this cannot be changed on-the-fly... */ |
| @@ -774,8 +802,8 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) | |||
| 774 | */ | 802 | */ |
| 775 | static inline void stride_align(__u32 *width) | 803 | static inline void stride_align(__u32 *width) |
| 776 | { | 804 | { |
| 777 | if (((*width + 7) & ~7) < 4096) | 805 | if (ALIGN(*width, 8) < 4096) |
| 778 | *width = (*width + 7) & ~7; | 806 | *width = ALIGN(*width, 8); |
| 779 | else | 807 | else |
| 780 | *width = *width & ~7; | 808 | *width = *width & ~7; |
| 781 | } | 809 | } |
| @@ -801,11 +829,14 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
| 801 | if (ret < 0) | 829 | if (ret < 0) |
| 802 | return ret; | 830 | return ret; |
| 803 | 831 | ||
| 804 | /* The capture device might have changed its output */ | 832 | /* The capture device might have changed its output sizes */ |
| 805 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | 833 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
| 806 | if (ret < 0) | 834 | if (ret < 0) |
| 807 | return ret; | 835 | return ret; |
| 808 | 836 | ||
| 837 | if (mf.code != icd->current_fmt->code) | ||
| 838 | return -EINVAL; | ||
| 839 | |||
| 809 | if (mf.width & 7) { | 840 | if (mf.width & 7) { |
| 810 | /* Ouch! We can only handle 8-byte aligned width... */ | 841 | /* Ouch! We can only handle 8-byte aligned width... */ |
| 811 | stride_align(&mf.width); | 842 | stride_align(&mf.width); |
| @@ -815,7 +846,8 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
| 815 | } | 846 | } |
| 816 | 847 | ||
| 817 | if (mf.width != icd->user_width || mf.height != icd->user_height) | 848 | if (mf.width != icd->user_width || mf.height != icd->user_height) |
| 818 | configure_geometry(mx3_cam, mf.width, mf.height, mf.code); | 849 | configure_geometry(mx3_cam, mf.width, mf.height, |
| 850 | icd->current_fmt->host_fmt); | ||
| 819 | 851 | ||
| 820 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", | 852 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", |
| 821 | mf.width, mf.height); | 853 | mf.width, mf.height); |
| @@ -853,7 +885,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
| 853 | * mxc_v4l2_s_fmt() | 885 | * mxc_v4l2_s_fmt() |
| 854 | */ | 886 | */ |
| 855 | 887 | ||
| 856 | configure_geometry(mx3_cam, pix->width, pix->height, xlate->code); | 888 | configure_geometry(mx3_cam, pix->width, pix->height, xlate->host_fmt); |
| 857 | 889 | ||
| 858 | mf.width = pix->width; | 890 | mf.width = pix->width; |
| 859 | mf.height = pix->height; | 891 | mf.height = pix->height; |
diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c index 5954b9306630..e7cfc85b0a1c 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/video/omap1_camera.c | |||
| @@ -990,63 +990,80 @@ static void omap1_cam_remove_device(struct soc_camera_device *icd) | |||
| 990 | } | 990 | } |
| 991 | 991 | ||
| 992 | /* Duplicate standard formats based on host capability of byte swapping */ | 992 | /* Duplicate standard formats based on host capability of byte swapping */ |
| 993 | static const struct soc_mbus_pixelfmt omap1_cam_formats[] = { | 993 | static const struct soc_mbus_lookup omap1_cam_formats[] = { |
| 994 | [V4L2_MBUS_FMT_UYVY8_2X8] = { | 994 | { |
| 995 | .code = V4L2_MBUS_FMT_UYVY8_2X8, | ||
| 996 | .fmt = { | ||
| 995 | .fourcc = V4L2_PIX_FMT_YUYV, | 997 | .fourcc = V4L2_PIX_FMT_YUYV, |
| 996 | .name = "YUYV", | 998 | .name = "YUYV", |
| 997 | .bits_per_sample = 8, | 999 | .bits_per_sample = 8, |
| 998 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1000 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 999 | .order = SOC_MBUS_ORDER_BE, | 1001 | .order = SOC_MBUS_ORDER_BE, |
| 1000 | }, | 1002 | }, |
| 1001 | [V4L2_MBUS_FMT_VYUY8_2X8] = { | 1003 | }, { |
| 1004 | .code = V4L2_MBUS_FMT_VYUY8_2X8, | ||
| 1005 | .fmt = { | ||
| 1002 | .fourcc = V4L2_PIX_FMT_YVYU, | 1006 | .fourcc = V4L2_PIX_FMT_YVYU, |
| 1003 | .name = "YVYU", | 1007 | .name = "YVYU", |
| 1004 | .bits_per_sample = 8, | 1008 | .bits_per_sample = 8, |
| 1005 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1009 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 1006 | .order = SOC_MBUS_ORDER_BE, | 1010 | .order = SOC_MBUS_ORDER_BE, |
| 1007 | }, | 1011 | }, |
| 1008 | [V4L2_MBUS_FMT_YUYV8_2X8] = { | 1012 | }, { |
| 1013 | .code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
| 1014 | .fmt = { | ||
| 1009 | .fourcc = V4L2_PIX_FMT_UYVY, | 1015 | .fourcc = V4L2_PIX_FMT_UYVY, |
| 1010 | .name = "UYVY", | 1016 | .name = "UYVY", |
| 1011 | .bits_per_sample = 8, | 1017 | .bits_per_sample = 8, |
| 1012 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1018 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 1013 | .order = SOC_MBUS_ORDER_BE, | 1019 | .order = SOC_MBUS_ORDER_BE, |
| 1014 | }, | 1020 | }, |
| 1015 | [V4L2_MBUS_FMT_YVYU8_2X8] = { | 1021 | }, { |
| 1022 | .code = V4L2_MBUS_FMT_YVYU8_2X8, | ||
| 1023 | .fmt = { | ||
| 1016 | .fourcc = V4L2_PIX_FMT_VYUY, | 1024 | .fourcc = V4L2_PIX_FMT_VYUY, |
| 1017 | .name = "VYUY", | 1025 | .name = "VYUY", |
| 1018 | .bits_per_sample = 8, | 1026 | .bits_per_sample = 8, |
| 1019 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1027 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 1020 | .order = SOC_MBUS_ORDER_BE, | 1028 | .order = SOC_MBUS_ORDER_BE, |
| 1021 | }, | 1029 | }, |
| 1022 | [V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE] = { | 1030 | }, { |
| 1031 | .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, | ||
| 1032 | .fmt = { | ||
| 1023 | .fourcc = V4L2_PIX_FMT_RGB555, | 1033 | .fourcc = V4L2_PIX_FMT_RGB555, |
| 1024 | .name = "RGB555", | 1034 | .name = "RGB555", |
| 1025 | .bits_per_sample = 8, | 1035 | .bits_per_sample = 8, |
| 1026 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1036 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 1027 | .order = SOC_MBUS_ORDER_BE, | 1037 | .order = SOC_MBUS_ORDER_BE, |
| 1028 | }, | 1038 | }, |
| 1029 | [V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE] = { | 1039 | }, { |
| 1040 | .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, | ||
| 1041 | .fmt = { | ||
| 1030 | .fourcc = V4L2_PIX_FMT_RGB555X, | 1042 | .fourcc = V4L2_PIX_FMT_RGB555X, |
| 1031 | .name = "RGB555X", | 1043 | .name = "RGB555X", |
| 1032 | .bits_per_sample = 8, | 1044 | .bits_per_sample = 8, |
| 1033 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1045 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 1034 | .order = SOC_MBUS_ORDER_BE, | 1046 | .order = SOC_MBUS_ORDER_BE, |
| 1035 | }, | 1047 | }, |
| 1036 | [V4L2_MBUS_FMT_RGB565_2X8_BE] = { | 1048 | }, { |
| 1049 | .code = V4L2_MBUS_FMT_RGB565_2X8_BE, | ||
| 1050 | .fmt = { | ||
| 1037 | .fourcc = V4L2_PIX_FMT_RGB565, | 1051 | .fourcc = V4L2_PIX_FMT_RGB565, |
| 1038 | .name = "RGB565", | 1052 | .name = "RGB565", |
| 1039 | .bits_per_sample = 8, | 1053 | .bits_per_sample = 8, |
| 1040 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1054 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 1041 | .order = SOC_MBUS_ORDER_BE, | 1055 | .order = SOC_MBUS_ORDER_BE, |
| 1042 | }, | 1056 | }, |
| 1043 | [V4L2_MBUS_FMT_RGB565_2X8_LE] = { | 1057 | }, { |
| 1058 | .code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
| 1059 | .fmt = { | ||
| 1044 | .fourcc = V4L2_PIX_FMT_RGB565X, | 1060 | .fourcc = V4L2_PIX_FMT_RGB565X, |
| 1045 | .name = "RGB565X", | 1061 | .name = "RGB565X", |
| 1046 | .bits_per_sample = 8, | 1062 | .bits_per_sample = 8, |
| 1047 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 1063 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 1048 | .order = SOC_MBUS_ORDER_BE, | 1064 | .order = SOC_MBUS_ORDER_BE, |
| 1049 | }, | 1065 | }, |
| 1066 | }, | ||
| 1050 | }; | 1067 | }; |
| 1051 | 1068 | ||
| 1052 | static int omap1_cam_get_formats(struct soc_camera_device *icd, | 1069 | static int omap1_cam_get_formats(struct soc_camera_device *icd, |
| @@ -1065,7 +1082,7 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd, | |||
| 1065 | 1082 | ||
| 1066 | fmt = soc_mbus_get_fmtdesc(code); | 1083 | fmt = soc_mbus_get_fmtdesc(code); |
| 1067 | if (!fmt) { | 1084 | if (!fmt) { |
| 1068 | dev_err(dev, "%s: invalid format code #%d: %d\n", __func__, | 1085 | dev_warn(dev, "%s: unsupported format code #%d: %d\n", __func__, |
| 1069 | idx, code); | 1086 | idx, code); |
| 1070 | return 0; | 1087 | return 0; |
| 1071 | } | 1088 | } |
| @@ -1085,12 +1102,14 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd, | |||
| 1085 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | 1102 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
| 1086 | formats++; | 1103 | formats++; |
| 1087 | if (xlate) { | 1104 | if (xlate) { |
| 1088 | xlate->host_fmt = &omap1_cam_formats[code]; | 1105 | xlate->host_fmt = soc_mbus_find_fmtdesc(code, |
| 1106 | omap1_cam_formats, | ||
| 1107 | ARRAY_SIZE(omap1_cam_formats)); | ||
| 1089 | xlate->code = code; | 1108 | xlate->code = code; |
| 1090 | xlate++; | 1109 | xlate++; |
| 1091 | dev_dbg(dev, | 1110 | dev_dbg(dev, |
| 1092 | "%s: providing format %s as byte swapped code #%d\n", | 1111 | "%s: providing format %s as byte swapped code #%d\n", |
| 1093 | __func__, omap1_cam_formats[code].name, code); | 1112 | __func__, xlate->host_fmt->name, code); |
| 1094 | } | 1113 | } |
| 1095 | default: | 1114 | default: |
| 1096 | if (xlate) | 1115 | if (xlate) |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c index ca9f83a85ca5..453627b07833 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-std.c +++ b/drivers/media/video/pvrusb2/pvrusb2-std.c | |||
| @@ -278,12 +278,10 @@ static struct v4l2_standard generic_standards[] = { | |||
| 278 | } | 278 | } |
| 279 | }; | 279 | }; |
| 280 | 280 | ||
| 281 | #define generic_standards_cnt ARRAY_SIZE(generic_standards) | ||
| 282 | |||
| 283 | static struct v4l2_standard *match_std(v4l2_std_id id) | 281 | static struct v4l2_standard *match_std(v4l2_std_id id) |
| 284 | { | 282 | { |
| 285 | unsigned int idx; | 283 | unsigned int idx; |
| 286 | for (idx = 0; idx < generic_standards_cnt; idx++) { | 284 | for (idx = 0; idx < ARRAY_SIZE(generic_standards); idx++) { |
| 287 | if (generic_standards[idx].id & id) { | 285 | if (generic_standards[idx].id & id) { |
| 288 | return generic_standards + idx; | 286 | return generic_standards + idx; |
| 289 | } | 287 | } |
| @@ -370,7 +368,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, | |||
| 370 | 368 | ||
| 371 | stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt, | 369 | stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt, |
| 372 | GFP_KERNEL); | 370 | GFP_KERNEL); |
| 373 | for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx; | 371 | if (!stddefs) |
| 372 | return NULL; | ||
| 373 | |||
| 374 | for (idx = 0; idx < std_cnt; idx++) | ||
| 375 | stddefs[idx].index = idx; | ||
| 374 | 376 | ||
| 375 | idx = 0; | 377 | idx = 0; |
| 376 | 378 | ||
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 780af5f81642..356cd42b593b 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
| @@ -1850,7 +1850,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
| 1850 | } else { | 1850 | } else { |
| 1851 | /* Device is closed, so we can safely unregister it */ | 1851 | /* Device is closed, so we can safely unregister it */ |
| 1852 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); | 1852 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); |
| 1853 | pwc_cleanup(pdev); | ||
| 1854 | 1853 | ||
| 1855 | disconnect_out: | 1854 | disconnect_out: |
| 1856 | /* search device_hint[] table if we occupy a slot, by any chance */ | 1855 | /* search device_hint[] table if we occupy a slot, by any chance */ |
| @@ -1860,6 +1859,7 @@ disconnect_out: | |||
| 1860 | } | 1859 | } |
| 1861 | 1860 | ||
| 1862 | mutex_unlock(&pdev->modlock); | 1861 | mutex_unlock(&pdev->modlock); |
| 1862 | pwc_cleanup(pdev); | ||
| 1863 | } | 1863 | } |
| 1864 | 1864 | ||
| 1865 | 1865 | ||
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index aa87e462a958..f85c51249c7b 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
| @@ -379,8 +379,27 @@ static int pwc_s_input(struct file *file, void *fh, unsigned int i) | |||
| 379 | 379 | ||
| 380 | static int pwc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) | 380 | static int pwc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) |
| 381 | { | 381 | { |
| 382 | int i; | 382 | int i, idx; |
| 383 | 383 | u32 id; | |
| 384 | |||
| 385 | id = c->id; | ||
| 386 | if (id & V4L2_CTRL_FLAG_NEXT_CTRL) { | ||
| 387 | id &= V4L2_CTRL_ID_MASK; | ||
| 388 | id++; | ||
| 389 | idx = -1; | ||
| 390 | for (i = 0; i < ARRAY_SIZE(pwc_controls); i++) { | ||
| 391 | if (pwc_controls[i].id < id) | ||
| 392 | continue; | ||
| 393 | if (idx >= 0 | ||
| 394 | && pwc_controls[i].id > pwc_controls[idx].id) | ||
| 395 | continue; | ||
| 396 | idx = i; | ||
| 397 | } | ||
| 398 | if (idx < 0) | ||
| 399 | return -EINVAL; | ||
| 400 | memcpy(c, &pwc_controls[idx], sizeof pwc_controls[0]); | ||
| 401 | return 0; | ||
| 402 | } | ||
| 384 | for (i = 0; i < sizeof(pwc_controls) / sizeof(struct v4l2_queryctrl); i++) { | 403 | for (i = 0; i < sizeof(pwc_controls) / sizeof(struct v4l2_queryctrl); i++) { |
| 385 | if (pwc_controls[i].id == c->id) { | 404 | if (pwc_controls[i].id == c->id) { |
| 386 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n"); | 405 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n"); |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index c1ee09a043ba..b42bfa5ccdf2 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
| @@ -1155,15 +1155,11 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
| 1155 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1155 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
| 1156 | struct pxa_camera_dev *pcdev = ici->priv; | 1156 | struct pxa_camera_dev *pcdev = ici->priv; |
| 1157 | unsigned long bus_flags, camera_flags, common_flags; | 1157 | unsigned long bus_flags, camera_flags, common_flags; |
| 1158 | const struct soc_mbus_pixelfmt *fmt; | ||
| 1159 | int ret; | 1158 | int ret; |
| 1160 | struct pxa_cam *cam = icd->host_priv; | 1159 | struct pxa_cam *cam = icd->host_priv; |
| 1161 | 1160 | ||
| 1162 | fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); | 1161 | ret = test_platform_param(pcdev, icd->current_fmt->host_fmt->bits_per_sample, |
| 1163 | if (!fmt) | 1162 | &bus_flags); |
| 1164 | return -EINVAL; | ||
| 1165 | |||
| 1166 | ret = test_platform_param(pcdev, fmt->bits_per_sample, &bus_flags); | ||
| 1167 | if (ret < 0) | 1163 | if (ret < 0) |
| 1168 | return ret; | 1164 | return ret; |
| 1169 | 1165 | ||
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 561909b65ce6..5b9dce85645c 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
| @@ -394,12 +394,17 @@ static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ | |||
| 394 | /* start video number */ | 394 | /* start video number */ |
| 395 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ | 395 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ |
| 396 | 396 | ||
| 397 | /* Enable jpeg capture. */ | ||
| 398 | static int jpeg_enable = 1; | ||
| 399 | |||
| 397 | module_param(debug, int, 0644); | 400 | module_param(debug, int, 0644); |
| 398 | MODULE_PARM_DESC(debug, "Debug level(0-100) default 0"); | 401 | MODULE_PARM_DESC(debug, "Debug level(0-100) default 0"); |
| 399 | module_param(vid_limit, int, 0644); | 402 | module_param(vid_limit, int, 0644); |
| 400 | MODULE_PARM_DESC(vid_limit, "video memory limit(Mb)"); | 403 | MODULE_PARM_DESC(vid_limit, "video memory limit(Mb)"); |
| 401 | module_param(video_nr, int, 0644); | 404 | module_param(video_nr, int, 0644); |
| 402 | MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)"); | 405 | MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)"); |
| 406 | module_param(jpeg_enable, int, 0644); | ||
| 407 | MODULE_PARM_DESC(jpeg_enable, "Jpeg enable(1-on 0-off) default 1"); | ||
| 403 | 408 | ||
| 404 | /* USB device table */ | 409 | /* USB device table */ |
| 405 | #define USB_SENSORAY_VID 0x1943 | 410 | #define USB_SENSORAY_VID 0x1943 |
| @@ -413,6 +418,7 @@ MODULE_DEVICE_TABLE(usb, s2255_table); | |||
| 413 | #define BUFFER_TIMEOUT msecs_to_jiffies(400) | 418 | #define BUFFER_TIMEOUT msecs_to_jiffies(400) |
| 414 | 419 | ||
| 415 | /* image formats. */ | 420 | /* image formats. */ |
| 421 | /* JPEG formats must be defined last to support jpeg_enable parameter */ | ||
| 416 | static const struct s2255_fmt formats[] = { | 422 | static const struct s2255_fmt formats[] = { |
| 417 | { | 423 | { |
| 418 | .name = "4:2:2, planar, YUV422P", | 424 | .name = "4:2:2, planar, YUV422P", |
| @@ -429,13 +435,17 @@ static const struct s2255_fmt formats[] = { | |||
| 429 | .fourcc = V4L2_PIX_FMT_UYVY, | 435 | .fourcc = V4L2_PIX_FMT_UYVY, |
| 430 | .depth = 16 | 436 | .depth = 16 |
| 431 | }, { | 437 | }, { |
| 438 | .name = "8bpp GREY", | ||
| 439 | .fourcc = V4L2_PIX_FMT_GREY, | ||
| 440 | .depth = 8 | ||
| 441 | }, { | ||
| 432 | .name = "JPG", | 442 | .name = "JPG", |
| 433 | .fourcc = V4L2_PIX_FMT_JPEG, | 443 | .fourcc = V4L2_PIX_FMT_JPEG, |
| 434 | .depth = 24 | 444 | .depth = 24 |
| 435 | }, { | 445 | }, { |
| 436 | .name = "8bpp GREY", | 446 | .name = "MJPG", |
| 437 | .fourcc = V4L2_PIX_FMT_GREY, | 447 | .fourcc = V4L2_PIX_FMT_MJPEG, |
| 438 | .depth = 8 | 448 | .depth = 24 |
| 439 | } | 449 | } |
| 440 | }; | 450 | }; |
| 441 | 451 | ||
| @@ -610,6 +620,9 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc) | |||
| 610 | for (i = 0; i < ARRAY_SIZE(formats); i++) { | 620 | for (i = 0; i < ARRAY_SIZE(formats); i++) { |
| 611 | if (-1 == formats[i].fourcc) | 621 | if (-1 == formats[i].fourcc) |
| 612 | continue; | 622 | continue; |
| 623 | if (!jpeg_enable && ((formats[i].fourcc == V4L2_PIX_FMT_JPEG) || | ||
| 624 | (formats[i].fourcc == V4L2_PIX_FMT_MJPEG))) | ||
| 625 | continue; | ||
| 613 | if (formats[i].fourcc == fourcc) | 626 | if (formats[i].fourcc == fourcc) |
| 614 | return formats + i; | 627 | return formats + i; |
| 615 | } | 628 | } |
| @@ -653,6 +666,7 @@ static void s2255_fillbuff(struct s2255_channel *channel, | |||
| 653 | memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height); | 666 | memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height); |
| 654 | break; | 667 | break; |
| 655 | case V4L2_PIX_FMT_JPEG: | 668 | case V4L2_PIX_FMT_JPEG: |
| 669 | case V4L2_PIX_FMT_MJPEG: | ||
| 656 | buf->vb.size = jpgsize; | 670 | buf->vb.size = jpgsize; |
| 657 | memcpy(vbuf, tmpbuf, buf->vb.size); | 671 | memcpy(vbuf, tmpbuf, buf->vb.size); |
| 658 | break; | 672 | break; |
| @@ -856,7 +870,9 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
| 856 | 870 | ||
| 857 | if (index >= ARRAY_SIZE(formats)) | 871 | if (index >= ARRAY_SIZE(formats)) |
| 858 | return -EINVAL; | 872 | return -EINVAL; |
| 859 | 873 | if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || | |
| 874 | (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) | ||
| 875 | return -EINVAL; | ||
| 860 | dprintk(4, "name %s\n", formats[index].name); | 876 | dprintk(4, "name %s\n", formats[index].name); |
| 861 | strlcpy(f->description, formats[index].name, sizeof(f->description)); | 877 | strlcpy(f->description, formats[index].name, sizeof(f->description)); |
| 862 | f->pixelformat = formats[index].fourcc; | 878 | f->pixelformat = formats[index].fourcc; |
| @@ -1037,6 +1053,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 1037 | mode.color |= COLOR_Y8; | 1053 | mode.color |= COLOR_Y8; |
| 1038 | break; | 1054 | break; |
| 1039 | case V4L2_PIX_FMT_JPEG: | 1055 | case V4L2_PIX_FMT_JPEG: |
| 1056 | case V4L2_PIX_FMT_MJPEG: | ||
| 1040 | mode.color &= ~MASK_COLOR; | 1057 | mode.color &= ~MASK_COLOR; |
| 1041 | mode.color |= COLOR_JPG; | 1058 | mode.color |= COLOR_JPG; |
| 1042 | mode.color |= (channel->jc.quality << 8); | 1059 | mode.color |= (channel->jc.quality << 8); |
| @@ -2382,7 +2399,7 @@ static void read_pipe_completion(struct urb *purb) | |||
| 2382 | read_pipe_completion, pipe_info); | 2399 | read_pipe_completion, pipe_info); |
| 2383 | 2400 | ||
| 2384 | if (pipe_info->state != 0) { | 2401 | if (pipe_info->state != 0) { |
| 2385 | if (usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL)) { | 2402 | if (usb_submit_urb(pipe_info->stream_urb, GFP_ATOMIC)) { |
| 2386 | dev_err(&dev->udev->dev, "error submitting urb\n"); | 2403 | dev_err(&dev->udev->dev, "error submitting urb\n"); |
| 2387 | } | 2404 | } |
| 2388 | } else { | 2405 | } else { |
diff --git a/drivers/media/video/s5p-fimc/Makefile b/drivers/media/video/s5p-fimc/Makefile index 7ea1b1403b1e..df6954ab1d99 100644 --- a/drivers/media/video/s5p-fimc/Makefile +++ b/drivers/media/video/s5p-fimc/Makefile | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-capture.o | ||
| 2 | s5p-csis-objs := mipi-csis.o | ||
| 1 | 3 | ||
| 2 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) := s5p-fimc.o | 4 | obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o |
| 3 | s5p-fimc-y := fimc-core.o fimc-reg.o fimc-capture.o | 5 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc.o |
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c new file mode 100644 index 000000000000..ef056d6605ca --- /dev/null +++ b/drivers/media/video/s5p-fimc/mipi-csis.c | |||
| @@ -0,0 +1,724 @@ | |||
| 1 | /* | ||
| 2 | * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
| 5 | * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/clk.h> | ||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | #include <linux/irq.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/memory.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/pm_runtime.h> | ||
| 24 | #include <linux/regulator/consumer.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/spinlock.h> | ||
| 27 | #include <linux/videodev2.h> | ||
| 28 | #include <media/v4l2-subdev.h> | ||
| 29 | #include <plat/mipi_csis.h> | ||
| 30 | #include "mipi-csis.h" | ||
| 31 | |||
| 32 | static int debug; | ||
| 33 | module_param(debug, int, 0644); | ||
| 34 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | ||
| 35 | |||
| 36 | /* Register map definition */ | ||
| 37 | |||
| 38 | /* CSIS global control */ | ||
| 39 | #define S5PCSIS_CTRL 0x00 | ||
| 40 | #define S5PCSIS_CTRL_DPDN_DEFAULT (0 << 31) | ||
| 41 | #define S5PCSIS_CTRL_DPDN_SWAP (1 << 31) | ||
| 42 | #define S5PCSIS_CTRL_ALIGN_32BIT (1 << 20) | ||
| 43 | #define S5PCSIS_CTRL_UPDATE_SHADOW (1 << 16) | ||
| 44 | #define S5PCSIS_CTRL_WCLK_EXTCLK (1 << 8) | ||
| 45 | #define S5PCSIS_CTRL_RESET (1 << 4) | ||
| 46 | #define S5PCSIS_CTRL_ENABLE (1 << 0) | ||
| 47 | |||
| 48 | /* D-PHY control */ | ||
| 49 | #define S5PCSIS_DPHYCTRL 0x04 | ||
| 50 | #define S5PCSIS_DPHYCTRL_HSS_MASK (0x1f << 27) | ||
| 51 | #define S5PCSIS_DPHYCTRL_ENABLE (0x1f << 0) | ||
| 52 | |||
| 53 | #define S5PCSIS_CONFIG 0x08 | ||
| 54 | #define S5PCSIS_CFG_FMT_YCBCR422_8BIT (0x1e << 2) | ||
| 55 | #define S5PCSIS_CFG_FMT_RAW8 (0x2a << 2) | ||
| 56 | #define S5PCSIS_CFG_FMT_RAW10 (0x2b << 2) | ||
| 57 | #define S5PCSIS_CFG_FMT_RAW12 (0x2c << 2) | ||
| 58 | /* User defined formats, x = 1...4 */ | ||
| 59 | #define S5PCSIS_CFG_FMT_USER(x) ((0x30 + x - 1) << 2) | ||
| 60 | #define S5PCSIS_CFG_FMT_MASK (0x3f << 2) | ||
| 61 | #define S5PCSIS_CFG_NR_LANE_MASK 3 | ||
| 62 | |||
| 63 | /* Interrupt mask. */ | ||
| 64 | #define S5PCSIS_INTMSK 0x10 | ||
| 65 | #define S5PCSIS_INTMSK_EN_ALL 0xf000003f | ||
| 66 | #define S5PCSIS_INTSRC 0x14 | ||
| 67 | |||
| 68 | /* Pixel resolution */ | ||
| 69 | #define S5PCSIS_RESOL 0x2c | ||
| 70 | #define CSIS_MAX_PIX_WIDTH 0xffff | ||
| 71 | #define CSIS_MAX_PIX_HEIGHT 0xffff | ||
| 72 | |||
| 73 | enum { | ||
| 74 | CSIS_CLK_MUX, | ||
| 75 | CSIS_CLK_GATE, | ||
| 76 | }; | ||
| 77 | |||
| 78 | static char *csi_clock_name[] = { | ||
| 79 | [CSIS_CLK_MUX] = "sclk_csis", | ||
| 80 | [CSIS_CLK_GATE] = "csis", | ||
| 81 | }; | ||
| 82 | #define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name) | ||
| 83 | |||
| 84 | enum { | ||
| 85 | ST_POWERED = 1, | ||
| 86 | ST_STREAMING = 2, | ||
| 87 | ST_SUSPENDED = 4, | ||
| 88 | }; | ||
| 89 | |||
| 90 | /** | ||
| 91 | * struct csis_state - the driver's internal state data structure | ||
| 92 | * @lock: mutex serializing the subdev and power management operations, | ||
| 93 | * protecting @format and @flags members | ||
| 94 | * @pads: CSIS pads array | ||
| 95 | * @sd: v4l2_subdev associated with CSIS device instance | ||
| 96 | * @pdev: CSIS platform device | ||
| 97 | * @regs_res: requested I/O register memory resource | ||
| 98 | * @regs: mmaped I/O registers memory | ||
| 99 | * @clock: CSIS clocks | ||
| 100 | * @irq: requested s5p-mipi-csis irq number | ||
| 101 | * @flags: the state variable for power and streaming control | ||
| 102 | * @csis_fmt: current CSIS pixel format | ||
| 103 | * @format: common media bus format for the source and sink pad | ||
| 104 | */ | ||
| 105 | struct csis_state { | ||
| 106 | struct mutex lock; | ||
| 107 | struct media_pad pads[CSIS_PADS_NUM]; | ||
| 108 | struct v4l2_subdev sd; | ||
| 109 | struct platform_device *pdev; | ||
| 110 | struct resource *regs_res; | ||
| 111 | void __iomem *regs; | ||
| 112 | struct clk *clock[NUM_CSIS_CLOCKS]; | ||
| 113 | int irq; | ||
| 114 | struct regulator *supply; | ||
| 115 | u32 flags; | ||
| 116 | const struct csis_pix_format *csis_fmt; | ||
| 117 | struct v4l2_mbus_framefmt format; | ||
| 118 | }; | ||
| 119 | |||
| 120 | /** | ||
| 121 | * struct csis_pix_format - CSIS pixel format description | ||
| 122 | * @pix_width_alignment: horizontal pixel alignment, width will be | ||
| 123 | * multiple of 2^pix_width_alignment | ||
| 124 | * @code: corresponding media bus code | ||
| 125 | * @fmt_reg: S5PCSIS_CONFIG register value | ||
| 126 | */ | ||
| 127 | struct csis_pix_format { | ||
| 128 | unsigned int pix_width_alignment; | ||
| 129 | enum v4l2_mbus_pixelcode code; | ||
| 130 | u32 fmt_reg; | ||
| 131 | }; | ||
| 132 | |||
| 133 | static const struct csis_pix_format s5pcsis_formats[] = { | ||
| 134 | { | ||
| 135 | .code = V4L2_MBUS_FMT_VYUY8_2X8, | ||
| 136 | .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT, | ||
| 137 | }, { | ||
| 138 | .code = V4L2_MBUS_FMT_JPEG_1X8, | ||
| 139 | .fmt_reg = S5PCSIS_CFG_FMT_USER(1), | ||
| 140 | }, | ||
| 141 | }; | ||
| 142 | |||
| 143 | #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r) | ||
| 144 | #define s5pcsis_read(__csis, __r) readl(__csis->regs + __r) | ||
| 145 | |||
| 146 | static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev) | ||
| 147 | { | ||
| 148 | return container_of(sdev, struct csis_state, sd); | ||
| 149 | } | ||
| 150 | |||
| 151 | static const struct csis_pix_format *find_csis_format( | ||
| 152 | struct v4l2_mbus_framefmt *mf) | ||
| 153 | { | ||
| 154 | int i; | ||
| 155 | |||
| 156 | for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++) | ||
| 157 | if (mf->code == s5pcsis_formats[i].code) | ||
| 158 | return &s5pcsis_formats[i]; | ||
| 159 | return NULL; | ||
| 160 | } | ||
| 161 | |||
| 162 | static void s5pcsis_enable_interrupts(struct csis_state *state, bool on) | ||
| 163 | { | ||
| 164 | u32 val = s5pcsis_read(state, S5PCSIS_INTMSK); | ||
| 165 | |||
| 166 | val = on ? val | S5PCSIS_INTMSK_EN_ALL : | ||
| 167 | val & ~S5PCSIS_INTMSK_EN_ALL; | ||
| 168 | s5pcsis_write(state, S5PCSIS_INTMSK, val); | ||
| 169 | } | ||
| 170 | |||
| 171 | static void s5pcsis_reset(struct csis_state *state) | ||
| 172 | { | ||
| 173 | u32 val = s5pcsis_read(state, S5PCSIS_CTRL); | ||
| 174 | |||
| 175 | s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET); | ||
| 176 | udelay(10); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void s5pcsis_system_enable(struct csis_state *state, int on) | ||
| 180 | { | ||
| 181 | u32 val; | ||
| 182 | |||
| 183 | val = s5pcsis_read(state, S5PCSIS_CTRL); | ||
| 184 | if (on) | ||
| 185 | val |= S5PCSIS_CTRL_ENABLE; | ||
| 186 | else | ||
| 187 | val &= ~S5PCSIS_CTRL_ENABLE; | ||
| 188 | s5pcsis_write(state, S5PCSIS_CTRL, val); | ||
| 189 | |||
| 190 | val = s5pcsis_read(state, S5PCSIS_DPHYCTRL); | ||
| 191 | if (on) | ||
| 192 | val |= S5PCSIS_DPHYCTRL_ENABLE; | ||
| 193 | else | ||
| 194 | val &= ~S5PCSIS_DPHYCTRL_ENABLE; | ||
| 195 | s5pcsis_write(state, S5PCSIS_DPHYCTRL, val); | ||
| 196 | } | ||
| 197 | |||
| 198 | /* Called with the state.lock mutex held */ | ||
| 199 | static void __s5pcsis_set_format(struct csis_state *state) | ||
| 200 | { | ||
| 201 | struct v4l2_mbus_framefmt *mf = &state->format; | ||
| 202 | u32 val; | ||
| 203 | |||
| 204 | v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n", | ||
| 205 | mf->code, mf->width, mf->height); | ||
| 206 | |||
| 207 | /* Color format */ | ||
| 208 | val = s5pcsis_read(state, S5PCSIS_CONFIG); | ||
| 209 | val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg; | ||
| 210 | s5pcsis_write(state, S5PCSIS_CONFIG, val); | ||
| 211 | |||
| 212 | /* Pixel resolution */ | ||
| 213 | val = (mf->width << 16) | mf->height; | ||
| 214 | s5pcsis_write(state, S5PCSIS_RESOL, val); | ||
| 215 | } | ||
| 216 | |||
| 217 | static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle) | ||
| 218 | { | ||
| 219 | u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL); | ||
| 220 | |||
| 221 | val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27); | ||
| 222 | s5pcsis_write(state, S5PCSIS_DPHYCTRL, val); | ||
| 223 | } | ||
| 224 | |||
| 225 | static void s5pcsis_set_params(struct csis_state *state) | ||
| 226 | { | ||
| 227 | struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data; | ||
| 228 | u32 val; | ||
| 229 | |||
| 230 | val = s5pcsis_read(state, S5PCSIS_CONFIG); | ||
| 231 | val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (pdata->lanes - 1); | ||
| 232 | s5pcsis_write(state, S5PCSIS_CONFIG, val); | ||
| 233 | |||
| 234 | __s5pcsis_set_format(state); | ||
| 235 | s5pcsis_set_hsync_settle(state, pdata->hs_settle); | ||
| 236 | |||
| 237 | val = s5pcsis_read(state, S5PCSIS_CTRL); | ||
| 238 | if (pdata->alignment == 32) | ||
| 239 | val |= S5PCSIS_CTRL_ALIGN_32BIT; | ||
| 240 | else /* 24-bits */ | ||
| 241 | val &= ~S5PCSIS_CTRL_ALIGN_32BIT; | ||
| 242 | /* Not using external clock. */ | ||
| 243 | val &= ~S5PCSIS_CTRL_WCLK_EXTCLK; | ||
| 244 | s5pcsis_write(state, S5PCSIS_CTRL, val); | ||
| 245 | |||
| 246 | /* Update the shadow register. */ | ||
| 247 | val = s5pcsis_read(state, S5PCSIS_CTRL); | ||
| 248 | s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void s5pcsis_clk_put(struct csis_state *state) | ||
| 252 | { | ||
| 253 | int i; | ||
| 254 | |||
| 255 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) | ||
| 256 | if (!IS_ERR_OR_NULL(state->clock[i])) | ||
| 257 | clk_put(state->clock[i]); | ||
| 258 | } | ||
| 259 | |||
| 260 | static int s5pcsis_clk_get(struct csis_state *state) | ||
| 261 | { | ||
| 262 | struct device *dev = &state->pdev->dev; | ||
| 263 | int i; | ||
| 264 | |||
| 265 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { | ||
| 266 | state->clock[i] = clk_get(dev, csi_clock_name[i]); | ||
| 267 | if (IS_ERR(state->clock[i])) { | ||
| 268 | s5pcsis_clk_put(state); | ||
| 269 | dev_err(dev, "failed to get clock: %s\n", | ||
| 270 | csi_clock_name[i]); | ||
| 271 | return -ENXIO; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) | ||
| 278 | { | ||
| 279 | struct csis_state *state = sd_to_csis_state(sd); | ||
| 280 | struct device *dev = &state->pdev->dev; | ||
| 281 | |||
| 282 | if (on) | ||
| 283 | return pm_runtime_get_sync(dev); | ||
| 284 | |||
| 285 | return pm_runtime_put_sync(dev); | ||
| 286 | } | ||
| 287 | |||
| 288 | static void s5pcsis_start_stream(struct csis_state *state) | ||
| 289 | { | ||
| 290 | s5pcsis_reset(state); | ||
| 291 | s5pcsis_set_params(state); | ||
| 292 | s5pcsis_system_enable(state, true); | ||
| 293 | s5pcsis_enable_interrupts(state, true); | ||
| 294 | } | ||
| 295 | |||
| 296 | static void s5pcsis_stop_stream(struct csis_state *state) | ||
| 297 | { | ||
| 298 | s5pcsis_enable_interrupts(state, false); | ||
| 299 | s5pcsis_system_enable(state, false); | ||
| 300 | } | ||
| 301 | |||
| 302 | /* v4l2_subdev operations */ | ||
| 303 | static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable) | ||
| 304 | { | ||
| 305 | struct csis_state *state = sd_to_csis_state(sd); | ||
| 306 | int ret = 0; | ||
| 307 | |||
| 308 | v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n", | ||
| 309 | __func__, enable, state->flags); | ||
| 310 | |||
| 311 | if (enable) { | ||
| 312 | ret = pm_runtime_get_sync(&state->pdev->dev); | ||
| 313 | if (ret && ret != 1) | ||
| 314 | return ret; | ||
| 315 | } | ||
| 316 | mutex_lock(&state->lock); | ||
| 317 | if (enable) { | ||
| 318 | if (state->flags & ST_SUSPENDED) { | ||
| 319 | ret = -EBUSY; | ||
| 320 | goto unlock; | ||
| 321 | } | ||
| 322 | s5pcsis_start_stream(state); | ||
| 323 | state->flags |= ST_STREAMING; | ||
| 324 | } else { | ||
| 325 | s5pcsis_stop_stream(state); | ||
| 326 | state->flags &= ~ST_STREAMING; | ||
| 327 | } | ||
| 328 | unlock: | ||
| 329 | mutex_unlock(&state->lock); | ||
| 330 | if (!enable) | ||
| 331 | pm_runtime_put(&state->pdev->dev); | ||
| 332 | |||
| 333 | return ret == 1 ? 0 : ret; | ||
| 334 | } | ||
| 335 | |||
| 336 | static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd, | ||
| 337 | struct v4l2_subdev_fh *fh, | ||
| 338 | struct v4l2_subdev_mbus_code_enum *code) | ||
| 339 | { | ||
| 340 | if (code->index >= ARRAY_SIZE(s5pcsis_formats)) | ||
| 341 | return -EINVAL; | ||
| 342 | |||
| 343 | code->code = s5pcsis_formats[code->index].code; | ||
| 344 | return 0; | ||
| 345 | } | ||
| 346 | |||
| 347 | static struct csis_pix_format const *s5pcsis_try_format( | ||
| 348 | struct v4l2_mbus_framefmt *mf) | ||
| 349 | { | ||
| 350 | struct csis_pix_format const *csis_fmt; | ||
| 351 | |||
| 352 | csis_fmt = find_csis_format(mf); | ||
| 353 | if (csis_fmt == NULL) | ||
| 354 | csis_fmt = &s5pcsis_formats[0]; | ||
| 355 | |||
| 356 | mf->code = csis_fmt->code; | ||
| 357 | v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH, | ||
| 358 | csis_fmt->pix_width_alignment, | ||
| 359 | &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1, | ||
| 360 | 0); | ||
| 361 | return csis_fmt; | ||
| 362 | } | ||
| 363 | |||
| 364 | static struct v4l2_mbus_framefmt *__s5pcsis_get_format( | ||
| 365 | struct csis_state *state, struct v4l2_subdev_fh *fh, | ||
| 366 | u32 pad, enum v4l2_subdev_format_whence which) | ||
| 367 | { | ||
| 368 | if (which == V4L2_SUBDEV_FORMAT_TRY) | ||
| 369 | return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL; | ||
| 370 | |||
| 371 | return &state->format; | ||
| 372 | } | ||
| 373 | |||
| 374 | static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | ||
| 375 | struct v4l2_subdev_format *fmt) | ||
| 376 | { | ||
| 377 | struct csis_state *state = sd_to_csis_state(sd); | ||
| 378 | struct csis_pix_format const *csis_fmt; | ||
| 379 | struct v4l2_mbus_framefmt *mf; | ||
| 380 | |||
| 381 | if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK) | ||
| 382 | return -EINVAL; | ||
| 383 | |||
| 384 | mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which); | ||
| 385 | |||
| 386 | if (fmt->pad == CSIS_PAD_SOURCE) { | ||
| 387 | if (mf) { | ||
| 388 | mutex_lock(&state->lock); | ||
| 389 | fmt->format = *mf; | ||
| 390 | mutex_unlock(&state->lock); | ||
| 391 | } | ||
| 392 | return 0; | ||
| 393 | } | ||
| 394 | csis_fmt = s5pcsis_try_format(&fmt->format); | ||
| 395 | if (mf) { | ||
| 396 | mutex_lock(&state->lock); | ||
| 397 | *mf = fmt->format; | ||
| 398 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
| 399 | state->csis_fmt = csis_fmt; | ||
| 400 | mutex_unlock(&state->lock); | ||
| 401 | } | ||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | ||
| 406 | struct v4l2_subdev_format *fmt) | ||
| 407 | { | ||
| 408 | struct csis_state *state = sd_to_csis_state(sd); | ||
| 409 | struct v4l2_mbus_framefmt *mf; | ||
| 410 | |||
| 411 | if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK) | ||
| 412 | return -EINVAL; | ||
| 413 | |||
| 414 | mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which); | ||
| 415 | if (!mf) | ||
| 416 | return -EINVAL; | ||
| 417 | |||
| 418 | mutex_lock(&state->lock); | ||
| 419 | fmt->format = *mf; | ||
| 420 | mutex_unlock(&state->lock); | ||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | static struct v4l2_subdev_core_ops s5pcsis_core_ops = { | ||
| 425 | .s_power = s5pcsis_s_power, | ||
| 426 | }; | ||
| 427 | |||
| 428 | static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = { | ||
| 429 | .enum_mbus_code = s5pcsis_enum_mbus_code, | ||
| 430 | .get_fmt = s5pcsis_get_fmt, | ||
| 431 | .set_fmt = s5pcsis_set_fmt, | ||
| 432 | }; | ||
| 433 | |||
| 434 | static struct v4l2_subdev_video_ops s5pcsis_video_ops = { | ||
| 435 | .s_stream = s5pcsis_s_stream, | ||
| 436 | }; | ||
| 437 | |||
| 438 | static struct v4l2_subdev_ops s5pcsis_subdev_ops = { | ||
| 439 | .core = &s5pcsis_core_ops, | ||
| 440 | .pad = &s5pcsis_pad_ops, | ||
| 441 | .video = &s5pcsis_video_ops, | ||
| 442 | }; | ||
| 443 | |||
| 444 | static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) | ||
| 445 | { | ||
| 446 | struct csis_state *state = dev_id; | ||
| 447 | u32 val; | ||
| 448 | |||
| 449 | /* Just clear the interrupt pending bits. */ | ||
| 450 | val = s5pcsis_read(state, S5PCSIS_INTSRC); | ||
| 451 | s5pcsis_write(state, S5PCSIS_INTSRC, val); | ||
| 452 | |||
| 453 | return IRQ_HANDLED; | ||
| 454 | } | ||
| 455 | |||
| 456 | static int __devinit s5pcsis_probe(struct platform_device *pdev) | ||
| 457 | { | ||
| 458 | struct s5p_platform_mipi_csis *pdata; | ||
| 459 | struct resource *mem_res; | ||
| 460 | struct resource *regs_res; | ||
| 461 | struct csis_state *state; | ||
| 462 | int ret = -ENOMEM; | ||
| 463 | |||
| 464 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
| 465 | if (!state) | ||
| 466 | return -ENOMEM; | ||
| 467 | |||
| 468 | mutex_init(&state->lock); | ||
| 469 | state->pdev = pdev; | ||
| 470 | |||
| 471 | pdata = pdev->dev.platform_data; | ||
| 472 | if (pdata == NULL || pdata->phy_enable == NULL) { | ||
| 473 | dev_err(&pdev->dev, "Platform data not fully specified\n"); | ||
| 474 | goto e_free; | ||
| 475 | } | ||
| 476 | |||
| 477 | if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || | ||
| 478 | pdata->lanes > CSIS0_MAX_LANES) { | ||
| 479 | ret = -EINVAL; | ||
| 480 | dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", | ||
| 481 | pdata->lanes); | ||
| 482 | goto e_free; | ||
| 483 | } | ||
| 484 | |||
| 485 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 486 | if (!mem_res) { | ||
| 487 | dev_err(&pdev->dev, "Failed to get IO memory region\n"); | ||
| 488 | goto e_free; | ||
| 489 | } | ||
| 490 | |||
| 491 | regs_res = request_mem_region(mem_res->start, resource_size(mem_res), | ||
| 492 | pdev->name); | ||
| 493 | if (!regs_res) { | ||
| 494 | dev_err(&pdev->dev, "Failed to request IO memory region\n"); | ||
| 495 | goto e_free; | ||
| 496 | } | ||
| 497 | state->regs_res = regs_res; | ||
| 498 | |||
| 499 | state->regs = ioremap(mem_res->start, resource_size(mem_res)); | ||
| 500 | if (!state->regs) { | ||
| 501 | dev_err(&pdev->dev, "Failed to remap IO region\n"); | ||
| 502 | goto e_reqmem; | ||
| 503 | } | ||
| 504 | |||
| 505 | ret = s5pcsis_clk_get(state); | ||
| 506 | if (ret) | ||
| 507 | goto e_unmap; | ||
| 508 | |||
| 509 | clk_enable(state->clock[CSIS_CLK_MUX]); | ||
| 510 | if (pdata->clk_rate) | ||
| 511 | clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); | ||
| 512 | else | ||
| 513 | dev_WARN(&pdev->dev, "No clock frequency specified!\n"); | ||
| 514 | |||
| 515 | state->irq = platform_get_irq(pdev, 0); | ||
| 516 | if (state->irq < 0) { | ||
| 517 | ret = state->irq; | ||
| 518 | dev_err(&pdev->dev, "Failed to get irq\n"); | ||
| 519 | goto e_clkput; | ||
| 520 | } | ||
| 521 | |||
| 522 | if (!pdata->fixed_phy_vdd) { | ||
| 523 | state->supply = regulator_get(&pdev->dev, "vdd"); | ||
| 524 | if (IS_ERR(state->supply)) { | ||
| 525 | ret = PTR_ERR(state->supply); | ||
| 526 | state->supply = NULL; | ||
| 527 | goto e_clkput; | ||
| 528 | } | ||
| 529 | } | ||
| 530 | |||
| 531 | ret = request_irq(state->irq, s5pcsis_irq_handler, 0, | ||
| 532 | dev_name(&pdev->dev), state); | ||
| 533 | if (ret) { | ||
| 534 | dev_err(&pdev->dev, "request_irq failed\n"); | ||
| 535 | goto e_regput; | ||
| 536 | } | ||
| 537 | |||
| 538 | v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops); | ||
| 539 | state->sd.owner = THIS_MODULE; | ||
| 540 | strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name)); | ||
| 541 | state->csis_fmt = &s5pcsis_formats[0]; | ||
| 542 | |||
| 543 | state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; | ||
| 544 | state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | ||
| 545 | ret = media_entity_init(&state->sd.entity, | ||
| 546 | CSIS_PADS_NUM, state->pads, 0); | ||
| 547 | if (ret < 0) | ||
| 548 | goto e_irqfree; | ||
| 549 | |||
| 550 | /* This allows to retrieve the platform device id by the host driver */ | ||
| 551 | v4l2_set_subdevdata(&state->sd, pdev); | ||
| 552 | |||
| 553 | /* .. and a pointer to the subdev. */ | ||
| 554 | platform_set_drvdata(pdev, &state->sd); | ||
| 555 | |||
| 556 | state->flags = ST_SUSPENDED; | ||
| 557 | pm_runtime_enable(&pdev->dev); | ||
| 558 | |||
| 559 | return 0; | ||
| 560 | |||
| 561 | e_irqfree: | ||
| 562 | free_irq(state->irq, state); | ||
| 563 | e_regput: | ||
| 564 | if (state->supply) | ||
| 565 | regulator_put(state->supply); | ||
| 566 | e_clkput: | ||
| 567 | clk_disable(state->clock[CSIS_CLK_MUX]); | ||
| 568 | s5pcsis_clk_put(state); | ||
| 569 | e_unmap: | ||
| 570 | iounmap(state->regs); | ||
| 571 | e_reqmem: | ||
| 572 | release_mem_region(regs_res->start, resource_size(regs_res)); | ||
| 573 | e_free: | ||
| 574 | kfree(state); | ||
| 575 | return ret; | ||
| 576 | } | ||
| 577 | |||
| 578 | static int s5pcsis_suspend(struct device *dev) | ||
| 579 | { | ||
| 580 | struct s5p_platform_mipi_csis *pdata = dev->platform_data; | ||
| 581 | struct platform_device *pdev = to_platform_device(dev); | ||
| 582 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); | ||
| 583 | struct csis_state *state = sd_to_csis_state(sd); | ||
| 584 | int ret = 0; | ||
| 585 | |||
| 586 | v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n", | ||
| 587 | __func__, state->flags); | ||
| 588 | |||
| 589 | mutex_lock(&state->lock); | ||
| 590 | if (state->flags & ST_POWERED) { | ||
| 591 | s5pcsis_stop_stream(state); | ||
| 592 | ret = pdata->phy_enable(state->pdev, false); | ||
| 593 | if (ret) | ||
| 594 | goto unlock; | ||
| 595 | if (state->supply) { | ||
| 596 | ret = regulator_disable(state->supply); | ||
| 597 | if (ret) | ||
| 598 | goto unlock; | ||
| 599 | } | ||
| 600 | clk_disable(state->clock[CSIS_CLK_GATE]); | ||
| 601 | state->flags &= ~ST_POWERED; | ||
| 602 | } | ||
| 603 | state->flags |= ST_SUSPENDED; | ||
| 604 | unlock: | ||
| 605 | mutex_unlock(&state->lock); | ||
| 606 | return ret ? -EAGAIN : 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | static int s5pcsis_resume(struct device *dev) | ||
| 610 | { | ||
| 611 | struct s5p_platform_mipi_csis *pdata = dev->platform_data; | ||
| 612 | struct platform_device *pdev = to_platform_device(dev); | ||
| 613 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); | ||
| 614 | struct csis_state *state = sd_to_csis_state(sd); | ||
| 615 | int ret = 0; | ||
| 616 | |||
| 617 | v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n", | ||
| 618 | __func__, state->flags); | ||
| 619 | |||
| 620 | mutex_lock(&state->lock); | ||
| 621 | if (!(state->flags & ST_SUSPENDED)) | ||
| 622 | goto unlock; | ||
| 623 | |||
| 624 | if (!(state->flags & ST_POWERED)) { | ||
| 625 | if (state->supply) | ||
| 626 | ret = regulator_enable(state->supply); | ||
| 627 | if (ret) | ||
| 628 | goto unlock; | ||
| 629 | |||
| 630 | ret = pdata->phy_enable(state->pdev, true); | ||
| 631 | if (!ret) { | ||
| 632 | state->flags |= ST_POWERED; | ||
| 633 | } else if (state->supply) { | ||
| 634 | regulator_disable(state->supply); | ||
| 635 | goto unlock; | ||
| 636 | } | ||
| 637 | clk_enable(state->clock[CSIS_CLK_GATE]); | ||
| 638 | } | ||
| 639 | if (state->flags & ST_STREAMING) | ||
| 640 | s5pcsis_start_stream(state); | ||
| 641 | |||
| 642 | state->flags &= ~ST_SUSPENDED; | ||
| 643 | unlock: | ||
| 644 | mutex_unlock(&state->lock); | ||
| 645 | return ret ? -EAGAIN : 0; | ||
| 646 | } | ||
| 647 | |||
| 648 | #ifdef CONFIG_PM_SLEEP | ||
| 649 | static int s5pcsis_pm_suspend(struct device *dev) | ||
| 650 | { | ||
| 651 | return s5pcsis_suspend(dev); | ||
| 652 | } | ||
| 653 | |||
| 654 | static int s5pcsis_pm_resume(struct device *dev) | ||
| 655 | { | ||
| 656 | int ret; | ||
| 657 | |||
| 658 | ret = s5pcsis_resume(dev); | ||
| 659 | |||
| 660 | if (!ret) { | ||
| 661 | pm_runtime_disable(dev); | ||
| 662 | ret = pm_runtime_set_active(dev); | ||
| 663 | pm_runtime_enable(dev); | ||
| 664 | } | ||
| 665 | |||
| 666 | return ret; | ||
| 667 | } | ||
| 668 | #endif | ||
| 669 | |||
| 670 | static int __devexit s5pcsis_remove(struct platform_device *pdev) | ||
| 671 | { | ||
| 672 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); | ||
| 673 | struct csis_state *state = sd_to_csis_state(sd); | ||
| 674 | struct resource *res = state->regs_res; | ||
| 675 | |||
| 676 | pm_runtime_disable(&pdev->dev); | ||
| 677 | s5pcsis_suspend(&pdev->dev); | ||
| 678 | clk_disable(state->clock[CSIS_CLK_MUX]); | ||
| 679 | pm_runtime_set_suspended(&pdev->dev); | ||
| 680 | |||
| 681 | s5pcsis_clk_put(state); | ||
| 682 | if (state->supply) | ||
| 683 | regulator_put(state->supply); | ||
| 684 | |||
| 685 | media_entity_cleanup(&state->sd.entity); | ||
| 686 | free_irq(state->irq, state); | ||
| 687 | iounmap(state->regs); | ||
| 688 | release_mem_region(res->start, resource_size(res)); | ||
| 689 | kfree(state); | ||
| 690 | |||
| 691 | return 0; | ||
| 692 | } | ||
| 693 | |||
| 694 | static const struct dev_pm_ops s5pcsis_pm_ops = { | ||
| 695 | SET_RUNTIME_PM_OPS(s5pcsis_suspend, s5pcsis_resume, NULL) | ||
| 696 | SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_pm_suspend, s5pcsis_pm_resume) | ||
| 697 | }; | ||
| 698 | |||
| 699 | static struct platform_driver s5pcsis_driver = { | ||
| 700 | .probe = s5pcsis_probe, | ||
| 701 | .remove = __devexit_p(s5pcsis_remove), | ||
| 702 | .driver = { | ||
| 703 | .name = CSIS_DRIVER_NAME, | ||
| 704 | .owner = THIS_MODULE, | ||
| 705 | .pm = &s5pcsis_pm_ops, | ||
| 706 | }, | ||
| 707 | }; | ||
| 708 | |||
| 709 | static int __init s5pcsis_init(void) | ||
| 710 | { | ||
| 711 | return platform_driver_probe(&s5pcsis_driver, s5pcsis_probe); | ||
| 712 | } | ||
| 713 | |||
| 714 | static void __exit s5pcsis_exit(void) | ||
| 715 | { | ||
| 716 | platform_driver_unregister(&s5pcsis_driver); | ||
| 717 | } | ||
| 718 | |||
| 719 | module_init(s5pcsis_init); | ||
| 720 | module_exit(s5pcsis_exit); | ||
| 721 | |||
| 722 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | ||
| 723 | MODULE_DESCRIPTION("S5P/EXYNOS4 MIPI CSI receiver driver"); | ||
| 724 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.h b/drivers/media/video/s5p-fimc/mipi-csis.h new file mode 100644 index 000000000000..f5691336dd5c --- /dev/null +++ b/drivers/media/video/s5p-fimc/mipi-csis.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | #ifndef S5P_MIPI_CSIS_H_ | ||
| 11 | #define S5P_MIPI_CSIS_H_ | ||
| 12 | |||
| 13 | #define CSIS_DRIVER_NAME "s5p-mipi-csis" | ||
| 14 | #define CSIS_MAX_ENTITIES 2 | ||
| 15 | #define CSIS0_MAX_LANES 4 | ||
| 16 | #define CSIS1_MAX_LANES 2 | ||
| 17 | |||
| 18 | #define CSIS_PAD_SINK 0 | ||
| 19 | #define CSIS_PAD_SOURCE 1 | ||
| 20 | #define CSIS_PADS_NUM 2 | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 50f1be05ebd3..e2062b240e32 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
| @@ -5591,6 +5591,105 @@ struct saa7134_board saa7134_boards[] = { | |||
| 5591 | .amux = TV, | 5591 | .amux = TV, |
| 5592 | }, | 5592 | }, |
| 5593 | }, | 5593 | }, |
| 5594 | [SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2] = { | ||
| 5595 | /* Timothy Lee <timothy.lee@siriushk.com> */ | ||
| 5596 | .name = "MagicPro ProHDTV Pro2 DMB-TH/Hybrid", | ||
| 5597 | .audio_clock = 0x00187de7, | ||
| 5598 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
| 5599 | .radio_type = UNSET, | ||
| 5600 | .tuner_config = 3, | ||
| 5601 | .tuner_addr = ADDR_UNSET, | ||
| 5602 | .radio_addr = ADDR_UNSET, | ||
| 5603 | .gpiomask = 0x02050000, | ||
| 5604 | .mpeg = SAA7134_MPEG_DVB, | ||
| 5605 | .ts_type = SAA7134_MPEG_TS_PARALLEL, | ||
| 5606 | .inputs = { { | ||
| 5607 | .name = name_tv, | ||
| 5608 | .vmux = 1, | ||
| 5609 | .amux = TV, | ||
| 5610 | .tv = 1, | ||
| 5611 | .gpio = 0x00050000, | ||
| 5612 | }, { | ||
| 5613 | .name = name_comp1, | ||
| 5614 | .vmux = 3, | ||
| 5615 | .amux = LINE1, | ||
| 5616 | .gpio = 0x00050000, | ||
| 5617 | }, { | ||
| 5618 | .name = name_svideo, | ||
| 5619 | .vmux = 8, | ||
| 5620 | .amux = LINE1, | ||
| 5621 | .gpio = 0x00050000, | ||
| 5622 | } }, | ||
| 5623 | .radio = { | ||
| 5624 | .name = name_radio, | ||
| 5625 | .amux = TV, | ||
| 5626 | .gpio = 0x00050000, | ||
| 5627 | }, | ||
| 5628 | .mute = { | ||
| 5629 | .name = name_mute, | ||
| 5630 | .vmux = 0, | ||
| 5631 | .amux = TV, | ||
| 5632 | .gpio = 0x00050000, | ||
| 5633 | }, | ||
| 5634 | }, | ||
| 5635 | [SAA7134_BOARD_BEHOLD_501] = { | ||
| 5636 | /* Beholder Intl. Ltd. 2010 */ | ||
| 5637 | /* Dmitry Belimov <d.belimov@gmail.com> */ | ||
| 5638 | .name = "Beholder BeholdTV 501", | ||
| 5639 | .audio_clock = 0x00200000, | ||
| 5640 | .tuner_type = TUNER_ABSENT, | ||
| 5641 | .radio_type = UNSET, | ||
| 5642 | .tuner_addr = ADDR_UNSET, | ||
| 5643 | .radio_addr = ADDR_UNSET, | ||
| 5644 | .gpiomask = 0x00008000, | ||
| 5645 | .inputs = { { | ||
| 5646 | .name = name_tv, | ||
| 5647 | .vmux = 3, | ||
| 5648 | .amux = LINE2, | ||
| 5649 | .tv = 1, | ||
| 5650 | }, { | ||
| 5651 | .name = name_comp1, | ||
| 5652 | .vmux = 1, | ||
| 5653 | .amux = LINE1, | ||
| 5654 | }, { | ||
| 5655 | .name = name_svideo, | ||
| 5656 | .vmux = 8, | ||
| 5657 | .amux = LINE1, | ||
| 5658 | } }, | ||
| 5659 | .mute = { | ||
| 5660 | .name = name_mute, | ||
| 5661 | .amux = LINE1, | ||
| 5662 | }, | ||
| 5663 | }, | ||
| 5664 | [SAA7134_BOARD_BEHOLD_503FM] = { | ||
| 5665 | /* Beholder Intl. Ltd. 2010 */ | ||
| 5666 | /* Dmitry Belimov <d.belimov@gmail.com> */ | ||
| 5667 | .name = "Beholder BeholdTV 503 FM", | ||
| 5668 | .audio_clock = 0x00200000, | ||
| 5669 | .tuner_type = TUNER_ABSENT, | ||
| 5670 | .radio_type = UNSET, | ||
| 5671 | .tuner_addr = ADDR_UNSET, | ||
| 5672 | .radio_addr = ADDR_UNSET, | ||
| 5673 | .gpiomask = 0x00008000, | ||
| 5674 | .inputs = { { | ||
| 5675 | .name = name_tv, | ||
| 5676 | .vmux = 3, | ||
| 5677 | .amux = LINE2, | ||
| 5678 | .tv = 1, | ||
| 5679 | }, { | ||
| 5680 | .name = name_comp1, | ||
| 5681 | .vmux = 1, | ||
| 5682 | .amux = LINE1, | ||
| 5683 | }, { | ||
| 5684 | .name = name_svideo, | ||
| 5685 | .vmux = 8, | ||
| 5686 | .amux = LINE1, | ||
| 5687 | } }, | ||
| 5688 | .mute = { | ||
| 5689 | .name = name_mute, | ||
| 5690 | .amux = LINE1, | ||
| 5691 | }, | ||
| 5692 | }, | ||
| 5594 | 5693 | ||
| 5595 | }; | 5694 | }; |
| 5596 | 5695 | ||
| @@ -6796,6 +6895,24 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
| 6796 | .subdevice = 0xc900, | 6895 | .subdevice = 0xc900, |
| 6797 | .driver_data = SAA7134_BOARD_VIDEOMATE_M1F, | 6896 | .driver_data = SAA7134_BOARD_VIDEOMATE_M1F, |
| 6798 | }, { | 6897 | }, { |
| 6898 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 6899 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
| 6900 | .subvendor = 0x5ace, | ||
| 6901 | .subdevice = 0x5030, | ||
| 6902 | .driver_data = SAA7134_BOARD_BEHOLD_503FM, | ||
| 6903 | }, { | ||
| 6904 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 6905 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
| 6906 | .subvendor = 0x5ace, | ||
| 6907 | .subdevice = 0x5010, | ||
| 6908 | .driver_data = SAA7134_BOARD_BEHOLD_501, | ||
| 6909 | }, { | ||
| 6910 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 6911 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | ||
| 6912 | .subvendor = 0x17de, | ||
| 6913 | .subdevice = 0xd136, | ||
| 6914 | .driver_data = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2, | ||
| 6915 | }, { | ||
| 6799 | /* --- boards without eeprom + subsystem ID --- */ | 6916 | /* --- boards without eeprom + subsystem ID --- */ |
| 6800 | .vendor = PCI_VENDOR_ID_PHILIPS, | 6917 | .vendor = PCI_VENDOR_ID_PHILIPS, |
| 6801 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 6918 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
| @@ -6988,6 +7105,7 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, | |||
| 6988 | switch (dev->board) { | 7105 | switch (dev->board) { |
| 6989 | case SAA7134_BOARD_HAUPPAUGE_HVR1150: | 7106 | case SAA7134_BOARD_HAUPPAUGE_HVR1150: |
| 6990 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: | 7107 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: |
| 7108 | case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: | ||
| 6991 | ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); | 7109 | ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); |
| 6992 | break; | 7110 | break; |
| 6993 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: | 7111 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: |
| @@ -7014,6 +7132,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, | |||
| 7014 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: | 7132 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: |
| 7015 | case SAA7134_BOARD_AVERMEDIA_M733A: | 7133 | case SAA7134_BOARD_AVERMEDIA_M733A: |
| 7016 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: | 7134 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: |
| 7135 | case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: | ||
| 7017 | /* tda8290 + tda18271 */ | 7136 | /* tda8290 + tda18271 */ |
| 7018 | ret = saa7134_tda8290_18271_callback(dev, command, arg); | 7137 | ret = saa7134_tda8290_18271_callback(dev, command, arg); |
| 7019 | break; | 7138 | break; |
| @@ -7264,6 +7383,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 7264 | break; | 7383 | break; |
| 7265 | case SAA7134_BOARD_HAUPPAUGE_HVR1150: | 7384 | case SAA7134_BOARD_HAUPPAUGE_HVR1150: |
| 7266 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: | 7385 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: |
| 7386 | dev->has_remote = SAA7134_REMOTE_GPIO; | ||
| 7267 | /* GPIO 26 high for digital, low for analog */ | 7387 | /* GPIO 26 high for digital, low for analog */ |
| 7268 | saa7134_set_gpio(dev, 26, 0); | 7388 | saa7134_set_gpio(dev, 26, 0); |
| 7269 | msleep(1); | 7389 | msleep(1); |
| @@ -7326,6 +7446,11 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 7326 | saa7134_set_gpio(dev, 1, 1); | 7446 | saa7134_set_gpio(dev, 1, 1); |
| 7327 | dev->has_remote = SAA7134_REMOTE_GPIO; | 7447 | dev->has_remote = SAA7134_REMOTE_GPIO; |
| 7328 | break; | 7448 | break; |
| 7449 | case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: | ||
| 7450 | /* enable LGS-8G75 */ | ||
| 7451 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0e050000, 0x0c050000); | ||
| 7452 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0e050000, 0x0c050000); | ||
| 7453 | break; | ||
| 7329 | } | 7454 | } |
| 7330 | return 0; | 7455 | return 0; |
| 7331 | } | 7456 | } |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 41f836fc93ec..f9be737ba6f4 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
| @@ -927,7 +927,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
| 927 | } | 927 | } |
| 928 | 928 | ||
| 929 | /* print pci info */ | 929 | /* print pci info */ |
| 930 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); | 930 | dev->pci_rev = pci_dev->revision; |
| 931 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); | 931 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); |
| 932 | printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " | 932 | printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " |
| 933 | "latency: %d, mmio: 0x%llx\n", dev->name, | 933 | "latency: %d, mmio: 0x%llx\n", dev->name, |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index f65cad287b83..996a206c6d79 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include "lgdt3305.h" | 53 | #include "lgdt3305.h" |
| 54 | #include "tda8290.h" | 54 | #include "tda8290.h" |
| 55 | #include "mb86a20s.h" | 55 | #include "mb86a20s.h" |
| 56 | #include "lgs8gxx.h" | ||
| 56 | 57 | ||
| 57 | #include "zl10353.h" | 58 | #include "zl10353.h" |
| 58 | 59 | ||
| @@ -1123,6 +1124,26 @@ static struct tda18271_config dtv1000s_tda18271_config = { | |||
| 1123 | .gate = TDA18271_GATE_ANALOG, | 1124 | .gate = TDA18271_GATE_ANALOG, |
| 1124 | }; | 1125 | }; |
| 1125 | 1126 | ||
| 1127 | static struct lgs8gxx_config prohdtv_pro2_lgs8g75_config = { | ||
| 1128 | .prod = LGS8GXX_PROD_LGS8G75, | ||
| 1129 | .demod_address = 0x1d, | ||
| 1130 | .serial_ts = 0, | ||
| 1131 | .ts_clk_pol = 1, | ||
| 1132 | .ts_clk_gated = 0, | ||
| 1133 | .if_clk_freq = 30400, /* 30.4 MHz */ | ||
| 1134 | .if_freq = 4000, /* 4.00 MHz */ | ||
| 1135 | .if_neg_center = 0, | ||
| 1136 | .ext_adc = 0, | ||
| 1137 | .adc_signed = 1, | ||
| 1138 | .adc_vpp = 3, /* 2.0 Vpp */ | ||
| 1139 | .if_neg_edge = 1, | ||
| 1140 | }; | ||
| 1141 | |||
| 1142 | static struct tda18271_config prohdtv_pro2_tda18271_config = { | ||
| 1143 | .gate = TDA18271_GATE_ANALOG, | ||
| 1144 | .output_opt = TDA18271_OUTPUT_LT_OFF, | ||
| 1145 | }; | ||
| 1146 | |||
| 1126 | /* ================================================================== | 1147 | /* ================================================================== |
| 1127 | * Core code | 1148 | * Core code |
| 1128 | */ | 1149 | */ |
| @@ -1674,6 +1695,19 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 1674 | 1695 | ||
| 1675 | /* mb86a20s need to use the I2C gateway */ | 1696 | /* mb86a20s need to use the I2C gateway */ |
| 1676 | break; | 1697 | break; |
| 1698 | case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: | ||
| 1699 | fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, | ||
| 1700 | &prohdtv_pro2_lgs8g75_config, | ||
| 1701 | &dev->i2c_adap); | ||
| 1702 | if (fe0->dvb.frontend != NULL) { | ||
| 1703 | dvb_attach(tda829x_attach, fe0->dvb.frontend, | ||
| 1704 | &dev->i2c_adap, 0x4b, | ||
| 1705 | &tda829x_no_probe); | ||
| 1706 | dvb_attach(tda18271_attach, fe0->dvb.frontend, | ||
| 1707 | 0x60, &dev->i2c_adap, | ||
| 1708 | &prohdtv_pro2_tda18271_config); | ||
| 1709 | } | ||
| 1710 | break; | ||
| 1677 | default: | 1711 | default: |
| 1678 | wprintk("Huh? unknown DVB card?\n"); | 1712 | wprintk("Huh? unknown DVB card?\n"); |
| 1679 | break; | 1713 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index be1c2a2de27c..ff6c0e97563e 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
| @@ -756,6 +756,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
| 756 | mask_keycode = 0x0ff00; | 756 | mask_keycode = 0x0ff00; |
| 757 | mask_keyup = 0x040000; | 757 | mask_keyup = 0x040000; |
| 758 | break; | 758 | break; |
| 759 | case SAA7134_BOARD_HAUPPAUGE_HVR1150: | ||
| 760 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: | ||
| 761 | ir_codes = RC_MAP_HAUPPAUGE; | ||
| 762 | mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ | ||
| 763 | mask_keyup = 0x0040000; | ||
| 764 | mask_keycode = 0xffff; | ||
| 765 | raw_decode = true; | ||
| 766 | break; | ||
| 759 | } | 767 | } |
| 760 | if (NULL == ir_codes) { | 768 | if (NULL == ir_codes) { |
| 761 | printk("%s: Oops: IR config error [card=%d]\n", | 769 | printk("%s: Oops: IR config error [card=%d]\n", |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f96cd5d761f9..28eb10398323 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
| @@ -328,6 +328,9 @@ struct saa7134_card_ir { | |||
| 328 | #define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182 | 328 | #define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182 |
| 329 | #define SAA7134_BOARD_VIDEOMATE_M1F 183 | 329 | #define SAA7134_BOARD_VIDEOMATE_M1F 183 |
| 330 | #define SAA7134_BOARD_ENCORE_ENLTV_FM3 184 | 330 | #define SAA7134_BOARD_ENCORE_ENLTV_FM3 184 |
| 331 | #define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185 | ||
| 332 | #define SAA7134_BOARD_BEHOLD_501 186 | ||
| 333 | #define SAA7134_BOARD_BEHOLD_503FM 187 | ||
| 331 | 334 | ||
| 332 | #define SAA7134_MAXBOARDS 32 | 335 | #define SAA7134_MAXBOARDS 32 |
| 333 | #define SAA7134_INPUT_MAX 8 | 336 | #define SAA7134_INPUT_MAX 8 |
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index b813aec1e456..3b7d7b4e3034 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c | |||
| @@ -1247,7 +1247,7 @@ static int __devinit saa7164_initdev(struct pci_dev *pci_dev, | |||
| 1247 | } | 1247 | } |
| 1248 | 1248 | ||
| 1249 | /* print pci info */ | 1249 | /* print pci info */ |
| 1250 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); | 1250 | dev->pci_rev = pci_dev->revision; |
| 1251 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); | 1251 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); |
| 1252 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " | 1252 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " |
| 1253 | "latency: %d, mmio: 0x%llx\n", dev->name, | 1253 | "latency: %d, mmio: 0x%llx\n", dev->name, |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 134e86bf6d97..3ae5c9c58cba 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
| 20 | #include <linux/completion.h> | ||
| 20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 21 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
| 22 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
| @@ -106,6 +107,7 @@ struct sh_mobile_ceu_dev { | |||
| 106 | struct vb2_alloc_ctx *alloc_ctx; | 107 | struct vb2_alloc_ctx *alloc_ctx; |
| 107 | 108 | ||
| 108 | struct sh_mobile_ceu_info *pdata; | 109 | struct sh_mobile_ceu_info *pdata; |
| 110 | struct completion complete; | ||
| 109 | 111 | ||
| 110 | u32 cflcr; | 112 | u32 cflcr; |
| 111 | 113 | ||
| @@ -114,6 +116,7 @@ struct sh_mobile_ceu_dev { | |||
| 114 | 116 | ||
| 115 | unsigned int image_mode:1; | 117 | unsigned int image_mode:1; |
| 116 | unsigned int is_16bit:1; | 118 | unsigned int is_16bit:1; |
| 119 | unsigned int frozen:1; | ||
| 117 | }; | 120 | }; |
| 118 | 121 | ||
| 119 | struct sh_mobile_ceu_cam { | 122 | struct sh_mobile_ceu_cam { |
| @@ -273,7 +276,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
| 273 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_MASK); | 276 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_MASK); |
| 274 | status = ceu_read(pcdev, CETCR); | 277 | status = ceu_read(pcdev, CETCR); |
| 275 | ceu_write(pcdev, CETCR, ~status & CEU_CETCR_MAGIC); | 278 | ceu_write(pcdev, CETCR, ~status & CEU_CETCR_MAGIC); |
| 276 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_MASK); | 279 | if (!pcdev->frozen) |
| 280 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_MASK); | ||
| 277 | ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); | 281 | ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); |
| 278 | ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); | 282 | ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); |
| 279 | 283 | ||
| @@ -287,6 +291,11 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
| 287 | ret = -EIO; | 291 | ret = -EIO; |
| 288 | } | 292 | } |
| 289 | 293 | ||
| 294 | if (pcdev->frozen) { | ||
| 295 | complete(&pcdev->complete); | ||
| 296 | return ret; | ||
| 297 | } | ||
| 298 | |||
| 290 | if (!pcdev->active) | 299 | if (!pcdev->active) |
| 291 | return ret; | 300 | return ret; |
| 292 | 301 | ||
| @@ -378,12 +387,11 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) | |||
| 378 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 387 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
| 379 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 388 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
| 380 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); | 389 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); |
| 381 | unsigned long flags; | ||
| 382 | 390 | ||
| 383 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, | 391 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
| 384 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); | 392 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
| 385 | 393 | ||
| 386 | spin_lock_irqsave(&pcdev->lock, flags); | 394 | spin_lock_irq(&pcdev->lock); |
| 387 | list_add_tail(&buf->queue, &pcdev->capture); | 395 | list_add_tail(&buf->queue, &pcdev->capture); |
| 388 | 396 | ||
| 389 | if (!pcdev->active) { | 397 | if (!pcdev->active) { |
| @@ -395,7 +403,7 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) | |||
| 395 | pcdev->active = vb; | 403 | pcdev->active = vb; |
| 396 | sh_mobile_ceu_capture(pcdev); | 404 | sh_mobile_ceu_capture(pcdev); |
| 397 | } | 405 | } |
| 398 | spin_unlock_irqrestore(&pcdev->lock, flags); | 406 | spin_unlock_irq(&pcdev->lock); |
| 399 | } | 407 | } |
| 400 | 408 | ||
| 401 | static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) | 409 | static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) |
| @@ -404,9 +412,8 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) | |||
| 404 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 412 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
| 405 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); | 413 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); |
| 406 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 414 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
| 407 | unsigned long flags; | ||
| 408 | 415 | ||
| 409 | spin_lock_irqsave(&pcdev->lock, flags); | 416 | spin_lock_irq(&pcdev->lock); |
| 410 | 417 | ||
| 411 | if (pcdev->active == vb) { | 418 | if (pcdev->active == vb) { |
| 412 | /* disable capture (release DMA buffer), reset */ | 419 | /* disable capture (release DMA buffer), reset */ |
| @@ -417,7 +424,7 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) | |||
| 417 | /* Doesn't hurt also if the list is empty */ | 424 | /* Doesn't hurt also if the list is empty */ |
| 418 | list_del_init(&buf->queue); | 425 | list_del_init(&buf->queue); |
| 419 | 426 | ||
| 420 | spin_unlock_irqrestore(&pcdev->lock, flags); | 427 | spin_unlock_irq(&pcdev->lock); |
| 421 | } | 428 | } |
| 422 | 429 | ||
| 423 | static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) | 430 | static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) |
| @@ -427,6 +434,25 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) | |||
| 427 | return 0; | 434 | return 0; |
| 428 | } | 435 | } |
| 429 | 436 | ||
| 437 | static int sh_mobile_ceu_stop_streaming(struct vb2_queue *q) | ||
| 438 | { | ||
| 439 | struct soc_camera_device *icd = container_of(q, struct soc_camera_device, vb2_vidq); | ||
| 440 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
| 441 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
| 442 | struct list_head *buf_head, *tmp; | ||
| 443 | |||
| 444 | spin_lock_irq(&pcdev->lock); | ||
| 445 | |||
| 446 | pcdev->active = NULL; | ||
| 447 | |||
| 448 | list_for_each_safe(buf_head, tmp, &pcdev->capture) | ||
| 449 | list_del_init(buf_head); | ||
| 450 | |||
| 451 | spin_unlock_irq(&pcdev->lock); | ||
| 452 | |||
| 453 | return sh_mobile_ceu_soft_reset(pcdev); | ||
| 454 | } | ||
| 455 | |||
| 430 | static struct vb2_ops sh_mobile_ceu_videobuf_ops = { | 456 | static struct vb2_ops sh_mobile_ceu_videobuf_ops = { |
| 431 | .queue_setup = sh_mobile_ceu_videobuf_setup, | 457 | .queue_setup = sh_mobile_ceu_videobuf_setup, |
| 432 | .buf_prepare = sh_mobile_ceu_videobuf_prepare, | 458 | .buf_prepare = sh_mobile_ceu_videobuf_prepare, |
| @@ -435,6 +461,7 @@ static struct vb2_ops sh_mobile_ceu_videobuf_ops = { | |||
| 435 | .buf_init = sh_mobile_ceu_videobuf_init, | 461 | .buf_init = sh_mobile_ceu_videobuf_init, |
| 436 | .wait_prepare = soc_camera_unlock, | 462 | .wait_prepare = soc_camera_unlock, |
| 437 | .wait_finish = soc_camera_lock, | 463 | .wait_finish = soc_camera_lock, |
| 464 | .stop_streaming = sh_mobile_ceu_stop_streaming, | ||
| 438 | }; | 465 | }; |
| 439 | 466 | ||
| 440 | static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) | 467 | static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) |
| @@ -500,7 +527,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
| 500 | { | 527 | { |
| 501 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 528 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
| 502 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 529 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
| 503 | unsigned long flags; | ||
| 504 | 530 | ||
| 505 | BUG_ON(icd != pcdev->icd); | 531 | BUG_ON(icd != pcdev->icd); |
| 506 | 532 | ||
| @@ -509,13 +535,13 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
| 509 | sh_mobile_ceu_soft_reset(pcdev); | 535 | sh_mobile_ceu_soft_reset(pcdev); |
| 510 | 536 | ||
| 511 | /* make sure active buffer is canceled */ | 537 | /* make sure active buffer is canceled */ |
| 512 | spin_lock_irqsave(&pcdev->lock, flags); | 538 | spin_lock_irq(&pcdev->lock); |
| 513 | if (pcdev->active) { | 539 | if (pcdev->active) { |
| 514 | list_del_init(&to_ceu_vb(pcdev->active)->queue); | 540 | list_del_init(&to_ceu_vb(pcdev->active)->queue); |
| 515 | vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR); | 541 | vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR); |
| 516 | pcdev->active = NULL; | 542 | pcdev->active = NULL; |
| 517 | } | 543 | } |
| 518 | spin_unlock_irqrestore(&pcdev->lock, flags); | 544 | spin_unlock_irq(&pcdev->lock); |
| 519 | 545 | ||
| 520 | pm_runtime_put_sync(ici->v4l2_dev.dev); | 546 | pm_runtime_put_sync(ici->v4l2_dev.dev); |
| 521 | 547 | ||
| @@ -891,8 +917,8 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
| 891 | 917 | ||
| 892 | fmt = soc_mbus_get_fmtdesc(code); | 918 | fmt = soc_mbus_get_fmtdesc(code); |
| 893 | if (!fmt) { | 919 | if (!fmt) { |
| 894 | dev_err(dev, "Invalid format code #%u: %d\n", idx, code); | 920 | dev_warn(dev, "unsupported format code #%u: %d\n", idx, code); |
| 895 | return -EINVAL; | 921 | return 0; |
| 896 | } | 922 | } |
| 897 | 923 | ||
| 898 | if (!pcdev->pdata->csi2_dev) { | 924 | if (!pcdev->pdata->csi2_dev) { |
| @@ -1330,7 +1356,7 @@ static int client_scale(struct soc_camera_device *icd, | |||
| 1330 | /* | 1356 | /* |
| 1331 | * CEU can scale and crop, but we don't want to waste bandwidth and kill the | 1357 | * CEU can scale and crop, but we don't want to waste bandwidth and kill the |
| 1332 | * framerate by always requesting the maximum image from the client. See | 1358 | * framerate by always requesting the maximum image from the client. See |
| 1333 | * Documentation/video4linux/sh_mobile_camera_ceu.txt for a description of | 1359 | * Documentation/video4linux/sh_mobile_ceu_camera.txt for a description of |
| 1334 | * scaling and cropping algorithms and for the meaning of referenced here steps. | 1360 | * scaling and cropping algorithms and for the meaning of referenced here steps. |
| 1335 | */ | 1361 | */ |
| 1336 | static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | 1362 | static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, |
| @@ -1377,10 +1403,6 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
| 1377 | if (mf.width > 2560 || mf.height > 1920) | 1403 | if (mf.width > 2560 || mf.height > 1920) |
| 1378 | return -EINVAL; | 1404 | return -EINVAL; |
| 1379 | 1405 | ||
| 1380 | /* Cache camera output window */ | ||
| 1381 | cam->width = mf.width; | ||
| 1382 | cam->height = mf.height; | ||
| 1383 | |||
| 1384 | /* 4. Calculate camera scales */ | 1406 | /* 4. Calculate camera scales */ |
| 1385 | scale_cam_h = calc_generic_scale(cam_rect->width, mf.width); | 1407 | scale_cam_h = calc_generic_scale(cam_rect->width, mf.width); |
| 1386 | scale_cam_v = calc_generic_scale(cam_rect->height, mf.height); | 1408 | scale_cam_v = calc_generic_scale(cam_rect->height, mf.height); |
| @@ -1389,6 +1411,39 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
| 1389 | interm_width = scale_down(rect->width, scale_cam_h); | 1411 | interm_width = scale_down(rect->width, scale_cam_h); |
| 1390 | interm_height = scale_down(rect->height, scale_cam_v); | 1412 | interm_height = scale_down(rect->height, scale_cam_v); |
| 1391 | 1413 | ||
| 1414 | if (interm_width < icd->user_width) { | ||
| 1415 | u32 new_scale_h; | ||
| 1416 | |||
| 1417 | new_scale_h = calc_generic_scale(rect->width, icd->user_width); | ||
| 1418 | |||
| 1419 | mf.width = scale_down(cam_rect->width, new_scale_h); | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | if (interm_height < icd->user_height) { | ||
| 1423 | u32 new_scale_v; | ||
| 1424 | |||
| 1425 | new_scale_v = calc_generic_scale(rect->height, icd->user_height); | ||
| 1426 | |||
| 1427 | mf.height = scale_down(cam_rect->height, new_scale_v); | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | if (interm_width < icd->user_width || interm_height < icd->user_height) { | ||
| 1431 | ret = v4l2_device_call_until_err(sd->v4l2_dev, (int)icd, video, | ||
| 1432 | s_mbus_fmt, &mf); | ||
| 1433 | if (ret < 0) | ||
| 1434 | return ret; | ||
| 1435 | |||
| 1436 | dev_geo(dev, "New camera output %ux%u\n", mf.width, mf.height); | ||
| 1437 | scale_cam_h = calc_generic_scale(cam_rect->width, mf.width); | ||
| 1438 | scale_cam_v = calc_generic_scale(cam_rect->height, mf.height); | ||
| 1439 | interm_width = scale_down(rect->width, scale_cam_h); | ||
| 1440 | interm_height = scale_down(rect->height, scale_cam_v); | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | /* Cache camera output window */ | ||
| 1444 | cam->width = mf.width; | ||
| 1445 | cam->height = mf.height; | ||
| 1446 | |||
| 1392 | if (pcdev->image_mode) { | 1447 | if (pcdev->image_mode) { |
| 1393 | out_width = min(interm_width, icd->user_width); | 1448 | out_width = min(interm_width, icd->user_width); |
| 1394 | out_height = min(interm_height, icd->user_height); | 1449 | out_height = min(interm_height, icd->user_height); |
| @@ -1704,6 +1759,63 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
| 1704 | return ret; | 1759 | return ret; |
| 1705 | } | 1760 | } |
| 1706 | 1761 | ||
| 1762 | static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd, | ||
| 1763 | struct v4l2_crop *a) | ||
| 1764 | { | ||
| 1765 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
| 1766 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
| 1767 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
| 1768 | u32 out_width = icd->user_width, out_height = icd->user_height; | ||
| 1769 | int ret; | ||
| 1770 | |||
| 1771 | /* Freeze queue */ | ||
| 1772 | pcdev->frozen = 1; | ||
| 1773 | /* Wait for frame */ | ||
| 1774 | ret = wait_for_completion_interruptible(&pcdev->complete); | ||
| 1775 | /* Stop the client */ | ||
| 1776 | ret = v4l2_subdev_call(sd, video, s_stream, 0); | ||
| 1777 | if (ret < 0) | ||
| 1778 | dev_warn(icd->dev.parent, | ||
| 1779 | "Client failed to stop the stream: %d\n", ret); | ||
| 1780 | else | ||
| 1781 | /* Do the crop, if it fails, there's nothing more we can do */ | ||
| 1782 | sh_mobile_ceu_set_crop(icd, a); | ||
| 1783 | |||
| 1784 | dev_geo(icd->dev.parent, "Output after crop: %ux%u\n", icd->user_width, icd->user_height); | ||
| 1785 | |||
| 1786 | if (icd->user_width != out_width || icd->user_height != out_height) { | ||
| 1787 | struct v4l2_format f = { | ||
| 1788 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
| 1789 | .fmt.pix = { | ||
| 1790 | .width = out_width, | ||
| 1791 | .height = out_height, | ||
| 1792 | .pixelformat = icd->current_fmt->host_fmt->fourcc, | ||
| 1793 | .field = pcdev->field, | ||
| 1794 | .colorspace = icd->colorspace, | ||
| 1795 | }, | ||
| 1796 | }; | ||
| 1797 | ret = sh_mobile_ceu_set_fmt(icd, &f); | ||
| 1798 | if (!ret && (out_width != f.fmt.pix.width || | ||
| 1799 | out_height != f.fmt.pix.height)) | ||
| 1800 | ret = -EINVAL; | ||
| 1801 | if (!ret) { | ||
| 1802 | icd->user_width = out_width; | ||
| 1803 | icd->user_height = out_height; | ||
| 1804 | ret = sh_mobile_ceu_set_bus_param(icd, | ||
| 1805 | icd->current_fmt->host_fmt->fourcc); | ||
| 1806 | } | ||
| 1807 | } | ||
| 1808 | |||
| 1809 | /* Thaw the queue */ | ||
| 1810 | pcdev->frozen = 0; | ||
| 1811 | spin_lock_irq(&pcdev->lock); | ||
| 1812 | sh_mobile_ceu_capture(pcdev); | ||
| 1813 | spin_unlock_irq(&pcdev->lock); | ||
| 1814 | /* Start the client */ | ||
| 1815 | ret = v4l2_subdev_call(sd, video, s_stream, 1); | ||
| 1816 | return ret; | ||
| 1817 | } | ||
| 1818 | |||
| 1707 | static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) | 1819 | static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) |
| 1708 | { | 1820 | { |
| 1709 | struct soc_camera_device *icd = file->private_data; | 1821 | struct soc_camera_device *icd = file->private_data; |
| @@ -1790,6 +1902,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
| 1790 | .put_formats = sh_mobile_ceu_put_formats, | 1902 | .put_formats = sh_mobile_ceu_put_formats, |
| 1791 | .get_crop = sh_mobile_ceu_get_crop, | 1903 | .get_crop = sh_mobile_ceu_get_crop, |
| 1792 | .set_crop = sh_mobile_ceu_set_crop, | 1904 | .set_crop = sh_mobile_ceu_set_crop, |
| 1905 | .set_livecrop = sh_mobile_ceu_set_livecrop, | ||
| 1793 | .set_fmt = sh_mobile_ceu_set_fmt, | 1906 | .set_fmt = sh_mobile_ceu_set_fmt, |
| 1794 | .try_fmt = sh_mobile_ceu_try_fmt, | 1907 | .try_fmt = sh_mobile_ceu_try_fmt, |
| 1795 | .set_ctrl = sh_mobile_ceu_set_ctrl, | 1908 | .set_ctrl = sh_mobile_ceu_set_ctrl, |
| @@ -1856,6 +1969,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
| 1856 | 1969 | ||
| 1857 | INIT_LIST_HEAD(&pcdev->capture); | 1970 | INIT_LIST_HEAD(&pcdev->capture); |
| 1858 | spin_lock_init(&pcdev->lock); | 1971 | spin_lock_init(&pcdev->lock); |
| 1972 | init_completion(&pcdev->complete); | ||
| 1859 | 1973 | ||
| 1860 | pcdev->pdata = pdev->dev.platform_data; | 1974 | pcdev->pdata = pdev->dev.platform_data; |
| 1861 | if (!pcdev->pdata) { | 1975 | if (!pcdev->pdata) { |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index ddb4c091dedc..398864370267 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
| @@ -41,6 +41,11 @@ | |||
| 41 | #define DEFAULT_WIDTH 640 | 41 | #define DEFAULT_WIDTH 640 |
| 42 | #define DEFAULT_HEIGHT 480 | 42 | #define DEFAULT_HEIGHT 480 |
| 43 | 43 | ||
| 44 | #define is_streaming(ici, icd) \ | ||
| 45 | (((ici)->ops->init_videobuf) ? \ | ||
| 46 | (icd)->vb_vidq.streaming : \ | ||
| 47 | vb2_is_streaming(&(icd)->vb2_vidq)) | ||
| 48 | |||
| 44 | static LIST_HEAD(hosts); | 49 | static LIST_HEAD(hosts); |
| 45 | static LIST_HEAD(devices); | 50 | static LIST_HEAD(devices); |
| 46 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ | 51 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ |
| @@ -358,8 +363,6 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
| 358 | if (!icd->user_formats) | 363 | if (!icd->user_formats) |
| 359 | return -ENOMEM; | 364 | return -ENOMEM; |
| 360 | 365 | ||
| 361 | icd->num_user_formats = fmts; | ||
| 362 | |||
| 363 | dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); | 366 | dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); |
| 364 | 367 | ||
| 365 | /* Second pass - actually fill data formats */ | 368 | /* Second pass - actually fill data formats */ |
| @@ -367,9 +370,10 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
| 367 | for (i = 0; i < raw_fmts; i++) | 370 | for (i = 0; i < raw_fmts; i++) |
| 368 | if (!ici->ops->get_formats) { | 371 | if (!ici->ops->get_formats) { |
| 369 | v4l2_subdev_call(sd, video, enum_mbus_fmt, i, &code); | 372 | v4l2_subdev_call(sd, video, enum_mbus_fmt, i, &code); |
| 370 | icd->user_formats[i].host_fmt = | 373 | icd->user_formats[fmts].host_fmt = |
| 371 | soc_mbus_get_fmtdesc(code); | 374 | soc_mbus_get_fmtdesc(code); |
| 372 | icd->user_formats[i].code = code; | 375 | if (icd->user_formats[fmts].host_fmt) |
| 376 | icd->user_formats[fmts++].code = code; | ||
| 373 | } else { | 377 | } else { |
| 374 | ret = ici->ops->get_formats(icd, i, | 378 | ret = ici->ops->get_formats(icd, i, |
| 375 | &icd->user_formats[fmts]); | 379 | &icd->user_formats[fmts]); |
| @@ -378,12 +382,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
| 378 | fmts += ret; | 382 | fmts += ret; |
| 379 | } | 383 | } |
| 380 | 384 | ||
| 385 | icd->num_user_formats = fmts; | ||
| 381 | icd->current_fmt = &icd->user_formats[0]; | 386 | icd->current_fmt = &icd->user_formats[0]; |
| 382 | 387 | ||
| 383 | return 0; | 388 | return 0; |
| 384 | 389 | ||
| 385 | egfmt: | 390 | egfmt: |
| 386 | icd->num_user_formats = 0; | ||
| 387 | vfree(icd->user_formats); | 391 | vfree(icd->user_formats); |
| 388 | return ret; | 392 | return ret; |
| 389 | } | 393 | } |
| @@ -662,7 +666,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 662 | if (icd->streamer && icd->streamer != file) | 666 | if (icd->streamer && icd->streamer != file) |
| 663 | return -EBUSY; | 667 | return -EBUSY; |
| 664 | 668 | ||
| 665 | if (icd->vb_vidq.bufs[0]) { | 669 | if (is_streaming(to_soc_camera_host(icd->dev.parent), icd)) { |
| 666 | dev_err(&icd->dev, "S_FMT denied: queue initialised\n"); | 670 | dev_err(&icd->dev, "S_FMT denied: queue initialised\n"); |
| 667 | return -EBUSY; | 671 | return -EBUSY; |
| 668 | } | 672 | } |
| @@ -903,14 +907,17 @@ static int soc_camera_s_crop(struct file *file, void *fh, | |||
| 903 | if (ret < 0) { | 907 | if (ret < 0) { |
| 904 | dev_err(&icd->dev, | 908 | dev_err(&icd->dev, |
| 905 | "S_CROP denied: getting current crop failed\n"); | 909 | "S_CROP denied: getting current crop failed\n"); |
| 906 | } else if (icd->vb_vidq.bufs[0] && | 910 | } else if ((a->c.width == current_crop.c.width && |
| 907 | (a->c.width != current_crop.c.width || | 911 | a->c.height == current_crop.c.height) || |
| 908 | a->c.height != current_crop.c.height)) { | 912 | !is_streaming(ici, icd)) { |
| 913 | /* same size or not streaming - use .set_crop() */ | ||
| 914 | ret = ici->ops->set_crop(icd, a); | ||
| 915 | } else if (ici->ops->set_livecrop) { | ||
| 916 | ret = ici->ops->set_livecrop(icd, a); | ||
| 917 | } else { | ||
| 909 | dev_err(&icd->dev, | 918 | dev_err(&icd->dev, |
| 910 | "S_CROP denied: queue initialised and sizes differ\n"); | 919 | "S_CROP denied: queue initialised and sizes differ\n"); |
| 911 | ret = -EBUSY; | 920 | ret = -EBUSY; |
| 912 | } else { | ||
| 913 | ret = ici->ops->set_crop(icd, a); | ||
| 914 | } | 921 | } |
| 915 | 922 | ||
| 916 | return ret; | 923 | return ret; |
diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c index ed77aa055b63..bea7c9cf4f88 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/video/soc_mediabus.c | |||
| @@ -15,132 +15,329 @@ | |||
| 15 | #include <media/v4l2-mediabus.h> | 15 | #include <media/v4l2-mediabus.h> |
| 16 | #include <media/soc_mediabus.h> | 16 | #include <media/soc_mediabus.h> |
| 17 | 17 | ||
| 18 | #define MBUS_IDX(f) (V4L2_MBUS_FMT_ ## f - V4L2_MBUS_FMT_FIXED - 1) | 18 | static const struct soc_mbus_lookup mbus_fmt[] = { |
| 19 | 19 | { | |
| 20 | static const struct soc_mbus_pixelfmt mbus_fmt[] = { | 20 | .code = V4L2_MBUS_FMT_YUYV8_2X8, |
| 21 | [MBUS_IDX(YUYV8_2X8)] = { | 21 | .fmt = { |
| 22 | .fourcc = V4L2_PIX_FMT_YUYV, | 22 | .fourcc = V4L2_PIX_FMT_YUYV, |
| 23 | .name = "YUYV", | 23 | .name = "YUYV", |
| 24 | .bits_per_sample = 8, | 24 | .bits_per_sample = 8, |
| 25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 26 | .order = SOC_MBUS_ORDER_LE, | 26 | .order = SOC_MBUS_ORDER_LE, |
| 27 | }, | 27 | }, |
| 28 | [MBUS_IDX(YVYU8_2X8)] = { | 28 | }, { |
| 29 | .code = V4L2_MBUS_FMT_YVYU8_2X8, | ||
| 30 | .fmt = { | ||
| 29 | .fourcc = V4L2_PIX_FMT_YVYU, | 31 | .fourcc = V4L2_PIX_FMT_YVYU, |
| 30 | .name = "YVYU", | 32 | .name = "YVYU", |
| 31 | .bits_per_sample = 8, | 33 | .bits_per_sample = 8, |
| 32 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 34 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 33 | .order = SOC_MBUS_ORDER_LE, | 35 | .order = SOC_MBUS_ORDER_LE, |
| 34 | }, | 36 | }, |
| 35 | [MBUS_IDX(UYVY8_2X8)] = { | 37 | }, { |
| 38 | .code = V4L2_MBUS_FMT_UYVY8_2X8, | ||
| 39 | .fmt = { | ||
| 36 | .fourcc = V4L2_PIX_FMT_UYVY, | 40 | .fourcc = V4L2_PIX_FMT_UYVY, |
| 37 | .name = "UYVY", | 41 | .name = "UYVY", |
| 38 | .bits_per_sample = 8, | 42 | .bits_per_sample = 8, |
| 39 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 43 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 40 | .order = SOC_MBUS_ORDER_LE, | 44 | .order = SOC_MBUS_ORDER_LE, |
| 41 | }, | 45 | }, |
| 42 | [MBUS_IDX(VYUY8_2X8)] = { | 46 | }, { |
| 47 | .code = V4L2_MBUS_FMT_VYUY8_2X8, | ||
| 48 | .fmt = { | ||
| 43 | .fourcc = V4L2_PIX_FMT_VYUY, | 49 | .fourcc = V4L2_PIX_FMT_VYUY, |
| 44 | .name = "VYUY", | 50 | .name = "VYUY", |
| 45 | .bits_per_sample = 8, | 51 | .bits_per_sample = 8, |
| 46 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 52 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 47 | .order = SOC_MBUS_ORDER_LE, | 53 | .order = SOC_MBUS_ORDER_LE, |
| 48 | }, | 54 | }, |
| 49 | [MBUS_IDX(RGB555_2X8_PADHI_LE)] = { | 55 | }, { |
| 56 | .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, | ||
| 57 | .fmt = { | ||
| 50 | .fourcc = V4L2_PIX_FMT_RGB555, | 58 | .fourcc = V4L2_PIX_FMT_RGB555, |
| 51 | .name = "RGB555", | 59 | .name = "RGB555", |
| 52 | .bits_per_sample = 8, | 60 | .bits_per_sample = 8, |
| 53 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 61 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 54 | .order = SOC_MBUS_ORDER_LE, | 62 | .order = SOC_MBUS_ORDER_LE, |
| 55 | }, | 63 | }, |
| 56 | [MBUS_IDX(RGB555_2X8_PADHI_BE)] = { | 64 | }, { |
| 65 | .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, | ||
| 66 | .fmt = { | ||
| 57 | .fourcc = V4L2_PIX_FMT_RGB555X, | 67 | .fourcc = V4L2_PIX_FMT_RGB555X, |
| 58 | .name = "RGB555X", | 68 | .name = "RGB555X", |
| 59 | .bits_per_sample = 8, | 69 | .bits_per_sample = 8, |
| 60 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 70 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 61 | .order = SOC_MBUS_ORDER_LE, | 71 | .order = SOC_MBUS_ORDER_LE, |
| 62 | }, | 72 | }, |
| 63 | [MBUS_IDX(RGB565_2X8_LE)] = { | 73 | }, { |
| 74 | .code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
| 75 | .fmt = { | ||
| 64 | .fourcc = V4L2_PIX_FMT_RGB565, | 76 | .fourcc = V4L2_PIX_FMT_RGB565, |
| 65 | .name = "RGB565", | 77 | .name = "RGB565", |
| 66 | .bits_per_sample = 8, | 78 | .bits_per_sample = 8, |
| 67 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 79 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 68 | .order = SOC_MBUS_ORDER_LE, | 80 | .order = SOC_MBUS_ORDER_LE, |
| 69 | }, | 81 | }, |
| 70 | [MBUS_IDX(RGB565_2X8_BE)] = { | 82 | }, { |
| 83 | .code = V4L2_MBUS_FMT_RGB565_2X8_BE, | ||
| 84 | .fmt = { | ||
| 71 | .fourcc = V4L2_PIX_FMT_RGB565X, | 85 | .fourcc = V4L2_PIX_FMT_RGB565X, |
| 72 | .name = "RGB565X", | 86 | .name = "RGB565X", |
| 73 | .bits_per_sample = 8, | 87 | .bits_per_sample = 8, |
| 74 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 88 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 75 | .order = SOC_MBUS_ORDER_LE, | 89 | .order = SOC_MBUS_ORDER_LE, |
| 76 | }, | 90 | }, |
| 77 | [MBUS_IDX(SBGGR8_1X8)] = { | 91 | }, { |
| 92 | .code = V4L2_MBUS_FMT_SBGGR8_1X8, | ||
| 93 | .fmt = { | ||
| 78 | .fourcc = V4L2_PIX_FMT_SBGGR8, | 94 | .fourcc = V4L2_PIX_FMT_SBGGR8, |
| 79 | .name = "Bayer 8 BGGR", | 95 | .name = "Bayer 8 BGGR", |
| 80 | .bits_per_sample = 8, | 96 | .bits_per_sample = 8, |
| 81 | .packing = SOC_MBUS_PACKING_NONE, | 97 | .packing = SOC_MBUS_PACKING_NONE, |
| 82 | .order = SOC_MBUS_ORDER_LE, | 98 | .order = SOC_MBUS_ORDER_LE, |
| 83 | }, | 99 | }, |
| 84 | [MBUS_IDX(SBGGR10_1X10)] = { | 100 | }, { |
| 101 | .code = V4L2_MBUS_FMT_SBGGR10_1X10, | ||
| 102 | .fmt = { | ||
| 85 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 103 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
| 86 | .name = "Bayer 10 BGGR", | 104 | .name = "Bayer 10 BGGR", |
| 87 | .bits_per_sample = 10, | 105 | .bits_per_sample = 10, |
| 88 | .packing = SOC_MBUS_PACKING_EXTEND16, | 106 | .packing = SOC_MBUS_PACKING_EXTEND16, |
| 89 | .order = SOC_MBUS_ORDER_LE, | 107 | .order = SOC_MBUS_ORDER_LE, |
| 90 | }, | 108 | }, |
| 91 | [MBUS_IDX(Y8_1X8)] = { | 109 | }, { |
| 110 | .code = V4L2_MBUS_FMT_Y8_1X8, | ||
| 111 | .fmt = { | ||
| 92 | .fourcc = V4L2_PIX_FMT_GREY, | 112 | .fourcc = V4L2_PIX_FMT_GREY, |
| 93 | .name = "Grey", | 113 | .name = "Grey", |
| 94 | .bits_per_sample = 8, | 114 | .bits_per_sample = 8, |
| 95 | .packing = SOC_MBUS_PACKING_NONE, | 115 | .packing = SOC_MBUS_PACKING_NONE, |
| 96 | .order = SOC_MBUS_ORDER_LE, | 116 | .order = SOC_MBUS_ORDER_LE, |
| 97 | }, | 117 | }, |
| 98 | [MBUS_IDX(Y10_1X10)] = { | 118 | }, { |
| 119 | .code = V4L2_MBUS_FMT_Y10_1X10, | ||
| 120 | .fmt = { | ||
| 99 | .fourcc = V4L2_PIX_FMT_Y10, | 121 | .fourcc = V4L2_PIX_FMT_Y10, |
| 100 | .name = "Grey 10bit", | 122 | .name = "Grey 10bit", |
| 101 | .bits_per_sample = 10, | 123 | .bits_per_sample = 10, |
| 102 | .packing = SOC_MBUS_PACKING_EXTEND16, | 124 | .packing = SOC_MBUS_PACKING_EXTEND16, |
| 103 | .order = SOC_MBUS_ORDER_LE, | 125 | .order = SOC_MBUS_ORDER_LE, |
| 104 | }, | 126 | }, |
| 105 | [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = { | 127 | }, { |
| 128 | .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, | ||
| 129 | .fmt = { | ||
| 106 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 130 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
| 107 | .name = "Bayer 10 BGGR", | 131 | .name = "Bayer 10 BGGR", |
| 108 | .bits_per_sample = 8, | 132 | .bits_per_sample = 8, |
| 109 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 133 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 110 | .order = SOC_MBUS_ORDER_LE, | 134 | .order = SOC_MBUS_ORDER_LE, |
| 111 | }, | 135 | }, |
| 112 | [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = { | 136 | }, { |
| 137 | .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, | ||
| 138 | .fmt = { | ||
| 113 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 139 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
| 114 | .name = "Bayer 10 BGGR", | 140 | .name = "Bayer 10 BGGR", |
| 115 | .bits_per_sample = 8, | 141 | .bits_per_sample = 8, |
| 116 | .packing = SOC_MBUS_PACKING_2X8_PADLO, | 142 | .packing = SOC_MBUS_PACKING_2X8_PADLO, |
| 117 | .order = SOC_MBUS_ORDER_LE, | 143 | .order = SOC_MBUS_ORDER_LE, |
| 118 | }, | 144 | }, |
| 119 | [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = { | 145 | }, { |
| 146 | .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, | ||
| 147 | .fmt = { | ||
| 120 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 148 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
| 121 | .name = "Bayer 10 BGGR", | 149 | .name = "Bayer 10 BGGR", |
| 122 | .bits_per_sample = 8, | 150 | .bits_per_sample = 8, |
| 123 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 151 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
| 124 | .order = SOC_MBUS_ORDER_BE, | 152 | .order = SOC_MBUS_ORDER_BE, |
| 125 | }, | 153 | }, |
| 126 | [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = { | 154 | }, { |
| 155 | .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, | ||
| 156 | .fmt = { | ||
| 127 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 157 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
| 128 | .name = "Bayer 10 BGGR", | 158 | .name = "Bayer 10 BGGR", |
| 129 | .bits_per_sample = 8, | 159 | .bits_per_sample = 8, |
| 130 | .packing = SOC_MBUS_PACKING_2X8_PADLO, | 160 | .packing = SOC_MBUS_PACKING_2X8_PADLO, |
| 131 | .order = SOC_MBUS_ORDER_BE, | 161 | .order = SOC_MBUS_ORDER_BE, |
| 132 | }, | 162 | }, |
| 163 | }, { | ||
| 164 | .code = V4L2_MBUS_FMT_JPEG_1X8, | ||
| 165 | .fmt = { | ||
| 166 | .fourcc = V4L2_PIX_FMT_JPEG, | ||
| 167 | .name = "JPEG", | ||
| 168 | .bits_per_sample = 8, | ||
| 169 | .packing = SOC_MBUS_PACKING_VARIABLE, | ||
| 170 | .order = SOC_MBUS_ORDER_LE, | ||
| 171 | }, | ||
| 172 | }, { | ||
| 173 | .code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE, | ||
| 174 | .fmt = { | ||
| 175 | .fourcc = V4L2_PIX_FMT_RGB444, | ||
| 176 | .name = "RGB444", | ||
| 177 | .bits_per_sample = 8, | ||
| 178 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
| 179 | .order = SOC_MBUS_ORDER_BE, | ||
| 180 | }, | ||
| 181 | }, { | ||
| 182 | .code = V4L2_MBUS_FMT_YUYV8_1_5X8, | ||
| 183 | .fmt = { | ||
| 184 | .fourcc = V4L2_PIX_FMT_YUV420, | ||
| 185 | .name = "YUYV 4:2:0", | ||
| 186 | .bits_per_sample = 8, | ||
| 187 | .packing = SOC_MBUS_PACKING_1_5X8, | ||
| 188 | .order = SOC_MBUS_ORDER_LE, | ||
| 189 | }, | ||
| 190 | }, { | ||
| 191 | .code = V4L2_MBUS_FMT_YVYU8_1_5X8, | ||
| 192 | .fmt = { | ||
| 193 | .fourcc = V4L2_PIX_FMT_YVU420, | ||
| 194 | .name = "YVYU 4:2:0", | ||
| 195 | .bits_per_sample = 8, | ||
| 196 | .packing = SOC_MBUS_PACKING_1_5X8, | ||
| 197 | .order = SOC_MBUS_ORDER_LE, | ||
| 198 | }, | ||
| 199 | }, { | ||
| 200 | .code = V4L2_MBUS_FMT_UYVY8_1X16, | ||
| 201 | .fmt = { | ||
| 202 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
| 203 | .name = "UYVY 16bit", | ||
| 204 | .bits_per_sample = 16, | ||
| 205 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 206 | .order = SOC_MBUS_ORDER_LE, | ||
| 207 | }, | ||
| 208 | }, { | ||
| 209 | .code = V4L2_MBUS_FMT_VYUY8_1X16, | ||
| 210 | .fmt = { | ||
| 211 | .fourcc = V4L2_PIX_FMT_VYUY, | ||
| 212 | .name = "VYUY 16bit", | ||
| 213 | .bits_per_sample = 16, | ||
| 214 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 215 | .order = SOC_MBUS_ORDER_LE, | ||
| 216 | }, | ||
| 217 | }, { | ||
| 218 | .code = V4L2_MBUS_FMT_YUYV8_1X16, | ||
| 219 | .fmt = { | ||
| 220 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
| 221 | .name = "YUYV 16bit", | ||
| 222 | .bits_per_sample = 16, | ||
| 223 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 224 | .order = SOC_MBUS_ORDER_LE, | ||
| 225 | }, | ||
| 226 | }, { | ||
| 227 | .code = V4L2_MBUS_FMT_YVYU8_1X16, | ||
| 228 | .fmt = { | ||
| 229 | .fourcc = V4L2_PIX_FMT_YVYU, | ||
| 230 | .name = "YVYU 16bit", | ||
| 231 | .bits_per_sample = 16, | ||
| 232 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 233 | .order = SOC_MBUS_ORDER_LE, | ||
| 234 | }, | ||
| 235 | }, { | ||
| 236 | .code = V4L2_MBUS_FMT_SGRBG8_1X8, | ||
| 237 | .fmt = { | ||
| 238 | .fourcc = V4L2_PIX_FMT_SGRBG8, | ||
| 239 | .name = "Bayer 8 GRBG", | ||
| 240 | .bits_per_sample = 8, | ||
| 241 | .packing = SOC_MBUS_PACKING_NONE, | ||
| 242 | .order = SOC_MBUS_ORDER_LE, | ||
| 243 | }, | ||
| 244 | }, { | ||
| 245 | .code = V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, | ||
| 246 | .fmt = { | ||
| 247 | .fourcc = V4L2_PIX_FMT_SGRBG10DPCM8, | ||
| 248 | .name = "Bayer 10 BGGR DPCM 8", | ||
| 249 | .bits_per_sample = 8, | ||
| 250 | .packing = SOC_MBUS_PACKING_NONE, | ||
| 251 | .order = SOC_MBUS_ORDER_LE, | ||
| 252 | }, | ||
| 253 | }, { | ||
| 254 | .code = V4L2_MBUS_FMT_SGBRG10_1X10, | ||
| 255 | .fmt = { | ||
| 256 | .fourcc = V4L2_PIX_FMT_SGBRG10, | ||
| 257 | .name = "Bayer 10 GBRG", | ||
| 258 | .bits_per_sample = 10, | ||
| 259 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 260 | .order = SOC_MBUS_ORDER_LE, | ||
| 261 | }, | ||
| 262 | }, { | ||
| 263 | .code = V4L2_MBUS_FMT_SGRBG10_1X10, | ||
| 264 | .fmt = { | ||
| 265 | .fourcc = V4L2_PIX_FMT_SGRBG10, | ||
| 266 | .name = "Bayer 10 GRBG", | ||
| 267 | .bits_per_sample = 10, | ||
| 268 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 269 | .order = SOC_MBUS_ORDER_LE, | ||
| 270 | }, | ||
| 271 | }, { | ||
| 272 | .code = V4L2_MBUS_FMT_SRGGB10_1X10, | ||
| 273 | .fmt = { | ||
| 274 | .fourcc = V4L2_PIX_FMT_SRGGB10, | ||
| 275 | .name = "Bayer 10 RGGB", | ||
| 276 | .bits_per_sample = 10, | ||
| 277 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 278 | .order = SOC_MBUS_ORDER_LE, | ||
| 279 | }, | ||
| 280 | }, { | ||
| 281 | .code = V4L2_MBUS_FMT_SBGGR12_1X12, | ||
| 282 | .fmt = { | ||
| 283 | .fourcc = V4L2_PIX_FMT_SBGGR12, | ||
| 284 | .name = "Bayer 12 BGGR", | ||
| 285 | .bits_per_sample = 12, | ||
| 286 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 287 | .order = SOC_MBUS_ORDER_LE, | ||
| 288 | }, | ||
| 289 | }, { | ||
| 290 | .code = V4L2_MBUS_FMT_SGBRG12_1X12, | ||
| 291 | .fmt = { | ||
| 292 | .fourcc = V4L2_PIX_FMT_SGBRG12, | ||
| 293 | .name = "Bayer 12 GBRG", | ||
| 294 | .bits_per_sample = 12, | ||
| 295 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 296 | .order = SOC_MBUS_ORDER_LE, | ||
| 297 | }, | ||
| 298 | }, { | ||
| 299 | .code = V4L2_MBUS_FMT_SGRBG12_1X12, | ||
| 300 | .fmt = { | ||
| 301 | .fourcc = V4L2_PIX_FMT_SGRBG12, | ||
| 302 | .name = "Bayer 12 GRBG", | ||
| 303 | .bits_per_sample = 12, | ||
| 304 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 305 | .order = SOC_MBUS_ORDER_LE, | ||
| 306 | }, | ||
| 307 | }, { | ||
| 308 | .code = V4L2_MBUS_FMT_SRGGB12_1X12, | ||
| 309 | .fmt = { | ||
| 310 | .fourcc = V4L2_PIX_FMT_SRGGB12, | ||
| 311 | .name = "Bayer 12 RGGB", | ||
| 312 | .bits_per_sample = 12, | ||
| 313 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
| 314 | .order = SOC_MBUS_ORDER_LE, | ||
| 315 | }, | ||
| 316 | }, | ||
| 133 | }; | 317 | }; |
| 134 | 318 | ||
| 135 | int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf) | 319 | int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf, |
| 320 | unsigned int *numerator, unsigned int *denominator) | ||
| 136 | { | 321 | { |
| 137 | switch (mf->packing) { | 322 | switch (mf->packing) { |
| 138 | case SOC_MBUS_PACKING_NONE: | 323 | case SOC_MBUS_PACKING_NONE: |
| 139 | case SOC_MBUS_PACKING_EXTEND16: | 324 | case SOC_MBUS_PACKING_EXTEND16: |
| 140 | return 1; | 325 | *numerator = 1; |
| 326 | *denominator = 1; | ||
| 327 | return 0; | ||
| 141 | case SOC_MBUS_PACKING_2X8_PADHI: | 328 | case SOC_MBUS_PACKING_2X8_PADHI: |
| 142 | case SOC_MBUS_PACKING_2X8_PADLO: | 329 | case SOC_MBUS_PACKING_2X8_PADLO: |
| 143 | return 2; | 330 | *numerator = 2; |
| 331 | *denominator = 1; | ||
| 332 | return 0; | ||
| 333 | case SOC_MBUS_PACKING_1_5X8: | ||
| 334 | *numerator = 3; | ||
| 335 | *denominator = 2; | ||
| 336 | return 0; | ||
| 337 | case SOC_MBUS_PACKING_VARIABLE: | ||
| 338 | *numerator = 0; | ||
| 339 | *denominator = 1; | ||
| 340 | return 0; | ||
| 144 | } | 341 | } |
| 145 | return -EINVAL; | 342 | return -EINVAL; |
| 146 | } | 343 | } |
| @@ -155,18 +352,34 @@ s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) | |||
| 155 | case SOC_MBUS_PACKING_2X8_PADLO: | 352 | case SOC_MBUS_PACKING_2X8_PADLO: |
| 156 | case SOC_MBUS_PACKING_EXTEND16: | 353 | case SOC_MBUS_PACKING_EXTEND16: |
| 157 | return width * 2; | 354 | return width * 2; |
| 355 | case SOC_MBUS_PACKING_1_5X8: | ||
| 356 | return width * 3 / 2; | ||
| 357 | case SOC_MBUS_PACKING_VARIABLE: | ||
| 358 | return 0; | ||
| 158 | } | 359 | } |
| 159 | return -EINVAL; | 360 | return -EINVAL; |
| 160 | } | 361 | } |
| 161 | EXPORT_SYMBOL(soc_mbus_bytes_per_line); | 362 | EXPORT_SYMBOL(soc_mbus_bytes_per_line); |
| 162 | 363 | ||
| 364 | const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc( | ||
| 365 | enum v4l2_mbus_pixelcode code, | ||
| 366 | const struct soc_mbus_lookup *lookup, | ||
| 367 | int n) | ||
| 368 | { | ||
| 369 | int i; | ||
| 370 | |||
| 371 | for (i = 0; i < n; i++) | ||
| 372 | if (lookup[i].code == code) | ||
| 373 | return &lookup[i].fmt; | ||
| 374 | |||
| 375 | return NULL; | ||
| 376 | } | ||
| 377 | EXPORT_SYMBOL(soc_mbus_find_fmtdesc); | ||
| 378 | |||
| 163 | const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( | 379 | const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( |
| 164 | enum v4l2_mbus_pixelcode code) | 380 | enum v4l2_mbus_pixelcode code) |
| 165 | { | 381 | { |
| 166 | if (code - V4L2_MBUS_FMT_FIXED > ARRAY_SIZE(mbus_fmt) || | 382 | return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt)); |
| 167 | code <= V4L2_MBUS_FMT_FIXED) | ||
| 168 | return NULL; | ||
| 169 | return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1; | ||
| 170 | } | 383 | } |
| 171 | EXPORT_SYMBOL(soc_mbus_get_fmtdesc); | 384 | EXPORT_SYMBOL(soc_mbus_get_fmtdesc); |
| 172 | 385 | ||
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 07fabdd9b465..6103d1b1081e 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
| @@ -267,21 +267,27 @@ hauppauge_tuner[] = | |||
| 267 | { TUNER_ABSENT, "Xceive XC4000"}, | 267 | { TUNER_ABSENT, "Xceive XC4000"}, |
| 268 | { TUNER_ABSENT, "Dibcom 7070"}, | 268 | { TUNER_ABSENT, "Dibcom 7070"}, |
| 269 | { TUNER_PHILIPS_TDA8290, "NXP 18271C2"}, | 269 | { TUNER_PHILIPS_TDA8290, "NXP 18271C2"}, |
| 270 | { TUNER_ABSENT, "unknown"}, | 270 | { TUNER_ABSENT, "Siano SMS1010"}, |
| 271 | { TUNER_ABSENT, "unknown"}, | 271 | { TUNER_ABSENT, "Siano SMS1150"}, |
| 272 | { TUNER_ABSENT, "unknown"}, | 272 | { TUNER_ABSENT, "MaxLinear 5007"}, |
| 273 | { TUNER_ABSENT, "unknown"}, | 273 | { TUNER_ABSENT, "TCL M09WPP_2P_E"}, |
| 274 | /* 160-169 */ | 274 | /* 160-169 */ |
| 275 | { TUNER_ABSENT, "unknown"}, | 275 | { TUNER_ABSENT, "Siano SMS1180"}, |
| 276 | { TUNER_ABSENT, "unknown"}, | 276 | { TUNER_ABSENT, "Maxim_MAX2165"}, |
| 277 | { TUNER_ABSENT, "unknown"}, | 277 | { TUNER_ABSENT, "Siano SMS1140"}, |
| 278 | { TUNER_ABSENT, "unknown"}, | 278 | { TUNER_ABSENT, "Siano SMS1150 B1"}, |
| 279 | { TUNER_ABSENT, "unknown"}, | 279 | { TUNER_ABSENT, "MaxLinear 111"}, |
| 280 | { TUNER_ABSENT, "unknown"}, | 280 | { TUNER_ABSENT, "Dibcom 7770"}, |
| 281 | { TUNER_ABSENT, "unknown"}, | 281 | { TUNER_ABSENT, "Siano SMS1180VNS"}, |
| 282 | { TUNER_ABSENT, "unknown"}, | 282 | { TUNER_ABSENT, "Siano SMS1184"}, |
| 283 | { TUNER_PHILIPS_FQ1236_MK5, "TCL M30WTP-4N-E"}, | 283 | { TUNER_PHILIPS_FQ1236_MK5, "TCL M30WTP-4N-E"}, |
| 284 | { TUNER_ABSENT, "unknown"}, | 284 | { TUNER_ABSENT, "TCL_M11WPP_2PN_E"}, |
| 285 | /* 170-179 */ | ||
| 286 | { TUNER_ABSENT, "MaxLinear 301"}, | ||
| 287 | { TUNER_ABSENT, "Mirics MSi001"}, | ||
| 288 | { TUNER_ABSENT, "MaxLinear MxL241SF"}, | ||
| 289 | { TUNER_ABSENT, "Xceive XC5000C"}, | ||
| 290 | { TUNER_ABSENT, "Montage M68TS2020"}, | ||
| 285 | }; | 291 | }; |
| 286 | 292 | ||
| 287 | /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are | 293 | /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are |
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c index 68b998bd203f..8f5266157f15 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/video/usbvision/usbvision-cards.c | |||
| @@ -1025,6 +1025,34 @@ struct usbvision_device_data_st usbvision_device_data[] = { | |||
| 1025 | .y_offset = -1, | 1025 | .y_offset = -1, |
| 1026 | .model_string = "Hauppauge WinTv-USB", | 1026 | .model_string = "Hauppauge WinTv-USB", |
| 1027 | }, | 1027 | }, |
| 1028 | [MICROCAM_NTSC] = { | ||
| 1029 | .interface = -1, | ||
| 1030 | .codec = CODEC_WEBCAM, | ||
| 1031 | .video_channels = 1, | ||
| 1032 | .video_norm = V4L2_STD_NTSC, | ||
| 1033 | .audio_channels = 0, | ||
| 1034 | .radio = 0, | ||
| 1035 | .vbi = 0, | ||
| 1036 | .tuner = 0, | ||
| 1037 | .tuner_type = 0, | ||
| 1038 | .x_offset = 71, | ||
| 1039 | .y_offset = 15, | ||
| 1040 | .model_string = "Nogatech USB MicroCam NTSC (NV3000N)", | ||
| 1041 | }, | ||
| 1042 | [MICROCAM_PAL] = { | ||
| 1043 | .interface = -1, | ||
| 1044 | .codec = CODEC_WEBCAM, | ||
| 1045 | .video_channels = 1, | ||
| 1046 | .video_norm = V4L2_STD_PAL, | ||
| 1047 | .audio_channels = 0, | ||
| 1048 | .radio = 0, | ||
| 1049 | .vbi = 0, | ||
| 1050 | .tuner = 0, | ||
| 1051 | .tuner_type = 0, | ||
| 1052 | .x_offset = 71, | ||
| 1053 | .y_offset = 18, | ||
| 1054 | .model_string = "Nogatech USB MicroCam PAL (NV3001P)", | ||
| 1055 | }, | ||
| 1028 | }; | 1056 | }; |
| 1029 | const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data); | 1057 | const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data); |
| 1030 | 1058 | ||
| @@ -1042,6 +1070,8 @@ struct usb_device_id usbvision_table[] = { | |||
| 1042 | { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG }, | 1070 | { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG }, |
| 1043 | { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN }, | 1071 | { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN }, |
| 1044 | { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH }, | 1072 | { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH }, |
| 1073 | { USB_DEVICE(0x0573, 0x3000), .driver_info = MICROCAM_NTSC }, | ||
| 1074 | { USB_DEVICE(0x0573, 0x3001), .driver_info = MICROCAM_PAL }, | ||
| 1045 | { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM }, | 1075 | { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM }, |
| 1046 | { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM }, | 1076 | { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM }, |
| 1047 | { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM }, | 1077 | { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM }, |
| @@ -1088,8 +1118,7 @@ struct usb_device_id usbvision_table[] = { | |||
| 1088 | { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM }, | 1118 | { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM }, |
| 1089 | { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB }, | 1119 | { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB }, |
| 1090 | { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM }, | 1120 | { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM }, |
| 1091 | { USB_DEVICE(0x2304, 0x0113), | 1121 | { USB_DEVICE(0x2304, 0x0113), .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, |
| 1092 | .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, | ||
| 1093 | { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 }, | 1122 | { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 }, |
| 1094 | { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 }, | 1123 | { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 }, |
| 1095 | { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 }, | 1124 | { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 }, |
diff --git a/drivers/media/video/usbvision/usbvision-cards.h b/drivers/media/video/usbvision/usbvision-cards.h index 9c6ad22960d8..a51cc1185cce 100644 --- a/drivers/media/video/usbvision/usbvision-cards.h +++ b/drivers/media/video/usbvision/usbvision-cards.h | |||
| @@ -63,5 +63,7 @@ | |||
| 63 | #define PINNA_PCTV_BUNGEE_PAL_FM 62 | 63 | #define PINNA_PCTV_BUNGEE_PAL_FM 62 |
| 64 | #define HPG_WINTV 63 | 64 | #define HPG_WINTV 63 |
| 65 | #define PINNA_PCTV_USB_NTSC_FM_V3 64 | 65 | #define PINNA_PCTV_USB_NTSC_FM_V3 64 |
| 66 | #define MICROCAM_NTSC 65 | ||
| 67 | #define MICROCAM_PAL 66 | ||
| 66 | 68 | ||
| 67 | extern const int usbvision_device_data_size; | 69 | extern const int usbvision_device_data_size; |
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index c8feb0d6fccf..f344411a4578 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
| @@ -49,10 +49,6 @@ static unsigned int core_debug; | |||
| 49 | module_param(core_debug, int, 0644); | 49 | module_param(core_debug, int, 0644); |
| 50 | MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); | 50 | MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); |
| 51 | 51 | ||
| 52 | static unsigned int force_testpattern; | ||
| 53 | module_param(force_testpattern, int, 0644); | ||
| 54 | MODULE_PARM_DESC(force_testpattern, "enable test pattern display [core]"); | ||
| 55 | |||
| 56 | static int adjust_compression = 1; /* Set the compression to be adaptive */ | 52 | static int adjust_compression = 1; /* Set the compression to be adaptive */ |
| 57 | module_param(adjust_compression, int, 0444); | 53 | module_param(adjust_compression, int, 0444); |
| 58 | MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device. Default: 1 (On)"); | 54 | MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device. Default: 1 (On)"); |
| @@ -388,90 +384,6 @@ void usbvision_scratch_free(struct usb_usbvision *usbvision) | |||
| 388 | } | 384 | } |
| 389 | 385 | ||
| 390 | /* | 386 | /* |
| 391 | * usbvision_testpattern() | ||
| 392 | * | ||
| 393 | * Procedure forms a test pattern (yellow grid on blue background). | ||
| 394 | * | ||
| 395 | * Parameters: | ||
| 396 | * fullframe: if TRUE then entire frame is filled, otherwise the procedure | ||
| 397 | * continues from the current scanline. | ||
| 398 | * pmode 0: fill the frame with solid blue color (like on VCR or TV) | ||
| 399 | * 1: Draw a colored grid | ||
| 400 | * | ||
| 401 | */ | ||
| 402 | static void usbvision_testpattern(struct usb_usbvision *usbvision, | ||
| 403 | int fullframe, int pmode) | ||
| 404 | { | ||
| 405 | static const char proc[] = "usbvision_testpattern"; | ||
| 406 | struct usbvision_frame *frame; | ||
| 407 | unsigned char *f; | ||
| 408 | int num_cell = 0; | ||
| 409 | int scan_length = 0; | ||
| 410 | static int num_pass; | ||
| 411 | |||
| 412 | if (usbvision == NULL) { | ||
| 413 | printk(KERN_ERR "%s: usbvision == NULL\n", proc); | ||
| 414 | return; | ||
| 415 | } | ||
| 416 | if (usbvision->cur_frame == NULL) { | ||
| 417 | printk(KERN_ERR "%s: usbvision->cur_frame is NULL.\n", proc); | ||
| 418 | return; | ||
| 419 | } | ||
| 420 | |||
| 421 | /* Grab the current frame */ | ||
| 422 | frame = usbvision->cur_frame; | ||
| 423 | |||
| 424 | /* Optionally start at the beginning */ | ||
| 425 | if (fullframe) { | ||
| 426 | frame->curline = 0; | ||
| 427 | frame->scanlength = 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | /* Form every scan line */ | ||
| 431 | for (; frame->curline < frame->frmheight; frame->curline++) { | ||
| 432 | int i; | ||
| 433 | |||
| 434 | f = frame->data + (usbvision->curwidth * 3 * frame->curline); | ||
| 435 | for (i = 0; i < usbvision->curwidth; i++) { | ||
| 436 | unsigned char cb = 0x80; | ||
| 437 | unsigned char cg = 0; | ||
| 438 | unsigned char cr = 0; | ||
| 439 | |||
| 440 | if (pmode == 1) { | ||
| 441 | if (frame->curline % 32 == 0) | ||
| 442 | cb = 0, cg = cr = 0xFF; | ||
| 443 | else if (i % 32 == 0) { | ||
| 444 | if (frame->curline % 32 == 1) | ||
| 445 | num_cell++; | ||
| 446 | cb = 0, cg = cr = 0xFF; | ||
| 447 | } else { | ||
| 448 | cb = | ||
| 449 | ((num_cell * 7) + | ||
| 450 | num_pass) & 0xFF; | ||
| 451 | cg = | ||
| 452 | ((num_cell * 5) + | ||
| 453 | num_pass * 2) & 0xFF; | ||
| 454 | cr = | ||
| 455 | ((num_cell * 3) + | ||
| 456 | num_pass * 3) & 0xFF; | ||
| 457 | } | ||
| 458 | } else { | ||
| 459 | /* Just the blue screen */ | ||
| 460 | } | ||
| 461 | |||
| 462 | *f++ = cb; | ||
| 463 | *f++ = cg; | ||
| 464 | *f++ = cr; | ||
| 465 | scan_length += 3; | ||
| 466 | } | ||
| 467 | } | ||
| 468 | |||
| 469 | frame->grabstate = frame_state_done; | ||
| 470 | frame->scanlength += scan_length; | ||
| 471 | ++num_pass; | ||
| 472 | } | ||
| 473 | |||
| 474 | /* | ||
| 475 | * usbvision_decompress_alloc() | 387 | * usbvision_decompress_alloc() |
| 476 | * | 388 | * |
| 477 | * allocates intermediate buffer for decompression | 389 | * allocates intermediate buffer for decompression |
| @@ -571,10 +483,6 @@ static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) | |||
| 571 | frame->scanstate = scan_state_lines; | 483 | frame->scanstate = scan_state_lines; |
| 572 | frame->curline = 0; | 484 | frame->curline = 0; |
| 573 | 485 | ||
| 574 | if (force_testpattern) { | ||
| 575 | usbvision_testpattern(usbvision, 1, 1); | ||
| 576 | return parse_state_next_frame; | ||
| 577 | } | ||
| 578 | return parse_state_continue; | 486 | return parse_state_continue; |
| 579 | } | 487 | } |
| 580 | 488 | ||
| @@ -1679,6 +1587,55 @@ int usbvision_power_off(struct usb_usbvision *usbvision) | |||
| 1679 | return err_code; | 1587 | return err_code; |
| 1680 | } | 1588 | } |
| 1681 | 1589 | ||
| 1590 | /* configure webcam image sensor using the serial port */ | ||
| 1591 | static int usbvision_init_webcam(struct usb_usbvision *usbvision) | ||
| 1592 | { | ||
| 1593 | int rc; | ||
| 1594 | int i; | ||
| 1595 | static char init_values[38][3] = { | ||
| 1596 | { 0x04, 0x12, 0x08 }, { 0x05, 0xff, 0xc8 }, { 0x06, 0x18, 0x07 }, { 0x07, 0x90, 0x00 }, | ||
| 1597 | { 0x09, 0x00, 0x00 }, { 0x0a, 0x00, 0x00 }, { 0x0b, 0x08, 0x00 }, { 0x0d, 0xcc, 0xcc }, | ||
| 1598 | { 0x0e, 0x13, 0x14 }, { 0x10, 0x9b, 0x83 }, { 0x11, 0x5a, 0x3f }, { 0x12, 0xe4, 0x73 }, | ||
| 1599 | { 0x13, 0x88, 0x84 }, { 0x14, 0x89, 0x80 }, { 0x15, 0x00, 0x20 }, { 0x16, 0x00, 0x00 }, | ||
| 1600 | { 0x17, 0xff, 0xa0 }, { 0x18, 0x6b, 0x20 }, { 0x19, 0x22, 0x40 }, { 0x1a, 0x10, 0x07 }, | ||
| 1601 | { 0x1b, 0x00, 0x47 }, { 0x1c, 0x03, 0xe0 }, { 0x1d, 0x00, 0x00 }, { 0x1e, 0x00, 0x00 }, | ||
| 1602 | { 0x1f, 0x00, 0x00 }, { 0x20, 0x00, 0x00 }, { 0x21, 0x00, 0x00 }, { 0x22, 0x00, 0x00 }, | ||
| 1603 | { 0x23, 0x00, 0x00 }, { 0x24, 0x00, 0x00 }, { 0x25, 0x00, 0x00 }, { 0x26, 0x00, 0x00 }, | ||
| 1604 | { 0x27, 0x00, 0x00 }, { 0x28, 0x00, 0x00 }, { 0x29, 0x00, 0x00 }, { 0x08, 0x80, 0x60 }, | ||
| 1605 | { 0x0f, 0x2d, 0x24 }, { 0x0c, 0x80, 0x80 } | ||
| 1606 | }; | ||
| 1607 | char value[3]; | ||
| 1608 | |||
| 1609 | /* the only difference between PAL and NTSC init_values */ | ||
| 1610 | if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_NTSC) | ||
| 1611 | init_values[4][1] = 0x34; | ||
| 1612 | |||
| 1613 | for (i = 0; i < sizeof(init_values) / 3; i++) { | ||
| 1614 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); | ||
| 1615 | memcpy(value, init_values[i], 3); | ||
| 1616 | rc = usb_control_msg(usbvision->dev, | ||
| 1617 | usb_sndctrlpipe(usbvision->dev, 1), | ||
| 1618 | USBVISION_OP_CODE, | ||
| 1619 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
| 1620 | USB_RECIP_ENDPOINT, 0, | ||
| 1621 | (__u16) USBVISION_SER_DAT1, value, | ||
| 1622 | 3, HZ); | ||
| 1623 | if (rc < 0) | ||
| 1624 | return rc; | ||
| 1625 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SIO); | ||
| 1626 | /* write 3 bytes to the serial port using SIO mode */ | ||
| 1627 | usbvision_write_reg(usbvision, USBVISION_SER_CONT, 3 | 0x10); | ||
| 1628 | usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, 0); | ||
| 1629 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); | ||
| 1630 | usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_IO_2); | ||
| 1631 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT); | ||
| 1632 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_DAT_IO); | ||
| 1633 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT | USBVISION_DAT_IO); | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | return 0; | ||
| 1637 | } | ||
| 1638 | |||
| 1682 | /* | 1639 | /* |
| 1683 | * usbvision_set_video_format() | 1640 | * usbvision_set_video_format() |
| 1684 | * | 1641 | * |
| @@ -1797,6 +1754,13 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, | |||
| 1797 | 1754 | ||
| 1798 | frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ | 1755 | frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ |
| 1799 | 1756 | ||
| 1757 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { | ||
| 1758 | if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_PAL) | ||
| 1759 | frame_drop = 25; | ||
| 1760 | else | ||
| 1761 | frame_drop = 30; | ||
| 1762 | } | ||
| 1763 | |||
| 1800 | /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... | 1764 | /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... |
| 1801 | => frame_skip = 4; | 1765 | => frame_skip = 4; |
| 1802 | => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; | 1766 | => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; |
| @@ -2046,6 +2010,12 @@ int usbvision_set_input(struct usb_usbvision *usbvision) | |||
| 2046 | value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ | 2010 | value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ |
| 2047 | } | 2011 | } |
| 2048 | 2012 | ||
| 2013 | /* webcam is only 480 pixels wide, both PAL and NTSC version */ | ||
| 2014 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { | ||
| 2015 | value[0] = 0xe0; | ||
| 2016 | value[1] = 0x01; /* 0x01E0 -> 480 Input video line length */ | ||
| 2017 | } | ||
| 2018 | |||
| 2049 | if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { | 2019 | if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { |
| 2050 | value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; | 2020 | value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; |
| 2051 | value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; | 2021 | value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; |
| @@ -2148,7 +2118,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) | |||
| 2148 | (__u16) USBVISION_DRM_PRM1, value, 8, HZ); | 2118 | (__u16) USBVISION_DRM_PRM1, value, 8, HZ); |
| 2149 | 2119 | ||
| 2150 | if (rc < 0) { | 2120 | if (rc < 0) { |
| 2151 | dev_err(&usbvision->dev->dev, "%sERROR=%d\n", __func__, rc); | 2121 | dev_err(&usbvision->dev->dev, "%s: ERROR=%d\n", __func__, rc); |
| 2152 | return rc; | 2122 | return rc; |
| 2153 | } | 2123 | } |
| 2154 | 2124 | ||
| @@ -2180,8 +2150,15 @@ int usbvision_power_on(struct usb_usbvision *usbvision) | |||
| 2180 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | 2150 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, |
| 2181 | USBVISION_SSPND_EN | USBVISION_RES2); | 2151 | USBVISION_SSPND_EN | USBVISION_RES2); |
| 2182 | 2152 | ||
| 2153 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { | ||
| 2154 | usbvision_write_reg(usbvision, USBVISION_VIN_REG1, | ||
| 2155 | USBVISION_16_422_SYNC | USBVISION_HVALID_PO); | ||
| 2156 | usbvision_write_reg(usbvision, USBVISION_VIN_REG2, | ||
| 2157 | USBVISION_NOHVALID | USBVISION_KEEP_BLANK); | ||
| 2158 | } | ||
| 2183 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | 2159 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, |
| 2184 | USBVISION_SSPND_EN | USBVISION_PWR_VID); | 2160 | USBVISION_SSPND_EN | USBVISION_PWR_VID); |
| 2161 | mdelay(10); | ||
| 2185 | err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, | 2162 | err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, |
| 2186 | USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); | 2163 | USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); |
| 2187 | if (err_code == 1) | 2164 | if (err_code == 1) |
| @@ -2310,6 +2287,8 @@ int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel) | |||
| 2310 | 2287 | ||
| 2311 | int usbvision_setup(struct usb_usbvision *usbvision, int format) | 2288 | int usbvision_setup(struct usb_usbvision *usbvision, int format) |
| 2312 | { | 2289 | { |
| 2290 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) | ||
| 2291 | usbvision_init_webcam(usbvision); | ||
| 2313 | usbvision_set_video_format(usbvision, format); | 2292 | usbvision_set_video_format(usbvision, format); |
| 2314 | usbvision_set_dram_settings(usbvision); | 2293 | usbvision_set_dram_settings(usbvision); |
| 2315 | usbvision_set_compress_params(usbvision); | 2294 | usbvision_set_compress_params(usbvision); |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 05b1344181cd..d7f97513b289 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
| @@ -222,7 +222,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) | |||
| 222 | i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); | 222 | i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); |
| 223 | 223 | ||
| 224 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { | 224 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { |
| 225 | printk(KERN_ERR "usbvision_register: can't write reg\n"); | 225 | printk(KERN_ERR "usbvision_i2c_register: can't write reg\n"); |
| 226 | return -EBUSY; | 226 | return -EBUSY; |
| 227 | } | 227 | } |
| 228 | 228 | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 9855fbe5927a..ea8ea8a48dfe 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
| @@ -1471,7 +1471,8 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) | |||
| 1471 | 1471 | ||
| 1472 | /* This should be here to make i2c clients to be able to register */ | 1472 | /* This should be here to make i2c clients to be able to register */ |
| 1473 | /* first switch off audio */ | 1473 | /* first switch off audio */ |
| 1474 | usbvision_audio_off(usbvision); | 1474 | if (usbvision_device_data[model].audio_channels > 0) |
| 1475 | usbvision_audio_off(usbvision); | ||
| 1475 | if (!power_on_at_open) { | 1476 | if (!power_on_at_open) { |
| 1476 | /* and then power up the noisy tuner */ | 1477 | /* and then power up the noisy tuner */ |
| 1477 | usbvision_power_on(usbvision); | 1478 | usbvision_power_on(usbvision); |
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 8074787fd1ac..43cf61fe4943 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h | |||
| @@ -59,6 +59,11 @@ | |||
| 59 | #define USBVISION_AUDIO_RADIO 2 | 59 | #define USBVISION_AUDIO_RADIO 2 |
| 60 | #define USBVISION_AUDIO_MUTE 3 | 60 | #define USBVISION_AUDIO_MUTE 3 |
| 61 | #define USBVISION_SER_MODE 0x07 | 61 | #define USBVISION_SER_MODE 0x07 |
| 62 | #define USBVISION_CLK_OUT (1 << 0) | ||
| 63 | #define USBVISION_DAT_IO (1 << 1) | ||
| 64 | #define USBVISION_SENS_OUT (1 << 2) | ||
| 65 | #define USBVISION_SER_MODE_SOFT (0 << 4) | ||
| 66 | #define USBVISION_SER_MODE_SIO (1 << 4) | ||
| 62 | #define USBVISION_SER_ADRS 0x08 | 67 | #define USBVISION_SER_ADRS 0x08 |
| 63 | #define USBVISION_SER_CONT 0x09 | 68 | #define USBVISION_SER_CONT 0x09 |
| 64 | #define USBVISION_SER_DAT1 0x0A | 69 | #define USBVISION_SER_DAT1 0x0A |
| @@ -328,6 +333,7 @@ struct usbvision_frame { | |||
| 328 | 333 | ||
| 329 | #define CODEC_SAA7113 7113 | 334 | #define CODEC_SAA7113 7113 |
| 330 | #define CODEC_SAA7111 7111 | 335 | #define CODEC_SAA7111 7111 |
| 336 | #define CODEC_WEBCAM 3000 | ||
| 331 | #define BRIDGE_NT1003 1003 | 337 | #define BRIDGE_NT1003 1003 |
| 332 | #define BRIDGE_NT1004 1004 | 338 | #define BRIDGE_NT1004 1004 |
| 333 | #define BRIDGE_NT1005 1005 | 339 | #define BRIDGE_NT1005 1005 |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 59f8a9ad3796..a4db26fa2f53 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
| @@ -42,281 +42,313 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
| 42 | .selector = UVC_PU_BRIGHTNESS_CONTROL, | 42 | .selector = UVC_PU_BRIGHTNESS_CONTROL, |
| 43 | .index = 0, | 43 | .index = 0, |
| 44 | .size = 2, | 44 | .size = 2, |
| 45 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 45 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 46 | | UVC_CONTROL_RESTORE, | 46 | | UVC_CTRL_FLAG_GET_RANGE |
| 47 | | UVC_CTRL_FLAG_RESTORE, | ||
| 47 | }, | 48 | }, |
| 48 | { | 49 | { |
| 49 | .entity = UVC_GUID_UVC_PROCESSING, | 50 | .entity = UVC_GUID_UVC_PROCESSING, |
| 50 | .selector = UVC_PU_CONTRAST_CONTROL, | 51 | .selector = UVC_PU_CONTRAST_CONTROL, |
| 51 | .index = 1, | 52 | .index = 1, |
| 52 | .size = 2, | 53 | .size = 2, |
| 53 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 54 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 54 | | UVC_CONTROL_RESTORE, | 55 | | UVC_CTRL_FLAG_GET_RANGE |
| 56 | | UVC_CTRL_FLAG_RESTORE, | ||
| 55 | }, | 57 | }, |
| 56 | { | 58 | { |
| 57 | .entity = UVC_GUID_UVC_PROCESSING, | 59 | .entity = UVC_GUID_UVC_PROCESSING, |
| 58 | .selector = UVC_PU_HUE_CONTROL, | 60 | .selector = UVC_PU_HUE_CONTROL, |
| 59 | .index = 2, | 61 | .index = 2, |
| 60 | .size = 2, | 62 | .size = 2, |
| 61 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 63 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 62 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 64 | | UVC_CTRL_FLAG_GET_RANGE |
| 65 | | UVC_CTRL_FLAG_RESTORE | ||
| 66 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 63 | }, | 67 | }, |
| 64 | { | 68 | { |
| 65 | .entity = UVC_GUID_UVC_PROCESSING, | 69 | .entity = UVC_GUID_UVC_PROCESSING, |
| 66 | .selector = UVC_PU_SATURATION_CONTROL, | 70 | .selector = UVC_PU_SATURATION_CONTROL, |
| 67 | .index = 3, | 71 | .index = 3, |
| 68 | .size = 2, | 72 | .size = 2, |
| 69 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 73 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 70 | | UVC_CONTROL_RESTORE, | 74 | | UVC_CTRL_FLAG_GET_RANGE |
| 75 | | UVC_CTRL_FLAG_RESTORE, | ||
| 71 | }, | 76 | }, |
| 72 | { | 77 | { |
| 73 | .entity = UVC_GUID_UVC_PROCESSING, | 78 | .entity = UVC_GUID_UVC_PROCESSING, |
| 74 | .selector = UVC_PU_SHARPNESS_CONTROL, | 79 | .selector = UVC_PU_SHARPNESS_CONTROL, |
| 75 | .index = 4, | 80 | .index = 4, |
| 76 | .size = 2, | 81 | .size = 2, |
| 77 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 82 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 78 | | UVC_CONTROL_RESTORE, | 83 | | UVC_CTRL_FLAG_GET_RANGE |
| 84 | | UVC_CTRL_FLAG_RESTORE, | ||
| 79 | }, | 85 | }, |
| 80 | { | 86 | { |
| 81 | .entity = UVC_GUID_UVC_PROCESSING, | 87 | .entity = UVC_GUID_UVC_PROCESSING, |
| 82 | .selector = UVC_PU_GAMMA_CONTROL, | 88 | .selector = UVC_PU_GAMMA_CONTROL, |
| 83 | .index = 5, | 89 | .index = 5, |
| 84 | .size = 2, | 90 | .size = 2, |
| 85 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 91 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 86 | | UVC_CONTROL_RESTORE, | 92 | | UVC_CTRL_FLAG_GET_RANGE |
| 93 | | UVC_CTRL_FLAG_RESTORE, | ||
| 87 | }, | 94 | }, |
| 88 | { | 95 | { |
| 89 | .entity = UVC_GUID_UVC_PROCESSING, | 96 | .entity = UVC_GUID_UVC_PROCESSING, |
| 90 | .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | 97 | .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, |
| 91 | .index = 6, | 98 | .index = 6, |
| 92 | .size = 2, | 99 | .size = 2, |
| 93 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 100 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 94 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 101 | | UVC_CTRL_FLAG_GET_RANGE |
| 102 | | UVC_CTRL_FLAG_RESTORE | ||
| 103 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 95 | }, | 104 | }, |
| 96 | { | 105 | { |
| 97 | .entity = UVC_GUID_UVC_PROCESSING, | 106 | .entity = UVC_GUID_UVC_PROCESSING, |
| 98 | .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, | 107 | .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, |
| 99 | .index = 7, | 108 | .index = 7, |
| 100 | .size = 4, | 109 | .size = 4, |
| 101 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 110 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 102 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 111 | | UVC_CTRL_FLAG_GET_RANGE |
| 112 | | UVC_CTRL_FLAG_RESTORE | ||
| 113 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 103 | }, | 114 | }, |
| 104 | { | 115 | { |
| 105 | .entity = UVC_GUID_UVC_PROCESSING, | 116 | .entity = UVC_GUID_UVC_PROCESSING, |
| 106 | .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, | 117 | .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, |
| 107 | .index = 8, | 118 | .index = 8, |
| 108 | .size = 2, | 119 | .size = 2, |
| 109 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 120 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 110 | | UVC_CONTROL_RESTORE, | 121 | | UVC_CTRL_FLAG_GET_RANGE |
| 122 | | UVC_CTRL_FLAG_RESTORE, | ||
| 111 | }, | 123 | }, |
| 112 | { | 124 | { |
| 113 | .entity = UVC_GUID_UVC_PROCESSING, | 125 | .entity = UVC_GUID_UVC_PROCESSING, |
| 114 | .selector = UVC_PU_GAIN_CONTROL, | 126 | .selector = UVC_PU_GAIN_CONTROL, |
| 115 | .index = 9, | 127 | .index = 9, |
| 116 | .size = 2, | 128 | .size = 2, |
| 117 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 129 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 118 | | UVC_CONTROL_RESTORE, | 130 | | UVC_CTRL_FLAG_GET_RANGE |
| 131 | | UVC_CTRL_FLAG_RESTORE, | ||
| 119 | }, | 132 | }, |
| 120 | { | 133 | { |
| 121 | .entity = UVC_GUID_UVC_PROCESSING, | 134 | .entity = UVC_GUID_UVC_PROCESSING, |
| 122 | .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, | 135 | .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, |
| 123 | .index = 10, | 136 | .index = 10, |
| 124 | .size = 1, | 137 | .size = 1, |
| 125 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 138 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 126 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 139 | | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, |
| 127 | }, | 140 | }, |
| 128 | { | 141 | { |
| 129 | .entity = UVC_GUID_UVC_PROCESSING, | 142 | .entity = UVC_GUID_UVC_PROCESSING, |
| 130 | .selector = UVC_PU_HUE_AUTO_CONTROL, | 143 | .selector = UVC_PU_HUE_AUTO_CONTROL, |
| 131 | .index = 11, | 144 | .index = 11, |
| 132 | .size = 1, | 145 | .size = 1, |
| 133 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 146 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 134 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 147 | | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, |
| 135 | }, | 148 | }, |
| 136 | { | 149 | { |
| 137 | .entity = UVC_GUID_UVC_PROCESSING, | 150 | .entity = UVC_GUID_UVC_PROCESSING, |
| 138 | .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | 151 | .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, |
| 139 | .index = 12, | 152 | .index = 12, |
| 140 | .size = 1, | 153 | .size = 1, |
| 141 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 154 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 142 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 155 | | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, |
| 143 | }, | 156 | }, |
| 144 | { | 157 | { |
| 145 | .entity = UVC_GUID_UVC_PROCESSING, | 158 | .entity = UVC_GUID_UVC_PROCESSING, |
| 146 | .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | 159 | .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, |
| 147 | .index = 13, | 160 | .index = 13, |
| 148 | .size = 1, | 161 | .size = 1, |
| 149 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 162 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 150 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 163 | | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, |
| 151 | }, | 164 | }, |
| 152 | { | 165 | { |
| 153 | .entity = UVC_GUID_UVC_PROCESSING, | 166 | .entity = UVC_GUID_UVC_PROCESSING, |
| 154 | .selector = UVC_PU_DIGITAL_MULTIPLIER_CONTROL, | 167 | .selector = UVC_PU_DIGITAL_MULTIPLIER_CONTROL, |
| 155 | .index = 14, | 168 | .index = 14, |
| 156 | .size = 2, | 169 | .size = 2, |
| 157 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 170 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 158 | | UVC_CONTROL_RESTORE, | 171 | | UVC_CTRL_FLAG_GET_RANGE |
| 172 | | UVC_CTRL_FLAG_RESTORE, | ||
| 159 | }, | 173 | }, |
| 160 | { | 174 | { |
| 161 | .entity = UVC_GUID_UVC_PROCESSING, | 175 | .entity = UVC_GUID_UVC_PROCESSING, |
| 162 | .selector = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, | 176 | .selector = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, |
| 163 | .index = 15, | 177 | .index = 15, |
| 164 | .size = 2, | 178 | .size = 2, |
| 165 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 179 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 166 | | UVC_CONTROL_RESTORE, | 180 | | UVC_CTRL_FLAG_GET_RANGE |
| 181 | | UVC_CTRL_FLAG_RESTORE, | ||
| 167 | }, | 182 | }, |
| 168 | { | 183 | { |
| 169 | .entity = UVC_GUID_UVC_PROCESSING, | 184 | .entity = UVC_GUID_UVC_PROCESSING, |
| 170 | .selector = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL, | 185 | .selector = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL, |
| 171 | .index = 16, | 186 | .index = 16, |
| 172 | .size = 1, | 187 | .size = 1, |
| 173 | .flags = UVC_CONTROL_GET_CUR, | 188 | .flags = UVC_CTRL_FLAG_GET_CUR, |
| 174 | }, | 189 | }, |
| 175 | { | 190 | { |
| 176 | .entity = UVC_GUID_UVC_PROCESSING, | 191 | .entity = UVC_GUID_UVC_PROCESSING, |
| 177 | .selector = UVC_PU_ANALOG_LOCK_STATUS_CONTROL, | 192 | .selector = UVC_PU_ANALOG_LOCK_STATUS_CONTROL, |
| 178 | .index = 17, | 193 | .index = 17, |
| 179 | .size = 1, | 194 | .size = 1, |
| 180 | .flags = UVC_CONTROL_GET_CUR, | 195 | .flags = UVC_CTRL_FLAG_GET_CUR, |
| 181 | }, | 196 | }, |
| 182 | { | 197 | { |
| 183 | .entity = UVC_GUID_UVC_CAMERA, | 198 | .entity = UVC_GUID_UVC_CAMERA, |
| 184 | .selector = UVC_CT_SCANNING_MODE_CONTROL, | 199 | .selector = UVC_CT_SCANNING_MODE_CONTROL, |
| 185 | .index = 0, | 200 | .index = 0, |
| 186 | .size = 1, | 201 | .size = 1, |
| 187 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 202 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 188 | | UVC_CONTROL_RESTORE, | 203 | | UVC_CTRL_FLAG_RESTORE, |
| 189 | }, | 204 | }, |
| 190 | { | 205 | { |
| 191 | .entity = UVC_GUID_UVC_CAMERA, | 206 | .entity = UVC_GUID_UVC_CAMERA, |
| 192 | .selector = UVC_CT_AE_MODE_CONTROL, | 207 | .selector = UVC_CT_AE_MODE_CONTROL, |
| 193 | .index = 1, | 208 | .index = 1, |
| 194 | .size = 1, | 209 | .size = 1, |
| 195 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 210 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 196 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_GET_RES | 211 | | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_GET_RES |
| 197 | | UVC_CONTROL_RESTORE, | 212 | | UVC_CTRL_FLAG_RESTORE, |
| 198 | }, | 213 | }, |
| 199 | { | 214 | { |
| 200 | .entity = UVC_GUID_UVC_CAMERA, | 215 | .entity = UVC_GUID_UVC_CAMERA, |
| 201 | .selector = UVC_CT_AE_PRIORITY_CONTROL, | 216 | .selector = UVC_CT_AE_PRIORITY_CONTROL, |
| 202 | .index = 2, | 217 | .index = 2, |
| 203 | .size = 1, | 218 | .size = 1, |
| 204 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 219 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 205 | | UVC_CONTROL_RESTORE, | 220 | | UVC_CTRL_FLAG_RESTORE, |
| 206 | }, | 221 | }, |
| 207 | { | 222 | { |
| 208 | .entity = UVC_GUID_UVC_CAMERA, | 223 | .entity = UVC_GUID_UVC_CAMERA, |
| 209 | .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, | 224 | .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, |
| 210 | .index = 3, | 225 | .index = 3, |
| 211 | .size = 4, | 226 | .size = 4, |
| 212 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 227 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 213 | | UVC_CONTROL_RESTORE, | 228 | | UVC_CTRL_FLAG_GET_RANGE |
| 229 | | UVC_CTRL_FLAG_RESTORE, | ||
| 214 | }, | 230 | }, |
| 215 | { | 231 | { |
| 216 | .entity = UVC_GUID_UVC_CAMERA, | 232 | .entity = UVC_GUID_UVC_CAMERA, |
| 217 | .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, | 233 | .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, |
| 218 | .index = 4, | 234 | .index = 4, |
| 219 | .size = 1, | 235 | .size = 1, |
| 220 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_RESTORE, | 236 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_RESTORE, |
| 221 | }, | 237 | }, |
| 222 | { | 238 | { |
| 223 | .entity = UVC_GUID_UVC_CAMERA, | 239 | .entity = UVC_GUID_UVC_CAMERA, |
| 224 | .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, | 240 | .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, |
| 225 | .index = 5, | 241 | .index = 5, |
| 226 | .size = 2, | 242 | .size = 2, |
| 227 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 243 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 228 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 244 | | UVC_CTRL_FLAG_GET_RANGE |
| 245 | | UVC_CTRL_FLAG_RESTORE | ||
| 246 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 229 | }, | 247 | }, |
| 230 | { | 248 | { |
| 231 | .entity = UVC_GUID_UVC_CAMERA, | 249 | .entity = UVC_GUID_UVC_CAMERA, |
| 232 | .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, | 250 | .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, |
| 233 | .index = 6, | 251 | .index = 6, |
| 234 | .size = 2, | 252 | .size = 2, |
| 235 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | 253 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN |
| 236 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | 254 | | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES |
| 237 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | 255 | | UVC_CTRL_FLAG_GET_DEF |
| 256 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 238 | }, | 257 | }, |
| 239 | { | 258 | { |
| 240 | .entity = UVC_GUID_UVC_CAMERA, | 259 | .entity = UVC_GUID_UVC_CAMERA, |
| 241 | .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, | 260 | .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, |
| 242 | .index = 7, | 261 | .index = 7, |
| 243 | .size = 2, | 262 | .size = 2, |
| 244 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 263 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 245 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 264 | | UVC_CTRL_FLAG_GET_RANGE |
| 265 | | UVC_CTRL_FLAG_RESTORE | ||
| 266 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 246 | }, | 267 | }, |
| 247 | { | 268 | { |
| 248 | .entity = UVC_GUID_UVC_CAMERA, | 269 | .entity = UVC_GUID_UVC_CAMERA, |
| 249 | .selector = UVC_CT_IRIS_RELATIVE_CONTROL, | 270 | .selector = UVC_CT_IRIS_RELATIVE_CONTROL, |
| 250 | .index = 8, | 271 | .index = 8, |
| 251 | .size = 1, | 272 | .size = 1, |
| 252 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_AUTO_UPDATE, | 273 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 274 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 253 | }, | 275 | }, |
| 254 | { | 276 | { |
| 255 | .entity = UVC_GUID_UVC_CAMERA, | 277 | .entity = UVC_GUID_UVC_CAMERA, |
| 256 | .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, | 278 | .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, |
| 257 | .index = 9, | 279 | .index = 9, |
| 258 | .size = 2, | 280 | .size = 2, |
| 259 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 281 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 260 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 282 | | UVC_CTRL_FLAG_GET_RANGE |
| 283 | | UVC_CTRL_FLAG_RESTORE | ||
| 284 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 261 | }, | 285 | }, |
| 262 | { | 286 | { |
| 263 | .entity = UVC_GUID_UVC_CAMERA, | 287 | .entity = UVC_GUID_UVC_CAMERA, |
| 264 | .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, | 288 | .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, |
| 265 | .index = 10, | 289 | .index = 10, |
| 266 | .size = 3, | 290 | .size = 3, |
| 267 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | 291 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN |
| 268 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | 292 | | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES |
| 269 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | 293 | | UVC_CTRL_FLAG_GET_DEF |
| 294 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 270 | }, | 295 | }, |
| 271 | { | 296 | { |
| 272 | .entity = UVC_GUID_UVC_CAMERA, | 297 | .entity = UVC_GUID_UVC_CAMERA, |
| 273 | .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, | 298 | .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, |
| 274 | .index = 11, | 299 | .index = 11, |
| 275 | .size = 8, | 300 | .size = 8, |
| 276 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 301 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 277 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 302 | | UVC_CTRL_FLAG_GET_RANGE |
| 303 | | UVC_CTRL_FLAG_RESTORE | ||
| 304 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 278 | }, | 305 | }, |
| 279 | { | 306 | { |
| 280 | .entity = UVC_GUID_UVC_CAMERA, | 307 | .entity = UVC_GUID_UVC_CAMERA, |
| 281 | .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, | 308 | .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, |
| 282 | .index = 12, | 309 | .index = 12, |
| 283 | .size = 4, | 310 | .size = 4, |
| 284 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | 311 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN |
| 285 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | 312 | | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES |
| 286 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | 313 | | UVC_CTRL_FLAG_GET_DEF |
| 314 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 287 | }, | 315 | }, |
| 288 | { | 316 | { |
| 289 | .entity = UVC_GUID_UVC_CAMERA, | 317 | .entity = UVC_GUID_UVC_CAMERA, |
| 290 | .selector = UVC_CT_ROLL_ABSOLUTE_CONTROL, | 318 | .selector = UVC_CT_ROLL_ABSOLUTE_CONTROL, |
| 291 | .index = 13, | 319 | .index = 13, |
| 292 | .size = 2, | 320 | .size = 2, |
| 293 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 321 | .flags = UVC_CTRL_FLAG_SET_CUR |
| 294 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 322 | | UVC_CTRL_FLAG_GET_RANGE |
| 323 | | UVC_CTRL_FLAG_RESTORE | ||
| 324 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 295 | }, | 325 | }, |
| 296 | { | 326 | { |
| 297 | .entity = UVC_GUID_UVC_CAMERA, | 327 | .entity = UVC_GUID_UVC_CAMERA, |
| 298 | .selector = UVC_CT_ROLL_RELATIVE_CONTROL, | 328 | .selector = UVC_CT_ROLL_RELATIVE_CONTROL, |
| 299 | .index = 14, | 329 | .index = 14, |
| 300 | .size = 2, | 330 | .size = 2, |
| 301 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | 331 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN |
| 302 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | 332 | | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES |
| 303 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | 333 | | UVC_CTRL_FLAG_GET_DEF |
| 334 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 304 | }, | 335 | }, |
| 305 | { | 336 | { |
| 306 | .entity = UVC_GUID_UVC_CAMERA, | 337 | .entity = UVC_GUID_UVC_CAMERA, |
| 307 | .selector = UVC_CT_FOCUS_AUTO_CONTROL, | 338 | .selector = UVC_CT_FOCUS_AUTO_CONTROL, |
| 308 | .index = 17, | 339 | .index = 17, |
| 309 | .size = 1, | 340 | .size = 1, |
| 310 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 341 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 311 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 342 | | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, |
| 312 | }, | 343 | }, |
| 313 | { | 344 | { |
| 314 | .entity = UVC_GUID_UVC_CAMERA, | 345 | .entity = UVC_GUID_UVC_CAMERA, |
| 315 | .selector = UVC_CT_PRIVACY_CONTROL, | 346 | .selector = UVC_CT_PRIVACY_CONTROL, |
| 316 | .index = 18, | 347 | .index = 18, |
| 317 | .size = 1, | 348 | .size = 1, |
| 318 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 349 | .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR |
| 319 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 350 | | UVC_CTRL_FLAG_RESTORE |
| 351 | | UVC_CTRL_FLAG_AUTO_UPDATE, | ||
| 320 | }, | 352 | }, |
| 321 | }; | 353 | }; |
| 322 | 354 | ||
| @@ -816,7 +848,7 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, | |||
| 816 | { | 848 | { |
| 817 | int ret; | 849 | int ret; |
| 818 | 850 | ||
| 819 | if (ctrl->info.flags & UVC_CONTROL_GET_DEF) { | 851 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { |
| 820 | ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, | 852 | ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, |
| 821 | chain->dev->intfnum, ctrl->info.selector, | 853 | chain->dev->intfnum, ctrl->info.selector, |
| 822 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF), | 854 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF), |
| @@ -825,7 +857,7 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, | |||
| 825 | return ret; | 857 | return ret; |
| 826 | } | 858 | } |
| 827 | 859 | ||
| 828 | if (ctrl->info.flags & UVC_CONTROL_GET_MIN) { | 860 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) { |
| 829 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, | 861 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, |
| 830 | chain->dev->intfnum, ctrl->info.selector, | 862 | chain->dev->intfnum, ctrl->info.selector, |
| 831 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN), | 863 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN), |
| @@ -833,7 +865,7 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, | |||
| 833 | if (ret < 0) | 865 | if (ret < 0) |
| 834 | return ret; | 866 | return ret; |
| 835 | } | 867 | } |
| 836 | if (ctrl->info.flags & UVC_CONTROL_GET_MAX) { | 868 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) { |
| 837 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, | 869 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, |
| 838 | chain->dev->intfnum, ctrl->info.selector, | 870 | chain->dev->intfnum, ctrl->info.selector, |
| 839 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX), | 871 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX), |
| @@ -841,7 +873,7 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, | |||
| 841 | if (ret < 0) | 873 | if (ret < 0) |
| 842 | return ret; | 874 | return ret; |
| 843 | } | 875 | } |
| 844 | if (ctrl->info.flags & UVC_CONTROL_GET_RES) { | 876 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { |
| 845 | ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, | 877 | ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, |
| 846 | chain->dev->intfnum, ctrl->info.selector, | 878 | chain->dev->intfnum, ctrl->info.selector, |
| 847 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), | 879 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), |
| @@ -879,9 +911,9 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
| 879 | strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); | 911 | strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); |
| 880 | v4l2_ctrl->flags = 0; | 912 | v4l2_ctrl->flags = 0; |
| 881 | 913 | ||
| 882 | if (!(ctrl->info.flags & UVC_CONTROL_GET_CUR)) | 914 | if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) |
| 883 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; | 915 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; |
| 884 | if (!(ctrl->info.flags & UVC_CONTROL_SET_CUR)) | 916 | if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) |
| 885 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 917 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
| 886 | 918 | ||
| 887 | if (!ctrl->cached) { | 919 | if (!ctrl->cached) { |
| @@ -890,7 +922,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
| 890 | goto done; | 922 | goto done; |
| 891 | } | 923 | } |
| 892 | 924 | ||
| 893 | if (ctrl->info.flags & UVC_CONTROL_GET_DEF) { | 925 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { |
| 894 | v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF, | 926 | v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF, |
| 895 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF)); | 927 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF)); |
| 896 | } | 928 | } |
| @@ -927,15 +959,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
| 927 | break; | 959 | break; |
| 928 | } | 960 | } |
| 929 | 961 | ||
| 930 | if (ctrl->info.flags & UVC_CONTROL_GET_MIN) | 962 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) |
| 931 | v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, | 963 | v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, |
| 932 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); | 964 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); |
| 933 | 965 | ||
| 934 | if (ctrl->info.flags & UVC_CONTROL_GET_MAX) | 966 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) |
| 935 | v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, | 967 | v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, |
| 936 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); | 968 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); |
| 937 | 969 | ||
| 938 | if (ctrl->info.flags & UVC_CONTROL_GET_RES) | 970 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) |
| 939 | v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, | 971 | v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, |
| 940 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | 972 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); |
| 941 | 973 | ||
| @@ -983,6 +1015,24 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain, | |||
| 983 | } | 1015 | } |
| 984 | 1016 | ||
| 985 | menu_info = &mapping->menu_info[query_menu->index]; | 1017 | menu_info = &mapping->menu_info[query_menu->index]; |
| 1018 | |||
| 1019 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { | ||
| 1020 | s32 bitmap; | ||
| 1021 | |||
| 1022 | if (!ctrl->cached) { | ||
| 1023 | ret = uvc_ctrl_populate_cache(chain, ctrl); | ||
| 1024 | if (ret < 0) | ||
| 1025 | goto done; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | bitmap = mapping->get(mapping, UVC_GET_RES, | ||
| 1029 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | ||
| 1030 | if (!(bitmap & menu_info->value)) { | ||
| 1031 | ret = -EINVAL; | ||
| 1032 | goto done; | ||
| 1033 | } | ||
| 1034 | } | ||
| 1035 | |||
| 986 | strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); | 1036 | strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); |
| 987 | 1037 | ||
| 988 | done: | 1038 | done: |
| @@ -1039,7 +1089,7 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, | |||
| 1039 | * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent | 1089 | * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent |
| 1040 | * uvc_ctrl_get from using the cached value. | 1090 | * uvc_ctrl_get from using the cached value. |
| 1041 | */ | 1091 | */ |
| 1042 | if (ctrl->info.flags & UVC_CONTROL_AUTO_UPDATE) | 1092 | if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE) |
| 1043 | ctrl->loaded = 0; | 1093 | ctrl->loaded = 0; |
| 1044 | 1094 | ||
| 1045 | if (!ctrl->dirty) | 1095 | if (!ctrl->dirty) |
| @@ -1094,7 +1144,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, | |||
| 1094 | int ret; | 1144 | int ret; |
| 1095 | 1145 | ||
| 1096 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 1146 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); |
| 1097 | if (ctrl == NULL || (ctrl->info.flags & UVC_CONTROL_GET_CUR) == 0) | 1147 | if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) |
| 1098 | return -EINVAL; | 1148 | return -EINVAL; |
| 1099 | 1149 | ||
| 1100 | if (!ctrl->loaded) { | 1150 | if (!ctrl->loaded) { |
| @@ -1136,7 +1186,7 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
| 1136 | int ret; | 1186 | int ret; |
| 1137 | 1187 | ||
| 1138 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 1188 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); |
| 1139 | if (ctrl == NULL || (ctrl->info.flags & UVC_CONTROL_SET_CUR) == 0) | 1189 | if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0) |
| 1140 | return -EINVAL; | 1190 | return -EINVAL; |
| 1141 | 1191 | ||
| 1142 | /* Clamp out of range values. */ | 1192 | /* Clamp out of range values. */ |
| @@ -1171,6 +1221,23 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
| 1171 | if (xctrl->value < 0 || xctrl->value >= mapping->menu_count) | 1221 | if (xctrl->value < 0 || xctrl->value >= mapping->menu_count) |
| 1172 | return -ERANGE; | 1222 | return -ERANGE; |
| 1173 | value = mapping->menu_info[xctrl->value].value; | 1223 | value = mapping->menu_info[xctrl->value].value; |
| 1224 | |||
| 1225 | /* Valid menu indices are reported by the GET_RES request for | ||
| 1226 | * UVC controls that support it. | ||
| 1227 | */ | ||
| 1228 | if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { | ||
| 1229 | if (!ctrl->cached) { | ||
| 1230 | ret = uvc_ctrl_populate_cache(chain, ctrl); | ||
| 1231 | if (ret < 0) | ||
| 1232 | return ret; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | step = mapping->get(mapping, UVC_GET_RES, | ||
| 1236 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | ||
| 1237 | if (!(step & value)) | ||
| 1238 | return -ERANGE; | ||
| 1239 | } | ||
| 1240 | |||
| 1174 | break; | 1241 | break; |
| 1175 | 1242 | ||
| 1176 | default: | 1243 | default: |
| @@ -1183,7 +1250,7 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
| 1183 | * operation. | 1250 | * operation. |
| 1184 | */ | 1251 | */ |
| 1185 | if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) { | 1252 | if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) { |
| 1186 | if ((ctrl->info.flags & UVC_CONTROL_GET_CUR) == 0) { | 1253 | if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { |
| 1187 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | 1254 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), |
| 1188 | 0, ctrl->info.size); | 1255 | 0, ctrl->info.size); |
| 1189 | } else { | 1256 | } else { |
| @@ -1230,17 +1297,17 @@ static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev, | |||
| 1230 | 1297 | ||
| 1231 | static const struct uvc_ctrl_fixup fixups[] = { | 1298 | static const struct uvc_ctrl_fixup fixups[] = { |
| 1232 | { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1, | 1299 | { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1, |
| 1233 | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | 1300 | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | |
| 1234 | UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | | 1301 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR | |
| 1235 | UVC_CONTROL_AUTO_UPDATE }, | 1302 | UVC_CTRL_FLAG_AUTO_UPDATE }, |
| 1236 | { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1, | 1303 | { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1, |
| 1237 | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | 1304 | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | |
| 1238 | UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | | 1305 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR | |
| 1239 | UVC_CONTROL_AUTO_UPDATE }, | 1306 | UVC_CTRL_FLAG_AUTO_UPDATE }, |
| 1240 | { { USB_DEVICE(0x046d, 0x0994) }, 9, 1, | 1307 | { { USB_DEVICE(0x046d, 0x0994) }, 9, 1, |
| 1241 | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | 1308 | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | |
| 1242 | UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | | 1309 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR | |
| 1243 | UVC_CONTROL_AUTO_UPDATE }, | 1310 | UVC_CTRL_FLAG_AUTO_UPDATE }, |
| 1244 | }; | 1311 | }; |
| 1245 | 1312 | ||
| 1246 | unsigned int i; | 1313 | unsigned int i; |
| @@ -1297,21 +1364,23 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev, | |||
| 1297 | goto done; | 1364 | goto done; |
| 1298 | } | 1365 | } |
| 1299 | 1366 | ||
| 1300 | info->flags = UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | 1367 | info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
| 1301 | | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | 1368 | | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF |
| 1302 | | (data[0] & UVC_CONTROL_CAP_GET ? UVC_CONTROL_GET_CUR : 0) | 1369 | | (data[0] & UVC_CONTROL_CAP_GET ? |
| 1303 | | (data[0] & UVC_CONTROL_CAP_SET ? UVC_CONTROL_SET_CUR : 0) | 1370 | UVC_CTRL_FLAG_GET_CUR : 0) |
| 1371 | | (data[0] & UVC_CONTROL_CAP_SET ? | ||
| 1372 | UVC_CTRL_FLAG_SET_CUR : 0) | ||
| 1304 | | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? | 1373 | | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? |
| 1305 | UVC_CONTROL_AUTO_UPDATE : 0); | 1374 | UVC_CTRL_FLAG_AUTO_UPDATE : 0); |
| 1306 | 1375 | ||
| 1307 | uvc_ctrl_fixup_xu_info(dev, ctrl, info); | 1376 | uvc_ctrl_fixup_xu_info(dev, ctrl, info); |
| 1308 | 1377 | ||
| 1309 | uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, " | 1378 | uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, " |
| 1310 | "flags { get %u set %u auto %u }.\n", | 1379 | "flags { get %u set %u auto %u }.\n", |
| 1311 | info->entity, info->selector, info->size, | 1380 | info->entity, info->selector, info->size, |
| 1312 | (info->flags & UVC_CONTROL_GET_CUR) ? 1 : 0, | 1381 | (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0, |
| 1313 | (info->flags & UVC_CONTROL_SET_CUR) ? 1 : 0, | 1382 | (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0, |
| 1314 | (info->flags & UVC_CONTROL_AUTO_UPDATE) ? 1 : 0); | 1383 | (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0); |
| 1315 | 1384 | ||
| 1316 | done: | 1385 | done: |
| 1317 | kfree(data); | 1386 | kfree(data); |
| @@ -1344,32 +1413,33 @@ static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev, | |||
| 1344 | } | 1413 | } |
| 1345 | 1414 | ||
| 1346 | int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | 1415 | int uvc_xu_ctrl_query(struct uvc_video_chain *chain, |
| 1347 | struct uvc_xu_control *xctrl, int set) | 1416 | struct uvc_xu_control_query *xqry) |
| 1348 | { | 1417 | { |
| 1349 | struct uvc_entity *entity; | 1418 | struct uvc_entity *entity; |
| 1350 | struct uvc_control *ctrl = NULL; | 1419 | struct uvc_control *ctrl; |
| 1351 | unsigned int i, found = 0; | 1420 | unsigned int i, found = 0; |
| 1352 | int restore = 0; | 1421 | __u32 reqflags; |
| 1353 | __u8 *data; | 1422 | __u16 size; |
| 1423 | __u8 *data = NULL; | ||
| 1354 | int ret; | 1424 | int ret; |
| 1355 | 1425 | ||
| 1356 | /* Find the extension unit. */ | 1426 | /* Find the extension unit. */ |
| 1357 | list_for_each_entry(entity, &chain->entities, chain) { | 1427 | list_for_each_entry(entity, &chain->entities, chain) { |
| 1358 | if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT && | 1428 | if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT && |
| 1359 | entity->id == xctrl->unit) | 1429 | entity->id == xqry->unit) |
| 1360 | break; | 1430 | break; |
| 1361 | } | 1431 | } |
| 1362 | 1432 | ||
| 1363 | if (entity->id != xctrl->unit) { | 1433 | if (entity->id != xqry->unit) { |
| 1364 | uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n", | 1434 | uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n", |
| 1365 | xctrl->unit); | 1435 | xqry->unit); |
| 1366 | return -EINVAL; | 1436 | return -ENOENT; |
| 1367 | } | 1437 | } |
| 1368 | 1438 | ||
| 1369 | /* Find the control and perform delayed initialization if needed. */ | 1439 | /* Find the control and perform delayed initialization if needed. */ |
| 1370 | for (i = 0; i < entity->ncontrols; ++i) { | 1440 | for (i = 0; i < entity->ncontrols; ++i) { |
| 1371 | ctrl = &entity->controls[i]; | 1441 | ctrl = &entity->controls[i]; |
| 1372 | if (ctrl->index == xctrl->selector - 1) { | 1442 | if (ctrl->index == xqry->selector - 1) { |
| 1373 | found = 1; | 1443 | found = 1; |
| 1374 | break; | 1444 | break; |
| 1375 | } | 1445 | } |
| @@ -1377,8 +1447,8 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | |||
| 1377 | 1447 | ||
| 1378 | if (!found) { | 1448 | if (!found) { |
| 1379 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n", | 1449 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n", |
| 1380 | entity->extension.guidExtensionCode, xctrl->selector); | 1450 | entity->extension.guidExtensionCode, xqry->selector); |
| 1381 | return -EINVAL; | 1451 | return -ENOENT; |
| 1382 | } | 1452 | } |
| 1383 | 1453 | ||
| 1384 | if (mutex_lock_interruptible(&chain->ctrl_mutex)) | 1454 | if (mutex_lock_interruptible(&chain->ctrl_mutex)) |
| @@ -1390,43 +1460,72 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | |||
| 1390 | goto done; | 1460 | goto done; |
| 1391 | } | 1461 | } |
| 1392 | 1462 | ||
| 1393 | /* Validate control data size. */ | 1463 | /* Validate the required buffer size and flags for the request */ |
| 1394 | if (ctrl->info.size != xctrl->size) { | 1464 | reqflags = 0; |
| 1465 | size = ctrl->info.size; | ||
| 1466 | |||
| 1467 | switch (xqry->query) { | ||
| 1468 | case UVC_GET_CUR: | ||
| 1469 | reqflags = UVC_CTRL_FLAG_GET_CUR; | ||
| 1470 | break; | ||
| 1471 | case UVC_GET_MIN: | ||
| 1472 | reqflags = UVC_CTRL_FLAG_GET_MIN; | ||
| 1473 | break; | ||
| 1474 | case UVC_GET_MAX: | ||
| 1475 | reqflags = UVC_CTRL_FLAG_GET_MAX; | ||
| 1476 | break; | ||
| 1477 | case UVC_GET_DEF: | ||
| 1478 | reqflags = UVC_CTRL_FLAG_GET_DEF; | ||
| 1479 | break; | ||
| 1480 | case UVC_GET_RES: | ||
| 1481 | reqflags = UVC_CTRL_FLAG_GET_RES; | ||
| 1482 | break; | ||
| 1483 | case UVC_SET_CUR: | ||
| 1484 | reqflags = UVC_CTRL_FLAG_SET_CUR; | ||
| 1485 | break; | ||
| 1486 | case UVC_GET_LEN: | ||
| 1487 | size = 2; | ||
| 1488 | break; | ||
| 1489 | case UVC_GET_INFO: | ||
| 1490 | size = 1; | ||
| 1491 | break; | ||
| 1492 | default: | ||
| 1395 | ret = -EINVAL; | 1493 | ret = -EINVAL; |
| 1396 | goto done; | 1494 | goto done; |
| 1397 | } | 1495 | } |
| 1398 | 1496 | ||
| 1399 | if ((set && !(ctrl->info.flags & UVC_CONTROL_SET_CUR)) || | 1497 | if (size != xqry->size) { |
| 1400 | (!set && !(ctrl->info.flags & UVC_CONTROL_GET_CUR))) { | 1498 | ret = -ENOBUFS; |
| 1401 | ret = -EINVAL; | ||
| 1402 | goto done; | 1499 | goto done; |
| 1403 | } | 1500 | } |
| 1404 | 1501 | ||
| 1405 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | 1502 | if (reqflags && !(ctrl->info.flags & reqflags)) { |
| 1406 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | 1503 | ret = -EBADRQC; |
| 1407 | ctrl->info.size); | 1504 | goto done; |
| 1408 | data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT); | 1505 | } |
| 1409 | restore = set; | ||
| 1410 | 1506 | ||
| 1411 | if (set && copy_from_user(data, xctrl->data, xctrl->size)) { | 1507 | data = kmalloc(size, GFP_KERNEL); |
| 1508 | if (data == NULL) { | ||
| 1509 | ret = -ENOMEM; | ||
| 1510 | goto done; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | if (xqry->query == UVC_SET_CUR && | ||
| 1514 | copy_from_user(data, xqry->data, size)) { | ||
| 1412 | ret = -EFAULT; | 1515 | ret = -EFAULT; |
| 1413 | goto done; | 1516 | goto done; |
| 1414 | } | 1517 | } |
| 1415 | 1518 | ||
| 1416 | ret = uvc_query_ctrl(chain->dev, set ? UVC_SET_CUR : UVC_GET_CUR, | 1519 | ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit, |
| 1417 | xctrl->unit, chain->dev->intfnum, xctrl->selector, | 1520 | chain->dev->intfnum, xqry->selector, data, size); |
| 1418 | data, xctrl->size); | ||
| 1419 | if (ret < 0) | 1521 | if (ret < 0) |
| 1420 | goto done; | 1522 | goto done; |
| 1421 | 1523 | ||
| 1422 | if (!set && copy_to_user(xctrl->data, data, xctrl->size)) | 1524 | if (xqry->query != UVC_SET_CUR && |
| 1525 | copy_to_user(xqry->data, data, size)) | ||
| 1423 | ret = -EFAULT; | 1526 | ret = -EFAULT; |
| 1424 | done: | 1527 | done: |
| 1425 | if (ret && restore) | 1528 | kfree(data); |
| 1426 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 1427 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
| 1428 | xctrl->size); | ||
| 1429 | |||
| 1430 | mutex_unlock(&chain->ctrl_mutex); | 1529 | mutex_unlock(&chain->ctrl_mutex); |
| 1431 | return ret; | 1530 | return ret; |
| 1432 | } | 1531 | } |
| @@ -1458,7 +1557,7 @@ int uvc_ctrl_resume_device(struct uvc_device *dev) | |||
| 1458 | ctrl = &entity->controls[i]; | 1557 | ctrl = &entity->controls[i]; |
| 1459 | 1558 | ||
| 1460 | if (!ctrl->initialized || !ctrl->modified || | 1559 | if (!ctrl->initialized || !ctrl->modified || |
| 1461 | (ctrl->info.flags & UVC_CONTROL_RESTORE) == 0) | 1560 | (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0) |
| 1462 | continue; | 1561 | continue; |
| 1463 | 1562 | ||
| 1464 | printk(KERN_INFO "restoring control %pUl/%u/%u\n", | 1563 | printk(KERN_INFO "restoring control %pUl/%u/%u\n", |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 6459b8cba223..823f4b389745 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
| @@ -84,6 +84,11 @@ static struct uvc_format_desc uvc_fmts[] = { | |||
| 84 | .fcc = V4L2_PIX_FMT_YUV420, | 84 | .fcc = V4L2_PIX_FMT_YUV420, |
| 85 | }, | 85 | }, |
| 86 | { | 86 | { |
| 87 | .name = "YUV 4:2:0 (M420)", | ||
| 88 | .guid = UVC_GUID_FORMAT_M420, | ||
| 89 | .fcc = V4L2_PIX_FMT_M420, | ||
| 90 | }, | ||
| 91 | { | ||
| 87 | .name = "YUV 4:2:2 (UYVY)", | 92 | .name = "YUV 4:2:2 (UYVY)", |
| 88 | .guid = UVC_GUID_FORMAT_UYVY, | 93 | .guid = UVC_GUID_FORMAT_UYVY, |
| 89 | .fcc = V4L2_PIX_FMT_UYVY, | 94 | .fcc = V4L2_PIX_FMT_UYVY, |
| @@ -103,6 +108,11 @@ static struct uvc_format_desc uvc_fmts[] = { | |||
| 103 | .guid = UVC_GUID_FORMAT_BY8, | 108 | .guid = UVC_GUID_FORMAT_BY8, |
| 104 | .fcc = V4L2_PIX_FMT_SBGGR8, | 109 | .fcc = V4L2_PIX_FMT_SBGGR8, |
| 105 | }, | 110 | }, |
| 111 | { | ||
| 112 | .name = "RGB565", | ||
| 113 | .guid = UVC_GUID_FORMAT_RGBP, | ||
| 114 | .fcc = V4L2_PIX_FMT_RGB565, | ||
| 115 | }, | ||
| 106 | }; | 116 | }; |
| 107 | 117 | ||
| 108 | /* ------------------------------------------------------------------------ | 118 | /* ------------------------------------------------------------------------ |
| @@ -2077,6 +2087,15 @@ static struct usb_device_id uvc_ids[] = { | |||
| 2077 | .bInterfaceSubClass = 1, | 2087 | .bInterfaceSubClass = 1, |
| 2078 | .bInterfaceProtocol = 0, | 2088 | .bInterfaceProtocol = 0, |
| 2079 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 2089 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
| 2090 | /* Hercules Classic Silver */ | ||
| 2091 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 2092 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 2093 | .idVendor = 0x06f8, | ||
| 2094 | .idProduct = 0x300c, | ||
| 2095 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 2096 | .bInterfaceSubClass = 1, | ||
| 2097 | .bInterfaceProtocol = 0, | ||
| 2098 | .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, | ||
| 2080 | /* ViMicro Vega */ | 2099 | /* ViMicro Vega */ |
| 2081 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2100 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
| 2082 | | USB_DEVICE_ID_MATCH_INT_INFO, | 2101 | | USB_DEVICE_ID_MATCH_INT_INFO, |
| @@ -2123,6 +2142,15 @@ static struct usb_device_id uvc_ids[] = { | |||
| 2123 | .bInterfaceSubClass = 1, | 2142 | .bInterfaceSubClass = 1, |
| 2124 | .bInterfaceProtocol = 0, | 2143 | .bInterfaceProtocol = 0, |
| 2125 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 2144 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
| 2145 | /* JMicron USB2.0 XGA WebCam */ | ||
| 2146 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 2147 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 2148 | .idVendor = 0x152d, | ||
| 2149 | .idProduct = 0x0310, | ||
| 2150 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 2151 | .bInterfaceSubClass = 1, | ||
| 2152 | .bInterfaceProtocol = 0, | ||
| 2153 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 2126 | /* Syntek (HP Spartan) */ | 2154 | /* Syntek (HP Spartan) */ |
| 2127 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2155 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
| 2128 | | USB_DEVICE_ID_MATCH_INT_INFO, | 2156 | | USB_DEVICE_ID_MATCH_INT_INFO, |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f14581bd707f..109a06384a8f 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
| @@ -424,7 +424,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) | |||
| 424 | break; | 424 | break; |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | if (i == queue->count || size != queue->buf_size) { | 427 | if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) { |
| 428 | ret = -EINVAL; | 428 | ret = -EINVAL; |
| 429 | goto done; | 429 | goto done; |
| 430 | } | 430 | } |
| @@ -436,6 +436,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) | |||
| 436 | vma->vm_flags |= VM_IO; | 436 | vma->vm_flags |= VM_IO; |
| 437 | 437 | ||
| 438 | addr = (unsigned long)queue->mem + buffer->buf.m.offset; | 438 | addr = (unsigned long)queue->mem + buffer->buf.m.offset; |
| 439 | #ifdef CONFIG_MMU | ||
| 439 | while (size > 0) { | 440 | while (size > 0) { |
| 440 | page = vmalloc_to_page((void *)addr); | 441 | page = vmalloc_to_page((void *)addr); |
| 441 | if ((ret = vm_insert_page(vma, start, page)) < 0) | 442 | if ((ret = vm_insert_page(vma, start, page)) < 0) |
| @@ -445,6 +446,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) | |||
| 445 | addr += PAGE_SIZE; | 446 | addr += PAGE_SIZE; |
| 446 | size -= PAGE_SIZE; | 447 | size -= PAGE_SIZE; |
| 447 | } | 448 | } |
| 449 | #endif | ||
| 448 | 450 | ||
| 449 | vma->vm_ops = &uvc_vm_ops; | 451 | vma->vm_ops = &uvc_vm_ops; |
| 450 | vma->vm_private_data = buffer; | 452 | vma->vm_private_data = buffer; |
| @@ -488,6 +490,36 @@ done: | |||
| 488 | return mask; | 490 | return mask; |
| 489 | } | 491 | } |
| 490 | 492 | ||
| 493 | #ifndef CONFIG_MMU | ||
| 494 | /* | ||
| 495 | * Get unmapped area. | ||
| 496 | * | ||
| 497 | * NO-MMU arch need this function to make mmap() work correctly. | ||
| 498 | */ | ||
| 499 | unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, | ||
| 500 | unsigned long pgoff) | ||
| 501 | { | ||
| 502 | struct uvc_buffer *buffer; | ||
| 503 | unsigned int i; | ||
| 504 | unsigned long ret; | ||
| 505 | |||
| 506 | mutex_lock(&queue->mutex); | ||
| 507 | for (i = 0; i < queue->count; ++i) { | ||
| 508 | buffer = &queue->buffer[i]; | ||
| 509 | if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) | ||
| 510 | break; | ||
| 511 | } | ||
| 512 | if (i == queue->count) { | ||
| 513 | ret = -EINVAL; | ||
| 514 | goto done; | ||
| 515 | } | ||
| 516 | ret = (unsigned long)queue->mem + buffer->buf.m.offset; | ||
| 517 | done: | ||
| 518 | mutex_unlock(&queue->mutex); | ||
| 519 | return ret; | ||
| 520 | } | ||
| 521 | #endif | ||
| 522 | |||
| 491 | /* | 523 | /* |
| 492 | * Enable or disable the video buffers queue. | 524 | * Enable or disable the video buffers queue. |
| 493 | * | 525 | * |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 9005a8d9d5f8..543a80395b7f 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
| @@ -538,6 +538,20 @@ static int uvc_v4l2_release(struct file *file) | |||
| 538 | return 0; | 538 | return 0; |
| 539 | } | 539 | } |
| 540 | 540 | ||
| 541 | static void uvc_v4l2_ioctl_warn(void) | ||
| 542 | { | ||
| 543 | static int warned; | ||
| 544 | |||
| 545 | if (warned) | ||
| 546 | return; | ||
| 547 | |||
| 548 | uvc_printk(KERN_INFO, "Deprecated UVCIOC_CTRL_{ADD,MAP_OLD,GET,SET} " | ||
| 549 | "ioctls will be removed in 2.6.42.\n"); | ||
| 550 | uvc_printk(KERN_INFO, "See http://www.ideasonboard.org/uvc/upgrade/ " | ||
| 551 | "for upgrade instructions.\n"); | ||
| 552 | warned = 1; | ||
| 553 | } | ||
| 554 | |||
| 541 | static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 555 | static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) |
| 542 | { | 556 | { |
| 543 | struct video_device *vdev = video_devdata(file); | 557 | struct video_device *vdev = video_devdata(file); |
| @@ -1018,21 +1032,40 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
| 1018 | uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd); | 1032 | uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd); |
| 1019 | return -EINVAL; | 1033 | return -EINVAL; |
| 1020 | 1034 | ||
| 1021 | /* Dynamic controls. */ | 1035 | /* Dynamic controls. UVCIOC_CTRL_ADD, UVCIOC_CTRL_MAP_OLD, |
| 1022 | case UVCIOC_CTRL_ADD: | 1036 | * UVCIOC_CTRL_GET and UVCIOC_CTRL_SET are deprecated and scheduled for |
| 1023 | /* Legacy ioctl, kept for API compatibility reasons */ | 1037 | * removal in 2.6.42. |
| 1038 | */ | ||
| 1039 | case __UVCIOC_CTRL_ADD: | ||
| 1040 | uvc_v4l2_ioctl_warn(); | ||
| 1024 | return -EEXIST; | 1041 | return -EEXIST; |
| 1025 | 1042 | ||
| 1026 | case UVCIOC_CTRL_MAP_OLD: | 1043 | case __UVCIOC_CTRL_MAP_OLD: |
| 1044 | uvc_v4l2_ioctl_warn(); | ||
| 1045 | case __UVCIOC_CTRL_MAP: | ||
| 1027 | case UVCIOC_CTRL_MAP: | 1046 | case UVCIOC_CTRL_MAP: |
| 1028 | return uvc_ioctl_ctrl_map(chain, arg, | 1047 | return uvc_ioctl_ctrl_map(chain, arg, |
| 1029 | cmd == UVCIOC_CTRL_MAP_OLD); | 1048 | cmd == __UVCIOC_CTRL_MAP_OLD); |
| 1030 | 1049 | ||
| 1031 | case UVCIOC_CTRL_GET: | 1050 | case __UVCIOC_CTRL_GET: |
| 1032 | return uvc_xu_ctrl_query(chain, arg, 0); | 1051 | case __UVCIOC_CTRL_SET: |
| 1052 | { | ||
| 1053 | struct uvc_xu_control *xctrl = arg; | ||
| 1054 | struct uvc_xu_control_query xqry = { | ||
| 1055 | .unit = xctrl->unit, | ||
| 1056 | .selector = xctrl->selector, | ||
| 1057 | .query = cmd == __UVCIOC_CTRL_GET | ||
| 1058 | ? UVC_GET_CUR : UVC_SET_CUR, | ||
| 1059 | .size = xctrl->size, | ||
| 1060 | .data = xctrl->data, | ||
| 1061 | }; | ||
| 1062 | |||
| 1063 | uvc_v4l2_ioctl_warn(); | ||
| 1064 | return uvc_xu_ctrl_query(chain, &xqry); | ||
| 1065 | } | ||
| 1033 | 1066 | ||
| 1034 | case UVCIOC_CTRL_SET: | 1067 | case UVCIOC_CTRL_QUERY: |
| 1035 | return uvc_xu_ctrl_query(chain, arg, 1); | 1068 | return uvc_xu_ctrl_query(chain, arg); |
| 1036 | 1069 | ||
| 1037 | default: | 1070 | default: |
| 1038 | uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); | 1071 | uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); |
| @@ -1081,6 +1114,20 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) | |||
| 1081 | return uvc_queue_poll(&stream->queue, file, wait); | 1114 | return uvc_queue_poll(&stream->queue, file, wait); |
| 1082 | } | 1115 | } |
| 1083 | 1116 | ||
| 1117 | #ifndef CONFIG_MMU | ||
| 1118 | static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, | ||
| 1119 | unsigned long addr, unsigned long len, unsigned long pgoff, | ||
| 1120 | unsigned long flags) | ||
| 1121 | { | ||
| 1122 | struct uvc_fh *handle = file->private_data; | ||
| 1123 | struct uvc_streaming *stream = handle->stream; | ||
| 1124 | |||
| 1125 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); | ||
| 1126 | |||
| 1127 | return uvc_queue_get_unmapped_area(&stream->queue, pgoff); | ||
| 1128 | } | ||
| 1129 | #endif | ||
| 1130 | |||
| 1084 | const struct v4l2_file_operations uvc_fops = { | 1131 | const struct v4l2_file_operations uvc_fops = { |
| 1085 | .owner = THIS_MODULE, | 1132 | .owner = THIS_MODULE, |
| 1086 | .open = uvc_v4l2_open, | 1133 | .open = uvc_v4l2_open, |
| @@ -1089,5 +1136,8 @@ const struct v4l2_file_operations uvc_fops = { | |||
| 1089 | .read = uvc_v4l2_read, | 1136 | .read = uvc_v4l2_read, |
| 1090 | .mmap = uvc_v4l2_mmap, | 1137 | .mmap = uvc_v4l2_mmap, |
| 1091 | .poll = uvc_v4l2_poll, | 1138 | .poll = uvc_v4l2_poll, |
| 1139 | #ifndef CONFIG_MMU | ||
| 1140 | .get_unmapped_area = uvc_v4l2_get_unmapped_area, | ||
| 1141 | #endif | ||
| 1092 | }; | 1142 | }; |
| 1093 | 1143 | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 45f01e7e13d2..7cf224bae2e5 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
| @@ -4,6 +4,14 @@ | |||
| 4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
| 5 | #include <linux/videodev2.h> | 5 | #include <linux/videodev2.h> |
| 6 | 6 | ||
| 7 | #ifndef __KERNEL__ | ||
| 8 | /* | ||
| 9 | * This header provides binary compatibility with applications using the private | ||
| 10 | * uvcvideo API. This API is deprecated and will be removed in 2.6.42. | ||
| 11 | * Applications should be recompiled against the public linux/uvcvideo.h header. | ||
| 12 | */ | ||
| 13 | #warn "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead." | ||
| 14 | |||
| 7 | /* | 15 | /* |
| 8 | * Dynamic controls | 16 | * Dynamic controls |
| 9 | */ | 17 | */ |
| @@ -23,32 +31,18 @@ | |||
| 23 | #define UVC_CONTROL_GET_MAX (1 << 3) | 31 | #define UVC_CONTROL_GET_MAX (1 << 3) |
| 24 | #define UVC_CONTROL_GET_RES (1 << 4) | 32 | #define UVC_CONTROL_GET_RES (1 << 4) |
| 25 | #define UVC_CONTROL_GET_DEF (1 << 5) | 33 | #define UVC_CONTROL_GET_DEF (1 << 5) |
| 26 | /* Control should be saved at suspend and restored at resume. */ | ||
| 27 | #define UVC_CONTROL_RESTORE (1 << 6) | 34 | #define UVC_CONTROL_RESTORE (1 << 6) |
| 28 | /* Control can be updated by the camera. */ | ||
| 29 | #define UVC_CONTROL_AUTO_UPDATE (1 << 7) | 35 | #define UVC_CONTROL_AUTO_UPDATE (1 << 7) |
| 30 | 36 | ||
| 31 | #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ | 37 | #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ |
| 32 | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ | 38 | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ |
| 33 | UVC_CONTROL_GET_DEF) | 39 | UVC_CONTROL_GET_DEF) |
| 34 | 40 | ||
| 35 | struct uvc_xu_control_info { | ||
| 36 | __u8 entity[16]; | ||
| 37 | __u8 index; | ||
| 38 | __u8 selector; | ||
| 39 | __u16 size; | ||
| 40 | __u32 flags; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct uvc_menu_info { | 41 | struct uvc_menu_info { |
| 44 | __u32 value; | 42 | __u32 value; |
| 45 | __u8 name[32]; | 43 | __u8 name[32]; |
| 46 | }; | 44 | }; |
| 47 | 45 | ||
| 48 | struct uvc_xu_control_mapping_old { | ||
| 49 | __u8 reserved[64]; | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct uvc_xu_control_mapping { | 46 | struct uvc_xu_control_mapping { |
| 53 | __u32 id; | 47 | __u32 id; |
| 54 | __u8 name[32]; | 48 | __u8 name[32]; |
| @@ -57,7 +51,7 @@ struct uvc_xu_control_mapping { | |||
| 57 | 51 | ||
| 58 | __u8 size; | 52 | __u8 size; |
| 59 | __u8 offset; | 53 | __u8 offset; |
| 60 | enum v4l2_ctrl_type v4l2_type; | 54 | __u32 v4l2_type; |
| 61 | __u32 data_type; | 55 | __u32 data_type; |
| 62 | 56 | ||
| 63 | struct uvc_menu_info __user *menu_info; | 57 | struct uvc_menu_info __user *menu_info; |
| @@ -66,6 +60,20 @@ struct uvc_xu_control_mapping { | |||
| 66 | __u32 reserved[4]; | 60 | __u32 reserved[4]; |
| 67 | }; | 61 | }; |
| 68 | 62 | ||
| 63 | #endif | ||
| 64 | |||
| 65 | struct uvc_xu_control_info { | ||
| 66 | __u8 entity[16]; | ||
| 67 | __u8 index; | ||
| 68 | __u8 selector; | ||
| 69 | __u16 size; | ||
| 70 | __u32 flags; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct uvc_xu_control_mapping_old { | ||
| 74 | __u8 reserved[64]; | ||
| 75 | }; | ||
| 76 | |||
| 69 | struct uvc_xu_control { | 77 | struct uvc_xu_control { |
| 70 | __u8 unit; | 78 | __u8 unit; |
| 71 | __u8 selector; | 79 | __u8 selector; |
| @@ -73,16 +81,25 @@ struct uvc_xu_control { | |||
| 73 | __u8 __user *data; | 81 | __u8 __user *data; |
| 74 | }; | 82 | }; |
| 75 | 83 | ||
| 84 | #ifndef __KERNEL__ | ||
| 76 | #define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) | 85 | #define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) |
| 77 | #define UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old) | 86 | #define UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old) |
| 78 | #define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) | 87 | #define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) |
| 79 | #define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) | 88 | #define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) |
| 80 | #define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) | 89 | #define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) |
| 90 | #else | ||
| 91 | #define __UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) | ||
| 92 | #define __UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old) | ||
| 93 | #define __UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) | ||
| 94 | #define __UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) | ||
| 95 | #define __UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) | ||
| 96 | #endif | ||
| 81 | 97 | ||
| 82 | #ifdef __KERNEL__ | 98 | #ifdef __KERNEL__ |
| 83 | 99 | ||
| 84 | #include <linux/poll.h> | 100 | #include <linux/poll.h> |
| 85 | #include <linux/usb/video.h> | 101 | #include <linux/usb/video.h> |
| 102 | #include <linux/uvcvideo.h> | ||
| 86 | 103 | ||
| 87 | /* -------------------------------------------------------------------------- | 104 | /* -------------------------------------------------------------------------- |
| 88 | * UVC constants | 105 | * UVC constants |
| @@ -152,13 +169,19 @@ struct uvc_xu_control { | |||
| 152 | #define UVC_GUID_FORMAT_BY8 \ | 169 | #define UVC_GUID_FORMAT_BY8 \ |
| 153 | { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ | 170 | { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ |
| 154 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | 171 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
| 172 | #define UVC_GUID_FORMAT_RGBP \ | ||
| 173 | { 'R', 'G', 'B', 'P', 0x00, 0x00, 0x10, 0x00, \ | ||
| 174 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 175 | #define UVC_GUID_FORMAT_M420 \ | ||
| 176 | { 'M', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ | ||
| 177 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 155 | 178 | ||
| 156 | /* ------------------------------------------------------------------------ | 179 | /* ------------------------------------------------------------------------ |
| 157 | * Driver specific constants. | 180 | * Driver specific constants. |
| 158 | */ | 181 | */ |
| 159 | 182 | ||
| 160 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(1, 0, 0) | 183 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(1, 1, 0) |
| 161 | #define DRIVER_VERSION "v1.0.0" | 184 | #define DRIVER_VERSION "v1.1.0" |
| 162 | 185 | ||
| 163 | /* Number of isochronous URBs. */ | 186 | /* Number of isochronous URBs. */ |
| 164 | #define UVC_URBS 5 | 187 | #define UVC_URBS 5 |
| @@ -580,6 +603,10 @@ extern int uvc_queue_mmap(struct uvc_video_queue *queue, | |||
| 580 | struct vm_area_struct *vma); | 603 | struct vm_area_struct *vma); |
| 581 | extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, | 604 | extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, |
| 582 | struct file *file, poll_table *wait); | 605 | struct file *file, poll_table *wait); |
| 606 | #ifndef CONFIG_MMU | ||
| 607 | extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, | ||
| 608 | unsigned long pgoff); | ||
| 609 | #endif | ||
| 583 | extern int uvc_queue_allocated(struct uvc_video_queue *queue); | 610 | extern int uvc_queue_allocated(struct uvc_video_queue *queue); |
| 584 | static inline int uvc_queue_streaming(struct uvc_video_queue *queue) | 611 | static inline int uvc_queue_streaming(struct uvc_video_queue *queue) |
| 585 | { | 612 | { |
| @@ -638,7 +665,7 @@ extern int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
| 638 | struct v4l2_ext_control *xctrl); | 665 | struct v4l2_ext_control *xctrl); |
| 639 | 666 | ||
| 640 | extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | 667 | extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain, |
| 641 | struct uvc_xu_control *ctrl, int set); | 668 | struct uvc_xu_control_query *xqry); |
| 642 | 669 | ||
| 643 | /* Utility functions */ | 670 | /* Utility functions */ |
| 644 | extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, | 671 | extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, |
| @@ -655,4 +682,3 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, | |||
| 655 | #endif /* __KERNEL__ */ | 682 | #endif /* __KERNEL__ */ |
| 656 | 683 | ||
| 657 | #endif | 684 | #endif |
| 658 | |||
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 6dc7196296b3..19d5ae293780 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
| @@ -352,6 +352,23 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 352 | return ret; | 352 | return ret; |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | #ifdef CONFIG_MMU | ||
| 356 | #define v4l2_get_unmapped_area NULL | ||
| 357 | #else | ||
| 358 | static unsigned long v4l2_get_unmapped_area(struct file *filp, | ||
| 359 | unsigned long addr, unsigned long len, unsigned long pgoff, | ||
| 360 | unsigned long flags) | ||
| 361 | { | ||
| 362 | struct video_device *vdev = video_devdata(filp); | ||
| 363 | |||
| 364 | if (!vdev->fops->get_unmapped_area) | ||
| 365 | return -ENOSYS; | ||
| 366 | if (!video_is_registered(vdev)) | ||
| 367 | return -ENODEV; | ||
| 368 | return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); | ||
| 369 | } | ||
| 370 | #endif | ||
| 371 | |||
| 355 | static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) | 372 | static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) |
| 356 | { | 373 | { |
| 357 | struct video_device *vdev = video_devdata(filp); | 374 | struct video_device *vdev = video_devdata(filp); |
| @@ -454,6 +471,7 @@ static const struct file_operations v4l2_fops = { | |||
| 454 | .read = v4l2_read, | 471 | .read = v4l2_read, |
| 455 | .write = v4l2_write, | 472 | .write = v4l2_write, |
| 456 | .open = v4l2_open, | 473 | .open = v4l2_open, |
| 474 | .get_unmapped_area = v4l2_get_unmapped_area, | ||
| 457 | .mmap = v4l2_mmap, | 475 | .mmap = v4l2_mmap, |
| 458 | .unlocked_ioctl = v4l2_ioctl, | 476 | .unlocked_ioctl = v4l2_ioctl, |
| 459 | #ifdef CONFIG_COMPAT | 477 | #ifdef CONFIG_COMPAT |
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index 8c780c2d937b..85d3048c1d67 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | #include "via-camera.h" | 30 | #include "via-camera.h" |
| 31 | 31 | ||
| 32 | MODULE_ALIAS("platform:viafb-camera"); | ||
| 32 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | 33 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); |
| 33 | MODULE_DESCRIPTION("VIA framebuffer-based camera controller driver"); | 34 | MODULE_DESCRIPTION("VIA framebuffer-based camera controller driver"); |
| 34 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 9f2bac519647..79b04ac0f1ad 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c | |||
| @@ -64,14 +64,6 @@ static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; | |||
| 64 | module_param_array(card, int, NULL, 0444); | 64 | module_param_array(card, int, NULL, 0444); |
| 65 | MODULE_PARM_DESC(card, "Card type"); | 65 | MODULE_PARM_DESC(card, "Card type"); |
| 66 | 66 | ||
| 67 | static int encoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; | ||
| 68 | module_param_array(encoder, int, NULL, 0444); | ||
| 69 | MODULE_PARM_DESC(encoder, "Video encoder chip"); | ||
| 70 | |||
| 71 | static int decoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; | ||
| 72 | module_param_array(decoder, int, NULL, 0444); | ||
| 73 | MODULE_PARM_DESC(decoder, "Video decoder chip"); | ||
| 74 | |||
| 75 | /* | 67 | /* |
| 76 | The video mem address of the video card. | 68 | The video mem address of the video card. |
| 77 | The driver has a little database for some videocards | 69 | The driver has a little database for some videocards |
| @@ -1230,7 +1222,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, | |||
| 1230 | mutex_init(&zr->other_lock); | 1222 | mutex_init(&zr->other_lock); |
| 1231 | if (pci_enable_device(pdev)) | 1223 | if (pci_enable_device(pdev)) |
| 1232 | goto zr_unreg; | 1224 | goto zr_unreg; |
| 1233 | pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); | 1225 | zr->revision = zr->pci_dev->revision; |
| 1234 | 1226 | ||
| 1235 | dprintk(1, | 1227 | dprintk(1, |
| 1236 | KERN_INFO | 1228 | KERN_INFO |
