1711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari/* 2711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * Silicon Labs Si2168 DVB-T/T2/C demodulator driver 3711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * 4711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> 5711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * 6711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * This program is free software; you can redistribute it and/or modify 7711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * it under the terms of the GNU General Public License as published by 8711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * the Free Software Foundation; either version 2 of the License, or 9711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * (at your option) any later version. 10711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * 11711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * This program is distributed in the hope that it will be useful, 12711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * but WITHOUT ANY WARRANTY; without even the implied warranty of 13711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari * GNU General Public License for more details. 15711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari */ 16711615df0b597832ad6ba56c49b23a79a010d540Antti Palosaari 17845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari#include "si2168_priv.h" 18845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 19845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic const struct dvb_frontend_ops si2168_ops; 20845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 21845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari/* execute firmware command */ 22845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) 23845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 24845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari int ret; 25845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari unsigned long timeout; 26845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 27845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari mutex_lock(&s->i2c_mutex); 28845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 29845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (cmd->wlen) { 30845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* write cmd and args for firmware */ 31845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = i2c_master_send(s->client, cmd->args, cmd->wlen); 32845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret < 0) { 33845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err_mutex_unlock; 34845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } else if (ret != cmd->wlen) { 35845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -EREMOTEIO; 36845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err_mutex_unlock; 37845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 38845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 39845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 40845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (cmd->rlen) { 41845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* wait cmd execution terminate */ 42845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari #define TIMEOUT 50 43845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari timeout = jiffies + msecs_to_jiffies(TIMEOUT); 44845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari while (!time_after(jiffies, timeout)) { 45845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = i2c_master_recv(s->client, cmd->args, cmd->rlen); 46845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret < 0) { 47845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err_mutex_unlock; 48845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } else if (ret != cmd->rlen) { 49845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -EREMOTEIO; 50845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err_mutex_unlock; 51845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 52845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 53845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* firmware ready? */ 54845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if ((cmd->args[0] >> 7) & 0x01) 55845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari break; 56845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 57845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 5837b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "cmd execution took %d ms\n", 59845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari jiffies_to_msecs(jiffies) - 60845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari (jiffies_to_msecs(timeout) - TIMEOUT)); 61845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 62eefae30a1b3aabab6085be2ca0e314021253daa2Antti Palosaari if (!((cmd->args[0] >> 7) & 0x01)) { 63845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -ETIMEDOUT; 64845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err_mutex_unlock; 65845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 66845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 67845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 68845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = 0; 69845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 70845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaarierr_mutex_unlock: 71845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari mutex_unlock(&s->i2c_mutex); 72845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 73845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 74845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 75845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 76845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaarierr: 7737b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "failed=%d\n", ret); 78845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return ret; 79845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 80845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 81845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) 82845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 83845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s = fe->demodulator_priv; 84bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 85845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari int ret; 86845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168_cmd cmd; 87845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 88845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari *status = 0; 89845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 90845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (!s->active) { 91845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -EAGAIN; 92845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 93845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 94845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 95bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari switch (c->delivery_system) { 96bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari case SYS_DVBT: 97888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\xa0\x01", 2); 98bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari cmd.wlen = 2; 99bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari cmd.rlen = 13; 100bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari break; 101c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari case SYS_DVBC_ANNEX_A: 102888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\x90\x01", 2); 103c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari cmd.wlen = 2; 104c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari cmd.rlen = 9; 105c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari break; 106bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari case SYS_DVBT2: 107888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\x50\x01", 2); 108bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari cmd.wlen = 2; 109bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari cmd.rlen = 14; 110bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari break; 111bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari default: 112bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari ret = -EINVAL; 113bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari goto err; 114bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari } 115bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari 116845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 117845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 118845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 119845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 120845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* 121845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * Possible values seen, in order from strong signal to weak: 122845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * 16 0001 0110 full lock 123845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * 1e 0001 1110 partial lock 124845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * 1a 0001 1010 partial lock 125845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * 18 0001 1000 no lock 126845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * 127845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * [b3:b1] lock bits 128845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * [b4] statistics ready? Set in a few secs after lock is gained. 129845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari */ 130845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 131722a042de7c9a893a87d2d853c68473eb4000c05Antti Palosaari switch ((cmd.args[2] >> 1) & 0x03) { 132722a042de7c9a893a87d2d853c68473eb4000c05Antti Palosaari case 0x01: 133845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; 134845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari break; 135722a042de7c9a893a87d2d853c68473eb4000c05Antti Palosaari case 0x03: 136845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | 137845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_HAS_SYNC | FE_HAS_LOCK; 138845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari break; 139845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 140845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 141845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->fe_status = *status; 142845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 14388ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari if (*status & FE_HAS_LOCK) { 14488ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari c->cnr.len = 1; 14588ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 14688ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4; 14788ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari } else { 14888ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari c->cnr.len = 1; 14988ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 15088ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari } 15188ac8f860640f28ae6fae43ca690adc3f7294b90Antti Palosaari 15237b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "status=%02x args=%*ph\n", 15337b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen *status, cmd.rlen, cmd.args); 154845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 155845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 156845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaarierr: 15737b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "failed=%d\n", ret); 158845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return ret; 159845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 160845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 161845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_set_frontend(struct dvb_frontend *fe) 162845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 163845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s = fe->demodulator_priv; 164845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 165845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari int ret; 166845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168_cmd cmd; 167bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari u8 bandwidth, delivery_system; 168845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 169845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari dev_dbg(&s->client->dev, 170e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n", 17137b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen c->delivery_system, c->modulation, 172845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari c->frequency, c->bandwidth_hz, c->symbol_rate, 173e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat c->inversion, c->stream_id); 174845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 175845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (!s->active) { 176845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -EAGAIN; 177845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 178845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 179845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 180bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari switch (c->delivery_system) { 181bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari case SYS_DVBT: 182bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari delivery_system = 0x20; 183bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari break; 184c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari case SYS_DVBC_ANNEX_A: 185c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari delivery_system = 0x30; 186c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari break; 187bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari case SYS_DVBT2: 188bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari delivery_system = 0x70; 189bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari break; 190bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari default: 191bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari ret = -EINVAL; 192bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari goto err; 193bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari } 194bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari 195c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari if (c->bandwidth_hz <= 5000000) 196bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari bandwidth = 0x05; 197c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari else if (c->bandwidth_hz <= 6000000) 198bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari bandwidth = 0x06; 199c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari else if (c->bandwidth_hz <= 7000000) 200bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari bandwidth = 0x07; 201c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari else if (c->bandwidth_hz <= 8000000) 202bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari bandwidth = 0x08; 203c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari else if (c->bandwidth_hz <= 9000000) 204c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari bandwidth = 0x09; 205c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari else if (c->bandwidth_hz <= 10000000) 206c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari bandwidth = 0x0a; 207c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari else 208c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari bandwidth = 0x0f; 209845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 210845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* program tuner */ 211845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (fe->ops.tuner_ops.set_params) { 212845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = fe->ops.tuner_ops.set_params(fe); 213845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 214845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 215845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 216845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 217845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5); 218845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 5; 219845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 5; 220845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 221845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 222845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 223845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 224bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari /* that has no big effect */ 225bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari if (c->delivery_system == SYS_DVBT) 226bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6); 227c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari else if (c->delivery_system == SYS_DVBC_ANNEX_A) 228c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6); 229bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari else if (c->delivery_system == SYS_DVBT2) 230bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6); 231845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 232845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 3; 233845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 234845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 235845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 236845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 237e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat if (c->delivery_system == SYS_DVBT2) { 238e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat /* select PLP */ 239e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat cmd.args[0] = 0x52; 240e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat cmd.args[1] = c->stream_id & 0xff; 241e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1; 242e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat cmd.wlen = 3; 243e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat cmd.rlen = 1; 244e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat ret = si2168_cmd_execute(s, &cmd); 245e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat if (ret) 246e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat goto err; 247e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat } 248e395e573b3ca028271fb2ee7edf614d45913d948CrazyCat 249845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x51\x03", 2); 250845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 2; 251845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 12; 252845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 253845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 254845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 255845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 256845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x12\x08\x04", 3); 257845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 3; 258845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 3; 259845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 260845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 261845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 262845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 263845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6); 264845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 2651d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 266845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 267845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 268845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 269845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 270845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6); 271845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 2721d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 273845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 274845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 275845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 276845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 277845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6); 278845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 2791d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 280845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 281845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 282845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 283845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 284845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6); 285bffab93c46434c99fcb27eb4e65af90a142f205cAntti Palosaari cmd.args[4] = delivery_system | bandwidth; 286845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 2871d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 288845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 289845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 290845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 291845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 29232bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves /* set DVB-C symbol rate */ 29332bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves if (c->delivery_system == SYS_DVBC_ANNEX_A) { 29432bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves memcpy(cmd.args, "\x14\x00\x02\x11", 4); 29532bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves cmd.args[4] = (c->symbol_rate / 1000) & 0xff; 29632bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff; 29732bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves cmd.wlen = 6; 29832bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves cmd.rlen = 4; 29932bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves ret = si2168_cmd_execute(s, &cmd); 30032bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves if (ret) 30132bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves goto err; 30232bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves } 30332bf88182d8babfa205e2bd5cbaa992cd1c75511Luis Alves 304845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); 305845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 3061d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 307845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 308845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 309845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 310845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 311845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6); 312845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 3131d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 314845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 315845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 316845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 317845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 318845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6); 319845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 3201d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 321845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 322845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 323845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 324845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 325845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6); 326845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 6; 3271d518c2763555309deebcd1b0230385d3496e948Antti Palosaari cmd.rlen = 4; 328845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 329845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 330845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 331845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 33243911776faf04599f48732403959d510bde03815Olli Salonen memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6); 33343911776faf04599f48732403959d510bde03815Olli Salonen cmd.wlen = 6; 33443911776faf04599f48732403959d510bde03815Olli Salonen cmd.rlen = 4; 33543911776faf04599f48732403959d510bde03815Olli Salonen ret = si2168_cmd_execute(s, &cmd); 33643911776faf04599f48732403959d510bde03815Olli Salonen if (ret) 33743911776faf04599f48732403959d510bde03815Olli Salonen goto err; 33843911776faf04599f48732403959d510bde03815Olli Salonen 339888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\x85", 1); 340845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 1; 341845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 1; 342845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 343845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 344845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 345845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 346845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->delivery_system = c->delivery_system; 347845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 348845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 349845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaarierr: 35037b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "failed=%d\n", ret); 351845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return ret; 352845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 353845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 354845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_init(struct dvb_frontend *fe) 355845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 356845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s = fe->demodulator_priv; 357845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari int ret, len, remaining; 358845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari const struct firmware *fw = NULL; 359c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen u8 *fw_file; 360845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari const unsigned int i2c_wr_max = 8; 361845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168_cmd cmd; 362b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari unsigned int chip_id; 363845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 36437b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "\n"); 365845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 3668e417224dfb397633601a04214841df12cd470b0Olli Salonen /* initialize */ 367888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); 368845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 13; 369845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 0; 370845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 371845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 372845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 373845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 3748e417224dfb397633601a04214841df12cd470b0Olli Salonen if (s->fw_loaded) { 3758e417224dfb397633601a04214841df12cd470b0Olli Salonen /* resume */ 3768e417224dfb397633601a04214841df12cd470b0Olli Salonen memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); 3778e417224dfb397633601a04214841df12cd470b0Olli Salonen cmd.wlen = 8; 3788e417224dfb397633601a04214841df12cd470b0Olli Salonen cmd.rlen = 1; 3798e417224dfb397633601a04214841df12cd470b0Olli Salonen ret = si2168_cmd_execute(s, &cmd); 3808e417224dfb397633601a04214841df12cd470b0Olli Salonen if (ret) 3818e417224dfb397633601a04214841df12cd470b0Olli Salonen goto err; 3828e417224dfb397633601a04214841df12cd470b0Olli Salonen 3838e417224dfb397633601a04214841df12cd470b0Olli Salonen memcpy(cmd.args, "\x85", 1); 3848e417224dfb397633601a04214841df12cd470b0Olli Salonen cmd.wlen = 1; 3858e417224dfb397633601a04214841df12cd470b0Olli Salonen cmd.rlen = 1; 3868e417224dfb397633601a04214841df12cd470b0Olli Salonen ret = si2168_cmd_execute(s, &cmd); 3878e417224dfb397633601a04214841df12cd470b0Olli Salonen if (ret) 3888e417224dfb397633601a04214841df12cd470b0Olli Salonen goto err; 3898e417224dfb397633601a04214841df12cd470b0Olli Salonen 3908e417224dfb397633601a04214841df12cd470b0Olli Salonen goto warm; 3918e417224dfb397633601a04214841df12cd470b0Olli Salonen } 3928e417224dfb397633601a04214841df12cd470b0Olli Salonen 3938e417224dfb397633601a04214841df12cd470b0Olli Salonen /* power up */ 394888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); 395845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 8; 396845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 1; 397845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 398845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 399845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 400845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 401c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen /* query chip revision */ 402888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\x02", 1); 403845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 1; 404845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 13; 405845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 406845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 407845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 408845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 409b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 | 410b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari cmd.args[4] << 0; 411b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari 412635a90cf9385721dcb9c7f5c59a2873ef0279c8bLuis Alves #define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0) 413b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari #define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0) 414b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari #define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0) 415b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari 416b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari switch (chip_id) { 417635a90cf9385721dcb9c7f5c59a2873ef0279c8bLuis Alves case SI2168_A20: 418635a90cf9385721dcb9c7f5c59a2873ef0279c8bLuis Alves fw_file = SI2168_A20_FIRMWARE; 419635a90cf9385721dcb9c7f5c59a2873ef0279c8bLuis Alves break; 420b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari case SI2168_A30: 421c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen fw_file = SI2168_A30_FIRMWARE; 422b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari break; 423b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari case SI2168_B40: 424b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari fw_file = SI2168_B40_FIRMWARE; 425b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari break; 426b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari default: 427c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen dev_err(&s->client->dev, 42837b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen "unknown chip version Si21%d-%c%c%c\n", 42937b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen cmd.args[2], cmd.args[1], 430b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari cmd.args[3], cmd.args[4]); 431c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen ret = -EINVAL; 432c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen goto err; 433c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen } 434c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen 435845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* cold state - try to download firmware */ 43637b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_info(&s->client->dev, "found a '%s' in cold state\n", 43737b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen si2168_ops.info.name); 438845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 439845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* request the firmware, this will block and timeout */ 440845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = request_firmware(&fw, fw_file, &s->client->dev); 441845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) { 442b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari /* fallback mechanism to handle old name for Si2168 B40 fw */ 443b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari if (chip_id == SI2168_B40) { 444c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen fw_file = SI2168_B40_FIRMWARE_FALLBACK; 445c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen ret = request_firmware(&fw, fw_file, &s->client->dev); 446c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen } 447b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari 448b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari if (ret == 0) { 449b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari dev_notice(&s->client->dev, 45037b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen "please install firmware file '%s'\n", 45137b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen SI2168_B40_FIRMWARE); 452b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari } else { 453b6b6fd6feb5f71267ef535f15061a397f86ebb26Antti Palosaari dev_err(&s->client->dev, 45437b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen "firmware file '%s' not found\n", 45537b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen fw_file); 456c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen goto err; 457c9cb0820d5d756f2fac550213e664cc0be511349Olli Salonen } 458845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 459845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 46037b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_info(&s->client->dev, "downloading firmware from file '%s'\n", 46137b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen fw_file); 462845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 463845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) { 464845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari len = remaining; 465845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (len > i2c_wr_max) 466845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari len = i2c_wr_max; 467845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 468845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(cmd.args, &fw->data[fw->size - remaining], len); 469845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = len; 470845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 1; 471845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 472845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) { 473845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari dev_err(&s->client->dev, 47437b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen "firmware download failed=%d\n", 47537b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen ret); 476845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 477845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 478845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 479845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 480845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari release_firmware(fw); 481845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari fw = NULL; 482845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 483888680ff9d2690b64ef7ee3b53d4169a7c4d31b6Antti Palosaari memcpy(cmd.args, "\x01\x01", 2); 484845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.wlen = 2; 485845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari cmd.rlen = 1; 486845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = si2168_cmd_execute(s, &cmd); 487845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret) 488845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 489845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 490389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen /* set ts mode */ 491389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); 492389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen cmd.args[4] |= s->ts_mode; 493389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen cmd.wlen = 6; 494389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen cmd.rlen = 4; 495389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen ret = si2168_cmd_execute(s, &cmd); 496389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen if (ret) 497389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen goto err; 498389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen 4998e417224dfb397633601a04214841df12cd470b0Olli Salonen s->fw_loaded = true; 5008e417224dfb397633601a04214841df12cd470b0Olli Salonen 5018e417224dfb397633601a04214841df12cd470b0Olli Salonenwarm: 5028e417224dfb397633601a04214841df12cd470b0Olli Salonen dev_info(&s->client->dev, "found a '%s' in warm state\n", 5038e417224dfb397633601a04214841df12cd470b0Olli Salonen si2168_ops.info.name); 5048e417224dfb397633601a04214841df12cd470b0Olli Salonen 505845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->active = true; 506845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 507845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 508845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaarierr: 509845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (fw) 510845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari release_firmware(fw); 511845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 51237b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "failed=%d\n", ret); 513845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return ret; 514845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 515845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 516845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_sleep(struct dvb_frontend *fe) 517845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 518845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s = fe->demodulator_priv; 5194de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari int ret; 5204de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari struct si2168_cmd cmd; 521845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 52237b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "\n"); 523845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 524845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->active = false; 525845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 5264de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari memcpy(cmd.args, "\x13", 1); 5274de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari cmd.wlen = 1; 5284de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari cmd.rlen = 0; 5294de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari ret = si2168_cmd_execute(s, &cmd); 5304de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari if (ret) 5314de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari goto err; 5324de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari 533845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 5344de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaarierr: 53537b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&s->client->dev, "failed=%d\n", ret); 5364de0ed7cf7a49384f3438a39543fb85d6dcd3bfcAntti Palosaari return ret; 537845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 538845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 539845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_get_tune_settings(struct dvb_frontend *fe, 540845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct dvb_frontend_tune_settings *s) 541845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 542845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->min_delay_ms = 900; 543845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 544845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 545845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 546845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 547845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari/* 548845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * I2C gate logic 549845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * We must use unlocked i2c_transfer() here because I2C lock is already taken 550845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari * by tuner driver. 551845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari */ 552845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) 553845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 554845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s = mux_priv; 555845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari int ret; 556845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct i2c_msg gate_open_msg = { 557845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .addr = s->client->addr, 558845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .flags = 0, 559845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .len = 3, 560845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .buf = "\xc0\x0d\x01", 561845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari }; 562845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 563845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari mutex_lock(&s->i2c_mutex); 564845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 565845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* open tuner I2C gate */ 566845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1); 567845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret != 1) { 56837b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); 569845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret >= 0) 570845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -EREMOTEIO; 571845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } else { 572845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = 0; 573845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 574845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 575845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return ret; 576845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 577845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 578845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) 579845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 580845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s = mux_priv; 581845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari int ret; 582845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct i2c_msg gate_close_msg = { 583845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .addr = s->client->addr, 584845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .flags = 0, 585845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .len = 3, 586845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .buf = "\xc0\x0d\x00", 587845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari }; 588845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 589845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* close tuner I2C gate */ 590845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1); 591845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret != 1) { 59237b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); 593845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (ret >= 0) 594845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -EREMOTEIO; 595845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } else { 596845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = 0; 597845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 598845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 599845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari mutex_unlock(&s->i2c_mutex); 600845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 601845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return ret; 602845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 603845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 604845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic const struct dvb_frontend_ops si2168_ops = { 605c790885b87670277bdd00523bdbcf876be8f8263Antti Palosaari .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A}, 606845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .info = { 607845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .name = "Silicon Labs Si2168", 608845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .caps = FE_CAN_FEC_1_2 | 609845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_FEC_2_3 | 610845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_FEC_3_4 | 611845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_FEC_5_6 | 612845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_FEC_7_8 | 613845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_FEC_AUTO | 614845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_QPSK | 615845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_QAM_16 | 616845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_QAM_32 | 617845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_QAM_64 | 618845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_QAM_128 | 619845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_QAM_256 | 620845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_QAM_AUTO | 621845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_TRANSMISSION_MODE_AUTO | 622845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_GUARD_INTERVAL_AUTO | 623845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_HIERARCHY_AUTO | 624845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari FE_CAN_MUTE_TS | 625327eeb3a1a335f2580e72878191ca7a5236797bcOlli Salonen FE_CAN_2G_MODULATION | 626327eeb3a1a335f2580e72878191ca7a5236797bcOlli Salonen FE_CAN_MULTISTREAM 627845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari }, 628845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 629845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .get_tune_settings = si2168_get_tune_settings, 630845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 631845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .init = si2168_init, 632845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .sleep = si2168_sleep, 633845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 634845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .set_frontend = si2168_set_frontend, 635845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 636845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .read_status = si2168_read_status, 637845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari}; 638845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 639845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_probe(struct i2c_client *client, 640845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari const struct i2c_device_id *id) 641845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 642845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168_config *config = client->dev.platform_data; 643845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s; 644845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari int ret; 645845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 64637b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&client->dev, "\n"); 647845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 648845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s = kzalloc(sizeof(struct si2168), GFP_KERNEL); 649845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari if (!s) { 650845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari ret = -ENOMEM; 65137b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_err(&client->dev, "kzalloc() failed\n"); 652845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 653845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari } 654845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 655845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->client = client; 656845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari mutex_init(&s->i2c_mutex); 657845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 658845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* create mux i2c adapter for tuner */ 659845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s, 660845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 0, 0, 0, si2168_select, si2168_deselect); 6614d6efc7a96c126f2b21ffd4edad9b11144a0336aLuis Alves if (s->adapter == NULL) { 6624d6efc7a96c126f2b21ffd4edad9b11144a0336aLuis Alves ret = -ENODEV; 663845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari goto err; 6644d6efc7a96c126f2b21ffd4edad9b11144a0336aLuis Alves } 665845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 666845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari /* create dvb_frontend */ 667845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); 668845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->fe.demodulator_priv = s; 669845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 670845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari *config->i2c_adapter = s->adapter; 671845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari *config->fe = &s->fe; 672389ce3984b337690ed5124f2379fc8c3f3975c53Olli Salonen s->ts_mode = config->ts_mode; 6738e417224dfb397633601a04214841df12cd470b0Olli Salonen s->fw_loaded = false; 674845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 675845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari i2c_set_clientdata(client, s); 676845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 677845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari dev_info(&s->client->dev, 67837b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen "Silicon Labs Si2168 successfully attached\n"); 679845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 680845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaarierr: 681845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari kfree(s); 68237b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&client->dev, "failed=%d\n", ret); 683845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return ret; 684845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 685845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 686845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic int si2168_remove(struct i2c_client *client) 687845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari{ 688845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari struct si2168 *s = i2c_get_clientdata(client); 689845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 69037b4e43d8b51163183fef32d6f3334c9f97f61c1Olli Salonen dev_dbg(&client->dev, "\n"); 691845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 692845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari i2c_del_mux_adapter(s->adapter); 693845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 694845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->fe.ops.release = NULL; 695845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari s->fe.demodulator_priv = NULL; 696845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 697845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari kfree(s); 698845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 699845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari return 0; 700845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari} 701845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 702845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic const struct i2c_device_id si2168_id[] = { 703845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari {"si2168", 0}, 704845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari {} 705845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari}; 706845f35052ea94661dd32d80fc95a93d0502345e2Antti PalosaariMODULE_DEVICE_TABLE(i2c, si2168_id); 707845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 708845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaaristatic struct i2c_driver si2168_driver = { 709845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .driver = { 710845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .owner = THIS_MODULE, 711845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .name = "si2168", 712845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari }, 713845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .probe = si2168_probe, 714845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .remove = si2168_remove, 715845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari .id_table = si2168_id, 716845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari}; 717845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 718845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaarimodule_i2c_driver(si2168_driver); 719845f35052ea94661dd32d80fc95a93d0502345e2Antti Palosaari 720845f35052ea94661dd32d80fc95a93d0502345e2Antti PalosaariMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 721845f35052ea94661dd32d80fc95a93d0502345e2Antti PalosaariMODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver"); 722845f35052ea94661dd32d80fc95a93d0502345e2Antti PalosaariMODULE_LICENSE("GPL"); 723635a90cf9385721dcb9c7f5c59a2873ef0279c8bLuis AlvesMODULE_FIRMWARE(SI2168_A20_FIRMWARE); 724668aa63cfcc33e13f2d4c2eef6f65146775b9ed6Antti PalosaariMODULE_FIRMWARE(SI2168_A30_FIRMWARE); 725c9cb0820d5d756f2fac550213e664cc0be511349Olli SalonenMODULE_FIRMWARE(SI2168_B40_FIRMWARE); 726