Lines Matching +full:4 +full:- +full:line

1 // SPDX-License-Identifier: GPL-2.0
3 * camss-vfe-480.c
5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v480 (SM8250)
7 * Copyright (C) 2020-2021 Linaro Ltd.
16 #include "camss-vfe.h"
33 #define VFE_IRQ_MASK(n) ((vfe_is_lite(vfe) ? 0x28 : 0x3c) + (n) * 4)
35 #define IRQ_MASK_0_BUS_TOP_IRQ (vfe_is_lite(vfe) ? BIT(4) : BIT(7))
36 #define VFE_IRQ_CLEAR(n) ((vfe_is_lite(vfe) ? 0x34 : 0x48) + (n) * 4)
37 #define VFE_IRQ_STATUS(n) ((vfe_is_lite(vfe) ? 0x40 : 0x54) + (n) * 4)
46 #define VFE_BUS_IRQ_MASK(n) (BUS_REG_BASE + 0x18 + (n) * 4)
55 return vfe_is_lite(vfe) ? BIT(4 + (n)) : BIT(6 + (n)); in bus_irq_mask_0_comp_done()
59 #define VFE_BUS_IRQ_CLEAR(n) (BUS_REG_BASE + 0x20 + (n) * 4)
60 #define VFE_BUS_IRQ_STATUS(n) (BUS_REG_BASE + 0x28 + (n) * 4)
93 #define MAX_VFE_OUTPUT_LINES 4
97 u32 hw_version = readl_relaxed(vfe->base + VFE_HW_VERSION); in vfe_hw_version()
103 dev_dbg(vfe->camss->dev, "VFE HW Version = %u.%u.%u\n", gen, rev, step); in vfe_hw_version()
110 writel_relaxed(IRQ_MASK_0_RESET_ACK, vfe->base + VFE_IRQ_MASK(0)); in vfe_global_reset()
111 writel_relaxed(GLOBAL_RESET_HW_AND_REG, vfe->base + VFE_GLOBAL_RESET_CMD); in vfe_global_reset()
114 static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) in vfe_wm_start() argument
117 &line->video_out.active_fmt.fmt.pix_mp; in vfe_wm_start()
122 writel_relaxed(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); in vfe_wm_start()
124 writel_relaxed(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); in vfe_wm_start()
126 writel_relaxed(pix->plane_fmt[0].bytesperline * pix->height, in vfe_wm_start()
127 vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); in vfe_wm_start()
128 writel_relaxed(0xf, vfe->base + VFE_BUS_WM_BURST_LIMIT(wm)); in vfe_wm_start()
130 vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); in vfe_wm_start()
131 writel_relaxed(pix->plane_fmt[0].bytesperline, in vfe_wm_start()
132 vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); in vfe_wm_start()
133 writel_relaxed(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); in vfe_wm_start()
136 writel_relaxed(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); in vfe_wm_start()
137 writel_relaxed(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); in vfe_wm_start()
138 writel_relaxed(0, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(wm)); in vfe_wm_start()
139 writel_relaxed(1, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(wm)); in vfe_wm_start()
142 vfe->base + VFE_BUS_WM_CFG(wm)); in vfe_wm_start()
148 writel_relaxed(0, vfe->base + VFE_BUS_WM_CFG(wm)); in vfe_wm_stop()
152 struct vfe_line *line) in vfe_wm_update() argument
155 writel_relaxed(addr, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); in vfe_wm_update()
160 vfe->reg_update |= REG_UPDATE_RDI(vfe, line_id); in vfe_reg_update()
161 writel_relaxed(vfe->reg_update, vfe->base + VFE_REG_UPDATE_CMD); in vfe_reg_update()
167 vfe->reg_update &= ~REG_UPDATE_RDI(vfe, line_id); in vfe_reg_update_clear()
174 vfe->base + VFE_IRQ_MASK(0)); in vfe_enable_irq_common()
184 if (vfe->line[i].output.state == VFE_OUTPUT_RESERVED || in vfe_enable_lines_irq()
185 vfe->line[i].output.state == VFE_OUTPUT_ON) { in vfe_enable_lines_irq()
191 writel_relaxed(bus_irq_mask, vfe->base + VFE_BUS_IRQ_MASK(0)); in vfe_enable_lines_irq()
198 * vfe_isr - VFE module interrupt handler
199 * @irq: Interrupt line
210 status = readl_relaxed(vfe->base + VFE_IRQ_STATUS(0)); in vfe_isr()
211 writel_relaxed(status, vfe->base + VFE_IRQ_CLEAR(0)); in vfe_isr()
212 writel_relaxed(IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_IRQ_CMD); in vfe_isr()
218 u32 status = readl_relaxed(vfe->base + VFE_BUS_IRQ_STATUS(0)); in vfe_isr()
220 writel_relaxed(status, vfe->base + VFE_BUS_IRQ_CLEAR(0)); in vfe_isr()
221 writel_relaxed(1, vfe->base + VFE_BUS_IRQ_CLEAR_GLOBAL); in vfe_isr()
237 * vfe_halt - Trigger halt on VFE module and wait to complete
248 static int vfe_get_output(struct vfe_line *line) in vfe_get_output() argument
250 struct vfe_device *vfe = to_vfe(line); in vfe_get_output()
254 spin_lock_irqsave(&vfe->output_lock, flags); in vfe_get_output()
256 output = &line->output; in vfe_get_output()
257 if (output->state > VFE_OUTPUT_RESERVED) { in vfe_get_output()
258 dev_err(vfe->camss->dev, "Output is running\n"); in vfe_get_output()
262 output->wm_num = 1; in vfe_get_output()
264 /* Correspondence between VFE line number and WM number. in vfe_get_output()
265 * line 0 -> RDI 0, line 1 -> RDI1, line 2 -> RDI2, line 3 -> PIX/RDI3 in vfe_get_output()
268 output->wm_idx[0] = line->id; in vfe_get_output()
269 vfe->wm_output_map[line->id] = line->id; in vfe_get_output()
271 output->drop_update_idx = 0; in vfe_get_output()
273 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_get_output()
278 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_get_output()
279 output->state = VFE_OUTPUT_OFF; in vfe_get_output()
281 return -EINVAL; in vfe_get_output()
284 static int vfe_enable_output(struct vfe_line *line) in vfe_enable_output() argument
286 struct vfe_device *vfe = to_vfe(line); in vfe_enable_output()
287 struct vfe_output *output = &line->output; in vfe_enable_output()
291 spin_lock_irqsave(&vfe->output_lock, flags); in vfe_enable_output()
293 vfe_reg_update_clear(vfe, line->id); in vfe_enable_output()
295 if (output->state > VFE_OUTPUT_RESERVED) { in vfe_enable_output()
296 dev_err(vfe->camss->dev, "Output is not in reserved state %d\n", in vfe_enable_output()
297 output->state); in vfe_enable_output()
298 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_enable_output()
299 return -EINVAL; in vfe_enable_output()
302 WARN_ON(output->gen2.active_num); in vfe_enable_output()
304 output->state = VFE_OUTPUT_ON; in vfe_enable_output()
306 output->sequence = 0; in vfe_enable_output()
307 output->wait_reg_update = 0; in vfe_enable_output()
308 reinit_completion(&output->reg_update); in vfe_enable_output()
310 vfe_wm_start(vfe, output->wm_idx[0], line); in vfe_enable_output()
313 output->buf[i] = vfe_buf_get_pending(output); in vfe_enable_output()
314 if (!output->buf[i]) in vfe_enable_output()
316 output->gen2.active_num++; in vfe_enable_output()
317 vfe_wm_update(vfe, output->wm_idx[0], output->buf[i]->addr[0], line); in vfe_enable_output()
320 vfe_reg_update(vfe, line->id); in vfe_enable_output()
322 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_enable_output()
328 * vfe_enable - Enable streaming on VFE line
329 * @line: VFE line
333 static int vfe_enable(struct vfe_line *line) in vfe_enable() argument
335 struct vfe_device *vfe = to_vfe(line); in vfe_enable()
338 mutex_lock(&vfe->stream_lock); in vfe_enable()
340 if (!vfe->stream_count) in vfe_enable()
343 vfe->stream_count++; in vfe_enable()
347 mutex_unlock(&vfe->stream_lock); in vfe_enable()
349 ret = vfe_get_output(line); in vfe_enable()
353 ret = vfe_enable_output(line); in vfe_enable()
357 vfe->was_streaming = 1; in vfe_enable()
362 vfe_put_output(line); in vfe_enable()
365 mutex_lock(&vfe->stream_lock); in vfe_enable()
367 vfe->stream_count--; in vfe_enable()
369 mutex_unlock(&vfe->stream_lock); in vfe_enable()
375 * vfe_isr_reg_update - Process reg update interrupt
377 * @line_id: VFE line
384 spin_lock_irqsave(&vfe->output_lock, flags); in vfe_isr_reg_update()
387 output = &vfe->line[line_id].output; in vfe_isr_reg_update()
389 if (output->wait_reg_update) { in vfe_isr_reg_update()
390 output->wait_reg_update = 0; in vfe_isr_reg_update()
391 complete(&output->reg_update); in vfe_isr_reg_update()
394 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_isr_reg_update()
398 * vfe_isr_wm_done - Process write master done interrupt
404 struct vfe_line *line = &vfe->line[vfe->wm_output_map[wm]]; in vfe_isr_wm_done() local
411 spin_lock_irqsave(&vfe->output_lock, flags); in vfe_isr_wm_done()
413 if (vfe->wm_output_map[wm] == VFE_LINE_NONE) { in vfe_isr_wm_done()
414 dev_err_ratelimited(vfe->camss->dev, in vfe_isr_wm_done()
418 output = &vfe->line[vfe->wm_output_map[wm]].output; in vfe_isr_wm_done()
420 ready_buf = output->buf[0]; in vfe_isr_wm_done()
422 dev_err_ratelimited(vfe->camss->dev, in vfe_isr_wm_done()
423 "Missing ready buf %d!\n", output->state); in vfe_isr_wm_done()
427 ready_buf->vb.vb2_buf.timestamp = ts; in vfe_isr_wm_done()
428 ready_buf->vb.sequence = output->sequence++; in vfe_isr_wm_done()
431 output->buf[0] = output->buf[1]; in vfe_isr_wm_done()
432 if (output->buf[0]) in vfe_isr_wm_done()
435 output->buf[index] = vfe_buf_get_pending(output); in vfe_isr_wm_done()
437 if (output->buf[index]) in vfe_isr_wm_done()
438 vfe_wm_update(vfe, output->wm_idx[0], output->buf[index]->addr[0], line); in vfe_isr_wm_done()
440 output->gen2.active_num--; in vfe_isr_wm_done()
442 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_isr_wm_done()
444 vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); in vfe_isr_wm_done()
449 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_isr_wm_done()
453 * vfe_queue_buffer - Add empty buffer
457 * Add an empty buffer - depending on the current number of buffers it will be
465 struct vfe_line *line = container_of(vid, struct vfe_line, video_out); in vfe_queue_buffer() local
466 struct vfe_device *vfe = to_vfe(line); in vfe_queue_buffer()
470 output = &line->output; in vfe_queue_buffer()
472 spin_lock_irqsave(&vfe->output_lock, flags); in vfe_queue_buffer()
474 if (output->state == VFE_OUTPUT_ON && output->gen2.active_num < 2) { in vfe_queue_buffer()
475 output->buf[output->gen2.active_num++] = buf; in vfe_queue_buffer()
476 vfe_wm_update(vfe, output->wm_idx[0], buf->addr[0], line); in vfe_queue_buffer()
481 spin_unlock_irqrestore(&vfe->output_lock, flags); in vfe_queue_buffer()
493 vfe->video_ops = vfe_video_ops_480; in vfe_subdev_init()