2 * cx18 functions for DVB support
4 * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "cx18-version.h"
24 #include "cx18-streams.h"
25 #include "cx18-cards.h"
29 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
31 #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
33 static struct mxl5005s_config hauppauge_hvr1600_tuner
= {
34 .i2c_address
= 0xC6 >> 1,
35 .if_freq
= IF_FREQ_5380000HZ
,
36 .xtal_freq
= CRYSTAL_FREQ_16000000HZ
,
37 .agc_mode
= MXL_SINGLE_AGC
,
38 .tracking_filter
= MXL_TF_C_H
,
39 .rssi_enable
= MXL_RSSI_ENABLE
,
40 .cap_select
= MXL_CAP_SEL_ENABLE
,
41 .div_out
= MXL_DIV_OUT_4
,
42 .clock_out
= MXL_CLOCK_OUT_DISABLE
,
43 .output_load
= MXL5005S_IF_OUTPUT_LOAD_200_OHM
,
44 .top
= MXL5005S_TOP_25P2
,
45 .mod_mode
= MXL_DIGITAL_MODE
,
46 .if_mode
= MXL_ZERO_IF
,
47 .AgcMasterByte
= 0x00,
50 static struct s5h1409_config hauppauge_hvr1600_config
= {
51 .demod_address
= 0x32 >> 1,
52 .output_mode
= S5H1409_SERIAL_OUTPUT
,
53 .gpio
= S5H1409_GPIO_ON
,
55 .inversion
= S5H1409_INVERSION_OFF
,
56 .status_mode
= S5H1409_DEMODLOCKING
,
57 .mpeg_timing
= S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
61 static int dvb_register(struct cx18_stream
*stream
);
63 /* Kernel DVB framework calls this when the feed needs to start.
64 * The CX18 framework should enable the transport DMA handling
65 * and queue processing.
67 static int cx18_dvb_start_feed(struct dvb_demux_feed
*feed
)
69 struct dvb_demux
*demux
= feed
->demux
;
70 struct cx18_stream
*stream
= (struct cx18_stream
*) demux
->priv
;
71 struct cx18
*cx
= stream
->cx
;
75 CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
76 feed
->pid
, feed
->index
);
77 switch (cx
->card
->type
) {
78 case CX18_CARD_HVR_1600_ESMT
:
79 case CX18_CARD_HVR_1600_SAMSUNG
:
80 v
= read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL
);
81 v
|= 0x00400000; /* Serial Mode */
82 v
|= 0x00002000; /* Data Length - Byte */
83 v
|= 0x00010000; /* Error - Polarity */
84 v
|= 0x00020000; /* Error - Passthru */
85 v
|= 0x000c0000; /* Error - Ignore */
86 write_reg(v
, CX18_REG_DMUX_NUM_PORT_0_CONTROL
);
90 /* Assumption - Parallel transport - Signalling
91 * undefined or default.
96 if (!demux
->dmx
.frontend
)
100 mutex_lock(&stream
->dvb
.feedlock
);
101 if (stream
->dvb
.feeding
++ == 0) {
102 CX18_DEBUG_INFO("Starting Transport DMA\n");
103 ret
= cx18_start_v4l2_encode_stream(stream
);
106 mutex_unlock(&stream
->dvb
.feedlock
);
112 /* Kernel DVB framework calls this when the feed needs to stop. */
113 static int cx18_dvb_stop_feed(struct dvb_demux_feed
*feed
)
115 struct dvb_demux
*demux
= feed
->demux
;
116 struct cx18_stream
*stream
= (struct cx18_stream
*)demux
->priv
;
117 struct cx18
*cx
= stream
->cx
;
120 CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
121 feed
->pid
, feed
->index
);
124 mutex_lock(&stream
->dvb
.feedlock
);
125 if (--stream
->dvb
.feeding
== 0) {
126 CX18_DEBUG_INFO("Stopping Transport DMA\n");
127 ret
= cx18_stop_v4l2_encode_stream(stream
, 0);
130 mutex_unlock(&stream
->dvb
.feedlock
);
136 int cx18_dvb_register(struct cx18_stream
*stream
)
138 struct cx18
*cx
= stream
->cx
;
139 struct cx18_dvb
*dvb
= &stream
->dvb
;
140 struct dvb_adapter
*dvb_adapter
;
141 struct dvb_demux
*dvbdemux
;
142 struct dmx_demux
*dmx
;
148 ret
= dvb_register_adapter(&dvb
->dvb_adapter
,
150 THIS_MODULE
, &cx
->dev
->dev
, adapter_nr
);
154 dvb_adapter
= &dvb
->dvb_adapter
;
156 dvbdemux
= &dvb
->demux
;
158 dvbdemux
->priv
= (void *)stream
;
160 dvbdemux
->filternum
= 256;
161 dvbdemux
->feednum
= 256;
162 dvbdemux
->start_feed
= cx18_dvb_start_feed
;
163 dvbdemux
->stop_feed
= cx18_dvb_stop_feed
;
164 dvbdemux
->dmx
.capabilities
= (DMX_TS_FILTERING
|
165 DMX_SECTION_FILTERING
| DMX_MEMORY_BASED_FILTERING
);
166 ret
= dvb_dmx_init(dvbdemux
);
168 goto err_dvb_unregister_adapter
;
170 dmx
= &dvbdemux
->dmx
;
172 dvb
->hw_frontend
.source
= DMX_FRONTEND_0
;
173 dvb
->mem_frontend
.source
= DMX_MEMORY_FE
;
174 dvb
->dmxdev
.filternum
= 256;
175 dvb
->dmxdev
.demux
= dmx
;
177 ret
= dvb_dmxdev_init(&dvb
->dmxdev
, dvb_adapter
);
179 goto err_dvb_dmx_release
;
181 ret
= dmx
->add_frontend(dmx
, &dvb
->hw_frontend
);
183 goto err_dvb_dmxdev_release
;
185 ret
= dmx
->add_frontend(dmx
, &dvb
->mem_frontend
);
187 goto err_remove_hw_frontend
;
189 ret
= dmx
->connect_frontend(dmx
, &dvb
->hw_frontend
);
191 goto err_remove_mem_frontend
;
193 ret
= dvb_register(stream
);
195 goto err_disconnect_frontend
;
197 dvb_net_init(dvb_adapter
, &dvb
->dvbnet
, dmx
);
199 CX18_INFO("DVB Frontend registered\n");
200 mutex_init(&dvb
->feedlock
);
204 err_disconnect_frontend
:
205 dmx
->disconnect_frontend(dmx
);
206 err_remove_mem_frontend
:
207 dmx
->remove_frontend(dmx
, &dvb
->mem_frontend
);
208 err_remove_hw_frontend
:
209 dmx
->remove_frontend(dmx
, &dvb
->hw_frontend
);
210 err_dvb_dmxdev_release
:
211 dvb_dmxdev_release(&dvb
->dmxdev
);
213 dvb_dmx_release(dvbdemux
);
214 err_dvb_unregister_adapter
:
215 dvb_unregister_adapter(dvb_adapter
);
220 void cx18_dvb_unregister(struct cx18_stream
*stream
)
222 struct cx18
*cx
= stream
->cx
;
223 struct cx18_dvb
*dvb
= &stream
->dvb
;
224 struct dvb_adapter
*dvb_adapter
;
225 struct dvb_demux
*dvbdemux
;
226 struct dmx_demux
*dmx
;
228 CX18_INFO("unregister DVB\n");
230 dvb_adapter
= &dvb
->dvb_adapter
;
231 dvbdemux
= &dvb
->demux
;
232 dmx
= &dvbdemux
->dmx
;
235 dvb_net_release(&dvb
->dvbnet
);
236 dmx
->remove_frontend(dmx
, &dvb
->mem_frontend
);
237 dmx
->remove_frontend(dmx
, &dvb
->hw_frontend
);
238 dvb_dmxdev_release(&dvb
->dmxdev
);
239 dvb_dmx_release(dvbdemux
);
240 dvb_unregister_frontend(dvb
->fe
);
241 dvb_frontend_detach(dvb
->fe
);
242 dvb_unregister_adapter(dvb_adapter
);
245 /* All the DVB attach calls go here, this function get's modified
246 * for each new card. No other function in this file needs
249 static int dvb_register(struct cx18_stream
*stream
)
251 struct cx18_dvb
*dvb
= &stream
->dvb
;
252 struct cx18
*cx
= stream
->cx
;
255 switch (cx
->card
->type
) {
256 case CX18_CARD_HVR_1600_ESMT
:
257 case CX18_CARD_HVR_1600_SAMSUNG
:
258 dvb
->fe
= dvb_attach(s5h1409_attach
,
259 &hauppauge_hvr1600_config
,
261 if (dvb
->fe
!= NULL
) {
262 dvb_attach(mxl5005s_attach
, dvb
->fe
,
264 &hauppauge_hvr1600_tuner
);
269 /* No Digital Tv Support */
273 if (dvb
->fe
== NULL
) {
274 CX18_ERR("frontend initialization failed\n");
278 ret
= dvb_register_frontend(&dvb
->dvb_adapter
, dvb
->fe
);
280 if (dvb
->fe
->ops
.release
)
281 dvb
->fe
->ops
.release(dvb
->fe
);