diff options
author | Uri Shkolnik <uris@siano-ms.com> | 2009-05-12 11:28:46 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-16 18:14:29 -0400 |
commit | 793786d19a35c59a9379cb75da5b5d6bd052820d (patch) | |
tree | 0f7384f23a77505630db3ba6a5ea4152ad76af13 /drivers/media/dvb/siano/smsdvb.c | |
parent | ba79bb2c381f01224786270d0914d46f31667cf0 (diff) |
V4L/DVB (11782): Siano: smsdvb - use 'push' status mechanism
This patch replace the old method of pulling the device status by
sending "get_statistics" request, to push mode. This make status update
much faster, and reduce various operation time (UHF scan now takes 15s
instead of 2m). In order to make the change the following modification
have been applied:
1) core header - update statistics headers.
2) dvb adapter - omit the statistics request, add handling of
status indications.
3) core 'onresponse' - re-route messages addressed to other adapter
to the dvb adapter.
Signed-off-by: Uri Shkolnik <uris@siano-ms.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/siano/smsdvb.c')
-rw-r--r-- | drivers/media/dvb/siano/smsdvb.c | 266 |
1 files changed, 154 insertions, 112 deletions
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 8fb283b85b6b..881f5c5778f7 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c | |||
@@ -40,12 +40,15 @@ struct smsdvb_client_t { | |||
40 | struct dvb_frontend frontend; | 40 | struct dvb_frontend frontend; |
41 | 41 | ||
42 | fe_status_t fe_status; | 42 | fe_status_t fe_status; |
43 | int fe_ber, fe_snr, fe_unc, fe_signal_strength; | ||
44 | 43 | ||
45 | struct completion tune_done, stat_done; | 44 | struct completion tune_done; |
46 | 45 | ||
47 | /* todo: save freq/band instead whole struct */ | 46 | /* todo: save freq/band instead whole struct */ |
48 | struct dvb_frontend_parameters fe_params; | 47 | struct dvb_frontend_parameters fe_params; |
48 | |||
49 | struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb; | ||
50 | int event_fe_state; | ||
51 | int event_unc_state; | ||
49 | }; | 52 | }; |
50 | 53 | ||
51 | static struct list_head g_smsdvb_clients; | 54 | static struct list_head g_smsdvb_clients; |
@@ -55,11 +58,19 @@ static int sms_dbg; | |||
55 | module_param_named(debug, sms_dbg, int, 0644); | 58 | module_param_named(debug, sms_dbg, int, 0644); |
56 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); | 59 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); |
57 | 60 | ||
61 | /* Events that may come from DVB v3 adapter */ | ||
62 | static void sms_board_dvb3_event(struct smsdvb_client_t *client, | ||
63 | enum SMS_DVB3_EVENTS event) { | ||
64 | } | ||
65 | |||
58 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | 66 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) |
59 | { | 67 | { |
60 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; | 68 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; |
61 | struct SmsMsgHdr_ST *phdr = | 69 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) |
62 | (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset); | 70 | + cb->offset); |
71 | u32 *pMsgData = (u32 *) phdr + 1; | ||
72 | /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ | ||
73 | bool is_status_update = false; | ||
63 | 74 | ||
64 | smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); | 75 | smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); |
65 | 76 | ||
@@ -73,43 +84,110 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | |||
73 | complete(&client->tune_done); | 84 | complete(&client->tune_done); |
74 | break; | 85 | break; |
75 | 86 | ||
76 | case MSG_SMS_GET_STATISTICS_RES: | 87 | case MSG_SMS_SIGNAL_DETECTED_IND: |
77 | { | 88 | sms_info("MSG_SMS_SIGNAL_DETECTED_IND"); |
78 | struct SmsMsgStatisticsInfo_ST *p = | 89 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = true; |
79 | (struct SmsMsgStatisticsInfo_ST *)(phdr + 1); | 90 | is_status_update = true; |
80 | 91 | break; | |
81 | if (p->Stat.IsDemodLocked) { | 92 | |
82 | client->fe_status = FE_HAS_SIGNAL | | 93 | case MSG_SMS_NO_SIGNAL_IND: |
83 | FE_HAS_CARRIER | | 94 | sms_info("MSG_SMS_NO_SIGNAL_IND"); |
84 | FE_HAS_VITERBI | | 95 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = false; |
85 | FE_HAS_SYNC | | 96 | is_status_update = true; |
86 | FE_HAS_LOCK; | 97 | break; |
87 | 98 | ||
88 | client->fe_snr = p->Stat.SNR; | 99 | case MSG_SMS_TRANSMISSION_IND: { |
89 | client->fe_ber = p->Stat.BER; | 100 | sms_info("MSG_SMS_TRANSMISSION_IND"); |
90 | client->fe_unc = p->Stat.BERErrorCount; | 101 | |
91 | 102 | pMsgData++; | |
92 | if (p->Stat.InBandPwr < -95) | 103 | memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData, |
93 | client->fe_signal_strength = 0; | 104 | sizeof(struct TRANSMISSION_STATISTICS_S)); |
94 | else if (p->Stat.InBandPwr > -29) | 105 | |
95 | client->fe_signal_strength = 100; | 106 | /* Mo need to correct guard interval |
96 | else | 107 | * (as opposed to old statistics message). |
97 | client->fe_signal_strength = | 108 | */ |
98 | (p->Stat.InBandPwr + 95) * 3 / 2; | 109 | CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData); |
110 | CORRECT_STAT_TRANSMISSON_MODE( | ||
111 | client->sms_stat_dvb.TransmissionData); | ||
112 | is_status_update = true; | ||
113 | break; | ||
114 | } | ||
115 | case MSG_SMS_HO_PER_SLICES_IND: { | ||
116 | struct RECEPTION_STATISTICS_S *pReceptionData = | ||
117 | &client->sms_stat_dvb.ReceptionData; | ||
118 | struct SRVM_SIGNAL_STATUS_S SignalStatusData; | ||
119 | |||
120 | /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/ | ||
121 | pMsgData++; | ||
122 | SignalStatusData.result = pMsgData[0]; | ||
123 | SignalStatusData.snr = pMsgData[1]; | ||
124 | SignalStatusData.inBandPower = (s32) pMsgData[2]; | ||
125 | SignalStatusData.tsPackets = pMsgData[3]; | ||
126 | SignalStatusData.etsPackets = pMsgData[4]; | ||
127 | SignalStatusData.constellation = pMsgData[5]; | ||
128 | SignalStatusData.hpCode = pMsgData[6]; | ||
129 | SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03; | ||
130 | SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03; | ||
131 | SignalStatusData.cellId = pMsgData[9] & 0xFFFF; | ||
132 | SignalStatusData.reason = pMsgData[10]; | ||
133 | SignalStatusData.requestId = pMsgData[11]; | ||
134 | pReceptionData->IsRfLocked = pMsgData[16]; | ||
135 | pReceptionData->IsDemodLocked = pMsgData[17]; | ||
136 | pReceptionData->ModemState = pMsgData[12]; | ||
137 | pReceptionData->SNR = pMsgData[1]; | ||
138 | pReceptionData->BER = pMsgData[13]; | ||
139 | pReceptionData->RSSI = pMsgData[14]; | ||
140 | CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); | ||
141 | |||
142 | pReceptionData->InBandPwr = (s32) pMsgData[2]; | ||
143 | pReceptionData->CarrierOffset = (s32) pMsgData[15]; | ||
144 | pReceptionData->TotalTSPackets = pMsgData[3]; | ||
145 | pReceptionData->ErrorTSPackets = pMsgData[4]; | ||
146 | |||
147 | /* TS PER */ | ||
148 | if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) | ||
149 | > 0) { | ||
150 | pReceptionData->TS_PER = (SignalStatusData.etsPackets | ||
151 | * 100) / (SignalStatusData.tsPackets | ||
152 | + SignalStatusData.etsPackets); | ||
99 | } else { | 153 | } else { |
100 | client->fe_status = 0; | 154 | pReceptionData->TS_PER = 0; |
101 | client->fe_snr = | ||
102 | client->fe_ber = | ||
103 | client->fe_unc = | ||
104 | client->fe_signal_strength = 0; | ||
105 | } | 155 | } |
106 | 156 | ||
107 | complete(&client->stat_done); | 157 | pReceptionData->BERBitCount = pMsgData[18]; |
108 | break; | 158 | pReceptionData->BERErrorCount = pMsgData[19]; |
109 | } } | ||
110 | 159 | ||
160 | pReceptionData->MRC_SNR = pMsgData[20]; | ||
161 | pReceptionData->MRC_InBandPwr = pMsgData[21]; | ||
162 | pReceptionData->MRC_RSSI = pMsgData[22]; | ||
163 | |||
164 | is_status_update = true; | ||
165 | break; | ||
166 | } | ||
167 | } | ||
111 | smscore_putbuffer(client->coredev, cb); | 168 | smscore_putbuffer(client->coredev, cb); |
112 | 169 | ||
170 | if (is_status_update) { | ||
171 | if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { | ||
172 | client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | ||
173 | | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
174 | sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); | ||
175 | if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets | ||
176 | == 0) | ||
177 | sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); | ||
178 | else | ||
179 | sms_board_dvb3_event(client, | ||
180 | DVB3_EVENT_UNC_ERR); | ||
181 | |||
182 | } else { | ||
183 | /*client->fe_status = | ||
184 | (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ? | ||
185 | 0 : FE_HAS_SIGNAL;*/ | ||
186 | client->fe_status = 0; | ||
187 | sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); | ||
188 | } | ||
189 | } | ||
190 | |||
113 | return 0; | 191 | return 0; |
114 | } | 192 | } |
115 | 193 | ||
@@ -194,83 +272,61 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, | |||
194 | 0 : -ETIME; | 272 | 0 : -ETIME; |
195 | } | 273 | } |
196 | 274 | ||
197 | static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) | ||
198 | { | ||
199 | struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, | ||
200 | DVBT_BDA_CONTROL_MSG_ID, | ||
201 | HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 }; | ||
202 | int ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
203 | &client->stat_done); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | if (client->fe_status & FE_HAS_LOCK) | ||
208 | sms_board_led_feedback(client->coredev, | ||
209 | (client->fe_unc == 0) ? | ||
210 | SMS_LED_HI : SMS_LED_LO); | ||
211 | else | ||
212 | sms_board_led_feedback(client->coredev, SMS_LED_OFF); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) | 275 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) |
217 | { | 276 | { |
218 | struct smsdvb_client_t *client = | 277 | struct smsdvb_client_t *client; |
219 | container_of(fe, struct smsdvb_client_t, frontend); | 278 | client = container_of(fe, struct smsdvb_client_t, frontend); |
220 | int rc = smsdvb_send_statistics_request(client); | ||
221 | 279 | ||
222 | if (!rc) | 280 | *stat = client->fe_status; |
223 | *stat = client->fe_status; | ||
224 | 281 | ||
225 | return rc; | 282 | return 0; |
226 | } | 283 | } |
227 | 284 | ||
228 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) | 285 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) |
229 | { | 286 | { |
230 | struct smsdvb_client_t *client = | 287 | struct smsdvb_client_t *client; |
231 | container_of(fe, struct smsdvb_client_t, frontend); | 288 | client = container_of(fe, struct smsdvb_client_t, frontend); |
232 | int rc = smsdvb_send_statistics_request(client); | ||
233 | 289 | ||
234 | if (!rc) | 290 | *ber = client->sms_stat_dvb.ReceptionData.BER; |
235 | *ber = client->fe_ber; | ||
236 | 291 | ||
237 | return rc; | 292 | return 0; |
238 | } | 293 | } |
239 | 294 | ||
240 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | 295 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) |
241 | { | 296 | { |
242 | struct smsdvb_client_t *client = | 297 | struct smsdvb_client_t *client; |
243 | container_of(fe, struct smsdvb_client_t, frontend); | 298 | client = container_of(fe, struct smsdvb_client_t, frontend); |
244 | int rc = smsdvb_send_statistics_request(client); | ||
245 | 299 | ||
246 | if (!rc) | 300 | if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) |
247 | *strength = client->fe_signal_strength; | 301 | *strength = 0; |
302 | else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) | ||
303 | *strength = 100; | ||
304 | else | ||
305 | *strength = | ||
306 | (client->sms_stat_dvb.ReceptionData.InBandPwr | ||
307 | + 95) * 3 / 2; | ||
248 | 308 | ||
249 | return rc; | 309 | return 0; |
250 | } | 310 | } |
251 | 311 | ||
252 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) | 312 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) |
253 | { | 313 | { |
254 | struct smsdvb_client_t *client = | 314 | struct smsdvb_client_t *client; |
255 | container_of(fe, struct smsdvb_client_t, frontend); | 315 | client = container_of(fe, struct smsdvb_client_t, frontend); |
256 | int rc = smsdvb_send_statistics_request(client); | ||
257 | 316 | ||
258 | if (!rc) | 317 | *snr = client->sms_stat_dvb.ReceptionData.SNR; |
259 | *snr = client->fe_snr; | ||
260 | 318 | ||
261 | return rc; | 319 | return 0; |
262 | } | 320 | } |
263 | 321 | ||
264 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | 322 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) |
265 | { | 323 | { |
266 | struct smsdvb_client_t *client = | 324 | struct smsdvb_client_t *client; |
267 | container_of(fe, struct smsdvb_client_t, frontend); | 325 | client = container_of(fe, struct smsdvb_client_t, frontend); |
268 | int rc = smsdvb_send_statistics_request(client); | ||
269 | 326 | ||
270 | if (!rc) | 327 | *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; |
271 | *ucblocks = client->fe_unc; | ||
272 | 328 | ||
273 | return rc; | 329 | return 0; |
274 | } | 330 | } |
275 | 331 | ||
276 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, | 332 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, |
@@ -294,12 +350,15 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, | |||
294 | struct SmsMsgHdr_ST Msg; | 350 | struct SmsMsgHdr_ST Msg; |
295 | u32 Data[3]; | 351 | u32 Data[3]; |
296 | } Msg; | 352 | } Msg; |
297 | int ret; | ||
298 | 353 | ||
299 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | 354 | client->fe_status = FE_HAS_SIGNAL; |
300 | Msg.Msg.msgDstId = HIF_TASK; | 355 | client->event_fe_state = -1; |
301 | Msg.Msg.msgFlags = 0; | 356 | client->event_unc_state = -1; |
302 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; | 357 | |
358 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
359 | Msg.Msg.msgDstId = HIF_TASK; | ||
360 | Msg.Msg.msgFlags = 0; | ||
361 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; | ||
303 | Msg.Msg.msgLength = sizeof(Msg); | 362 | Msg.Msg.msgLength = sizeof(Msg); |
304 | Msg.Data[0] = fep->frequency; | 363 | Msg.Data[0] = fep->frequency; |
305 | Msg.Data[2] = 12000000; | 364 | Msg.Data[2] = 12000000; |
@@ -315,24 +374,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, | |||
315 | default: return -EINVAL; | 374 | default: return -EINVAL; |
316 | } | 375 | } |
317 | 376 | ||
318 | /* Disable LNA, if any. An error is returned if no LNA is present */ | ||
319 | ret = sms_board_lna_control(client->coredev, 0); | ||
320 | if (ret == 0) { | ||
321 | fe_status_t status; | ||
322 | |||
323 | /* tune with LNA off at first */ | ||
324 | ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
325 | &client->tune_done); | ||
326 | |||
327 | smsdvb_read_status(fe, &status); | ||
328 | |||
329 | if (status & FE_HAS_LOCK) | ||
330 | return ret; | ||
331 | |||
332 | /* previous tune didnt lock - enable LNA and tune again */ | ||
333 | sms_board_lna_control(client->coredev, 1); | ||
334 | } | ||
335 | |||
336 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | 377 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), |
337 | &client->tune_done); | 378 | &client->tune_done); |
338 | } | 379 | } |
@@ -357,8 +398,7 @@ static int smsdvb_init(struct dvb_frontend *fe) | |||
357 | struct smsdvb_client_t *client = | 398 | struct smsdvb_client_t *client = |
358 | container_of(fe, struct smsdvb_client_t, frontend); | 399 | container_of(fe, struct smsdvb_client_t, frontend); |
359 | 400 | ||
360 | sms_board_power(client->coredev, 1); | 401 | sms_board_dvb3_event(client, DVB3_EVENT_INIT); |
361 | |||
362 | return 0; | 402 | return 0; |
363 | } | 403 | } |
364 | 404 | ||
@@ -367,8 +407,7 @@ static int smsdvb_sleep(struct dvb_frontend *fe) | |||
367 | struct smsdvb_client_t *client = | 407 | struct smsdvb_client_t *client = |
368 | container_of(fe, struct smsdvb_client_t, frontend); | 408 | container_of(fe, struct smsdvb_client_t, frontend); |
369 | 409 | ||
370 | sms_board_led_feedback(client->coredev, SMS_LED_OFF); | 410 | sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); |
371 | sms_board_power(client->coredev, 0); | ||
372 | 411 | ||
373 | return 0; | 412 | return 0; |
374 | } | 413 | } |
@@ -500,8 +539,11 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, | |||
500 | 539 | ||
501 | kmutex_unlock(&g_smsdvb_clientslock); | 540 | kmutex_unlock(&g_smsdvb_clientslock); |
502 | 541 | ||
503 | sms_info("success"); | 542 | client->event_fe_state = -1; |
543 | client->event_unc_state = -1; | ||
544 | sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); | ||
504 | 545 | ||
546 | sms_info("success"); | ||
505 | sms_board_setup(coredev); | 547 | sms_board_setup(coredev); |
506 | 548 | ||
507 | return 0; | 549 | return 0; |