2 * cx18 functions for DVB support
4 * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "cx18-version.h"
26 #include "cx18-queue.h"
27 #include "cx18-streams.h"
28 #include "cx18-cards.h"
32 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
34 #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
36 static struct mxl5005s_config hauppauge_hvr1600_tuner
= {
37 .i2c_address
= 0xC6 >> 1,
38 .if_freq
= IF_FREQ_5380000HZ
,
39 .xtal_freq
= CRYSTAL_FREQ_16000000HZ
,
40 .agc_mode
= MXL_SINGLE_AGC
,
41 .tracking_filter
= MXL_TF_C_H
,
42 .rssi_enable
= MXL_RSSI_ENABLE
,
43 .cap_select
= MXL_CAP_SEL_ENABLE
,
44 .div_out
= MXL_DIV_OUT_4
,
45 .clock_out
= MXL_CLOCK_OUT_DISABLE
,
46 .output_load
= MXL5005S_IF_OUTPUT_LOAD_200_OHM
,
47 .top
= MXL5005S_TOP_25P2
,
48 .mod_mode
= MXL_DIGITAL_MODE
,
49 .if_mode
= MXL_ZERO_IF
,
50 .AgcMasterByte
= 0x00,
53 static struct s5h1409_config hauppauge_hvr1600_config
= {
54 .demod_address
= 0x32 >> 1,
55 .output_mode
= S5H1409_SERIAL_OUTPUT
,
56 .gpio
= S5H1409_GPIO_ON
,
58 .inversion
= S5H1409_INVERSION_OFF
,
59 .status_mode
= S5H1409_DEMODLOCKING
,
60 .mpeg_timing
= S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
64 static int dvb_register(struct cx18_stream
*stream
);
66 /* Kernel DVB framework calls this when the feed needs to start.
67 * The CX18 framework should enable the transport DMA handling
68 * and queue processing.
70 static int cx18_dvb_start_feed(struct dvb_demux_feed
*feed
)
72 struct dvb_demux
*demux
= feed
->demux
;
73 struct cx18_stream
*stream
= (struct cx18_stream
*) demux
->priv
;
74 struct cx18
*cx
= stream
->cx
;
78 CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
79 feed
->pid
, feed
->index
);
81 mutex_lock(&cx
->serialize_lock
);
82 ret
= cx18_init_on_first_open(cx
);
83 mutex_unlock(&cx
->serialize_lock
);
85 CX18_ERR("Failed to initialize firmware starting DVB feed\n");
90 switch (cx
->card
->type
) {
91 case CX18_CARD_HVR_1600_ESMT
:
92 case CX18_CARD_HVR_1600_SAMSUNG
:
93 v
= cx18_read_reg(cx
, CX18_REG_DMUX_NUM_PORT_0_CONTROL
);
94 v
|= 0x00400000; /* Serial Mode */
95 v
|= 0x00002000; /* Data Length - Byte */
96 v
|= 0x00010000; /* Error - Polarity */
97 v
|= 0x00020000; /* Error - Passthru */
98 v
|= 0x000c0000; /* Error - Ignore */
99 cx18_write_reg(cx
, v
, CX18_REG_DMUX_NUM_PORT_0_CONTROL
);
103 /* Assumption - Parallel transport - Signalling
104 * undefined or default.
109 if (!demux
->dmx
.frontend
)
115 mutex_lock(&stream
->dvb
.feedlock
);
116 if (stream
->dvb
.feeding
++ == 0) {
117 CX18_DEBUG_INFO("Starting Transport DMA\n");
118 set_bit(CX18_F_S_STREAMING
, &stream
->s_flags
);
119 ret
= cx18_start_v4l2_encode_stream(stream
);
121 CX18_DEBUG_INFO("Failed to start Transport DMA\n");
122 stream
->dvb
.feeding
--;
123 if (stream
->dvb
.feeding
== 0)
124 clear_bit(CX18_F_S_STREAMING
, &stream
->s_flags
);
128 mutex_unlock(&stream
->dvb
.feedlock
);
133 /* Kernel DVB framework calls this when the feed needs to stop. */
134 static int cx18_dvb_stop_feed(struct dvb_demux_feed
*feed
)
136 struct dvb_demux
*demux
= feed
->demux
;
137 struct cx18_stream
*stream
= (struct cx18_stream
*)demux
->priv
;
138 struct cx18
*cx
= stream
->cx
;
141 CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
142 feed
->pid
, feed
->index
);
145 mutex_lock(&stream
->dvb
.feedlock
);
146 if (--stream
->dvb
.feeding
== 0) {
147 CX18_DEBUG_INFO("Stopping Transport DMA\n");
148 ret
= cx18_stop_v4l2_encode_stream(stream
, 0);
151 mutex_unlock(&stream
->dvb
.feedlock
);
157 int cx18_dvb_register(struct cx18_stream
*stream
)
159 struct cx18
*cx
= stream
->cx
;
160 struct cx18_dvb
*dvb
= &stream
->dvb
;
161 struct dvb_adapter
*dvb_adapter
;
162 struct dvb_demux
*dvbdemux
;
163 struct dmx_demux
*dmx
;
169 ret
= dvb_register_adapter(&dvb
->dvb_adapter
,
171 THIS_MODULE
, &cx
->pci_dev
->dev
, adapter_nr
);
175 dvb_adapter
= &dvb
->dvb_adapter
;
177 dvbdemux
= &dvb
->demux
;
179 dvbdemux
->priv
= (void *)stream
;
181 dvbdemux
->filternum
= 256;
182 dvbdemux
->feednum
= 256;
183 dvbdemux
->start_feed
= cx18_dvb_start_feed
;
184 dvbdemux
->stop_feed
= cx18_dvb_stop_feed
;
185 dvbdemux
->dmx
.capabilities
= (DMX_TS_FILTERING
|
186 DMX_SECTION_FILTERING
| DMX_MEMORY_BASED_FILTERING
);
187 ret
= dvb_dmx_init(dvbdemux
);
189 goto err_dvb_unregister_adapter
;
191 dmx
= &dvbdemux
->dmx
;
193 dvb
->hw_frontend
.source
= DMX_FRONTEND_0
;
194 dvb
->mem_frontend
.source
= DMX_MEMORY_FE
;
195 dvb
->dmxdev
.filternum
= 256;
196 dvb
->dmxdev
.demux
= dmx
;
198 ret
= dvb_dmxdev_init(&dvb
->dmxdev
, dvb_adapter
);
200 goto err_dvb_dmx_release
;
202 ret
= dmx
->add_frontend(dmx
, &dvb
->hw_frontend
);
204 goto err_dvb_dmxdev_release
;
206 ret
= dmx
->add_frontend(dmx
, &dvb
->mem_frontend
);
208 goto err_remove_hw_frontend
;
210 ret
= dmx
->connect_frontend(dmx
, &dvb
->hw_frontend
);
212 goto err_remove_mem_frontend
;
214 ret
= dvb_register(stream
);
216 goto err_disconnect_frontend
;
218 dvb_net_init(dvb_adapter
, &dvb
->dvbnet
, dmx
);
220 CX18_INFO("DVB Frontend registered\n");
221 CX18_INFO("Registered DVB adapter%d for %s (%d x %d kB)\n",
222 stream
->dvb
.dvb_adapter
.num
, stream
->name
,
223 stream
->buffers
, stream
->buf_size
/1024);
225 mutex_init(&dvb
->feedlock
);
229 err_disconnect_frontend
:
230 dmx
->disconnect_frontend(dmx
);
231 err_remove_mem_frontend
:
232 dmx
->remove_frontend(dmx
, &dvb
->mem_frontend
);
233 err_remove_hw_frontend
:
234 dmx
->remove_frontend(dmx
, &dvb
->hw_frontend
);
235 err_dvb_dmxdev_release
:
236 dvb_dmxdev_release(&dvb
->dmxdev
);
238 dvb_dmx_release(dvbdemux
);
239 err_dvb_unregister_adapter
:
240 dvb_unregister_adapter(dvb_adapter
);
245 void cx18_dvb_unregister(struct cx18_stream
*stream
)
247 struct cx18
*cx
= stream
->cx
;
248 struct cx18_dvb
*dvb
= &stream
->dvb
;
249 struct dvb_adapter
*dvb_adapter
;
250 struct dvb_demux
*dvbdemux
;
251 struct dmx_demux
*dmx
;
253 CX18_INFO("unregister DVB\n");
255 dvb_adapter
= &dvb
->dvb_adapter
;
256 dvbdemux
= &dvb
->demux
;
257 dmx
= &dvbdemux
->dmx
;
260 dvb_net_release(&dvb
->dvbnet
);
261 dmx
->remove_frontend(dmx
, &dvb
->mem_frontend
);
262 dmx
->remove_frontend(dmx
, &dvb
->hw_frontend
);
263 dvb_dmxdev_release(&dvb
->dmxdev
);
264 dvb_dmx_release(dvbdemux
);
265 dvb_unregister_frontend(dvb
->fe
);
266 dvb_frontend_detach(dvb
->fe
);
267 dvb_unregister_adapter(dvb_adapter
);
270 /* All the DVB attach calls go here, this function get's modified
271 * for each new card. No other function in this file needs
274 static int dvb_register(struct cx18_stream
*stream
)
276 struct cx18_dvb
*dvb
= &stream
->dvb
;
277 struct cx18
*cx
= stream
->cx
;
280 switch (cx
->card
->type
) {
281 case CX18_CARD_HVR_1600_ESMT
:
282 case CX18_CARD_HVR_1600_SAMSUNG
:
283 dvb
->fe
= dvb_attach(s5h1409_attach
,
284 &hauppauge_hvr1600_config
,
286 if (dvb
->fe
!= NULL
) {
287 dvb_attach(mxl5005s_attach
, dvb
->fe
,
289 &hauppauge_hvr1600_tuner
);
294 /* No Digital Tv Support */
298 if (dvb
->fe
== NULL
) {
299 CX18_ERR("frontend initialization failed\n");
303 ret
= dvb_register_frontend(&dvb
->dvb_adapter
, dvb
->fe
);
305 if (dvb
->fe
->ops
.release
)
306 dvb
->fe
->ops
.release(dvb
->fe
);