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