Path: blob/master/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
15115 views
/*1* TTUSB DEC Frontend Driver2*3* Copyright (C) 2003-2004 Alex Woods <[email protected]>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.18*19*/2021#include "dvb_frontend.h"22#include "ttusbdecfe.h"232425#define LOF_HI 1060000026#define LOF_LO 97500002728struct ttusbdecfe_state {2930/* configuration settings */31const struct ttusbdecfe_config* config;3233struct dvb_frontend frontend;3435u8 hi_band;36u8 voltage;37};383940static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe,41fe_status_t *status)42{43*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |44FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;45return 0;46}474849static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,50fe_status_t *status)51{52struct ttusbdecfe_state* state = fe->demodulator_priv;53u8 b[] = { 0x00, 0x00, 0x00, 0x00,540x00, 0x00, 0x00, 0x00 };55u8 result[4];56int len, ret;5758*status=0;5960ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);61if(ret)62return ret;6364if(len != 4) {65printk(KERN_ERR "%s: unexpected reply\n", __func__);66return -EIO;67}6869switch(result[3]) {70case 1: /* not tuned yet */71case 2: /* no signal/no lock*/72break;73case 3: /* signal found and locked*/74*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |75FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;76break;77case 4:78*status = FE_TIMEDOUT;79break;80default:81pr_info("%s: returned unknown value: %d\n",82__func__, result[3]);83return -EIO;84}8586return 0;87}8889static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)90{91struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;92u8 b[] = { 0x00, 0x00, 0x00, 0x03,930x00, 0x00, 0x00, 0x00,940x00, 0x00, 0x00, 0x01,950x00, 0x00, 0x00, 0xff,960x00, 0x00, 0x00, 0xff };9798__be32 freq = htonl(p->frequency / 1000);99memcpy(&b[4], &freq, sizeof (u32));100state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);101102return 0;103}104105static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,106struct dvb_frontend_tune_settings* fesettings)107{108fesettings->min_delay_ms = 1500;109/* Drift compensation makes no sense for DVB-T */110fesettings->step_size = 0;111fesettings->max_drift = 0;112return 0;113}114115static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)116{117struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;118119u8 b[] = { 0x00, 0x00, 0x00, 0x01,1200x00, 0x00, 0x00, 0x00,1210x00, 0x00, 0x00, 0x01,1220x00, 0x00, 0x00, 0x00,1230x00, 0x00, 0x00, 0x00,1240x00, 0x00, 0x00, 0x00,1250x00, 0x00, 0x00, 0x00,1260x00, 0x00, 0x00, 0x00,1270x00, 0x00, 0x00, 0x00,1280x00, 0x00, 0x00, 0x00 };129__be32 freq;130__be32 sym_rate;131__be32 band;132__be32 lnb_voltage;133134freq = htonl(p->frequency +135(state->hi_band ? LOF_HI : LOF_LO));136memcpy(&b[4], &freq, sizeof(u32));137sym_rate = htonl(p->u.qam.symbol_rate);138memcpy(&b[12], &sym_rate, sizeof(u32));139band = htonl(state->hi_band ? LOF_HI : LOF_LO);140memcpy(&b[24], &band, sizeof(u32));141lnb_voltage = htonl(state->voltage);142memcpy(&b[28], &lnb_voltage, sizeof(u32));143144state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);145146return 0;147}148149static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)150{151struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;152u8 b[] = { 0x00, 0xff, 0x00, 0x00,1530x00, 0x00, 0x00, 0x00,1540x00, 0x00 };155156memcpy(&b[4], cmd->msg, cmd->msg_len);157158state->config->send_command(fe, 0x72,159sizeof(b) - (6 - cmd->msg_len), b,160NULL, NULL);161162return 0;163}164165166static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)167{168struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;169170state->hi_band = (SEC_TONE_ON == tone);171172return 0;173}174175176static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)177{178struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;179180switch (voltage) {181case SEC_VOLTAGE_13:182state->voltage = 13;183break;184case SEC_VOLTAGE_18:185state->voltage = 18;186break;187default:188return -EINVAL;189}190191return 0;192}193194static void ttusbdecfe_release(struct dvb_frontend* fe)195{196struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;197kfree(state);198}199200static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;201202struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)203{204struct ttusbdecfe_state* state = NULL;205206/* allocate memory for the internal state */207state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);208if (state == NULL)209return NULL;210211/* setup the state */212state->config = config;213214/* create dvb_frontend */215memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));216state->frontend.demodulator_priv = state;217return &state->frontend;218}219220static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;221222struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)223{224struct ttusbdecfe_state* state = NULL;225226/* allocate memory for the internal state */227state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);228if (state == NULL)229return NULL;230231/* setup the state */232state->config = config;233state->voltage = 0;234state->hi_band = 0;235236/* create dvb_frontend */237memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));238state->frontend.demodulator_priv = state;239return &state->frontend;240}241242static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {243244.info = {245.name = "TechnoTrend/Hauppauge DEC2000-t Frontend",246.type = FE_OFDM,247.frequency_min = 51000000,248.frequency_max = 858000000,249.frequency_stepsize = 62500,250.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |251FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |252FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |253FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |254FE_CAN_HIERARCHY_AUTO,255},256257.release = ttusbdecfe_release,258259.set_frontend = ttusbdecfe_dvbt_set_frontend,260261.get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,262263.read_status = ttusbdecfe_dvbt_read_status,264};265266static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {267268.info = {269.name = "TechnoTrend/Hauppauge DEC3000-s Frontend",270.type = FE_QPSK,271.frequency_min = 950000,272.frequency_max = 2150000,273.frequency_stepsize = 125,274.symbol_rate_min = 1000000, /* guessed */275.symbol_rate_max = 45000000, /* guessed */276.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |277FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |278FE_CAN_QPSK279},280281.release = ttusbdecfe_release,282283.set_frontend = ttusbdecfe_dvbs_set_frontend,284285.read_status = ttusbdecfe_dvbs_read_status,286287.diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,288.set_voltage = ttusbdecfe_dvbs_set_voltage,289.set_tone = ttusbdecfe_dvbs_set_tone,290};291292MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");293MODULE_AUTHOR("Alex Woods/Andrew de Quincey");294MODULE_LICENSE("GPL");295296EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);297EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);298299300