1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * camss-vfe.c 4 * 5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module 6 * 7 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. 8 * Copyright (C) 2015-2018 Linaro Ltd. 9 */ 10 #include <linux/clk.h> 11 #include <linux/completion.h> 12 #include <linux/interrupt.h> 13 #include <linux/iommu.h> 14 #include <linux/mutex.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 #include <linux/pm_domain.h> 18 #include <linux/pm_runtime.h> 19 #include <linux/spinlock_types.h> 20 #include <linux/spinlock.h> 21 #include <media/media-entity.h> 22 #include <media/v4l2-device.h> 23 #include <media/v4l2-subdev.h> 24 25 #include "camss-vfe.h" 26 #include "camss.h" 27 28 #define MSM_VFE_NAME "msm_vfe" 29 30 /* VFE reset timeout */ 31 #define VFE_RESET_TIMEOUT_MS 50 32 33 #define SCALER_RATIO_MAX 16 34 35 static const struct camss_format_info formats_rdi_8x16[] = { 36 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, 37 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 38 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, 39 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 40 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, 41 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 42 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, 43 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 44 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1, 45 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 46 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1, 47 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 48 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1, 49 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 50 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1, 51 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 52 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1, 53 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 54 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1, 55 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 56 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1, 57 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 58 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1, 59 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 60 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1, 61 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 62 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1, 63 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 64 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1, 65 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 66 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1, 67 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 68 { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1, 69 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 70 }; 71 72 static const struct camss_format_info formats_rdi_8x96[] = { 73 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, 74 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 75 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, 76 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 77 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, 78 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 79 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, 80 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 81 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1, 82 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 83 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1, 84 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 85 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1, 86 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 87 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1, 88 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 89 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1, 90 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 91 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1, 92 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 93 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1, 94 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 95 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1, 96 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 97 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1, 98 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 99 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1, 100 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 101 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1, 102 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 103 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1, 104 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 105 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1, 106 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 107 { MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1, 108 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 109 { MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1, 110 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 111 { MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1, 112 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 113 { MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1, 114 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 115 { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1, 116 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 117 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1, 118 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 119 }; 120 121 static const struct camss_format_info formats_rdi_845[] = { 122 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, 123 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 124 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, 125 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 126 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, 127 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 128 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, 129 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 130 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1, 131 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 132 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1, 133 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 134 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1, 135 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 136 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1, 137 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 138 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1, 139 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 140 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1, 141 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 142 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1, 143 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 144 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1, 145 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 146 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1, 147 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 148 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1, 149 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 150 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1, 151 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 152 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1, 153 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 154 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1, 155 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, 156 { MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1, 157 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 158 { MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1, 159 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 160 { MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1, 161 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 162 { MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1, 163 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, 164 { MEDIA_BUS_FMT_Y8_1X8, 8, V4L2_PIX_FMT_GREY, 1, 165 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, 166 { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1, 167 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, 168 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1, 169 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 170 }; 171 172 static const struct camss_format_info formats_pix_8x16[] = { 173 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 174 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 175 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 176 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 177 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 178 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 179 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 180 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 181 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 182 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 183 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 184 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 185 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 186 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 187 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 188 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 189 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 190 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 191 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 192 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 193 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 194 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 195 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 196 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 197 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 198 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 199 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 200 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 201 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 202 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 203 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 204 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 205 }; 206 207 static const struct camss_format_info formats_pix_8x96[] = { 208 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 209 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 210 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 211 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 212 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 213 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 214 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, 215 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 216 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 217 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 218 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 219 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 220 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 221 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 222 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, 223 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, 224 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 225 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 226 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 227 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 228 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 229 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 230 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, 231 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 232 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 233 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 234 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 235 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 236 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 237 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 238 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, 239 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, 240 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, 241 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 242 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, 243 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 244 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, 245 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 246 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, 247 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, 248 }; 249 250 const struct camss_formats vfe_formats_rdi_8x16 = { 251 .nformats = ARRAY_SIZE(formats_rdi_8x16), 252 .formats = formats_rdi_8x16 253 }; 254 255 const struct camss_formats vfe_formats_pix_8x16 = { 256 .nformats = ARRAY_SIZE(formats_pix_8x16), 257 .formats = formats_pix_8x16 258 }; 259 260 const struct camss_formats vfe_formats_rdi_8x96 = { 261 .nformats = ARRAY_SIZE(formats_rdi_8x96), 262 .formats = formats_rdi_8x96 263 }; 264 265 const struct camss_formats vfe_formats_pix_8x96 = { 266 .nformats = ARRAY_SIZE(formats_pix_8x96), 267 .formats = formats_pix_8x96 268 }; 269 270 const struct camss_formats vfe_formats_rdi_845 = { 271 .nformats = ARRAY_SIZE(formats_rdi_845), 272 .formats = formats_rdi_845 273 }; 274 275 /* TODO: Replace with pix formats */ 276 const struct camss_formats vfe_formats_pix_845 = { 277 .nformats = ARRAY_SIZE(formats_rdi_845), 278 .formats = formats_rdi_845 279 }; 280 281 static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, 282 unsigned int index, u32 src_req_code) 283 { 284 struct vfe_device *vfe = to_vfe(line); 285 286 switch (vfe->camss->res->version) { 287 case CAMSS_8x16: 288 case CAMSS_8x53: 289 switch (sink_code) { 290 case MEDIA_BUS_FMT_YUYV8_1X16: 291 { 292 u32 src_code[] = { 293 MEDIA_BUS_FMT_YUYV8_1X16, 294 MEDIA_BUS_FMT_YUYV8_1_5X8, 295 }; 296 297 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 298 index, src_req_code); 299 } 300 case MEDIA_BUS_FMT_YVYU8_1X16: 301 { 302 u32 src_code[] = { 303 MEDIA_BUS_FMT_YVYU8_1X16, 304 MEDIA_BUS_FMT_YVYU8_1_5X8, 305 }; 306 307 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 308 index, src_req_code); 309 } 310 case MEDIA_BUS_FMT_UYVY8_1X16: 311 { 312 u32 src_code[] = { 313 MEDIA_BUS_FMT_UYVY8_1X16, 314 MEDIA_BUS_FMT_UYVY8_1_5X8, 315 }; 316 317 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 318 index, src_req_code); 319 } 320 case MEDIA_BUS_FMT_VYUY8_1X16: 321 { 322 u32 src_code[] = { 323 MEDIA_BUS_FMT_VYUY8_1X16, 324 MEDIA_BUS_FMT_VYUY8_1_5X8, 325 }; 326 327 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 328 index, src_req_code); 329 } 330 default: 331 if (index > 0) 332 return 0; 333 334 return sink_code; 335 } 336 break; 337 case CAMSS_8x96: 338 case CAMSS_660: 339 case CAMSS_845: 340 case CAMSS_8250: 341 case CAMSS_8280XP: 342 switch (sink_code) { 343 case MEDIA_BUS_FMT_YUYV8_1X16: 344 { 345 u32 src_code[] = { 346 MEDIA_BUS_FMT_YUYV8_1X16, 347 MEDIA_BUS_FMT_YVYU8_1X16, 348 MEDIA_BUS_FMT_UYVY8_1X16, 349 MEDIA_BUS_FMT_VYUY8_1X16, 350 MEDIA_BUS_FMT_YUYV8_1_5X8, 351 }; 352 353 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 354 index, src_req_code); 355 } 356 case MEDIA_BUS_FMT_YVYU8_1X16: 357 { 358 u32 src_code[] = { 359 MEDIA_BUS_FMT_YVYU8_1X16, 360 MEDIA_BUS_FMT_YUYV8_1X16, 361 MEDIA_BUS_FMT_UYVY8_1X16, 362 MEDIA_BUS_FMT_VYUY8_1X16, 363 MEDIA_BUS_FMT_YVYU8_1_5X8, 364 }; 365 366 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 367 index, src_req_code); 368 } 369 case MEDIA_BUS_FMT_UYVY8_1X16: 370 { 371 u32 src_code[] = { 372 MEDIA_BUS_FMT_UYVY8_1X16, 373 MEDIA_BUS_FMT_YUYV8_1X16, 374 MEDIA_BUS_FMT_YVYU8_1X16, 375 MEDIA_BUS_FMT_VYUY8_1X16, 376 MEDIA_BUS_FMT_UYVY8_1_5X8, 377 }; 378 379 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 380 index, src_req_code); 381 } 382 case MEDIA_BUS_FMT_VYUY8_1X16: 383 { 384 u32 src_code[] = { 385 MEDIA_BUS_FMT_VYUY8_1X16, 386 MEDIA_BUS_FMT_YUYV8_1X16, 387 MEDIA_BUS_FMT_YVYU8_1X16, 388 MEDIA_BUS_FMT_UYVY8_1X16, 389 MEDIA_BUS_FMT_VYUY8_1_5X8, 390 }; 391 392 return camss_format_find_code(src_code, ARRAY_SIZE(src_code), 393 index, src_req_code); 394 } 395 default: 396 if (index > 0) 397 return 0; 398 399 return sink_code; 400 } 401 break; 402 } 403 return 0; 404 } 405 406 int vfe_reset(struct vfe_device *vfe) 407 { 408 unsigned long time; 409 410 reinit_completion(&vfe->reset_complete); 411 412 vfe->res->hw_ops->global_reset(vfe); 413 414 time = wait_for_completion_timeout(&vfe->reset_complete, 415 msecs_to_jiffies(VFE_RESET_TIMEOUT_MS)); 416 if (!time) { 417 dev_err(vfe->camss->dev, "VFE reset timeout\n"); 418 return -EIO; 419 } 420 421 return 0; 422 } 423 424 static void vfe_init_outputs(struct vfe_device *vfe) 425 { 426 int i; 427 428 for (i = 0; i < vfe->res->line_num; i++) { 429 struct vfe_output *output = &vfe->line[i].output; 430 431 output->state = VFE_OUTPUT_OFF; 432 output->buf[0] = NULL; 433 output->buf[1] = NULL; 434 INIT_LIST_HEAD(&output->pending_bufs); 435 } 436 } 437 438 static void vfe_reset_output_maps(struct vfe_device *vfe) 439 { 440 int i; 441 442 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) 443 vfe->wm_output_map[i] = VFE_LINE_NONE; 444 } 445 446 int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id) 447 { 448 int ret = -EBUSY; 449 int i; 450 451 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) { 452 if (vfe->wm_output_map[i] == VFE_LINE_NONE) { 453 vfe->wm_output_map[i] = line_id; 454 ret = i; 455 break; 456 } 457 } 458 459 return ret; 460 } 461 462 int vfe_release_wm(struct vfe_device *vfe, u8 wm) 463 { 464 if (wm >= ARRAY_SIZE(vfe->wm_output_map)) 465 return -EINVAL; 466 467 vfe->wm_output_map[wm] = VFE_LINE_NONE; 468 469 return 0; 470 } 471 472 struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output) 473 { 474 struct camss_buffer *buffer = NULL; 475 476 if (!list_empty(&output->pending_bufs)) { 477 buffer = list_first_entry(&output->pending_bufs, 478 struct camss_buffer, 479 queue); 480 list_del(&buffer->queue); 481 } 482 483 return buffer; 484 } 485 486 void vfe_buf_add_pending(struct vfe_output *output, 487 struct camss_buffer *buffer) 488 { 489 INIT_LIST_HEAD(&buffer->queue); 490 list_add_tail(&buffer->queue, &output->pending_bufs); 491 } 492 493 /* 494 * vfe_buf_flush_pending - Flush all pending buffers. 495 * @output: VFE output 496 * @state: vb2 buffer state 497 */ 498 static void vfe_buf_flush_pending(struct vfe_output *output, 499 enum vb2_buffer_state state) 500 { 501 struct camss_buffer *buf; 502 struct camss_buffer *t; 503 504 list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) { 505 vb2_buffer_done(&buf->vb.vb2_buf, state); 506 list_del(&buf->queue); 507 } 508 } 509 510 int vfe_put_output(struct vfe_line *line) 511 { 512 struct vfe_device *vfe = to_vfe(line); 513 struct vfe_output *output = &line->output; 514 unsigned long flags; 515 unsigned int i; 516 517 spin_lock_irqsave(&vfe->output_lock, flags); 518 519 for (i = 0; i < output->wm_num; i++) 520 vfe_release_wm(vfe, output->wm_idx[i]); 521 522 output->state = VFE_OUTPUT_OFF; 523 524 spin_unlock_irqrestore(&vfe->output_lock, flags); 525 return 0; 526 } 527 528 static int vfe_disable_output(struct vfe_line *line) 529 { 530 struct vfe_device *vfe = to_vfe(line); 531 struct vfe_output *output = &line->output; 532 unsigned long flags; 533 unsigned int i; 534 535 spin_lock_irqsave(&vfe->output_lock, flags); 536 for (i = 0; i < output->wm_num; i++) 537 vfe->res->hw_ops->vfe_wm_stop(vfe, output->wm_idx[i]); 538 output->gen2.active_num = 0; 539 spin_unlock_irqrestore(&vfe->output_lock, flags); 540 541 return vfe_reset(vfe); 542 } 543 544 /* 545 * vfe_disable - Disable streaming on VFE line 546 * @line: VFE line 547 * 548 * Return 0 on success or a negative error code otherwise 549 */ 550 int vfe_disable(struct vfe_line *line) 551 { 552 struct vfe_device *vfe = to_vfe(line); 553 int ret; 554 555 ret = vfe_disable_output(line); 556 if (ret) 557 goto error; 558 559 vfe_put_output(line); 560 561 mutex_lock(&vfe->stream_lock); 562 563 vfe->stream_count--; 564 565 mutex_unlock(&vfe->stream_lock); 566 567 error: 568 return ret; 569 } 570 571 /** 572 * vfe_isr_comp_done() - Process composite image done interrupt 573 * @vfe: VFE Device 574 * @comp: Composite image id 575 */ 576 void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp) 577 { 578 unsigned int i; 579 580 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) 581 if (vfe->wm_output_map[i] == VFE_LINE_PIX) { 582 vfe->isr_ops.wm_done(vfe, i); 583 break; 584 } 585 } 586 587 void vfe_isr_reset_ack(struct vfe_device *vfe) 588 { 589 complete(&vfe->reset_complete); 590 } 591 592 /* 593 * vfe_pm_domain_off - Disable power domains specific to this VFE. 594 * @vfe: VFE Device 595 */ 596 void vfe_pm_domain_off(struct vfe_device *vfe) 597 { 598 if (!vfe->genpd) 599 return; 600 601 device_link_del(vfe->genpd_link); 602 vfe->genpd_link = NULL; 603 } 604 605 /* 606 * vfe_pm_domain_on - Enable power domains specific to this VFE. 607 * @vfe: VFE Device 608 */ 609 int vfe_pm_domain_on(struct vfe_device *vfe) 610 { 611 struct camss *camss = vfe->camss; 612 613 if (!vfe->genpd) 614 return 0; 615 616 vfe->genpd_link = device_link_add(camss->dev, vfe->genpd, 617 DL_FLAG_STATELESS | 618 DL_FLAG_PM_RUNTIME | 619 DL_FLAG_RPM_ACTIVE); 620 if (!vfe->genpd_link) 621 return -EINVAL; 622 623 return 0; 624 } 625 626 static int vfe_match_clock_names(struct vfe_device *vfe, 627 struct camss_clock *clock) 628 { 629 char vfe_name[7]; /* vfeXXX\0 */ 630 char vfe_lite_name[12]; /* vfe_liteXXX\0 */ 631 632 snprintf(vfe_name, sizeof(vfe_name), "vfe%d", vfe->id); 633 snprintf(vfe_lite_name, sizeof(vfe_lite_name), "vfe_lite%d", vfe->id); 634 635 return (!strcmp(clock->name, vfe_name) || 636 !strcmp(clock->name, vfe_lite_name) || 637 !strcmp(clock->name, "vfe_lite")); 638 } 639 640 /* 641 * vfe_set_clock_rates - Calculate and set clock rates on VFE module 642 * @vfe: VFE device 643 * 644 * Return 0 on success or a negative error code otherwise 645 */ 646 static int vfe_set_clock_rates(struct vfe_device *vfe) 647 { 648 struct device *dev = vfe->camss->dev; 649 u64 pixel_clock[VFE_LINE_NUM_MAX]; 650 int i, j; 651 int ret; 652 653 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) { 654 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity, 655 &pixel_clock[i]); 656 if (ret) 657 pixel_clock[i] = 0; 658 } 659 660 for (i = 0; i < vfe->nclocks; i++) { 661 struct camss_clock *clock = &vfe->clock[i]; 662 663 if (vfe_match_clock_names(vfe, clock)) { 664 u64 min_rate = 0; 665 long rate; 666 667 for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) { 668 u32 tmp; 669 u8 bpp; 670 671 if (j == VFE_LINE_PIX) { 672 tmp = pixel_clock[j]; 673 } else { 674 struct vfe_line *l = &vfe->line[j]; 675 676 bpp = camss_format_get_bpp(l->formats, 677 l->nformats, 678 l->fmt[MSM_VFE_PAD_SINK].code); 679 tmp = pixel_clock[j] * bpp / 64; 680 } 681 682 if (min_rate < tmp) 683 min_rate = tmp; 684 } 685 686 camss_add_clock_margin(&min_rate); 687 688 for (j = 0; j < clock->nfreqs; j++) 689 if (min_rate < clock->freq[j]) 690 break; 691 692 if (j == clock->nfreqs) { 693 dev_err(dev, 694 "Pixel clock is too high for VFE"); 695 return -EINVAL; 696 } 697 698 /* if sensor pixel clock is not available */ 699 /* set highest possible VFE clock rate */ 700 if (min_rate == 0) 701 j = clock->nfreqs - 1; 702 703 rate = clk_round_rate(clock->clk, clock->freq[j]); 704 if (rate < 0) { 705 dev_err(dev, "clk round rate failed: %ld\n", 706 rate); 707 return -EINVAL; 708 } 709 710 ret = clk_set_rate(clock->clk, rate); 711 if (ret < 0) { 712 dev_err(dev, "clk set rate failed: %d\n", ret); 713 return ret; 714 } 715 } 716 } 717 718 return 0; 719 } 720 721 /* 722 * vfe_check_clock_rates - Check current clock rates on VFE module 723 * @vfe: VFE device 724 * 725 * Return 0 if current clock rates are suitable for a new pipeline 726 * or a negative error code otherwise 727 */ 728 static int vfe_check_clock_rates(struct vfe_device *vfe) 729 { 730 u64 pixel_clock[VFE_LINE_NUM_MAX]; 731 int i, j; 732 int ret; 733 734 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) { 735 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity, 736 &pixel_clock[i]); 737 if (ret) 738 pixel_clock[i] = 0; 739 } 740 741 for (i = 0; i < vfe->nclocks; i++) { 742 struct camss_clock *clock = &vfe->clock[i]; 743 744 if (vfe_match_clock_names(vfe, clock)) { 745 u64 min_rate = 0; 746 unsigned long rate; 747 748 for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) { 749 u32 tmp; 750 u8 bpp; 751 752 if (j == VFE_LINE_PIX) { 753 tmp = pixel_clock[j]; 754 } else { 755 struct vfe_line *l = &vfe->line[j]; 756 757 bpp = camss_format_get_bpp(l->formats, 758 l->nformats, 759 l->fmt[MSM_VFE_PAD_SINK].code); 760 tmp = pixel_clock[j] * bpp / 64; 761 } 762 763 if (min_rate < tmp) 764 min_rate = tmp; 765 } 766 767 camss_add_clock_margin(&min_rate); 768 769 rate = clk_get_rate(clock->clk); 770 if (rate < min_rate) 771 return -EBUSY; 772 } 773 } 774 775 return 0; 776 } 777 778 /* 779 * vfe_get - Power up and reset VFE module 780 * @vfe: VFE Device 781 * 782 * Return 0 on success or a negative error code otherwise 783 */ 784 int vfe_get(struct vfe_device *vfe) 785 { 786 int ret; 787 788 mutex_lock(&vfe->power_lock); 789 790 if (vfe->power_count == 0) { 791 ret = vfe->res->hw_ops->pm_domain_on(vfe); 792 if (ret < 0) 793 goto error_pm_domain; 794 795 ret = pm_runtime_resume_and_get(vfe->camss->dev); 796 if (ret < 0) 797 goto error_domain_off; 798 799 ret = vfe_set_clock_rates(vfe); 800 if (ret < 0) 801 goto error_pm_runtime_get; 802 803 ret = camss_enable_clocks(vfe->nclocks, vfe->clock, 804 vfe->camss->dev); 805 if (ret < 0) 806 goto error_pm_runtime_get; 807 808 ret = vfe_reset(vfe); 809 if (ret < 0) 810 goto error_reset; 811 812 vfe_reset_output_maps(vfe); 813 814 vfe_init_outputs(vfe); 815 816 vfe->res->hw_ops->hw_version(vfe); 817 } else { 818 ret = vfe_check_clock_rates(vfe); 819 if (ret < 0) 820 goto error_pm_domain; 821 } 822 vfe->power_count++; 823 824 mutex_unlock(&vfe->power_lock); 825 826 return 0; 827 828 error_reset: 829 camss_disable_clocks(vfe->nclocks, vfe->clock); 830 831 error_pm_runtime_get: 832 pm_runtime_put_sync(vfe->camss->dev); 833 error_domain_off: 834 vfe->res->hw_ops->pm_domain_off(vfe); 835 836 error_pm_domain: 837 mutex_unlock(&vfe->power_lock); 838 839 return ret; 840 } 841 842 /* 843 * vfe_put - Power down VFE module 844 * @vfe: VFE Device 845 */ 846 void vfe_put(struct vfe_device *vfe) 847 { 848 mutex_lock(&vfe->power_lock); 849 850 if (vfe->power_count == 0) { 851 dev_err(vfe->camss->dev, "vfe power off on power_count == 0\n"); 852 goto exit; 853 } else if (vfe->power_count == 1) { 854 if (vfe->was_streaming) { 855 vfe->was_streaming = 0; 856 vfe->res->hw_ops->vfe_halt(vfe); 857 } 858 camss_disable_clocks(vfe->nclocks, vfe->clock); 859 pm_runtime_put_sync(vfe->camss->dev); 860 vfe->res->hw_ops->pm_domain_off(vfe); 861 } 862 863 vfe->power_count--; 864 865 exit: 866 mutex_unlock(&vfe->power_lock); 867 } 868 869 /* 870 * vfe_flush_buffers - Return all vb2 buffers 871 * @vid: Video device structure 872 * @state: vb2 buffer state of the returned buffers 873 * 874 * Return all buffers to vb2. This includes queued pending buffers (still 875 * unused) and any buffers given to the hardware but again still not used. 876 * 877 * Return 0 on success or a negative error code otherwise 878 */ 879 int vfe_flush_buffers(struct camss_video *vid, 880 enum vb2_buffer_state state) 881 { 882 struct vfe_line *line = container_of(vid, struct vfe_line, video_out); 883 struct vfe_device *vfe = to_vfe(line); 884 struct vfe_output *output; 885 unsigned long flags; 886 887 output = &line->output; 888 889 spin_lock_irqsave(&vfe->output_lock, flags); 890 891 vfe_buf_flush_pending(output, state); 892 893 if (output->buf[0]) 894 vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state); 895 896 if (output->buf[1]) 897 vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state); 898 899 if (output->last_buffer) { 900 vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state); 901 output->last_buffer = NULL; 902 } 903 904 spin_unlock_irqrestore(&vfe->output_lock, flags); 905 906 return 0; 907 } 908 909 /* 910 * vfe_set_power - Power on/off VFE module 911 * @sd: VFE V4L2 subdevice 912 * @on: Requested power state 913 * 914 * Return 0 on success or a negative error code otherwise 915 */ 916 static int vfe_set_power(struct v4l2_subdev *sd, int on) 917 { 918 struct vfe_line *line = v4l2_get_subdevdata(sd); 919 struct vfe_device *vfe = to_vfe(line); 920 int ret; 921 922 if (on) { 923 ret = vfe_get(vfe); 924 if (ret < 0) 925 return ret; 926 } else { 927 vfe_put(vfe); 928 } 929 930 return 0; 931 } 932 933 /* 934 * vfe_set_stream - Enable/disable streaming on VFE module 935 * @sd: VFE V4L2 subdevice 936 * @enable: Requested streaming state 937 * 938 * Main configuration of VFE module is triggered here. 939 * 940 * Return 0 on success or a negative error code otherwise 941 */ 942 static int vfe_set_stream(struct v4l2_subdev *sd, int enable) 943 { 944 struct vfe_line *line = v4l2_get_subdevdata(sd); 945 struct vfe_device *vfe = to_vfe(line); 946 int ret; 947 948 if (enable) { 949 line->output.state = VFE_OUTPUT_RESERVED; 950 ret = vfe->res->hw_ops->vfe_enable(line); 951 if (ret < 0) 952 dev_err(vfe->camss->dev, 953 "Failed to enable vfe outputs\n"); 954 } else { 955 ret = vfe->res->hw_ops->vfe_disable(line); 956 if (ret < 0) 957 dev_err(vfe->camss->dev, 958 "Failed to disable vfe outputs\n"); 959 } 960 961 return ret; 962 } 963 964 /* 965 * __vfe_get_format - Get pointer to format structure 966 * @line: VFE line 967 * @sd_state: V4L2 subdev state 968 * @pad: pad from which format is requested 969 * @which: TRY or ACTIVE format 970 * 971 * Return pointer to TRY or ACTIVE format structure 972 */ 973 static struct v4l2_mbus_framefmt * 974 __vfe_get_format(struct vfe_line *line, 975 struct v4l2_subdev_state *sd_state, 976 unsigned int pad, 977 enum v4l2_subdev_format_whence which) 978 { 979 if (which == V4L2_SUBDEV_FORMAT_TRY) 980 return v4l2_subdev_state_get_format(sd_state, pad); 981 982 return &line->fmt[pad]; 983 } 984 985 /* 986 * __vfe_get_compose - Get pointer to compose selection structure 987 * @line: VFE line 988 * @sd_state: V4L2 subdev state 989 * @which: TRY or ACTIVE format 990 * 991 * Return pointer to TRY or ACTIVE compose rectangle structure 992 */ 993 static struct v4l2_rect * 994 __vfe_get_compose(struct vfe_line *line, 995 struct v4l2_subdev_state *sd_state, 996 enum v4l2_subdev_format_whence which) 997 { 998 if (which == V4L2_SUBDEV_FORMAT_TRY) 999 return v4l2_subdev_state_get_compose(sd_state, 1000 MSM_VFE_PAD_SINK); 1001 1002 return &line->compose; 1003 } 1004 1005 /* 1006 * __vfe_get_crop - Get pointer to crop selection structure 1007 * @line: VFE line 1008 * @sd_state: V4L2 subdev state 1009 * @which: TRY or ACTIVE format 1010 * 1011 * Return pointer to TRY or ACTIVE crop rectangle structure 1012 */ 1013 static struct v4l2_rect * 1014 __vfe_get_crop(struct vfe_line *line, 1015 struct v4l2_subdev_state *sd_state, 1016 enum v4l2_subdev_format_whence which) 1017 { 1018 if (which == V4L2_SUBDEV_FORMAT_TRY) 1019 return v4l2_subdev_state_get_crop(sd_state, MSM_VFE_PAD_SRC); 1020 1021 return &line->crop; 1022 } 1023 1024 /* 1025 * vfe_try_format - Handle try format by pad subdev method 1026 * @line: VFE line 1027 * @sd_state: V4L2 subdev state 1028 * @pad: pad on which format is requested 1029 * @fmt: pointer to v4l2 format structure 1030 * @which: wanted subdev format 1031 */ 1032 static void vfe_try_format(struct vfe_line *line, 1033 struct v4l2_subdev_state *sd_state, 1034 unsigned int pad, 1035 struct v4l2_mbus_framefmt *fmt, 1036 enum v4l2_subdev_format_whence which) 1037 { 1038 unsigned int i; 1039 u32 code; 1040 1041 switch (pad) { 1042 case MSM_VFE_PAD_SINK: 1043 /* Set format on sink pad */ 1044 1045 for (i = 0; i < line->nformats; i++) 1046 if (fmt->code == line->formats[i].code) 1047 break; 1048 1049 /* If not found, use UYVY as default */ 1050 if (i >= line->nformats) 1051 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; 1052 1053 fmt->width = clamp_t(u32, fmt->width, 1, 8191); 1054 fmt->height = clamp_t(u32, fmt->height, 1, 8191); 1055 1056 fmt->field = V4L2_FIELD_NONE; 1057 fmt->colorspace = V4L2_COLORSPACE_SRGB; 1058 1059 break; 1060 1061 case MSM_VFE_PAD_SRC: 1062 /* Set and return a format same as sink pad */ 1063 code = fmt->code; 1064 1065 *fmt = *__vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, 1066 which); 1067 1068 fmt->code = vfe_src_pad_code(line, fmt->code, 0, code); 1069 1070 if (line->id == VFE_LINE_PIX) { 1071 struct v4l2_rect *rect; 1072 1073 rect = __vfe_get_crop(line, sd_state, which); 1074 1075 fmt->width = rect->width; 1076 fmt->height = rect->height; 1077 } 1078 1079 break; 1080 } 1081 1082 fmt->colorspace = V4L2_COLORSPACE_SRGB; 1083 } 1084 1085 /* 1086 * vfe_try_compose - Handle try compose selection by pad subdev method 1087 * @line: VFE line 1088 * @sd_state: V4L2 subdev state 1089 * @rect: pointer to v4l2 rect structure 1090 * @which: wanted subdev format 1091 */ 1092 static void vfe_try_compose(struct vfe_line *line, 1093 struct v4l2_subdev_state *sd_state, 1094 struct v4l2_rect *rect, 1095 enum v4l2_subdev_format_whence which) 1096 { 1097 struct v4l2_mbus_framefmt *fmt; 1098 1099 fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, which); 1100 1101 if (rect->width > fmt->width) 1102 rect->width = fmt->width; 1103 1104 if (rect->height > fmt->height) 1105 rect->height = fmt->height; 1106 1107 if (fmt->width > rect->width * SCALER_RATIO_MAX) 1108 rect->width = (fmt->width + SCALER_RATIO_MAX - 1) / 1109 SCALER_RATIO_MAX; 1110 1111 rect->width &= ~0x1; 1112 1113 if (fmt->height > rect->height * SCALER_RATIO_MAX) 1114 rect->height = (fmt->height + SCALER_RATIO_MAX - 1) / 1115 SCALER_RATIO_MAX; 1116 1117 if (rect->width < 16) 1118 rect->width = 16; 1119 1120 if (rect->height < 4) 1121 rect->height = 4; 1122 } 1123 1124 /* 1125 * vfe_try_crop - Handle try crop selection by pad subdev method 1126 * @line: VFE line 1127 * @sd_state: V4L2 subdev state 1128 * @rect: pointer to v4l2 rect structure 1129 * @which: wanted subdev format 1130 */ 1131 static void vfe_try_crop(struct vfe_line *line, 1132 struct v4l2_subdev_state *sd_state, 1133 struct v4l2_rect *rect, 1134 enum v4l2_subdev_format_whence which) 1135 { 1136 struct v4l2_rect *compose; 1137 1138 compose = __vfe_get_compose(line, sd_state, which); 1139 1140 if (rect->width > compose->width) 1141 rect->width = compose->width; 1142 1143 if (rect->width + rect->left > compose->width) 1144 rect->left = compose->width - rect->width; 1145 1146 if (rect->height > compose->height) 1147 rect->height = compose->height; 1148 1149 if (rect->height + rect->top > compose->height) 1150 rect->top = compose->height - rect->height; 1151 1152 /* wm in line based mode writes multiple of 16 horizontally */ 1153 rect->left += (rect->width & 0xf) >> 1; 1154 rect->width &= ~0xf; 1155 1156 if (rect->width < 16) { 1157 rect->left = 0; 1158 rect->width = 16; 1159 } 1160 1161 if (rect->height < 4) { 1162 rect->top = 0; 1163 rect->height = 4; 1164 } 1165 } 1166 1167 /* 1168 * vfe_enum_mbus_code - Handle pixel format enumeration 1169 * @sd: VFE V4L2 subdevice 1170 * @sd_state: V4L2 subdev state 1171 * @code: pointer to v4l2_subdev_mbus_code_enum structure 1172 * 1173 * return -EINVAL or zero on success 1174 */ 1175 static int vfe_enum_mbus_code(struct v4l2_subdev *sd, 1176 struct v4l2_subdev_state *sd_state, 1177 struct v4l2_subdev_mbus_code_enum *code) 1178 { 1179 struct vfe_line *line = v4l2_get_subdevdata(sd); 1180 1181 if (code->pad == MSM_VFE_PAD_SINK) { 1182 if (code->index >= line->nformats) 1183 return -EINVAL; 1184 1185 code->code = line->formats[code->index].code; 1186 } else { 1187 struct v4l2_mbus_framefmt *sink_fmt; 1188 1189 sink_fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, 1190 code->which); 1191 1192 code->code = vfe_src_pad_code(line, sink_fmt->code, 1193 code->index, 0); 1194 if (!code->code) 1195 return -EINVAL; 1196 } 1197 1198 return 0; 1199 } 1200 1201 /* 1202 * vfe_enum_frame_size - Handle frame size enumeration 1203 * @sd: VFE V4L2 subdevice 1204 * @sd_state: V4L2 subdev state 1205 * @fse: pointer to v4l2_subdev_frame_size_enum structure 1206 * 1207 * Return -EINVAL or zero on success 1208 */ 1209 static int vfe_enum_frame_size(struct v4l2_subdev *sd, 1210 struct v4l2_subdev_state *sd_state, 1211 struct v4l2_subdev_frame_size_enum *fse) 1212 { 1213 struct vfe_line *line = v4l2_get_subdevdata(sd); 1214 struct v4l2_mbus_framefmt format; 1215 1216 if (fse->index != 0) 1217 return -EINVAL; 1218 1219 format.code = fse->code; 1220 format.width = 1; 1221 format.height = 1; 1222 vfe_try_format(line, sd_state, fse->pad, &format, fse->which); 1223 fse->min_width = format.width; 1224 fse->min_height = format.height; 1225 1226 if (format.code != fse->code) 1227 return -EINVAL; 1228 1229 format.code = fse->code; 1230 format.width = -1; 1231 format.height = -1; 1232 vfe_try_format(line, sd_state, fse->pad, &format, fse->which); 1233 fse->max_width = format.width; 1234 fse->max_height = format.height; 1235 1236 return 0; 1237 } 1238 1239 /* 1240 * vfe_get_format - Handle get format by pads subdev method 1241 * @sd: VFE V4L2 subdevice 1242 * @sd_state: V4L2 subdev state 1243 * @fmt: pointer to v4l2 subdev format structure 1244 * 1245 * Return -EINVAL or zero on success 1246 */ 1247 static int vfe_get_format(struct v4l2_subdev *sd, 1248 struct v4l2_subdev_state *sd_state, 1249 struct v4l2_subdev_format *fmt) 1250 { 1251 struct vfe_line *line = v4l2_get_subdevdata(sd); 1252 struct v4l2_mbus_framefmt *format; 1253 1254 format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which); 1255 if (format == NULL) 1256 return -EINVAL; 1257 1258 fmt->format = *format; 1259 1260 return 0; 1261 } 1262 1263 static int vfe_set_selection(struct v4l2_subdev *sd, 1264 struct v4l2_subdev_state *sd_state, 1265 struct v4l2_subdev_selection *sel); 1266 1267 /* 1268 * vfe_set_format - Handle set format by pads subdev method 1269 * @sd: VFE V4L2 subdevice 1270 * @sd_state: V4L2 subdev state 1271 * @fmt: pointer to v4l2 subdev format structure 1272 * 1273 * Return -EINVAL or zero on success 1274 */ 1275 static int vfe_set_format(struct v4l2_subdev *sd, 1276 struct v4l2_subdev_state *sd_state, 1277 struct v4l2_subdev_format *fmt) 1278 { 1279 struct vfe_line *line = v4l2_get_subdevdata(sd); 1280 struct v4l2_mbus_framefmt *format; 1281 1282 format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which); 1283 if (format == NULL) 1284 return -EINVAL; 1285 1286 vfe_try_format(line, sd_state, fmt->pad, &fmt->format, fmt->which); 1287 *format = fmt->format; 1288 1289 if (fmt->pad == MSM_VFE_PAD_SINK) { 1290 struct v4l2_subdev_selection sel = { 0 }; 1291 int ret; 1292 1293 /* Propagate the format from sink to source */ 1294 format = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SRC, 1295 fmt->which); 1296 1297 *format = fmt->format; 1298 vfe_try_format(line, sd_state, MSM_VFE_PAD_SRC, format, 1299 fmt->which); 1300 1301 if (line->id != VFE_LINE_PIX) 1302 return 0; 1303 1304 /* Reset sink pad compose selection */ 1305 sel.which = fmt->which; 1306 sel.pad = MSM_VFE_PAD_SINK; 1307 sel.target = V4L2_SEL_TGT_COMPOSE; 1308 sel.r.width = fmt->format.width; 1309 sel.r.height = fmt->format.height; 1310 ret = vfe_set_selection(sd, sd_state, &sel); 1311 if (ret < 0) 1312 return ret; 1313 } 1314 1315 return 0; 1316 } 1317 1318 /* 1319 * vfe_get_selection - Handle get selection by pads subdev method 1320 * @sd: VFE V4L2 subdevice 1321 * @sd_state: V4L2 subdev state 1322 * @sel: pointer to v4l2 subdev selection structure 1323 * 1324 * Return -EINVAL or zero on success 1325 */ 1326 static int vfe_get_selection(struct v4l2_subdev *sd, 1327 struct v4l2_subdev_state *sd_state, 1328 struct v4l2_subdev_selection *sel) 1329 { 1330 struct vfe_line *line = v4l2_get_subdevdata(sd); 1331 struct v4l2_subdev_format fmt = { 0 }; 1332 struct v4l2_rect *rect; 1333 int ret; 1334 1335 if (line->id != VFE_LINE_PIX) 1336 return -EINVAL; 1337 1338 if (sel->pad == MSM_VFE_PAD_SINK) 1339 switch (sel->target) { 1340 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 1341 fmt.pad = sel->pad; 1342 fmt.which = sel->which; 1343 ret = vfe_get_format(sd, sd_state, &fmt); 1344 if (ret < 0) 1345 return ret; 1346 1347 sel->r.left = 0; 1348 sel->r.top = 0; 1349 sel->r.width = fmt.format.width; 1350 sel->r.height = fmt.format.height; 1351 break; 1352 case V4L2_SEL_TGT_COMPOSE: 1353 rect = __vfe_get_compose(line, sd_state, sel->which); 1354 if (rect == NULL) 1355 return -EINVAL; 1356 1357 sel->r = *rect; 1358 break; 1359 default: 1360 return -EINVAL; 1361 } 1362 else if (sel->pad == MSM_VFE_PAD_SRC) 1363 switch (sel->target) { 1364 case V4L2_SEL_TGT_CROP_BOUNDS: 1365 rect = __vfe_get_compose(line, sd_state, sel->which); 1366 if (rect == NULL) 1367 return -EINVAL; 1368 1369 sel->r.left = rect->left; 1370 sel->r.top = rect->top; 1371 sel->r.width = rect->width; 1372 sel->r.height = rect->height; 1373 break; 1374 case V4L2_SEL_TGT_CROP: 1375 rect = __vfe_get_crop(line, sd_state, sel->which); 1376 if (rect == NULL) 1377 return -EINVAL; 1378 1379 sel->r = *rect; 1380 break; 1381 default: 1382 return -EINVAL; 1383 } 1384 1385 return 0; 1386 } 1387 1388 /* 1389 * vfe_set_selection - Handle set selection by pads subdev method 1390 * @sd: VFE V4L2 subdevice 1391 * @sd_state: V4L2 subdev state 1392 * @sel: pointer to v4l2 subdev selection structure 1393 * 1394 * Return -EINVAL or zero on success 1395 */ 1396 static int vfe_set_selection(struct v4l2_subdev *sd, 1397 struct v4l2_subdev_state *sd_state, 1398 struct v4l2_subdev_selection *sel) 1399 { 1400 struct vfe_line *line = v4l2_get_subdevdata(sd); 1401 struct v4l2_rect *rect; 1402 int ret; 1403 1404 if (line->id != VFE_LINE_PIX) 1405 return -EINVAL; 1406 1407 if (sel->target == V4L2_SEL_TGT_COMPOSE && 1408 sel->pad == MSM_VFE_PAD_SINK) { 1409 struct v4l2_subdev_selection crop = { 0 }; 1410 1411 rect = __vfe_get_compose(line, sd_state, sel->which); 1412 if (rect == NULL) 1413 return -EINVAL; 1414 1415 vfe_try_compose(line, sd_state, &sel->r, sel->which); 1416 *rect = sel->r; 1417 1418 /* Reset source crop selection */ 1419 crop.which = sel->which; 1420 crop.pad = MSM_VFE_PAD_SRC; 1421 crop.target = V4L2_SEL_TGT_CROP; 1422 crop.r = *rect; 1423 ret = vfe_set_selection(sd, sd_state, &crop); 1424 } else if (sel->target == V4L2_SEL_TGT_CROP && 1425 sel->pad == MSM_VFE_PAD_SRC) { 1426 struct v4l2_subdev_format fmt = { 0 }; 1427 1428 rect = __vfe_get_crop(line, sd_state, sel->which); 1429 if (rect == NULL) 1430 return -EINVAL; 1431 1432 vfe_try_crop(line, sd_state, &sel->r, sel->which); 1433 *rect = sel->r; 1434 1435 /* Reset source pad format width and height */ 1436 fmt.which = sel->which; 1437 fmt.pad = MSM_VFE_PAD_SRC; 1438 ret = vfe_get_format(sd, sd_state, &fmt); 1439 if (ret < 0) 1440 return ret; 1441 1442 fmt.format.width = rect->width; 1443 fmt.format.height = rect->height; 1444 ret = vfe_set_format(sd, sd_state, &fmt); 1445 } else { 1446 ret = -EINVAL; 1447 } 1448 1449 return ret; 1450 } 1451 1452 /* 1453 * vfe_init_formats - Initialize formats on all pads 1454 * @sd: VFE V4L2 subdevice 1455 * @fh: V4L2 subdev file handle 1456 * 1457 * Initialize all pad formats with default values. 1458 * 1459 * Return 0 on success or a negative error code otherwise 1460 */ 1461 static int vfe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1462 { 1463 struct v4l2_subdev_format format = { 1464 .pad = MSM_VFE_PAD_SINK, 1465 .which = fh ? V4L2_SUBDEV_FORMAT_TRY : 1466 V4L2_SUBDEV_FORMAT_ACTIVE, 1467 .format = { 1468 .code = MEDIA_BUS_FMT_UYVY8_1X16, 1469 .width = 1920, 1470 .height = 1080 1471 } 1472 }; 1473 1474 return vfe_set_format(sd, fh ? fh->state : NULL, &format); 1475 } 1476 1477 /* 1478 * msm_vfe_subdev_init - Initialize VFE device structure and resources 1479 * @vfe: VFE device 1480 * @res: VFE module resources table 1481 * 1482 * Return 0 on success or a negative error code otherwise 1483 */ 1484 int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, 1485 const struct camss_subdev_resources *res, u8 id) 1486 { 1487 struct device *dev = camss->dev; 1488 struct platform_device *pdev = to_platform_device(dev); 1489 int i, j; 1490 int ret; 1491 1492 if (!res->vfe.line_num) 1493 return -EINVAL; 1494 1495 vfe->res = &res->vfe; 1496 vfe->res->hw_ops->subdev_init(dev, vfe); 1497 1498 /* Power domain */ 1499 1500 if (res->vfe.pd_name) { 1501 vfe->genpd = dev_pm_domain_attach_by_name(camss->dev, 1502 res->vfe.pd_name); 1503 if (IS_ERR(vfe->genpd)) { 1504 ret = PTR_ERR(vfe->genpd); 1505 return ret; 1506 } 1507 } 1508 1509 if (!vfe->genpd && res->vfe.has_pd) { 1510 /* 1511 * Legacy magic index. 1512 * Requires 1513 * power-domain = <VFE_X>, 1514 * <VFE_Y>, 1515 * <TITAN_TOP> 1516 * id must correspondng to the index of the VFE which must 1517 * come before the TOP GDSC. VFE Lite has no individually 1518 * collapasible domain which is why id < vfe_num is a valid 1519 * check. 1520 */ 1521 vfe->genpd = dev_pm_domain_attach_by_id(camss->dev, id); 1522 if (IS_ERR(vfe->genpd)) 1523 return PTR_ERR(vfe->genpd); 1524 } 1525 1526 /* Memory */ 1527 1528 vfe->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); 1529 if (IS_ERR(vfe->base)) { 1530 dev_err(dev, "could not map memory\n"); 1531 return PTR_ERR(vfe->base); 1532 } 1533 1534 /* Interrupt */ 1535 1536 ret = platform_get_irq_byname(pdev, res->interrupt[0]); 1537 if (ret < 0) 1538 return ret; 1539 1540 vfe->irq = ret; 1541 snprintf(vfe->irq_name, sizeof(vfe->irq_name), "%s_%s%d", 1542 dev_name(dev), MSM_VFE_NAME, id); 1543 ret = devm_request_irq(dev, vfe->irq, vfe->res->hw_ops->isr, 1544 IRQF_TRIGGER_RISING, vfe->irq_name, vfe); 1545 if (ret < 0) { 1546 dev_err(dev, "request_irq failed: %d\n", ret); 1547 return ret; 1548 } 1549 1550 /* Clocks */ 1551 1552 vfe->nclocks = 0; 1553 while (res->clock[vfe->nclocks]) 1554 vfe->nclocks++; 1555 1556 vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock), 1557 GFP_KERNEL); 1558 if (!vfe->clock) 1559 return -ENOMEM; 1560 1561 for (i = 0; i < vfe->nclocks; i++) { 1562 struct camss_clock *clock = &vfe->clock[i]; 1563 1564 clock->clk = devm_clk_get(dev, res->clock[i]); 1565 if (IS_ERR(clock->clk)) 1566 return PTR_ERR(clock->clk); 1567 1568 clock->name = res->clock[i]; 1569 1570 clock->nfreqs = 0; 1571 while (res->clock_rate[i][clock->nfreqs]) 1572 clock->nfreqs++; 1573 1574 if (!clock->nfreqs) { 1575 clock->freq = NULL; 1576 continue; 1577 } 1578 1579 clock->freq = devm_kcalloc(dev, 1580 clock->nfreqs, 1581 sizeof(*clock->freq), 1582 GFP_KERNEL); 1583 if (!clock->freq) 1584 return -ENOMEM; 1585 1586 for (j = 0; j < clock->nfreqs; j++) 1587 clock->freq[j] = res->clock_rate[i][j]; 1588 } 1589 1590 mutex_init(&vfe->power_lock); 1591 vfe->power_count = 0; 1592 1593 mutex_init(&vfe->stream_lock); 1594 vfe->stream_count = 0; 1595 1596 spin_lock_init(&vfe->output_lock); 1597 1598 vfe->camss = camss; 1599 vfe->id = id; 1600 vfe->reg_update = 0; 1601 1602 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) { 1603 struct vfe_line *l = &vfe->line[i]; 1604 1605 l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1606 l->video_out.camss = camss; 1607 l->id = i; 1608 init_completion(&l->output.sof); 1609 init_completion(&l->output.reg_update); 1610 1611 if (i == VFE_LINE_PIX) { 1612 l->nformats = res->vfe.formats_pix->nformats; 1613 l->formats = res->vfe.formats_pix->formats; 1614 } else { 1615 l->nformats = res->vfe.formats_rdi->nformats; 1616 l->formats = res->vfe.formats_rdi->formats; 1617 } 1618 } 1619 1620 init_completion(&vfe->reset_complete); 1621 init_completion(&vfe->halt_complete); 1622 1623 return 0; 1624 } 1625 1626 /* 1627 * msm_vfe_genpd_cleanup - Cleanup VFE genpd linkages 1628 * @vfe: VFE device 1629 */ 1630 void msm_vfe_genpd_cleanup(struct vfe_device *vfe) 1631 { 1632 if (vfe->genpd_link) 1633 device_link_del(vfe->genpd_link); 1634 1635 if (vfe->genpd) 1636 dev_pm_domain_detach(vfe->genpd, true); 1637 } 1638 1639 /* 1640 * vfe_link_setup - Setup VFE connections 1641 * @entity: Pointer to media entity structure 1642 * @local: Pointer to local pad 1643 * @remote: Pointer to remote pad 1644 * @flags: Link flags 1645 * 1646 * Return 0 on success 1647 */ 1648 static int vfe_link_setup(struct media_entity *entity, 1649 const struct media_pad *local, 1650 const struct media_pad *remote, u32 flags) 1651 { 1652 if (flags & MEDIA_LNK_FL_ENABLED) 1653 if (media_pad_remote_pad_first(local)) 1654 return -EBUSY; 1655 1656 return 0; 1657 } 1658 1659 static const struct v4l2_subdev_core_ops vfe_core_ops = { 1660 .s_power = vfe_set_power, 1661 }; 1662 1663 static const struct v4l2_subdev_video_ops vfe_video_ops = { 1664 .s_stream = vfe_set_stream, 1665 }; 1666 1667 static const struct v4l2_subdev_pad_ops vfe_pad_ops = { 1668 .enum_mbus_code = vfe_enum_mbus_code, 1669 .enum_frame_size = vfe_enum_frame_size, 1670 .get_fmt = vfe_get_format, 1671 .set_fmt = vfe_set_format, 1672 .get_selection = vfe_get_selection, 1673 .set_selection = vfe_set_selection, 1674 }; 1675 1676 static const struct v4l2_subdev_ops vfe_v4l2_ops = { 1677 .core = &vfe_core_ops, 1678 .video = &vfe_video_ops, 1679 .pad = &vfe_pad_ops, 1680 }; 1681 1682 static const struct v4l2_subdev_internal_ops vfe_v4l2_internal_ops = { 1683 .open = vfe_init_formats, 1684 }; 1685 1686 static const struct media_entity_operations vfe_media_ops = { 1687 .link_setup = vfe_link_setup, 1688 .link_validate = v4l2_subdev_link_validate, 1689 }; 1690 1691 static int vfe_bpl_align(struct vfe_device *vfe) 1692 { 1693 int ret = 8; 1694 1695 switch (vfe->camss->res->version) { 1696 case CAMSS_845: 1697 case CAMSS_8250: 1698 case CAMSS_8280XP: 1699 ret = 16; 1700 break; 1701 default: 1702 break; 1703 } 1704 1705 return ret; 1706 } 1707 1708 /* 1709 * msm_vfe_register_entities - Register subdev node for VFE module 1710 * @vfe: VFE device 1711 * @v4l2_dev: V4L2 device 1712 * 1713 * Initialize and register a subdev node for the VFE module. Then 1714 * call msm_video_register() to register the video device node which 1715 * will be connected to this subdev node. Then actually create the 1716 * media link between them. 1717 * 1718 * Return 0 on success or a negative error code otherwise 1719 */ 1720 int msm_vfe_register_entities(struct vfe_device *vfe, 1721 struct v4l2_device *v4l2_dev) 1722 { 1723 struct device *dev = vfe->camss->dev; 1724 struct v4l2_subdev *sd; 1725 struct media_pad *pads; 1726 struct camss_video *video_out; 1727 int ret; 1728 int i; 1729 1730 for (i = 0; i < vfe->res->line_num; i++) { 1731 char name[32]; 1732 1733 sd = &vfe->line[i].subdev; 1734 pads = vfe->line[i].pads; 1735 video_out = &vfe->line[i].video_out; 1736 1737 v4l2_subdev_init(sd, &vfe_v4l2_ops); 1738 sd->internal_ops = &vfe_v4l2_internal_ops; 1739 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1740 if (i == VFE_LINE_PIX) 1741 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s", 1742 MSM_VFE_NAME, vfe->id, "pix"); 1743 else 1744 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s%d", 1745 MSM_VFE_NAME, vfe->id, "rdi", i); 1746 1747 v4l2_set_subdevdata(sd, &vfe->line[i]); 1748 1749 ret = vfe_init_formats(sd, NULL); 1750 if (ret < 0) { 1751 dev_err(dev, "Failed to init format: %d\n", ret); 1752 goto error_init; 1753 } 1754 1755 pads[MSM_VFE_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 1756 pads[MSM_VFE_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE; 1757 1758 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; 1759 sd->entity.ops = &vfe_media_ops; 1760 ret = media_entity_pads_init(&sd->entity, MSM_VFE_PADS_NUM, 1761 pads); 1762 if (ret < 0) { 1763 dev_err(dev, "Failed to init media entity: %d\n", ret); 1764 goto error_init; 1765 } 1766 1767 ret = v4l2_device_register_subdev(v4l2_dev, sd); 1768 if (ret < 0) { 1769 dev_err(dev, "Failed to register subdev: %d\n", ret); 1770 goto error_reg_subdev; 1771 } 1772 1773 video_out->ops = &vfe->video_ops; 1774 video_out->bpl_alignment = vfe_bpl_align(vfe); 1775 video_out->line_based = 0; 1776 if (i == VFE_LINE_PIX) { 1777 video_out->bpl_alignment = 16; 1778 video_out->line_based = 1; 1779 } 1780 1781 video_out->nformats = vfe->line[i].nformats; 1782 video_out->formats = vfe->line[i].formats; 1783 1784 snprintf(name, ARRAY_SIZE(name), "%s%d_%s%d", 1785 MSM_VFE_NAME, vfe->id, "video", i); 1786 ret = msm_video_register(video_out, v4l2_dev, name); 1787 if (ret < 0) { 1788 dev_err(dev, "Failed to register video node: %d\n", 1789 ret); 1790 goto error_reg_video; 1791 } 1792 1793 ret = media_create_pad_link( 1794 &sd->entity, MSM_VFE_PAD_SRC, 1795 &video_out->vdev.entity, 0, 1796 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); 1797 if (ret < 0) { 1798 dev_err(dev, "Failed to link %s->%s entities: %d\n", 1799 sd->entity.name, video_out->vdev.entity.name, 1800 ret); 1801 goto error_link; 1802 } 1803 } 1804 1805 return 0; 1806 1807 error_link: 1808 msm_video_unregister(video_out); 1809 1810 error_reg_video: 1811 v4l2_device_unregister_subdev(sd); 1812 1813 error_reg_subdev: 1814 media_entity_cleanup(&sd->entity); 1815 1816 error_init: 1817 for (i--; i >= 0; i--) { 1818 sd = &vfe->line[i].subdev; 1819 video_out = &vfe->line[i].video_out; 1820 1821 msm_video_unregister(video_out); 1822 v4l2_device_unregister_subdev(sd); 1823 media_entity_cleanup(&sd->entity); 1824 } 1825 1826 return ret; 1827 } 1828 1829 /* 1830 * msm_vfe_unregister_entities - Unregister VFE module subdev node 1831 * @vfe: VFE device 1832 */ 1833 void msm_vfe_unregister_entities(struct vfe_device *vfe) 1834 { 1835 int i; 1836 1837 mutex_destroy(&vfe->power_lock); 1838 mutex_destroy(&vfe->stream_lock); 1839 1840 for (i = 0; i < vfe->res->line_num; i++) { 1841 struct v4l2_subdev *sd = &vfe->line[i].subdev; 1842 struct camss_video *video_out = &vfe->line[i].video_out; 1843 1844 msm_video_unregister(video_out); 1845 v4l2_device_unregister_subdev(sd); 1846 media_entity_cleanup(&sd->entity); 1847 } 1848 } 1849 1850 bool vfe_is_lite(struct vfe_device *vfe) 1851 { 1852 return vfe->camss->res->vfe_res[vfe->id].vfe.is_lite; 1853 } 1854