Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] ascot2e: Sony Ascot2e DVB-C/T/T2 tuner driver

Add DVB-T/T2/C frontend driver for Sony Ascot2e (CXD2861ER) chip.

Signed-off-by: Kozlov Sergey <serjk@netup.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

authored by

Kozlov Sergey and committed by
Mauro Carvalho Chehab
dacf9ce8 a5d32b35

+615
+9
MAINTAINERS
··· 6601 6601 F: Documentation/devicetree/bindings/media/renesas,vsp1.txt 6602 6602 F: drivers/media/platform/vsp1/ 6603 6603 6604 + MEDIA DRIVERS FOR ASCOT2E 6605 + M: Sergey Kozlov <serjk@netup.ru> 6606 + L: linux-media@vger.kernel.org 6607 + W: http://linuxtv.org 6608 + W: http://netup.tv/ 6609 + T: git git://linuxtv.org/media_tree.git 6610 + S: Supported 6611 + F: drivers/media/dvb-frontends/ascot2e* 6612 + 6604 6613 MEDIA DRIVERS FOR HORUS3A 6605 6614 M: Sergey Kozlov <serjk@netup.ru> 6606 6615 L: linux-media@vger.kernel.org
+7
drivers/media/dvb-frontends/Kconfig
··· 823 823 help 824 824 Say Y when you want to support this frontend. 825 825 826 + config DVB_ASCOT2E 827 + tristate "Sony Ascot2E tuner" 828 + depends on DVB_CORE && I2C 829 + default m if !MEDIA_SUBDRV_AUTOSELECT 830 + help 831 + Say Y when you want to support this frontend. 832 + 826 833 comment "Tools to develop new frontends" 827 834 828 835 config DVB_DUMMY_FE
+1
drivers/media/dvb-frontends/Makefile
··· 119 119 obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o 120 120 obj-$(CONFIG_DVB_TC90522) += tc90522.o 121 121 obj-$(CONFIG_DVB_HORUS3A) += horus3a.o 122 + obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
+540
drivers/media/dvb-frontends/ascot2e.c
··· 1 + /* 2 + * ascot2e.c 3 + * 4 + * Sony Ascot3E DVB-T/T2/C/C2 tuner driver 5 + * 6 + * Copyright 2012 Sony Corporation 7 + * Copyright (C) 2014 NetUP Inc. 8 + * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru> 9 + * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru> 10 + * 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * This program is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + */ 21 + 22 + #include <linux/slab.h> 23 + #include <linux/module.h> 24 + #include <linux/dvb/frontend.h> 25 + #include <linux/types.h> 26 + #include "ascot2e.h" 27 + #include "dvb_frontend.h" 28 + 29 + enum ascot2e_state { 30 + STATE_UNKNOWN, 31 + STATE_SLEEP, 32 + STATE_ACTIVE 33 + }; 34 + 35 + struct ascot2e_priv { 36 + u32 frequency; 37 + u8 i2c_address; 38 + struct i2c_adapter *i2c; 39 + enum ascot2e_state state; 40 + void *set_tuner_data; 41 + int (*set_tuner)(void *, int); 42 + }; 43 + 44 + enum ascot2e_tv_system_t { 45 + ASCOT2E_DTV_DVBT_5, 46 + ASCOT2E_DTV_DVBT_6, 47 + ASCOT2E_DTV_DVBT_7, 48 + ASCOT2E_DTV_DVBT_8, 49 + ASCOT2E_DTV_DVBT2_1_7, 50 + ASCOT2E_DTV_DVBT2_5, 51 + ASCOT2E_DTV_DVBT2_6, 52 + ASCOT2E_DTV_DVBT2_7, 53 + ASCOT2E_DTV_DVBT2_8, 54 + ASCOT2E_DTV_DVBC_6, 55 + ASCOT2E_DTV_DVBC_8, 56 + ASCOT2E_DTV_DVBC2_6, 57 + ASCOT2E_DTV_DVBC2_8, 58 + ASCOT2E_DTV_UNKNOWN 59 + }; 60 + 61 + struct ascot2e_band_sett { 62 + u8 if_out_sel; 63 + u8 agc_sel; 64 + u8 mix_oll; 65 + u8 rf_gain; 66 + u8 if_bpf_gc; 67 + u8 fif_offset; 68 + u8 bw_offset; 69 + u8 bw; 70 + u8 rf_oldet; 71 + u8 if_bpf_f0; 72 + }; 73 + 74 + #define ASCOT2E_AUTO 0xff 75 + #define ASCOT2E_OFFSET(ofs) ((u8)(ofs) & 0x1F) 76 + #define ASCOT2E_BW_6 0x00 77 + #define ASCOT2E_BW_7 0x01 78 + #define ASCOT2E_BW_8 0x02 79 + #define ASCOT2E_BW_1_7 0x03 80 + 81 + static struct ascot2e_band_sett ascot2e_sett[] = { 82 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 83 + ASCOT2E_OFFSET(-8), ASCOT2E_OFFSET(-6), ASCOT2E_BW_6, 0x0B, 0x00 }, 84 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 85 + ASCOT2E_OFFSET(-8), ASCOT2E_OFFSET(-6), ASCOT2E_BW_6, 0x0B, 0x00 }, 86 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 87 + ASCOT2E_OFFSET(-6), ASCOT2E_OFFSET(-4), ASCOT2E_BW_7, 0x0B, 0x00 }, 88 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 89 + ASCOT2E_OFFSET(-4), ASCOT2E_OFFSET(-2), ASCOT2E_BW_8, 0x0B, 0x00 }, 90 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 91 + ASCOT2E_OFFSET(-10), ASCOT2E_OFFSET(-16), ASCOT2E_BW_1_7, 0x0B, 0x00 }, 92 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 93 + ASCOT2E_OFFSET(-8), ASCOT2E_OFFSET(-6), ASCOT2E_BW_6, 0x0B, 0x00 }, 94 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 95 + ASCOT2E_OFFSET(-8), ASCOT2E_OFFSET(-6), ASCOT2E_BW_6, 0x0B, 0x00 }, 96 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 97 + ASCOT2E_OFFSET(-6), ASCOT2E_OFFSET(-4), ASCOT2E_BW_7, 0x0B, 0x00 }, 98 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x06, 99 + ASCOT2E_OFFSET(-4), ASCOT2E_OFFSET(-2), ASCOT2E_BW_8, 0x0B, 0x00 }, 100 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x02, ASCOT2E_AUTO, 0x03, 101 + ASCOT2E_OFFSET(-6), ASCOT2E_OFFSET(-8), ASCOT2E_BW_6, 0x09, 0x00 }, 102 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x02, ASCOT2E_AUTO, 0x03, 103 + ASCOT2E_OFFSET(-2), ASCOT2E_OFFSET(-1), ASCOT2E_BW_8, 0x09, 0x00 }, 104 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x01, 105 + ASCOT2E_OFFSET(-6), ASCOT2E_OFFSET(-4), ASCOT2E_BW_6, 0x09, 0x00 }, 106 + { ASCOT2E_AUTO, ASCOT2E_AUTO, 0x03, ASCOT2E_AUTO, 0x01, 107 + ASCOT2E_OFFSET(-2), ASCOT2E_OFFSET(2), ASCOT2E_BW_8, 0x09, 0x00 } 108 + }; 109 + 110 + static void ascot2e_i2c_debug(struct ascot2e_priv *priv, 111 + u8 reg, u8 write, const u8 *data, u32 len) 112 + { 113 + dev_dbg(&priv->i2c->dev, "ascot2e: I2C %s reg 0x%02x size %d\n", 114 + (write == 0 ? "read" : "write"), reg, len); 115 + print_hex_dump_bytes("ascot2e: I2C data: ", 116 + DUMP_PREFIX_OFFSET, data, len); 117 + } 118 + 119 + static int ascot2e_write_regs(struct ascot2e_priv *priv, 120 + u8 reg, const u8 *data, u32 len) 121 + { 122 + int ret; 123 + u8 buf[len+1]; 124 + struct i2c_msg msg[1] = { 125 + { 126 + .addr = priv->i2c_address, 127 + .flags = 0, 128 + .len = sizeof(buf), 129 + .buf = buf, 130 + } 131 + }; 132 + 133 + ascot2e_i2c_debug(priv, reg, 1, data, len); 134 + buf[0] = reg; 135 + memcpy(&buf[1], data, len); 136 + ret = i2c_transfer(priv->i2c, msg, 1); 137 + if (ret >= 0 && ret != 1) 138 + ret = -EREMOTEIO; 139 + if (ret < 0) { 140 + dev_warn(&priv->i2c->dev, 141 + "%s: i2c wr failed=%d reg=%02x len=%d\n", 142 + KBUILD_MODNAME, ret, reg, len); 143 + return ret; 144 + } 145 + return 0; 146 + } 147 + 148 + static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val) 149 + { 150 + return ascot2e_write_regs(priv, reg, &val, 1); 151 + } 152 + 153 + static int ascot2e_read_regs(struct ascot2e_priv *priv, 154 + u8 reg, u8 *val, u32 len) 155 + { 156 + int ret; 157 + struct i2c_msg msg[2] = { 158 + { 159 + .addr = priv->i2c_address, 160 + .flags = 0, 161 + .len = 1, 162 + .buf = &reg, 163 + }, { 164 + .addr = priv->i2c_address, 165 + .flags = I2C_M_RD, 166 + .len = len, 167 + .buf = val, 168 + } 169 + }; 170 + 171 + ret = i2c_transfer(priv->i2c, &msg[0], 1); 172 + if (ret >= 0 && ret != 1) 173 + ret = -EREMOTEIO; 174 + if (ret < 0) { 175 + dev_warn(&priv->i2c->dev, 176 + "%s: I2C rw failed=%d addr=%02x reg=%02x\n", 177 + KBUILD_MODNAME, ret, priv->i2c_address, reg); 178 + return ret; 179 + } 180 + ret = i2c_transfer(priv->i2c, &msg[1], 1); 181 + if (ret >= 0 && ret != 1) 182 + ret = -EREMOTEIO; 183 + if (ret < 0) { 184 + dev_warn(&priv->i2c->dev, 185 + "%s: i2c rd failed=%d addr=%02x reg=%02x\n", 186 + KBUILD_MODNAME, ret, priv->i2c_address, reg); 187 + return ret; 188 + } 189 + ascot2e_i2c_debug(priv, reg, 0, val, len); 190 + return 0; 191 + } 192 + 193 + static int ascot2e_read_reg(struct ascot2e_priv *priv, u8 reg, u8 *val) 194 + { 195 + return ascot2e_read_regs(priv, reg, val, 1); 196 + } 197 + 198 + static int ascot2e_set_reg_bits(struct ascot2e_priv *priv, 199 + u8 reg, u8 data, u8 mask) 200 + { 201 + int res; 202 + u8 rdata; 203 + 204 + if (mask != 0xff) { 205 + res = ascot2e_read_reg(priv, reg, &rdata); 206 + if (res != 0) 207 + return res; 208 + data = ((data & mask) | (rdata & (mask ^ 0xFF))); 209 + } 210 + return ascot2e_write_reg(priv, reg, data); 211 + } 212 + 213 + static int ascot2e_enter_power_save(struct ascot2e_priv *priv) 214 + { 215 + u8 data[2]; 216 + 217 + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 218 + if (priv->state == STATE_SLEEP) 219 + return 0; 220 + data[0] = 0x00; 221 + data[1] = 0x04; 222 + ascot2e_write_regs(priv, 0x14, data, 2); 223 + ascot2e_write_reg(priv, 0x50, 0x01); 224 + priv->state = STATE_SLEEP; 225 + return 0; 226 + } 227 + 228 + static int ascot2e_leave_power_save(struct ascot2e_priv *priv) 229 + { 230 + u8 data[2] = { 0xFB, 0x0F }; 231 + 232 + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 233 + if (priv->state == STATE_ACTIVE) 234 + return 0; 235 + ascot2e_write_regs(priv, 0x14, data, 2); 236 + ascot2e_write_reg(priv, 0x50, 0x00); 237 + priv->state = STATE_ACTIVE; 238 + return 0; 239 + } 240 + 241 + static int ascot2e_init(struct dvb_frontend *fe) 242 + { 243 + struct ascot2e_priv *priv = fe->tuner_priv; 244 + 245 + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 246 + return ascot2e_leave_power_save(priv); 247 + } 248 + 249 + static int ascot2e_release(struct dvb_frontend *fe) 250 + { 251 + struct ascot2e_priv *priv = fe->tuner_priv; 252 + 253 + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 254 + kfree(fe->tuner_priv); 255 + fe->tuner_priv = NULL; 256 + return 0; 257 + } 258 + 259 + static int ascot2e_sleep(struct dvb_frontend *fe) 260 + { 261 + struct ascot2e_priv *priv = fe->tuner_priv; 262 + 263 + dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 264 + ascot2e_enter_power_save(priv); 265 + return 0; 266 + } 267 + 268 + static enum ascot2e_tv_system_t ascot2e_get_tv_system(struct dvb_frontend *fe) 269 + { 270 + enum ascot2e_tv_system_t system = ASCOT2E_DTV_UNKNOWN; 271 + struct dtv_frontend_properties *p = &fe->dtv_property_cache; 272 + struct ascot2e_priv *priv = fe->tuner_priv; 273 + 274 + if (p->delivery_system == SYS_DVBT) { 275 + if (p->bandwidth_hz <= 5000000) 276 + system = ASCOT2E_DTV_DVBT_5; 277 + else if (p->bandwidth_hz <= 6000000) 278 + system = ASCOT2E_DTV_DVBT_6; 279 + else if (p->bandwidth_hz <= 7000000) 280 + system = ASCOT2E_DTV_DVBT_7; 281 + else if (p->bandwidth_hz <= 8000000) 282 + system = ASCOT2E_DTV_DVBT_8; 283 + else { 284 + system = ASCOT2E_DTV_DVBT_8; 285 + p->bandwidth_hz = 8000000; 286 + } 287 + } else if (p->delivery_system == SYS_DVBT2) { 288 + if (p->bandwidth_hz <= 5000000) 289 + system = ASCOT2E_DTV_DVBT2_5; 290 + else if (p->bandwidth_hz <= 6000000) 291 + system = ASCOT2E_DTV_DVBT2_6; 292 + else if (p->bandwidth_hz <= 7000000) 293 + system = ASCOT2E_DTV_DVBT2_7; 294 + else if (p->bandwidth_hz <= 8000000) 295 + system = ASCOT2E_DTV_DVBT2_8; 296 + else { 297 + system = ASCOT2E_DTV_DVBT2_8; 298 + p->bandwidth_hz = 8000000; 299 + } 300 + } else if (p->delivery_system == SYS_DVBC_ANNEX_A) { 301 + if (p->bandwidth_hz <= 6000000) 302 + system = ASCOT2E_DTV_DVBC_6; 303 + else if (p->bandwidth_hz <= 8000000) 304 + system = ASCOT2E_DTV_DVBC_8; 305 + } 306 + dev_dbg(&priv->i2c->dev, 307 + "%s(): ASCOT2E DTV system %d (delsys %d, bandwidth %d)\n", 308 + __func__, (int)system, p->delivery_system, p->bandwidth_hz); 309 + return system; 310 + } 311 + 312 + static int ascot2e_set_params(struct dvb_frontend *fe) 313 + { 314 + u8 data[10]; 315 + u32 frequency; 316 + enum ascot2e_tv_system_t tv_system; 317 + struct dtv_frontend_properties *p = &fe->dtv_property_cache; 318 + struct ascot2e_priv *priv = fe->tuner_priv; 319 + 320 + dev_dbg(&priv->i2c->dev, "%s(): tune frequency %dkHz\n", 321 + __func__, p->frequency / 1000); 322 + tv_system = ascot2e_get_tv_system(fe); 323 + 324 + if (tv_system == ASCOT2E_DTV_UNKNOWN) { 325 + dev_dbg(&priv->i2c->dev, "%s(): unknown DTV system\n", 326 + __func__); 327 + return -EINVAL; 328 + } 329 + if (priv->set_tuner) 330 + priv->set_tuner(priv->set_tuner_data, 1); 331 + frequency = roundup(p->frequency / 1000, 25); 332 + if (priv->state == STATE_SLEEP) 333 + ascot2e_leave_power_save(priv); 334 + 335 + /* IF_OUT_SEL / AGC_SEL setting */ 336 + data[0] = 0x00; 337 + if (ascot2e_sett[tv_system].agc_sel != ASCOT2E_AUTO) { 338 + /* AGC pin setting from parameter table */ 339 + data[0] |= (u8)( 340 + (ascot2e_sett[tv_system].agc_sel & 0x03) << 3); 341 + } 342 + if (ascot2e_sett[tv_system].if_out_sel != ASCOT2E_AUTO) { 343 + /* IFOUT pin setting from parameter table */ 344 + data[0] |= (u8)( 345 + (ascot2e_sett[tv_system].if_out_sel & 0x01) << 2); 346 + } 347 + /* Set bit[4:2] only */ 348 + ascot2e_set_reg_bits(priv, 0x05, data[0], 0x1c); 349 + /* 0x06 - 0x0F */ 350 + /* REF_R setting (0x06) */ 351 + if (tv_system == ASCOT2E_DTV_DVBC_6 || 352 + tv_system == ASCOT2E_DTV_DVBC_8) { 353 + /* xtal, xtal*2 */ 354 + data[0] = (frequency > 500000) ? 16 : 32; 355 + } else { 356 + /* xtal/8, xtal/4 */ 357 + data[0] = (frequency > 500000) ? 2 : 4; 358 + } 359 + /* XOSC_SEL=100uA */ 360 + data[1] = 0x04; 361 + /* KBW setting (0x08), KC0 setting (0x09), KC1 setting (0x0A) */ 362 + if (tv_system == ASCOT2E_DTV_DVBC_6 || 363 + tv_system == ASCOT2E_DTV_DVBC_8) { 364 + data[2] = 18; 365 + data[3] = 120; 366 + data[4] = 20; 367 + } else { 368 + data[2] = 48; 369 + data[3] = 10; 370 + data[4] = 30; 371 + } 372 + /* ORDER/R2_RANGE/R2_BANK/C2_BANK setting (0x0B) */ 373 + if (tv_system == ASCOT2E_DTV_DVBC_6 || 374 + tv_system == ASCOT2E_DTV_DVBC_8) 375 + data[5] = (frequency > 500000) ? 0x08 : 0x0c; 376 + else 377 + data[5] = (frequency > 500000) ? 0x30 : 0x38; 378 + /* Set MIX_OLL (0x0C) value from parameter table */ 379 + data[6] = ascot2e_sett[tv_system].mix_oll; 380 + /* Set RF_GAIN (0x0D) setting from parameter table */ 381 + if (ascot2e_sett[tv_system].rf_gain == ASCOT2E_AUTO) { 382 + /* RF_GAIN auto control enable */ 383 + ascot2e_write_reg(priv, 0x4E, 0x01); 384 + /* RF_GAIN Default value */ 385 + data[7] = 0x00; 386 + } else { 387 + /* RF_GAIN auto control disable */ 388 + ascot2e_write_reg(priv, 0x4E, 0x00); 389 + data[7] = ascot2e_sett[tv_system].rf_gain; 390 + } 391 + /* Set IF_BPF_GC/FIF_OFFSET (0x0E) value from parameter table */ 392 + data[8] = (u8)((ascot2e_sett[tv_system].fif_offset << 3) | 393 + (ascot2e_sett[tv_system].if_bpf_gc & 0x07)); 394 + /* Set BW_OFFSET (0x0F) value from parameter table */ 395 + data[9] = ascot2e_sett[tv_system].bw_offset; 396 + ascot2e_write_regs(priv, 0x06, data, 10); 397 + /* 398 + * 0x45 - 0x47 399 + * LNA optimization setting 400 + * RF_LNA_DIST1-5, RF_LNA_CM 401 + */ 402 + if (tv_system == ASCOT2E_DTV_DVBC_6 || 403 + tv_system == ASCOT2E_DTV_DVBC_8) { 404 + data[0] = 0x0F; 405 + data[1] = 0x00; 406 + data[2] = 0x01; 407 + } else { 408 + data[0] = 0x0F; 409 + data[1] = 0x00; 410 + data[2] = 0x03; 411 + } 412 + ascot2e_write_regs(priv, 0x45, data, 3); 413 + /* 0x49 - 0x4A 414 + Set RF_OLDET_ENX/RF_OLDET_OLL value from parameter table */ 415 + data[0] = ascot2e_sett[tv_system].rf_oldet; 416 + /* Set IF_BPF_F0 value from parameter table */ 417 + data[1] = ascot2e_sett[tv_system].if_bpf_f0; 418 + ascot2e_write_regs(priv, 0x49, data, 2); 419 + /* 420 + * Tune now 421 + * RFAGC fast mode / RFAGC auto control enable 422 + * (set bit[7], bit[5:4] only) 423 + * vco_cal = 1, set MIX_OL_CPU_EN 424 + */ 425 + ascot2e_set_reg_bits(priv, 0x0c, 0x90, 0xb0); 426 + /* Logic wake up, CPU wake up */ 427 + data[0] = 0xc4; 428 + data[1] = 0x40; 429 + ascot2e_write_regs(priv, 0x03, data, 2); 430 + /* 0x10 - 0x14 */ 431 + data[0] = (u8)(frequency & 0xFF); /* 0x10: FRF_L */ 432 + data[1] = (u8)((frequency >> 8) & 0xFF); /* 0x11: FRF_M */ 433 + data[2] = (u8)((frequency >> 16) & 0x0F); /* 0x12: FRF_H (bit[3:0]) */ 434 + /* 0x12: BW (bit[5:4]) */ 435 + data[2] |= (u8)(ascot2e_sett[tv_system].bw << 4); 436 + data[3] = 0xFF; /* 0x13: VCO calibration enable */ 437 + data[4] = 0xFF; /* 0x14: Analog block enable */ 438 + /* Tune (Burst write) */ 439 + ascot2e_write_regs(priv, 0x10, data, 5); 440 + msleep(50); 441 + /* CPU deep sleep */ 442 + ascot2e_write_reg(priv, 0x04, 0x00); 443 + /* Logic sleep */ 444 + ascot2e_write_reg(priv, 0x03, 0xC0); 445 + /* RFAGC normal mode (set bit[5:4] only) */ 446 + ascot2e_set_reg_bits(priv, 0x0C, 0x00, 0x30); 447 + priv->frequency = frequency; 448 + return 0; 449 + } 450 + 451 + static int ascot2e_get_frequency(struct dvb_frontend *fe, u32 *frequency) 452 + { 453 + struct ascot2e_priv *priv = fe->tuner_priv; 454 + 455 + *frequency = priv->frequency * 1000; 456 + return 0; 457 + } 458 + 459 + static struct dvb_tuner_ops ascot2e_tuner_ops = { 460 + .info = { 461 + .name = "Sony ASCOT2E", 462 + .frequency_min = 1000000, 463 + .frequency_max = 1200000000, 464 + .frequency_step = 25000, 465 + }, 466 + .init = ascot2e_init, 467 + .release = ascot2e_release, 468 + .sleep = ascot2e_sleep, 469 + .set_params = ascot2e_set_params, 470 + .get_frequency = ascot2e_get_frequency, 471 + }; 472 + 473 + struct dvb_frontend *ascot2e_attach(struct dvb_frontend *fe, 474 + const struct ascot2e_config *config, 475 + struct i2c_adapter *i2c) 476 + { 477 + u8 data[4]; 478 + struct ascot2e_priv *priv = NULL; 479 + 480 + priv = kzalloc(sizeof(struct ascot2e_priv), GFP_KERNEL); 481 + if (priv == NULL) 482 + return NULL; 483 + priv->i2c_address = (config->i2c_address >> 1); 484 + priv->i2c = i2c; 485 + priv->set_tuner_data = config->set_tuner_priv; 486 + priv->set_tuner = config->set_tuner_callback; 487 + 488 + if (fe->ops.i2c_gate_ctrl) 489 + fe->ops.i2c_gate_ctrl(fe, 1); 490 + 491 + /* 16 MHz xTal frequency */ 492 + data[0] = 16; 493 + /* VCO current setting */ 494 + data[1] = 0x06; 495 + /* Logic wake up, CPU boot */ 496 + data[2] = 0xC4; 497 + data[3] = 0x40; 498 + ascot2e_write_regs(priv, 0x01, data, 4); 499 + /* RFVGA optimization setting (RF_DIST0 - RF_DIST2) */ 500 + data[0] = 0x10; 501 + data[1] = 0x3F; 502 + data[2] = 0x25; 503 + ascot2e_write_regs(priv, 0x22, data, 3); 504 + /* PLL mode setting */ 505 + ascot2e_write_reg(priv, 0x28, 0x1e); 506 + /* RSSI setting */ 507 + ascot2e_write_reg(priv, 0x59, 0x04); 508 + /* TODO check CPU HW error state here */ 509 + msleep(80); 510 + /* Xtal oscillator current control setting */ 511 + ascot2e_write_reg(priv, 0x4c, 0x01); 512 + /* XOSC_SEL=100uA */ 513 + ascot2e_write_reg(priv, 0x07, 0x04); 514 + /* CPU deep sleep */ 515 + ascot2e_write_reg(priv, 0x04, 0x00); 516 + /* Logic sleep */ 517 + ascot2e_write_reg(priv, 0x03, 0xc0); 518 + /* Power save setting */ 519 + data[0] = 0x00; 520 + data[1] = 0x04; 521 + ascot2e_write_regs(priv, 0x14, data, 2); 522 + ascot2e_write_reg(priv, 0x50, 0x01); 523 + priv->state = STATE_SLEEP; 524 + 525 + if (fe->ops.i2c_gate_ctrl) 526 + fe->ops.i2c_gate_ctrl(fe, 0); 527 + 528 + memcpy(&fe->ops.tuner_ops, &ascot2e_tuner_ops, 529 + sizeof(struct dvb_tuner_ops)); 530 + fe->tuner_priv = priv; 531 + dev_info(&priv->i2c->dev, 532 + "Sony ASCOT2E attached on addr=%x at I2C adapter %p\n", 533 + priv->i2c_address, priv->i2c); 534 + return fe; 535 + } 536 + EXPORT_SYMBOL(ascot2e_attach); 537 + 538 + MODULE_DESCRIPTION("Sony ASCOT2E terr/cab tuner driver"); 539 + MODULE_AUTHOR("info@netup.ru"); 540 + MODULE_LICENSE("GPL");
+58
drivers/media/dvb-frontends/ascot2e.h
··· 1 + /* 2 + * ascot2e.h 3 + * 4 + * Sony Ascot3E DVB-T/T2/C/C2 tuner driver 5 + * 6 + * Copyright 2012 Sony Corporation 7 + * Copyright (C) 2014 NetUP Inc. 8 + * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru> 9 + * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru> 10 + * 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * This program is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + */ 21 + 22 + #ifndef __DVB_ASCOT2E_H__ 23 + #define __DVB_ASCOT2E_H__ 24 + 25 + #include <linux/kconfig.h> 26 + #include <linux/dvb/frontend.h> 27 + #include <linux/i2c.h> 28 + 29 + /** 30 + * struct ascot2e_config - the configuration of Ascot2E tuner driver 31 + * @i2c_address: I2C address of the tuner 32 + * @xtal_freq_mhz: Oscillator frequency, MHz 33 + * @set_tuner_priv: Callback function private context 34 + * @set_tuner_callback: Callback function that notifies the parent driver 35 + * which tuner is active now 36 + */ 37 + struct ascot2e_config { 38 + u8 i2c_address; 39 + u8 xtal_freq_mhz; 40 + void *set_tuner_priv; 41 + int (*set_tuner_callback)(void *, int); 42 + }; 43 + 44 + #if IS_REACHABLE(CONFIG_DVB_ASCOT2E) 45 + extern struct dvb_frontend *ascot2e_attach(struct dvb_frontend *fe, 46 + const struct ascot2e_config *config, 47 + struct i2c_adapter *i2c); 48 + #else 49 + static inline struct dvb_frontend *ascot2e_attach(struct dvb_frontend *fe, 50 + const struct ascot2e_config *config, 51 + struct i2c_adapter *i2c) 52 + { 53 + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 54 + return NULL; 55 + } 56 + #endif 57 + 58 + #endif