/** * s3c_camif_find_format() - lookup camif color format by fourcc or an index * @vp: video path (DMA) description (codec/preview) * @pixelformat: fourcc to match, ignored if null * @index: index to the camif_formats array, ignored if negative
*/ conststruct camif_fmt *s3c_camif_find_format(struct camif_vp *vp, const u32 *pixelformat, int index)
{ conststruct camif_fmt *fmt, *def_fmt = NULL; unsignedint i; int id = 0;
if (index >= (int)ARRAY_SIZE(camif_formats)) return NULL;
for (i = 0; i < ARRAY_SIZE(camif_formats); ++i) {
fmt = &camif_formats[i]; if (vp && !(vp->fmt_flags & fmt->flags)) continue; if (pixelformat && fmt->fourcc == *pixelformat) return fmt; if (index == id)
def_fmt = fmt;
id++;
} return def_fmt;
}
staticint camif_create_media_links(struct camif_dev *camif)
{ int i, ret;
ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
&camif->subdev.entity, CAMIF_SD_PAD_SINK,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED); if (ret) return ret;
for (i = 1; i < CAMIF_SD_PADS_NUM && !ret; i++) {
ret = media_create_pad_link(&camif->subdev.entity, i,
&camif->vp[i - 1].vdev.entity, 0,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
}
return ret;
}
staticint camif_register_video_nodes(struct camif_dev *camif)
{ int ret = s3c_camif_register_video_node(camif, VP_CODEC); if (ret < 0) return ret;
ret = v4l2_device_register(camif->dev, v4l2_dev); if (ret < 0) return ret;
return ret;
}
staticvoid camif_clk_put(struct camif_dev *camif)
{ int i;
for (i = 0; i < CLK_MAX_NUM; i++) { if (IS_ERR(camif->clock[i])) continue;
clk_unprepare(camif->clock[i]);
clk_put(camif->clock[i]);
camif->clock[i] = ERR_PTR(-EINVAL);
}
}
staticint camif_clk_get(struct camif_dev *camif)
{ int ret, i;
for (i = 1; i < CLK_MAX_NUM; i++)
camif->clock[i] = ERR_PTR(-EINVAL);
for (i = 0; i < CLK_MAX_NUM; i++) {
camif->clock[i] = clk_get(camif->dev, camif_clocks[i]); if (IS_ERR(camif->clock[i])) {
ret = PTR_ERR(camif->clock[i]); goto err;
}
ret = clk_prepare(camif->clock[i]); if (ret < 0) {
clk_put(camif->clock[i]);
camif->clock[i] = NULL; goto err;
}
} return 0;
err:
camif_clk_put(camif);
dev_err(camif->dev, "failed to get clock: %s\n",
camif_clocks[i]); return ret;
}
/* * The CAMIF device has two relatively independent data processing paths * that can source data from memory or the common camera input frontend. * Register interrupts for each data processing path (camif_vp).
*/ staticint camif_request_irqs(struct platform_device *pdev, struct camif_dev *camif)
{ int irq, ret, i;
for (i = 0; i < CAMIF_VP_NUM; i++) { struct camif_vp *vp = &camif->vp[i];
init_waitqueue_head(&vp->irq_queue);
irq = platform_get_irq(pdev, i); if (irq < 0) return irq;
ret = devm_request_irq(&pdev->dev, irq, s3c_camif_irq_handler,
0, dev_name(&pdev->dev), vp); if (ret < 0) {
dev_err(&pdev->dev, "failed to install IRQ: %d\n", ret); break;
}
}
dev_info(dev, "sensor clock frequency: %lu\n",
clk_get_rate(camif->clock[CLK_CAM])); /* * Set initial pixel format, resolution and crop rectangle. * Must be done before a sensor subdev is registered as some * settings are overrode with values from sensor subdev.
*/
s3c_camif_set_defaults(camif);
pm_runtime_enable(dev);
ret = pm_runtime_resume_and_get(dev); if (ret < 0) goto err_disable;
ret = camif_media_dev_init(camif); if (ret < 0) goto err_pm;
ret = camif_register_sensor(camif); if (ret < 0) goto err_sens;
ret = v4l2_device_register_subdev(&camif->v4l2_dev, &camif->subdev); if (ret < 0) goto err_sens;
ret = v4l2_device_register_subdev_nodes(&camif->v4l2_dev); if (ret < 0) goto err_sens;
ret = camif_register_video_nodes(camif); if (ret < 0) goto err_sens;
ret = camif_create_media_links(camif); if (ret < 0) goto err_sens;
ret = media_device_register(&camif->media_dev); if (ret < 0) goto err_sens;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.