aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pxa_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2008-12-18 09:38:03 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:40:19 -0500
commitcf34cba78d0e0a7244bd7f11addb4d971293fb30 (patch)
treec7478141810e57e31c47503fbc9c02683f71869f /drivers/media/video/pxa_camera.c
parenta9bef518cd78d569a3ff0b1ac2afa5e2d8b3573a (diff)
V4L/DVB (10075): pxa-camera: setup the FIFO inactivity time-out register
Using PXA270's FIFO inactivity time-out register (CITOR) reduces FIFO overruns. The time-out is calculated in CICLK / LCDCLK ticks and has to be longer than one pixel time. For this we have to know the pixel clock frequency, which usually is provided by the camera. We use the struct soc_camera_sense to request PCLK frequency from the camera driver upon each data format change. Tested-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pxa_camera.c')
-rw-r--r--drivers/media/video/pxa_camera.c90
1 files changed, 69 insertions, 21 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 45040f99031d..28ea13f7b2b0 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -215,7 +215,9 @@ struct pxa_camera_dev {
215 struct pxacamera_platform_data *pdata; 215 struct pxacamera_platform_data *pdata;
216 struct resource *res; 216 struct resource *res;
217 unsigned long platform_flags; 217 unsigned long platform_flags;
218 unsigned long platform_mclk_10khz; 218 unsigned long ciclk;
219 unsigned long mclk;
220 u32 mclk_divisor;
219 221
220 struct list_head capture; 222 struct list_head capture;
221 223
@@ -707,24 +709,43 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
707 sizeof(struct pxa_buffer), icd); 709 sizeof(struct pxa_buffer), icd);
708} 710}
709 711
710static int mclk_get_divisor(struct pxa_camera_dev *pcdev) 712static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
711{ 713{
712 unsigned int mclk_10khz = pcdev->platform_mclk_10khz; 714 unsigned long mclk = pcdev->mclk;
713 unsigned long div; 715 u32 div;
714 unsigned long lcdclk; 716 unsigned long lcdclk;
715 717
716 lcdclk = clk_get_rate(pcdev->clk) / 10000; 718 lcdclk = clk_get_rate(pcdev->clk);
719 pcdev->ciclk = lcdclk;
717 720
718 /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here 721 /* mclk <= ciclk / 4 (27.4.2) */
719 * they get a nice Oops */ 722 if (mclk > lcdclk / 4) {
720 div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1; 723 mclk = lcdclk / 4;
724 dev_warn(pcdev->dev, "Limiting master clock to %lu\n", mclk);
725 }
726
727 /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
728 div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
729
730 /* If we're not supplying MCLK, leave it at 0 */
731 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
732 pcdev->mclk = lcdclk / (2 * (div + 1));
721 733
722 dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, " 734 dev_dbg(pcdev->dev, "LCD clock %luHz, target freq %luHz, "
723 "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div); 735 "divisor %u\n", lcdclk, mclk, div);
724 736
725 return div; 737 return div;
726} 738}
727 739
740static void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev,
741 unsigned long pclk)
742{
743 /* We want a timeout > 1 pixel time, not ">=" */
744 u32 ciclk_per_pixel = pcdev->ciclk / pclk + 1;
745
746 __raw_writel(ciclk_per_pixel, pcdev->base + CITOR);
747}
748
728static void pxa_camera_activate(struct pxa_camera_dev *pcdev) 749static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
729{ 750{
730 struct pxacamera_platform_data *pdata = pcdev->pdata; 751 struct pxacamera_platform_data *pdata = pcdev->pdata;
@@ -752,8 +773,14 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
752 if (pcdev->platform_flags & PXA_CAMERA_VSP) 773 if (pcdev->platform_flags & PXA_CAMERA_VSP)
753 cicr4 |= CICR4_VSP; 774 cicr4 |= CICR4_VSP;
754 775
755 cicr4 |= mclk_get_divisor(pcdev); 776 __raw_writel(pcdev->mclk_divisor | cicr4, pcdev->base + CICR4);
756 __raw_writel(cicr4, pcdev->base + CICR4); 777
778 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
779 /* Initialise the timeout under the assumption pclk = mclk */
780 recalculate_fifo_timeout(pcdev, pcdev->mclk);
781 else
782 /* "Safe default" - 13MHz */
783 recalculate_fifo_timeout(pcdev, 13000000);
757 784
758 clk_enable(pcdev->clk); 785 clk_enable(pcdev->clk);
759} 786}
@@ -1000,7 +1027,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1000 cicr2 = 0; 1027 cicr2 = 0;
1001 cicr3 = CICR3_LPF_VAL(icd->height - 1) | 1028 cicr3 = CICR3_LPF_VAL(icd->height - 1) |
1002 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); 1029 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
1003 cicr4 |= mclk_get_divisor(pcdev); 1030 cicr4 |= pcdev->mclk_divisor;
1004 1031
1005 __raw_writel(cicr1, pcdev->base + CICR1); 1032 __raw_writel(cicr1, pcdev->base + CICR1);
1006 __raw_writel(cicr2, pcdev->base + CICR2); 1033 __raw_writel(cicr2, pcdev->base + CICR2);
@@ -1019,8 +1046,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1019static int pxa_camera_try_bus_param(struct soc_camera_device *icd, 1046static int pxa_camera_try_bus_param(struct soc_camera_device *icd,
1020 unsigned char buswidth) 1047 unsigned char buswidth)
1021{ 1048{
1022 struct soc_camera_host *ici = 1049 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1023 to_soc_camera_host(icd->dev.parent);
1024 struct pxa_camera_dev *pcdev = ici->priv; 1050 struct pxa_camera_dev *pcdev = ici->priv;
1025 unsigned long bus_flags, camera_flags; 1051 unsigned long bus_flags, camera_flags;
1026 int ret = test_platform_param(pcdev, buswidth, &bus_flags); 1052 int ret = test_platform_param(pcdev, buswidth, &bus_flags);
@@ -1136,8 +1162,13 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
1136 __u32 pixfmt, struct v4l2_rect *rect) 1162 __u32 pixfmt, struct v4l2_rect *rect)
1137{ 1163{
1138 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 1164 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1165 struct pxa_camera_dev *pcdev = ici->priv;
1139 const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL; 1166 const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL;
1140 const struct soc_camera_format_xlate *xlate; 1167 const struct soc_camera_format_xlate *xlate;
1168 struct soc_camera_sense sense = {
1169 .master_clock = pcdev->mclk,
1170 .pixel_clock_max = pcdev->ciclk / 4,
1171 };
1141 int ret, buswidth; 1172 int ret, buswidth;
1142 1173
1143 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); 1174 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
@@ -1150,6 +1181,10 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
1150 host_fmt = xlate->host_fmt; 1181 host_fmt = xlate->host_fmt;
1151 cam_fmt = xlate->cam_fmt; 1182 cam_fmt = xlate->cam_fmt;
1152 1183
1184 /* If PCLK is used to latch data from the sensor, check sense */
1185 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
1186 icd->sense = &sense;
1187
1153 switch (pixfmt) { 1188 switch (pixfmt) {
1154 case 0: /* Only geometry change */ 1189 case 0: /* Only geometry change */
1155 ret = icd->ops->set_fmt(icd, pixfmt, rect); 1190 ret = icd->ops->set_fmt(icd, pixfmt, rect);
@@ -1158,9 +1193,20 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
1158 ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect); 1193 ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect);
1159 } 1194 }
1160 1195
1161 if (ret < 0) 1196 icd->sense = NULL;
1197
1198 if (ret < 0) {
1162 dev_warn(&ici->dev, "Failed to configure for format %x\n", 1199 dev_warn(&ici->dev, "Failed to configure for format %x\n",
1163 pixfmt); 1200 pixfmt);
1201 } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
1202 if (sense.pixel_clock > sense.pixel_clock_max) {
1203 dev_err(&ici->dev,
1204 "pixel clock %lu set by the camera too high!",
1205 sense.pixel_clock);
1206 return -EIO;
1207 }
1208 recalculate_fifo_timeout(pcdev, sense.pixel_clock);
1209 }
1164 1210
1165 if (pixfmt && !ret) { 1211 if (pixfmt && !ret) {
1166 icd->buswidth = buswidth; 1212 icd->buswidth = buswidth;
@@ -1369,14 +1415,17 @@ static int pxa_camera_probe(struct platform_device *pdev)
1369 "data widths, using default 10 bit\n"); 1415 "data widths, using default 10 bit\n");
1370 pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; 1416 pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
1371 } 1417 }
1372 pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz; 1418 pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
1373 if (!pcdev->platform_mclk_10khz) { 1419 if (!pcdev->mclk) {
1374 dev_warn(&pdev->dev, 1420 dev_warn(&pdev->dev,
1375 "mclk_10khz == 0! Please, fix your platform data. " 1421 "mclk == 0! Please, fix your platform data. "
1376 "Using default 20MHz\n"); 1422 "Using default 20MHz\n");
1377 pcdev->platform_mclk_10khz = 2000; 1423 pcdev->mclk = 20000000;
1378 } 1424 }
1379 1425
1426 pcdev->dev = &pdev->dev;
1427 pcdev->mclk_divisor = mclk_get_divisor(pcdev);
1428
1380 INIT_LIST_HEAD(&pcdev->capture); 1429 INIT_LIST_HEAD(&pcdev->capture);
1381 spin_lock_init(&pcdev->lock); 1430 spin_lock_init(&pcdev->lock);
1382 1431
@@ -1396,7 +1445,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
1396 } 1445 }
1397 pcdev->irq = irq; 1446 pcdev->irq = irq;
1398 pcdev->base = base; 1447 pcdev->base = base;
1399 pcdev->dev = &pdev->dev;
1400 1448
1401 /* request dma */ 1449 /* request dma */
1402 err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, 1450 err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,