162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci Mantis VP-1033 driver 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci Copyright (C) Manu Abraham (abraham.manu@gmail.com) 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci*/ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/signal.h> 1062306a36Sopenharmony_ci#include <linux/sched.h> 1162306a36Sopenharmony_ci#include <linux/interrupt.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <media/dmxdev.h> 1462306a36Sopenharmony_ci#include <media/dvbdev.h> 1562306a36Sopenharmony_ci#include <media/dvb_demux.h> 1662306a36Sopenharmony_ci#include <media/dvb_frontend.h> 1762306a36Sopenharmony_ci#include <media/dvb_net.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "stv0299.h" 2062306a36Sopenharmony_ci#include "mantis_common.h" 2162306a36Sopenharmony_ci#include "mantis_ioc.h" 2262306a36Sopenharmony_ci#include "mantis_dvb.h" 2362306a36Sopenharmony_ci#include "mantis_vp1033.h" 2462306a36Sopenharmony_ci#include "mantis_reg.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic u8 lgtdqcs001f_inittab[] = { 2762306a36Sopenharmony_ci 0x01, 0x15, 2862306a36Sopenharmony_ci 0x02, 0x30, 2962306a36Sopenharmony_ci 0x03, 0x00, 3062306a36Sopenharmony_ci 0x04, 0x2a, 3162306a36Sopenharmony_ci 0x05, 0x85, 3262306a36Sopenharmony_ci 0x06, 0x02, 3362306a36Sopenharmony_ci 0x07, 0x00, 3462306a36Sopenharmony_ci 0x08, 0x00, 3562306a36Sopenharmony_ci 0x0c, 0x01, 3662306a36Sopenharmony_ci 0x0d, 0x81, 3762306a36Sopenharmony_ci 0x0e, 0x44, 3862306a36Sopenharmony_ci 0x0f, 0x94, 3962306a36Sopenharmony_ci 0x10, 0x3c, 4062306a36Sopenharmony_ci 0x11, 0x84, 4162306a36Sopenharmony_ci 0x12, 0xb9, 4262306a36Sopenharmony_ci 0x13, 0xb5, 4362306a36Sopenharmony_ci 0x14, 0x4f, 4462306a36Sopenharmony_ci 0x15, 0xc9, 4562306a36Sopenharmony_ci 0x16, 0x80, 4662306a36Sopenharmony_ci 0x17, 0x36, 4762306a36Sopenharmony_ci 0x18, 0xfb, 4862306a36Sopenharmony_ci 0x19, 0xcf, 4962306a36Sopenharmony_ci 0x1a, 0xbc, 5062306a36Sopenharmony_ci 0x1c, 0x2b, 5162306a36Sopenharmony_ci 0x1d, 0x27, 5262306a36Sopenharmony_ci 0x1e, 0x00, 5362306a36Sopenharmony_ci 0x1f, 0x0b, 5462306a36Sopenharmony_ci 0x20, 0xa1, 5562306a36Sopenharmony_ci 0x21, 0x60, 5662306a36Sopenharmony_ci 0x22, 0x00, 5762306a36Sopenharmony_ci 0x23, 0x00, 5862306a36Sopenharmony_ci 0x28, 0x00, 5962306a36Sopenharmony_ci 0x29, 0x28, 6062306a36Sopenharmony_ci 0x2a, 0x14, 6162306a36Sopenharmony_ci 0x2b, 0x0f, 6262306a36Sopenharmony_ci 0x2c, 0x09, 6362306a36Sopenharmony_ci 0x2d, 0x05, 6462306a36Sopenharmony_ci 0x31, 0x1f, 6562306a36Sopenharmony_ci 0x32, 0x19, 6662306a36Sopenharmony_ci 0x33, 0xfc, 6762306a36Sopenharmony_ci 0x34, 0x13, 6862306a36Sopenharmony_ci 0xff, 0xff, 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define MANTIS_MODEL_NAME "VP-1033" 7262306a36Sopenharmony_ci#define MANTIS_DEV_TYPE "DVB-S/DSS" 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic int lgtdqcs001f_tuner_set(struct dvb_frontend *fe) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 7762306a36Sopenharmony_ci struct mantis_pci *mantis = fe->dvb->priv; 7862306a36Sopenharmony_ci struct i2c_adapter *adapter = &mantis->adapter; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci u8 buf[4]; 8162306a36Sopenharmony_ci u32 div; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci div = p->frequency / 250; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci buf[0] = (div >> 8) & 0x7f; 8962306a36Sopenharmony_ci buf[1] = div & 0xff; 9062306a36Sopenharmony_ci buf[2] = 0x83; 9162306a36Sopenharmony_ci buf[3] = 0xc0; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (p->frequency < 1531000) 9462306a36Sopenharmony_ci buf[3] |= 0x04; 9562306a36Sopenharmony_ci else 9662306a36Sopenharmony_ci buf[3] &= ~0x04; 9762306a36Sopenharmony_ci if (i2c_transfer(adapter, &msg, 1) < 0) { 9862306a36Sopenharmony_ci dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed"); 9962306a36Sopenharmony_ci return -EIO; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci msleep_interruptible(100); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return 0; 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, 10762306a36Sopenharmony_ci u32 srate, u32 ratio) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci u8 aclk = 0; 11062306a36Sopenharmony_ci u8 bclk = 0; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (srate < 1500000) { 11362306a36Sopenharmony_ci aclk = 0xb7; 11462306a36Sopenharmony_ci bclk = 0x47; 11562306a36Sopenharmony_ci } else if (srate < 3000000) { 11662306a36Sopenharmony_ci aclk = 0xb7; 11762306a36Sopenharmony_ci bclk = 0x4b; 11862306a36Sopenharmony_ci } else if (srate < 7000000) { 11962306a36Sopenharmony_ci aclk = 0xb7; 12062306a36Sopenharmony_ci bclk = 0x4f; 12162306a36Sopenharmony_ci } else if (srate < 14000000) { 12262306a36Sopenharmony_ci aclk = 0xb7; 12362306a36Sopenharmony_ci bclk = 0x53; 12462306a36Sopenharmony_ci } else if (srate < 30000000) { 12562306a36Sopenharmony_ci aclk = 0xb6; 12662306a36Sopenharmony_ci bclk = 0x53; 12762306a36Sopenharmony_ci } else if (srate < 45000000) { 12862306a36Sopenharmony_ci aclk = 0xb4; 12962306a36Sopenharmony_ci bclk = 0x51; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci stv0299_writereg(fe, 0x13, aclk); 13262306a36Sopenharmony_ci stv0299_writereg(fe, 0x14, bclk); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); 13562306a36Sopenharmony_ci stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); 13662306a36Sopenharmony_ci stv0299_writereg(fe, 0x21, ratio & 0xf0); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return 0; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic struct stv0299_config lgtdqcs001f_config = { 14262306a36Sopenharmony_ci .demod_address = 0x68, 14362306a36Sopenharmony_ci .inittab = lgtdqcs001f_inittab, 14462306a36Sopenharmony_ci .mclk = 88000000UL, 14562306a36Sopenharmony_ci .invert = 0, 14662306a36Sopenharmony_ci .skip_reinit = 0, 14762306a36Sopenharmony_ci .volt13_op0_op1 = STV0299_VOLT13_OP0, 14862306a36Sopenharmony_ci .min_delay_ms = 100, 14962306a36Sopenharmony_ci .set_symbol_rate = lgtdqcs001f_set_symbol_rate, 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci struct i2c_adapter *adapter = &mantis->adapter; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci int err = 0; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci err = mantis_frontend_power(mantis, POWER_ON); 15962306a36Sopenharmony_ci if (err == 0) { 16062306a36Sopenharmony_ci mantis_frontend_soft_reset(mantis); 16162306a36Sopenharmony_ci msleep(250); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); 16462306a36Sopenharmony_ci fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config, adapter); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (fe) { 16762306a36Sopenharmony_ci fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; 16862306a36Sopenharmony_ci dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", 16962306a36Sopenharmony_ci lgtdqcs001f_config.demod_address); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); 17262306a36Sopenharmony_ci } else { 17362306a36Sopenharmony_ci return -1; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci } else { 17662306a36Sopenharmony_ci dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", 17762306a36Sopenharmony_ci adapter->name, 17862306a36Sopenharmony_ci err); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return -EIO; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci mantis->fe = fe; 18362306a36Sopenharmony_ci dprintk(MANTIS_ERROR, 1, "Done!"); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci return 0; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistruct mantis_hwconfig vp1033_config = { 18962306a36Sopenharmony_ci .model_name = MANTIS_MODEL_NAME, 19062306a36Sopenharmony_ci .dev_type = MANTIS_DEV_TYPE, 19162306a36Sopenharmony_ci .ts_size = MANTIS_TS_204, 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci .baud_rate = MANTIS_BAUD_9600, 19462306a36Sopenharmony_ci .parity = MANTIS_PARITY_NONE, 19562306a36Sopenharmony_ci .bytes = 0, 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci .frontend_init = vp1033_frontend_init, 19862306a36Sopenharmony_ci .power = GPIF_A12, 19962306a36Sopenharmony_ci .reset = GPIF_A13, 20062306a36Sopenharmony_ci}; 201