1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * vimc-core.c Virtual Media Controller Driver 4 * 5 * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com> 6 */ 7 8 #include <linux/dma-mapping.h> 9 #include <linux/font.h> 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/platform_device.h> 13 #include <media/media-device.h> 14 #include <media/tpg/v4l2-tpg.h> 15 #include <media/v4l2-device.h> 16 17 #include "vimc-common.h" 18 19 unsigned int vimc_allocator; 20 module_param_named(allocator, vimc_allocator, uint, 0444); 21 MODULE_PARM_DESC(allocator, " memory allocator selection, default is 0.\n" 22 "\t\t 0 == vmalloc\n" 23 "\t\t 1 == dma-contig"); 24 25 #define VIMC_MDEV_MODEL_NAME "VIMC MDEV" 26 27 #define VIMC_DATA_LINK(src, srcpad, sink, sinkpad, link_flags) { \ 28 .src_ent = src, \ 29 .src_pad = srcpad, \ 30 .sink_ent = sink, \ 31 .sink_pad = sinkpad, \ 32 .flags = link_flags, \ 33 } 34 35 #define VIMC_ANCILLARY_LINK(primary, ancillary) { \ 36 .primary_ent = primary, \ 37 .ancillary_ent = ancillary \ 38 } 39 40 /* Structure which describes data links between entities */ 41 struct vimc_data_link { 42 unsigned int src_ent; 43 u16 src_pad; 44 unsigned int sink_ent; 45 u16 sink_pad; 46 u32 flags; 47 }; 48 49 /* Enum to improve clarity when defining vimc_data_links */ 50 enum vimc_data_link_ents { 51 SENSOR_A, 52 SENSOR_B, 53 DEBAYER_A, 54 DEBAYER_B, 55 RAW_CAPTURE_0, 56 RAW_CAPTURE_1, 57 RGB_YUV_INPUT, 58 SCALER, 59 RGB_YUV_CAPTURE, 60 LENS_A, 61 LENS_B, 62 }; 63 64 /* Structure which describes ancillary links between entities */ 65 struct vimc_ancillary_link { 66 unsigned int primary_ent; 67 unsigned int ancillary_ent; 68 }; 69 70 /* Structure which describes the whole topology */ 71 struct vimc_pipeline_config { 72 const struct vimc_ent_config *ents; 73 size_t num_ents; 74 const struct vimc_data_link *data_links; 75 size_t num_data_links; 76 const struct vimc_ancillary_link *ancillary_links; 77 size_t num_ancillary_links; 78 }; 79 80 /* -------------------------------------------------------------------------- 81 * Topology Configuration 82 */ 83 84 static struct vimc_ent_config ent_config[] = { 85 [SENSOR_A] = { 86 .name = "Sensor A", 87 .type = &vimc_sensor_type 88 }, 89 [SENSOR_B] = { 90 .name = "Sensor B", 91 .type = &vimc_sensor_type 92 }, 93 [DEBAYER_A] = { 94 .name = "Debayer A", 95 .type = &vimc_debayer_type 96 }, 97 [DEBAYER_B] = { 98 .name = "Debayer B", 99 .type = &vimc_debayer_type 100 }, 101 [RAW_CAPTURE_0] = { 102 .name = "Raw Capture 0", 103 .type = &vimc_capture_type 104 }, 105 [RAW_CAPTURE_1] = { 106 .name = "Raw Capture 1", 107 .type = &vimc_capture_type 108 }, 109 [RGB_YUV_INPUT] = { 110 /* TODO: change this to vimc-input when it is implemented */ 111 .name = "RGB/YUV Input", 112 .type = &vimc_sensor_type 113 }, 114 [SCALER] = { 115 .name = "Scaler", 116 .type = &vimc_scaler_type 117 }, 118 [RGB_YUV_CAPTURE] = { 119 .name = "RGB/YUV Capture", 120 .type = &vimc_capture_type 121 }, 122 [LENS_A] = { 123 .name = "Lens A", 124 .type = &vimc_lens_type 125 }, 126 [LENS_B] = { 127 .name = "Lens B", 128 .type = &vimc_lens_type 129 }, 130 }; 131 132 static const struct vimc_data_link data_links[] = { 133 /* Link: Sensor A (Pad 0)->(Pad 0) Debayer A */ 134 VIMC_DATA_LINK(SENSOR_A, 0, DEBAYER_A, 0, 135 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 136 /* Link: Sensor A (Pad 0)->(Pad 0) Raw Capture 0 */ 137 VIMC_DATA_LINK(SENSOR_A, 0, RAW_CAPTURE_0, 0, 138 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 139 /* Link: Sensor B (Pad 0)->(Pad 0) Debayer B */ 140 VIMC_DATA_LINK(SENSOR_B, 0, DEBAYER_B, 0, 141 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 142 /* Link: Sensor B (Pad 0)->(Pad 0) Raw Capture 1 */ 143 VIMC_DATA_LINK(SENSOR_B, 0, RAW_CAPTURE_1, 0, 144 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 145 /* Link: Debayer A (Pad 1)->(Pad 0) Scaler */ 146 VIMC_DATA_LINK(DEBAYER_A, 1, SCALER, 0, MEDIA_LNK_FL_ENABLED), 147 /* Link: Debayer B (Pad 1)->(Pad 0) Scaler */ 148 VIMC_DATA_LINK(DEBAYER_B, 1, SCALER, 0, 0), 149 /* Link: RGB/YUV Input (Pad 0)->(Pad 0) Scaler */ 150 VIMC_DATA_LINK(RGB_YUV_INPUT, 0, SCALER, 0, 0), 151 /* Link: Scaler (Pad 1)->(Pad 0) RGB/YUV Capture */ 152 VIMC_DATA_LINK(SCALER, 1, RGB_YUV_CAPTURE, 0, 153 MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 154 }; 155 156 static const struct vimc_ancillary_link ancillary_links[] = { 157 /* Link: Sensor A -> Lens A */ 158 VIMC_ANCILLARY_LINK(0, 9), 159 /* Link: Sensor B -> Lens B */ 160 VIMC_ANCILLARY_LINK(1, 10), 161 }; 162 163 static struct vimc_pipeline_config pipe_cfg = { 164 .ents = ent_config, 165 .num_ents = ARRAY_SIZE(ent_config), 166 .data_links = data_links, 167 .num_data_links = ARRAY_SIZE(data_links), 168 .ancillary_links = ancillary_links, 169 .num_ancillary_links = ARRAY_SIZE(ancillary_links), 170 }; 171 172 /* -------------------------------------------------------------------------- */ 173 174 static void vimc_rm_links(struct vimc_device *vimc) 175 { 176 unsigned int i; 177 178 for (i = 0; i < vimc->pipe_cfg->num_ents; i++) 179 media_entity_remove_links(vimc->ent_devs[i]->ent); 180 } 181 182 static int vimc_create_links(struct vimc_device *vimc) 183 { 184 unsigned int i; 185 int ret; 186 187 /* Initialize the links between entities */ 188 for (i = 0; i < vimc->pipe_cfg->num_data_links; i++) { 189 const struct vimc_data_link *link = &vimc->pipe_cfg->data_links[i]; 190 191 struct vimc_ent_device *ved_src = 192 vimc->ent_devs[link->src_ent]; 193 struct vimc_ent_device *ved_sink = 194 vimc->ent_devs[link->sink_ent]; 195 196 ret = media_create_pad_link(ved_src->ent, link->src_pad, 197 ved_sink->ent, link->sink_pad, 198 link->flags); 199 if (ret) 200 goto err_rm_links; 201 } 202 203 for (i = 0; i < vimc->pipe_cfg->num_ancillary_links; i++) { 204 const struct vimc_ancillary_link *link = &vimc->pipe_cfg->ancillary_links[i]; 205 206 struct vimc_ent_device *ved_primary = 207 vimc->ent_devs[link->primary_ent]; 208 struct vimc_ent_device *ved_ancillary = 209 vimc->ent_devs[link->ancillary_ent]; 210 struct media_link *ret_link = 211 media_create_ancillary_link(ved_primary->ent, ved_ancillary->ent); 212 213 if (IS_ERR(ret_link)) { 214 ret = PTR_ERR(ret_link); 215 goto err_rm_links; 216 } 217 } 218 219 return 0; 220 221 err_rm_links: 222 vimc_rm_links(vimc); 223 return ret; 224 } 225 226 static void vimc_release_subdevs(struct vimc_device *vimc) 227 { 228 unsigned int i; 229 230 for (i = 0; i < vimc->pipe_cfg->num_ents; i++) 231 if (vimc->ent_devs[i]) 232 vimc->pipe_cfg->ents[i].type->release(vimc->ent_devs[i]); 233 } 234 235 static void vimc_unregister_subdevs(struct vimc_device *vimc) 236 { 237 unsigned int i; 238 239 for (i = 0; i < vimc->pipe_cfg->num_ents; i++) 240 if (vimc->ent_devs[i] && vimc->pipe_cfg->ents[i].type->unregister) 241 vimc->pipe_cfg->ents[i].type->unregister(vimc->ent_devs[i]); 242 } 243 244 static int vimc_add_subdevs(struct vimc_device *vimc) 245 { 246 unsigned int i; 247 248 for (i = 0; i < vimc->pipe_cfg->num_ents; i++) { 249 dev_dbg(vimc->mdev.dev, "new entity for %s\n", 250 vimc->pipe_cfg->ents[i].name); 251 vimc->ent_devs[i] = vimc->pipe_cfg->ents[i].type->add(vimc, 252 vimc->pipe_cfg->ents[i].name); 253 if (IS_ERR(vimc->ent_devs[i])) { 254 int err = PTR_ERR(vimc->ent_devs[i]); 255 256 dev_err(vimc->mdev.dev, "adding entity %s failed (%d)\n", 257 vimc->pipe_cfg->ents[i].name, err); 258 vimc->ent_devs[i] = NULL; 259 vimc_unregister_subdevs(vimc); 260 vimc_release_subdevs(vimc); 261 return err; 262 } 263 } 264 return 0; 265 } 266 267 static void vimc_v4l2_dev_release(struct v4l2_device *v4l2_dev) 268 { 269 struct vimc_device *vimc = 270 container_of(v4l2_dev, struct vimc_device, v4l2_dev); 271 272 vimc_release_subdevs(vimc); 273 media_device_cleanup(&vimc->mdev); 274 kfree(vimc->ent_devs); 275 kfree(vimc); 276 } 277 278 static int vimc_register_devices(struct vimc_device *vimc) 279 { 280 int ret; 281 282 /* Register the v4l2 struct */ 283 ret = v4l2_device_register(vimc->mdev.dev, &vimc->v4l2_dev); 284 if (ret) { 285 dev_err(vimc->mdev.dev, 286 "v4l2 device register failed (err=%d)\n", ret); 287 return ret; 288 } 289 /* allocate ent_devs */ 290 vimc->ent_devs = kcalloc(vimc->pipe_cfg->num_ents, 291 sizeof(*vimc->ent_devs), GFP_KERNEL); 292 if (!vimc->ent_devs) { 293 ret = -ENOMEM; 294 goto err_v4l2_unregister; 295 } 296 297 /* Invoke entity config hooks to initialize and register subdevs */ 298 ret = vimc_add_subdevs(vimc); 299 if (ret) 300 goto err_free_ent_devs; 301 302 /* Initialize links */ 303 ret = vimc_create_links(vimc); 304 if (ret) 305 goto err_rm_subdevs; 306 307 /* Register the media device */ 308 ret = media_device_register(&vimc->mdev); 309 if (ret) { 310 dev_err(vimc->mdev.dev, 311 "media device register failed (err=%d)\n", ret); 312 goto err_rm_subdevs; 313 } 314 315 /* Expose all subdev's nodes*/ 316 ret = v4l2_device_register_subdev_nodes(&vimc->v4l2_dev); 317 if (ret) { 318 dev_err(vimc->mdev.dev, 319 "vimc subdev nodes registration failed (err=%d)\n", 320 ret); 321 goto err_mdev_unregister; 322 } 323 324 return 0; 325 326 err_mdev_unregister: 327 media_device_unregister(&vimc->mdev); 328 err_rm_subdevs: 329 vimc_unregister_subdevs(vimc); 330 vimc_release_subdevs(vimc); 331 err_free_ent_devs: 332 kfree(vimc->ent_devs); 333 err_v4l2_unregister: 334 v4l2_device_unregister(&vimc->v4l2_dev); 335 336 return ret; 337 } 338 339 static int vimc_probe(struct platform_device *pdev) 340 { 341 const struct font_desc *font = find_font("VGA8x16"); 342 struct vimc_device *vimc; 343 int ret; 344 345 dev_dbg(&pdev->dev, "probe"); 346 347 if (!font) { 348 dev_err(&pdev->dev, "could not find font\n"); 349 return -ENODEV; 350 } 351 352 tpg_set_font(font->data); 353 354 if (vimc_allocator == VIMC_ALLOCATOR_DMA_CONTIG) 355 dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 356 357 vimc = kzalloc(sizeof(*vimc), GFP_KERNEL); 358 if (!vimc) 359 return -ENOMEM; 360 361 vimc->pipe_cfg = &pipe_cfg; 362 363 /* Link the media device within the v4l2_device */ 364 vimc->v4l2_dev.mdev = &vimc->mdev; 365 366 /* Initialize media device */ 367 strscpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME, 368 sizeof(vimc->mdev.model)); 369 snprintf(vimc->mdev.bus_info, sizeof(vimc->mdev.bus_info), 370 "platform:%s", VIMC_PDEV_NAME); 371 vimc->mdev.dev = &pdev->dev; 372 media_device_init(&vimc->mdev); 373 374 ret = vimc_register_devices(vimc); 375 if (ret) { 376 media_device_cleanup(&vimc->mdev); 377 kfree(vimc); 378 return ret; 379 } 380 /* 381 * the release cb is set only after successful registration. 382 * if the registration fails, we release directly from probe 383 */ 384 385 vimc->v4l2_dev.release = vimc_v4l2_dev_release; 386 platform_set_drvdata(pdev, vimc); 387 return 0; 388 } 389 390 static int vimc_remove(struct platform_device *pdev) 391 { 392 struct vimc_device *vimc = platform_get_drvdata(pdev); 393 394 dev_dbg(&pdev->dev, "remove"); 395 396 vimc_unregister_subdevs(vimc); 397 media_device_unregister(&vimc->mdev); 398 v4l2_device_unregister(&vimc->v4l2_dev); 399 v4l2_device_put(&vimc->v4l2_dev); 400 401 return 0; 402 } 403 404 static void vimc_dev_release(struct device *dev) 405 { 406 } 407 408 static struct platform_device vimc_pdev = { 409 .name = VIMC_PDEV_NAME, 410 .dev.release = vimc_dev_release, 411 }; 412 413 static struct platform_driver vimc_pdrv = { 414 .probe = vimc_probe, 415 .remove = vimc_remove, 416 .driver = { 417 .name = VIMC_PDEV_NAME, 418 }, 419 }; 420 421 static int __init vimc_init(void) 422 { 423 int ret; 424 425 ret = platform_device_register(&vimc_pdev); 426 if (ret) { 427 dev_err(&vimc_pdev.dev, 428 "platform device registration failed (err=%d)\n", ret); 429 return ret; 430 } 431 432 ret = platform_driver_register(&vimc_pdrv); 433 if (ret) { 434 dev_err(&vimc_pdev.dev, 435 "platform driver registration failed (err=%d)\n", ret); 436 platform_driver_unregister(&vimc_pdrv); 437 return ret; 438 } 439 440 return 0; 441 } 442 443 static void __exit vimc_exit(void) 444 { 445 platform_driver_unregister(&vimc_pdrv); 446 447 platform_device_unregister(&vimc_pdev); 448 } 449 450 module_init(vimc_init); 451 module_exit(vimc_exit); 452 453 MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC)"); 454 MODULE_AUTHOR("Helen Fornazier <helen.fornazier@gmail.com>"); 455 MODULE_LICENSE("GPL"); 456