cx23885-dvb.c revision f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9
1d19770e5178a4bc49641711246360c25781d20a4Steven Toth/*
2d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  Driver for the Conexant CX23885 PCIe bridge
3d19770e5178a4bc49641711246360c25781d20a4Steven Toth *
4d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
5d19770e5178a4bc49641711246360c25781d20a4Steven Toth *
6d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  This program is free software; you can redistribute it and/or modify
7d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  it under the terms of the GNU General Public License as published by
8d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  the Free Software Foundation; either version 2 of the License, or
9d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  (at your option) any later version.
10d19770e5178a4bc49641711246360c25781d20a4Steven Toth *
11d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  This program is distributed in the hope that it will be useful,
12d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d19770e5178a4bc49641711246360c25781d20a4Steven Toth *
15d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  GNU General Public License for more details.
16d19770e5178a4bc49641711246360c25781d20a4Steven Toth *
17d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  You should have received a copy of the GNU General Public License
18d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  along with this program; if not, write to the Free Software
19d19770e5178a4bc49641711246360c25781d20a4Steven Toth *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20d19770e5178a4bc49641711246360c25781d20a4Steven Toth */
21d19770e5178a4bc49641711246360c25781d20a4Steven Toth
22d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <linux/module.h>
23d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <linux/init.h>
24d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <linux/device.h>
25d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <linux/fs.h>
26d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <linux/kthread.h>
27d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <linux/file.h>
28d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <linux/suspend.h>
29d19770e5178a4bc49641711246360c25781d20a4Steven Toth
30d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include "cx23885.h"
31d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include <media/v4l2-common.h>
32d19770e5178a4bc49641711246360c25781d20a4Steven Toth
33d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include "s5h1409.h"
34d19770e5178a4bc49641711246360c25781d20a4Steven Toth#include "mt2131.h"
359bc37caadffe8327683980b2323371691fa182e3Michael Krufky#include "lgdt330x.h"
369bc37caadffe8327683980b2323371691fa182e3Michael Krufky#include "dvb-pll.h"
37d19770e5178a4bc49641711246360c25781d20a4Steven Toth
382e52f215be1b3a0337788c8d3345bdf5e3894e19Steven Tothstatic unsigned int debug = 0;
39d19770e5178a4bc49641711246360c25781d20a4Steven Toth
40d19770e5178a4bc49641711246360c25781d20a4Steven Toth#define dprintk(level,fmt, arg...)	if (debug >= level) \
41d19770e5178a4bc49641711246360c25781d20a4Steven Toth	printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg)
42d19770e5178a4bc49641711246360c25781d20a4Steven Toth
43d19770e5178a4bc49641711246360c25781d20a4Steven Toth/* ------------------------------------------------------------------ */
44d19770e5178a4bc49641711246360c25781d20a4Steven Toth
45d19770e5178a4bc49641711246360c25781d20a4Steven Tothstatic int dvb_buf_setup(struct videobuf_queue *q,
46d19770e5178a4bc49641711246360c25781d20a4Steven Toth			 unsigned int *count, unsigned int *size)
47d19770e5178a4bc49641711246360c25781d20a4Steven Toth{
48d19770e5178a4bc49641711246360c25781d20a4Steven Toth	struct cx23885_tsport *port = q->priv_data;
49d19770e5178a4bc49641711246360c25781d20a4Steven Toth
50d19770e5178a4bc49641711246360c25781d20a4Steven Toth	port->ts_packet_size  = 188 * 4;
51d19770e5178a4bc49641711246360c25781d20a4Steven Toth	port->ts_packet_count = 32;
52d19770e5178a4bc49641711246360c25781d20a4Steven Toth
53d19770e5178a4bc49641711246360c25781d20a4Steven Toth	*size  = port->ts_packet_size * port->ts_packet_count;
54d19770e5178a4bc49641711246360c25781d20a4Steven Toth	*count = 32;
55d19770e5178a4bc49641711246360c25781d20a4Steven Toth	return 0;
56d19770e5178a4bc49641711246360c25781d20a4Steven Toth}
57d19770e5178a4bc49641711246360c25781d20a4Steven Toth
5844a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufkystatic int dvb_buf_prepare(struct videobuf_queue *q,
5944a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky			   struct videobuf_buffer *vb, enum v4l2_field field)
60d19770e5178a4bc49641711246360c25781d20a4Steven Toth{
61d19770e5178a4bc49641711246360c25781d20a4Steven Toth	struct cx23885_tsport *port = q->priv_data;
6244a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky	return cx23885_buf_prepare(q, port, (struct cx23885_buffer*)vb, field);
63d19770e5178a4bc49641711246360c25781d20a4Steven Toth}
64d19770e5178a4bc49641711246360c25781d20a4Steven Toth
65d19770e5178a4bc49641711246360c25781d20a4Steven Tothstatic void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
66d19770e5178a4bc49641711246360c25781d20a4Steven Toth{
67d19770e5178a4bc49641711246360c25781d20a4Steven Toth	struct cx23885_tsport *port = q->priv_data;
68d19770e5178a4bc49641711246360c25781d20a4Steven Toth	cx23885_buf_queue(port, (struct cx23885_buffer*)vb);
69d19770e5178a4bc49641711246360c25781d20a4Steven Toth}
70d19770e5178a4bc49641711246360c25781d20a4Steven Toth
7144a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufkystatic void dvb_buf_release(struct videobuf_queue *q,
7244a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky			    struct videobuf_buffer *vb)
73d19770e5178a4bc49641711246360c25781d20a4Steven Toth{
74d19770e5178a4bc49641711246360c25781d20a4Steven Toth	cx23885_free_buffer(q, (struct cx23885_buffer*)vb);
75d19770e5178a4bc49641711246360c25781d20a4Steven Toth}
76d19770e5178a4bc49641711246360c25781d20a4Steven Toth
77d19770e5178a4bc49641711246360c25781d20a4Steven Tothstatic struct videobuf_queue_ops dvb_qops = {
78d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.buf_setup    = dvb_buf_setup,
79d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.buf_prepare  = dvb_buf_prepare,
80d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.buf_queue    = dvb_buf_queue,
81d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.buf_release  = dvb_buf_release,
82d19770e5178a4bc49641711246360c25781d20a4Steven Toth};
83d19770e5178a4bc49641711246360c25781d20a4Steven Toth
8486184e06da4b71fc24ae9505ec60ce95c098d0deSteven Tothstatic struct s5h1409_config hauppauge_generic_config = {
85d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.demod_address = 0x32 >> 1,
86d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.output_mode   = S5H1409_SERIAL_OUTPUT,
87fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth	.gpio          = S5H1409_GPIO_ON,
88fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth	.if_freq       = 44000,
89fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth	.inversion     = S5H1409_INVERSION_OFF,
90fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth	.status_mode   = S5H1409_DEMODLOCKING
91fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth};
92fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth
93fc959befe0f0e4647bb4e326e3ae55875401888aSteven Tothstatic struct s5h1409_config hauppauge_hvr1800lp_config = {
94fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth	.demod_address = 0x32 >> 1,
95fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth	.output_mode   = S5H1409_SERIAL_OUTPUT,
96d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.gpio          = S5H1409_GPIO_OFF,
97d19770e5178a4bc49641711246360c25781d20a4Steven Toth	.if_freq       = 44000,
98fe475163ff9680495af3b1b5b7633ea7a42e4185Steven Toth	.inversion     = S5H1409_INVERSION_OFF,
99fe475163ff9680495af3b1b5b7633ea7a42e4185Steven Toth	.status_mode   = S5H1409_DEMODLOCKING
100d19770e5178a4bc49641711246360c25781d20a4Steven Toth};
101d19770e5178a4bc49641711246360c25781d20a4Steven Toth
10286184e06da4b71fc24ae9505ec60ce95c098d0deSteven Tothstatic struct mt2131_config hauppauge_generic_tunerconfig = {
103a77743bc2d29197d48a6f4ae9f8f9e0f0b0ba5d7Steven Toth	0x61
104a77743bc2d29197d48a6f4ae9f8f9e0f0b0ba5d7Steven Toth};
105a77743bc2d29197d48a6f4ae9f8f9e0f0b0ba5d7Steven Toth
1069bc37caadffe8327683980b2323371691fa182e3Michael Krufkystatic struct lgdt330x_config fusionhdtv_5_express = {
1079bc37caadffe8327683980b2323371691fa182e3Michael Krufky	.demod_address = 0x0e,
1089bc37caadffe8327683980b2323371691fa182e3Michael Krufky	.demod_chip = LGDT3303,
1099bc37caadffe8327683980b2323371691fa182e3Michael Krufky	.serial_mpeg = 0x40,
1109bc37caadffe8327683980b2323371691fa182e3Michael Krufky};
1119bc37caadffe8327683980b2323371691fa182e3Michael Krufky
112d19770e5178a4bc49641711246360c25781d20a4Steven Tothstatic int dvb_register(struct cx23885_tsport *port)
113d19770e5178a4bc49641711246360c25781d20a4Steven Toth{
114d19770e5178a4bc49641711246360c25781d20a4Steven Toth	struct cx23885_dev *dev = port->dev;
115f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky	struct cx23885_i2c *i2c_bus = NULL;
116d19770e5178a4bc49641711246360c25781d20a4Steven Toth
117d19770e5178a4bc49641711246360c25781d20a4Steven Toth	/* init struct videobuf_dvb */
118d19770e5178a4bc49641711246360c25781d20a4Steven Toth	port->dvb.name = dev->name;
119d19770e5178a4bc49641711246360c25781d20a4Steven Toth
120d19770e5178a4bc49641711246360c25781d20a4Steven Toth	/* init frontend */
121d19770e5178a4bc49641711246360c25781d20a4Steven Toth	switch (dev->board) {
122a77743bc2d29197d48a6f4ae9f8f9e0f0b0ba5d7Steven Toth	case CX23885_BOARD_HAUPPAUGE_HVR1250:
123d19770e5178a4bc49641711246360c25781d20a4Steven Toth	case CX23885_BOARD_HAUPPAUGE_HVR1800:
124f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky		i2c_bus = &dev->i2c_bus[0];
125d19770e5178a4bc49641711246360c25781d20a4Steven Toth		port->dvb.frontend = dvb_attach(s5h1409_attach,
12686184e06da4b71fc24ae9505ec60ce95c098d0deSteven Toth						&hauppauge_generic_config,
127f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky						&i2c_bus->i2c_adap);
128d19770e5178a4bc49641711246360c25781d20a4Steven Toth		if (port->dvb.frontend != NULL) {
12944a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky			dvb_attach(mt2131_attach, port->dvb.frontend,
130f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky				   &i2c_bus->i2c_adap,
13186184e06da4b71fc24ae9505ec60ce95c098d0deSteven Toth				   &hauppauge_generic_tunerconfig, 0);
132d19770e5178a4bc49641711246360c25781d20a4Steven Toth		}
133d19770e5178a4bc49641711246360c25781d20a4Steven Toth		break;
134fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
135f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky		i2c_bus = &dev->i2c_bus[0];
136fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth		port->dvb.frontend = dvb_attach(s5h1409_attach,
137fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth						&hauppauge_hvr1800lp_config,
138f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky						&i2c_bus->i2c_adap);
139fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth		if (port->dvb.frontend != NULL) {
140fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth			dvb_attach(mt2131_attach, port->dvb.frontend,
141f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky				   &i2c_bus->i2c_adap,
142fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth				   &hauppauge_generic_tunerconfig, 0);
143fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth		}
144fc959befe0f0e4647bb4e326e3ae55875401888aSteven Toth		break;
1459bc37caadffe8327683980b2323371691fa182e3Michael Krufky	case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
146f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky		i2c_bus = &dev->i2c_bus[0];
1479bc37caadffe8327683980b2323371691fa182e3Michael Krufky		port->dvb.frontend = dvb_attach(lgdt330x_attach,
1489bc37caadffe8327683980b2323371691fa182e3Michael Krufky						&fusionhdtv_5_express,
149f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky						&i2c_bus->i2c_adap);
1509bc37caadffe8327683980b2323371691fa182e3Michael Krufky		if (port->dvb.frontend != NULL) {
151f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky			dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61,
152f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky				   &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
1539bc37caadffe8327683980b2323371691fa182e3Michael Krufky		}
1549bc37caadffe8327683980b2323371691fa182e3Michael Krufky		break;
155d19770e5178a4bc49641711246360c25781d20a4Steven Toth	default:
156d19770e5178a4bc49641711246360c25781d20a4Steven Toth		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
157d19770e5178a4bc49641711246360c25781d20a4Steven Toth		       dev->name);
158d19770e5178a4bc49641711246360c25781d20a4Steven Toth		break;
159d19770e5178a4bc49641711246360c25781d20a4Steven Toth	}
160d19770e5178a4bc49641711246360c25781d20a4Steven Toth	if (NULL == port->dvb.frontend) {
161d19770e5178a4bc49641711246360c25781d20a4Steven Toth		printk("%s: frontend initialization failed\n", dev->name);
162d19770e5178a4bc49641711246360c25781d20a4Steven Toth		return -1;
163d19770e5178a4bc49641711246360c25781d20a4Steven Toth	}
164d19770e5178a4bc49641711246360c25781d20a4Steven Toth
165d19770e5178a4bc49641711246360c25781d20a4Steven Toth	/* Put the analog decoder in standby to keep it quiet */
166f139fa71c03d80c1d1ee60aa4b0a3ec7a14d45f9Michael Krufky	cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
167d19770e5178a4bc49641711246360c25781d20a4Steven Toth
168d19770e5178a4bc49641711246360c25781d20a4Steven Toth	/* register everything */
16944a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky	return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
17044a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky				     &dev->pci->dev);
171d19770e5178a4bc49641711246360c25781d20a4Steven Toth}
172d19770e5178a4bc49641711246360c25781d20a4Steven Toth
173d19770e5178a4bc49641711246360c25781d20a4Steven Tothint cx23885_dvb_register(struct cx23885_tsport *port)
174d19770e5178a4bc49641711246360c25781d20a4Steven Toth{
175d19770e5178a4bc49641711246360c25781d20a4Steven Toth	struct cx23885_dev *dev = port->dev;
176d19770e5178a4bc49641711246360c25781d20a4Steven Toth	int err;
177d19770e5178a4bc49641711246360c25781d20a4Steven Toth
17844a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky	dprintk(1, "%s\n", __FUNCTION__);
17944a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
180d19770e5178a4bc49641711246360c25781d20a4Steven Toth		dev->board,
181d19770e5178a4bc49641711246360c25781d20a4Steven Toth		dev->name,
182d19770e5178a4bc49641711246360c25781d20a4Steven Toth		dev->pci_bus,
183d19770e5178a4bc49641711246360c25781d20a4Steven Toth		dev->pci_slot);
184d19770e5178a4bc49641711246360c25781d20a4Steven Toth
185d19770e5178a4bc49641711246360c25781d20a4Steven Toth	err = -ENODEV;
186d19770e5178a4bc49641711246360c25781d20a4Steven Toth
187d19770e5178a4bc49641711246360c25781d20a4Steven Toth	/* dvb stuff */
188d19770e5178a4bc49641711246360c25781d20a4Steven Toth	printk("%s: cx23885 based dvb card\n", dev->name);
18944a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky	videobuf_queue_init(&port->dvb.dvbq, &dvb_qops,	dev->pci, &port->slock,
19044a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky			    V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
19144a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky			    sizeof(struct cx23885_buffer), port);
192d19770e5178a4bc49641711246360c25781d20a4Steven Toth	err = dvb_register(port);
193d19770e5178a4bc49641711246360c25781d20a4Steven Toth	if (err != 0)
194d19770e5178a4bc49641711246360c25781d20a4Steven Toth		printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err);
195d19770e5178a4bc49641711246360c25781d20a4Steven Toth
196d19770e5178a4bc49641711246360c25781d20a4Steven Toth	return err;
197d19770e5178a4bc49641711246360c25781d20a4Steven Toth}
198d19770e5178a4bc49641711246360c25781d20a4Steven Toth
199d19770e5178a4bc49641711246360c25781d20a4Steven Tothint cx23885_dvb_unregister(struct cx23885_tsport *port)
200d19770e5178a4bc49641711246360c25781d20a4Steven Toth{
201d19770e5178a4bc49641711246360c25781d20a4Steven Toth	/* dvb */
202d19770e5178a4bc49641711246360c25781d20a4Steven Toth	if(port->dvb.frontend)
203d19770e5178a4bc49641711246360c25781d20a4Steven Toth		videobuf_dvb_unregister(&port->dvb);
204d19770e5178a4bc49641711246360c25781d20a4Steven Toth
205d19770e5178a4bc49641711246360c25781d20a4Steven Toth	return 0;
206d19770e5178a4bc49641711246360c25781d20a4Steven Toth}
20744a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky
20844a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky/*
20944a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky * Local variables:
21044a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky * c-basic-offset: 8
21144a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky * End:
21244a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
21344a6481dcd9ec835bbd608b1b2ee47ee62c7e1d8Michael Krufky*/
214