diff options
Diffstat (limited to 'drivers/media/video/s5p-g2d/g2d.c')
-rw-r--r-- | drivers/media/video/s5p-g2d/g2d.c | 63 |
1 files changed, 50 insertions, 13 deletions
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c index febaa673d363..789de74014e5 100644 --- a/drivers/media/video/s5p-g2d/g2d.c +++ b/drivers/media/video/s5p-g2d/g2d.c | |||
@@ -178,6 +178,9 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) | |||
178 | { | 178 | { |
179 | struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, | 179 | struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, |
180 | ctrl_handler); | 180 | ctrl_handler); |
181 | unsigned long flags; | ||
182 | |||
183 | spin_lock_irqsave(&ctx->dev->ctrl_lock, flags); | ||
181 | switch (ctrl->id) { | 184 | switch (ctrl->id) { |
182 | case V4L2_CID_COLORFX: | 185 | case V4L2_CID_COLORFX: |
183 | if (ctrl->val == V4L2_COLORFX_NEGATIVE) | 186 | if (ctrl->val == V4L2_COLORFX_NEGATIVE) |
@@ -185,10 +188,13 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) | |||
185 | else | 188 | else |
186 | ctx->rop = ROP4_COPY; | 189 | ctx->rop = ROP4_COPY; |
187 | break; | 190 | break; |
188 | default: | 191 | |
189 | v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); | 192 | case V4L2_CID_HFLIP: |
190 | return -EINVAL; | 193 | ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1); |
194 | break; | ||
195 | |||
191 | } | 196 | } |
197 | spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); | ||
192 | return 0; | 198 | return 0; |
193 | } | 199 | } |
194 | 200 | ||
@@ -200,11 +206,13 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) | |||
200 | { | 206 | { |
201 | struct g2d_dev *dev = ctx->dev; | 207 | struct g2d_dev *dev = ctx->dev; |
202 | 208 | ||
203 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); | 209 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); |
204 | if (ctx->ctrl_handler.error) { | 210 | |
205 | v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); | 211 | ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, |
206 | return ctx->ctrl_handler.error; | 212 | V4L2_CID_HFLIP, 0, 1, 1, 0); |
207 | } | 213 | |
214 | ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, | ||
215 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
208 | 216 | ||
209 | v4l2_ctrl_new_std_menu( | 217 | v4l2_ctrl_new_std_menu( |
210 | &ctx->ctrl_handler, | 218 | &ctx->ctrl_handler, |
@@ -215,10 +223,14 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) | |||
215 | V4L2_COLORFX_NONE); | 223 | V4L2_COLORFX_NONE); |
216 | 224 | ||
217 | if (ctx->ctrl_handler.error) { | 225 | if (ctx->ctrl_handler.error) { |
218 | v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); | 226 | int err = ctx->ctrl_handler.error; |
219 | return ctx->ctrl_handler.error; | 227 | v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n"); |
228 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | ||
229 | return err; | ||
220 | } | 230 | } |
221 | 231 | ||
232 | v4l2_ctrl_cluster(2, &ctx->ctrl_hflip); | ||
233 | |||
222 | return 0; | 234 | return 0; |
223 | } | 235 | } |
224 | 236 | ||
@@ -547,6 +559,7 @@ static void device_run(void *prv) | |||
547 | struct g2d_ctx *ctx = prv; | 559 | struct g2d_ctx *ctx = prv; |
548 | struct g2d_dev *dev = ctx->dev; | 560 | struct g2d_dev *dev = ctx->dev; |
549 | struct vb2_buffer *src, *dst; | 561 | struct vb2_buffer *src, *dst; |
562 | unsigned long flags; | ||
550 | u32 cmd = 0; | 563 | u32 cmd = 0; |
551 | 564 | ||
552 | dev->curr = ctx; | 565 | dev->curr = ctx; |
@@ -557,6 +570,8 @@ static void device_run(void *prv) | |||
557 | clk_enable(dev->gate); | 570 | clk_enable(dev->gate); |
558 | g2d_reset(dev); | 571 | g2d_reset(dev); |
559 | 572 | ||
573 | spin_lock_irqsave(&dev->ctrl_lock, flags); | ||
574 | |||
560 | g2d_set_src_size(dev, &ctx->in); | 575 | g2d_set_src_size(dev, &ctx->in); |
561 | g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); | 576 | g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); |
562 | 577 | ||
@@ -564,11 +579,15 @@ static void device_run(void *prv) | |||
564 | g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); | 579 | g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); |
565 | 580 | ||
566 | g2d_set_rop4(dev, ctx->rop); | 581 | g2d_set_rop4(dev, ctx->rop); |
582 | g2d_set_flip(dev, ctx->flip); | ||
583 | |||
567 | if (ctx->in.c_width != ctx->out.c_width || | 584 | if (ctx->in.c_width != ctx->out.c_width || |
568 | ctx->in.c_height != ctx->out.c_height) | 585 | ctx->in.c_height != ctx->out.c_height) |
569 | cmd |= g2d_cmd_stretch(1); | 586 | cmd |= g2d_cmd_stretch(1); |
570 | g2d_set_cmd(dev, cmd); | 587 | g2d_set_cmd(dev, cmd); |
571 | g2d_start(dev); | 588 | g2d_start(dev); |
589 | |||
590 | spin_unlock_irqrestore(&dev->ctrl_lock, flags); | ||
572 | } | 591 | } |
573 | 592 | ||
574 | static irqreturn_t g2d_isr(int irq, void *prv) | 593 | static irqreturn_t g2d_isr(int irq, void *prv) |
@@ -658,7 +677,7 @@ static int g2d_probe(struct platform_device *pdev) | |||
658 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 677 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
659 | if (!dev) | 678 | if (!dev) |
660 | return -ENOMEM; | 679 | return -ENOMEM; |
661 | spin_lock_init(&dev->irqlock); | 680 | spin_lock_init(&dev->ctrl_lock); |
662 | mutex_init(&dev->mutex); | 681 | mutex_init(&dev->mutex); |
663 | atomic_set(&dev->num_inst, 0); | 682 | atomic_set(&dev->num_inst, 0); |
664 | init_waitqueue_head(&dev->irq_queue); | 683 | init_waitqueue_head(&dev->irq_queue); |
@@ -693,18 +712,30 @@ static int g2d_probe(struct platform_device *pdev) | |||
693 | goto unmap_regs; | 712 | goto unmap_regs; |
694 | } | 713 | } |
695 | 714 | ||
715 | ret = clk_prepare(dev->clk); | ||
716 | if (ret) { | ||
717 | dev_err(&pdev->dev, "failed to prepare g2d clock\n"); | ||
718 | goto put_clk; | ||
719 | } | ||
720 | |||
696 | dev->gate = clk_get(&pdev->dev, "fimg2d"); | 721 | dev->gate = clk_get(&pdev->dev, "fimg2d"); |
697 | if (IS_ERR_OR_NULL(dev->gate)) { | 722 | if (IS_ERR_OR_NULL(dev->gate)) { |
698 | dev_err(&pdev->dev, "failed to get g2d clock gate\n"); | 723 | dev_err(&pdev->dev, "failed to get g2d clock gate\n"); |
699 | ret = -ENXIO; | 724 | ret = -ENXIO; |
700 | goto put_clk; | 725 | goto unprep_clk; |
726 | } | ||
727 | |||
728 | ret = clk_prepare(dev->gate); | ||
729 | if (ret) { | ||
730 | dev_err(&pdev->dev, "failed to prepare g2d clock gate\n"); | ||
731 | goto put_clk_gate; | ||
701 | } | 732 | } |
702 | 733 | ||
703 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 734 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
704 | if (!res) { | 735 | if (!res) { |
705 | dev_err(&pdev->dev, "failed to find IRQ\n"); | 736 | dev_err(&pdev->dev, "failed to find IRQ\n"); |
706 | ret = -ENXIO; | 737 | ret = -ENXIO; |
707 | goto put_clk_gate; | 738 | goto unprep_clk_gate; |
708 | } | 739 | } |
709 | 740 | ||
710 | dev->irq = res->start; | 741 | dev->irq = res->start; |
@@ -764,8 +795,12 @@ alloc_ctx_cleanup: | |||
764 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | 795 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); |
765 | rel_irq: | 796 | rel_irq: |
766 | free_irq(dev->irq, dev); | 797 | free_irq(dev->irq, dev); |
798 | unprep_clk_gate: | ||
799 | clk_unprepare(dev->gate); | ||
767 | put_clk_gate: | 800 | put_clk_gate: |
768 | clk_put(dev->gate); | 801 | clk_put(dev->gate); |
802 | unprep_clk: | ||
803 | clk_unprepare(dev->clk); | ||
769 | put_clk: | 804 | put_clk: |
770 | clk_put(dev->clk); | 805 | clk_put(dev->clk); |
771 | unmap_regs: | 806 | unmap_regs: |
@@ -787,7 +822,9 @@ static int g2d_remove(struct platform_device *pdev) | |||
787 | v4l2_device_unregister(&dev->v4l2_dev); | 822 | v4l2_device_unregister(&dev->v4l2_dev); |
788 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | 823 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); |
789 | free_irq(dev->irq, dev); | 824 | free_irq(dev->irq, dev); |
825 | clk_unprepare(dev->gate); | ||
790 | clk_put(dev->gate); | 826 | clk_put(dev->gate); |
827 | clk_unprepare(dev->clk); | ||
791 | clk_put(dev->clk); | 828 | clk_put(dev->clk); |
792 | iounmap(dev->regs); | 829 | iounmap(dev->regs); |
793 | release_resource(dev->res_regs); | 830 | release_resource(dev->res_regs); |