Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: rcar-vin: Add r8a779a0 support

Add support for the R-Car V3U (r8a779a0) to the driver. The V3U has the
VIN modules connected to a ISP instead of directly to the R-Car CSI-2
receivers. The reason being that the ISP performs channel selection
based on CSI-2 VC/DT pairs and routes the video data to different VIN
modules. In other SoC versions this filtering is done by the VIN modules
themself.

While the media graph is very different from other SoCs the only
difference in operating the VIN modules is that the VC/DT filtering
should be skipped as that is performed by the ISP.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Niklas Söderlund and committed by
Mauro Carvalho Chehab
406bb586 688565db

+129 -13
+104 -2
drivers/media/platform/rcar-vin/rcar-core.c
··· 1008 1008 } 1009 1009 1010 1010 /* ----------------------------------------------------------------------------- 1011 + * ISP 1012 + */ 1013 + 1014 + static int rvin_isp_setup_links(struct rvin_dev *vin) 1015 + { 1016 + unsigned int i; 1017 + int ret = -EINVAL; 1018 + 1019 + /* Create all media device links between VINs and ISP's. */ 1020 + mutex_lock(&vin->group->lock); 1021 + for (i = 0; i < RCAR_VIN_NUM; i++) { 1022 + struct media_pad *source_pad, *sink_pad; 1023 + struct media_entity *source, *sink; 1024 + unsigned int source_slot = i / 8; 1025 + unsigned int source_idx = i % 8 + 1; 1026 + 1027 + if (!vin->group->vin[i]) 1028 + continue; 1029 + 1030 + /* Check that ISP is part of the group. */ 1031 + if (!vin->group->remotes[source_slot].subdev) 1032 + continue; 1033 + 1034 + source = &vin->group->remotes[source_slot].subdev->entity; 1035 + source_pad = &source->pads[source_idx]; 1036 + 1037 + sink = &vin->group->vin[i]->vdev.entity; 1038 + sink_pad = &sink->pads[0]; 1039 + 1040 + /* Skip if link already exists. */ 1041 + if (media_entity_find_link(source_pad, sink_pad)) 1042 + continue; 1043 + 1044 + ret = media_create_pad_link(source, source_idx, sink, 0, 1045 + MEDIA_LNK_FL_ENABLED | 1046 + MEDIA_LNK_FL_IMMUTABLE); 1047 + if (ret) { 1048 + vin_err(vin, "Error adding link from %s to %s\n", 1049 + source->name, sink->name); 1050 + break; 1051 + } 1052 + } 1053 + mutex_unlock(&vin->group->lock); 1054 + 1055 + return ret; 1056 + } 1057 + 1058 + static void rvin_isp_cleanup(struct rvin_dev *vin) 1059 + { 1060 + rvin_group_notifier_cleanup(vin); 1061 + rvin_group_put(vin); 1062 + rvin_free_controls(vin); 1063 + } 1064 + 1065 + static int rvin_isp_init(struct rvin_dev *vin) 1066 + { 1067 + int ret; 1068 + 1069 + vin->pad.flags = MEDIA_PAD_FL_SINK; 1070 + ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad); 1071 + if (ret) 1072 + return ret; 1073 + 1074 + ret = rvin_create_controls(vin, NULL); 1075 + if (ret < 0) 1076 + return ret; 1077 + 1078 + ret = rvin_group_get(vin, rvin_isp_setup_links, NULL); 1079 + if (ret) 1080 + goto err_controls; 1081 + 1082 + ret = rvin_group_notifier_init(vin, 2, RVIN_ISP_MAX); 1083 + if (ret) 1084 + goto err_group; 1085 + 1086 + return 0; 1087 + err_group: 1088 + rvin_group_put(vin); 1089 + err_controls: 1090 + rvin_free_controls(vin); 1091 + 1092 + return ret; 1093 + } 1094 + 1095 + /* ----------------------------------------------------------------------------- 1011 1096 * Suspend / Resume 1012 1097 */ 1013 1098 ··· 1464 1379 .routes = rcar_info_r8a77995_routes, 1465 1380 }; 1466 1381 1382 + static const struct rvin_info rcar_info_r8a779a0 = { 1383 + .model = RCAR_GEN3, 1384 + .use_mc = true, 1385 + .use_isp = true, 1386 + .nv12 = true, 1387 + .max_width = 4096, 1388 + .max_height = 4096, 1389 + }; 1390 + 1467 1391 static const struct of_device_id rvin_of_id_table[] = { 1468 1392 { 1469 1393 .compatible = "renesas,vin-r8a774a1", ··· 1534 1440 .compatible = "renesas,vin-r8a77995", 1535 1441 .data = &rcar_info_r8a77995, 1536 1442 }, 1443 + { 1444 + .compatible = "renesas,vin-r8a779a0", 1445 + .data = &rcar_info_r8a779a0, 1446 + }, 1537 1447 { /* Sentinel */ }, 1538 1448 }; 1539 1449 MODULE_DEVICE_TABLE(of, rvin_of_id_table); ··· 1586 1488 1587 1489 platform_set_drvdata(pdev, vin); 1588 1490 1589 - if (vin->info->use_mc) 1491 + if (vin->info->use_isp) 1492 + ret = rvin_isp_init(vin); 1493 + else if (vin->info->use_mc) 1590 1494 ret = rvin_csi2_init(vin); 1591 1495 else 1592 1496 ret = rvin_parallel_init(vin); ··· 1612 1512 1613 1513 rvin_v4l2_unregister(vin); 1614 1514 1615 - if (vin->info->use_mc) 1515 + if (vin->info->use_isp) 1516 + rvin_isp_cleanup(vin); 1517 + else if (vin->info->use_mc) 1616 1518 rvin_csi2_cleanup(vin); 1617 1519 else 1618 1520 rvin_parallel_cleanup(vin);
+11 -9
drivers/media/platform/rcar-vin/rcar-dma.c
··· 783 783 /* Always update on field change */ 784 784 vnmc |= VNMC_VUP; 785 785 786 - /* If input and output use the same colorspace, use bypass mode */ 787 - if (input_is_yuv == output_is_yuv) 788 - vnmc |= VNMC_BPS; 786 + if (!vin->info->use_isp) { 787 + /* If input and output use the same colorspace, use bypass mode */ 788 + if (input_is_yuv == output_is_yuv) 789 + vnmc |= VNMC_BPS; 789 790 790 - if (vin->info->model == RCAR_GEN3) { 791 - /* Select between CSI-2 and parallel input */ 792 - if (vin->is_csi) 793 - vnmc &= ~VNMC_DPINE; 794 - else 795 - vnmc |= VNMC_DPINE; 791 + if (vin->info->model == RCAR_GEN3) { 792 + /* Select between CSI-2 and parallel input */ 793 + if (vin->is_csi) 794 + vnmc &= ~VNMC_DPINE; 795 + else 796 + vnmc |= VNMC_DPINE; 797 + } 796 798 } 797 799 798 800 /* Progressive or interlaced mode */
+14 -2
drivers/media/platform/rcar-vin/rcar-vin.h
··· 29 29 #define HW_BUFFER_MASK 0x7f 30 30 31 31 /* Max number on VIN instances that can be in a system */ 32 - #define RCAR_VIN_NUM 8 32 + #define RCAR_VIN_NUM 32 33 33 34 34 struct rvin_group; 35 35 ··· 48 48 RVIN_CSI_MAX, 49 49 }; 50 50 51 - #define RVIN_REMOTES_MAX RVIN_CSI_MAX 51 + enum rvin_isp_id { 52 + RVIN_ISP0, 53 + RVIN_ISP1, 54 + RVIN_ISP2, 55 + RVIN_ISP4, 56 + RVIN_ISP_MAX, 57 + }; 58 + 59 + #define RVIN_REMOTES_MAX \ 60 + (((unsigned int)RVIN_CSI_MAX) > ((unsigned int)RVIN_ISP_MAX) ? \ 61 + RVIN_CSI_MAX : RVIN_ISP_MAX) 52 62 53 63 /** 54 64 * enum rvin_dma_state - DMA states ··· 159 149 * struct rvin_info - Information about the particular VIN implementation 160 150 * @model: VIN model 161 151 * @use_mc: use media controller instead of controlling subdevice 152 + * @use_isp: the VIN is connected to the ISP and not to the CSI-2 162 153 * @nv12: support outputing NV12 pixel format 163 154 * @max_width: max input width the VIN supports 164 155 * @max_height: max input height the VIN supports ··· 169 158 struct rvin_info { 170 159 enum model_id model; 171 160 bool use_mc; 161 + bool use_isp; 172 162 bool nv12; 173 163 174 164 unsigned int max_width;