aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2010-10-11 12:19:27 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-21 05:55:48 -0400
commita7d5bbcf9c77596f94154906ca54ce8e28945a68 (patch)
tree5f8ae76a70b5c012848da7f8286089fa806f2b03 /drivers/media/video/s5p-fimc
parent5f3cc4474cdeab3ee44962fd752baec24e8fecec (diff)
[media] s5p-fimc: Add suport for FIMC on S5PC210 SoCs
Enable FIMC operation on S5PC210 (S5PV310) SoCs. This a minimal adaptation to obtain functionality of older FIMC IP revisions (S5PC100, S5PC110) on S5PC210 SOcs. 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/fimc-core.c157
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h56
-rw-r--r--drivers/media/video/s5p-fimc/regs-fimc.h3
3 files changed, 156 insertions, 60 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 5168a9a5d821..4b655461d399 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -823,10 +823,10 @@ int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
823 goto tf_out; 823 goto tf_out;
824 824
825 if (is_output) { 825 if (is_output) {
826 max_width = variant->scaler_dis_w; 826 max_width = variant->pix_limit->scaler_dis_w;
827 mod_x = ffs(variant->min_inp_pixsize) - 1; 827 mod_x = ffs(variant->min_inp_pixsize) - 1;
828 } else { 828 } else {
829 max_width = variant->out_rot_dis_w; 829 max_width = variant->pix_limit->out_rot_dis_w;
830 mod_x = ffs(variant->min_out_pixsize) - 1; 830 mod_x = ffs(variant->min_out_pixsize) - 1;
831 } 831 }
832 832
@@ -843,7 +843,7 @@ int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
843 dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_width); 843 dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_width);
844 844
845 v4l_bound_align_image(&pix->width, 16, max_width, mod_x, 845 v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
846 &pix->height, 8, variant->scaler_dis_w, mod_y, 0); 846 &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
847 847
848 if (pix->bytesperline == 0 || 848 if (pix->bytesperline == 0 ||
849 (pix->bytesperline * 8 / fmt->depth) > pix->width) 849 (pix->bytesperline * 8 / fmt->depth) > pix->width)
@@ -1519,7 +1519,7 @@ static int fimc_probe(struct platform_device *pdev)
1519 drv_data = (struct samsung_fimc_driverdata *) 1519 drv_data = (struct samsung_fimc_driverdata *)
1520 platform_get_device_id(pdev)->driver_data; 1520 platform_get_device_id(pdev)->driver_data;
1521 1521
1522 if (pdev->id >= drv_data->devs_cnt) { 1522 if (pdev->id >= drv_data->num_entities) {
1523 dev_err(&pdev->dev, "Invalid platform device id: %d\n", 1523 dev_err(&pdev->dev, "Invalid platform device id: %d\n",
1524 pdev->id); 1524 pdev->id);
1525 return -EINVAL; 1525 return -EINVAL;
@@ -1602,6 +1602,13 @@ static int fimc_probe(struct platform_device *pdev)
1602 } 1602 }
1603 } 1603 }
1604 1604
1605 /*
1606 * Exclude the additional output DMA address registers by masking
1607 * them out on HW revisions that provide extended capabilites.
1608 */
1609 if (fimc->variant->out_buf_count > 4)
1610 fimc_hw_set_dma_seq(fimc, 0xF);
1611
1605 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n", 1612 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
1606 __func__, fimc->id); 1613 __func__, fimc->id);
1607 1614
@@ -1645,78 +1652,135 @@ static int __devexit fimc_remove(struct platform_device *pdev)
1645 return 0; 1652 return 0;
1646} 1653}
1647 1654
1648static struct samsung_fimc_variant fimc01_variant_s5p = { 1655/* Image pixel limits, similar across several FIMC HW revisions. */
1649 .has_inp_rot = 1, 1656static struct fimc_pix_limit s5p_pix_limit[3] = {
1650 .has_out_rot = 1, 1657 [0] = {
1658 .scaler_en_w = 3264,
1659 .scaler_dis_w = 8192,
1660 .in_rot_en_h = 1920,
1661 .in_rot_dis_w = 8192,
1662 .out_rot_en_w = 1920,
1663 .out_rot_dis_w = 4224,
1664 },
1665 [1] = {
1666 .scaler_en_w = 4224,
1667 .scaler_dis_w = 8192,
1668 .in_rot_en_h = 1920,
1669 .in_rot_dis_w = 8192,
1670 .out_rot_en_w = 1920,
1671 .out_rot_dis_w = 4224,
1672 },
1673 [2] = {
1674 .scaler_en_w = 1920,
1675 .scaler_dis_w = 8192,
1676 .in_rot_en_h = 1280,
1677 .in_rot_dis_w = 8192,
1678 .out_rot_en_w = 1280,
1679 .out_rot_dis_w = 1920,
1680 },
1681};
1682
1683static struct samsung_fimc_variant fimc0_variant_s5p = {
1684 .has_inp_rot = 1,
1685 .has_out_rot = 1,
1651 .min_inp_pixsize = 16, 1686 .min_inp_pixsize = 16,
1652 .min_out_pixsize = 16, 1687 .min_out_pixsize = 16,
1653 1688 .hor_offs_align = 8,
1654 .scaler_en_w = 3264, 1689 .out_buf_count = 4,
1655 .scaler_dis_w = 8192, 1690 .pix_limit = &s5p_pix_limit[0],
1656 .in_rot_en_h = 1920,
1657 .in_rot_dis_w = 8192,
1658 .out_rot_en_w = 1920,
1659 .out_rot_dis_w = 4224,
1660}; 1691};
1661 1692
1662static struct samsung_fimc_variant fimc2_variant_s5p = { 1693static struct samsung_fimc_variant fimc2_variant_s5p = {
1663 .min_inp_pixsize = 16, 1694 .min_inp_pixsize = 16,
1664 .min_out_pixsize = 16, 1695 .min_out_pixsize = 16,
1665 1696 .hor_offs_align = 8,
1666 .scaler_en_w = 4224, 1697 .out_buf_count = 4,
1667 .scaler_dis_w = 8192, 1698 .pix_limit = &s5p_pix_limit[1],
1668 .in_rot_en_h = 1920,
1669 .in_rot_dis_w = 8192,
1670 .out_rot_en_w = 1920,
1671 .out_rot_dis_w = 4224,
1672}; 1699};
1673 1700
1674static struct samsung_fimc_variant fimc01_variant_s5pv210 = { 1701static struct samsung_fimc_variant fimc0_variant_s5pv210 = {
1675 .pix_hoff = 1, 1702 .pix_hoff = 1,
1676 .has_inp_rot = 1, 1703 .has_inp_rot = 1,
1677 .has_out_rot = 1, 1704 .has_out_rot = 1,
1678 .min_inp_pixsize = 16, 1705 .min_inp_pixsize = 16,
1679 .min_out_pixsize = 16, 1706 .min_out_pixsize = 16,
1707 .hor_offs_align = 8,
1708 .out_buf_count = 4,
1709 .pix_limit = &s5p_pix_limit[1],
1710};
1680 1711
1681 .scaler_en_w = 4224, 1712static struct samsung_fimc_variant fimc1_variant_s5pv210 = {
1682 .scaler_dis_w = 8192, 1713 .pix_hoff = 1,
1683 .in_rot_en_h = 1920, 1714 .has_inp_rot = 1,
1684 .in_rot_dis_w = 8192, 1715 .has_out_rot = 1,
1685 .out_rot_en_w = 1920, 1716 .min_inp_pixsize = 16,
1686 .out_rot_dis_w = 4224, 1717 .min_out_pixsize = 16,
1718 .hor_offs_align = 1,
1719 .out_buf_count = 4,
1720 .pix_limit = &s5p_pix_limit[2],
1687}; 1721};
1688 1722
1689static struct samsung_fimc_variant fimc2_variant_s5pv210 = { 1723static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
1690 .pix_hoff = 1, 1724 .pix_hoff = 1,
1691 .min_inp_pixsize = 16, 1725 .min_inp_pixsize = 16,
1692 .min_out_pixsize = 16, 1726 .min_out_pixsize = 16,
1727 .hor_offs_align = 8,
1728 .out_buf_count = 4,
1729 .pix_limit = &s5p_pix_limit[2],
1730};
1693 1731
1694 .scaler_en_w = 1920, 1732static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
1695 .scaler_dis_w = 8192, 1733 .pix_hoff = 1,
1696 .in_rot_en_h = 1280, 1734 .has_inp_rot = 1,
1697 .in_rot_dis_w = 8192, 1735 .has_out_rot = 1,
1698 .out_rot_en_w = 1280, 1736 .min_inp_pixsize = 16,
1699 .out_rot_dis_w = 1920, 1737 .min_out_pixsize = 16,
1738 .hor_offs_align = 1,
1739 .out_buf_count = 32,
1740 .pix_limit = &s5p_pix_limit[1],
1741};
1742
1743static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
1744 .pix_hoff = 1,
1745 .min_inp_pixsize = 16,
1746 .min_out_pixsize = 16,
1747 .hor_offs_align = 1,
1748 .out_buf_count = 32,
1749 .pix_limit = &s5p_pix_limit[2],
1700}; 1750};
1701 1751
1752/* S5PC100 */
1702static struct samsung_fimc_driverdata fimc_drvdata_s5p = { 1753static struct samsung_fimc_driverdata fimc_drvdata_s5p = {
1703 .variant = { 1754 .variant = {
1704 [0] = &fimc01_variant_s5p, 1755 [0] = &fimc0_variant_s5p,
1705 [1] = &fimc01_variant_s5p, 1756 [1] = &fimc0_variant_s5p,
1706 [2] = &fimc2_variant_s5p, 1757 [2] = &fimc2_variant_s5p,
1707 }, 1758 },
1708 .devs_cnt = 3, 1759 .num_entities = 3,
1709 .lclk_frequency = 133000000UL, 1760 .lclk_frequency = 133000000UL,
1710}; 1761};
1711 1762
1763/* S5PV210, S5PC110 */
1712static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = { 1764static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
1713 .variant = { 1765 .variant = {
1714 [0] = &fimc01_variant_s5pv210, 1766 [0] = &fimc0_variant_s5pv210,
1715 [1] = &fimc01_variant_s5pv210, 1767 [1] = &fimc1_variant_s5pv210,
1716 [2] = &fimc2_variant_s5pv210, 1768 [2] = &fimc2_variant_s5pv210,
1717 }, 1769 },
1718 .devs_cnt = 3, 1770 .num_entities = 3,
1719 .lclk_frequency = 166000000UL, 1771 .lclk_frequency = 166000000UL,
1772};
1773
1774/* S5PV310, S5PC210 */
1775static struct samsung_fimc_driverdata fimc_drvdata_s5pv310 = {
1776 .variant = {
1777 [0] = &fimc0_variant_s5pv310,
1778 [1] = &fimc0_variant_s5pv310,
1779 [2] = &fimc0_variant_s5pv310,
1780 [3] = &fimc2_variant_s5pv310,
1781 },
1782 .num_entities = 4,
1783 .lclk_frequency = 166000000UL,
1720}; 1784};
1721 1785
1722static struct platform_device_id fimc_driver_ids[] = { 1786static struct platform_device_id fimc_driver_ids[] = {
@@ -1726,6 +1790,9 @@ static struct platform_device_id fimc_driver_ids[] = {
1726 }, { 1790 }, {
1727 .name = "s5pv210-fimc", 1791 .name = "s5pv210-fimc",
1728 .driver_data = (unsigned long)&fimc_drvdata_s5pv210, 1792 .driver_data = (unsigned long)&fimc_drvdata_s5pv210,
1793 }, {
1794 .name = "s5pv310-fimc",
1795 .driver_data = (unsigned long)&fimc_drvdata_s5pv310,
1729 }, 1796 },
1730 {}, 1797 {},
1731}; 1798};
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index ce0a6b8a7d54..e3a7c6a0dce2 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -36,7 +36,7 @@
36#define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000) 36#define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000)
37#define NUM_FIMC_CLOCKS 2 37#define NUM_FIMC_CLOCKS 2
38#define MODULE_NAME "s5p-fimc" 38#define MODULE_NAME "s5p-fimc"
39#define FIMC_MAX_DEVS 3 39#define FIMC_MAX_DEVS 4
40#define FIMC_MAX_OUT_BUFS 4 40#define FIMC_MAX_OUT_BUFS 4
41#define SCALER_MAX_HRATIO 64 41#define SCALER_MAX_HRATIO 64
42#define SCALER_MAX_VRATIO 64 42#define SCALER_MAX_VRATIO 64
@@ -345,33 +345,45 @@ struct fimc_vid_cap {
345}; 345};
346 346
347/** 347/**
348 * struct fimc_pix_limit - image pixel size limits in various IP configurations
349 *
350 * @scaler_en_w: max input pixel width when the scaler is enabled
351 * @scaler_dis_w: max input pixel width when the scaler is disabled
352 * @in_rot_en_h: max input width with the input rotator is on
353 * @in_rot_dis_w: max input width with the input rotator is off
354 * @out_rot_en_w: max output width with the output rotator on
355 * @out_rot_dis_w: max output width with the output rotator off
356 */
357struct fimc_pix_limit {
358 u16 scaler_en_w;
359 u16 scaler_dis_w;
360 u16 in_rot_en_h;
361 u16 in_rot_dis_w;
362 u16 out_rot_en_w;
363 u16 out_rot_dis_w;
364};
365
366/**
348 * struct samsung_fimc_variant - camera interface variant information 367 * struct samsung_fimc_variant - camera interface variant information
349 * 368 *
350 * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes 369 * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
351 * @has_inp_rot: set if has input rotator 370 * @has_inp_rot: set if has input rotator
352 * @has_out_rot: set if has output rotator 371 * @has_out_rot: set if has output rotator
372 * @pix_limit: pixel size constraints for the scaler
353 * @min_inp_pixsize: minimum input pixel size 373 * @min_inp_pixsize: minimum input pixel size
354 * @min_out_pixsize: minimum output pixel size 374 * @min_out_pixsize: minimum output pixel size
355 * @scaler_en_w: maximum input pixel width when the scaler is enabled 375 * @hor_offs_align: horizontal pixel offset aligment
356 * @scaler_dis_w: maximum input pixel width when the scaler is disabled 376 * @out_buf_count: the number of buffers in output DMA sequence
357 * @in_rot_en_h: maximum input width when the input rotator is enabled
358 * @in_rot_dis_w: maximum input width when the input rotator is disabled
359 * @out_rot_en_w: maximum target width when the output rotator enabled
360 * @out_rot_dis_w: maximum target width when the output rotator disnabled
361 */ 377 */
362struct samsung_fimc_variant { 378struct samsung_fimc_variant {
363 unsigned int pix_hoff:1; 379 unsigned int pix_hoff:1;
364 unsigned int has_inp_rot:1; 380 unsigned int has_inp_rot:1;
365 unsigned int has_out_rot:1; 381 unsigned int has_out_rot:1;
366 382 struct fimc_pix_limit *pix_limit;
367 u16 min_inp_pixsize; 383 u16 min_inp_pixsize;
368 u16 min_out_pixsize; 384 u16 min_out_pixsize;
369 u16 scaler_en_w; 385 u16 hor_offs_align;
370 u16 scaler_dis_w; 386 u16 out_buf_count;
371 u16 in_rot_en_h;
372 u16 in_rot_dis_w;
373 u16 out_rot_en_w;
374 u16 out_rot_dis_w;
375}; 387};
376 388
377/** 389/**
@@ -384,7 +396,7 @@ struct samsung_fimc_variant {
384struct samsung_fimc_driverdata { 396struct samsung_fimc_driverdata {
385 struct samsung_fimc_variant *variant[FIMC_MAX_DEVS]; 397 struct samsung_fimc_variant *variant[FIMC_MAX_DEVS];
386 unsigned long lclk_frequency; 398 unsigned long lclk_frequency;
387 int devs_cnt; 399 int num_entities;
388}; 400};
389 401
390struct fimc_ctx; 402struct fimc_ctx;
@@ -507,6 +519,20 @@ static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
507 writel(cfg, dev->regs + S5P_CIIMGCPT); 519 writel(cfg, dev->regs + S5P_CIIMGCPT);
508} 520}
509 521
522/**
523 * fimc_hw_set_dma_seq - configure output DMA buffer sequence
524 * @mask: each bit corresponds to one of 32 output buffer registers set
525 * 1 to include buffer in the sequence, 0 to disable
526 *
527 * This function mask output DMA ring buffers, i.e. it allows to configure
528 * which of the output buffer address registers will be used by the DMA
529 * engine.
530 */
531static inline void fimc_hw_set_dma_seq(struct fimc_dev *dev, u32 mask)
532{
533 writel(mask, dev->regs + S5P_CIFCNTSEQ);
534}
535
510static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, 536static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
511 enum v4l2_buf_type type) 537 enum v4l2_buf_type type)
512{ 538{
diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h
index 9e833151562d..a57daedb5b5c 100644
--- a/drivers/media/video/s5p-fimc/regs-fimc.h
+++ b/drivers/media/video/s5p-fimc/regs-fimc.h
@@ -279,4 +279,7 @@
279#define S5P_CSIIMGFMT_USER3 0x32 279#define S5P_CSIIMGFMT_USER3 0x32
280#define S5P_CSIIMGFMT_USER4 0x33 280#define S5P_CSIIMGFMT_USER4 0x33
281 281
282/* Output frame buffer sequence mask */
283#define S5P_CIFCNTSEQ 0x1FC
284
282#endif /* REGS_FIMC_H_ */ 285#endif /* REGS_FIMC_H_ */