aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-23 17:39:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-23 17:39:09 -0400
commite317234975cb7463b8ca21a93bb6862d9dcf113f (patch)
tree4446fa3a21364f3cba23a22aa2a94027f169d8df /drivers/media/video/s5p-fimc
parentf37ab0fba271e43edab0e3ae9fe644fcda455402 (diff)
parent7483d45f0aee3afc0646d185cabd4af9f6cab58c (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - V4L2 API additions to better support JPEG compression control - media API additions to properly support MPEG decoders - V4L2 API additions for image crop/scaling - a few other V4L2 API DocBook fixes/improvements - two new DVB frontend drivers: m88rs2000 and rtl2830 - two new DVB drivers: az6007 and rtl28xxu - a framework for ISA drivers, that removed lots of common code found at the ISA radio drivers - a new FM transmitter driver (radio-keene) - a GPIO-based IR receiver driver - a new sensor driver: mt9m032 - some new video drivers: adv7183, blackfin, mx2_emmaprp, sii9234_drv, vs6624 - several new board additions, driver fixes, improvements and cleanups. * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (295 commits) [media] update CARDLIST.em28xx [media] partially reverts changeset fa5527c [media] stb0899: fix the limits for signal strength values [media] em28xx: support for 2304:0242 PCTV QuatroStick (510e) [media] em28xx: support for 2013:0251 PCTV QuatroStick nano (520e) [media] -EINVAL -> -ENOTTY [media] gspca - sn9c20x: Cleanup source [media] gspca - sn9c20x: Simplify register write for capture start/stop [media] gspca - sn9c20x: Add automatic JPEG compression mechanism [media] gspca - sn9c20x: Greater delay in case of sensor no response [media] gspca - sn9c20x: Optimize the code of write sequences [media] gspca - sn9c20x: Add the JPEG compression quality control [media] gspca - sn9c20x: Add a delay after Omnivision sensor reset [media] gspca - sn9c20x: Propagate USB errors to higher level [media] gspca - sn9c20x: Use the new video control mechanism [media] gspca - sn9c20x: Fix loss of frame start [media] gspca - zc3xx: Lack of register 08 value for sensor cs2102k [media] gspca - ov534_9: Add brightness to OmniVision 5621 sensor [media] gspca - zc3xx: Add V4L2_CID_JPEG_COMPRESSION_QUALITY control support [media] pvrusb2: fix 7MHz & 8MHz DVB-T tuner support for HVR1900 rev D1F5 ...
Diffstat (limited to 'drivers/media/video/s5p-fimc')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c121
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c85
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h2
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.c7
-rw-r--r--drivers/media/video/s5p-fimc/mipi-csis.c111
5 files changed, 172 insertions, 154 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index a9e9653beeb4..b06efd208328 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -1019,52 +1019,117 @@ static int fimc_cap_dqbuf(struct file *file, void *priv,
1019 return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK); 1019 return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK);
1020} 1020}
1021 1021
1022static int fimc_cap_cropcap(struct file *file, void *fh, 1022static int fimc_cap_create_bufs(struct file *file, void *priv,
1023 struct v4l2_cropcap *cr) 1023 struct v4l2_create_buffers *create)
1024{ 1024{
1025 struct fimc_dev *fimc = video_drvdata(file); 1025 struct fimc_dev *fimc = video_drvdata(file);
1026 struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
1027 1026
1028 if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 1027 return vb2_create_bufs(&fimc->vid_cap.vbq, create);
1029 return -EINVAL; 1028}
1030 1029
1031 cr->bounds.left = 0; 1030static int fimc_cap_prepare_buf(struct file *file, void *priv,
1032 cr->bounds.top = 0; 1031 struct v4l2_buffer *b)
1033 cr->bounds.width = f->o_width; 1032{
1034 cr->bounds.height = f->o_height; 1033 struct fimc_dev *fimc = video_drvdata(file);
1035 cr->defrect = cr->bounds;
1036 1034
1037 return 0; 1035 return vb2_prepare_buf(&fimc->vid_cap.vbq, b);
1038} 1036}
1039 1037
1040static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) 1038static int fimc_cap_g_selection(struct file *file, void *fh,
1039 struct v4l2_selection *s)
1041{ 1040{
1042 struct fimc_dev *fimc = video_drvdata(file); 1041 struct fimc_dev *fimc = video_drvdata(file);
1043 struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; 1042 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1043 struct fimc_frame *f = &ctx->s_frame;
1044 1044
1045 cr->c.left = f->offs_h; 1045 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1046 cr->c.top = f->offs_v; 1046 return -EINVAL;
1047 cr->c.width = f->width;
1048 cr->c.height = f->height;
1049 1047
1050 return 0; 1048 switch (s->target) {
1049 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1050 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1051 f = &ctx->d_frame;
1052 case V4L2_SEL_TGT_CROP_BOUNDS:
1053 case V4L2_SEL_TGT_CROP_DEFAULT:
1054 s->r.left = 0;
1055 s->r.top = 0;
1056 s->r.width = f->o_width;
1057 s->r.height = f->o_height;
1058 return 0;
1059
1060 case V4L2_SEL_TGT_COMPOSE_ACTIVE:
1061 f = &ctx->d_frame;
1062 case V4L2_SEL_TGT_CROP_ACTIVE:
1063 s->r.left = f->offs_h;
1064 s->r.top = f->offs_v;
1065 s->r.width = f->width;
1066 s->r.height = f->height;
1067 return 0;
1068 }
1069
1070 return -EINVAL;
1051} 1071}
1052 1072
1053static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) 1073/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
1074int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
1075{
1076 if (a->left < b->left || a->top < b->top)
1077 return 0;
1078 if (a->left + a->width > b->left + b->width)
1079 return 0;
1080 if (a->top + a->height > b->top + b->height)
1081 return 0;
1082
1083 return 1;
1084}
1085
1086static int fimc_cap_s_selection(struct file *file, void *fh,
1087 struct v4l2_selection *s)
1054{ 1088{
1055 struct fimc_dev *fimc = video_drvdata(file); 1089 struct fimc_dev *fimc = video_drvdata(file);
1056 struct fimc_ctx *ctx = fimc->vid_cap.ctx; 1090 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1057 struct fimc_frame *ff; 1091 struct v4l2_rect rect = s->r;
1092 struct fimc_frame *f;
1058 unsigned long flags; 1093 unsigned long flags;
1094 unsigned int pad;
1059 1095
1060 fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK); 1096 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1061 ff = &ctx->s_frame; 1097 return -EINVAL;
1062 1098
1099 switch (s->target) {
1100 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1101 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1102 case V4L2_SEL_TGT_COMPOSE_ACTIVE:
1103 f = &ctx->d_frame;
1104 pad = FIMC_SD_PAD_SOURCE;
1105 break;
1106 case V4L2_SEL_TGT_CROP_BOUNDS:
1107 case V4L2_SEL_TGT_CROP_DEFAULT:
1108 case V4L2_SEL_TGT_CROP_ACTIVE:
1109 f = &ctx->s_frame;
1110 pad = FIMC_SD_PAD_SINK;
1111 break;
1112 default:
1113 return -EINVAL;
1114 }
1115
1116 fimc_capture_try_crop(ctx, &rect, pad);
1117
1118 if (s->flags & V4L2_SEL_FLAG_LE &&
1119 !enclosed_rectangle(&rect, &s->r))
1120 return -ERANGE;
1121
1122 if (s->flags & V4L2_SEL_FLAG_GE &&
1123 !enclosed_rectangle(&s->r, &rect))
1124 return -ERANGE;
1125
1126 s->r = rect;
1063 spin_lock_irqsave(&fimc->slock, flags); 1127 spin_lock_irqsave(&fimc->slock, flags);
1064 set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height); 1128 set_frame_crop(f, s->r.left, s->r.top, s->r.width,
1065 set_bit(ST_CAPT_APPLY_CFG, &fimc->state); 1129 s->r.height);
1066 spin_unlock_irqrestore(&fimc->slock, flags); 1130 spin_unlock_irqrestore(&fimc->slock, flags);
1067 1131
1132 set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
1068 return 0; 1133 return 0;
1069} 1134}
1070 1135
@@ -1082,12 +1147,14 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
1082 .vidioc_qbuf = fimc_cap_qbuf, 1147 .vidioc_qbuf = fimc_cap_qbuf,
1083 .vidioc_dqbuf = fimc_cap_dqbuf, 1148 .vidioc_dqbuf = fimc_cap_dqbuf,
1084 1149
1150 .vidioc_prepare_buf = fimc_cap_prepare_buf,
1151 .vidioc_create_bufs = fimc_cap_create_bufs,
1152
1085 .vidioc_streamon = fimc_cap_streamon, 1153 .vidioc_streamon = fimc_cap_streamon,
1086 .vidioc_streamoff = fimc_cap_streamoff, 1154 .vidioc_streamoff = fimc_cap_streamoff,
1087 1155
1088 .vidioc_g_crop = fimc_cap_g_crop, 1156 .vidioc_g_selection = fimc_cap_g_selection,
1089 .vidioc_s_crop = fimc_cap_s_crop, 1157 .vidioc_s_selection = fimc_cap_s_selection,
1090 .vidioc_cropcap = fimc_cap_cropcap,
1091 1158
1092 .vidioc_enum_input = fimc_cap_enum_input, 1159 .vidioc_enum_input = fimc_cap_enum_input,
1093 .vidioc_s_input = fimc_cap_s_input, 1160 .vidioc_s_input = fimc_cap_s_input,
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 81bcbb9492ea..e184e650022a 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -1602,24 +1602,35 @@ static void fimc_clk_put(struct fimc_dev *fimc)
1602{ 1602{
1603 int i; 1603 int i;
1604 for (i = 0; i < fimc->num_clocks; i++) { 1604 for (i = 0; i < fimc->num_clocks; i++) {
1605 if (fimc->clock[i]) 1605 if (IS_ERR_OR_NULL(fimc->clock[i]))
1606 clk_put(fimc->clock[i]); 1606 continue;
1607 clk_unprepare(fimc->clock[i]);
1608 clk_put(fimc->clock[i]);
1609 fimc->clock[i] = NULL;
1607 } 1610 }
1608} 1611}
1609 1612
1610static int fimc_clk_get(struct fimc_dev *fimc) 1613static int fimc_clk_get(struct fimc_dev *fimc)
1611{ 1614{
1612 int i; 1615 int i, ret;
1616
1613 for (i = 0; i < fimc->num_clocks; i++) { 1617 for (i = 0; i < fimc->num_clocks; i++) {
1614 fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); 1618 fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]);
1615 if (!IS_ERR_OR_NULL(fimc->clock[i])) 1619 if (IS_ERR(fimc->clock[i]))
1616 continue; 1620 goto err;
1617 dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n", 1621 ret = clk_prepare(fimc->clock[i]);
1618 fimc_clocks[i]); 1622 if (ret < 0) {
1619 return -ENXIO; 1623 clk_put(fimc->clock[i]);
1624 fimc->clock[i] = NULL;
1625 goto err;
1626 }
1620 } 1627 }
1621
1622 return 0; 1628 return 0;
1629err:
1630 fimc_clk_put(fimc);
1631 dev_err(&fimc->pdev->dev, "failed to get clock: %s\n",
1632 fimc_clocks[i]);
1633 return -ENXIO;
1623} 1634}
1624 1635
1625static int fimc_m2m_suspend(struct fimc_dev *fimc) 1636static int fimc_m2m_suspend(struct fimc_dev *fimc)
@@ -1667,8 +1678,6 @@ static int fimc_probe(struct platform_device *pdev)
1667 struct s5p_platform_fimc *pdata; 1678 struct s5p_platform_fimc *pdata;
1668 int ret = 0; 1679 int ret = 0;
1669 1680
1670 dev_dbg(&pdev->dev, "%s():\n", __func__);
1671
1672 drv_data = (struct samsung_fimc_driverdata *) 1681 drv_data = (struct samsung_fimc_driverdata *)
1673 platform_get_device_id(pdev)->driver_data; 1682 platform_get_device_id(pdev)->driver_data;
1674 1683
@@ -1678,7 +1687,7 @@ static int fimc_probe(struct platform_device *pdev)
1678 return -EINVAL; 1687 return -EINVAL;
1679 } 1688 }
1680 1689
1681 fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL); 1690 fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL);
1682 if (!fimc) 1691 if (!fimc)
1683 return -ENOMEM; 1692 return -ENOMEM;
1684 1693
@@ -1689,51 +1698,35 @@ static int fimc_probe(struct platform_device *pdev)
1689 pdata = pdev->dev.platform_data; 1698 pdata = pdev->dev.platform_data;
1690 fimc->pdata = pdata; 1699 fimc->pdata = pdata;
1691 1700
1692
1693 init_waitqueue_head(&fimc->irq_queue); 1701 init_waitqueue_head(&fimc->irq_queue);
1694 spin_lock_init(&fimc->slock); 1702 spin_lock_init(&fimc->slock);
1695 mutex_init(&fimc->lock); 1703 mutex_init(&fimc->lock);
1696 1704
1697 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1705 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1698 if (!res) { 1706 fimc->regs = devm_request_and_ioremap(&pdev->dev, res);
1699 dev_err(&pdev->dev, "failed to find the registers\n"); 1707 if (fimc->regs == NULL) {
1700 ret = -ENOENT; 1708 dev_err(&pdev->dev, "Failed to obtain io memory\n");
1701 goto err_info; 1709 return -ENOENT;
1702 }
1703
1704 fimc->regs_res = request_mem_region(res->start, resource_size(res),
1705 dev_name(&pdev->dev));
1706 if (!fimc->regs_res) {
1707 dev_err(&pdev->dev, "failed to obtain register region\n");
1708 ret = -ENOENT;
1709 goto err_info;
1710 }
1711
1712 fimc->regs = ioremap(res->start, resource_size(res));
1713 if (!fimc->regs) {
1714 dev_err(&pdev->dev, "failed to map registers\n");
1715 ret = -ENXIO;
1716 goto err_req_region;
1717 } 1710 }
1718 1711
1719 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1712 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1720 if (!res) { 1713 if (res == NULL) {
1721 dev_err(&pdev->dev, "failed to get IRQ resource\n"); 1714 dev_err(&pdev->dev, "Failed to get IRQ resource\n");
1722 ret = -ENXIO; 1715 return -ENXIO;
1723 goto err_regs_unmap;
1724 } 1716 }
1725 fimc->irq = res->start; 1717 fimc->irq = res->start;
1726 1718
1727 fimc->num_clocks = MAX_FIMC_CLOCKS; 1719 fimc->num_clocks = MAX_FIMC_CLOCKS;
1728 ret = fimc_clk_get(fimc); 1720 ret = fimc_clk_get(fimc);
1729 if (ret) 1721 if (ret)
1730 goto err_regs_unmap; 1722 return ret;
1731 clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); 1723 clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
1732 clk_enable(fimc->clock[CLK_BUS]); 1724 clk_enable(fimc->clock[CLK_BUS]);
1733 1725
1734 platform_set_drvdata(pdev, fimc); 1726 platform_set_drvdata(pdev, fimc);
1735 1727
1736 ret = request_irq(fimc->irq, fimc_irq_handler, 0, pdev->name, fimc); 1728 ret = devm_request_irq(&pdev->dev, fimc->irq, fimc_irq_handler,
1729 0, pdev->name, fimc);
1737 if (ret) { 1730 if (ret) {
1738 dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); 1731 dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
1739 goto err_clk; 1732 goto err_clk;
@@ -1742,7 +1735,7 @@ static int fimc_probe(struct platform_device *pdev)
1742 pm_runtime_enable(&pdev->dev); 1735 pm_runtime_enable(&pdev->dev);
1743 ret = pm_runtime_get_sync(&pdev->dev); 1736 ret = pm_runtime_get_sync(&pdev->dev);
1744 if (ret < 0) 1737 if (ret < 0)
1745 goto err_irq; 1738 goto err_clk;
1746 /* Initialize contiguous memory allocator */ 1739 /* Initialize contiguous memory allocator */
1747 fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); 1740 fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1748 if (IS_ERR(fimc->alloc_ctx)) { 1741 if (IS_ERR(fimc->alloc_ctx)) {
@@ -1757,17 +1750,8 @@ static int fimc_probe(struct platform_device *pdev)
1757 1750
1758err_pm: 1751err_pm:
1759 pm_runtime_put(&pdev->dev); 1752 pm_runtime_put(&pdev->dev);
1760err_irq:
1761 free_irq(fimc->irq, fimc);
1762err_clk: 1753err_clk:
1763 fimc_clk_put(fimc); 1754 fimc_clk_put(fimc);
1764err_regs_unmap:
1765 iounmap(fimc->regs);
1766err_req_region:
1767 release_resource(fimc->regs_res);
1768 kfree(fimc->regs_res);
1769err_info:
1770 kfree(fimc);
1771 return ret; 1755 return ret;
1772} 1756}
1773 1757
@@ -1854,11 +1838,6 @@ static int __devexit fimc_remove(struct platform_device *pdev)
1854 1838
1855 clk_disable(fimc->clock[CLK_BUS]); 1839 clk_disable(fimc->clock[CLK_BUS]);
1856 fimc_clk_put(fimc); 1840 fimc_clk_put(fimc);
1857 free_irq(fimc->irq, fimc);
1858 iounmap(fimc->regs);
1859 release_resource(fimc->regs_res);
1860 kfree(fimc->regs_res);
1861 kfree(fimc);
1862 1841
1863 dev_info(&pdev->dev, "driver unloaded\n"); 1842 dev_info(&pdev->dev, "driver unloaded\n");
1864 return 0; 1843 return 0;
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 4e20560c73d4..a18291e648e2 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -434,7 +434,6 @@ struct fimc_ctx;
434 * @num_clocks: the number of clocks managed by this device instance 434 * @num_clocks: the number of clocks managed by this device instance
435 * @clock: clocks required for FIMC operation 435 * @clock: clocks required for FIMC operation
436 * @regs: the mapped hardware registers 436 * @regs: the mapped hardware registers
437 * @regs_res: the resource claimed for IO registers
438 * @irq: FIMC interrupt number 437 * @irq: FIMC interrupt number
439 * @irq_queue: interrupt handler waitqueue 438 * @irq_queue: interrupt handler waitqueue
440 * @v4l2_dev: root v4l2_device 439 * @v4l2_dev: root v4l2_device
@@ -454,7 +453,6 @@ struct fimc_dev {
454 u16 num_clocks; 453 u16 num_clocks;
455 struct clk *clock[MAX_FIMC_CLOCKS]; 454 struct clk *clock[MAX_FIMC_CLOCKS];
456 void __iomem *regs; 455 void __iomem *regs;
457 struct resource *regs_res;
458 int irq; 456 int irq;
459 wait_queue_head_t irq_queue; 457 wait_queue_head_t irq_queue;
460 struct v4l2_device *v4l2_dev; 458 struct v4l2_device *v4l2_dev;
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
index 63eccb55728f..62ed37e40149 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -750,7 +750,7 @@ static int __devinit fimc_md_probe(struct platform_device *pdev)
750 struct fimc_md *fmd; 750 struct fimc_md *fmd;
751 int ret; 751 int ret;
752 752
753 fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL); 753 fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL);
754 if (!fmd) 754 if (!fmd)
755 return -ENOMEM; 755 return -ENOMEM;
756 756
@@ -771,7 +771,7 @@ static int __devinit fimc_md_probe(struct platform_device *pdev)
771 ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); 771 ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
772 if (ret < 0) { 772 if (ret < 0) {
773 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); 773 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
774 goto err1; 774 return ret;
775 } 775 }
776 ret = media_device_register(&fmd->media_dev); 776 ret = media_device_register(&fmd->media_dev);
777 if (ret < 0) { 777 if (ret < 0) {
@@ -813,8 +813,6 @@ err3:
813 fimc_md_unregister_entities(fmd); 813 fimc_md_unregister_entities(fmd);
814err2: 814err2:
815 v4l2_device_unregister(&fmd->v4l2_dev); 815 v4l2_device_unregister(&fmd->v4l2_dev);
816err1:
817 kfree(fmd);
818 return ret; 816 return ret;
819} 817}
820 818
@@ -828,7 +826,6 @@ static int __devexit fimc_md_remove(struct platform_device *pdev)
828 fimc_md_unregister_entities(fmd); 826 fimc_md_unregister_entities(fmd);
829 media_device_unregister(&fmd->media_dev); 827 media_device_unregister(&fmd->media_dev);
830 fimc_md_put_clocks(fmd); 828 fimc_md_put_clocks(fmd);
831 kfree(fmd);
832 return 0; 829 return 0;
833} 830}
834 831
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c
index 130335cf62fd..f44f690397f7 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];
@@ -258,26 +256,36 @@ static void s5pcsis_clk_put(struct csis_state *state)
258{ 256{
259 int i; 257 int i;
260 258
261 for (i = 0; i < NUM_CSIS_CLOCKS; i++) 259 for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
262 if (!IS_ERR_OR_NULL(state->clock[i])) 260 if (IS_ERR_OR_NULL(state->clock[i]))
263 clk_put(state->clock[i]); 261 continue;
262 clk_unprepare(state->clock[i]);
263 clk_put(state->clock[i]);
264 state->clock[i] = NULL;
265 }
264} 266}
265 267
266static int s5pcsis_clk_get(struct csis_state *state) 268static int s5pcsis_clk_get(struct csis_state *state)
267{ 269{
268 struct device *dev = &state->pdev->dev; 270 struct device *dev = &state->pdev->dev;
269 int i; 271 int i, ret;
270 272
271 for (i = 0; i < NUM_CSIS_CLOCKS; i++) { 273 for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
272 state->clock[i] = clk_get(dev, csi_clock_name[i]); 274 state->clock[i] = clk_get(dev, csi_clock_name[i]);
273 if (IS_ERR(state->clock[i])) { 275 if (IS_ERR(state->clock[i]))
274 s5pcsis_clk_put(state); 276 goto err;
275 dev_err(dev, "failed to get clock: %s\n", 277 ret = clk_prepare(state->clock[i]);
276 csi_clock_name[i]); 278 if (ret < 0) {
277 return -ENXIO; 279 clk_put(state->clock[i]);
280 state->clock[i] = NULL;
281 goto err;
278 } 282 }
279 } 283 }
280 return 0; 284 return 0;
285err:
286 s5pcsis_clk_put(state);
287 dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]);
288 return -ENXIO;
281} 289}
282 290
283static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) 291static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
@@ -480,12 +488,11 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
480{ 488{
481 struct s5p_platform_mipi_csis *pdata; 489 struct s5p_platform_mipi_csis *pdata;
482 struct resource *mem_res; 490 struct resource *mem_res;
483 struct resource *regs_res;
484 struct csis_state *state; 491 struct csis_state *state;
485 int ret = -ENOMEM; 492 int ret = -ENOMEM;
486 int i; 493 int i;
487 494
488 state = kzalloc(sizeof(*state), GFP_KERNEL); 495 state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
489 if (!state) 496 if (!state)
490 return -ENOMEM; 497 return -ENOMEM;
491 498
@@ -495,52 +502,27 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
495 pdata = pdev->dev.platform_data; 502 pdata = pdev->dev.platform_data;
496 if (pdata == NULL || pdata->phy_enable == NULL) { 503 if (pdata == NULL || pdata->phy_enable == NULL) {
497 dev_err(&pdev->dev, "Platform data not fully specified\n"); 504 dev_err(&pdev->dev, "Platform data not fully specified\n");
498 goto e_free; 505 return -EINVAL;
499 } 506 }
500 507
501 if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || 508 if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
502 pdata->lanes > CSIS0_MAX_LANES) { 509 pdata->lanes > CSIS0_MAX_LANES) {
503 ret = -EINVAL;
504 dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", 510 dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
505 pdata->lanes); 511 pdata->lanes);
506 goto e_free; 512 return -EINVAL;
507 } 513 }
508 514
509 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 515 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
510 if (!mem_res) { 516 state->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
511 dev_err(&pdev->dev, "Failed to get IO memory region\n"); 517 if (state->regs == NULL) {
512 goto e_free; 518 dev_err(&pdev->dev, "Failed to request and remap io memory\n");
519 return -ENXIO;
513 } 520 }
514 521
515 regs_res = request_mem_region(mem_res->start, resource_size(mem_res),
516 pdev->name);
517 if (!regs_res) {
518 dev_err(&pdev->dev, "Failed to request IO memory region\n");
519 goto e_free;
520 }
521 state->regs_res = regs_res;
522
523 state->regs = ioremap(mem_res->start, resource_size(mem_res));
524 if (!state->regs) {
525 dev_err(&pdev->dev, "Failed to remap IO region\n");
526 goto e_reqmem;
527 }
528
529 ret = s5pcsis_clk_get(state);
530 if (ret)
531 goto e_unmap;
532
533 clk_enable(state->clock[CSIS_CLK_MUX]);
534 if (pdata->clk_rate)
535 clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate);
536 else
537 dev_WARN(&pdev->dev, "No clock frequency specified!\n");
538
539 state->irq = platform_get_irq(pdev, 0); 522 state->irq = platform_get_irq(pdev, 0);
540 if (state->irq < 0) { 523 if (state->irq < 0) {
541 ret = state->irq;
542 dev_err(&pdev->dev, "Failed to get irq\n"); 524 dev_err(&pdev->dev, "Failed to get irq\n");
543 goto e_clkput; 525 return state->irq;
544 } 526 }
545 527
546 for (i = 0; i < CSIS_NUM_SUPPLIES; i++) 528 for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
@@ -549,12 +531,22 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
549 ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, 531 ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
550 state->supplies); 532 state->supplies);
551 if (ret) 533 if (ret)
534 return ret;
535
536 ret = s5pcsis_clk_get(state);
537 if (ret)
552 goto e_clkput; 538 goto e_clkput;
553 539
554 ret = request_irq(state->irq, s5pcsis_irq_handler, 0, 540 clk_enable(state->clock[CSIS_CLK_MUX]);
555 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);
556 if (ret) { 548 if (ret) {
557 dev_err(&pdev->dev, "request_irq failed\n"); 549 dev_err(&pdev->dev, "Interrupt request failed\n");
558 goto e_regput; 550 goto e_regput;
559 } 551 }
560 552
@@ -573,7 +565,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
573 ret = media_entity_init(&state->sd.entity, 565 ret = media_entity_init(&state->sd.entity,
574 CSIS_PADS_NUM, state->pads, 0); 566 CSIS_PADS_NUM, state->pads, 0);
575 if (ret < 0) 567 if (ret < 0)
576 goto e_irqfree; 568 goto e_clkput;
577 569
578 /* 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 */
579 v4l2_set_subdevdata(&state->sd, pdev); 571 v4l2_set_subdevdata(&state->sd, pdev);
@@ -582,22 +574,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
582 platform_set_drvdata(pdev, &state->sd); 574 platform_set_drvdata(pdev, &state->sd);
583 575
584 pm_runtime_enable(&pdev->dev); 576 pm_runtime_enable(&pdev->dev);
585
586 return 0; 577 return 0;
587 578
588e_irqfree:
589 free_irq(state->irq, state);
590e_regput: 579e_regput:
591 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); 580 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
592e_clkput: 581e_clkput:
593 clk_disable(state->clock[CSIS_CLK_MUX]); 582 clk_disable(state->clock[CSIS_CLK_MUX]);
594 s5pcsis_clk_put(state); 583 s5pcsis_clk_put(state);
595e_unmap:
596 iounmap(state->regs);
597e_reqmem:
598 release_mem_region(regs_res->start, resource_size(regs_res));
599e_free:
600 kfree(state);
601 return ret; 584 return ret;
602} 585}
603 586
@@ -699,21 +682,15 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev)
699{ 682{
700 struct v4l2_subdev *sd = platform_get_drvdata(pdev); 683 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
701 struct csis_state *state = sd_to_csis_state(sd); 684 struct csis_state *state = sd_to_csis_state(sd);
702 struct resource *res = state->regs_res;
703 685
704 pm_runtime_disable(&pdev->dev); 686 pm_runtime_disable(&pdev->dev);
705 s5pcsis_suspend(&pdev->dev); 687 s5pcsis_pm_suspend(&pdev->dev, false);
706 clk_disable(state->clock[CSIS_CLK_MUX]); 688 clk_disable(state->clock[CSIS_CLK_MUX]);
707 pm_runtime_set_suspended(&pdev->dev); 689 pm_runtime_set_suspended(&pdev->dev);
708
709 s5pcsis_clk_put(state); 690 s5pcsis_clk_put(state);
710 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); 691 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
711 692
712 media_entity_cleanup(&state->sd.entity); 693 media_entity_cleanup(&state->sd.entity);
713 free_irq(state->irq, state);
714 iounmap(state->regs);
715 release_mem_region(res->start, resource_size(res));
716 kfree(state);
717 694
718 return 0; 695 return 0;
719} 696}