xref: /openbmc/linux/drivers/media/pci/mantis/mantis_vp1033.c (revision 58e16d792a6a8c6b750f637a4649967fcac853dc)
1*74ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
225aee3deSMauro Carvalho Chehab /*
325aee3deSMauro Carvalho Chehab 	Mantis VP-1033 driver
425aee3deSMauro Carvalho Chehab 
525aee3deSMauro Carvalho Chehab 	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
625aee3deSMauro Carvalho Chehab 
725aee3deSMauro Carvalho Chehab */
825aee3deSMauro Carvalho Chehab 
925aee3deSMauro Carvalho Chehab #include <linux/signal.h>
1025aee3deSMauro Carvalho Chehab #include <linux/sched.h>
1125aee3deSMauro Carvalho Chehab #include <linux/interrupt.h>
1225aee3deSMauro Carvalho Chehab 
13fada1935SMauro Carvalho Chehab #include <media/dmxdev.h>
14fada1935SMauro Carvalho Chehab #include <media/dvbdev.h>
15fada1935SMauro Carvalho Chehab #include <media/dvb_demux.h>
16fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h>
17fada1935SMauro Carvalho Chehab #include <media/dvb_net.h>
1825aee3deSMauro Carvalho Chehab 
1925aee3deSMauro Carvalho Chehab #include "stv0299.h"
2025aee3deSMauro Carvalho Chehab #include "mantis_common.h"
2125aee3deSMauro Carvalho Chehab #include "mantis_ioc.h"
2225aee3deSMauro Carvalho Chehab #include "mantis_dvb.h"
2325aee3deSMauro Carvalho Chehab #include "mantis_vp1033.h"
2425aee3deSMauro Carvalho Chehab #include "mantis_reg.h"
2525aee3deSMauro Carvalho Chehab 
26967a3783SHans Verkuil static u8 lgtdqcs001f_inittab[] = {
2725aee3deSMauro Carvalho Chehab 	0x01, 0x15,
2825aee3deSMauro Carvalho Chehab 	0x02, 0x30,
2925aee3deSMauro Carvalho Chehab 	0x03, 0x00,
3025aee3deSMauro Carvalho Chehab 	0x04, 0x2a,
3125aee3deSMauro Carvalho Chehab 	0x05, 0x85,
3225aee3deSMauro Carvalho Chehab 	0x06, 0x02,
3325aee3deSMauro Carvalho Chehab 	0x07, 0x00,
3425aee3deSMauro Carvalho Chehab 	0x08, 0x00,
3525aee3deSMauro Carvalho Chehab 	0x0c, 0x01,
3625aee3deSMauro Carvalho Chehab 	0x0d, 0x81,
3725aee3deSMauro Carvalho Chehab 	0x0e, 0x44,
3825aee3deSMauro Carvalho Chehab 	0x0f, 0x94,
3925aee3deSMauro Carvalho Chehab 	0x10, 0x3c,
4025aee3deSMauro Carvalho Chehab 	0x11, 0x84,
4125aee3deSMauro Carvalho Chehab 	0x12, 0xb9,
4225aee3deSMauro Carvalho Chehab 	0x13, 0xb5,
4325aee3deSMauro Carvalho Chehab 	0x14, 0x4f,
4425aee3deSMauro Carvalho Chehab 	0x15, 0xc9,
4525aee3deSMauro Carvalho Chehab 	0x16, 0x80,
4625aee3deSMauro Carvalho Chehab 	0x17, 0x36,
4725aee3deSMauro Carvalho Chehab 	0x18, 0xfb,
4825aee3deSMauro Carvalho Chehab 	0x19, 0xcf,
4925aee3deSMauro Carvalho Chehab 	0x1a, 0xbc,
5025aee3deSMauro Carvalho Chehab 	0x1c, 0x2b,
5125aee3deSMauro Carvalho Chehab 	0x1d, 0x27,
5225aee3deSMauro Carvalho Chehab 	0x1e, 0x00,
5325aee3deSMauro Carvalho Chehab 	0x1f, 0x0b,
5425aee3deSMauro Carvalho Chehab 	0x20, 0xa1,
5525aee3deSMauro Carvalho Chehab 	0x21, 0x60,
5625aee3deSMauro Carvalho Chehab 	0x22, 0x00,
5725aee3deSMauro Carvalho Chehab 	0x23, 0x00,
5825aee3deSMauro Carvalho Chehab 	0x28, 0x00,
5925aee3deSMauro Carvalho Chehab 	0x29, 0x28,
6025aee3deSMauro Carvalho Chehab 	0x2a, 0x14,
6125aee3deSMauro Carvalho Chehab 	0x2b, 0x0f,
6225aee3deSMauro Carvalho Chehab 	0x2c, 0x09,
6325aee3deSMauro Carvalho Chehab 	0x2d, 0x05,
6425aee3deSMauro Carvalho Chehab 	0x31, 0x1f,
6525aee3deSMauro Carvalho Chehab 	0x32, 0x19,
6625aee3deSMauro Carvalho Chehab 	0x33, 0xfc,
6725aee3deSMauro Carvalho Chehab 	0x34, 0x13,
6825aee3deSMauro Carvalho Chehab 	0xff, 0xff,
6925aee3deSMauro Carvalho Chehab };
7025aee3deSMauro Carvalho Chehab 
7125aee3deSMauro Carvalho Chehab #define MANTIS_MODEL_NAME	"VP-1033"
7225aee3deSMauro Carvalho Chehab #define MANTIS_DEV_TYPE		"DVB-S/DSS"
7325aee3deSMauro Carvalho Chehab 
lgtdqcs001f_tuner_set(struct dvb_frontend * fe)746860f9caSMauro Carvalho Chehab static int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
7525aee3deSMauro Carvalho Chehab {
7625aee3deSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
7725aee3deSMauro Carvalho Chehab 	struct mantis_pci *mantis	= fe->dvb->priv;
7825aee3deSMauro Carvalho Chehab 	struct i2c_adapter *adapter	= &mantis->adapter;
7925aee3deSMauro Carvalho Chehab 
8025aee3deSMauro Carvalho Chehab 	u8 buf[4];
8125aee3deSMauro Carvalho Chehab 	u32 div;
8225aee3deSMauro Carvalho Chehab 
8325aee3deSMauro Carvalho Chehab 
8425aee3deSMauro Carvalho Chehab 	struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)};
8525aee3deSMauro Carvalho Chehab 
8625aee3deSMauro Carvalho Chehab 	div = p->frequency / 250;
8725aee3deSMauro Carvalho Chehab 
8825aee3deSMauro Carvalho Chehab 	buf[0] = (div >> 8) & 0x7f;
8925aee3deSMauro Carvalho Chehab 	buf[1] =  div & 0xff;
9025aee3deSMauro Carvalho Chehab 	buf[2] =  0x83;
9125aee3deSMauro Carvalho Chehab 	buf[3] =  0xc0;
9225aee3deSMauro Carvalho Chehab 
9325aee3deSMauro Carvalho Chehab 	if (p->frequency < 1531000)
9425aee3deSMauro Carvalho Chehab 		buf[3] |= 0x04;
9525aee3deSMauro Carvalho Chehab 	else
9625aee3deSMauro Carvalho Chehab 		buf[3] &= ~0x04;
9725aee3deSMauro Carvalho Chehab 	if (i2c_transfer(adapter, &msg, 1) < 0) {
9825aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed");
9925aee3deSMauro Carvalho Chehab 		return -EIO;
10025aee3deSMauro Carvalho Chehab 	}
10125aee3deSMauro Carvalho Chehab 	msleep_interruptible(100);
10225aee3deSMauro Carvalho Chehab 
10325aee3deSMauro Carvalho Chehab 	return 0;
10425aee3deSMauro Carvalho Chehab }
10525aee3deSMauro Carvalho Chehab 
lgtdqcs001f_set_symbol_rate(struct dvb_frontend * fe,u32 srate,u32 ratio)1066860f9caSMauro Carvalho Chehab static int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
10725aee3deSMauro Carvalho Chehab 				       u32 srate, u32 ratio)
10825aee3deSMauro Carvalho Chehab {
10925aee3deSMauro Carvalho Chehab 	u8 aclk = 0;
11025aee3deSMauro Carvalho Chehab 	u8 bclk = 0;
11125aee3deSMauro Carvalho Chehab 
11225aee3deSMauro Carvalho Chehab 	if (srate < 1500000) {
11325aee3deSMauro Carvalho Chehab 		aclk = 0xb7;
11425aee3deSMauro Carvalho Chehab 		bclk = 0x47;
11525aee3deSMauro Carvalho Chehab 	} else if (srate < 3000000) {
11625aee3deSMauro Carvalho Chehab 		aclk = 0xb7;
11725aee3deSMauro Carvalho Chehab 		bclk = 0x4b;
11825aee3deSMauro Carvalho Chehab 	} else if (srate < 7000000) {
11925aee3deSMauro Carvalho Chehab 		aclk = 0xb7;
12025aee3deSMauro Carvalho Chehab 		bclk = 0x4f;
12125aee3deSMauro Carvalho Chehab 	} else if (srate < 14000000) {
12225aee3deSMauro Carvalho Chehab 		aclk = 0xb7;
12325aee3deSMauro Carvalho Chehab 		bclk = 0x53;
12425aee3deSMauro Carvalho Chehab 	} else if (srate < 30000000) {
12525aee3deSMauro Carvalho Chehab 		aclk = 0xb6;
12625aee3deSMauro Carvalho Chehab 		bclk = 0x53;
12725aee3deSMauro Carvalho Chehab 	} else if (srate < 45000000) {
12825aee3deSMauro Carvalho Chehab 		aclk = 0xb4;
12925aee3deSMauro Carvalho Chehab 		bclk = 0x51;
13025aee3deSMauro Carvalho Chehab 	}
13125aee3deSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x13, aclk);
13225aee3deSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x14, bclk);
13325aee3deSMauro Carvalho Chehab 
13425aee3deSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
13525aee3deSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
13625aee3deSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x21,  ratio & 0xf0);
13725aee3deSMauro Carvalho Chehab 
13825aee3deSMauro Carvalho Chehab 	return 0;
13925aee3deSMauro Carvalho Chehab }
14025aee3deSMauro Carvalho Chehab 
141967a3783SHans Verkuil static struct stv0299_config lgtdqcs001f_config = {
14225aee3deSMauro Carvalho Chehab 	.demod_address		= 0x68,
14325aee3deSMauro Carvalho Chehab 	.inittab		= lgtdqcs001f_inittab,
14425aee3deSMauro Carvalho Chehab 	.mclk			= 88000000UL,
14525aee3deSMauro Carvalho Chehab 	.invert			= 0,
14625aee3deSMauro Carvalho Chehab 	.skip_reinit		= 0,
14725aee3deSMauro Carvalho Chehab 	.volt13_op0_op1		= STV0299_VOLT13_OP0,
14825aee3deSMauro Carvalho Chehab 	.min_delay_ms		= 100,
14925aee3deSMauro Carvalho Chehab 	.set_symbol_rate	= lgtdqcs001f_set_symbol_rate,
15025aee3deSMauro Carvalho Chehab };
15125aee3deSMauro Carvalho Chehab 
vp1033_frontend_init(struct mantis_pci * mantis,struct dvb_frontend * fe)15225aee3deSMauro Carvalho Chehab static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
15325aee3deSMauro Carvalho Chehab {
15425aee3deSMauro Carvalho Chehab 	struct i2c_adapter *adapter	= &mantis->adapter;
15525aee3deSMauro Carvalho Chehab 
15625aee3deSMauro Carvalho Chehab 	int err = 0;
15725aee3deSMauro Carvalho Chehab 
15825aee3deSMauro Carvalho Chehab 	err = mantis_frontend_power(mantis, POWER_ON);
15925aee3deSMauro Carvalho Chehab 	if (err == 0) {
16025aee3deSMauro Carvalho Chehab 		mantis_frontend_soft_reset(mantis);
16125aee3deSMauro Carvalho Chehab 		msleep(250);
16225aee3deSMauro Carvalho Chehab 
16325aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)");
16425aee3deSMauro Carvalho Chehab 		fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config, adapter);
16525aee3deSMauro Carvalho Chehab 
16625aee3deSMauro Carvalho Chehab 		if (fe) {
16725aee3deSMauro Carvalho Chehab 			fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set;
16825aee3deSMauro Carvalho Chehab 			dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x",
16925aee3deSMauro Carvalho Chehab 				lgtdqcs001f_config.demod_address);
17025aee3deSMauro Carvalho Chehab 
17125aee3deSMauro Carvalho Chehab 			dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success");
17225aee3deSMauro Carvalho Chehab 		} else {
17325aee3deSMauro Carvalho Chehab 			return -1;
17425aee3deSMauro Carvalho Chehab 		}
17525aee3deSMauro Carvalho Chehab 	} else {
17625aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
17725aee3deSMauro Carvalho Chehab 			adapter->name,
17825aee3deSMauro Carvalho Chehab 			err);
17925aee3deSMauro Carvalho Chehab 
18025aee3deSMauro Carvalho Chehab 		return -EIO;
18125aee3deSMauro Carvalho Chehab 	}
18225aee3deSMauro Carvalho Chehab 	mantis->fe = fe;
18325aee3deSMauro Carvalho Chehab 	dprintk(MANTIS_ERROR, 1, "Done!");
18425aee3deSMauro Carvalho Chehab 
18525aee3deSMauro Carvalho Chehab 	return 0;
18625aee3deSMauro Carvalho Chehab }
18725aee3deSMauro Carvalho Chehab 
18825aee3deSMauro Carvalho Chehab struct mantis_hwconfig vp1033_config = {
18925aee3deSMauro Carvalho Chehab 	.model_name		= MANTIS_MODEL_NAME,
19025aee3deSMauro Carvalho Chehab 	.dev_type		= MANTIS_DEV_TYPE,
19125aee3deSMauro Carvalho Chehab 	.ts_size		= MANTIS_TS_204,
19225aee3deSMauro Carvalho Chehab 
19325aee3deSMauro Carvalho Chehab 	.baud_rate		= MANTIS_BAUD_9600,
19425aee3deSMauro Carvalho Chehab 	.parity			= MANTIS_PARITY_NONE,
19525aee3deSMauro Carvalho Chehab 	.bytes			= 0,
19625aee3deSMauro Carvalho Chehab 
19725aee3deSMauro Carvalho Chehab 	.frontend_init		= vp1033_frontend_init,
19825aee3deSMauro Carvalho Chehab 	.power			= GPIF_A12,
19925aee3deSMauro Carvalho Chehab 	.reset			= GPIF_A13,
20025aee3deSMauro Carvalho Chehab };
201