18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * vimc-common.c Virtual Media Controller Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/init.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "vimc-common.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * NOTE: non-bayer formats need to come first (necessary for enum_mbus_code 158c2ecf20Sopenharmony_ci * in the scaler) 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_cistatic const struct vimc_pix_map vimc_pix_map_list[] = { 188c2ecf20Sopenharmony_ci /* TODO: add all missing formats */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci /* RGB formats */ 218c2ecf20Sopenharmony_ci { 228c2ecf20Sopenharmony_ci .code = { 238c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_BGR888_1X24, 248c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_BGR888_3X8 258c2ecf20Sopenharmony_ci }, 268c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_BGR24, 278c2ecf20Sopenharmony_ci .bpp = 3, 288c2ecf20Sopenharmony_ci .bayer = false, 298c2ecf20Sopenharmony_ci }, 308c2ecf20Sopenharmony_ci { 318c2ecf20Sopenharmony_ci .code = { 328c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_RGB888_1X24, 338c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_RGB888_2X12_BE, 348c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_RGB888_2X12_LE, 358c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_RGB888_3X8, 368c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 378c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 388c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_RGB888_1X32_PADHI, 398c2ecf20Sopenharmony_ci MEDIA_BUS_FMT_GBR888_1X24 408c2ecf20Sopenharmony_ci }, 418c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_RGB24, 428c2ecf20Sopenharmony_ci .bpp = 3, 438c2ecf20Sopenharmony_ci .bayer = false, 448c2ecf20Sopenharmony_ci }, 458c2ecf20Sopenharmony_ci { 468c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_ARGB8888_1X32 }, 478c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_ARGB32, 488c2ecf20Sopenharmony_ci .bpp = 4, 498c2ecf20Sopenharmony_ci .bayer = false, 508c2ecf20Sopenharmony_ci }, 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* Bayer formats */ 538c2ecf20Sopenharmony_ci { 548c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SBGGR8_1X8 }, 558c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SBGGR8, 568c2ecf20Sopenharmony_ci .bpp = 1, 578c2ecf20Sopenharmony_ci .bayer = true, 588c2ecf20Sopenharmony_ci }, 598c2ecf20Sopenharmony_ci { 608c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGBRG8_1X8 }, 618c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGBRG8, 628c2ecf20Sopenharmony_ci .bpp = 1, 638c2ecf20Sopenharmony_ci .bayer = true, 648c2ecf20Sopenharmony_ci }, 658c2ecf20Sopenharmony_ci { 668c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGRBG8_1X8 }, 678c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGRBG8, 688c2ecf20Sopenharmony_ci .bpp = 1, 698c2ecf20Sopenharmony_ci .bayer = true, 708c2ecf20Sopenharmony_ci }, 718c2ecf20Sopenharmony_ci { 728c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SRGGB8_1X8 }, 738c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SRGGB8, 748c2ecf20Sopenharmony_ci .bpp = 1, 758c2ecf20Sopenharmony_ci .bayer = true, 768c2ecf20Sopenharmony_ci }, 778c2ecf20Sopenharmony_ci { 788c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SBGGR10_1X10 }, 798c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SBGGR10, 808c2ecf20Sopenharmony_ci .bpp = 2, 818c2ecf20Sopenharmony_ci .bayer = true, 828c2ecf20Sopenharmony_ci }, 838c2ecf20Sopenharmony_ci { 848c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGBRG10_1X10 }, 858c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGBRG10, 868c2ecf20Sopenharmony_ci .bpp = 2, 878c2ecf20Sopenharmony_ci .bayer = true, 888c2ecf20Sopenharmony_ci }, 898c2ecf20Sopenharmony_ci { 908c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGRBG10_1X10 }, 918c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGRBG10, 928c2ecf20Sopenharmony_ci .bpp = 2, 938c2ecf20Sopenharmony_ci .bayer = true, 948c2ecf20Sopenharmony_ci }, 958c2ecf20Sopenharmony_ci { 968c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SRGGB10_1X10 }, 978c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SRGGB10, 988c2ecf20Sopenharmony_ci .bpp = 2, 998c2ecf20Sopenharmony_ci .bayer = true, 1008c2ecf20Sopenharmony_ci }, 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* 10bit raw bayer a-law compressed to 8 bits */ 1038c2ecf20Sopenharmony_ci { 1048c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8 }, 1058c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SBGGR10ALAW8, 1068c2ecf20Sopenharmony_ci .bpp = 1, 1078c2ecf20Sopenharmony_ci .bayer = true, 1088c2ecf20Sopenharmony_ci }, 1098c2ecf20Sopenharmony_ci { 1108c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8 }, 1118c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGBRG10ALAW8, 1128c2ecf20Sopenharmony_ci .bpp = 1, 1138c2ecf20Sopenharmony_ci .bayer = true, 1148c2ecf20Sopenharmony_ci }, 1158c2ecf20Sopenharmony_ci { 1168c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8 }, 1178c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8, 1188c2ecf20Sopenharmony_ci .bpp = 1, 1198c2ecf20Sopenharmony_ci .bayer = true, 1208c2ecf20Sopenharmony_ci }, 1218c2ecf20Sopenharmony_ci { 1228c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8 }, 1238c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SRGGB10ALAW8, 1248c2ecf20Sopenharmony_ci .bpp = 1, 1258c2ecf20Sopenharmony_ci .bayer = true, 1268c2ecf20Sopenharmony_ci }, 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* 10bit raw bayer DPCM compressed to 8 bits */ 1298c2ecf20Sopenharmony_ci { 1308c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 }, 1318c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SBGGR10DPCM8, 1328c2ecf20Sopenharmony_ci .bpp = 1, 1338c2ecf20Sopenharmony_ci .bayer = true, 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci { 1368c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 }, 1378c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGBRG10DPCM8, 1388c2ecf20Sopenharmony_ci .bpp = 1, 1398c2ecf20Sopenharmony_ci .bayer = true, 1408c2ecf20Sopenharmony_ci }, 1418c2ecf20Sopenharmony_ci { 1428c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 }, 1438c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8, 1448c2ecf20Sopenharmony_ci .bpp = 1, 1458c2ecf20Sopenharmony_ci .bayer = true, 1468c2ecf20Sopenharmony_ci }, 1478c2ecf20Sopenharmony_ci { 1488c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 }, 1498c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SRGGB10DPCM8, 1508c2ecf20Sopenharmony_ci .bpp = 1, 1518c2ecf20Sopenharmony_ci .bayer = true, 1528c2ecf20Sopenharmony_ci }, 1538c2ecf20Sopenharmony_ci { 1548c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SBGGR12_1X12 }, 1558c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SBGGR12, 1568c2ecf20Sopenharmony_ci .bpp = 2, 1578c2ecf20Sopenharmony_ci .bayer = true, 1588c2ecf20Sopenharmony_ci }, 1598c2ecf20Sopenharmony_ci { 1608c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGBRG12_1X12 }, 1618c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGBRG12, 1628c2ecf20Sopenharmony_ci .bpp = 2, 1638c2ecf20Sopenharmony_ci .bayer = true, 1648c2ecf20Sopenharmony_ci }, 1658c2ecf20Sopenharmony_ci { 1668c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SGRBG12_1X12 }, 1678c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SGRBG12, 1688c2ecf20Sopenharmony_ci .bpp = 2, 1698c2ecf20Sopenharmony_ci .bayer = true, 1708c2ecf20Sopenharmony_ci }, 1718c2ecf20Sopenharmony_ci { 1728c2ecf20Sopenharmony_ci .code = { MEDIA_BUS_FMT_SRGGB12_1X12 }, 1738c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_SRGGB12, 1748c2ecf20Sopenharmony_ci .bpp = 2, 1758c2ecf20Sopenharmony_ci .bayer = true, 1768c2ecf20Sopenharmony_ci }, 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cibool vimc_is_source(struct media_entity *ent) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci unsigned int i; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci for (i = 0; i < ent->num_pads; i++) 1848c2ecf20Sopenharmony_ci if (ent->pads[i].flags & MEDIA_PAD_FL_SINK) 1858c2ecf20Sopenharmony_ci return false; 1868c2ecf20Sopenharmony_ci return true; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ciconst struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci if (i >= ARRAY_SIZE(vimc_pix_map_list)) 1928c2ecf20Sopenharmony_ci return NULL; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci return &vimc_pix_map_list[i]; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ciu32 vimc_mbus_code_by_index(unsigned int index) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci unsigned int i, j; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) { 2028c2ecf20Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(vimc_pix_map_list[i].code); j++) { 2038c2ecf20Sopenharmony_ci if (!vimc_pix_map_list[i].code[j]) 2048c2ecf20Sopenharmony_ci break; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (!index) 2078c2ecf20Sopenharmony_ci return vimc_pix_map_list[i].code[j]; 2088c2ecf20Sopenharmony_ci index--; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci return 0; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ciconst struct vimc_pix_map *vimc_pix_map_by_code(u32 code) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci unsigned int i, j; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) { 2198c2ecf20Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(vimc_pix_map_list[i].code); j++) { 2208c2ecf20Sopenharmony_ci if (vimc_pix_map_list[i].code[j] == code) 2218c2ecf20Sopenharmony_ci return &vimc_pix_map_list[i]; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci return NULL; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciconst struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci unsigned int i; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) { 2328c2ecf20Sopenharmony_ci if (vimc_pix_map_list[i].pixelformat == pixelformat) 2338c2ecf20Sopenharmony_ci return &vimc_pix_map_list[i]; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci return NULL; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic int vimc_get_pix_format(struct media_pad *pad, 2398c2ecf20Sopenharmony_ci struct v4l2_pix_format *fmt) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci if (is_media_entity_v4l2_subdev(pad->entity)) { 2428c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = 2438c2ecf20Sopenharmony_ci media_entity_to_v4l2_subdev(pad->entity); 2448c2ecf20Sopenharmony_ci struct v4l2_subdev_format sd_fmt; 2458c2ecf20Sopenharmony_ci const struct vimc_pix_map *pix_map; 2468c2ecf20Sopenharmony_ci int ret; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; 2498c2ecf20Sopenharmony_ci sd_fmt.pad = pad->index; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt); 2528c2ecf20Sopenharmony_ci if (ret) 2538c2ecf20Sopenharmony_ci return ret; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci v4l2_fill_pix_format(fmt, &sd_fmt.format); 2568c2ecf20Sopenharmony_ci pix_map = vimc_pix_map_by_code(sd_fmt.format.code); 2578c2ecf20Sopenharmony_ci fmt->pixelformat = pix_map->pixelformat; 2588c2ecf20Sopenharmony_ci } else if (is_media_entity_v4l2_video_device(pad->entity)) { 2598c2ecf20Sopenharmony_ci struct video_device *vdev = container_of(pad->entity, 2608c2ecf20Sopenharmony_ci struct video_device, 2618c2ecf20Sopenharmony_ci entity); 2628c2ecf20Sopenharmony_ci struct vimc_ent_device *ved = video_get_drvdata(vdev); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (!ved->vdev_get_format) 2658c2ecf20Sopenharmony_ci return -ENOIOCTLCMD; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci ved->vdev_get_format(ved, fmt); 2688c2ecf20Sopenharmony_ci } else { 2698c2ecf20Sopenharmony_ci return -EINVAL; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return 0; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ciint vimc_vdev_link_validate(struct media_link *link) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci struct v4l2_pix_format source_fmt, sink_fmt; 2788c2ecf20Sopenharmony_ci int ret; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci ret = vimc_get_pix_format(link->source, &source_fmt); 2818c2ecf20Sopenharmony_ci if (ret) 2828c2ecf20Sopenharmony_ci return ret; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci ret = vimc_get_pix_format(link->sink, &sink_fmt); 2858c2ecf20Sopenharmony_ci if (ret) 2868c2ecf20Sopenharmony_ci return ret; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci pr_info("vimc link validate: " 2898c2ecf20Sopenharmony_ci "%s:src:%dx%d (0x%x, %d, %d, %d, %d) " 2908c2ecf20Sopenharmony_ci "%s:snk:%dx%d (0x%x, %d, %d, %d, %d)\n", 2918c2ecf20Sopenharmony_ci /* src */ 2928c2ecf20Sopenharmony_ci link->source->entity->name, 2938c2ecf20Sopenharmony_ci source_fmt.width, source_fmt.height, 2948c2ecf20Sopenharmony_ci source_fmt.pixelformat, source_fmt.colorspace, 2958c2ecf20Sopenharmony_ci source_fmt.quantization, source_fmt.xfer_func, 2968c2ecf20Sopenharmony_ci source_fmt.ycbcr_enc, 2978c2ecf20Sopenharmony_ci /* sink */ 2988c2ecf20Sopenharmony_ci link->sink->entity->name, 2998c2ecf20Sopenharmony_ci sink_fmt.width, sink_fmt.height, 3008c2ecf20Sopenharmony_ci sink_fmt.pixelformat, sink_fmt.colorspace, 3018c2ecf20Sopenharmony_ci sink_fmt.quantization, sink_fmt.xfer_func, 3028c2ecf20Sopenharmony_ci sink_fmt.ycbcr_enc); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* The width, height and pixelformat must match. */ 3058c2ecf20Sopenharmony_ci if (source_fmt.width != sink_fmt.width || 3068c2ecf20Sopenharmony_ci source_fmt.height != sink_fmt.height || 3078c2ecf20Sopenharmony_ci source_fmt.pixelformat != sink_fmt.pixelformat) 3088c2ecf20Sopenharmony_ci return -EPIPE; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* 3118c2ecf20Sopenharmony_ci * The field order must match, or the sink field order must be NONE 3128c2ecf20Sopenharmony_ci * to support interlaced hardware connected to bridges that support 3138c2ecf20Sopenharmony_ci * progressive formats only. 3148c2ecf20Sopenharmony_ci */ 3158c2ecf20Sopenharmony_ci if (source_fmt.field != sink_fmt.field && 3168c2ecf20Sopenharmony_ci sink_fmt.field != V4L2_FIELD_NONE) 3178c2ecf20Sopenharmony_ci return -EPIPE; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* 3208c2ecf20Sopenharmony_ci * If colorspace is DEFAULT, then assume all the colorimetry is also 3218c2ecf20Sopenharmony_ci * DEFAULT, return 0 to skip comparing the other colorimetry parameters 3228c2ecf20Sopenharmony_ci */ 3238c2ecf20Sopenharmony_ci if (source_fmt.colorspace == V4L2_COLORSPACE_DEFAULT || 3248c2ecf20Sopenharmony_ci sink_fmt.colorspace == V4L2_COLORSPACE_DEFAULT) 3258c2ecf20Sopenharmony_ci return 0; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* Colorspace must match. */ 3288c2ecf20Sopenharmony_ci if (source_fmt.colorspace != sink_fmt.colorspace) 3298c2ecf20Sopenharmony_ci return -EPIPE; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* Colorimetry must match if they are not set to DEFAULT */ 3328c2ecf20Sopenharmony_ci if (source_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT && 3338c2ecf20Sopenharmony_ci sink_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT && 3348c2ecf20Sopenharmony_ci source_fmt.ycbcr_enc != sink_fmt.ycbcr_enc) 3358c2ecf20Sopenharmony_ci return -EPIPE; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (source_fmt.quantization != V4L2_QUANTIZATION_DEFAULT && 3388c2ecf20Sopenharmony_ci sink_fmt.quantization != V4L2_QUANTIZATION_DEFAULT && 3398c2ecf20Sopenharmony_ci source_fmt.quantization != sink_fmt.quantization) 3408c2ecf20Sopenharmony_ci return -EPIPE; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if (source_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT && 3438c2ecf20Sopenharmony_ci sink_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT && 3448c2ecf20Sopenharmony_ci source_fmt.xfer_func != sink_fmt.xfer_func) 3458c2ecf20Sopenharmony_ci return -EPIPE; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci return 0; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic const struct media_entity_operations vimc_ent_sd_mops = { 3518c2ecf20Sopenharmony_ci .link_validate = v4l2_subdev_link_validate, 3528c2ecf20Sopenharmony_ci}; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ciint vimc_ent_sd_register(struct vimc_ent_device *ved, 3558c2ecf20Sopenharmony_ci struct v4l2_subdev *sd, 3568c2ecf20Sopenharmony_ci struct v4l2_device *v4l2_dev, 3578c2ecf20Sopenharmony_ci const char *const name, 3588c2ecf20Sopenharmony_ci u32 function, 3598c2ecf20Sopenharmony_ci u16 num_pads, 3608c2ecf20Sopenharmony_ci struct media_pad *pads, 3618c2ecf20Sopenharmony_ci const struct v4l2_subdev_ops *sd_ops) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci int ret; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /* Fill the vimc_ent_device struct */ 3668c2ecf20Sopenharmony_ci ved->ent = &sd->entity; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* Initialize the subdev */ 3698c2ecf20Sopenharmony_ci v4l2_subdev_init(sd, sd_ops); 3708c2ecf20Sopenharmony_ci sd->entity.function = function; 3718c2ecf20Sopenharmony_ci sd->entity.ops = &vimc_ent_sd_mops; 3728c2ecf20Sopenharmony_ci sd->owner = THIS_MODULE; 3738c2ecf20Sopenharmony_ci strscpy(sd->name, name, sizeof(sd->name)); 3748c2ecf20Sopenharmony_ci v4l2_set_subdevdata(sd, ved); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* Expose this subdev to user space */ 3778c2ecf20Sopenharmony_ci sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 3788c2ecf20Sopenharmony_ci if (sd->ctrl_handler) 3798c2ecf20Sopenharmony_ci sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci /* Initialize the media entity */ 3828c2ecf20Sopenharmony_ci ret = media_entity_pads_init(&sd->entity, num_pads, pads); 3838c2ecf20Sopenharmony_ci if (ret) 3848c2ecf20Sopenharmony_ci return ret; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci /* Register the subdev with the v4l2 and the media framework */ 3878c2ecf20Sopenharmony_ci ret = v4l2_device_register_subdev(v4l2_dev, sd); 3888c2ecf20Sopenharmony_ci if (ret) { 3898c2ecf20Sopenharmony_ci dev_err(v4l2_dev->dev, 3908c2ecf20Sopenharmony_ci "%s: subdev register failed (err=%d)\n", 3918c2ecf20Sopenharmony_ci name, ret); 3928c2ecf20Sopenharmony_ci goto err_clean_m_ent; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci return 0; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cierr_clean_m_ent: 3988c2ecf20Sopenharmony_ci media_entity_cleanup(&sd->entity); 3998c2ecf20Sopenharmony_ci return ret; 4008c2ecf20Sopenharmony_ci} 401