diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2010-10-11 12:19:27 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 05:55:48 -0400 |
commit | a7d5bbcf9c77596f94154906ca54ce8e28945a68 (patch) | |
tree | 5f8ae76a70b5c012848da7f8286089fa806f2b03 /drivers/media/video/s5p-fimc | |
parent | 5f3cc4474cdeab3ee44962fd752baec24e8fecec (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.c | 157 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-core.h | 56 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/regs-fimc.h | 3 |
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 | ||
1648 | static struct samsung_fimc_variant fimc01_variant_s5p = { | 1655 | /* Image pixel limits, similar across several FIMC HW revisions. */ |
1649 | .has_inp_rot = 1, | 1656 | static 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 | |||
1683 | static 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 | ||
1662 | static struct samsung_fimc_variant fimc2_variant_s5p = { | 1693 | static 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 | ||
1674 | static struct samsung_fimc_variant fimc01_variant_s5pv210 = { | 1701 | static 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, | 1712 | static 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 | ||
1689 | static struct samsung_fimc_variant fimc2_variant_s5pv210 = { | 1723 | static 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, | 1732 | static 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 | |||
1743 | static 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 */ | ||
1702 | static struct samsung_fimc_driverdata fimc_drvdata_s5p = { | 1753 | static 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 */ | ||
1712 | static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = { | 1764 | static 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 */ | ||
1775 | static 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 | ||
1722 | static struct platform_device_id fimc_driver_ids[] = { | 1786 | static 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 | */ | ||
357 | struct 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 | */ |
362 | struct samsung_fimc_variant { | 378 | struct 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 { | |||
384 | struct samsung_fimc_driverdata { | 396 | struct 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 | ||
390 | struct fimc_ctx; | 402 | struct 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 | */ | ||
531 | static inline void fimc_hw_set_dma_seq(struct fimc_dev *dev, u32 mask) | ||
532 | { | ||
533 | writel(mask, dev->regs + S5P_CIFCNTSEQ); | ||
534 | } | ||
535 | |||
510 | static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, | 536 | static 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_ */ |