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