V4L/DVB (8267): sms1xxx: Makefile cleanup
[deliverable/linux.git] / drivers / media / mdtv / smsdvb.c
CommitLineData
2e5c1ec8
MK
1#include <linux/module.h>
2#include <linux/init.h>
3
2e5c1ec8 4#include "smscoreapi.h"
2e5c1ec8 5
9c59f968
MK
6DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
7
2e5c1ec8
MK
8struct list_head g_smsdvb_clients;
9kmutex_t g_smsdvb_clientslock;
10
11int smsdvb_onresponse(void *context, smscore_buffer_t *cb)
12{
13 smsdvb_client_t *client = (smsdvb_client_t *) context;
14 SmsMsgHdr_ST *phdr = (SmsMsgHdr_ST *)(((u8*) cb->p) + cb->offset);
15
16 switch(phdr->msgType)
17 {
18 case MSG_SMS_DVBT_BDA_DATA:
19 dvb_dmx_swfilter(&client->demux, (u8*)(phdr + 1), cb->size - sizeof(SmsMsgHdr_ST));
20 break;
21
22 case MSG_SMS_RF_TUNE_RES:
23 complete(&client->tune_done);
24 break;
25
26 case MSG_SMS_GET_STATISTICS_RES:
27 {
28 SmsMsgStatisticsInfo_ST* p = (SmsMsgStatisticsInfo_ST*)(phdr + 1);
29
30 if (p->Stat.IsDemodLocked)
31 {
32 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
33 client->fe_snr = p->Stat.SNR;
34 client->fe_ber = p->Stat.BER;
35
36 if (p->Stat.InBandPwr < -95)
37 client->fe_signal_strength = 0;
38 else if (p->Stat.InBandPwr > -29)
39 client->fe_signal_strength = 100;
40 else
41 client->fe_signal_strength = (p->Stat.InBandPwr + 95) * 3 / 2;
42 }
43 else
44 {
45 client->fe_status = 0;
46 client->fe_snr =
47 client->fe_ber =
48 client->fe_signal_strength = 0;
49 }
50
51 complete(&client->stat_done);
52 break;
53 }
54 }
55
56 smscore_putbuffer(client->coredev, cb);
57
58 return 0;
59}
60
61void smsdvb_unregister_client(smsdvb_client_t* client)
62{
63 // must be called under clientslock
64
65 list_del(&client->entry);
66
67 smscore_unregister_client(client->smsclient);
68 dvb_unregister_frontend(&client->frontend);
69 dvb_dmxdev_release(&client->dmxdev);
70 dvb_dmx_release(&client->demux);
71 dvb_unregister_adapter(&client->adapter);
72 kfree(client);
73}
74
75void smsdvb_onremove(void *context)
76{
77 kmutex_lock(&g_smsdvb_clientslock);
78
79 smsdvb_unregister_client((smsdvb_client_t*) context);
80
81 kmutex_unlock(&g_smsdvb_clientslock);
82}
83
84static int smsdvb_start_feed(struct dvb_demux_feed *feed)
85{
86 smsdvb_client_t *client = container_of(feed->demux, smsdvb_client_t, demux);
87 SmsMsgData_ST PidMsg;
88
89 printk("%s add pid %d(%x)\n", __FUNCTION__, feed->pid, feed->pid);
90
91 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
92 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
93 PidMsg.xMsgHeader.msgFlags = 0;
94 PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
95 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
96 PidMsg.msgData[0] = feed->pid;
97
98 return smsclient_sendrequest(client->smsclient, &PidMsg, sizeof(PidMsg));
99}
100
101static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
102{
103 smsdvb_client_t *client = container_of(feed->demux, smsdvb_client_t, demux);
104 SmsMsgData_ST PidMsg;
105
106 printk("%s remove pid %d(%x)\n", __FUNCTION__, feed->pid, feed->pid);
107
108 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
109 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
110 PidMsg.xMsgHeader.msgFlags = 0;
111 PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
112 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
113 PidMsg.msgData[0] = feed->pid;
114
115 return smsclient_sendrequest(client->smsclient, &PidMsg, sizeof(PidMsg));
116}
117
118static int smsdvb_sendrequest_and_wait(smsdvb_client_t *client, void* buffer, size_t size, struct completion *completion)
119{
120 int rc = smsclient_sendrequest(client->smsclient, buffer, size);
121 if (rc < 0)
122 return rc;
123
124 return wait_for_completion_timeout(completion, msecs_to_jiffies(2000)) ? 0 : -ETIME;
125}
126
127static int smsdvb_send_statistics_request(smsdvb_client_t *client)
128{
129 SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, DVBT_BDA_CONTROL_MSG_ID, HIF_TASK, sizeof(SmsMsgHdr_ST), 0 };
130 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->stat_done);
131}
132
133static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
134{
135 smsdvb_client_t *client = container_of(fe, smsdvb_client_t, frontend);
136 int rc = smsdvb_send_statistics_request(client);
137
138 if (!rc)
139 *stat = client->fe_status;
140
141 return rc;
142}
143
144static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
145{
146 smsdvb_client_t *client = container_of(fe, smsdvb_client_t, frontend);
147 int rc = smsdvb_send_statistics_request(client);
148
149 if (!rc)
150 *ber = client->fe_ber;
151
152 return rc;
153}
154
155static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
156{
157 smsdvb_client_t *client = container_of(fe, smsdvb_client_t, frontend);
158 int rc = smsdvb_send_statistics_request(client);
159
160 if (!rc)
161 *strength = client->fe_signal_strength;
162
163 return rc;
164}
165
166static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
167{
168 smsdvb_client_t *client = container_of(fe, smsdvb_client_t, frontend);
169 int rc = smsdvb_send_statistics_request(client);
170
171 if (!rc)
172 *snr = client->fe_snr;
173
174 return rc;
175}
176
177static int smsdvb_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
178{
179 printk("%s\n", __FUNCTION__);
180
181 tune->min_delay_ms = 400;
182 tune->step_size = 250000;
183 tune->max_drift = 0;
184 return 0;
185}
186
187static int smsdvb_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
188{
189 smsdvb_client_t *client = container_of(fe, smsdvb_client_t, frontend);
190
191 struct
192 {
193 SmsMsgHdr_ST Msg;
194 u32 Data[3];
195 } Msg;
196
197 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
198 Msg.Msg.msgDstId = HIF_TASK;
199 Msg.Msg.msgFlags = 0;
200 Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
201 Msg.Msg.msgLength = sizeof(Msg);
202 Msg.Data[0] = fep->frequency;
203 Msg.Data[2] = 12000000;
204
205 printk("%s freq %d band %d\n", __FUNCTION__, fep->frequency, fep->u.ofdm.bandwidth);
206
207 switch(fep->u.ofdm.bandwidth)
208 {
209 case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break;
210 case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break;
211 case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break;
212// case BANDWIDTH_5_MHZ: Msg.Data[1] = BW_5_MHZ; break;
213 case BANDWIDTH_AUTO: return -EOPNOTSUPP;
214 default: return -EINVAL;
215 }
216
217 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done);
218}
219
220static int smsdvb_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
221{
222 smsdvb_client_t *client = container_of(fe, smsdvb_client_t, frontend);
223
224 printk("%s\n", __FUNCTION__);
225
226 // todo:
227 memcpy(fep, &client->fe_params, sizeof(struct dvb_frontend_parameters));
228 return 0;
229}
230
231static void smsdvb_release(struct dvb_frontend *fe)
232{
233 // do nothing
234}
235
236static struct dvb_frontend_ops smsdvb_fe_ops = {
237 .info = {
238 .name = "Siano Mobile Digital SMS10xx",
239 .type = FE_OFDM,
240 .frequency_min = 44250000,
241 .frequency_max = 867250000,
242 .frequency_stepsize = 250000,
243 .caps = FE_CAN_INVERSION_AUTO |
244 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
245 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
246 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
247 FE_CAN_TRANSMISSION_MODE_AUTO |
248 FE_CAN_GUARD_INTERVAL_AUTO |
249 FE_CAN_RECOVER |
250 FE_CAN_HIERARCHY_AUTO,
251 },
252
253 .release = smsdvb_release,
254
255 .set_frontend = smsdvb_set_frontend,
256 .get_frontend = smsdvb_get_frontend,
257 .get_tune_settings = smsdvb_get_tune_settings,
258
259 .read_status = smsdvb_read_status,
260 .read_ber = smsdvb_read_ber,
261 .read_signal_strength = smsdvb_read_signal_strength,
262 .read_snr = smsdvb_read_snr,
263};
264
265int smsdvb_hotplug(smscore_device_t *coredev, struct device* device, int arrival)
266{
267 smsclient_params_t params;
268 smsdvb_client_t* client;
269 int rc;
270
271 // device removal handled by onremove callback
272 if (!arrival)
273 return 0;
274
275 if (smscore_get_device_mode(coredev) != 4)
276 {
277 rc = smscore_set_device_mode(coredev, 4);
278 if (rc < 0)
279 return rc;
280 }
281
282 client = kzalloc(sizeof(smsdvb_client_t), GFP_KERNEL);
283 if (!client)
284 {
285 printk(KERN_INFO "%s kmalloc() failed\n", __FUNCTION__);
286 return -ENOMEM;
287 }
288
289 // register dvb adapter
9c59f968 290 rc = dvb_register_adapter(&client->adapter, "Siano Digital Receiver", THIS_MODULE, device, adapter_nr);
2e5c1ec8
MK
291 if (rc < 0)
292 {
293 printk("%s dvb_register_adapter() failed %d\n", __func__, rc);
294 goto adapter_error;
295 }
296
297 // init dvb demux
298 client->demux.dmx.capabilities = DMX_TS_FILTERING;
299 client->demux.filternum = 32; // todo: nova ???
300 client->demux.feednum = 32;
301 client->demux.start_feed = smsdvb_start_feed;
302 client->demux.stop_feed = smsdvb_stop_feed;
303
304 rc = dvb_dmx_init(&client->demux);
305 if (rc < 0)
306 {
307 printk("%s dvb_dmx_init failed %d\n\n", __FUNCTION__, rc);
308 goto dvbdmx_error;
309 }
310
311 // init dmxdev
312 client->dmxdev.filternum = 32;
313 client->dmxdev.demux = &client->demux.dmx;
314 client->dmxdev.capabilities = 0;
315
316 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
317 if (rc < 0)
318 {
319 printk("%s dvb_dmxdev_init failed %d\n", __FUNCTION__, rc);
320 goto dmxdev_error;
321 }
322
323 // init and register frontend
324 memcpy(&client->frontend.ops, &smsdvb_fe_ops, sizeof(struct dvb_frontend_ops));
325
326 rc = dvb_register_frontend(&client->adapter, &client->frontend);
327 if (rc < 0)
328 {
329 printk("%s frontend registration failed %d\n", __FUNCTION__, rc);
330 goto frontend_error;
331 }
332
333 params.initial_id = 0;
334 params.data_type = MSG_SMS_DVBT_BDA_DATA;
335 params.onresponse_handler = smsdvb_onresponse;
336 params.onremove_handler = smsdvb_onremove;
337 params.context = client;
338
339 rc = smscore_register_client(coredev, &params, &client->smsclient);
340 if (rc < 0)
341 {
342 printk(KERN_INFO "%s smscore_register_client() failed %d\n", __FUNCTION__, rc);
343 goto client_error;
344 }
345
346 client->coredev = coredev;
347
348 init_completion(&client->tune_done);
349 init_completion(&client->stat_done);
350
351 kmutex_lock(&g_smsdvb_clientslock);
352
353 list_add(&client->entry, &g_smsdvb_clients);
354
355 kmutex_unlock(&g_smsdvb_clientslock);
356
357 printk(KERN_INFO "%s success\n", __FUNCTION__);
358
359 return 0;
360
361client_error:
362 dvb_unregister_frontend(&client->frontend);
363
364frontend_error:
365 dvb_dmxdev_release(&client->dmxdev);
366
367dmxdev_error:
368 dvb_dmx_release(&client->demux);
369
370dvbdmx_error:
371 dvb_unregister_adapter(&client->adapter);
372
373adapter_error:
374 kfree(client);
375 return rc;
376}
377
This page took 0.054521 seconds and 5 git commands to generate.