x86/mm/pat: Don't report PAT on CPUs that don't support it
[linux/fpc-iii.git] / drivers / media / platform / sti / c8sectpfe / c8sectpfe-common.c
blob2dfbe8ab521435cc0d54915feb40e012ed2d8caf
1 /*
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>
20 #include <linux/io.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>
27 #include "dmxdev.h"
28 #include "dvbdev.h"
29 #include "dvb_demux.h"
30 #include "dvb_frontend.h"
31 #include "dvb_net.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)
41 int result;
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);
56 if (result < 0) {
57 dev_err(fei->dev, "dvb_dmx_init failed (errno = %d)\n",
58 result);
59 goto err_dmx;
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);
67 if (result < 0) {
68 dev_err(fei->dev, "dvb_dmxdev_init failed (errno = %d)\n",
69 result);
71 goto err_dmxdev;
74 demux->hw_frontend.source = DMX_FRONTEND_0 + demux->tsin_index;
76 result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx,
77 &demux->hw_frontend);
78 if (result < 0) {
79 dev_err(fei->dev, "add_frontend failed (errno = %d)\n", result);
80 goto err_fe_hw;
83 demux->mem_frontend.source = DMX_MEMORY_FE;
84 result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx,
85 &demux->mem_frontend);
86 if (result < 0) {
87 dev_err(fei->dev, "add_frontend failed (%d)\n", result);
88 goto err_fe_mem;
91 result = demux->dvb_demux.dmx.connect_frontend(&demux->dvb_demux.dmx,
92 &demux->hw_frontend);
93 if (result < 0) {
94 dev_err(fei->dev, "connect_frontend (%d)\n", result);
95 goto err_fe_con;
98 return 0;
100 err_fe_con:
101 demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
102 &demux->mem_frontend);
103 err_fe_mem:
104 demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
105 &demux->hw_frontend);
106 err_fe_hw:
107 dvb_dmxdev_release(&demux->dmxdev);
108 err_dmxdev:
109 dvb_dmx_release(&demux->dvb_demux);
110 err_dmx:
111 return result;
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,
130 void *start_feed,
131 void *stop_feed)
133 struct c8sectpfe *c8sectpfe;
134 int result;
135 int i, j;
137 short int ids[] = { -1 };
139 c8sectpfe = kzalloc(sizeof(struct c8sectpfe), GFP_KERNEL);
140 if (!c8sectpfe)
141 goto err1;
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);
149 if (result < 0) {
150 dev_err(fei->dev, "dvb_register_adapter failed (errno = %d)\n",
151 result);
152 goto err2;
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);
164 if (result < 0) {
165 dev_err(fei->dev,
166 "register_dvb feed=%d failed (errno = %d)\n",
167 result, i);
169 /* we take a all or nothing approach */
170 for (j = 0; j < i; j++)
171 unregister_dvb(&c8sectpfe->demux[j]);
172 goto err3;
176 c8sectpfe->num_feeds = fei->tsin_count;
178 return c8sectpfe;
179 err3:
180 dvb_unregister_adapter(&c8sectpfe->adapter);
181 err2:
182 kfree(c8sectpfe);
183 err1:
184 return NULL;
187 static void c8sectpfe_delete(struct c8sectpfe *c8sectpfe)
189 int i;
191 if (!c8sectpfe)
192 return;
194 for (i = 0; i < c8sectpfe->num_feeds; i++)
195 unregister_dvb(&c8sectpfe->demux[i]);
197 dvb_unregister_adapter(&c8sectpfe->adapter);
199 kfree(c8sectpfe);
202 void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe *c8sectpfe,
203 struct c8sectpfei *fei)
205 int n;
206 struct channel_info *tsin;
208 for (n = 0; n < fei->tsin_count; n++) {
210 tsin = fei->channel_data[n];
212 if (tsin) {
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,
232 void *start_feed,
233 void *stop_feed)
235 struct channel_info *tsin;
236 struct dvb_frontend *frontend;
237 int n, res;
239 *c8sectpfe = c8sectpfe_create(fei, start_feed, stop_feed);
240 if (!*c8sectpfe)
241 return -ENOMEM;
243 for (n = 0; n < fei->tsin_count; n++) {
244 tsin = fei->channel_data[n];
246 res = c8sectpfe_frontend_attach(&frontend, *c8sectpfe, tsin, n);
247 if (res)
248 goto err;
250 res = dvb_register_frontend(&c8sectpfe[0]->adapter, frontend);
251 if (res < 0) {
252 dev_err(fei->dev, "dvb_register_frontend failed (%d)\n",
253 res);
254 goto err;
257 tsin->frontend = frontend;
260 return 0;
262 err:
263 c8sectpfe_tuner_unregister_frontend(*c8sectpfe, fei);
264 return res;