FILE
camss-vfe-680.c
File preview with syntax highlighting.
linux-6.19.14/drivers/media/platform/qcom/camss/camss-vfe-680.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * camss-vfe-680.c 4 * 5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v680 6 * 7 * Copyright (C) 2025 Linaro Ltd. 8 */ 9 10#include <linux/delay.h> 11#include <linux/interrupt.h> 12#include <linux/io.h> 13#include <linux/iopoll.h> 14 15#include "camss.h" 16#include "camss-vfe.h" 17 18#define VFE_TOP_IRQn_STATUS(vfe, n) ((vfe_is_lite(vfe) ? 0x1c : 0x44) + (n) * 4) 19#define VFE_TOP_IRQn_MASK(vfe, n) ((vfe_is_lite(vfe) ? 0x24 : 0x34) + (n) * 4) 20#define VFE_TOP_IRQn_CLEAR(vfe, n) ((vfe_is_lite(vfe) ? 0x2c : 0x3c) + (n) * 4) 21#define VFE_IRQ1_SOF(vfe, n) ((vfe_is_lite(vfe) ? BIT(2) : BIT(8)) << ((n) * 2)) 22#define VFE_IRQ1_EOF(vfe, n) ((vfe_is_lite(vfe) ? BIT(3) : BIT(9)) << ((n) * 2)) 23#define VFE_TOP_IRQ_CMD(vfe) (vfe_is_lite(vfe) ? 0x38 : 0x30) 24#define VFE_TOP_IRQ_CMD_GLOBAL_CLEAR BIT(0) 25#define VFE_TOP_DIAG_CONFIG (vfe_is_lite(vfe) ? 0x40 : 0x50) 26 27#define VFE_TOP_DEBUG_11(vfe) (vfe_is_lite(vfe) ? 0x40 : 0xcc) 28#define VFE_TOP_DEBUG_12(vfe) (vfe_is_lite(vfe) ? 0x40 : 0xd0) 29#define VFE_TOP_DEBUG_13(vfe) (vfe_is_lite(vfe) ? 0x40 : 0xd4) 30 31#define VFE_BUS_IRQn_MASK(vfe, n) ((vfe_is_lite(vfe) ? 0x218 : 0xc18) + (n) * 4) 32#define VFE_BUS_IRQn_CLEAR(vfe, n) ((vfe_is_lite(vfe) ? 0x220 : 0xc20) + (n) * 4) 33#define VFE_BUS_IRQn_STATUS(vfe, n) ((vfe_is_lite(vfe) ? 0x228 : 0xc28) + (n) * 4) 34#define VFE_BUS_IRQ_GLOBAL_CLEAR(vfe) (vfe_is_lite(vfe) ? 0x230 : 0xc30) 35#define VFE_BUS_WR_VIOLATION_STATUS(vfe) (vfe_is_lite(vfe) ? 0x264 : 0xc64) 36#define VFE_BUS_WR_OVERFLOW_STATUS(vfe) (vfe_is_lite(vfe) ? 0x268 : 0xc68) 37#define VFE_BUS_WR_IMAGE_VIOLATION_STATUS(vfe) (vfe_is_lite(vfe) ? 0x270 : 0xc70) 38 39#define VFE_BUS_WRITE_CLIENT_CFG(vfe, c) ((vfe_is_lite(vfe) ? 0x400 : 0xe00) + (c) * 0x100) 40#define VFE_BUS_WRITE_CLIENT_CFG_EN BIT(0) 41#define VFE_BUS_IMAGE_ADDR(vfe, c) ((vfe_is_lite(vfe) ? 0x404 : 0xe04) + (c) * 0x100) 42#define VFE_BUS_FRAME_INCR(vfe, c) ((vfe_is_lite(vfe) ? 0x408 : 0xe08) + (c) * 0x100) 43#define VFE_BUS_IMAGE_CFG0(vfe, c) ((vfe_is_lite(vfe) ? 0x40c : 0xe0c) + (c) * 0x100) 44#define VFE_BUS_IMAGE_CFG0_DATA(h, s) (((h) << 16) | ((s) >> 4)) 45#define WM_IMAGE_CFG_0_DEFAULT_WIDTH (0xFFFF) 46 47#define VFE_BUS_IMAGE_CFG1(vfe, c) ((vfe_is_lite(vfe) ? 0x410 : 0xe10) + (c) * 0x100) 48#define VFE_BUS_IMAGE_CFG2(vfe, c) ((vfe_is_lite(vfe) ? 0x414 : 0xe14) + (c) * 0x100) 49#define VFE_BUS_PACKER_CFG(vfe, c) ((vfe_is_lite(vfe) ? 0x418 : 0xe18) + (c) * 0x100) 50#define VFE_BUS_IRQ_SUBSAMPLE_PERIOD(vfe, c) ((vfe_is_lite(vfe) ? 0x430 : 0xe30) + (c) * 0x100) 51#define VFE_BUS_IRQ_SUBSAMPLE_PATTERN(vfe, c) ((vfe_is_lite(vfe) ? 0x434 : 0xe34) + (c) * 0x100) 52#define VFE_BUS_FRAMEDROP_PERIOD(vfe, c) ((vfe_is_lite(vfe) ? 0x438 : 0xe38) + (c) * 0x100) 53#define VFE_BUS_FRAMEDROP_PATTERN(vfe, c) ((vfe_is_lite(vfe) ? 0x43c : 0xe3c) + (c) * 0x100) 54#define VFE_BUS_MMU_PREFETCH_CFG(vfe, c) ((vfe_is_lite(vfe) ? 0x460 : 0xe60) + (c) * 0x100) 55#define VFE_BUS_MMU_PREFETCH_CFG_EN BIT(0) 56#define VFE_BUS_MMU_PREFETCH_MAX_OFFSET(vfe, c) ((vfe_is_lite(vfe) ? 0x464 : 0xe64) + (c) * 0x100) 57#define VFE_BUS_ADDR_STATUS0(vfe, c) ((vfe_is_lite(vfe) ? 0x470 : 0xe70) + (c) * 0x100) 58 59/* 60 * TODO: differentiate the port id based on requested type of RDI, BHIST etc 61 * 62 * IFE write master IDs 63 * 64 * VIDEO_FULL_Y 0 65 * VIDEO_FULL_C 1 66 * VIDEO_DS_4:1 2 67 * VIDEO_DS_16:1 3 68 * DISPLAY_FULL_Y 4 69 * DISPLAY_FULL_C 5 70 * DISPLAY_DS_4:1 6 71 * DISPLAY_DS_16:1 7 72 * FD_Y 8 73 * FD_C 9 74 * PIXEL_RAW 10 75 * STATS_BE0 11 76 * STATS_BHIST0 12 77 * STATS_TINTLESS_BG 13 78 * STATS_AWB_BG 14 79 * STATS_AWB_BFW 15 80 * STATS_BAF 16 81 * STATS_BHIST 17 82 * STATS_RS 18 83 * STATS_IHIST 19 84 * SPARSE_PD 20 85 * PDAF_V2.0_PD_DATA 21 86 * PDAF_V2.0_SAD 22 87 * LCR 23 88 * RDI0 24 89 * RDI1 25 90 * RDI2 26 91 * LTM_STATS 27 92 * 93 * IFE Lite write master IDs 94 * 95 * RDI0 0 96 * RDI1 1 97 * RDI2 2 98 * RDI3 3 99 * GAMMA 4 100 * BE 5 101 */ 102 103/* TODO: assign an ENUM in resources and use the provided master 104 * id directly for RDI, STATS, AWB_BG, BHIST. 105 * This macro only works because RDI is all we support right now. 106 */ 107#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0 : 24) + (n)) 108 109static void vfe_global_reset(struct vfe_device *vfe) 110{ 111 /* VFE680 has no global reset, simply report a completion */ 112 complete(&vfe->reset_complete); 113} 114 115/* 116 * vfe_isr - VFE module interrupt handler 117 * @irq: Interrupt line 118 * @dev: VFE device 119 * 120 * Return IRQ_HANDLED on success 121 */ 122static irqreturn_t vfe_isr(int irq, void *dev) 123{ 124 return IRQ_HANDLED; 125} 126 127/* 128 * vfe_halt - Trigger halt on VFE module and wait to complete 129 * @vfe: VFE device 130 * 131 * Return 0 on success or a negative error code otherwise 132 */ 133static int vfe_halt(struct vfe_device *vfe) 134{ 135 /* rely on vfe_disable_output() to stop the VFE */ 136 return 0; 137} 138 139static void vfe_disable_irq(struct vfe_device *vfe) 140{ 141 writel(0u, vfe->base + VFE_TOP_IRQn_MASK(vfe, 0)); 142 writel(0u, vfe->base + VFE_TOP_IRQn_MASK(vfe, 1)); 143 writel(0u, vfe->base + VFE_BUS_IRQn_MASK(vfe, 0)); 144 writel(0u, vfe->base + VFE_BUS_IRQn_MASK(vfe, 1)); 145} 146 147static void vfe_wm_update(struct vfe_device *vfe, u8 rdi, u32 addr, 148 struct vfe_line *line) 149{ 150 u8 wm = RDI_WM(rdi); 151 152 writel(addr, vfe->base + VFE_BUS_IMAGE_ADDR(vfe, wm)); 153} 154 155static void vfe_wm_start(struct vfe_device *vfe, u8 rdi, struct vfe_line *line) 156{ 157 struct v4l2_pix_format_mplane *pix = 158 &line->video_out.active_fmt.fmt.pix_mp; 159 u32 stride = pix->plane_fmt[0].bytesperline; 160 u32 cfg; 161 u8 wm; 162 163 cfg = VFE_BUS_IMAGE_CFG0_DATA(pix->height, stride); 164 wm = RDI_WM(rdi); 165 166 writel(cfg, vfe->base + VFE_BUS_IMAGE_CFG0(vfe, wm)); 167 writel(0, vfe->base + VFE_BUS_IMAGE_CFG1(vfe, wm)); 168 writel(stride, vfe->base + VFE_BUS_IMAGE_CFG2(vfe, wm)); 169 writel(0, vfe->base + VFE_BUS_PACKER_CFG(vfe, wm)); 170 171 /* Set total frame increment value */ 172 writel(pix->plane_fmt[0].bytesperline * pix->height, 173 vfe->base + VFE_BUS_FRAME_INCR(vfe, wm)); 174 175 /* MMU */ 176 writel(VFE_BUS_MMU_PREFETCH_CFG_EN, vfe->base + VFE_BUS_MMU_PREFETCH_CFG(vfe, wm)); 177 writel(~0u, vfe->base + VFE_BUS_MMU_PREFETCH_MAX_OFFSET(vfe, wm)); 178 179 /* no dropped frames, one irq per frame */ 180 writel(1, vfe->base + VFE_BUS_FRAMEDROP_PATTERN(vfe, wm)); 181 writel(0, vfe->base + VFE_BUS_FRAMEDROP_PERIOD(vfe, wm)); 182 writel(1, vfe->base + VFE_BUS_IRQ_SUBSAMPLE_PATTERN(vfe, wm)); 183 writel(0, vfe->base + VFE_BUS_IRQ_SUBSAMPLE_PERIOD(vfe, wm)); 184 185 /* We don't process IRQs for VFE in RDI mode at the moment */ 186 vfe_disable_irq(vfe); 187 188 /* Enable WM */ 189 writel(VFE_BUS_WRITE_CLIENT_CFG_EN, 190 vfe->base + VFE_BUS_WRITE_CLIENT_CFG(vfe, wm)); 191 192 dev_dbg(vfe->camss->dev, "RDI%d WM:%d width %d height %d stride %d\n", 193 rdi, wm, pix->width, pix->height, stride); 194} 195 196static void vfe_wm_stop(struct vfe_device *vfe, u8 rdi) 197{ 198 u8 wm = RDI_WM(rdi); 199 200 writel(0, vfe->base + VFE_BUS_WRITE_CLIENT_CFG(vfe, wm)); 201} 202 203static const struct camss_video_ops vfe_video_ops_680 = { 204 .queue_buffer = vfe_queue_buffer_v2, 205 .flush_buffers = vfe_flush_buffers, 206}; 207 208static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) 209{ 210 vfe->video_ops = vfe_video_ops_680; 211} 212 213static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) 214{ 215 int port_id = line_id; 216 217 camss_reg_update(vfe->camss, vfe->id, port_id, false); 218} 219 220static inline void vfe_reg_update_clear(struct vfe_device *vfe, 221 enum vfe_line_id line_id) 222{ 223 int port_id = line_id; 224 225 camss_reg_update(vfe->camss, vfe->id, port_id, true); 226} 227 228const struct vfe_hw_ops vfe_ops_680 = { 229 .global_reset = vfe_global_reset, 230 .hw_version = vfe_hw_version, 231 .isr = vfe_isr, 232 .pm_domain_off = vfe_pm_domain_off, 233 .pm_domain_on = vfe_pm_domain_on, 234 .subdev_init = vfe_subdev_init, 235 .vfe_disable = vfe_disable, 236 .vfe_enable = vfe_enable_v2, 237 .vfe_halt = vfe_halt, 238 .vfe_wm_start = vfe_wm_start, 239 .vfe_wm_stop = vfe_wm_stop, 240 .vfe_buf_done = vfe_buf_done, 241 .vfe_wm_update = vfe_wm_update, 242 .reg_update = vfe_reg_update, 243 .reg_update_clear = vfe_reg_update_clear, 244};
~/
Read-only file preview.