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