~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/staging/crystalhd/crystalhd_cmds.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 * Copyright (c) 2005-2009, Broadcom Corporation.
 
3
 *
 
4
 *  Name: crystalhd_cmds . c
 
5
 *
 
6
 *  Description:
 
7
 *              BCM70010 Linux driver user command interfaces.
 
8
 *
 
9
 *  HISTORY:
 
10
 *
 
11
 **********************************************************************
 
12
 * This file is part of the crystalhd device driver.
 
13
 *
 
14
 * This driver is free software; you can redistribute it and/or modify
 
15
 * it under the terms of the GNU General Public License as published by
 
16
 * the Free Software Foundation, version 2 of the License.
 
17
 *
 
18
 * This driver is distributed in the hope that it will be useful,
 
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 * GNU General Public License for more details.
 
22
 *
 
23
 * You should have received a copy of the GNU General Public License
 
24
 * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
 
25
 **********************************************************************/
 
26
 
 
27
#include "crystalhd_cmds.h"
 
28
#include "crystalhd_hw.h"
 
29
 
 
30
static struct crystalhd_user *bc_cproc_get_uid(struct crystalhd_cmd *ctx)
 
31
{
 
32
        struct crystalhd_user *user = NULL;
 
33
        int i;
 
34
 
 
35
        for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
 
36
                if (!ctx->user[i].in_use) {
 
37
                        user = &ctx->user[i];
 
38
                        break;
 
39
                }
 
40
        }
 
41
 
 
42
        return user;
 
43
}
 
44
 
 
45
static int bc_cproc_get_user_count(struct crystalhd_cmd *ctx)
 
46
{
 
47
        int i, count = 0;
 
48
 
 
49
        for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
 
50
                if (ctx->user[i].in_use)
 
51
                        count++;
 
52
        }
 
53
 
 
54
        return count;
 
55
}
 
56
 
 
57
static void bc_cproc_mark_pwr_state(struct crystalhd_cmd *ctx)
 
58
{
 
59
        int i;
 
60
 
 
61
        for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
 
62
                if (!ctx->user[i].in_use)
 
63
                        continue;
 
64
                if (ctx->user[i].mode == DTS_DIAG_MODE ||
 
65
                    ctx->user[i].mode == DTS_PLAYBACK_MODE) {
 
66
                        ctx->pwr_state_change = 1;
 
67
                        break;
 
68
                }
 
69
        }
 
70
}
 
71
 
 
72
static enum BC_STATUS bc_cproc_notify_mode(struct crystalhd_cmd *ctx,
 
73
                                      struct crystalhd_ioctl_data *idata)
 
74
{
 
75
        int rc = 0, i = 0;
 
76
 
 
77
        if (!ctx || !idata) {
 
78
                BCMLOG_ERR("Invalid Arg!!\n");
 
79
                return BC_STS_INV_ARG;
 
80
        }
 
81
 
 
82
        if (ctx->user[idata->u_id].mode != DTS_MODE_INV) {
 
83
                BCMLOG_ERR("Close the handle first..\n");
 
84
                return BC_STS_ERR_USAGE;
 
85
        }
 
86
        if (idata->udata.u.NotifyMode.Mode == DTS_MONITOR_MODE) {
 
87
                ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
 
88
                return BC_STS_SUCCESS;
 
89
        }
 
90
        if (ctx->state != BC_LINK_INVALID) {
 
91
                BCMLOG_ERR("Link invalid state %d\n", ctx->state);
 
92
                return BC_STS_ERR_USAGE;
 
93
        }
 
94
        /* Check for duplicate playback sessions..*/
 
95
        for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
 
96
                if (ctx->user[i].mode == DTS_DIAG_MODE ||
 
97
                    ctx->user[i].mode == DTS_PLAYBACK_MODE) {
 
98
                        BCMLOG_ERR("multiple playback sessions are not "
 
99
                                   "supported..\n");
 
100
                        return BC_STS_ERR_USAGE;
 
101
                }
 
102
        }
 
103
        ctx->cin_wait_exit = 0;
 
104
        ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
 
105
        /* Setup mmap pool for uaddr sgl mapping..*/
 
106
        rc = crystalhd_create_dio_pool(ctx->adp, BC_LINK_MAX_SGLS);
 
107
        if (rc)
 
108
                return BC_STS_ERROR;
 
109
 
 
110
        /* Setup Hardware DMA rings */
 
111
        return crystalhd_hw_setup_dma_rings(&ctx->hw_ctx);
 
112
}
 
113
 
 
114
static enum BC_STATUS bc_cproc_get_version(struct crystalhd_cmd *ctx,
 
115
                                      struct crystalhd_ioctl_data *idata)
 
116
{
 
117
 
 
118
        if (!ctx || !idata) {
 
119
                BCMLOG_ERR("Invalid Arg!!\n");
 
120
                return BC_STS_INV_ARG;
 
121
        }
 
122
        idata->udata.u.VerInfo.DriverMajor = crystalhd_kmod_major;
 
123
        idata->udata.u.VerInfo.DriverMinor = crystalhd_kmod_minor;
 
124
        idata->udata.u.VerInfo.DriverRevision   = crystalhd_kmod_rev;
 
125
        return BC_STS_SUCCESS;
 
126
}
 
127
 
 
128
 
 
129
static enum BC_STATUS bc_cproc_get_hwtype(struct crystalhd_cmd *ctx,
 
130
                                        struct crystalhd_ioctl_data *idata)
 
131
{
 
132
        if (!ctx || !idata) {
 
133
                BCMLOG_ERR("Invalid Arg!!\n");
 
134
                return BC_STS_INV_ARG;
 
135
        }
 
136
 
 
137
        crystalhd_pci_cfg_rd(ctx->adp, 0, 2,
 
138
                           (uint32_t *)&idata->udata.u.hwType.PciVenId);
 
139
        crystalhd_pci_cfg_rd(ctx->adp, 2, 2,
 
140
                           (uint32_t *)&idata->udata.u.hwType.PciDevId);
 
141
        crystalhd_pci_cfg_rd(ctx->adp, 8, 1,
 
142
                           (uint32_t *)&idata->udata.u.hwType.HwRev);
 
143
 
 
144
        return BC_STS_SUCCESS;
 
145
}
 
146
 
 
147
static enum BC_STATUS bc_cproc_reg_rd(struct crystalhd_cmd *ctx,
 
148
                                 struct crystalhd_ioctl_data *idata)
 
149
{
 
150
        if (!ctx || !idata)
 
151
                return BC_STS_INV_ARG;
 
152
        idata->udata.u.regAcc.Value = bc_dec_reg_rd(ctx->adp,
 
153
                                        idata->udata.u.regAcc.Offset);
 
154
        return BC_STS_SUCCESS;
 
155
}
 
156
 
 
157
static enum BC_STATUS bc_cproc_reg_wr(struct crystalhd_cmd *ctx,
 
158
                                 struct crystalhd_ioctl_data *idata)
 
159
{
 
160
        if (!ctx || !idata)
 
161
                return BC_STS_INV_ARG;
 
162
 
 
163
        bc_dec_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
 
164
                      idata->udata.u.regAcc.Value);
 
165
 
 
166
        return BC_STS_SUCCESS;
 
167
}
 
168
 
 
169
static enum BC_STATUS bc_cproc_link_reg_rd(struct crystalhd_cmd *ctx,
 
170
                                      struct crystalhd_ioctl_data *idata)
 
171
{
 
172
        if (!ctx || !idata)
 
173
                return BC_STS_INV_ARG;
 
174
 
 
175
        idata->udata.u.regAcc.Value = crystalhd_reg_rd(ctx->adp,
 
176
                                        idata->udata.u.regAcc.Offset);
 
177
        return BC_STS_SUCCESS;
 
178
}
 
179
 
 
180
static enum BC_STATUS bc_cproc_link_reg_wr(struct crystalhd_cmd *ctx,
 
181
                                      struct crystalhd_ioctl_data *idata)
 
182
{
 
183
        if (!ctx || !idata)
 
184
                return BC_STS_INV_ARG;
 
185
 
 
186
        crystalhd_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
 
187
                       idata->udata.u.regAcc.Value);
 
188
 
 
189
        return BC_STS_SUCCESS;
 
190
}
 
191
 
 
192
static enum BC_STATUS bc_cproc_mem_rd(struct crystalhd_cmd *ctx,
 
193
                                 struct crystalhd_ioctl_data *idata)
 
194
{
 
195
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
196
 
 
197
        if (!ctx || !idata || !idata->add_cdata)
 
198
                return BC_STS_INV_ARG;
 
199
 
 
200
        if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
 
201
                BCMLOG_ERR("insufficient buffer\n");
 
202
                return BC_STS_INV_ARG;
 
203
        }
 
204
        sts = crystalhd_mem_rd(ctx->adp, idata->udata.u.devMem.StartOff,
 
205
                             idata->udata.u.devMem.NumDwords,
 
206
                             (uint32_t *)idata->add_cdata);
 
207
        return sts;
 
208
 
 
209
}
 
210
 
 
211
static enum BC_STATUS bc_cproc_mem_wr(struct crystalhd_cmd *ctx,
 
212
                                 struct crystalhd_ioctl_data *idata)
 
213
{
 
214
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
215
 
 
216
        if (!ctx || !idata || !idata->add_cdata)
 
217
                return BC_STS_INV_ARG;
 
218
 
 
219
        if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
 
220
                BCMLOG_ERR("insufficient buffer\n");
 
221
                return BC_STS_INV_ARG;
 
222
        }
 
223
 
 
224
        sts = crystalhd_mem_wr(ctx->adp, idata->udata.u.devMem.StartOff,
 
225
                             idata->udata.u.devMem.NumDwords,
 
226
                             (uint32_t *)idata->add_cdata);
 
227
        return sts;
 
228
}
 
229
 
 
230
static enum BC_STATUS bc_cproc_cfg_rd(struct crystalhd_cmd *ctx,
 
231
                                 struct crystalhd_ioctl_data *idata)
 
232
{
 
233
        uint32_t ix, cnt, off, len;
 
234
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
235
        uint32_t *temp;
 
236
 
 
237
        if (!ctx || !idata)
 
238
                return BC_STS_INV_ARG;
 
239
 
 
240
        temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
 
241
        off = idata->udata.u.pciCfg.Offset;
 
242
        len = idata->udata.u.pciCfg.Size;
 
243
 
 
244
        if (len <= 4)
 
245
                return crystalhd_pci_cfg_rd(ctx->adp, off, len, temp);
 
246
 
 
247
        /* Truncate to dword alignment..*/
 
248
        len = 4;
 
249
        cnt = idata->udata.u.pciCfg.Size / len;
 
250
        for (ix = 0; ix < cnt; ix++) {
 
251
                sts = crystalhd_pci_cfg_rd(ctx->adp, off, len, &temp[ix]);
 
252
                if (sts != BC_STS_SUCCESS) {
 
253
                        BCMLOG_ERR("config read : %d\n", sts);
 
254
                        return sts;
 
255
                }
 
256
                off += len;
 
257
        }
 
258
 
 
259
        return sts;
 
260
}
 
261
 
 
262
static enum BC_STATUS bc_cproc_cfg_wr(struct crystalhd_cmd *ctx,
 
263
                                 struct crystalhd_ioctl_data *idata)
 
264
{
 
265
        uint32_t ix, cnt, off, len;
 
266
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
267
        uint32_t *temp;
 
268
 
 
269
        if (!ctx || !idata)
 
270
                return BC_STS_INV_ARG;
 
271
 
 
272
        temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
 
273
        off = idata->udata.u.pciCfg.Offset;
 
274
        len = idata->udata.u.pciCfg.Size;
 
275
 
 
276
        if (len <= 4)
 
277
                return crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[0]);
 
278
 
 
279
        /* Truncate to dword alignment..*/
 
280
        len = 4;
 
281
        cnt = idata->udata.u.pciCfg.Size / len;
 
282
        for (ix = 0; ix < cnt; ix++) {
 
283
                sts = crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[ix]);
 
284
                if (sts != BC_STS_SUCCESS) {
 
285
                        BCMLOG_ERR("config write : %d\n", sts);
 
286
                        return sts;
 
287
                }
 
288
                off += len;
 
289
        }
 
290
 
 
291
        return sts;
 
292
}
 
293
 
 
294
static enum BC_STATUS bc_cproc_download_fw(struct crystalhd_cmd *ctx,
 
295
                                      struct crystalhd_ioctl_data *idata)
 
296
{
 
297
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
298
 
 
299
        if (!ctx || !idata || !idata->add_cdata || !idata->add_cdata_sz) {
 
300
                BCMLOG_ERR("Invalid Arg!!\n");
 
301
                return BC_STS_INV_ARG;
 
302
        }
 
303
 
 
304
        if (ctx->state != BC_LINK_INVALID) {
 
305
                BCMLOG_ERR("Link invalid state %d\n", ctx->state);
 
306
                return BC_STS_ERR_USAGE;
 
307
        }
 
308
 
 
309
        sts = crystalhd_download_fw(ctx->adp, (uint8_t *)idata->add_cdata,
 
310
                                  idata->add_cdata_sz);
 
311
 
 
312
        if (sts != BC_STS_SUCCESS) {
 
313
                BCMLOG_ERR("Firmware Download Failure!! - %d\n", sts);
 
314
        } else
 
315
                ctx->state |= BC_LINK_INIT;
 
316
 
 
317
        return sts;
 
318
}
 
319
 
 
320
/*
 
321
 * We use the FW_CMD interface to sync up playback state with application
 
322
 * and  firmware. This function will perform the required pre and post
 
323
 * processing of the Firmware commands.
 
324
 *
 
325
 * Pause -
 
326
 *      Disable capture after decoder pause.
 
327
 * Resume -
 
328
 *      First enable capture and issue decoder resume command.
 
329
 * Flush -
 
330
 *      Abort pending input transfers and issue decoder flush command.
 
331
 *
 
332
 */
 
333
static enum BC_STATUS bc_cproc_do_fw_cmd(struct crystalhd_cmd *ctx,
 
334
                                        struct crystalhd_ioctl_data *idata)
 
335
{
 
336
        enum BC_STATUS sts;
 
337
        uint32_t *cmd;
 
338
 
 
339
        if (!(ctx->state & BC_LINK_INIT)) {
 
340
                BCMLOG_ERR("Link invalid state %d\n", ctx->state);
 
341
                return BC_STS_ERR_USAGE;
 
342
        }
 
343
 
 
344
        cmd = idata->udata.u.fwCmd.cmd;
 
345
 
 
346
        /* Pre-Process */
 
347
        if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
 
348
                if (!cmd[3]) {
 
349
                        ctx->state &= ~BC_LINK_PAUSED;
 
350
                        crystalhd_hw_unpause(&ctx->hw_ctx);
 
351
                }
 
352
        } else if (cmd[0] == eCMD_C011_DEC_CHAN_FLUSH) {
 
353
                BCMLOG(BCMLOG_INFO, "Flush issued\n");
 
354
                if (cmd[3])
 
355
                        ctx->cin_wait_exit = 1;
 
356
        }
 
357
 
 
358
        sts = crystalhd_do_fw_cmd(&ctx->hw_ctx, &idata->udata.u.fwCmd);
 
359
 
 
360
        if (sts != BC_STS_SUCCESS) {
 
361
                BCMLOG(BCMLOG_INFO, "fw cmd %x failed\n", cmd[0]);
 
362
                return sts;
 
363
        }
 
364
 
 
365
        /* Post-Process */
 
366
        if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
 
367
                if (cmd[3]) {
 
368
                        ctx->state |= BC_LINK_PAUSED;
 
369
                        crystalhd_hw_pause(&ctx->hw_ctx);
 
370
                }
 
371
        }
 
372
 
 
373
        return sts;
 
374
}
 
375
 
 
376
static void bc_proc_in_completion(struct crystalhd_dio_req *dio_hnd,
 
377
                                  wait_queue_head_t *event, enum BC_STATUS sts)
 
378
{
 
379
        if (!dio_hnd || !event) {
 
380
                BCMLOG_ERR("Invalid Arg!!\n");
 
381
                return;
 
382
        }
 
383
        if (sts == BC_STS_IO_USER_ABORT)
 
384
                return;
 
385
 
 
386
        dio_hnd->uinfo.comp_sts = sts;
 
387
        dio_hnd->uinfo.ev_sts = 1;
 
388
        crystalhd_set_event(event);
 
389
}
 
390
 
 
391
static enum BC_STATUS bc_cproc_codein_sleep(struct crystalhd_cmd *ctx)
 
392
{
 
393
        wait_queue_head_t sleep_ev;
 
394
        int rc = 0;
 
395
 
 
396
        if (ctx->state & BC_LINK_SUSPEND)
 
397
                return BC_STS_IO_USER_ABORT;
 
398
 
 
399
        if (ctx->cin_wait_exit) {
 
400
                ctx->cin_wait_exit = 0;
 
401
                return BC_STS_CMD_CANCELLED;
 
402
        }
 
403
        crystalhd_create_event(&sleep_ev);
 
404
        crystalhd_wait_on_event(&sleep_ev, 0, 100, rc, 0);
 
405
        if (rc == -EINTR)
 
406
                return BC_STS_IO_USER_ABORT;
 
407
 
 
408
        return BC_STS_SUCCESS;
 
409
}
 
410
 
 
411
static enum BC_STATUS bc_cproc_hw_txdma(struct crystalhd_cmd *ctx,
 
412
                                   struct crystalhd_ioctl_data *idata,
 
413
                                   struct crystalhd_dio_req *dio)
 
414
{
 
415
        uint32_t tx_listid = 0;
 
416
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
417
        wait_queue_head_t event;
 
418
        int rc = 0;
 
419
 
 
420
        if (!ctx || !idata || !dio) {
 
421
                BCMLOG_ERR("Invalid Arg!!\n");
 
422
                return BC_STS_INV_ARG;
 
423
        }
 
424
 
 
425
        crystalhd_create_event(&event);
 
426
 
 
427
        ctx->tx_list_id = 0;
 
428
        /* msleep_interruptible(2000); */
 
429
        sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio, bc_proc_in_completion,
 
430
                                 &event, &tx_listid,
 
431
                                 idata->udata.u.ProcInput.Encrypted);
 
432
 
 
433
        while (sts == BC_STS_BUSY) {
 
434
                sts = bc_cproc_codein_sleep(ctx);
 
435
                if (sts != BC_STS_SUCCESS)
 
436
                        break;
 
437
                sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio,
 
438
                                         bc_proc_in_completion,
 
439
                                         &event, &tx_listid,
 
440
                                         idata->udata.u.ProcInput.Encrypted);
 
441
        }
 
442
        if (sts != BC_STS_SUCCESS) {
 
443
                BCMLOG(BCMLOG_DBG, "_hw_txdma returning sts:%d\n", sts);
 
444
                return sts;
 
445
        }
 
446
        if (ctx->cin_wait_exit)
 
447
                ctx->cin_wait_exit = 0;
 
448
 
 
449
        ctx->tx_list_id = tx_listid;
 
450
 
 
451
        /* _post() succeeded.. wait for the completion. */
 
452
        crystalhd_wait_on_event(&event, (dio->uinfo.ev_sts), 3000, rc, 0);
 
453
        ctx->tx_list_id = 0;
 
454
        if (!rc) {
 
455
                return dio->uinfo.comp_sts;
 
456
        } else if (rc == -EBUSY) {
 
457
                BCMLOG(BCMLOG_DBG, "_tx_post() T/O\n");
 
458
                sts = BC_STS_TIMEOUT;
 
459
        } else if (rc == -EINTR) {
 
460
                BCMLOG(BCMLOG_DBG, "Tx Wait Signal int.\n");
 
461
                sts = BC_STS_IO_USER_ABORT;
 
462
        } else {
 
463
                sts = BC_STS_IO_ERROR;
 
464
        }
 
465
 
 
466
        /* We are cancelling the IO from the same context as the _post().
 
467
         * so no need to wait on the event again.. the return itself
 
468
         * ensures the release of our resources.
 
469
         */
 
470
        crystalhd_hw_cancel_tx(&ctx->hw_ctx, tx_listid);
 
471
 
 
472
        return sts;
 
473
}
 
474
 
 
475
/* Helper function to check on user buffers */
 
476
static enum BC_STATUS bc_cproc_check_inbuffs(bool pin, void *ubuff, uint32_t ub_sz,
 
477
                                        uint32_t uv_off, bool en_422)
 
478
{
 
479
        if (!ubuff || !ub_sz) {
 
480
                BCMLOG_ERR("%s->Invalid Arg %p %x\n",
 
481
                        ((pin) ? "TX" : "RX"), ubuff, ub_sz);
 
482
                return BC_STS_INV_ARG;
 
483
        }
 
484
 
 
485
        /* Check for alignment */
 
486
        if (((uintptr_t)ubuff) & 0x03) {
 
487
                BCMLOG_ERR("%s-->Un-aligned address not implemented yet.. %p\n",
 
488
                                ((pin) ? "TX" : "RX"), ubuff);
 
489
                return BC_STS_NOT_IMPL;
 
490
        }
 
491
        if (pin)
 
492
                return BC_STS_SUCCESS;
 
493
 
 
494
        if (!en_422 && !uv_off) {
 
495
                BCMLOG_ERR("Need UV offset for 420 mode.\n");
 
496
                return BC_STS_INV_ARG;
 
497
        }
 
498
 
 
499
        if (en_422 && uv_off) {
 
500
                BCMLOG_ERR("UV offset in 422 mode ??\n");
 
501
                return BC_STS_INV_ARG;
 
502
        }
 
503
 
 
504
        return BC_STS_SUCCESS;
 
505
}
 
506
 
 
507
static enum BC_STATUS bc_cproc_proc_input(struct crystalhd_cmd *ctx,
 
508
                                        struct crystalhd_ioctl_data *idata)
 
509
{
 
510
        void *ubuff;
 
511
        uint32_t ub_sz;
 
512
        struct crystalhd_dio_req *dio_hnd = NULL;
 
513
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
514
 
 
515
        if (!ctx || !idata) {
 
516
                BCMLOG_ERR("Invalid Arg!!\n");
 
517
                return BC_STS_INV_ARG;
 
518
        }
 
519
 
 
520
        ubuff = idata->udata.u.ProcInput.pDmaBuff;
 
521
        ub_sz = idata->udata.u.ProcInput.BuffSz;
 
522
 
 
523
        sts = bc_cproc_check_inbuffs(1, ubuff, ub_sz, 0, 0);
 
524
        if (sts != BC_STS_SUCCESS)
 
525
                return sts;
 
526
 
 
527
        sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, 0, 0, 1, &dio_hnd);
 
528
        if (sts != BC_STS_SUCCESS) {
 
529
                BCMLOG_ERR("dio map - %d\n", sts);
 
530
                return sts;
 
531
        }
 
532
 
 
533
        if (!dio_hnd)
 
534
                return BC_STS_ERROR;
 
535
 
 
536
        sts = bc_cproc_hw_txdma(ctx, idata, dio_hnd);
 
537
 
 
538
        crystalhd_unmap_dio(ctx->adp, dio_hnd);
 
539
 
 
540
        return sts;
 
541
}
 
542
 
 
543
static enum BC_STATUS bc_cproc_add_cap_buff(struct crystalhd_cmd *ctx,
 
544
                                       struct crystalhd_ioctl_data *idata)
 
545
{
 
546
        void *ubuff;
 
547
        uint32_t ub_sz, uv_off;
 
548
        bool en_422;
 
549
        struct crystalhd_dio_req *dio_hnd = NULL;
 
550
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
551
 
 
552
        if (!ctx || !idata) {
 
553
                BCMLOG_ERR("Invalid Arg!!\n");
 
554
                return BC_STS_INV_ARG;
 
555
        }
 
556
 
 
557
        ubuff = idata->udata.u.RxBuffs.YuvBuff;
 
558
        ub_sz = idata->udata.u.RxBuffs.YuvBuffSz;
 
559
        uv_off = idata->udata.u.RxBuffs.UVbuffOffset;
 
560
        en_422 = idata->udata.u.RxBuffs.b422Mode;
 
561
 
 
562
        sts = bc_cproc_check_inbuffs(0, ubuff, ub_sz, uv_off, en_422);
 
563
        if (sts != BC_STS_SUCCESS)
 
564
                return sts;
 
565
 
 
566
        sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, uv_off,
 
567
                              en_422, 0, &dio_hnd);
 
568
        if (sts != BC_STS_SUCCESS) {
 
569
                BCMLOG_ERR("dio map - %d\n", sts);
 
570
                return sts;
 
571
        }
 
572
 
 
573
        if (!dio_hnd)
 
574
                return BC_STS_ERROR;
 
575
 
 
576
        sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio_hnd, (ctx->state == BC_LINK_READY));
 
577
        if ((sts != BC_STS_SUCCESS) && (sts != BC_STS_BUSY)) {
 
578
                crystalhd_unmap_dio(ctx->adp, dio_hnd);
 
579
                return sts;
 
580
        }
 
581
 
 
582
        return BC_STS_SUCCESS;
 
583
}
 
584
 
 
585
static enum BC_STATUS bc_cproc_fmt_change(struct crystalhd_cmd *ctx,
 
586
                                     struct crystalhd_dio_req *dio)
 
587
{
 
588
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
589
 
 
590
        sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio, 0);
 
591
        if (sts != BC_STS_SUCCESS)
 
592
                return sts;
 
593
 
 
594
        ctx->state |= BC_LINK_FMT_CHG;
 
595
        if (ctx->state == BC_LINK_READY)
 
596
                sts = crystalhd_hw_start_capture(&ctx->hw_ctx);
 
597
 
 
598
        return sts;
 
599
}
 
600
 
 
601
static enum BC_STATUS bc_cproc_fetch_frame(struct crystalhd_cmd *ctx,
 
602
                                      struct crystalhd_ioctl_data *idata)
 
603
{
 
604
        struct crystalhd_dio_req *dio = NULL;
 
605
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
606
        struct BC_DEC_OUT_BUFF *frame;
 
607
 
 
608
        if (!ctx || !idata) {
 
609
                BCMLOG_ERR("Invalid Arg!!\n");
 
610
                return BC_STS_INV_ARG;
 
611
        }
 
612
 
 
613
        if (!(ctx->state & BC_LINK_CAP_EN)) {
 
614
                BCMLOG(BCMLOG_DBG, "Capture not enabled..%x\n", ctx->state);
 
615
                return BC_STS_ERR_USAGE;
 
616
        }
 
617
 
 
618
        frame = &idata->udata.u.DecOutData;
 
619
 
 
620
        sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
 
621
        if (sts != BC_STS_SUCCESS)
 
622
                return (ctx->state & BC_LINK_SUSPEND) ? BC_STS_IO_USER_ABORT : sts;
 
623
 
 
624
        frame->Flags = dio->uinfo.comp_flags;
 
625
 
 
626
        if (frame->Flags & COMP_FLAG_FMT_CHANGE)
 
627
                return bc_cproc_fmt_change(ctx, dio);
 
628
 
 
629
        frame->OutPutBuffs.YuvBuff = dio->uinfo.xfr_buff;
 
630
        frame->OutPutBuffs.YuvBuffSz = dio->uinfo.xfr_len;
 
631
        frame->OutPutBuffs.UVbuffOffset = dio->uinfo.uv_offset;
 
632
        frame->OutPutBuffs.b422Mode = dio->uinfo.b422mode;
 
633
 
 
634
        frame->OutPutBuffs.YBuffDoneSz = dio->uinfo.y_done_sz;
 
635
        frame->OutPutBuffs.UVBuffDoneSz = dio->uinfo.uv_done_sz;
 
636
 
 
637
        crystalhd_unmap_dio(ctx->adp, dio);
 
638
 
 
639
        return BC_STS_SUCCESS;
 
640
}
 
641
 
 
642
static enum BC_STATUS bc_cproc_start_capture(struct crystalhd_cmd *ctx,
 
643
                                        struct crystalhd_ioctl_data *idata)
 
644
{
 
645
        ctx->state |= BC_LINK_CAP_EN;
 
646
        if (ctx->state == BC_LINK_READY)
 
647
                return crystalhd_hw_start_capture(&ctx->hw_ctx);
 
648
 
 
649
        return BC_STS_SUCCESS;
 
650
}
 
651
 
 
652
static enum BC_STATUS bc_cproc_flush_cap_buffs(struct crystalhd_cmd *ctx,
 
653
                                          struct crystalhd_ioctl_data *idata)
 
654
{
 
655
        struct crystalhd_dio_req *dio = NULL;
 
656
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
657
        struct BC_DEC_OUT_BUFF *frame;
 
658
        uint32_t count;
 
659
 
 
660
        if (!ctx || !idata) {
 
661
                BCMLOG_ERR("Invalid Arg!!\n");
 
662
                return BC_STS_INV_ARG;
 
663
        }
 
664
 
 
665
        if (!(ctx->state & BC_LINK_CAP_EN))
 
666
                return BC_STS_ERR_USAGE;
 
667
 
 
668
        /* We should ack flush even when we are in paused/suspend state */
 
669
        if (!(ctx->state & BC_LINK_READY))
 
670
                return crystalhd_hw_stop_capture(&ctx->hw_ctx);
 
671
 
 
672
        ctx->state &= ~(BC_LINK_CAP_EN|BC_LINK_FMT_CHG);
 
673
 
 
674
        frame = &idata->udata.u.DecOutData;
 
675
        for (count = 0; count < BC_RX_LIST_CNT; count++) {
 
676
 
 
677
                sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
 
678
                if (sts != BC_STS_SUCCESS)
 
679
                        break;
 
680
 
 
681
                crystalhd_unmap_dio(ctx->adp, dio);
 
682
        }
 
683
 
 
684
        return crystalhd_hw_stop_capture(&ctx->hw_ctx);
 
685
}
 
686
 
 
687
static enum BC_STATUS bc_cproc_get_stats(struct crystalhd_cmd *ctx,
 
688
                                    struct crystalhd_ioctl_data *idata)
 
689
{
 
690
        struct BC_DTS_STATS *stats;
 
691
        struct crystalhd_hw_stats       hw_stats;
 
692
 
 
693
        if (!ctx || !idata) {
 
694
                BCMLOG_ERR("Invalid Arg!!\n");
 
695
                return BC_STS_INV_ARG;
 
696
        }
 
697
 
 
698
        crystalhd_hw_stats(&ctx->hw_ctx, &hw_stats);
 
699
 
 
700
        stats = &idata->udata.u.drvStat;
 
701
        stats->drvRLL = hw_stats.rdyq_count;
 
702
        stats->drvFLL = hw_stats.freeq_count;
 
703
        stats->DrvTotalFrmDropped = hw_stats.rx_errors;
 
704
        stats->DrvTotalHWErrs = hw_stats.rx_errors + hw_stats.tx_errors;
 
705
        stats->intCount = hw_stats.num_interrupts;
 
706
        stats->DrvIgnIntrCnt = hw_stats.num_interrupts -
 
707
                                hw_stats.dev_interrupts;
 
708
        stats->TxFifoBsyCnt = hw_stats.cin_busy;
 
709
        stats->pauseCount = hw_stats.pause_cnt;
 
710
 
 
711
        if (ctx->pwr_state_change)
 
712
                stats->pwr_state_change = 1;
 
713
        if (ctx->state & BC_LINK_PAUSED)
 
714
                stats->DrvPauseTime = 1;
 
715
 
 
716
        return BC_STS_SUCCESS;
 
717
}
 
718
 
 
719
static enum BC_STATUS bc_cproc_reset_stats(struct crystalhd_cmd *ctx,
 
720
                                      struct crystalhd_ioctl_data *idata)
 
721
{
 
722
        crystalhd_hw_stats(&ctx->hw_ctx, NULL);
 
723
 
 
724
        return BC_STS_SUCCESS;
 
725
}
 
726
 
 
727
static enum BC_STATUS bc_cproc_chg_clk(struct crystalhd_cmd *ctx,
 
728
                                  struct crystalhd_ioctl_data *idata)
 
729
{
 
730
        struct BC_CLOCK *clock;
 
731
        uint32_t oldClk;
 
732
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
733
 
 
734
        if (!ctx || !idata) {
 
735
                BCMLOG_ERR("Invalid Arg!!\n");
 
736
                return BC_STS_INV_ARG;
 
737
        }
 
738
 
 
739
        clock = &idata->udata.u.clockValue;
 
740
        oldClk = ctx->hw_ctx.core_clock_mhz;
 
741
        ctx->hw_ctx.core_clock_mhz = clock->clk;
 
742
 
 
743
        if (ctx->state & BC_LINK_READY) {
 
744
                sts = crystalhd_hw_set_core_clock(&ctx->hw_ctx);
 
745
                if (sts == BC_STS_CLK_NOCHG)
 
746
                        ctx->hw_ctx.core_clock_mhz = oldClk;
 
747
        }
 
748
 
 
749
        clock->clk = ctx->hw_ctx.core_clock_mhz;
 
750
 
 
751
        return sts;
 
752
}
 
753
 
 
754
/*=============== Cmd Proc Table.. ======================================*/
 
755
static const struct crystalhd_cmd_tbl   g_crystalhd_cproc_tbl[] = {
 
756
        { BCM_IOC_GET_VERSION,          bc_cproc_get_version,   0},
 
757
        { BCM_IOC_GET_HWTYPE,           bc_cproc_get_hwtype,    0},
 
758
        { BCM_IOC_REG_RD,               bc_cproc_reg_rd,        0},
 
759
        { BCM_IOC_REG_WR,               bc_cproc_reg_wr,        0},
 
760
        { BCM_IOC_FPGA_RD,              bc_cproc_link_reg_rd,   0},
 
761
        { BCM_IOC_FPGA_WR,              bc_cproc_link_reg_wr,   0},
 
762
        { BCM_IOC_MEM_RD,               bc_cproc_mem_rd,        0},
 
763
        { BCM_IOC_MEM_WR,               bc_cproc_mem_wr,        0},
 
764
        { BCM_IOC_RD_PCI_CFG,           bc_cproc_cfg_rd,        0},
 
765
        { BCM_IOC_WR_PCI_CFG,           bc_cproc_cfg_wr,        1},
 
766
        { BCM_IOC_FW_DOWNLOAD,          bc_cproc_download_fw,   1},
 
767
        { BCM_IOC_FW_CMD,               bc_cproc_do_fw_cmd,     1},
 
768
        { BCM_IOC_PROC_INPUT,           bc_cproc_proc_input,    1},
 
769
        { BCM_IOC_ADD_RXBUFFS,          bc_cproc_add_cap_buff,  1},
 
770
        { BCM_IOC_FETCH_RXBUFF,         bc_cproc_fetch_frame,   1},
 
771
        { BCM_IOC_START_RX_CAP,         bc_cproc_start_capture, 1},
 
772
        { BCM_IOC_FLUSH_RX_CAP,         bc_cproc_flush_cap_buffs, 1},
 
773
        { BCM_IOC_GET_DRV_STAT,         bc_cproc_get_stats,     0},
 
774
        { BCM_IOC_RST_DRV_STAT,         bc_cproc_reset_stats,   0},
 
775
        { BCM_IOC_NOTIFY_MODE,          bc_cproc_notify_mode,   0},
 
776
        { BCM_IOC_CHG_CLK,              bc_cproc_chg_clk, 0},
 
777
        { BCM_IOC_END,                  NULL},
 
778
};
 
779
 
 
780
/*=============== Cmd Proc Functions.. ===================================*/
 
781
 
 
782
/**
 
783
 * crystalhd_suspend - Power management suspend request.
 
784
 * @ctx: Command layer context.
 
785
 * @idata: Iodata - required for internal use.
 
786
 *
 
787
 * Return:
 
788
 *      status
 
789
 *
 
790
 * 1. Set the state to Suspend.
 
791
 * 2. Flush the Rx Buffers it will unmap all the buffers and
 
792
 *    stop the RxDMA engine.
 
793
 * 3. Cancel The TX Io and Stop Dma Engine.
 
794
 * 4. Put the DDR in to deep sleep.
 
795
 * 5. Stop the hardware putting it in to Reset State.
 
796
 *
 
797
 * Current gstreamer frame work does not provide any power management
 
798
 * related notification to user mode decoder plug-in. As a work-around
 
799
 * we pass on the power mangement notification to our plug-in by completing
 
800
 * all outstanding requests with BC_STS_IO_USER_ABORT return code.
 
801
 */
 
802
enum BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx,
 
803
                                struct crystalhd_ioctl_data *idata)
 
804
{
 
805
        enum BC_STATUS sts = BC_STS_SUCCESS;
 
806
 
 
807
        if (!ctx || !idata) {
 
808
                BCMLOG_ERR("Invalid Parameters\n");
 
809
                return BC_STS_ERROR;
 
810
        }
 
811
 
 
812
        if (ctx->state & BC_LINK_SUSPEND)
 
813
                return BC_STS_SUCCESS;
 
814
 
 
815
        if (ctx->state == BC_LINK_INVALID) {
 
816
                BCMLOG(BCMLOG_DBG, "Nothing To Do Suspend Success\n");
 
817
                return BC_STS_SUCCESS;
 
818
        }
 
819
 
 
820
        ctx->state |= BC_LINK_SUSPEND;
 
821
 
 
822
        bc_cproc_mark_pwr_state(ctx);
 
823
 
 
824
        if (ctx->state & BC_LINK_CAP_EN) {
 
825
                sts = bc_cproc_flush_cap_buffs(ctx, idata);
 
826
                if (sts != BC_STS_SUCCESS)
 
827
                        return sts;
 
828
        }
 
829
 
 
830
        if (ctx->tx_list_id) {
 
831
                sts = crystalhd_hw_cancel_tx(&ctx->hw_ctx, ctx->tx_list_id);
 
832
                if (sts != BC_STS_SUCCESS)
 
833
                        return sts;
 
834
        }
 
835
 
 
836
        sts = crystalhd_hw_suspend(&ctx->hw_ctx);
 
837
        if (sts != BC_STS_SUCCESS)
 
838
                return sts;
 
839
 
 
840
        BCMLOG(BCMLOG_DBG, "BCM70012 suspend success\n");
 
841
 
 
842
        return BC_STS_SUCCESS;
 
843
}
 
844
 
 
845
/**
 
846
 * crystalhd_resume - Resume frame capture.
 
847
 * @ctx: Command layer contextx.
 
848
 *
 
849
 * Return:
 
850
 *      status
 
851
 *
 
852
 *
 
853
 * Resume frame capture.
 
854
 *
 
855
 * PM_Resume can't resume the playback state back to pre-suspend state
 
856
 * because we don't keep video clip related information within driver.
 
857
 * To get back to the pre-suspend state App will re-open the device and
 
858
 * start a new playback session from the pre-suspend clip position.
 
859
 *
 
860
 */
 
861
enum BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx)
 
862
{
 
863
        BCMLOG(BCMLOG_DBG, "crystalhd_resume Success %x\n", ctx->state);
 
864
 
 
865
        bc_cproc_mark_pwr_state(ctx);
 
866
 
 
867
        return BC_STS_SUCCESS;
 
868
}
 
869
 
 
870
/**
 
871
 * crystalhd_user_open - Create application handle.
 
872
 * @ctx: Command layer contextx.
 
873
 * @user_ctx: User ID context.
 
874
 *
 
875
 * Return:
 
876
 *      status
 
877
 *
 
878
 * Creates an application specific UID and allocates
 
879
 * application specific resources. HW layer initialization
 
880
 * is done for the first open request.
 
881
 */
 
882
enum BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx,
 
883
                            struct crystalhd_user **user_ctx)
 
884
{
 
885
        struct crystalhd_user *uc;
 
886
 
 
887
        if (!ctx || !user_ctx) {
 
888
                BCMLOG_ERR("Invalid arg..\n");
 
889
                return BC_STS_INV_ARG;
 
890
        }
 
891
 
 
892
        uc = bc_cproc_get_uid(ctx);
 
893
        if (!uc) {
 
894
                BCMLOG(BCMLOG_INFO, "No free user context...\n");
 
895
                return BC_STS_BUSY;
 
896
        }
 
897
 
 
898
        BCMLOG(BCMLOG_INFO, "Opening new user[%x] handle\n", uc->uid);
 
899
 
 
900
        crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
 
901
 
 
902
        uc->in_use = 1;
 
903
 
 
904
        *user_ctx = uc;
 
905
 
 
906
        return BC_STS_SUCCESS;
 
907
}
 
908
 
 
909
/**
 
910
 * crystalhd_user_close - Close application handle.
 
911
 * @ctx: Command layer contextx.
 
912
 * @uc: User ID context.
 
913
 *
 
914
 * Return:
 
915
 *      status
 
916
 *
 
917
 * Closer application handle and release app specific
 
918
 * resources.
 
919
 */
 
920
enum BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc)
 
921
{
 
922
        uint32_t mode = uc->mode;
 
923
 
 
924
        ctx->user[uc->uid].mode = DTS_MODE_INV;
 
925
        ctx->user[uc->uid].in_use = 0;
 
926
        ctx->cin_wait_exit = 1;
 
927
        ctx->pwr_state_change = 0;
 
928
 
 
929
        BCMLOG(BCMLOG_INFO, "Closing user[%x] handle\n", uc->uid);
 
930
 
 
931
        if ((mode == DTS_DIAG_MODE) || (mode == DTS_PLAYBACK_MODE)) {
 
932
                crystalhd_hw_free_dma_rings(&ctx->hw_ctx);
 
933
                crystalhd_destroy_dio_pool(ctx->adp);
 
934
        } else if (bc_cproc_get_user_count(ctx)) {
 
935
                return BC_STS_SUCCESS;
 
936
        }
 
937
 
 
938
        crystalhd_hw_close(&ctx->hw_ctx);
 
939
 
 
940
        ctx->state = BC_LINK_INVALID;
 
941
 
 
942
        return BC_STS_SUCCESS;
 
943
}
 
944
 
 
945
/**
 
946
 * crystalhd_setup_cmd_context - Setup Command layer resources.
 
947
 * @ctx: Command layer contextx.
 
948
 * @adp: Adapter context
 
949
 *
 
950
 * Return:
 
951
 *      status
 
952
 *
 
953
 * Called at the time of driver load.
 
954
 */
 
955
enum BC_STATUS __devinit crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
 
956
                                    struct crystalhd_adp *adp)
 
957
{
 
958
        int i = 0;
 
959
 
 
960
        if (!ctx || !adp) {
 
961
                BCMLOG_ERR("Invalid arg!!\n");
 
962
                return BC_STS_INV_ARG;
 
963
        }
 
964
 
 
965
        if (ctx->adp)
 
966
                BCMLOG(BCMLOG_DBG, "Resetting Cmd context delete missing..\n");
 
967
 
 
968
        ctx->adp = adp;
 
969
        for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
 
970
                ctx->user[i].uid = i;
 
971
                ctx->user[i].in_use = 0;
 
972
                ctx->user[i].mode = DTS_MODE_INV;
 
973
        }
 
974
 
 
975
        /*Open and Close the Hardware to put it in to sleep state*/
 
976
        crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
 
977
        crystalhd_hw_close(&ctx->hw_ctx);
 
978
        return BC_STS_SUCCESS;
 
979
}
 
980
 
 
981
/**
 
982
 * crystalhd_delete_cmd_context - Release Command layer resources.
 
983
 * @ctx: Command layer contextx.
 
984
 *
 
985
 * Return:
 
986
 *      status
 
987
 *
 
988
 * Called at the time of driver un-load.
 
989
 */
 
990
enum BC_STATUS __devexit crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
 
991
{
 
992
        BCMLOG(BCMLOG_DBG, "Deleting Command context..\n");
 
993
 
 
994
        ctx->adp = NULL;
 
995
 
 
996
        return BC_STS_SUCCESS;
 
997
}
 
998
 
 
999
/**
 
1000
 * crystalhd_get_cmd_proc  - Cproc table lookup.
 
1001
 * @ctx: Command layer contextx.
 
1002
 * @cmd: IOCTL command code.
 
1003
 * @uc: User ID context.
 
1004
 *
 
1005
 * Return:
 
1006
 *      command proc function pointer
 
1007
 *
 
1008
 * This function checks the process context, application's
 
1009
 * mode of operation and returns the function pointer
 
1010
 * from the cproc table.
 
1011
 */
 
1012
crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx, uint32_t cmd,
 
1013
                                      struct crystalhd_user *uc)
 
1014
{
 
1015
        crystalhd_cmd_proc cproc = NULL;
 
1016
        unsigned int i, tbl_sz;
 
1017
 
 
1018
        if (!ctx) {
 
1019
                BCMLOG_ERR("Invalid arg.. Cmd[%d]\n", cmd);
 
1020
                return NULL;
 
1021
        }
 
1022
 
 
1023
        if ((cmd != BCM_IOC_GET_DRV_STAT) && (ctx->state & BC_LINK_SUSPEND)) {
 
1024
                BCMLOG_ERR("Invalid State [suspend Set].. Cmd[%d]\n", cmd);
 
1025
                return NULL;
 
1026
        }
 
1027
 
 
1028
        tbl_sz = sizeof(g_crystalhd_cproc_tbl) / sizeof(struct crystalhd_cmd_tbl);
 
1029
        for (i = 0; i < tbl_sz; i++) {
 
1030
                if (g_crystalhd_cproc_tbl[i].cmd_id == cmd) {
 
1031
                        if ((uc->mode == DTS_MONITOR_MODE) &&
 
1032
                            (g_crystalhd_cproc_tbl[i].block_mon)) {
 
1033
                                BCMLOG(BCMLOG_INFO, "Blocking cmd %d\n", cmd);
 
1034
                                break;
 
1035
                        }
 
1036
                        cproc = g_crystalhd_cproc_tbl[i].cmd_proc;
 
1037
                        break;
 
1038
                }
 
1039
        }
 
1040
 
 
1041
        return cproc;
 
1042
}
 
1043
 
 
1044
/**
 
1045
 * crystalhd_cmd_interrupt - ISR entry point
 
1046
 * @ctx: Command layer contextx.
 
1047
 *
 
1048
 * Return:
 
1049
 *      TRUE: If interrupt from bcm70012 device.
 
1050
 *
 
1051
 *
 
1052
 * ISR entry point from OS layer.
 
1053
 */
 
1054
bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx)
 
1055
{
 
1056
        if (!ctx) {
 
1057
                BCMLOG_ERR("Invalid arg..\n");
 
1058
                return 0;
 
1059
        }
 
1060
 
 
1061
        return crystalhd_hw_interrupt(ctx->adp, &ctx->hw_ctx);
 
1062
}