aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2010-10-08 04:01:14 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-21 05:55:44 -0400
commit548aafcd9e73b14fd959ec3689d1551bf7f388d3 (patch)
treeb27564ac9ffddbb5e80745079e462cfc4e1e29ff /drivers/media/video
parent77e6208252cccc377aecec18340ee0bfbcb02108 (diff)
[media] s5p-fimc: mem2mem driver refactoring and cleanup
Register access functions refactored for camera capture interface control. Removed the workqueue since it was only useful for FIFO output mode which is not supported at this time. Fixed errors on module unload. Comments and whitespace cleanup. 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')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c151
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h132
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c43
3 files changed, 148 insertions, 178 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index c56029ee6e31..fccab1398425 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -117,7 +117,7 @@ static struct fimc_fmt fimc_formats[] = {
117 .buff_cnt = 1, 117 .buff_cnt = 1,
118 .planes_cnt = 2 118 .planes_cnt = 2
119 } 119 }
120 }; 120};
121 121
122static struct v4l2_queryctrl fimc_ctrls[] = { 122static struct v4l2_queryctrl fimc_ctrls[] = {
123 { 123 {
@@ -127,16 +127,14 @@ static struct v4l2_queryctrl fimc_ctrls[] = {
127 .minimum = 0, 127 .minimum = 0,
128 .maximum = 1, 128 .maximum = 1,
129 .default_value = 0, 129 .default_value = 0,
130 }, 130 }, {
131 {
132 .id = V4L2_CID_VFLIP, 131 .id = V4L2_CID_VFLIP,
133 .type = V4L2_CTRL_TYPE_BOOLEAN, 132 .type = V4L2_CTRL_TYPE_BOOLEAN,
134 .name = "Vertical flip", 133 .name = "Vertical flip",
135 .minimum = 0, 134 .minimum = 0,
136 .maximum = 1, 135 .maximum = 1,
137 .default_value = 0, 136 .default_value = 0,
138 }, 137 }, {
139 {
140 .id = V4L2_CID_ROTATE, 138 .id = V4L2_CID_ROTATE,
141 .type = V4L2_CTRL_TYPE_INTEGER, 139 .type = V4L2_CTRL_TYPE_INTEGER,
142 .name = "Rotation (CCW)", 140 .name = "Rotation (CCW)",
@@ -181,28 +179,23 @@ static int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f)
181 179
182static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift) 180static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
183{ 181{
184 if (src >= tar * 64) { 182 u32 sh = 6;
183
184 if (src >= 64 * tar)
185 return -EINVAL; 185 return -EINVAL;
186 } else if (src >= tar * 32) { 186
187 *ratio = 32; 187 while (sh--) {
188 *shift = 5; 188 u32 tmp = 1 << sh;
189 } else if (src >= tar * 16) { 189 if (src >= tar * tmp) {
190 *ratio = 16; 190 *shift = sh, *ratio = tmp;
191 *shift = 4; 191 return 0;
192 } else if (src >= tar * 8) { 192 }
193 *ratio = 8;
194 *shift = 3;
195 } else if (src >= tar * 4) {
196 *ratio = 4;
197 *shift = 2;
198 } else if (src >= tar * 2) {
199 *ratio = 2;
200 *shift = 1;
201 } else {
202 *ratio = 1;
203 *shift = 0;
204 } 193 }
205 194
195 *shift = 0, *ratio = 1;
196
197 dbg("s: %d, t: %d, shift: %d, ratio: %d",
198 src, tar, *shift, *ratio);
206 return 0; 199 return 0;
207} 200}
208 201
@@ -265,8 +258,8 @@ static int fimc_set_scaler_info(struct fimc_ctx *ctx)
265static irqreturn_t fimc_isr(int irq, void *priv) 258static irqreturn_t fimc_isr(int irq, void *priv)
266{ 259{
267 struct fimc_vid_buffer *src_buf, *dst_buf; 260 struct fimc_vid_buffer *src_buf, *dst_buf;
268 struct fimc_dev *fimc = (struct fimc_dev *)priv;
269 struct fimc_ctx *ctx; 261 struct fimc_ctx *ctx;
262 struct fimc_dev *fimc = priv;
270 263
271 BUG_ON(!fimc); 264 BUG_ON(!fimc);
272 fimc_hw_clear_irq(fimc); 265 fimc_hw_clear_irq(fimc);
@@ -281,7 +274,7 @@ static irqreturn_t fimc_isr(int irq, void *priv)
281 dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); 274 dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
282 if (src_buf && dst_buf) { 275 if (src_buf && dst_buf) {
283 spin_lock(&fimc->irqlock); 276 spin_lock(&fimc->irqlock);
284 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE; 277 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
285 wake_up(&src_buf->vb.done); 278 wake_up(&src_buf->vb.done);
286 wake_up(&dst_buf->vb.done); 279 wake_up(&dst_buf->vb.done);
287 spin_unlock(&fimc->irqlock); 280 spin_unlock(&fimc->irqlock);
@@ -295,20 +288,13 @@ isr_unlock:
295} 288}
296 289
297/* The color format (planes_cnt, buff_cnt) must be already configured. */ 290/* The color format (planes_cnt, buff_cnt) must be already configured. */
298static int fimc_prepare_addr(struct fimc_ctx *ctx, 291int fimc_prepare_addr(struct fimc_ctx *ctx, struct fimc_vid_buffer *buf,
299 struct fimc_vid_buffer *buf, enum v4l2_buf_type type) 292 struct fimc_frame *frame, struct fimc_addr *paddr)
300{ 293{
301 struct fimc_frame *frame;
302 struct fimc_addr *paddr;
303 u32 pix_size;
304 int ret = 0; 294 int ret = 0;
295 u32 pix_size;
305 296
306 frame = ctx_m2m_get_frame(ctx, type); 297 if (buf == NULL || frame == NULL)
307 if (IS_ERR(frame))
308 return PTR_ERR(frame);
309 paddr = &frame->paddr;
310
311 if (!buf)
312 return -EINVAL; 298 return -EINVAL;
313 299
314 pix_size = frame->width * frame->height; 300 pix_size = frame->width * frame->height;
@@ -344,8 +330,8 @@ static int fimc_prepare_addr(struct fimc_ctx *ctx,
344 } 330 }
345 } 331 }
346 332
347 dbg("PHYS_ADDR: type= %d, y= 0x%X cb= 0x%X cr= 0x%X ret= %d", 333 dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
348 type, paddr->y, paddr->cb, paddr->cr, ret); 334 paddr->y, paddr->cb, paddr->cr, ret);
349 335
350 return ret; 336 return ret;
351} 337}
@@ -466,16 +452,14 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
466 452
467 if (flags & FIMC_SRC_ADDR) { 453 if (flags & FIMC_SRC_ADDR) {
468 buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); 454 buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
469 ret = fimc_prepare_addr(ctx, buf, 455 ret = fimc_prepare_addr(ctx, buf, s_frame, &s_frame->paddr);
470 V4L2_BUF_TYPE_VIDEO_OUTPUT);
471 if (ret) 456 if (ret)
472 return ret; 457 return ret;
473 } 458 }
474 459
475 if (flags & FIMC_DST_ADDR) { 460 if (flags & FIMC_DST_ADDR) {
476 buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); 461 buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
477 ret = fimc_prepare_addr(ctx, buf, 462 ret = fimc_prepare_addr(ctx, buf, d_frame, &d_frame->paddr);
478 V4L2_BUF_TYPE_VIDEO_CAPTURE);
479 } 463 }
480 464
481 return ret; 465 return ret;
@@ -499,12 +483,14 @@ static void fimc_dma_run(void *priv)
499 ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR); 483 ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
500 ret = fimc_prepare_config(ctx, ctx->state); 484 ret = fimc_prepare_config(ctx, ctx->state);
501 if (ret) { 485 if (ret) {
502 err("general configuration error"); 486 err("Wrong parameters");
503 goto dma_unlock; 487 goto dma_unlock;
504 } 488 }
505 489 /* Reconfigure hardware if the context has changed. */
506 if (fimc->m2m.ctx != ctx) 490 if (fimc->m2m.ctx != ctx) {
507 ctx->state |= FIMC_PARAMS; 491 ctx->state |= FIMC_PARAMS;
492 fimc->m2m.ctx = ctx;
493 }
508 494
509 fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr); 495 fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
510 496
@@ -512,10 +498,9 @@ static void fimc_dma_run(void *priv)
512 fimc_hw_set_input_path(ctx); 498 fimc_hw_set_input_path(ctx);
513 fimc_hw_set_in_dma(ctx); 499 fimc_hw_set_in_dma(ctx);
514 if (fimc_set_scaler_info(ctx)) { 500 if (fimc_set_scaler_info(ctx)) {
515 err("scaler configuration error"); 501 err("Scaler setup error");
516 goto dma_unlock; 502 goto dma_unlock;
517 } 503 }
518 fimc_hw_set_prescaler(ctx);
519 fimc_hw_set_scaler(ctx); 504 fimc_hw_set_scaler(ctx);
520 fimc_hw_set_target_format(ctx); 505 fimc_hw_set_target_format(ctx);
521 fimc_hw_set_rotation(ctx); 506 fimc_hw_set_rotation(ctx);
@@ -524,19 +509,15 @@ static void fimc_dma_run(void *priv)
524 509
525 fimc_hw_set_output_path(ctx); 510 fimc_hw_set_output_path(ctx);
526 if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS)) 511 if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS))
527 fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr); 512 fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1);
528 513
529 if (ctx->state & FIMC_PARAMS) 514 if (ctx->state & FIMC_PARAMS)
530 fimc_hw_set_out_dma(ctx); 515 fimc_hw_set_out_dma(ctx);
531 516
532 if (ctx->scaler.enabled)
533 fimc_hw_start_scaler(fimc);
534 fimc_hw_en_capture(ctx);
535
536 ctx->state = 0; 517 ctx->state = 0;
537 fimc_hw_start_in_dma(fimc); 518 fimc_activate_capture(ctx);
538 519
539 fimc->m2m.ctx = ctx; 520 fimc_hw_activate_input_dma(fimc, true);
540 521
541dma_unlock: 522dma_unlock:
542 spin_unlock_irqrestore(&ctx->slock, flags); 523 spin_unlock_irqrestore(&ctx->slock, flags);
@@ -560,7 +541,7 @@ static int fimc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
560 struct fimc_ctx *ctx = vq->priv_data; 541 struct fimc_ctx *ctx = vq->priv_data;
561 struct fimc_frame *frame; 542 struct fimc_frame *frame;
562 543
563 frame = ctx_m2m_get_frame(ctx, vq->type); 544 frame = ctx_get_frame(ctx, vq->type);
564 if (IS_ERR(frame)) 545 if (IS_ERR(frame))
565 return PTR_ERR(frame); 546 return PTR_ERR(frame);
566 547
@@ -578,7 +559,7 @@ static int fimc_buf_prepare(struct videobuf_queue *vq,
578 struct fimc_frame *frame; 559 struct fimc_frame *frame;
579 int ret; 560 int ret;
580 561
581 frame = ctx_m2m_get_frame(ctx, vq->type); 562 frame = ctx_get_frame(ctx, vq->type);
582 if (IS_ERR(frame)) 563 if (IS_ERR(frame))
583 return PTR_ERR(frame); 564 return PTR_ERR(frame);
584 565
@@ -663,7 +644,7 @@ static int fimc_m2m_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
663 struct fimc_ctx *ctx = priv; 644 struct fimc_ctx *ctx = priv;
664 struct fimc_frame *frame; 645 struct fimc_frame *frame;
665 646
666 frame = ctx_m2m_get_frame(ctx, f->type); 647 frame = ctx_get_frame(ctx, f->type);
667 if (IS_ERR(frame)) 648 if (IS_ERR(frame))
668 return PTR_ERR(frame); 649 return PTR_ERR(frame);
669 650
@@ -999,7 +980,7 @@ static int fimc_m2m_cropcap(struct file *file, void *fh,
999 struct fimc_frame *frame; 980 struct fimc_frame *frame;
1000 struct fimc_ctx *ctx = fh; 981 struct fimc_ctx *ctx = fh;
1001 982
1002 frame = ctx_m2m_get_frame(ctx, cr->type); 983 frame = ctx_get_frame(ctx, cr->type);
1003 if (IS_ERR(frame)) 984 if (IS_ERR(frame))
1004 return PTR_ERR(frame); 985 return PTR_ERR(frame);
1005 986
@@ -1019,7 +1000,7 @@ static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1019 struct fimc_frame *frame; 1000 struct fimc_frame *frame;
1020 struct fimc_ctx *ctx = file->private_data; 1001 struct fimc_ctx *ctx = file->private_data;
1021 1002
1022 frame = ctx_m2m_get_frame(ctx, cr->type); 1003 frame = ctx_get_frame(ctx, cr->type);
1023 if (IS_ERR(frame)) 1004 if (IS_ERR(frame))
1024 return PTR_ERR(frame); 1005 return PTR_ERR(frame);
1025 1006
@@ -1052,7 +1033,7 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1052 return -EINVAL; 1033 return -EINVAL;
1053 } 1034 }
1054 1035
1055 f = ctx_m2m_get_frame(ctx, cr->type); 1036 f = ctx_get_frame(ctx, cr->type);
1056 if (IS_ERR(f)) 1037 if (IS_ERR(f))
1057 return PTR_ERR(f); 1038 return PTR_ERR(f);
1058 1039
@@ -1136,7 +1117,7 @@ static void queue_init(void *priv, struct videobuf_queue *vq,
1136 struct fimc_dev *fimc = ctx->fimc_dev; 1117 struct fimc_dev *fimc = ctx->fimc_dev;
1137 1118
1138 videobuf_queue_dma_contig_init(vq, &fimc_qops, 1119 videobuf_queue_dma_contig_init(vq, &fimc_qops,
1139 fimc->m2m.v4l2_dev.dev, 1120 &fimc->pdev->dev,
1140 &fimc->irqlock, type, V4L2_FIELD_NONE, 1121 &fimc->irqlock, type, V4L2_FIELD_NONE,
1141 sizeof(struct fimc_vid_buffer), priv, NULL); 1122 sizeof(struct fimc_vid_buffer), priv, NULL);
1142} 1123}
@@ -1159,13 +1140,12 @@ static int fimc_m2m_open(struct file *file)
1159 1140
1160 file->private_data = ctx; 1141 file->private_data = ctx;
1161 ctx->fimc_dev = fimc; 1142 ctx->fimc_dev = fimc;
1162 /* default format */ 1143 /* Default color format */
1163 ctx->s_frame.fmt = &fimc_formats[0]; 1144 ctx->s_frame.fmt = &fimc_formats[0];
1164 ctx->d_frame.fmt = &fimc_formats[0]; 1145 ctx->d_frame.fmt = &fimc_formats[0];
1165 /* per user process device context initialization */ 1146 /* per user process device context initialization */
1166 ctx->state = 0; 1147 ctx->state = 0;
1167 ctx->flags = 0; 1148 ctx->flags = 0;
1168 ctx->effect.type = S5P_FIMC_EFFECT_ORIGINAL;
1169 ctx->in_path = FIMC_DMA; 1149 ctx->in_path = FIMC_DMA;
1170 ctx->out_path = FIMC_DMA; 1150 ctx->out_path = FIMC_DMA;
1171 spin_lock_init(&ctx->slock); 1151 spin_lock_init(&ctx->slock);
@@ -1241,7 +1221,7 @@ static int fimc_register_m2m_device(struct fimc_dev *fimc)
1241 1221
1242 ret = v4l2_device_register(&pdev->dev, v4l2_dev); 1222 ret = v4l2_device_register(&pdev->dev, v4l2_dev);
1243 if (ret) 1223 if (ret)
1244 return ret;; 1224 goto err_m2m_r1;
1245 1225
1246 vfd = video_device_alloc(); 1226 vfd = video_device_alloc();
1247 if (!vfd) { 1227 if (!vfd) {
@@ -1293,7 +1273,7 @@ static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
1293 if (fimc) { 1273 if (fimc) {
1294 v4l2_m2m_release(fimc->m2m.m2m_dev); 1274 v4l2_m2m_release(fimc->m2m.m2m_dev);
1295 video_unregister_device(fimc->m2m.vfd); 1275 video_unregister_device(fimc->m2m.vfd);
1296 video_device_release(fimc->m2m.vfd); 1276
1297 v4l2_device_unregister(&fimc->m2m.v4l2_dev); 1277 v4l2_device_unregister(&fimc->m2m.v4l2_dev);
1298 } 1278 }
1299} 1279}
@@ -1399,25 +1379,15 @@ static int fimc_probe(struct platform_device *pdev)
1399 goto err_clk; 1379 goto err_clk;
1400 } 1380 }
1401 1381
1402 fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev));
1403 if (!fimc->work_queue) {
1404 ret = -ENOMEM;
1405 goto err_irq;
1406 }
1407
1408 ret = fimc_register_m2m_device(fimc); 1382 ret = fimc_register_m2m_device(fimc);
1409 if (ret) 1383 if (ret)
1410 goto err_wq; 1384 goto err_irq;
1411
1412 fimc_hw_en_lastirq(fimc, true);
1413 1385
1414 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n", 1386 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
1415 __func__, fimc->id); 1387 __func__, fimc->id);
1416 1388
1417 return 0; 1389 return 0;
1418 1390
1419err_wq:
1420 destroy_workqueue(fimc->work_queue);
1421err_irq: 1391err_irq:
1422 free_irq(fimc->irq, fimc); 1392 free_irq(fimc->irq, fimc);
1423err_clk: 1393err_clk:
@@ -1429,7 +1399,7 @@ err_req_region:
1429 kfree(fimc->regs_res); 1399 kfree(fimc->regs_res);
1430err_info: 1400err_info:
1431 kfree(fimc); 1401 kfree(fimc);
1432 dev_err(&pdev->dev, "failed to install\n"); 1402
1433 return ret; 1403 return ret;
1434} 1404}
1435 1405
@@ -1438,10 +1408,7 @@ static int __devexit fimc_remove(struct platform_device *pdev)
1438 struct fimc_dev *fimc = 1408 struct fimc_dev *fimc =
1439 (struct fimc_dev *)platform_get_drvdata(pdev); 1409 (struct fimc_dev *)platform_get_drvdata(pdev);
1440 1410
1441 v4l2_info(&fimc->m2m.v4l2_dev, "Removing %s\n", pdev->name);
1442
1443 free_irq(fimc->irq, fimc); 1411 free_irq(fimc->irq, fimc);
1444
1445 fimc_hw_reset(fimc); 1412 fimc_hw_reset(fimc);
1446 1413
1447 fimc_unregister_m2m_device(fimc); 1414 fimc_unregister_m2m_device(fimc);
@@ -1450,6 +1417,8 @@ static int __devexit fimc_remove(struct platform_device *pdev)
1450 release_resource(fimc->regs_res); 1417 release_resource(fimc->regs_res);
1451 kfree(fimc->regs_res); 1418 kfree(fimc->regs_res);
1452 kfree(fimc); 1419 kfree(fimc);
1420
1421 dev_info(&pdev->dev, "%s driver unloaded\n", pdev->name);
1453 return 0; 1422 return 0;
1454} 1423}
1455 1424
@@ -1484,7 +1453,7 @@ static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
1484 .has_inp_rot = 1, 1453 .has_inp_rot = 1,
1485 .has_out_rot = 1, 1454 .has_out_rot = 1,
1486 .min_inp_pixsize = 16, 1455 .min_inp_pixsize = 16,
1487 .min_out_pixsize = 32, 1456 .min_out_pixsize = 16,
1488 1457
1489 .scaler_en_w = 4224, 1458 .scaler_en_w = 4224,
1490 .scaler_dis_w = 8192, 1459 .scaler_dis_w = 8192,
@@ -1497,7 +1466,7 @@ static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
1497static struct samsung_fimc_variant fimc2_variant_s5pv210 = { 1466static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
1498 .pix_hoff = 1, 1467 .pix_hoff = 1,
1499 .min_inp_pixsize = 16, 1468 .min_inp_pixsize = 16,
1500 .min_out_pixsize = 32, 1469 .min_out_pixsize = 16,
1501 1470
1502 .scaler_en_w = 1920, 1471 .scaler_en_w = 1920,
1503 .scaler_dis_w = 8192, 1472 .scaler_dis_w = 8192,
@@ -1547,20 +1516,12 @@ static struct platform_driver fimc_driver = {
1547 } 1516 }
1548}; 1517};
1549 1518
1550static char banner[] __initdata = KERN_INFO
1551 "S5PC Camera Interface V4L2 Driver, (c) 2010 Samsung Electronics\n";
1552
1553static int __init fimc_init(void) 1519static int __init fimc_init(void)
1554{ 1520{
1555 u32 ret; 1521 int ret = platform_driver_register(&fimc_driver);
1556 printk(banner); 1522 if (ret)
1557 1523 err("platform_driver_register failed: %d\n", ret);
1558 ret = platform_driver_register(&fimc_driver); 1524 return ret;
1559 if (ret) {
1560 printk(KERN_ERR "FIMC platform driver register failed\n");
1561 return -1;
1562 }
1563 return 0;
1564} 1525}
1565 1526
1566static void __exit fimc_exit(void) 1527static void __exit fimc_exit(void)
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 6b3e0cd73cdd..5aeb3efbd457 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -34,6 +34,7 @@
34#define FIMC_MAX_OUT_BUFS 4 34#define FIMC_MAX_OUT_BUFS 4
35#define SCALER_MAX_HRATIO 64 35#define SCALER_MAX_HRATIO 64
36#define SCALER_MAX_VRATIO 64 36#define SCALER_MAX_VRATIO 64
37#define DMA_MIN_SIZE 8
37 38
38enum { 39enum {
39 ST_IDLE, 40 ST_IDLE,
@@ -54,21 +55,21 @@ enum fimc_datapath {
54}; 55};
55 56
56enum fimc_color_fmt { 57enum fimc_color_fmt {
57 S5P_FIMC_RGB565, 58 S5P_FIMC_RGB565 = 0x10,
58 S5P_FIMC_RGB666, 59 S5P_FIMC_RGB666,
59 S5P_FIMC_RGB888, 60 S5P_FIMC_RGB888,
60 S5P_FIMC_YCBCR420, 61 S5P_FIMC_RGB30_LOCAL,
62 S5P_FIMC_YCBCR420 = 0x20,
61 S5P_FIMC_YCBCR422, 63 S5P_FIMC_YCBCR422,
62 S5P_FIMC_YCBYCR422, 64 S5P_FIMC_YCBYCR422,
63 S5P_FIMC_YCRYCB422, 65 S5P_FIMC_YCRYCB422,
64 S5P_FIMC_CBYCRY422, 66 S5P_FIMC_CBYCRY422,
65 S5P_FIMC_CRYCBY422, 67 S5P_FIMC_CRYCBY422,
66 S5P_FIMC_RGB30_LOCAL,
67 S5P_FIMC_YCBCR444_LOCAL, 68 S5P_FIMC_YCBCR444_LOCAL,
68 S5P_FIMC_MAX_COLOR = S5P_FIMC_YCBCR444_LOCAL,
69 S5P_FIMC_COLOR_MASK = 0x0F,
70}; 69};
71 70
71#define fimc_fmt_is_rgb(x) ((x) & 0x10)
72
72/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */ 73/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */
73#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY 74#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY
74#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB 75#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB
@@ -93,11 +94,13 @@ enum fimc_color_fmt {
93#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE 94#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE
94 95
95/* The hardware context state. */ 96/* The hardware context state. */
96#define FIMC_PARAMS (1 << 0) 97#define FIMC_PARAMS (1 << 0)
97#define FIMC_SRC_ADDR (1 << 1) 98#define FIMC_SRC_ADDR (1 << 1)
98#define FIMC_DST_ADDR (1 << 2) 99#define FIMC_DST_ADDR (1 << 2)
99#define FIMC_SRC_FMT (1 << 3) 100#define FIMC_SRC_FMT (1 << 3)
100#define FIMC_DST_FMT (1 << 4) 101#define FIMC_DST_FMT (1 << 4)
102#define FIMC_CTX_M2M (1 << 5)
103#define FIMC_CTX_CAP (1 << 6)
101 104
102/* Image conversion flags */ 105/* Image conversion flags */
103#define FIMC_IN_DMA_ACCESS_TILED (1 << 0) 106#define FIMC_IN_DMA_ACCESS_TILED (1 << 0)
@@ -106,7 +109,9 @@ enum fimc_color_fmt {
106#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1) 109#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1)
107#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2) 110#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2)
108#define FIMC_SCAN_MODE_INTERLACED (1 << 2) 111#define FIMC_SCAN_MODE_INTERLACED (1 << 2)
109/* YCbCr data dynamic range for RGB-YUV color conversion. Y/Cb/Cr: (0 ~ 255) */ 112/*
113 * YCbCr data dynamic range for RGB-YUV color conversion.
114 * Y/Cb/Cr: (0 ~ 255) */
110#define FIMC_COLOR_RANGE_WIDE (0 << 3) 115#define FIMC_COLOR_RANGE_WIDE (0 << 3)
111/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */ 116/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */
112#define FIMC_COLOR_RANGE_NARROW (1 << 3) 117#define FIMC_COLOR_RANGE_NARROW (1 << 3)
@@ -167,37 +172,37 @@ struct fimc_effect {
167/** 172/**
168 * struct fimc_scaler - the configuration data for FIMC inetrnal scaler 173 * struct fimc_scaler - the configuration data for FIMC inetrnal scaler
169 * 174 *
170 * @enabled: the flag set when the scaler is used 175 * @scaleup_h: flag indicating scaling up horizontally
176 * @scaleup_v: flag indicating scaling up vertically
177 * @copy_mode: flag indicating transparent DMA transfer (no scaling
178 * and color format conversion)
179 * @enabled: flag indicating if the scaler is used
171 * @hfactor: horizontal shift factor 180 * @hfactor: horizontal shift factor
172 * @vfactor: vertical shift factor 181 * @vfactor: vertical shift factor
173 * @pre_hratio: horizontal ratio of the prescaler 182 * @pre_hratio: horizontal ratio of the prescaler
174 * @pre_vratio: vertical ratio of the prescaler 183 * @pre_vratio: vertical ratio of the prescaler
175 * @pre_dst_width: the prescaler's destination width 184 * @pre_dst_width: the prescaler's destination width
176 * @pre_dst_height: the prescaler's destination height 185 * @pre_dst_height: the prescaler's destination height
177 * @scaleup_h: flag indicating scaling up horizontally
178 * @scaleup_v: flag indicating scaling up vertically
179 * @main_hratio: the main scaler's horizontal ratio 186 * @main_hratio: the main scaler's horizontal ratio
180 * @main_vratio: the main scaler's vertical ratio 187 * @main_vratio: the main scaler's vertical ratio
181 * @real_width: source width - offset 188 * @real_width: source pixel (width - offset)
182 * @real_height: source height - offset 189 * @real_height: source pixel (height - offset)
183 * @copy_mode: flag set if one-to-one mode is used, i.e. no scaling
184 * and color format conversion
185 */ 190 */
186struct fimc_scaler { 191struct fimc_scaler {
187 u32 enabled; 192 int scaleup_h:1;
193 int scaleup_v:1;
194 int copy_mode:1;
195 int enabled:1;
188 u32 hfactor; 196 u32 hfactor;
189 u32 vfactor; 197 u32 vfactor;
190 u32 pre_hratio; 198 u32 pre_hratio;
191 u32 pre_vratio; 199 u32 pre_vratio;
192 u32 pre_dst_width; 200 u32 pre_dst_width;
193 u32 pre_dst_height; 201 u32 pre_dst_height;
194 u32 scaleup_h;
195 u32 scaleup_v;
196 u32 main_hratio; 202 u32 main_hratio;
197 u32 main_vratio; 203 u32 main_vratio;
198 u32 real_width; 204 u32 real_width;
199 u32 real_height; 205 u32 real_height;
200 u32 copy_mode;
201}; 206};
202 207
203/** 208/**
@@ -222,8 +227,7 @@ struct fimc_vid_buffer {
222}; 227};
223 228
224/** 229/**
225 * struct fimc_frame - input/output frame format properties 230 * struct fimc_frame - source/target frame properties
226 *
227 * @f_width: image full width (virtual screen size) 231 * @f_width: image full width (virtual screen size)
228 * @f_height: image full height (virtual screen size) 232 * @f_height: image full height (virtual screen size)
229 * @o_width: original image width as set by S_FMT 233 * @o_width: original image width as set by S_FMT
@@ -279,10 +283,10 @@ struct fimc_m2m_device {
279 * @min_out_pixsize: minimum output pixel size 283 * @min_out_pixsize: minimum output pixel size
280 * @scaler_en_w: maximum input pixel width when the scaler is enabled 284 * @scaler_en_w: maximum input pixel width when the scaler is enabled
281 * @scaler_dis_w: maximum input pixel width when the scaler is disabled 285 * @scaler_dis_w: maximum input pixel width when the scaler is disabled
282 * @in_rot_en_h: maximum input width when the input rotator is used 286 * @in_rot_en_h: maximum input width when the input rotator is enabled
283 * @in_rot_dis_w: maximum input width when the input rotator is used 287 * @in_rot_dis_w: maximum input width when the input rotator is disabled
284 * @out_rot_en_w: maximum output width for the output rotator enabled 288 * @out_rot_en_w: maximum target width when the output rotator enabled
285 * @out_rot_dis_w: maximum output width for the output rotator enabled 289 * @out_rot_dis_w: maximum target width when the output rotator disnabled
286 */ 290 */
287struct samsung_fimc_variant { 291struct samsung_fimc_variant {
288 unsigned int pix_hoff:1; 292 unsigned int pix_hoff:1;
@@ -300,7 +304,7 @@ struct samsung_fimc_variant {
300}; 304};
301 305
302/** 306/**
303 * struct samsung_fimc_driverdata - per-device type driver data for init time. 307 * struct samsung_fimc_driverdata - per device type driver data for init time.
304 * 308 *
305 * @variant: the variant information for this driver. 309 * @variant: the variant information for this driver.
306 * @dev_cnt: number of fimc sub-devices available in SoC 310 * @dev_cnt: number of fimc sub-devices available in SoC
@@ -313,7 +317,7 @@ struct samsung_fimc_driverdata {
313struct fimc_ctx; 317struct fimc_ctx;
314 318
315/** 319/**
316 * struct fimc_subdev - abstraction for a FIMC entity 320 * struct fimc_dev - abstraction for FIMC entity
317 * 321 *
318 * @slock: the spinlock protecting this data structure 322 * @slock: the spinlock protecting this data structure
319 * @lock: the mutex protecting this data structure 323 * @lock: the mutex protecting this data structure
@@ -323,7 +327,7 @@ struct fimc_ctx;
323 * @regs: the mapped hardware registers 327 * @regs: the mapped hardware registers
324 * @regs_res: the resource claimed for IO registers 328 * @regs_res: the resource claimed for IO registers
325 * @irq: interrupt number of the FIMC subdevice 329 * @irq: interrupt number of the FIMC subdevice
326 * @irqlock: spinlock protecting videbuffer queue 330 * @irqlock: spinlock protecting videobuffer queue
327 * @m2m: memory-to-memory V4L2 device information 331 * @m2m: memory-to-memory V4L2 device information
328 * @state: the FIMC device state flags 332 * @state: the FIMC device state flags
329 */ 333 */
@@ -338,7 +342,6 @@ struct fimc_dev {
338 struct resource *regs_res; 342 struct resource *regs_res;
339 int irq; 343 int irq;
340 spinlock_t irqlock; 344 spinlock_t irqlock;
341 struct workqueue_struct *work_queue;
342 struct fimc_m2m_device m2m; 345 struct fimc_m2m_device m2m;
343 unsigned long state; 346 unsigned long state;
344}; 347};
@@ -359,7 +362,7 @@ struct fimc_dev {
359 * @effect: image effect 362 * @effect: image effect
360 * @rotation: image clockwise rotation in degrees 363 * @rotation: image clockwise rotation in degrees
361 * @flip: image flip mode 364 * @flip: image flip mode
362 * @flags: an additional flags for image conversion 365 * @flags: additional flags for image conversion
363 * @state: flags to keep track of user configuration 366 * @state: flags to keep track of user configuration
364 * @fimc_dev: the FIMC device this context applies to 367 * @fimc_dev: the FIMC device this context applies to
365 * @m2m_ctx: memory-to-memory device context 368 * @m2m_ctx: memory-to-memory device context
@@ -397,18 +400,24 @@ static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
397 writel(cfg, dev->regs + S5P_CIGCTRL); 400 writel(cfg, dev->regs + S5P_CIGCTRL);
398} 401}
399 402
400static inline void fimc_hw_start_scaler(struct fimc_dev *dev) 403static inline void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on)
401{ 404{
402 u32 cfg = readl(dev->regs + S5P_CISCCTRL); 405 u32 cfg = readl(dev->regs + S5P_CISCCTRL);
403 cfg |= S5P_CISCCTRL_SCALERSTART; 406 if (on)
407 cfg |= S5P_CISCCTRL_SCALERSTART;
408 else
409 cfg &= ~S5P_CISCCTRL_SCALERSTART;
404 writel(cfg, dev->regs + S5P_CISCCTRL); 410 writel(cfg, dev->regs + S5P_CISCCTRL);
405} 411}
406 412
407static inline void fimc_hw_stop_scaler(struct fimc_dev *dev) 413static inline void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
408{ 414{
409 u32 cfg = readl(dev->regs + S5P_CISCCTRL); 415 u32 cfg = readl(dev->regs + S5P_MSCTRL);
410 cfg &= ~S5P_CISCCTRL_SCALERSTART; 416 if (on)
411 writel(cfg, dev->regs + S5P_CISCCTRL); 417 cfg |= S5P_MSCTRL_ENVID;
418 else
419 cfg &= ~S5P_MSCTRL_ENVID;
420 writel(cfg, dev->regs + S5P_MSCTRL);
412} 421}
413 422
414static inline void fimc_hw_dis_capture(struct fimc_dev *dev) 423static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
@@ -418,22 +427,8 @@ static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
418 writel(cfg, dev->regs + S5P_CIIMGCPT); 427 writel(cfg, dev->regs + S5P_CIIMGCPT);
419} 428}
420 429
421static inline void fimc_hw_start_in_dma(struct fimc_dev *dev) 430static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
422{ 431 enum v4l2_buf_type type)
423 u32 cfg = readl(dev->regs + S5P_MSCTRL);
424 cfg |= S5P_MSCTRL_ENVID;
425 writel(cfg, dev->regs + S5P_MSCTRL);
426}
427
428static inline void fimc_hw_stop_in_dma(struct fimc_dev *dev)
429{
430 u32 cfg = readl(dev->regs + S5P_MSCTRL);
431 cfg &= ~S5P_MSCTRL_ENVID;
432 writel(cfg, dev->regs + S5P_MSCTRL);
433}
434
435static inline struct fimc_frame *ctx_m2m_get_frame(struct fimc_ctx *ctx,
436 enum v4l2_buf_type type)
437{ 432{
438 struct fimc_frame *frame; 433 struct fimc_frame *frame;
439 434
@@ -452,20 +447,35 @@ static inline struct fimc_frame *ctx_m2m_get_frame(struct fimc_ctx *ctx,
452 447
453/* -----------------------------------------------------*/ 448/* -----------------------------------------------------*/
454/* fimc-reg.c */ 449/* fimc-reg.c */
455void fimc_hw_reset(struct fimc_dev *dev); 450void fimc_hw_reset(struct fimc_dev *fimc);
456void fimc_hw_set_rotation(struct fimc_ctx *ctx); 451void fimc_hw_set_rotation(struct fimc_ctx *ctx);
457void fimc_hw_set_target_format(struct fimc_ctx *ctx); 452void fimc_hw_set_target_format(struct fimc_ctx *ctx);
458void fimc_hw_set_out_dma(struct fimc_ctx *ctx); 453void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
459void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable); 454void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable);
460void fimc_hw_en_irq(struct fimc_dev *dev, int enable); 455void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
461void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
462void fimc_hw_set_scaler(struct fimc_ctx *ctx); 456void fimc_hw_set_scaler(struct fimc_ctx *ctx);
463void fimc_hw_en_capture(struct fimc_ctx *ctx); 457void fimc_hw_en_capture(struct fimc_ctx *ctx);
464void fimc_hw_set_effect(struct fimc_ctx *ctx); 458void fimc_hw_set_effect(struct fimc_ctx *ctx);
465void fimc_hw_set_in_dma(struct fimc_ctx *ctx); 459void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
466void fimc_hw_set_input_path(struct fimc_ctx *ctx); 460void fimc_hw_set_input_path(struct fimc_ctx *ctx);
467void fimc_hw_set_output_path(struct fimc_ctx *ctx); 461void fimc_hw_set_output_path(struct fimc_ctx *ctx);
468void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr); 462void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
469void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr); 463void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
464 int index);
465
466/* Locking: the caller holds fimc->slock */
467static inline void fimc_activate_capture(struct fimc_ctx *ctx)
468{
469 fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
470 fimc_hw_en_capture(ctx);
471}
472
473static inline void fimc_deactivate_capture(struct fimc_dev *fimc)
474{
475 fimc_hw_en_lastirq(fimc, true);
476 fimc_hw_dis_capture(fimc);
477 fimc_hw_enable_scaler(fimc, false);
478 fimc_hw_en_lastirq(fimc, false);
479}
470 480
471#endif /* FIMC_CORE_H_ */ 481#endif /* FIMC_CORE_H_ */
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 70f29c5a6d10..94e98d47a7d0 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -29,7 +29,7 @@ void fimc_hw_reset(struct fimc_dev *dev)
29 cfg = readl(dev->regs + S5P_CIGCTRL); 29 cfg = readl(dev->regs + S5P_CIGCTRL);
30 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL); 30 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
31 writel(cfg, dev->regs + S5P_CIGCTRL); 31 writel(cfg, dev->regs + S5P_CIGCTRL);
32 msleep(1); 32 udelay(1000);
33 33
34 cfg = readl(dev->regs + S5P_CIGCTRL); 34 cfg = readl(dev->regs + S5P_CIGCTRL);
35 cfg &= ~S5P_CIGCTRL_SWRST; 35 cfg &= ~S5P_CIGCTRL_SWRST;
@@ -247,21 +247,20 @@ void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
247 spin_unlock_irqrestore(&dev->slock, flags); 247 spin_unlock_irqrestore(&dev->slock, flags);
248} 248}
249 249
250void fimc_hw_set_prescaler(struct fimc_ctx *ctx) 250static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
251{ 251{
252 struct fimc_dev *dev = ctx->fimc_dev; 252 struct fimc_dev *dev = ctx->fimc_dev;
253 struct fimc_scaler *sc = &ctx->scaler; 253 struct fimc_scaler *sc = &ctx->scaler;
254 u32 cfg = 0, shfactor; 254 u32 cfg, shfactor;
255 255
256 shfactor = 10 - (sc->hfactor + sc->vfactor); 256 shfactor = 10 - (sc->hfactor + sc->vfactor);
257 257
258 cfg |= S5P_CISCPRERATIO_SHFACTOR(shfactor); 258 cfg = S5P_CISCPRERATIO_SHFACTOR(shfactor);
259 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio); 259 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio);
260 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio); 260 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio);
261 writel(cfg, dev->regs + S5P_CISCPRERATIO); 261 writel(cfg, dev->regs + S5P_CISCPRERATIO);
262 262
263 cfg = 0; 263 cfg = S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
264 cfg |= S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
265 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height); 264 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height);
266 writel(cfg, dev->regs + S5P_CISCPREDST); 265 writel(cfg, dev->regs + S5P_CISCPREDST);
267} 266}
@@ -274,6 +273,8 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
274 struct fimc_frame *dst_frame = &ctx->d_frame; 273 struct fimc_frame *dst_frame = &ctx->d_frame;
275 u32 cfg = 0; 274 u32 cfg = 0;
276 275
276 fimc_hw_set_prescaler(ctx);
277
277 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) 278 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
278 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE); 279 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
279 280
@@ -364,7 +365,7 @@ static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
364 u32 cfg_r = 0; 365 u32 cfg_r = 0;
365 366
366 if (FIMC_LCDFIFO == ctx->out_path) 367 if (FIMC_LCDFIFO == ctx->out_path)
367 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN; 368 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
368 369
369 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width); 370 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width);
370 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height); 371 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height);
@@ -380,27 +381,25 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
380 struct fimc_dev *dev = ctx->fimc_dev; 381 struct fimc_dev *dev = ctx->fimc_dev;
381 struct fimc_frame *frame = &ctx->s_frame; 382 struct fimc_frame *frame = &ctx->s_frame;
382 struct fimc_dma_offset *offset = &frame->dma_offset; 383 struct fimc_dma_offset *offset = &frame->dma_offset;
383 u32 cfg = 0; 384 u32 cfg;
384 385
385 /* Set the pixel offsets. */ 386 /* Set the pixel offsets. */
386 cfg |= S5P_CIO_OFFS_HOR(offset->y_h); 387 cfg = S5P_CIO_OFFS_HOR(offset->y_h);
387 cfg |= S5P_CIO_OFFS_VER(offset->y_v); 388 cfg |= S5P_CIO_OFFS_VER(offset->y_v);
388 writel(cfg, dev->regs + S5P_CIIYOFF); 389 writel(cfg, dev->regs + S5P_CIIYOFF);
389 390
390 cfg = 0; 391 cfg = S5P_CIO_OFFS_HOR(offset->cb_h);
391 cfg |= S5P_CIO_OFFS_HOR(offset->cb_h);
392 cfg |= S5P_CIO_OFFS_VER(offset->cb_v); 392 cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
393 writel(cfg, dev->regs + S5P_CIICBOFF); 393 writel(cfg, dev->regs + S5P_CIICBOFF);
394 394
395 cfg = 0; 395 cfg = S5P_CIO_OFFS_HOR(offset->cr_h);
396 cfg |= S5P_CIO_OFFS_HOR(offset->cr_h);
397 cfg |= S5P_CIO_OFFS_VER(offset->cr_v); 396 cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
398 writel(cfg, dev->regs + S5P_CIICROFF); 397 writel(cfg, dev->regs + S5P_CIICROFF);
399 398
400 /* Input original and real size. */ 399 /* Input original and real size. */
401 fimc_hw_set_in_dma_size(ctx); 400 fimc_hw_set_in_dma_size(ctx);
402 401
403 /* Autoload is used currently only in FIFO mode. */ 402 /* Use DMA autoload only in FIFO mode. */
404 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO); 403 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
405 404
406 /* Set the input DMA to process single frame only. */ 405 /* Set the input DMA to process single frame only. */
@@ -501,9 +500,7 @@ void fimc_hw_set_output_path(struct fimc_ctx *ctx)
501 500
502void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr) 501void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
503{ 502{
504 u32 cfg = 0; 503 u32 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
505
506 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
507 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS; 504 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS;
508 writel(cfg, dev->regs + S5P_CIREAL_ISIZE); 505 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
509 506
@@ -515,13 +512,15 @@ void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
515 writel(cfg, dev->regs + S5P_CIREAL_ISIZE); 512 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
516} 513}
517 514
518void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr) 515void fimc_hw_set_output_addr(struct fimc_dev *dev,
516 struct fimc_addr *paddr, int index)
519{ 517{
520 int i; 518 int i = (index == -1) ? 0 : index;
521 /* Set all the output register sets to point to single video buffer. */ 519 do {
522 for (i = 0; i < FIMC_MAX_OUT_BUFS; i++) {
523 writel(paddr->y, dev->regs + S5P_CIOYSA(i)); 520 writel(paddr->y, dev->regs + S5P_CIOYSA(i));
524 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i)); 521 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i));
525 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i)); 522 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i));
526 } 523 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
524 i, paddr->y, paddr->cb, paddr->cr);
525 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
527} 526}