static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { struct dvb_usb_device *d = fe_to_d(fe); struct lme2510_state *st = fe_to_priv(fe); static u8 voltage_low[] = LME_VOLTAGE_L; static u8 voltage_high[] = LME_VOLTAGE_H; static u8 rbuf[1]; int ret = 0, len = 3, rlen = 1; mutex_lock(&d->i2c_mutex); switch (voltage) { case SEC_VOLTAGE_18: ret |= lme2510_usb_talk(d, voltage_high, len, rbuf, rlen); break; case SEC_VOLTAGE_OFF: case SEC_VOLTAGE_13: default: ret |= lme2510_usb_talk(d, voltage_low, len, rbuf, rlen); break; } mutex_unlock(&d->i2c_mutex); if (st->tuner_config == TUNER_RS2000) if (st->fe_set_voltage) st->fe_set_voltage(fe, voltage); return (ret < 0) ? -ENODEV : 0; }
static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct dvb_usb_adapter *adap = fe->dvb->priv; static u8 voltage_low[] = LME_VOLTAGE_L; static u8 voltage_high[] = LME_VOLTAGE_H; static u8 rbuf[1]; int ret = 0, len = 3, rlen = 1; if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) return -EAGAIN; switch (voltage) { case SEC_VOLTAGE_18: ret |= lme2510_usb_talk(adap->dev, voltage_high, len, rbuf, rlen); break; case SEC_VOLTAGE_OFF: case SEC_VOLTAGE_13: default: ret |= lme2510_usb_talk(adap->dev, voltage_low, len, rbuf, rlen); break; } mutex_unlock(&adap->dev->i2c_mutex); return (ret < 0) ? -ENODEV : 0; }
static int lme2510_download_firmware(struct dvb_usb_device *d, const struct firmware *fw) { int ret = 0; u8 *data; u16 j, wlen, len_in, start, end; u8 packet_size, dlen, i; u8 *fw_data; packet_size = 0x31; len_in = 1; data = kzalloc(128, GFP_KERNEL); if (!data) { info("FRM Could not start Firmware Download"\ "(Buffer allocation failed)"); return -ENOMEM; } info("FRM Starting Firmware Download"); for (i = 1; i < 3; i++) { start = (i == 1) ? 0 : 512; end = (i == 1) ? 512 : fw->size; for (j = start; j < end; j += (packet_size+1)) { fw_data = (u8 *)(fw->data + j); if ((end - j) > packet_size) { data[0] = i; dlen = packet_size; } else { data[0] = i | 0x80; dlen = (u8)(end - j)-1; } data[1] = dlen; memcpy(&data[2], fw_data, dlen+1); wlen = (u8) dlen + 4; data[wlen-1] = check_sum(fw_data, dlen+1); deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], data[dlen+2], data[dlen+3]); lme2510_usb_talk(d, data, wlen, data, len_in); ret |= (data[0] == 0x88) ? 0 : -1; } } data[0] = 0x8a; len_in = 1; msleep(2000); lme2510_usb_talk(d, data, len_in, data, len_in); msleep(400); if (ret < 0) info("FRM Firmware Download Failed (%04x)" , ret); else info("FRM Firmware Download Completed - Resetting Device"); kfree(data); return RECONNECTS_USB; }
static int lme2510_stream_restart(struct dvb_usb_device *d) { struct lme2510_state *st = d->priv; u8 all_pids[] = LME_ALL_PIDS; u8 stream_on[] = LME_ST_ON_W; u8 rbuff[1]; if (st->pid_off) lme2510_usb_talk(d, all_pids, sizeof(all_pids), rbuff, sizeof(rbuff)); /*Restart Stream Command*/ return lme2510_usb_talk(d, stream_on, sizeof(stream_on), rbuff, sizeof(rbuff)); }
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct lme2510_state *st = adap->dev->priv; static u8 clear_reg_3[] = LME_ALL_PIDS; static u8 rbuf[1]; int ret = 0, rlen = sizeof(rbuf); deb_info(1, "STM (%02x)", onoff); if (onoff == 1) st->stream_on = 1; else { deb_info(1, "STM Steam Off"); mutex_lock(&adap->dev->i2c_mutex); ret = lme2510_usb_talk(adap->dev, clear_reg_3, sizeof(clear_reg_3), rbuf, rlen); st->stream_on = 0; st->i2c_talk_onoff = 1; mutex_unlock(&adap->dev->i2c_mutex); } return (ret < 0) ? -ENODEV : 0; }
static int lme2510_streaming_ctrl(struct dvb_frontend *fe, int onoff) { struct dvb_usb_adapter *adap = fe_to_adap(fe); struct dvb_usb_device *d = adap_to_d(adap); struct lme2510_state *st = adap_to_priv(adap); static u8 clear_reg_3[] = LME_ALL_PIDS; static u8 rbuf[1]; int ret = 0, rlen = sizeof(rbuf); deb_info(1, "STM (%02x)", onoff); /* Streaming is started by FE_HAS_LOCK */ if (onoff == 1) st->stream_on = 1; else { deb_info(1, "STM Steam Off"); /* mutex is here only to avoid collision with I2C */ mutex_lock(&d->i2c_mutex); ret = lme2510_usb_talk(d, clear_reg_3, sizeof(clear_reg_3), rbuf, rlen); st->stream_on = 0; st->i2c_talk_onoff = 1; mutex_unlock(&d->i2c_mutex); } return (ret < 0) ? -ENODEV : 0; }
static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct dvb_usb_device *d = adap_to_d(adap); struct lme2510_state *st = adap_to_priv(adap); static u8 clear_pid_reg[] = LME_ALL_PIDS; static u8 rbuf[1]; int ret = 0; deb_info(1, "PID Clearing Filter"); mutex_lock(&d->i2c_mutex); if (!onoff) { ret |= lme2510_usb_talk(d, clear_pid_reg, sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); st->pid_off = true; } else st->pid_off = false; st->pid_size = 0; mutex_unlock(&d->i2c_mutex); return 0; }
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct lme2510_state *st = adap->dev->priv; static u8 clear_reg_3[] = LME_CLEAR_PID; static u8 rbuf[1]; int ret = 0, rlen = sizeof(rbuf); deb_info(1, "STM (%02x)", onoff); /* Streaming is started by FE_HAS_LOCK */ if (onoff == 1) st->stream_on = 1; else { deb_info(1, "STM Steam Off"); /* mutex is here only to avoid collision with I2C */ ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); ret |= lme2510_usb_talk(adap->dev, clear_reg_3, sizeof(clear_reg_3), rbuf, rlen); st->stream_on = 0; st->i2c_talk_onoff = 1; mutex_unlock(&adap->dev->i2c_mutex); } return (ret < 0) ? -ENODEV : 0; }
static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) { struct lme2510_state *st = d->priv; static u8 pid_buff[] = LME_ZERO_PID; static u8 rbuf[1]; u8 pid_no = index * 2; u8 pid_len = pid_no + 2; int ret = 0; deb_info(1, "PID Setting Pid %04x", pid_out); if (st->pid_size == 0) ret |= lme2510_stream_restart(d); pid_buff[2] = pid_no; pid_buff[3] = (u8)pid_out & 0xff; pid_buff[4] = pid_no + 1; pid_buff[5] = (u8)(pid_out >> 8); if (pid_len > st->pid_size) st->pid_size = pid_len; pid_buff[7] = 0x80 + st->pid_size; ret |= lme2510_usb_talk(d, pid_buff , sizeof(pid_buff) , rbuf, sizeof(rbuf)); if (st->stream_on) ret |= lme2510_stream_restart(d); return ret; }
static int lme2510_msg(struct dvb_usb_device *d, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { struct lme2510_state *st = d->priv; st->i2c_talk_onoff = 1; return lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); }
static void lme_coldreset(struct dvb_usb_device *d) { u8 data[1] = {0}; data[0] = 0x0a; info("FRM Firmware Cold Reset"); lme2510_usb_talk(d, data, sizeof(data), data, sizeof(data)); return; }
static int lme2510_stream_restart(struct dvb_usb_device *d) { static u8 stream_on[] = LME_ST_ON_W; int ret; u8 rbuff[10]; /*Restart Stream Command*/ ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), rbuff, sizeof(rbuff)); return ret; }
static int lme2510_powerup(struct dvb_usb_device *d, int onoff) { struct lme2510_state *st = d->priv; static u8 lnb_on[] = LNB_ON; static u8 lnb_off[] = LNB_OFF; static u8 rbuf[1]; int ret, len = 3, rlen = 1; ret = mutex_lock_interruptible(&d->i2c_mutex); if (onoff) ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); else ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); st->i2c_talk_onoff = 1; mutex_unlock(&d->i2c_mutex); return ret; }
static int lme2510_powerup(struct dvb_usb_device *d, int onoff) { struct lme2510_state *st = d->priv; static u8 lnb_on[] = LNB_ON; static u8 lnb_off[] = LNB_OFF; static u8 rbuf[1]; int ret = 0, len = 3, rlen = 1; mutex_lock(&d->i2c_mutex); ret = lme2510_usb_talk(d, onoff ? lnb_on : lnb_off, len, rbuf, rlen); st->i2c_talk_onoff = 1; mutex_unlock(&d->i2c_mutex); return ret; }
static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct lme2510_state *st = adap->dev->priv; static u8 clear_pid_reg[] = LME_CLEAR_PID; static u8 rbuf[1]; int ret; deb_info(1, "PID Clearing Filter"); ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); if (ret < 0) return -EAGAIN; if (!onoff) ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); st->pid_size = 0; mutex_unlock(&adap->dev->i2c_mutex); return 0; }
static int lme2510_msg(struct dvb_usb_device *d, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { int ret = 0; struct lme2510_state *st = d->priv; if (st->i2c_talk_onoff == 1) { ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); switch (st->tuner_config) { case TUNER_LG: if (wbuf[2] == 0x1c) { if (wbuf[3] == 0x0e) { st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x10)) { lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } msleep(80); } } break; case TUNER_S7395: if (wbuf[2] == 0xd0) { if (wbuf[3] == 0x24) { st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x8)) { lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } } } break; case TUNER_S0194: if (wbuf[2] == 0xd0) { if (wbuf[3] == 0x1b) { st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x8)) { lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } } } break; case TUNER_RS2000: default: break; } } else { /* TODO rewrite this section */ switch (st->tuner_config) { case TUNER_LG: switch (wbuf[3]) { case 0x0e: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; case 0x43: rbuf[0] = 0x55; rbuf[1] = st->signal_level; break; case 0x1c: rbuf[0] = 0x55; rbuf[1] = st->signal_sn; break; case 0x15: case 0x16: case 0x17: case 0x18: rbuf[0] = 0x55; rbuf[1] = 0x00; break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; break; } break; case TUNER_S7395: switch (wbuf[3]) { case 0x10: rbuf[0] = 0x55; rbuf[1] = (st->signal_level & 0x80) ? 0 : (st->signal_level * 2); break; case 0x2d: rbuf[0] = 0x55; rbuf[1] = st->signal_sn; break; case 0x24: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; case 0x2e: case 0x26: case 0x27: rbuf[0] = 0x55; rbuf[1] = 0x00; break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; break; } break; case TUNER_S0194: switch (wbuf[3]) { case 0x18: rbuf[0] = 0x55; rbuf[1] = (st->signal_level & 0x80) ? 0 : (st->signal_level * 2); break; case 0x24: rbuf[0] = 0x55; rbuf[1] = st->signal_sn; break; case 0x1b: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; case 0x19: case 0x25: case 0x1e: case 0x1d: rbuf[0] = 0x55; rbuf[1] = 0x00; break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; break; } break; case TUNER_RS2000: switch (wbuf[3]) { case 0x8c: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; /* If int_urb_due overdue * set rbuf[1] to 0 to clear lock */ if (time_after(jiffies, st->int_urb_due)) rbuf[1] = 0; break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; break; } default: break; } deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)", wbuf[3], rbuf[1]); } return ret; }
static int lme2510_msg(struct dvb_usb_device *d, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { int ret = 0; struct lme2510_state *st = d->priv; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (st->i2c_talk_onoff == 1) { ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); switch (st->tuner_config) { case TUNER_LG: if (wbuf[2] == 0x1c) { if (wbuf[3] == 0x0e) { st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x10)) { lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } msleep(80); } } break; case TUNER_S7395: if (wbuf[2] == 0xd0) { if (wbuf[3] == 0x24) { st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x8)) { lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } } if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) msleep(5); } break; case TUNER_S0194: if (wbuf[2] == 0xd0) { if (wbuf[3] == 0x1b) { st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x8)) { lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } } } break; default: break; } } else { switch (st->tuner_config) { case TUNER_LG: switch (wbuf[3]) { case 0x0e: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; case 0x43: rbuf[0] = 0x55; rbuf[1] = st->signal_level; break; case 0x1c: rbuf[0] = 0x55; rbuf[1] = st->signal_sn; break; case 0x15: case 0x16: case 0x17: case 0x18: rbuf[0] = 0x55; rbuf[1] = 0x00; break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; break; } break; case TUNER_S7395: switch (wbuf[3]) { case 0x10: rbuf[0] = 0x55; rbuf[1] = (st->signal_level & 0x80) ? 0 : (st->signal_level * 2); break; case 0x2d: rbuf[0] = 0x55; rbuf[1] = st->signal_sn; break; case 0x24: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; case 0x2e: case 0x26: case 0x27: rbuf[0] = 0x55; rbuf[1] = 0x00; break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; break; } break; case TUNER_S0194: switch (wbuf[3]) { case 0x18: rbuf[0] = 0x55; rbuf[1] = (st->signal_level & 0x80) ? 0 : (st->signal_level * 2); break; case 0x24: rbuf[0] = 0x55; rbuf[1] = st->signal_sn; break; case 0x1b: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; case 0x19: case 0x25: case 0x1e: case 0x1d: rbuf[0] = 0x55; rbuf[1] = 0x00; break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; break; } break; default: break; } deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)", wbuf[3], rbuf[1]); } mutex_unlock(&d->i2c_mutex); return ret; }