aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pxa3xx-gcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pxa3xx-gcu.c')
-rw-r--r--drivers/video/pxa3xx-gcu.c191
1 files changed, 81 insertions, 110 deletions
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index ad382b3396cd..417f9a27eb7d 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -107,7 +107,6 @@ struct pxa3xx_gcu_priv {
107 struct timeval base_time; 107 struct timeval base_time;
108 108
109 struct pxa3xx_gcu_batch *free; 109 struct pxa3xx_gcu_batch *free;
110
111 struct pxa3xx_gcu_batch *ready; 110 struct pxa3xx_gcu_batch *ready;
112 struct pxa3xx_gcu_batch *ready_last; 111 struct pxa3xx_gcu_batch *ready_last;
113 struct pxa3xx_gcu_batch *running; 112 struct pxa3xx_gcu_batch *running;
@@ -368,27 +367,35 @@ pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
368 367
369/* Misc device layer */ 368/* Misc device layer */
370 369
371static inline struct pxa3xx_gcu_priv *file_dev(struct file *file) 370static inline struct pxa3xx_gcu_priv *to_pxa3xx_gcu_priv(struct file *file)
372{ 371{
373 struct miscdevice *dev = file->private_data; 372 struct miscdevice *dev = file->private_data;
374 return container_of(dev, struct pxa3xx_gcu_priv, misc_dev); 373 return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
375} 374}
376 375
376/*
377 * provide an empty .open callback, so the core sets file->private_data
378 * for us.
379 */
380static int pxa3xx_gcu_open(struct inode *inode, struct file *file)
381{
382 return 0;
383}
384
377static ssize_t 385static ssize_t
378pxa3xx_gcu_misc_write(struct file *file, const char *buff, 386pxa3xx_gcu_write(struct file *file, const char *buff,
379 size_t count, loff_t *offp) 387 size_t count, loff_t *offp)
380{ 388{
381 int ret; 389 int ret;
382 unsigned long flags; 390 unsigned long flags;
383 struct pxa3xx_gcu_batch *buffer; 391 struct pxa3xx_gcu_batch *buffer;
384 struct pxa3xx_gcu_priv *priv = file_dev(file); 392 struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
385 393
386 int words = count / 4; 394 int words = count / 4;
387 395
388 /* Does not need to be atomic. There's a lock in user space, 396 /* Does not need to be atomic. There's a lock in user space,
389 * but anyhow, this is just for statistics. */ 397 * but anyhow, this is just for statistics. */
390 priv->shared->num_writes++; 398 priv->shared->num_writes++;
391
392 priv->shared->num_words += words; 399 priv->shared->num_words += words;
393 400
394 /* Last word reserved for batch buffer end command */ 401 /* Last word reserved for batch buffer end command */
@@ -406,10 +413,8 @@ pxa3xx_gcu_misc_write(struct file *file, const char *buff,
406 * Get buffer from free list 413 * Get buffer from free list
407 */ 414 */
408 spin_lock_irqsave(&priv->spinlock, flags); 415 spin_lock_irqsave(&priv->spinlock, flags);
409
410 buffer = priv->free; 416 buffer = priv->free;
411 priv->free = buffer->next; 417 priv->free = buffer->next;
412
413 spin_unlock_irqrestore(&priv->spinlock, flags); 418 spin_unlock_irqrestore(&priv->spinlock, flags);
414 419
415 420
@@ -454,10 +459,10 @@ pxa3xx_gcu_misc_write(struct file *file, const char *buff,
454 459
455 460
456static long 461static long
457pxa3xx_gcu_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 462pxa3xx_gcu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
458{ 463{
459 unsigned long flags; 464 unsigned long flags;
460 struct pxa3xx_gcu_priv *priv = file_dev(file); 465 struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
461 466
462 switch (cmd) { 467 switch (cmd) {
463 case PXA3XX_GCU_IOCTL_RESET: 468 case PXA3XX_GCU_IOCTL_RESET:
@@ -474,10 +479,10 @@ pxa3xx_gcu_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
474} 479}
475 480
476static int 481static int
477pxa3xx_gcu_misc_mmap(struct file *file, struct vm_area_struct *vma) 482pxa3xx_gcu_mmap(struct file *file, struct vm_area_struct *vma)
478{ 483{
479 unsigned int size = vma->vm_end - vma->vm_start; 484 unsigned int size = vma->vm_end - vma->vm_start;
480 struct pxa3xx_gcu_priv *priv = file_dev(file); 485 struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
481 486
482 switch (vma->vm_pgoff) { 487 switch (vma->vm_pgoff) {
483 case 0: 488 case 0:
@@ -532,8 +537,8 @@ static inline void pxa3xx_gcu_init_debug_timer(void) {}
532#endif 537#endif
533 538
534static int 539static int
535add_buffer(struct platform_device *dev, 540pxa3xx_gcu_add_buffer(struct device *dev,
536 struct pxa3xx_gcu_priv *priv) 541 struct pxa3xx_gcu_priv *priv)
537{ 542{
538 struct pxa3xx_gcu_batch *buffer; 543 struct pxa3xx_gcu_batch *buffer;
539 544
@@ -541,7 +546,7 @@ add_buffer(struct platform_device *dev,
541 if (!buffer) 546 if (!buffer)
542 return -ENOMEM; 547 return -ENOMEM;
543 548
544 buffer->ptr = dma_alloc_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4, 549 buffer->ptr = dma_alloc_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
545 &buffer->phys, GFP_KERNEL); 550 &buffer->phys, GFP_KERNEL);
546 if (!buffer->ptr) { 551 if (!buffer->ptr) {
547 kfree(buffer); 552 kfree(buffer);
@@ -549,57 +554,49 @@ add_buffer(struct platform_device *dev,
549 } 554 }
550 555
551 buffer->next = priv->free; 556 buffer->next = priv->free;
552
553 priv->free = buffer; 557 priv->free = buffer;
554 558
555 return 0; 559 return 0;
556} 560}
557 561
558static void 562static void
559free_buffers(struct platform_device *dev, 563pxa3xx_gcu_free_buffers(struct device *dev,
560 struct pxa3xx_gcu_priv *priv) 564 struct pxa3xx_gcu_priv *priv)
561{ 565{
562 struct pxa3xx_gcu_batch *next, *buffer = priv->free; 566 struct pxa3xx_gcu_batch *next, *buffer = priv->free;
563 567
564 while (buffer) { 568 while (buffer) {
565 next = buffer->next; 569 next = buffer->next;
566 570
567 dma_free_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4, 571 dma_free_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
568 buffer->ptr, buffer->phys); 572 buffer->ptr, buffer->phys);
569 573
570 kfree(buffer); 574 kfree(buffer);
571
572 buffer = next; 575 buffer = next;
573 } 576 }
574 577
575 priv->free = NULL; 578 priv->free = NULL;
576} 579}
577 580
578static const struct file_operations misc_fops = { 581static const struct file_operations pxa3xx_gcu_miscdev_fops = {
579 .owner = THIS_MODULE, 582 .owner = THIS_MODULE,
580 .write = pxa3xx_gcu_misc_write, 583 .open = pxa3xx_gcu_open,
581 .unlocked_ioctl = pxa3xx_gcu_misc_ioctl, 584 .write = pxa3xx_gcu_write,
582 .mmap = pxa3xx_gcu_misc_mmap 585 .unlocked_ioctl = pxa3xx_gcu_ioctl,
586 .mmap = pxa3xx_gcu_mmap,
583}; 587};
584 588
585static int pxa3xx_gcu_probe(struct platform_device *dev) 589static int pxa3xx_gcu_probe(struct platform_device *pdev)
586{ 590{
587 int i, ret, irq; 591 int i, ret, irq;
588 struct resource *r; 592 struct resource *r;
589 struct pxa3xx_gcu_priv *priv; 593 struct pxa3xx_gcu_priv *priv;
594 struct device *dev = &pdev->dev;
590 595
591 priv = kzalloc(sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL); 596 priv = devm_kzalloc(dev, sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
592 if (!priv) 597 if (!priv)
593 return -ENOMEM; 598 return -ENOMEM;
594 599
595 for (i = 0; i < 8; i++) {
596 ret = add_buffer(dev, priv);
597 if (ret) {
598 dev_err(&dev->dev, "failed to allocate DMA memory\n");
599 goto err_free_priv;
600 }
601 }
602
603 init_waitqueue_head(&priv->wait_idle); 600 init_waitqueue_head(&priv->wait_idle);
604 init_waitqueue_head(&priv->wait_free); 601 init_waitqueue_head(&priv->wait_free);
605 spin_lock_init(&priv->spinlock); 602 spin_lock_init(&priv->spinlock);
@@ -611,125 +608,99 @@ static int pxa3xx_gcu_probe(struct platform_device *dev)
611 608
612 priv->misc_dev.minor = MISCDEV_MINOR, 609 priv->misc_dev.minor = MISCDEV_MINOR,
613 priv->misc_dev.name = DRV_NAME, 610 priv->misc_dev.name = DRV_NAME,
614 priv->misc_dev.fops = &misc_fops, 611 priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops;
615 612
616 /* register misc device */ 613 /* handle IO resources */
617 ret = misc_register(&priv->misc_dev); 614 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
618 if (ret < 0) { 615 priv->mmio_base = devm_request_and_ioremap(dev, r);
619 dev_err(&dev->dev, "misc_register() for minor %d failed\n", 616 if (IS_ERR(priv->mmio_base)) {
620 MISCDEV_MINOR); 617 dev_err(dev, "failed to map I/O memory\n");
621 goto err_free_priv; 618 return PTR_ERR(priv->mmio_base);
622 } 619 }
623 620
624 /* handle IO resources */ 621 /* enable the clock */
625 r = platform_get_resource(dev, IORESOURCE_MEM, 0); 622 priv->clk = devm_clk_get(dev, NULL);
626 if (r == NULL) { 623 if (IS_ERR(priv->clk)) {
627 dev_err(&dev->dev, "no I/O memory resource defined\n"); 624 dev_err(dev, "failed to get clock\n");
628 ret = -ENODEV; 625 return PTR_ERR(priv->clk);
629 goto err_misc_deregister;
630 } 626 }
631 627
632 if (!request_mem_region(r->start, resource_size(r), dev->name)) { 628 /* request the IRQ */
633 dev_err(&dev->dev, "failed to request I/O memory\n"); 629 irq = platform_get_irq(pdev, 0);
634 ret = -EBUSY; 630 if (irq < 0) {
635 goto err_misc_deregister; 631 dev_err(dev, "no IRQ defined\n");
632 return -ENODEV;
636 } 633 }
637 634
638 priv->mmio_base = ioremap_nocache(r->start, resource_size(r)); 635 ret = devm_request_irq(dev, irq, pxa3xx_gcu_handle_irq,
639 if (!priv->mmio_base) { 636 0, DRV_NAME, priv);
640 dev_err(&dev->dev, "failed to map I/O memory\n"); 637 if (ret < 0) {
641 ret = -EBUSY; 638 dev_err(dev, "request_irq failed\n");
642 goto err_free_mem_region; 639 return ret;
643 } 640 }
644 641
645 /* allocate dma memory */ 642 /* allocate dma memory */
646 priv->shared = dma_alloc_coherent(&dev->dev, SHARED_SIZE, 643 priv->shared = dma_alloc_coherent(dev, SHARED_SIZE,
647 &priv->shared_phys, GFP_KERNEL); 644 &priv->shared_phys, GFP_KERNEL);
648
649 if (!priv->shared) { 645 if (!priv->shared) {
650 dev_err(&dev->dev, "failed to allocate DMA memory\n"); 646 dev_err(dev, "failed to allocate DMA memory\n");
651 ret = -ENOMEM; 647 return -ENOMEM;
652 goto err_free_io;
653 } 648 }
654 649
655 /* enable the clock */ 650 /* register misc device */
656 priv->clk = clk_get(&dev->dev, NULL); 651 ret = misc_register(&priv->misc_dev);
657 if (IS_ERR(priv->clk)) { 652 if (ret < 0) {
658 dev_err(&dev->dev, "failed to get clock\n"); 653 dev_err(dev, "misc_register() for minor %d failed\n",
659 ret = -ENODEV; 654 MISCDEV_MINOR);
660 goto err_free_dma; 655 goto err_free_dma;
661 } 656 }
662 657
663 ret = clk_enable(priv->clk); 658 ret = clk_enable(priv->clk);
664 if (ret < 0) { 659 if (ret < 0) {
665 dev_err(&dev->dev, "failed to enable clock\n"); 660 dev_err(dev, "failed to enable clock\n");
666 goto err_put_clk; 661 goto err_misc_deregister;
667 }
668
669 /* request the IRQ */
670 irq = platform_get_irq(dev, 0);
671 if (irq < 0) {
672 dev_err(&dev->dev, "no IRQ defined\n");
673 ret = -ENODEV;
674 goto err_put_clk;
675 } 662 }
676 663
677 ret = request_irq(irq, pxa3xx_gcu_handle_irq, 664 for (i = 0; i < 8; i++) {
678 0, DRV_NAME, priv); 665 ret = pxa3xx_gcu_add_buffer(dev, priv);
679 if (ret) { 666 if (ret) {
680 dev_err(&dev->dev, "request_irq failed\n"); 667 dev_err(dev, "failed to allocate DMA memory\n");
681 ret = -EBUSY; 668 goto err_disable_clk;
682 goto err_put_clk; 669 }
683 } 670 }
684 671
685 platform_set_drvdata(dev, priv); 672 platform_set_drvdata(pdev, priv);
686 priv->resource_mem = r; 673 priv->resource_mem = r;
687 pxa3xx_gcu_reset(priv); 674 pxa3xx_gcu_reset(priv);
688 pxa3xx_gcu_init_debug_timer(); 675 pxa3xx_gcu_init_debug_timer();
689 676
690 dev_info(&dev->dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n", 677 dev_info(dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
691 (void *) r->start, (void *) priv->shared_phys, 678 (void *) r->start, (void *) priv->shared_phys,
692 SHARED_SIZE, irq); 679 SHARED_SIZE, irq);
693 return 0; 680 return 0;
694 681
695err_put_clk:
696 clk_disable(priv->clk);
697 clk_put(priv->clk);
698
699err_free_dma: 682err_free_dma:
700 dma_free_coherent(&dev->dev, SHARED_SIZE, 683 dma_free_coherent(dev, SHARED_SIZE,
701 priv->shared, priv->shared_phys); 684 priv->shared, priv->shared_phys);
702 685
703err_free_io:
704 iounmap(priv->mmio_base);
705
706err_free_mem_region:
707 release_mem_region(r->start, resource_size(r));
708
709err_misc_deregister: 686err_misc_deregister:
710 misc_deregister(&priv->misc_dev); 687 misc_deregister(&priv->misc_dev);
711 688
712err_free_priv: 689err_disable_clk:
713 free_buffers(dev, priv); 690 clk_disable(priv->clk);
714 kfree(priv); 691
715 return ret; 692 return ret;
716} 693}
717 694
718static int pxa3xx_gcu_remove(struct platform_device *dev) 695static int pxa3xx_gcu_remove(struct platform_device *pdev)
719{ 696{
720 struct pxa3xx_gcu_priv *priv = platform_get_drvdata(dev); 697 struct pxa3xx_gcu_priv *priv = platform_get_drvdata(pdev);
721 struct resource *r = priv->resource_mem; 698 struct device *dev = &pdev->dev;
722 699
723 pxa3xx_gcu_wait_idle(priv); 700 pxa3xx_gcu_wait_idle(priv);
724
725 misc_deregister(&priv->misc_dev); 701 misc_deregister(&priv->misc_dev);
726 dma_free_coherent(&dev->dev, SHARED_SIZE, 702 dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys);
727 priv->shared, priv->shared_phys); 703 pxa3xx_gcu_free_buffers(dev, priv);
728 iounmap(priv->mmio_base);
729 release_mem_region(r->start, resource_size(r));
730 clk_disable(priv->clk);
731 free_buffers(dev, priv);
732 kfree(priv);
733 704
734 return 0; 705 return 0;
735} 706}