Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / drivers / staging / crystalhd / crystalhd_lnx.c
1 /***************************************************************************
2   BCM70010 Linux driver
3   Copyright (c) 2005-2009, Broadcom Corporation.
4
5   This driver is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation, version 2 of the License.
8
9   This driver is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this driver.  If not, see <http://www.gnu.org/licenses/>.
16 ***************************************************************************/
17
18 #include <linux/version.h>
19 #include <linux/slab.h>
20
21 #include "crystalhd_lnx.h"
22
23 static struct class *crystalhd_class;
24
25 static struct crystalhd_adp *g_adp_info;
26
27 static irqreturn_t chd_dec_isr(int irq, void *arg)
28 {
29         struct crystalhd_adp *adp = (struct crystalhd_adp *) arg;
30         int rc = 0;
31         if (adp)
32                 rc = crystalhd_cmd_interrupt(&adp->cmds);
33
34         return IRQ_RETVAL(rc);
35 }
36
37 static int chd_dec_enable_int(struct crystalhd_adp *adp)
38 {
39         int rc = 0;
40
41         if (!adp || !adp->pdev) {
42                 BCMLOG_ERR("Invalid arg!!\n");
43                 return -EINVAL;
44         }
45
46         if (adp->pdev->msi_enabled)
47                 adp->msi = 1;
48         else
49                 adp->msi = pci_enable_msi(adp->pdev);
50
51         rc = request_irq(adp->pdev->irq, chd_dec_isr, IRQF_SHARED,
52                          adp->name, (void *)adp);
53         if (rc) {
54                 BCMLOG_ERR("Interrupt request failed.. \n");
55                 pci_disable_msi(adp->pdev);
56         }
57
58         return rc;
59 }
60
61 static int chd_dec_disable_int(struct crystalhd_adp *adp)
62 {
63         if (!adp || !adp->pdev) {
64                 BCMLOG_ERR("Invalid arg!!\n");
65                 return -EINVAL;
66         }
67
68         free_irq(adp->pdev->irq, adp);
69
70         if (adp->msi)
71                 pci_disable_msi(adp->pdev);
72
73         return 0;
74 }
75
76 crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, bool isr)
77 {
78         unsigned long flags = 0;
79         crystalhd_ioctl_data *temp;
80
81         if (!adp)
82                 return NULL;
83
84         spin_lock_irqsave(&adp->lock, flags);
85
86         temp = adp->idata_free_head;
87         if (temp) {
88                 adp->idata_free_head = adp->idata_free_head->next;
89                 memset(temp, 0, sizeof(*temp));
90         }
91
92         spin_unlock_irqrestore(&adp->lock, flags);
93         return temp;
94 }
95
96 void chd_dec_free_iodata(struct crystalhd_adp *adp, crystalhd_ioctl_data *iodata,
97                          bool isr)
98 {
99         unsigned long flags = 0;
100
101         if (!adp || !iodata)
102                 return;
103
104         spin_lock_irqsave(&adp->lock, flags);
105         iodata->next = adp->idata_free_head;
106         adp->idata_free_head = iodata;
107         spin_unlock_irqrestore(&adp->lock, flags);
108 }
109
110 static inline int crystalhd_user_data(unsigned long ud, void *dr, int size, int set)
111 {
112         int rc;
113
114         if (!ud || !dr) {
115                 BCMLOG_ERR("Invalid arg \n");
116                 return -EINVAL;
117         }
118
119         if (set)
120                 rc = copy_to_user((void *)ud, dr, size);
121         else
122                 rc = copy_from_user(dr, (void *)ud, size);
123
124         if (rc) {
125                 BCMLOG_ERR("Invalid args for command \n");
126                 rc = -EFAULT;
127         }
128
129         return rc;
130 }
131
132 static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, crystalhd_ioctl_data *io,
133                                uint32_t m_sz, unsigned long ua)
134 {
135         unsigned long ua_off;
136         int rc = 0;
137
138         if (!adp || !io || !ua || !m_sz) {
139                 BCMLOG_ERR("Invalid Arg!!\n");
140                 return -EINVAL;
141         }
142
143         io->add_cdata = vmalloc(m_sz);
144         if (!io->add_cdata) {
145                 BCMLOG_ERR("kalloc fail for sz:%x\n", m_sz);
146                 return -ENOMEM;
147         }
148
149         io->add_cdata_sz = m_sz;
150         ua_off = ua + sizeof(io->udata);
151         rc = crystalhd_user_data(ua_off, io->add_cdata, io->add_cdata_sz, 0);
152         if (rc) {
153                 BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n",
154                            io->add_cdata_sz, (unsigned int)ua_off);
155                 if (io->add_cdata) {
156                         kfree(io->add_cdata);
157                         io->add_cdata = NULL;
158                 }
159                 return -ENODATA;
160         }
161
162         return rc;
163 }
164
165 static int chd_dec_release_cdata(struct crystalhd_adp *adp,
166                                  crystalhd_ioctl_data *io, unsigned long ua)
167 {
168         unsigned long ua_off;
169         int rc;
170
171         if (!adp || !io || !ua) {
172                 BCMLOG_ERR("Invalid Arg!!\n");
173                 return -EINVAL;
174         }
175
176         if (io->cmd != BCM_IOC_FW_DOWNLOAD) {
177                 ua_off = ua + sizeof(io->udata);
178                 rc = crystalhd_user_data(ua_off, io->add_cdata,
179                                         io->add_cdata_sz, 1);
180                 if (rc) {
181                         BCMLOG_ERR("failed to push add_cdata sz:%x ua_off:%x\n",
182                                    io->add_cdata_sz, (unsigned int)ua_off);
183                         return -ENODATA;
184                 }
185         }
186
187         if (io->add_cdata) {
188                 vfree(io->add_cdata);
189                 io->add_cdata = NULL;
190         }
191
192         return 0;
193 }
194
195 static int chd_dec_proc_user_data(struct crystalhd_adp *adp,
196                                   crystalhd_ioctl_data *io,
197                                   unsigned long ua, int set)
198 {
199         int rc;
200         uint32_t m_sz = 0;
201
202         if (!adp || !io || !ua) {
203                 BCMLOG_ERR("Invalid Arg!!\n");
204                 return -EINVAL;
205         }
206
207         rc = crystalhd_user_data(ua, &io->udata, sizeof(io->udata), set);
208         if (rc) {
209                 BCMLOG_ERR("failed to %s iodata \n", (set ? "set" : "get"));
210                 return rc;
211         }
212
213         switch (io->cmd) {
214         case BCM_IOC_MEM_RD:
215         case BCM_IOC_MEM_WR:
216         case BCM_IOC_FW_DOWNLOAD:
217                 m_sz = io->udata.u.devMem.NumDwords * 4;
218                 if (set)
219                         rc = chd_dec_release_cdata(adp, io, ua);
220                 else
221                         rc = chd_dec_fetch_cdata(adp, io, m_sz, ua);
222                 break;
223         default:
224                 break;
225         }
226
227         return rc;
228 }
229
230 static int chd_dec_api_cmd(struct crystalhd_adp *adp, unsigned long ua,
231                            uint32_t uid, uint32_t cmd, crystalhd_cmd_proc func)
232 {
233         int rc;
234         crystalhd_ioctl_data *temp;
235         BC_STATUS sts = BC_STS_SUCCESS;
236
237         temp = chd_dec_alloc_iodata(adp, 0);
238         if (!temp) {
239                 BCMLOG_ERR("Failed to get iodata..\n");
240                 return -EINVAL;
241         }
242
243         temp->u_id = uid;
244         temp->cmd  = cmd;
245
246         rc = chd_dec_proc_user_data(adp, temp, ua, 0);
247         if (!rc) {
248                 sts = func(&adp->cmds, temp);
249                 if (sts == BC_STS_PENDING)
250                         sts = BC_STS_NOT_IMPL;
251                 temp->udata.RetSts = sts;
252                 rc = chd_dec_proc_user_data(adp, temp, ua, 1);
253         }
254
255         if (temp) {
256                 chd_dec_free_iodata(adp, temp, 0);
257                 temp = NULL;
258         }
259
260         return rc;
261 }
262
263 /* API interfaces */
264 static int chd_dec_ioctl(struct inode *in, struct file *fd,
265                          unsigned int cmd, unsigned long ua)
266 {
267         struct crystalhd_adp *adp = chd_get_adp();
268         crystalhd_cmd_proc cproc;
269         struct crystalhd_user *uc;
270
271         if (!adp || !fd) {
272                 BCMLOG_ERR("Invalid adp\n");
273                 return -EINVAL;
274         }
275
276         uc = (struct crystalhd_user *)fd->private_data;
277         if (!uc) {
278                 BCMLOG_ERR("Failed to get uc\n");
279                 return -ENODATA;
280         }
281
282         cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc);
283         if (!cproc) {
284                 BCMLOG_ERR("Unhandled command: %d\n", cmd);
285                 return -EINVAL;
286         }
287
288         return chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc);
289 }
290
291 static int chd_dec_open(struct inode *in, struct file *fd)
292 {
293         struct crystalhd_adp *adp = chd_get_adp();
294         int rc = 0;
295         BC_STATUS sts = BC_STS_SUCCESS;
296         struct crystalhd_user *uc = NULL;
297
298         BCMLOG_ENTER;
299         if (!adp) {
300                 BCMLOG_ERR("Invalid adp\n");
301                 return -EINVAL;
302         }
303
304         if (adp->cfg_users >= BC_LINK_MAX_OPENS) {
305                 BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users);
306                 return -EBUSY;
307         }
308
309         sts = crystalhd_user_open(&adp->cmds, &uc);
310         if (sts != BC_STS_SUCCESS) {
311                 BCMLOG_ERR("cmd_user_open - %d \n", sts);
312                 rc = -EBUSY;
313         }
314
315         adp->cfg_users++;
316
317         fd->private_data = uc;
318
319         return rc;
320 }
321
322 static int chd_dec_close(struct inode *in, struct file *fd)
323 {
324         struct crystalhd_adp *adp = chd_get_adp();
325         struct crystalhd_user *uc;
326
327         BCMLOG_ENTER;
328         if (!adp) {
329                 BCMLOG_ERR("Invalid adp \n");
330                 return -EINVAL;
331         }
332
333         uc = (struct crystalhd_user *)fd->private_data;
334         if (!uc) {
335                 BCMLOG_ERR("Failed to get uc\n");
336                 return -ENODATA;
337         }
338
339         crystalhd_user_close(&adp->cmds, uc);
340
341         adp->cfg_users--;
342
343         return 0;
344 }
345
346 static const struct file_operations chd_dec_fops = {
347         .owner   = THIS_MODULE,
348         .ioctl   = chd_dec_ioctl,
349         .open    = chd_dec_open,
350         .release = chd_dec_close,
351 };
352
353 static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
354 {
355         crystalhd_ioctl_data *temp;
356         struct device *dev;
357         int rc = -ENODEV, i = 0;
358
359         if (!adp)
360                 goto fail;
361
362         adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME,
363                                              &chd_dec_fops);
364         if (adp->chd_dec_major < 0) {
365                 BCMLOG_ERR("Failed to create config dev\n");
366                 rc = adp->chd_dec_major;
367                 goto fail;
368         }
369
370         /* register crystalhd class */
371         crystalhd_class = class_create(THIS_MODULE, "crystalhd");
372         if (IS_ERR(crystalhd_class)) {
373                 BCMLOG_ERR("failed to create class\n");
374                 goto fail;
375         }
376
377         dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0),
378                             NULL, "crystalhd");
379         if (!dev) {
380                 BCMLOG_ERR("failed to create device\n");
381                 goto device_create_fail;
382         }
383
384         rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ);
385         if (rc) {
386                 BCMLOG_ERR("failed to create device\n");
387                 goto elem_pool_fail;
388         }
389
390         /* Allocate general purpose ioctl pool. */
391         for (i = 0; i < CHD_IODATA_POOL_SZ; i++) {
392                 /* FIXME: jarod: why atomic? */
393                 temp = kzalloc(sizeof(crystalhd_ioctl_data), GFP_ATOMIC);
394                 if (!temp) {
395                         BCMLOG_ERR("ioctl data pool kzalloc failed\n");
396                         rc = -ENOMEM;
397                         goto kzalloc_fail;
398                 }
399                 /* Add to global pool.. */
400                 chd_dec_free_iodata(adp, temp, 0);
401         }
402
403         return 0;
404
405 kzalloc_fail:
406         crystalhd_delete_elem_pool(adp);
407 elem_pool_fail:
408         device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
409 device_create_fail:
410         class_destroy(crystalhd_class);
411 fail:
412         return rc;
413 }
414
415 static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
416 {
417         crystalhd_ioctl_data *temp = NULL;
418         if (!adp)
419                 return;
420
421         if (adp->chd_dec_major > 0) {
422                 /* unregister crystalhd class */
423                 device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
424                 unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
425                 BCMLOG(BCMLOG_INFO, "released api device - %d\n",
426                        adp->chd_dec_major);
427                 class_destroy(crystalhd_class);
428         }
429         adp->chd_dec_major = 0;
430
431         /* Clear iodata pool.. */
432         do {
433                 temp = chd_dec_alloc_iodata(adp, 0);
434                 if (temp)
435                         kfree(temp);
436         } while (temp);
437
438         crystalhd_delete_elem_pool(adp);
439 }
440
441 static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
442 {
443         int rc;
444         unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
445         uint32_t mem_len   = pci_resource_len(pinfo->pdev, 2);
446         unsigned long bar0 = pci_resource_start(pinfo->pdev, 0);
447         uint32_t i2o_len   = pci_resource_len(pinfo->pdev, 0);
448
449         BCMLOG(BCMLOG_SSTEP, "bar2:0x%lx-0x%08x  bar0:0x%lx-0x%08x\n",
450                bar2, mem_len, bar0, i2o_len);
451
452         rc = check_mem_region(bar2, mem_len);
453         if (rc) {
454                 BCMLOG_ERR("No valid mem region...\n");
455                 return -ENOMEM;
456         }
457
458         pinfo->addr = ioremap_nocache(bar2, mem_len);
459         if (!pinfo->addr) {
460                 BCMLOG_ERR("Failed to remap mem region...\n");
461                 return -ENOMEM;
462         }
463
464         pinfo->pci_mem_start = bar2;
465         pinfo->pci_mem_len   = mem_len;
466
467         rc = check_mem_region(bar0, i2o_len);
468         if (rc) {
469                 BCMLOG_ERR("No valid mem region...\n");
470                 return -ENOMEM;
471         }
472
473         pinfo->i2o_addr = ioremap_nocache(bar0, i2o_len);
474         if (!pinfo->i2o_addr) {
475                 BCMLOG_ERR("Failed to remap mem region...\n");
476                 return -ENOMEM;
477         }
478
479         pinfo->pci_i2o_start = bar0;
480         pinfo->pci_i2o_len   = i2o_len;
481
482         rc = pci_request_regions(pinfo->pdev, pinfo->name);
483         if (rc < 0) {
484                 BCMLOG_ERR("Region request failed: %d\n", rc);
485                 return rc;
486         }
487
488         BCMLOG(BCMLOG_SSTEP, "Mapped addr:0x%08lx  i2o_addr:0x%08lx\n",
489                (unsigned long)pinfo->addr, (unsigned long)pinfo->i2o_addr);
490
491         return 0;
492 }
493
494 static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
495 {
496         if (!pinfo)
497                 return;
498
499         if (pinfo->addr)
500                 iounmap(pinfo->addr);
501
502         if (pinfo->i2o_addr)
503                 iounmap(pinfo->i2o_addr);
504
505         pci_release_regions(pinfo->pdev);
506 }
507
508
509 static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
510 {
511         struct crystalhd_adp *pinfo;
512         BC_STATUS sts = BC_STS_SUCCESS;
513
514         BCMLOG_ENTER;
515
516         pinfo = (struct crystalhd_adp *) pci_get_drvdata(pdev);
517         if (!pinfo) {
518                 BCMLOG_ERR("could not get adp\n");
519                 return;
520         }
521
522         sts = crystalhd_delete_cmd_context(&pinfo->cmds);
523         if (sts != BC_STS_SUCCESS)
524                 BCMLOG_ERR("cmd delete :%d \n", sts);
525
526         chd_dec_release_chdev(pinfo);
527
528         chd_dec_disable_int(pinfo);
529
530         chd_pci_release_mem(pinfo);
531         pci_disable_device(pinfo->pdev);
532
533         kfree(pinfo);
534         g_adp_info = NULL;
535 }
536
537 static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
538                              const struct pci_device_id *entry)
539 {
540         struct crystalhd_adp *pinfo;
541         int rc;
542         BC_STATUS sts = BC_STS_SUCCESS;
543
544         BCMLOG(BCMLOG_DBG, "PCI_INFO: Vendor:0x%04x Device:0x%04x "
545                "s_vendor:0x%04x s_device: 0x%04x\n",
546                pdev->vendor, pdev->device, pdev->subsystem_vendor,
547                pdev->subsystem_device);
548
549         /* FIXME: jarod: why atomic? */
550         pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_ATOMIC);
551         if (!pinfo) {
552                 BCMLOG_ERR("Failed to allocate memory\n");
553                 return -ENOMEM;
554         }
555
556         pinfo->pdev = pdev;
557
558         rc = pci_enable_device(pdev);
559         if (rc) {
560                 BCMLOG_ERR("Failed to enable PCI device\n");
561                 return rc;
562         }
563
564         snprintf(pinfo->name, 31, "crystalhd_pci_e:%d:%d:%d",
565                  pdev->bus->number, PCI_SLOT(pdev->devfn),
566                  PCI_FUNC(pdev->devfn));
567
568         rc = chd_pci_reserve_mem(pinfo);
569         if (rc) {
570                 BCMLOG_ERR("Failed to setup memory regions.\n");
571                 return -ENOMEM;
572         }
573
574         pinfo->present  = 1;
575         pinfo->drv_data = entry->driver_data;
576
577         /* Setup adapter level lock.. */
578         spin_lock_init(&pinfo->lock);
579
580         /* setup api stuff.. */
581         chd_dec_init_chdev(pinfo);
582         rc = chd_dec_enable_int(pinfo);
583         if (rc) {
584                 BCMLOG_ERR("_enable_int err:%d \n", rc);
585                 pci_disable_device(pdev);
586                 return -ENODEV;
587         }
588
589         /* Set dma mask... */
590         if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
591                 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
592                 pinfo->dmabits = 64;
593         } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
594                 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
595                 pinfo->dmabits = 32;
596         } else {
597                 BCMLOG_ERR("Unabled to setup DMA %d\n", rc);
598                 pci_disable_device(pdev);
599                 return -ENODEV;
600         }
601
602         sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo);
603         if (sts != BC_STS_SUCCESS) {
604                 BCMLOG_ERR("cmd setup :%d \n", sts);
605                 pci_disable_device(pdev);
606                 return -ENODEV;
607         }
608
609         pci_set_master(pdev);
610
611         pci_set_drvdata(pdev, pinfo);
612
613         g_adp_info = pinfo;
614
615         return 0;
616 }
617
618 #ifdef CONFIG_PM
619 int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
620 {
621         struct crystalhd_adp *adp;
622         crystalhd_ioctl_data *temp;
623         BC_STATUS sts = BC_STS_SUCCESS;
624
625         adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
626         if (!adp) {
627                 BCMLOG_ERR("could not get adp\n");
628                 return -ENODEV;
629         }
630
631         temp = chd_dec_alloc_iodata(adp, false);
632         if (!temp) {
633                 BCMLOG_ERR("could not get ioctl data\n");
634                 return -ENODEV;
635         }
636
637         sts = crystalhd_suspend(&adp->cmds, temp);
638         if (sts != BC_STS_SUCCESS) {
639                 BCMLOG_ERR("BCM70012 Suspend %d\n", sts);
640                 return -ENODEV;
641         }
642
643         chd_dec_free_iodata(adp, temp, false);
644         chd_dec_disable_int(adp);
645         pci_save_state(pdev);
646
647         /* Disable IO/bus master/irq router */
648         pci_disable_device(pdev);
649         pci_set_power_state(pdev, pci_choose_state(pdev, state));
650         return 0;
651 }
652
653 int chd_dec_pci_resume(struct pci_dev *pdev)
654 {
655         struct crystalhd_adp *adp;
656         BC_STATUS sts = BC_STS_SUCCESS;
657         int rc;
658
659         adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
660         if (!adp) {
661                 BCMLOG_ERR("could not get adp\n");
662                 return -ENODEV;
663         }
664
665         pci_set_power_state(pdev, PCI_D0);
666         pci_restore_state(pdev);
667
668         /* device's irq possibly is changed, driver should take care */
669         if (pci_enable_device(pdev)) {
670                 BCMLOG_ERR("Failed to enable PCI device\n");
671                 return 1;
672         }
673
674         pci_set_master(pdev);
675
676         rc = chd_dec_enable_int(adp);
677         if (rc) {
678                 BCMLOG_ERR("_enable_int err:%d \n", rc);
679                 pci_disable_device(pdev);
680                 return -ENODEV;
681         }
682
683         sts = crystalhd_resume(&adp->cmds);
684         if (sts != BC_STS_SUCCESS) {
685                 BCMLOG_ERR("BCM70012 Resume %d\n", sts);
686                 pci_disable_device(pdev);
687                 return -ENODEV;
688         }
689
690         return 0;
691 }
692 #endif
693
694 static DEFINE_PCI_DEVICE_TABLE(chd_dec_pci_id_table) = {
695         { PCI_VDEVICE(BROADCOM, 0x1612), 8 },
696         { 0, },
697 };
698 MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
699
700 static struct pci_driver bc_chd_70012_driver = {
701         .name     = "Broadcom 70012 Decoder",
702         .probe    = chd_dec_pci_probe,
703         .remove   = __devexit_p(chd_dec_pci_remove),
704         .id_table = chd_dec_pci_id_table,
705 #ifdef CONFIG_PM
706         .suspend  = chd_dec_pci_suspend,
707         .resume   = chd_dec_pci_resume
708 #endif
709 };
710
711 void chd_set_log_level(struct crystalhd_adp *adp, char *arg)
712 {
713         if ((!arg) || (strlen(arg) < 3))
714                 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA;
715         else if (!strncmp(arg, "sstep", 5))
716                 g_linklog_level = BCMLOG_INFO | BCMLOG_DATA | BCMLOG_DBG |
717                                   BCMLOG_SSTEP | BCMLOG_ERROR;
718         else if (!strncmp(arg, "info", 4))
719                 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO;
720         else if (!strncmp(arg, "debug", 5))
721                 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO |
722                                   BCMLOG_DBG;
723         else if (!strncmp(arg, "pball", 5))
724                 g_linklog_level = 0xFFFFFFFF & ~(BCMLOG_SPINLOCK);
725         else if (!strncmp(arg, "silent", 6))
726                 g_linklog_level = 0;
727         else
728                 g_linklog_level = 0;
729 }
730
731 struct crystalhd_adp *chd_get_adp(void)
732 {
733         return g_adp_info;
734 }
735
736 static int __init chd_dec_module_init(void)
737 {
738         int rc;
739
740         chd_set_log_level(NULL, "debug");
741         BCMLOG(BCMLOG_DATA, "Loading crystalhd %d.%d.%d \n",
742                crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
743
744         rc = pci_register_driver(&bc_chd_70012_driver);
745
746         if (rc < 0)
747                 BCMLOG_ERR("Could not find any devices. err:%d \n", rc);
748
749         return rc;
750 }
751 module_init(chd_dec_module_init);
752
753 static void __exit chd_dec_module_cleanup(void)
754 {
755         BCMLOG(BCMLOG_DATA, "unloading crystalhd %d.%d.%d \n",
756                crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
757
758         pci_unregister_driver(&bc_chd_70012_driver);
759 }
760 module_exit(chd_dec_module_cleanup);
761
762 MODULE_AUTHOR("Naren Sankar <nsankar@broadcom.com>");
763 MODULE_AUTHOR("Prasad Bolisetty <prasadb@broadcom.com>");
764 MODULE_DESCRIPTION(CRYSTAL_HD_NAME);
765 MODULE_LICENSE("GPL");
766 MODULE_ALIAS("bcm70012");