aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2013-12-12 03:36:02 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-01-07 03:57:08 -0500
commit6c4f4cbb585bbb124cadc2ed6ef7b8aeae5ce82e (patch)
tree4506dab07334e06593cd5f13cfaa279cef8cecea
parent6948082d1c9d5cdebc00b317b3b290292c635d53 (diff)
[media] v4l: ti-vpe: Add helper to perform color conversion
The CSC block can be used for color space conversion between YUV and RGB formats. It is configurable via a programmable set of coefficients. Add functionality to choose the appropriate CSC coefficients and program them in the CSC registers. We take the source and destination colorspace formats as the arguments, and choose the coefficient table accordingly. YUV to RGB coefficients are provided for standard and high definition colorspaces. The coefficients can also be limited or full range. For now, only full range coefficients are chosen. We would need some sort of control ioctl for the user to specify the range needed. Not sure if there is a generic control ioctl for this already? Signed-off-by: Archit Taneja <archit@ti.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/media/platform/ti-vpe/csc.c120
-rw-r--r--drivers/media/platform/ti-vpe/csc.h3
2 files changed, 123 insertions, 0 deletions
diff --git a/drivers/media/platform/ti-vpe/csc.c b/drivers/media/platform/ti-vpe/csc.c
index 62e2fecd1798..acfea500710e 100644
--- a/drivers/media/platform/ti-vpe/csc.c
+++ b/drivers/media/platform/ti-vpe/csc.c
@@ -16,9 +16,79 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/videodev2.h>
19 20
20#include "csc.h" 21#include "csc.h"
21 22
23/*
24 * 16 coefficients in the order:
25 * a0, b0, c0, a1, b1, c1, a2, b2, c2, d0, d1, d2
26 * (we may need to pass non-default values from user space later on, we might
27 * need to make the coefficient struct more easy to populate)
28 */
29struct colorspace_coeffs {
30 u16 sd[12];
31 u16 hd[12];
32};
33
34/* VIDEO_RANGE: limited range, GRAPHICS_RANGE: full range */
35#define CSC_COEFFS_VIDEO_RANGE_Y2R 0
36#define CSC_COEFFS_GRAPHICS_RANGE_Y2R 1
37#define CSC_COEFFS_VIDEO_RANGE_R2Y 2
38#define CSC_COEFFS_GRAPHICS_RANGE_R2Y 3
39
40/* default colorspace coefficients */
41static struct colorspace_coeffs colorspace_coeffs[4] = {
42 [CSC_COEFFS_VIDEO_RANGE_Y2R] = {
43 {
44 /* SDTV */
45 0x0400, 0x0000, 0x057D, 0x0400, 0x1EA7, 0x1D35,
46 0x0400, 0x06EF, 0x1FFE, 0x0D40, 0x0210, 0x0C88,
47 },
48 {
49 /* HDTV */
50 0x0400, 0x0000, 0x0629, 0x0400, 0x1F45, 0x1E2B,
51 0x0400, 0x0742, 0x0000, 0x0CEC, 0x0148, 0x0C60,
52 },
53 },
54 [CSC_COEFFS_GRAPHICS_RANGE_Y2R] = {
55 {
56 /* SDTV */
57 0x04A8, 0x1FFE, 0x0662, 0x04A8, 0x1E6F, 0x1CBF,
58 0x04A8, 0x0812, 0x1FFF, 0x0C84, 0x0220, 0x0BAC,
59 },
60 {
61 /* HDTV */
62 0x04A8, 0x0000, 0x072C, 0x04A8, 0x1F26, 0x1DDE,
63 0x04A8, 0x0873, 0x0000, 0x0C20, 0x0134, 0x0B7C,
64 },
65 },
66 [CSC_COEFFS_VIDEO_RANGE_R2Y] = {
67 {
68 /* SDTV */
69 0x0132, 0x0259, 0x0075, 0x1F50, 0x1EA5, 0x020B,
70 0x020B, 0x1E4A, 0x1FAB, 0x0000, 0x0200, 0x0200,
71 },
72 {
73 /* HDTV */
74 0x00DA, 0x02DC, 0x004A, 0x1F88, 0x1E6C, 0x020C,
75 0x020C, 0x1E24, 0x1FD0, 0x0000, 0x0200, 0x0200,
76 },
77 },
78 [CSC_COEFFS_GRAPHICS_RANGE_R2Y] = {
79 {
80 /* SDTV */
81 0x0107, 0x0204, 0x0064, 0x1F68, 0x1ED6, 0x01C2,
82 0x01C2, 0x1E87, 0x1FB7, 0x0040, 0x0200, 0x0200,
83 },
84 {
85 /* HDTV */
86 0x04A8, 0x0000, 0x072C, 0x04A8, 0x1F26, 0x1DDE,
87 0x04A8, 0x0873, 0x0000, 0x0C20, 0x0134, 0x0B7C,
88 },
89 },
90};
91
22void csc_dump_regs(struct csc_data *csc) 92void csc_dump_regs(struct csc_data *csc)
23{ 93{
24 struct device *dev = &csc->pdev->dev; 94 struct device *dev = &csc->pdev->dev;
@@ -45,6 +115,56 @@ void csc_set_coeff_bypass(struct csc_data *csc, u32 *csc_reg5)
45 *csc_reg5 |= CSC_BYPASS; 115 *csc_reg5 |= CSC_BYPASS;
46} 116}
47 117
118/*
119 * set the color space converter coefficient shadow register values
120 */
121void csc_set_coeff(struct csc_data *csc, u32 *csc_reg0,
122 enum v4l2_colorspace src_colorspace,
123 enum v4l2_colorspace dst_colorspace)
124{
125 u32 *csc_reg5 = csc_reg0 + 5;
126 u32 *shadow_csc = csc_reg0;
127 struct colorspace_coeffs *sd_hd_coeffs;
128 u16 *coeff, *end_coeff;
129 enum v4l2_colorspace yuv_colorspace;
130 int sel = 0;
131
132 /*
133 * support only graphics data range(full range) for now, a control ioctl
134 * would be nice here
135 */
136 /* Y2R */
137 if (dst_colorspace == V4L2_COLORSPACE_SRGB &&
138 (src_colorspace == V4L2_COLORSPACE_SMPTE170M ||
139 src_colorspace == V4L2_COLORSPACE_REC709)) {
140 /* Y2R */
141 sel = 1;
142 yuv_colorspace = src_colorspace;
143 } else if ((dst_colorspace == V4L2_COLORSPACE_SMPTE170M ||
144 dst_colorspace == V4L2_COLORSPACE_REC709) &&
145 src_colorspace == V4L2_COLORSPACE_SRGB) {
146 /* R2Y */
147 sel = 3;
148 yuv_colorspace = dst_colorspace;
149 } else {
150 *csc_reg5 |= CSC_BYPASS;
151 return;
152 }
153
154 sd_hd_coeffs = &colorspace_coeffs[sel];
155
156 /* select between SD or HD coefficients */
157 if (yuv_colorspace == V4L2_COLORSPACE_SMPTE170M)
158 coeff = sd_hd_coeffs->sd;
159 else
160 coeff = sd_hd_coeffs->hd;
161
162 end_coeff = coeff + 12;
163
164 for (; coeff < end_coeff; coeff += 2)
165 *shadow_csc++ = (*(coeff + 1) << 16) | *coeff;
166}
167
48struct csc_data *csc_create(struct platform_device *pdev) 168struct csc_data *csc_create(struct platform_device *pdev)
49{ 169{
50 struct csc_data *csc; 170 struct csc_data *csc;
diff --git a/drivers/media/platform/ti-vpe/csc.h b/drivers/media/platform/ti-vpe/csc.h
index 57b5ed600394..1ad2b6dad561 100644
--- a/drivers/media/platform/ti-vpe/csc.h
+++ b/drivers/media/platform/ti-vpe/csc.h
@@ -60,6 +60,9 @@ struct csc_data {
60 60
61void csc_dump_regs(struct csc_data *csc); 61void csc_dump_regs(struct csc_data *csc);
62void csc_set_coeff_bypass(struct csc_data *csc, u32 *csc_reg5); 62void csc_set_coeff_bypass(struct csc_data *csc, u32 *csc_reg5);
63void csc_set_coeff(struct csc_data *csc, u32 *csc_reg0,
64 enum v4l2_colorspace src_colorspace,
65 enum v4l2_colorspace dst_colorspace);
63struct csc_data *csc_create(struct platform_device *pdev); 66struct csc_data *csc_create(struct platform_device *pdev);
64 67
65#endif 68#endif