aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/ti-vpe
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2013-12-12 03:36:00 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-01-07 03:55:35 -0500
commitbbee8b3933f5ddff85904aed9190eaca52c54d13 (patch)
treeb641f89c02f719e2d8bb3c5c4b0c615cca0e36d0 /drivers/media/platform/ti-vpe
parent773f06577b35f84f84de980e1be3eead8342b5e5 (diff)
[media] v4l: ti-vpe: enable basic scaler support
Add the required SC register configurations which lets us perform linear scaling for the supported range of horizontal and vertical scaling ratios. The horizontal scaler performs polyphase scaling using it's 8 tap 32 phase filter, decimation is performed when downscaling passes beyond 2x or 4x. The vertical scaler performs polyphase scaling using it's 5 tap 32 phase filter, it switches to a simpler form of scaling using the running average filter when the downscale ratio is more than 4x. Many of the SC features like peaking, trimming and non-linear scaling aren't implemented for now. Only the minimal register fields required for basic scaling operation are configured. The function to configure SC registers takes the sc_data handle, the source and destination widths and heights, and the scaler address data block offsets for the current context so that they can be configured. 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>
Diffstat (limited to 'drivers/media/platform/ti-vpe')
-rw-r--r--drivers/media/platform/ti-vpe/sc.c132
-rw-r--r--drivers/media/platform/ti-vpe/sc.h4
-rw-r--r--drivers/media/platform/ti-vpe/vpe.c24
3 files changed, 149 insertions, 11 deletions
diff --git a/drivers/media/platform/ti-vpe/sc.c b/drivers/media/platform/ti-vpe/sc.c
index 417feb9f1f79..93f0af546b76 100644
--- a/drivers/media/platform/ti-vpe/sc.c
+++ b/drivers/media/platform/ti-vpe/sc.c
@@ -20,11 +20,6 @@
20#include "sc.h" 20#include "sc.h"
21#include "sc_coeff.h" 21#include "sc_coeff.h"
22 22
23void sc_set_regs_bypass(struct sc_data *sc, u32 *sc_reg0)
24{
25 *sc_reg0 |= CFG_SC_BYPASS;
26}
27
28void sc_dump_regs(struct sc_data *sc) 23void sc_dump_regs(struct sc_data *sc)
29{ 24{
30 struct device *dev = &sc->pdev->dev; 25 struct device *dev = &sc->pdev->dev;
@@ -159,6 +154,133 @@ void sc_set_vs_coeffs(struct sc_data *sc, void *addr, unsigned int src_h,
159 sc->load_coeff_v = true; 154 sc->load_coeff_v = true;
160} 155}
161 156
157void sc_config_scaler(struct sc_data *sc, u32 *sc_reg0, u32 *sc_reg8,
158 u32 *sc_reg17, unsigned int src_w, unsigned int src_h,
159 unsigned int dst_w, unsigned int dst_h)
160{
161 struct device *dev = &sc->pdev->dev;
162 u32 val;
163 int dcm_x, dcm_shift;
164 bool use_rav;
165 unsigned long lltmp;
166 u32 lin_acc_inc, lin_acc_inc_u;
167 u32 col_acc_offset;
168 u16 factor = 0;
169 int row_acc_init_rav = 0, row_acc_init_rav_b = 0;
170 u32 row_acc_inc = 0, row_acc_offset = 0, row_acc_offset_b = 0;
171 /*
172 * location of SC register in payload memory with respect to the first
173 * register in the mmr address data block
174 */
175 u32 *sc_reg9 = sc_reg8 + 1;
176 u32 *sc_reg12 = sc_reg8 + 4;
177 u32 *sc_reg13 = sc_reg8 + 5;
178 u32 *sc_reg24 = sc_reg17 + 7;
179
180 val = sc_reg0[0];
181
182 /* clear all the features(they may get enabled elsewhere later) */
183 val &= ~(CFG_SELFGEN_FID | CFG_TRIM | CFG_ENABLE_SIN2_VER_INTP |
184 CFG_INTERLACE_I | CFG_DCM_4X | CFG_DCM_2X | CFG_AUTO_HS |
185 CFG_ENABLE_EV | CFG_USE_RAV | CFG_INVT_FID | CFG_SC_BYPASS |
186 CFG_INTERLACE_O | CFG_Y_PK_EN | CFG_HP_BYPASS | CFG_LINEAR);
187
188 if (src_w == dst_w && src_h == dst_h) {
189 val |= CFG_SC_BYPASS;
190 sc_reg0[0] = val;
191 return;
192 }
193
194 /* we only support linear scaling for now */
195 val |= CFG_LINEAR;
196
197 /* configure horizontal scaler */
198
199 /* enable 2X or 4X decimation */
200 dcm_x = src_w / dst_w;
201 if (dcm_x > 4) {
202 val |= CFG_DCM_4X;
203 dcm_shift = 2;
204 } else if (dcm_x > 2) {
205 val |= CFG_DCM_2X;
206 dcm_shift = 1;
207 } else {
208 dcm_shift = 0;
209 }
210
211 lltmp = dst_w - 1;
212 lin_acc_inc = div64_u64(((u64)(src_w >> dcm_shift) - 1) << 24, lltmp);
213 lin_acc_inc_u = 0;
214 col_acc_offset = 0;
215
216 dev_dbg(dev, "hs config: src_w = %d, dst_w = %d, decimation = %s, lin_acc_inc = %08x\n",
217 src_w, dst_w, dcm_shift == 2 ? "4x" :
218 (dcm_shift == 1 ? "2x" : "none"), lin_acc_inc);
219
220 /* configure vertical scaler */
221
222 /* use RAV for vertical scaler if vertical downscaling is > 4x */
223 if (dst_h < (src_h >> 2)) {
224 use_rav = true;
225 val |= CFG_USE_RAV;
226 } else {
227 use_rav = false;
228 }
229
230 if (use_rav) {
231 /* use RAV */
232 factor = (u16) ((dst_h << 10) / src_h);
233
234 row_acc_init_rav = factor + ((1 + factor) >> 1);
235 if (row_acc_init_rav >= 1024)
236 row_acc_init_rav -= 1024;
237
238 row_acc_init_rav_b = row_acc_init_rav +
239 (1 + (row_acc_init_rav >> 1)) -
240 (1024 >> 1);
241
242 if (row_acc_init_rav_b < 0) {
243 row_acc_init_rav_b += row_acc_init_rav;
244 row_acc_init_rav *= 2;
245 }
246
247 dev_dbg(dev, "vs config(RAV): src_h = %d, dst_h = %d, factor = %d, acc_init = %08x, acc_init_b = %08x\n",
248 src_h, dst_h, factor, row_acc_init_rav,
249 row_acc_init_rav_b);
250 } else {
251 /* use polyphase */
252 row_acc_inc = ((src_h - 1) << 16) / (dst_h - 1);
253 row_acc_offset = 0;
254 row_acc_offset_b = 0;
255
256 dev_dbg(dev, "vs config(POLY): src_h = %d, dst_h = %d,row_acc_inc = %08x\n",
257 src_h, dst_h, row_acc_inc);
258 }
259
260
261 sc_reg0[0] = val;
262 sc_reg0[1] = row_acc_inc;
263 sc_reg0[2] = row_acc_offset;
264 sc_reg0[3] = row_acc_offset_b;
265
266 sc_reg0[4] = ((lin_acc_inc_u & CFG_LIN_ACC_INC_U_MASK) <<
267 CFG_LIN_ACC_INC_U_SHIFT) | (dst_w << CFG_TAR_W_SHIFT) |
268 (dst_h << CFG_TAR_H_SHIFT);
269
270 sc_reg0[5] = (src_w << CFG_SRC_W_SHIFT) | (src_h << CFG_SRC_H_SHIFT);
271
272 sc_reg0[6] = (row_acc_init_rav_b << CFG_ROW_ACC_INIT_RAV_B_SHIFT) |
273 (row_acc_init_rav << CFG_ROW_ACC_INIT_RAV_SHIFT);
274
275 *sc_reg9 = lin_acc_inc;
276
277 *sc_reg12 = col_acc_offset << CFG_COL_ACC_OFFSET_SHIFT;
278
279 *sc_reg13 = factor;
280
281 *sc_reg24 = (src_w << CFG_ORG_W_SHIFT) | (src_h << CFG_ORG_H_SHIFT);
282}
283
162struct sc_data *sc_create(struct platform_device *pdev) 284struct sc_data *sc_create(struct platform_device *pdev)
163{ 285{
164 struct sc_data *sc; 286 struct sc_data *sc;
diff --git a/drivers/media/platform/ti-vpe/sc.h b/drivers/media/platform/ti-vpe/sc.h
index c89f3d1a3bad..60e411e05c30 100644
--- a/drivers/media/platform/ti-vpe/sc.h
+++ b/drivers/media/platform/ti-vpe/sc.h
@@ -195,12 +195,14 @@ struct sc_data {
195 struct platform_device *pdev; 195 struct platform_device *pdev;
196}; 196};
197 197
198void sc_set_regs_bypass(struct sc_data *sc, u32 *sc_reg0);
199void sc_dump_regs(struct sc_data *sc); 198void sc_dump_regs(struct sc_data *sc);
200void sc_set_hs_coeffs(struct sc_data *sc, void *addr, unsigned int src_w, 199void sc_set_hs_coeffs(struct sc_data *sc, void *addr, unsigned int src_w,
201 unsigned int dst_w); 200 unsigned int dst_w);
202void sc_set_vs_coeffs(struct sc_data *sc, void *addr, unsigned int src_h, 201void sc_set_vs_coeffs(struct sc_data *sc, void *addr, unsigned int src_h,
203 unsigned int dst_h); 202 unsigned int dst_h);
203void sc_config_scaler(struct sc_data *sc, u32 *sc_reg0, u32 *sc_reg8,
204 u32 *sc_reg17, unsigned int src_w, unsigned int src_h,
205 unsigned int dst_w, unsigned int dst_h);
204struct sc_data *sc_create(struct platform_device *pdev); 206struct sc_data *sc_create(struct platform_device *pdev);
205 207
206#endif 208#endif
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index 50d6d0e696e7..dc2b94cb2640 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -440,9 +440,15 @@ struct vpe_mmr_adb {
440 u32 us3_regs[8]; 440 u32 us3_regs[8];
441 struct vpdma_adb_hdr dei_hdr; 441 struct vpdma_adb_hdr dei_hdr;
442 u32 dei_regs[8]; 442 u32 dei_regs[8];
443 struct vpdma_adb_hdr sc_hdr; 443 struct vpdma_adb_hdr sc_hdr0;
444 u32 sc_regs[1]; 444 u32 sc_regs0[7];
445 u32 sc_pad[3]; 445 u32 sc_pad0[1];
446 struct vpdma_adb_hdr sc_hdr8;
447 u32 sc_regs8[6];
448 u32 sc_pad8[2];
449 struct vpdma_adb_hdr sc_hdr17;
450 u32 sc_regs17[9];
451 u32 sc_pad17[3];
446 struct vpdma_adb_hdr csc_hdr; 452 struct vpdma_adb_hdr csc_hdr;
447 u32 csc_regs[6]; 453 u32 csc_regs[6];
448 u32 csc_pad[2]; 454 u32 csc_pad[2];
@@ -463,8 +469,12 @@ static void init_adb_hdrs(struct vpe_ctx *ctx)
463 VPE_SET_MMR_ADB_HDR(ctx, us2_hdr, us2_regs, VPE_US2_R0); 469 VPE_SET_MMR_ADB_HDR(ctx, us2_hdr, us2_regs, VPE_US2_R0);
464 VPE_SET_MMR_ADB_HDR(ctx, us3_hdr, us3_regs, VPE_US3_R0); 470 VPE_SET_MMR_ADB_HDR(ctx, us3_hdr, us3_regs, VPE_US3_R0);
465 VPE_SET_MMR_ADB_HDR(ctx, dei_hdr, dei_regs, VPE_DEI_FRAME_SIZE); 471 VPE_SET_MMR_ADB_HDR(ctx, dei_hdr, dei_regs, VPE_DEI_FRAME_SIZE);
466 VPE_SET_MMR_ADB_HDR(ctx, sc_hdr, sc_regs, 472 VPE_SET_MMR_ADB_HDR(ctx, sc_hdr0, sc_regs0,
467 GET_OFFSET_TOP(ctx, ctx->dev->sc, CFG_SC0)); 473 GET_OFFSET_TOP(ctx, ctx->dev->sc, CFG_SC0));
474 VPE_SET_MMR_ADB_HDR(ctx, sc_hdr8, sc_regs8,
475 GET_OFFSET_TOP(ctx, ctx->dev->sc, CFG_SC8));
476 VPE_SET_MMR_ADB_HDR(ctx, sc_hdr17, sc_regs17,
477 GET_OFFSET_TOP(ctx, ctx->dev->sc, CFG_SC17));
468 VPE_SET_MMR_ADB_HDR(ctx, csc_hdr, csc_regs, VPE_CSC_CSC00); 478 VPE_SET_MMR_ADB_HDR(ctx, csc_hdr, csc_regs, VPE_CSC_CSC00);
469}; 479};
470 480
@@ -810,9 +820,13 @@ static int set_srcdst_params(struct vpe_ctx *ctx)
810 set_cfg_and_line_modes(ctx); 820 set_cfg_and_line_modes(ctx);
811 set_dei_regs(ctx); 821 set_dei_regs(ctx);
812 set_csc_coeff_bypass(ctx); 822 set_csc_coeff_bypass(ctx);
823
813 sc_set_hs_coeffs(ctx->dev->sc, ctx->sc_coeff_h.addr, src_w, dst_w); 824 sc_set_hs_coeffs(ctx->dev->sc, ctx->sc_coeff_h.addr, src_w, dst_w);
814 sc_set_vs_coeffs(ctx->dev->sc, ctx->sc_coeff_v.addr, src_h, dst_h); 825 sc_set_vs_coeffs(ctx->dev->sc, ctx->sc_coeff_v.addr, src_h, dst_h);
815 sc_set_regs_bypass(ctx->dev->sc, &mmr_adb->sc_regs[0]); 826
827 sc_config_scaler(ctx->dev->sc, &mmr_adb->sc_regs0[0],
828 &mmr_adb->sc_regs8[0], &mmr_adb->sc_regs17[0],
829 src_w, src_h, dst_w, dst_h);
816 830
817 return 0; 831 return 0;
818} 832}