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