2 * c8sectpfe-common.c - C8SECTPFE STi DVB driver
4 * Copyright (c) STMicroelectronics 2015
6 * Author: Peter Griffin <peter.griffin@linaro.org>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 #include <linux/completion.h>
14 #include <linux/delay.h>
15 #include <linux/device.h>
16 #include <linux/dvb/dmx.h>
17 #include <linux/errno.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
21 #include <linux/ioport.h>
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/time.h>
25 #include <linux/wait.h>
29 #include "dvb_demux.h"
30 #include "dvb_frontend.h"
33 #include "c8sectpfe-common.h"
34 #include "c8sectpfe-core.h"
35 #include "c8sectpfe-dvb.h"
37 static int register_dvb(struct stdemux
*demux
, struct dvb_adapter
*adap
,
38 void *start_feed
, void *stop_feed
,
39 struct c8sectpfei
*fei
)
43 demux
->dvb_demux
.dmx
.capabilities
= DMX_TS_FILTERING
|
44 DMX_SECTION_FILTERING
|
45 DMX_MEMORY_BASED_FILTERING
;
47 demux
->dvb_demux
.priv
= demux
;
48 demux
->dvb_demux
.filternum
= C8SECTPFE_MAXCHANNEL
;
49 demux
->dvb_demux
.feednum
= C8SECTPFE_MAXCHANNEL
;
51 demux
->dvb_demux
.start_feed
= start_feed
;
52 demux
->dvb_demux
.stop_feed
= stop_feed
;
53 demux
->dvb_demux
.write_to_decoder
= NULL
;
55 result
= dvb_dmx_init(&demux
->dvb_demux
);
57 dev_err(fei
->dev
, "dvb_dmx_init failed (errno = %d)\n",
62 demux
->dmxdev
.filternum
= demux
->dvb_demux
.filternum
;
63 demux
->dmxdev
.demux
= &demux
->dvb_demux
.dmx
;
64 demux
->dmxdev
.capabilities
= 0;
66 result
= dvb_dmxdev_init(&demux
->dmxdev
, adap
);
68 dev_err(fei
->dev
, "dvb_dmxdev_init failed (errno = %d)\n",
74 demux
->hw_frontend
.source
= DMX_FRONTEND_0
+ demux
->tsin_index
;
76 result
= demux
->dvb_demux
.dmx
.add_frontend(&demux
->dvb_demux
.dmx
,
79 dev_err(fei
->dev
, "add_frontend failed (errno = %d)\n", result
);
83 demux
->mem_frontend
.source
= DMX_MEMORY_FE
;
84 result
= demux
->dvb_demux
.dmx
.add_frontend(&demux
->dvb_demux
.dmx
,
85 &demux
->mem_frontend
);
87 dev_err(fei
->dev
, "add_frontend failed (%d)\n", result
);
91 result
= demux
->dvb_demux
.dmx
.connect_frontend(&demux
->dvb_demux
.dmx
,
94 dev_err(fei
->dev
, "connect_frontend (%d)\n", result
);
101 demux
->dvb_demux
.dmx
.remove_frontend(&demux
->dvb_demux
.dmx
,
102 &demux
->mem_frontend
);
104 demux
->dvb_demux
.dmx
.remove_frontend(&demux
->dvb_demux
.dmx
,
105 &demux
->hw_frontend
);
107 dvb_dmxdev_release(&demux
->dmxdev
);
109 dvb_dmx_release(&demux
->dvb_demux
);
115 static void unregister_dvb(struct stdemux
*demux
)
118 demux
->dvb_demux
.dmx
.remove_frontend(&demux
->dvb_demux
.dmx
,
119 &demux
->mem_frontend
);
121 demux
->dvb_demux
.dmx
.remove_frontend(&demux
->dvb_demux
.dmx
,
122 &demux
->hw_frontend
);
124 dvb_dmxdev_release(&demux
->dmxdev
);
126 dvb_dmx_release(&demux
->dvb_demux
);
129 static struct c8sectpfe
*c8sectpfe_create(struct c8sectpfei
*fei
,
133 struct c8sectpfe
*c8sectpfe
;
137 short int ids
[] = { -1 };
139 c8sectpfe
= kzalloc(sizeof(struct c8sectpfe
), GFP_KERNEL
);
143 mutex_init(&c8sectpfe
->lock
);
145 c8sectpfe
->device
= fei
->dev
;
147 result
= dvb_register_adapter(&c8sectpfe
->adapter
, "STi c8sectpfe",
148 THIS_MODULE
, fei
->dev
, ids
);
150 dev_err(fei
->dev
, "dvb_register_adapter failed (errno = %d)\n",
155 c8sectpfe
->adapter
.priv
= fei
;
157 for (i
= 0; i
< fei
->tsin_count
; i
++) {
159 c8sectpfe
->demux
[i
].tsin_index
= i
;
160 c8sectpfe
->demux
[i
].c8sectpfei
= fei
;
162 result
= register_dvb(&c8sectpfe
->demux
[i
], &c8sectpfe
->adapter
,
163 start_feed
, stop_feed
, fei
);
166 "register_dvb feed=%d failed (errno = %d)\n",
169 /* we take a all or nothing approach */
170 for (j
= 0; j
< i
; j
++)
171 unregister_dvb(&c8sectpfe
->demux
[j
]);
176 c8sectpfe
->num_feeds
= fei
->tsin_count
;
180 dvb_unregister_adapter(&c8sectpfe
->adapter
);
187 static void c8sectpfe_delete(struct c8sectpfe
*c8sectpfe
)
194 for (i
= 0; i
< c8sectpfe
->num_feeds
; i
++)
195 unregister_dvb(&c8sectpfe
->demux
[i
]);
197 dvb_unregister_adapter(&c8sectpfe
->adapter
);
202 void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe
*c8sectpfe
,
203 struct c8sectpfei
*fei
)
206 struct channel_info
*tsin
;
208 for (n
= 0; n
< fei
->tsin_count
; n
++) {
210 tsin
= fei
->channel_data
[n
];
213 if (tsin
->frontend
) {
214 dvb_unregister_frontend(tsin
->frontend
);
215 dvb_frontend_detach(tsin
->frontend
);
218 i2c_put_adapter(tsin
->i2c_adapter
);
220 if (tsin
->i2c_client
) {
221 module_put(tsin
->i2c_client
->dev
.driver
->owner
);
222 i2c_unregister_device(tsin
->i2c_client
);
227 c8sectpfe_delete(c8sectpfe
);
230 int c8sectpfe_tuner_register_frontend(struct c8sectpfe
**c8sectpfe
,
231 struct c8sectpfei
*fei
,
235 struct channel_info
*tsin
;
236 struct dvb_frontend
*frontend
;
239 *c8sectpfe
= c8sectpfe_create(fei
, start_feed
, stop_feed
);
243 for (n
= 0; n
< fei
->tsin_count
; n
++) {
244 tsin
= fei
->channel_data
[n
];
246 res
= c8sectpfe_frontend_attach(&frontend
, *c8sectpfe
, tsin
, n
);
250 res
= dvb_register_frontend(&c8sectpfe
[0]->adapter
, frontend
);
252 dev_err(fei
->dev
, "dvb_register_frontend failed (%d)\n",
257 tsin
->frontend
= frontend
;
263 c8sectpfe_tuner_unregister_frontend(*c8sectpfe
, fei
);