0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/dma-mapping.h>
0009 #include <linux/font.h>
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 #include <linux/platform_device.h>
0013 #include <media/media-device.h>
0014 #include <media/tpg/v4l2-tpg.h>
0015 #include <media/v4l2-device.h>
0016
0017 #include "vimc-common.h"
0018
0019 unsigned int vimc_allocator;
0020 module_param_named(allocator, vimc_allocator, uint, 0444);
0021 MODULE_PARM_DESC(allocator, " memory allocator selection, default is 0.\n"
0022 "\t\t 0 == vmalloc\n"
0023 "\t\t 1 == dma-contig");
0024
0025 #define VIMC_MDEV_MODEL_NAME "VIMC MDEV"
0026
0027 #define VIMC_DATA_LINK(src, srcpad, sink, sinkpad, link_flags) { \
0028 .src_ent = src, \
0029 .src_pad = srcpad, \
0030 .sink_ent = sink, \
0031 .sink_pad = sinkpad, \
0032 .flags = link_flags, \
0033 }
0034
0035 #define VIMC_ANCILLARY_LINK(primary, ancillary) { \
0036 .primary_ent = primary, \
0037 .ancillary_ent = ancillary \
0038 }
0039
0040
0041 struct vimc_data_link {
0042 unsigned int src_ent;
0043 u16 src_pad;
0044 unsigned int sink_ent;
0045 u16 sink_pad;
0046 u32 flags;
0047 };
0048
0049
0050 enum vimc_data_link_ents {
0051 SENSOR_A,
0052 SENSOR_B,
0053 DEBAYER_A,
0054 DEBAYER_B,
0055 RAW_CAPTURE_0,
0056 RAW_CAPTURE_1,
0057 RGB_YUV_INPUT,
0058 SCALER,
0059 RGB_YUV_CAPTURE,
0060 LENS_A,
0061 LENS_B,
0062 };
0063
0064
0065 struct vimc_ancillary_link {
0066 unsigned int primary_ent;
0067 unsigned int ancillary_ent;
0068 };
0069
0070
0071 struct vimc_pipeline_config {
0072 const struct vimc_ent_config *ents;
0073 size_t num_ents;
0074 const struct vimc_data_link *data_links;
0075 size_t num_data_links;
0076 const struct vimc_ancillary_link *ancillary_links;
0077 size_t num_ancillary_links;
0078 };
0079
0080
0081
0082
0083
0084 static struct vimc_ent_config ent_config[] = {
0085 [SENSOR_A] = {
0086 .name = "Sensor A",
0087 .type = &vimc_sensor_type
0088 },
0089 [SENSOR_B] = {
0090 .name = "Sensor B",
0091 .type = &vimc_sensor_type
0092 },
0093 [DEBAYER_A] = {
0094 .name = "Debayer A",
0095 .type = &vimc_debayer_type
0096 },
0097 [DEBAYER_B] = {
0098 .name = "Debayer B",
0099 .type = &vimc_debayer_type
0100 },
0101 [RAW_CAPTURE_0] = {
0102 .name = "Raw Capture 0",
0103 .type = &vimc_capture_type
0104 },
0105 [RAW_CAPTURE_1] = {
0106 .name = "Raw Capture 1",
0107 .type = &vimc_capture_type
0108 },
0109 [RGB_YUV_INPUT] = {
0110
0111 .name = "RGB/YUV Input",
0112 .type = &vimc_sensor_type
0113 },
0114 [SCALER] = {
0115 .name = "Scaler",
0116 .type = &vimc_scaler_type
0117 },
0118 [RGB_YUV_CAPTURE] = {
0119 .name = "RGB/YUV Capture",
0120 .type = &vimc_capture_type
0121 },
0122 [LENS_A] = {
0123 .name = "Lens A",
0124 .type = &vimc_lens_type
0125 },
0126 [LENS_B] = {
0127 .name = "Lens B",
0128 .type = &vimc_lens_type
0129 },
0130 };
0131
0132 static const struct vimc_data_link data_links[] = {
0133
0134 VIMC_DATA_LINK(SENSOR_A, 0, DEBAYER_A, 0,
0135 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
0136
0137 VIMC_DATA_LINK(SENSOR_A, 0, RAW_CAPTURE_0, 0,
0138 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
0139
0140 VIMC_DATA_LINK(SENSOR_B, 0, DEBAYER_B, 0,
0141 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
0142
0143 VIMC_DATA_LINK(SENSOR_B, 0, RAW_CAPTURE_1, 0,
0144 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
0145
0146 VIMC_DATA_LINK(DEBAYER_A, 1, SCALER, 0, MEDIA_LNK_FL_ENABLED),
0147
0148 VIMC_DATA_LINK(DEBAYER_B, 1, SCALER, 0, 0),
0149
0150 VIMC_DATA_LINK(RGB_YUV_INPUT, 0, SCALER, 0, 0),
0151
0152 VIMC_DATA_LINK(SCALER, 1, RGB_YUV_CAPTURE, 0,
0153 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
0154 };
0155
0156 static const struct vimc_ancillary_link ancillary_links[] = {
0157
0158 VIMC_ANCILLARY_LINK(0, 9),
0159
0160 VIMC_ANCILLARY_LINK(1, 10),
0161 };
0162
0163 static struct vimc_pipeline_config pipe_cfg = {
0164 .ents = ent_config,
0165 .num_ents = ARRAY_SIZE(ent_config),
0166 .data_links = data_links,
0167 .num_data_links = ARRAY_SIZE(data_links),
0168 .ancillary_links = ancillary_links,
0169 .num_ancillary_links = ARRAY_SIZE(ancillary_links),
0170 };
0171
0172
0173
0174 static void vimc_rm_links(struct vimc_device *vimc)
0175 {
0176 unsigned int i;
0177
0178 for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
0179 media_entity_remove_links(vimc->ent_devs[i]->ent);
0180 }
0181
0182 static int vimc_create_links(struct vimc_device *vimc)
0183 {
0184 unsigned int i;
0185 int ret;
0186
0187
0188 for (i = 0; i < vimc->pipe_cfg->num_data_links; i++) {
0189 const struct vimc_data_link *link = &vimc->pipe_cfg->data_links[i];
0190
0191 struct vimc_ent_device *ved_src =
0192 vimc->ent_devs[link->src_ent];
0193 struct vimc_ent_device *ved_sink =
0194 vimc->ent_devs[link->sink_ent];
0195
0196 ret = media_create_pad_link(ved_src->ent, link->src_pad,
0197 ved_sink->ent, link->sink_pad,
0198 link->flags);
0199 if (ret)
0200 goto err_rm_links;
0201 }
0202
0203 for (i = 0; i < vimc->pipe_cfg->num_ancillary_links; i++) {
0204 const struct vimc_ancillary_link *link = &vimc->pipe_cfg->ancillary_links[i];
0205
0206 struct vimc_ent_device *ved_primary =
0207 vimc->ent_devs[link->primary_ent];
0208 struct vimc_ent_device *ved_ancillary =
0209 vimc->ent_devs[link->ancillary_ent];
0210 struct media_link *ret_link =
0211 media_create_ancillary_link(ved_primary->ent, ved_ancillary->ent);
0212
0213 if (IS_ERR(ret_link)) {
0214 ret = PTR_ERR(ret_link);
0215 goto err_rm_links;
0216 }
0217 }
0218
0219 return 0;
0220
0221 err_rm_links:
0222 vimc_rm_links(vimc);
0223 return ret;
0224 }
0225
0226 static void vimc_release_subdevs(struct vimc_device *vimc)
0227 {
0228 unsigned int i;
0229
0230 for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
0231 if (vimc->ent_devs[i])
0232 vimc->pipe_cfg->ents[i].type->release(vimc->ent_devs[i]);
0233 }
0234
0235 static void vimc_unregister_subdevs(struct vimc_device *vimc)
0236 {
0237 unsigned int i;
0238
0239 for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
0240 if (vimc->ent_devs[i] && vimc->pipe_cfg->ents[i].type->unregister)
0241 vimc->pipe_cfg->ents[i].type->unregister(vimc->ent_devs[i]);
0242 }
0243
0244 static int vimc_add_subdevs(struct vimc_device *vimc)
0245 {
0246 unsigned int i;
0247
0248 for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
0249 dev_dbg(vimc->mdev.dev, "new entity for %s\n",
0250 vimc->pipe_cfg->ents[i].name);
0251 vimc->ent_devs[i] = vimc->pipe_cfg->ents[i].type->add(vimc,
0252 vimc->pipe_cfg->ents[i].name);
0253 if (IS_ERR(vimc->ent_devs[i])) {
0254 int err = PTR_ERR(vimc->ent_devs[i]);
0255
0256 dev_err(vimc->mdev.dev, "adding entity %s failed (%d)\n",
0257 vimc->pipe_cfg->ents[i].name, err);
0258 vimc->ent_devs[i] = NULL;
0259 vimc_unregister_subdevs(vimc);
0260 vimc_release_subdevs(vimc);
0261 return err;
0262 }
0263 }
0264 return 0;
0265 }
0266
0267 static void vimc_v4l2_dev_release(struct v4l2_device *v4l2_dev)
0268 {
0269 struct vimc_device *vimc =
0270 container_of(v4l2_dev, struct vimc_device, v4l2_dev);
0271
0272 vimc_release_subdevs(vimc);
0273 media_device_cleanup(&vimc->mdev);
0274 kfree(vimc->ent_devs);
0275 kfree(vimc);
0276 }
0277
0278 static int vimc_register_devices(struct vimc_device *vimc)
0279 {
0280 int ret;
0281
0282
0283 ret = v4l2_device_register(vimc->mdev.dev, &vimc->v4l2_dev);
0284 if (ret) {
0285 dev_err(vimc->mdev.dev,
0286 "v4l2 device register failed (err=%d)\n", ret);
0287 return ret;
0288 }
0289
0290 vimc->ent_devs = kcalloc(vimc->pipe_cfg->num_ents,
0291 sizeof(*vimc->ent_devs), GFP_KERNEL);
0292 if (!vimc->ent_devs) {
0293 ret = -ENOMEM;
0294 goto err_v4l2_unregister;
0295 }
0296
0297
0298 ret = vimc_add_subdevs(vimc);
0299 if (ret)
0300 goto err_free_ent_devs;
0301
0302
0303 ret = vimc_create_links(vimc);
0304 if (ret)
0305 goto err_rm_subdevs;
0306
0307
0308 ret = media_device_register(&vimc->mdev);
0309 if (ret) {
0310 dev_err(vimc->mdev.dev,
0311 "media device register failed (err=%d)\n", ret);
0312 goto err_rm_subdevs;
0313 }
0314
0315
0316 ret = v4l2_device_register_subdev_nodes(&vimc->v4l2_dev);
0317 if (ret) {
0318 dev_err(vimc->mdev.dev,
0319 "vimc subdev nodes registration failed (err=%d)\n",
0320 ret);
0321 goto err_mdev_unregister;
0322 }
0323
0324 return 0;
0325
0326 err_mdev_unregister:
0327 media_device_unregister(&vimc->mdev);
0328 err_rm_subdevs:
0329 vimc_unregister_subdevs(vimc);
0330 vimc_release_subdevs(vimc);
0331 err_free_ent_devs:
0332 kfree(vimc->ent_devs);
0333 err_v4l2_unregister:
0334 v4l2_device_unregister(&vimc->v4l2_dev);
0335
0336 return ret;
0337 }
0338
0339 static int vimc_probe(struct platform_device *pdev)
0340 {
0341 const struct font_desc *font = find_font("VGA8x16");
0342 struct vimc_device *vimc;
0343 int ret;
0344
0345 dev_dbg(&pdev->dev, "probe");
0346
0347 if (!font) {
0348 dev_err(&pdev->dev, "could not find font\n");
0349 return -ENODEV;
0350 }
0351
0352 tpg_set_font(font->data);
0353
0354 if (vimc_allocator == VIMC_ALLOCATOR_DMA_CONTIG)
0355 dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
0356
0357 vimc = kzalloc(sizeof(*vimc), GFP_KERNEL);
0358 if (!vimc)
0359 return -ENOMEM;
0360
0361 vimc->pipe_cfg = &pipe_cfg;
0362
0363
0364 vimc->v4l2_dev.mdev = &vimc->mdev;
0365
0366
0367 strscpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME,
0368 sizeof(vimc->mdev.model));
0369 snprintf(vimc->mdev.bus_info, sizeof(vimc->mdev.bus_info),
0370 "platform:%s", VIMC_PDEV_NAME);
0371 vimc->mdev.dev = &pdev->dev;
0372 media_device_init(&vimc->mdev);
0373
0374 ret = vimc_register_devices(vimc);
0375 if (ret) {
0376 media_device_cleanup(&vimc->mdev);
0377 kfree(vimc);
0378 return ret;
0379 }
0380
0381
0382
0383
0384
0385 vimc->v4l2_dev.release = vimc_v4l2_dev_release;
0386 platform_set_drvdata(pdev, vimc);
0387 return 0;
0388 }
0389
0390 static int vimc_remove(struct platform_device *pdev)
0391 {
0392 struct vimc_device *vimc = platform_get_drvdata(pdev);
0393
0394 dev_dbg(&pdev->dev, "remove");
0395
0396 vimc_unregister_subdevs(vimc);
0397 media_device_unregister(&vimc->mdev);
0398 v4l2_device_unregister(&vimc->v4l2_dev);
0399 v4l2_device_put(&vimc->v4l2_dev);
0400
0401 return 0;
0402 }
0403
0404 static void vimc_dev_release(struct device *dev)
0405 {
0406 }
0407
0408 static struct platform_device vimc_pdev = {
0409 .name = VIMC_PDEV_NAME,
0410 .dev.release = vimc_dev_release,
0411 };
0412
0413 static struct platform_driver vimc_pdrv = {
0414 .probe = vimc_probe,
0415 .remove = vimc_remove,
0416 .driver = {
0417 .name = VIMC_PDEV_NAME,
0418 },
0419 };
0420
0421 static int __init vimc_init(void)
0422 {
0423 int ret;
0424
0425 ret = platform_device_register(&vimc_pdev);
0426 if (ret) {
0427 dev_err(&vimc_pdev.dev,
0428 "platform device registration failed (err=%d)\n", ret);
0429 return ret;
0430 }
0431
0432 ret = platform_driver_register(&vimc_pdrv);
0433 if (ret) {
0434 dev_err(&vimc_pdev.dev,
0435 "platform driver registration failed (err=%d)\n", ret);
0436 platform_driver_unregister(&vimc_pdrv);
0437 return ret;
0438 }
0439
0440 return 0;
0441 }
0442
0443 static void __exit vimc_exit(void)
0444 {
0445 platform_driver_unregister(&vimc_pdrv);
0446
0447 platform_device_unregister(&vimc_pdev);
0448 }
0449
0450 module_init(vimc_init);
0451 module_exit(vimc_exit);
0452
0453 MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC)");
0454 MODULE_AUTHOR("Helen Fornazier <helen.fornazier@gmail.com>");
0455 MODULE_LICENSE("GPL");