aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-02-14 11:23:46 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-08 05:41:43 -0500
commita1212162f493852e4becb7abf55f78d17872d8a8 (patch)
treea1d92507d42deafff0e89da0a7fa28d79cc20e86 /drivers/media/video/s5p-fimc
parentf9331d115dadd4e63619ebb47960ec2b7d253700 (diff)
[media] s5p-csis: Convert to the device managed resources
The devm_* functions are used in the platform device probe() for data that is freed on driver removal. The managed device layer takes care of undoing actions taken in the probe callback() and freeing resources on driver detach. This eliminates the need for manually releasing resources and simplifies error handling. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/s5p-fimc')
-rw-r--r--drivers/media/video/s5p-fimc/mipi-csis.c81
1 files changed, 24 insertions, 57 deletions
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c
index 58c40750abc2..a903138b18da 100644
--- a/drivers/media/video/s5p-fimc/mipi-csis.c
+++ b/drivers/media/video/s5p-fimc/mipi-csis.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver 2 * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
3 * 3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd. 4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
5 * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com> 5 * Sylwester Nawrocki, <s.nawrocki@samsung.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -100,7 +100,6 @@ enum {
100 * @pads: CSIS pads array 100 * @pads: CSIS pads array
101 * @sd: v4l2_subdev associated with CSIS device instance 101 * @sd: v4l2_subdev associated with CSIS device instance
102 * @pdev: CSIS platform device 102 * @pdev: CSIS platform device
103 * @regs_res: requested I/O register memory resource
104 * @regs: mmaped I/O registers memory 103 * @regs: mmaped I/O registers memory
105 * @clock: CSIS clocks 104 * @clock: CSIS clocks
106 * @irq: requested s5p-mipi-csis irq number 105 * @irq: requested s5p-mipi-csis irq number
@@ -113,7 +112,6 @@ struct csis_state {
113 struct media_pad pads[CSIS_PADS_NUM]; 112 struct media_pad pads[CSIS_PADS_NUM];
114 struct v4l2_subdev sd; 113 struct v4l2_subdev sd;
115 struct platform_device *pdev; 114 struct platform_device *pdev;
116 struct resource *regs_res;
117 void __iomem *regs; 115 void __iomem *regs;
118 struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; 116 struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
119 struct clk *clock[NUM_CSIS_CLOCKS]; 117 struct clk *clock[NUM_CSIS_CLOCKS];
@@ -490,12 +488,11 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
490{ 488{
491 struct s5p_platform_mipi_csis *pdata; 489 struct s5p_platform_mipi_csis *pdata;
492 struct resource *mem_res; 490 struct resource *mem_res;
493 struct resource *regs_res;
494 struct csis_state *state; 491 struct csis_state *state;
495 int ret = -ENOMEM; 492 int ret = -ENOMEM;
496 int i; 493 int i;
497 494
498 state = kzalloc(sizeof(*state), GFP_KERNEL); 495 state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
499 if (!state) 496 if (!state)
500 return -ENOMEM; 497 return -ENOMEM;
501 498
@@ -505,52 +502,27 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
505 pdata = pdev->dev.platform_data; 502 pdata = pdev->dev.platform_data;
506 if (pdata == NULL || pdata->phy_enable == NULL) { 503 if (pdata == NULL || pdata->phy_enable == NULL) {
507 dev_err(&pdev->dev, "Platform data not fully specified\n"); 504 dev_err(&pdev->dev, "Platform data not fully specified\n");
508 goto e_free; 505 return -EINVAL;
509 } 506 }
510 507
511 if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || 508 if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
512 pdata->lanes > CSIS0_MAX_LANES) { 509 pdata->lanes > CSIS0_MAX_LANES) {
513 ret = -EINVAL;
514 dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", 510 dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
515 pdata->lanes); 511 pdata->lanes);
516 goto e_free; 512 return -EINVAL;
517 } 513 }
518 514
519 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 515 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
520 if (!mem_res) { 516 state->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
521 dev_err(&pdev->dev, "Failed to get IO memory region\n"); 517 if (state->regs == NULL) {
522 goto e_free; 518 dev_err(&pdev->dev, "Failed to request and remap io memory\n");
523 } 519 return -ENXIO;
524
525 regs_res = request_mem_region(mem_res->start, resource_size(mem_res),
526 pdev->name);
527 if (!regs_res) {
528 dev_err(&pdev->dev, "Failed to request IO memory region\n");
529 goto e_free;
530 } 520 }
531 state->regs_res = regs_res;
532
533 state->regs = ioremap(mem_res->start, resource_size(mem_res));
534 if (!state->regs) {
535 dev_err(&pdev->dev, "Failed to remap IO region\n");
536 goto e_reqmem;
537 }
538
539 ret = s5pcsis_clk_get(state);
540 if (ret)
541 goto e_unmap;
542
543 clk_enable(state->clock[CSIS_CLK_MUX]);
544 if (pdata->clk_rate)
545 clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate);
546 else
547 dev_WARN(&pdev->dev, "No clock frequency specified!\n");
548 521
549 state->irq = platform_get_irq(pdev, 0); 522 state->irq = platform_get_irq(pdev, 0);
550 if (state->irq < 0) { 523 if (state->irq < 0) {
551 ret = state->irq;
552 dev_err(&pdev->dev, "Failed to get irq\n"); 524 dev_err(&pdev->dev, "Failed to get irq\n");
553 goto e_clkput; 525 return state->irq;
554 } 526 }
555 527
556 for (i = 0; i < CSIS_NUM_SUPPLIES; i++) 528 for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
@@ -559,12 +531,22 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
559 ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, 531 ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
560 state->supplies); 532 state->supplies);
561 if (ret) 533 if (ret)
534 return ret;
535
536 ret = s5pcsis_clk_get(state);
537 if (ret)
562 goto e_clkput; 538 goto e_clkput;
563 539
564 ret = request_irq(state->irq, s5pcsis_irq_handler, 0, 540 clk_enable(state->clock[CSIS_CLK_MUX]);
565 dev_name(&pdev->dev), state); 541 if (pdata->clk_rate)
542 clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate);
543 else
544 dev_WARN(&pdev->dev, "No clock frequency specified!\n");
545
546 ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler,
547 0, dev_name(&pdev->dev), state);
566 if (ret) { 548 if (ret) {
567 dev_err(&pdev->dev, "request_irq failed\n"); 549 dev_err(&pdev->dev, "Interrupt request failed\n");
568 goto e_regput; 550 goto e_regput;
569 } 551 }
570 552
@@ -583,7 +565,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
583 ret = media_entity_init(&state->sd.entity, 565 ret = media_entity_init(&state->sd.entity,
584 CSIS_PADS_NUM, state->pads, 0); 566 CSIS_PADS_NUM, state->pads, 0);
585 if (ret < 0) 567 if (ret < 0)
586 goto e_irqfree; 568 goto e_clkput;
587 569
588 /* This allows to retrieve the platform device id by the host driver */ 570 /* This allows to retrieve the platform device id by the host driver */
589 v4l2_set_subdevdata(&state->sd, pdev); 571 v4l2_set_subdevdata(&state->sd, pdev);
@@ -592,22 +574,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
592 platform_set_drvdata(pdev, &state->sd); 574 platform_set_drvdata(pdev, &state->sd);
593 575
594 pm_runtime_enable(&pdev->dev); 576 pm_runtime_enable(&pdev->dev);
595
596 return 0; 577 return 0;
597 578
598e_irqfree:
599 free_irq(state->irq, state);
600e_regput: 579e_regput:
601 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); 580 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
602e_clkput: 581e_clkput:
603 clk_disable(state->clock[CSIS_CLK_MUX]); 582 clk_disable(state->clock[CSIS_CLK_MUX]);
604 s5pcsis_clk_put(state); 583 s5pcsis_clk_put(state);
605e_unmap:
606 iounmap(state->regs);
607e_reqmem:
608 release_mem_region(regs_res->start, resource_size(regs_res));
609e_free:
610 kfree(state);
611 return ret; 584 return ret;
612} 585}
613 586
@@ -709,21 +682,15 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev)
709{ 682{
710 struct v4l2_subdev *sd = platform_get_drvdata(pdev); 683 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
711 struct csis_state *state = sd_to_csis_state(sd); 684 struct csis_state *state = sd_to_csis_state(sd);
712 struct resource *res = state->regs_res;
713 685
714 pm_runtime_disable(&pdev->dev); 686 pm_runtime_disable(&pdev->dev);
715 s5pcsis_suspend(&pdev->dev); 687 s5pcsis_suspend(&pdev->dev);
716 clk_disable(state->clock[CSIS_CLK_MUX]); 688 clk_disable(state->clock[CSIS_CLK_MUX]);
717 pm_runtime_set_suspended(&pdev->dev); 689 pm_runtime_set_suspended(&pdev->dev);
718
719 s5pcsis_clk_put(state); 690 s5pcsis_clk_put(state);
720 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); 691 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
721 692
722 media_entity_cleanup(&state->sd.entity); 693 media_entity_cleanup(&state->sd.entity);
723 free_irq(state->irq, state);
724 iounmap(state->regs);
725 release_mem_region(res->start, resource_size(res));
726 kfree(state);
727 694
728 return 0; 695 return 0;
729} 696}