Lines Matching full:vin
3 * Driver for Renesas R-Car VIN
19 #include "rcar-vin.h"
25 /* Register offsets for R-Car VIN */
78 /* Register bit fields for R-Car VIN */
141 static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset) in rvin_write() argument
143 iowrite32(value, vin->base + offset); in rvin_write()
146 static u32 rvin_read(struct rvin_dev *vin, u32 offset) in rvin_read() argument
148 return ioread32(vin->base + offset); in rvin_read()
473 static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs) in rvin_set_coeff() argument
494 rvin_write(vin, p_set->coeff_set[0], VNC1A_REG); in rvin_set_coeff()
495 rvin_write(vin, p_set->coeff_set[1], VNC1B_REG); in rvin_set_coeff()
496 rvin_write(vin, p_set->coeff_set[2], VNC1C_REG); in rvin_set_coeff()
498 rvin_write(vin, p_set->coeff_set[3], VNC2A_REG); in rvin_set_coeff()
499 rvin_write(vin, p_set->coeff_set[4], VNC2B_REG); in rvin_set_coeff()
500 rvin_write(vin, p_set->coeff_set[5], VNC2C_REG); in rvin_set_coeff()
502 rvin_write(vin, p_set->coeff_set[6], VNC3A_REG); in rvin_set_coeff()
503 rvin_write(vin, p_set->coeff_set[7], VNC3B_REG); in rvin_set_coeff()
504 rvin_write(vin, p_set->coeff_set[8], VNC3C_REG); in rvin_set_coeff()
506 rvin_write(vin, p_set->coeff_set[9], VNC4A_REG); in rvin_set_coeff()
507 rvin_write(vin, p_set->coeff_set[10], VNC4B_REG); in rvin_set_coeff()
508 rvin_write(vin, p_set->coeff_set[11], VNC4C_REG); in rvin_set_coeff()
510 rvin_write(vin, p_set->coeff_set[12], VNC5A_REG); in rvin_set_coeff()
511 rvin_write(vin, p_set->coeff_set[13], VNC5B_REG); in rvin_set_coeff()
512 rvin_write(vin, p_set->coeff_set[14], VNC5C_REG); in rvin_set_coeff()
514 rvin_write(vin, p_set->coeff_set[15], VNC6A_REG); in rvin_set_coeff()
515 rvin_write(vin, p_set->coeff_set[16], VNC6B_REG); in rvin_set_coeff()
516 rvin_write(vin, p_set->coeff_set[17], VNC6C_REG); in rvin_set_coeff()
518 rvin_write(vin, p_set->coeff_set[18], VNC7A_REG); in rvin_set_coeff()
519 rvin_write(vin, p_set->coeff_set[19], VNC7B_REG); in rvin_set_coeff()
520 rvin_write(vin, p_set->coeff_set[20], VNC7C_REG); in rvin_set_coeff()
522 rvin_write(vin, p_set->coeff_set[21], VNC8A_REG); in rvin_set_coeff()
523 rvin_write(vin, p_set->coeff_set[22], VNC8B_REG); in rvin_set_coeff()
524 rvin_write(vin, p_set->coeff_set[23], VNC8C_REG); in rvin_set_coeff()
527 static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin) in rvin_crop_scale_comp_gen2() argument
533 if (vin->crop.height != vin->compose.height) in rvin_crop_scale_comp_gen2()
534 ys = (4096 * vin->crop.height) / vin->compose.height; in rvin_crop_scale_comp_gen2()
535 rvin_write(vin, ys, VNYS_REG); in rvin_crop_scale_comp_gen2()
538 if (vin->crop.width != vin->compose.width) in rvin_crop_scale_comp_gen2()
539 xs = (4096 * vin->crop.width) / vin->compose.width; in rvin_crop_scale_comp_gen2()
545 rvin_write(vin, xs, VNXS_REG); in rvin_crop_scale_comp_gen2()
551 rvin_set_coeff(vin, xs); in rvin_crop_scale_comp_gen2()
554 rvin_write(vin, 0, VNSPPOC_REG); in rvin_crop_scale_comp_gen2()
555 rvin_write(vin, 0, VNSLPOC_REG); in rvin_crop_scale_comp_gen2()
556 rvin_write(vin, vin->format.width - 1, VNEPPOC_REG); in rvin_crop_scale_comp_gen2()
557 switch (vin->format.field) { in rvin_crop_scale_comp_gen2()
561 rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG); in rvin_crop_scale_comp_gen2()
564 rvin_write(vin, vin->format.height - 1, VNELPOC_REG); in rvin_crop_scale_comp_gen2()
568 vin_dbg(vin, in rvin_crop_scale_comp_gen2()
570 vin->crop.width, vin->crop.height, vin->crop.left, in rvin_crop_scale_comp_gen2()
571 vin->crop.top, ys, xs, vin->format.width, vin->format.height, in rvin_crop_scale_comp_gen2()
575 void rvin_crop_scale_comp(struct rvin_dev *vin) in rvin_crop_scale_comp() argument
578 rvin_write(vin, vin->crop.left, VNSPPRC_REG); in rvin_crop_scale_comp()
579 rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG); in rvin_crop_scale_comp()
581 switch (vin->format.field) { in rvin_crop_scale_comp()
585 rvin_write(vin, vin->crop.top / 2, VNSLPRC_REG); in rvin_crop_scale_comp()
586 rvin_write(vin, (vin->crop.top + vin->crop.height) / 2 - 1, in rvin_crop_scale_comp()
590 rvin_write(vin, vin->crop.top, VNSLPRC_REG); in rvin_crop_scale_comp()
591 rvin_write(vin, vin->crop.top + vin->crop.height - 1, in rvin_crop_scale_comp()
597 if (vin->info->model != RCAR_GEN3) in rvin_crop_scale_comp()
598 rvin_crop_scale_comp_gen2(vin); in rvin_crop_scale_comp()
600 if (vin->format.pixelformat == V4L2_PIX_FMT_NV16) in rvin_crop_scale_comp()
601 rvin_write(vin, ALIGN(vin->format.width, 0x20), VNIS_REG); in rvin_crop_scale_comp()
603 rvin_write(vin, ALIGN(vin->format.width, 0x10), VNIS_REG); in rvin_crop_scale_comp()
610 static int rvin_setup(struct rvin_dev *vin) in rvin_setup() argument
615 switch (vin->format.field) { in rvin_setup()
626 if (!vin->info->use_mc && vin->std & V4L2_STD_525_60) in rvin_setup()
647 switch (vin->mbus_code) { in rvin_setup()
659 if (!vin->is_csi && in rvin_setup()
660 vin->parallel->mbus_type == V4L2_MBUS_BT656) in rvin_setup()
672 if (!vin->is_csi && in rvin_setup()
673 vin->parallel->mbus_type == V4L2_MBUS_BT656) in rvin_setup()
685 if (vin->info->model == RCAR_GEN3) in rvin_setup()
690 if (!vin->is_csi) { in rvin_setup()
692 if (!(vin->parallel->mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) in rvin_setup()
696 if (!(vin->parallel->mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) in rvin_setup()
700 if (vin->parallel->mbus_flags & V4L2_MBUS_DATA_ENABLE_LOW) in rvin_setup()
707 switch (vin->format.pixelformat) { in rvin_setup()
709 rvin_write(vin, in rvin_setup()
710 ALIGN(vin->format.width * vin->format.height, 0x80), in rvin_setup()
734 vin_err(vin, "Invalid pixelformat (0x%x)\n", in rvin_setup()
735 vin->format.pixelformat); in rvin_setup()
746 if (vin->info->model == RCAR_GEN3) { in rvin_setup()
748 if (vin->is_csi) in rvin_setup()
758 rvin_write(vin, interrupts, VNINTS_REG); in rvin_setup()
760 rvin_write(vin, interrupts, VNIE_REG); in rvin_setup()
762 rvin_write(vin, dmr, VNDMR_REG); in rvin_setup()
763 rvin_write(vin, dmr2, VNDMR2_REG); in rvin_setup()
766 rvin_write(vin, vnmc | VNMC_ME, VNMC_REG); in rvin_setup()
771 static void rvin_disable_interrupts(struct rvin_dev *vin) in rvin_disable_interrupts() argument
773 rvin_write(vin, 0, VNIE_REG); in rvin_disable_interrupts()
776 static u32 rvin_get_interrupt_status(struct rvin_dev *vin) in rvin_get_interrupt_status() argument
778 return rvin_read(vin, VNINTS_REG); in rvin_get_interrupt_status()
781 static void rvin_ack_interrupt(struct rvin_dev *vin) in rvin_ack_interrupt() argument
783 rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG); in rvin_ack_interrupt()
786 static bool rvin_capture_active(struct rvin_dev *vin) in rvin_capture_active() argument
788 return rvin_read(vin, VNMS_REG) & VNMS_CA; in rvin_capture_active()
791 static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr) in rvin_set_slot_addr() argument
797 fmt = rvin_format_from_pixel(vin->format.pixelformat); in rvin_set_slot_addr()
803 offsetx = vin->compose.left * fmt->bpp; in rvin_set_slot_addr()
804 offsety = vin->compose.top * vin->format.bytesperline; in rvin_set_slot_addr()
814 rvin_write(vin, offset, VNMB_REG(slot)); in rvin_set_slot_addr()
823 static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot) in rvin_fill_hw_slot() argument
830 if (WARN_ON(vin->queue_buf[slot] != NULL)) in rvin_fill_hw_slot()
833 vin_dbg(vin, "Filling HW slot: %d\n", slot); in rvin_fill_hw_slot()
835 if (list_empty(&vin->buf_list)) { in rvin_fill_hw_slot()
836 vin->queue_buf[slot] = NULL; in rvin_fill_hw_slot()
837 phys_addr = vin->scratch_phys; in rvin_fill_hw_slot()
840 buf = list_entry(vin->buf_list.next, struct rvin_buffer, list); in rvin_fill_hw_slot()
843 vin->queue_buf[slot] = vbuf; in rvin_fill_hw_slot()
849 rvin_set_slot_addr(vin, slot, phys_addr); in rvin_fill_hw_slot()
852 static int rvin_capture_start(struct rvin_dev *vin) in rvin_capture_start() argument
857 rvin_fill_hw_slot(vin, slot); in rvin_capture_start()
859 rvin_crop_scale_comp(vin); in rvin_capture_start()
861 ret = rvin_setup(vin); in rvin_capture_start()
865 vin_dbg(vin, "Starting to capture\n"); in rvin_capture_start()
868 rvin_write(vin, VNFC_C_FRAME, VNFC_REG); in rvin_capture_start()
870 vin->state = STARTING; in rvin_capture_start()
875 static void rvin_capture_stop(struct rvin_dev *vin) in rvin_capture_stop() argument
878 rvin_write(vin, 0, VNFC_REG); in rvin_capture_stop()
881 rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG); in rvin_capture_stop()
893 struct rvin_dev *vin = data; in rvin_irq() local
899 spin_lock_irqsave(&vin->qlock, flags); in rvin_irq()
901 int_status = rvin_get_interrupt_status(vin); in rvin_irq()
905 rvin_ack_interrupt(vin); in rvin_irq()
909 if (vin->state == STOPPED) { in rvin_irq()
910 vin_dbg(vin, "IRQ while state stopped\n"); in rvin_irq()
915 if (vin->state == STOPPING) { in rvin_irq()
916 vin_dbg(vin, "IRQ while state stopping\n"); in rvin_irq()
921 vnms = rvin_read(vin, VNMS_REG); in rvin_irq()
928 if (vin->state == STARTING) { in rvin_irq()
930 vin_dbg(vin, "Starting sync slot: %d\n", slot); in rvin_irq()
934 vin_dbg(vin, "Capture start synced!\n"); in rvin_irq()
935 vin->state = RUNNING; in rvin_irq()
939 if (vin->queue_buf[slot]) { in rvin_irq()
940 vin->queue_buf[slot]->field = vin->format.field; in rvin_irq()
941 vin->queue_buf[slot]->sequence = vin->sequence; in rvin_irq()
942 vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns(); in rvin_irq()
943 vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf, in rvin_irq()
945 vin->queue_buf[slot] = NULL; in rvin_irq()
948 vin_dbg(vin, "Dropping frame %u\n", vin->sequence); in rvin_irq()
951 vin->sequence++; in rvin_irq()
954 rvin_fill_hw_slot(vin, slot); in rvin_irq()
956 spin_unlock_irqrestore(&vin->qlock, flags); in rvin_irq()
962 static void return_all_buffers(struct rvin_dev *vin, in return_all_buffers() argument
969 if (vin->queue_buf[i]) { in return_all_buffers()
970 vb2_buffer_done(&vin->queue_buf[i]->vb2_buf, in return_all_buffers()
972 vin->queue_buf[i] = NULL; in return_all_buffers()
976 list_for_each_entry_safe(buf, node, &vin->buf_list, list) { in return_all_buffers()
987 struct rvin_dev *vin = vb2_get_drv_priv(vq); in rvin_queue_setup() local
991 return sizes[0] < vin->format.sizeimage ? -EINVAL : 0; in rvin_queue_setup()
994 sizes[0] = vin->format.sizeimage; in rvin_queue_setup()
1001 struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue); in rvin_buffer_prepare() local
1002 unsigned long size = vin->format.sizeimage; in rvin_buffer_prepare()
1005 vin_err(vin, "buffer too small (%lu < %lu)\n", in rvin_buffer_prepare()
1018 struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue); in rvin_buffer_queue() local
1021 spin_lock_irqsave(&vin->qlock, flags); in rvin_buffer_queue()
1023 list_add_tail(to_buf_list(vbuf), &vin->buf_list); in rvin_buffer_queue()
1025 spin_unlock_irqrestore(&vin->qlock, flags); in rvin_buffer_queue()
1028 static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd, in rvin_mc_validate_format() argument
1045 vin->mbus_code = fmt.format.code; in rvin_mc_validate_format()
1063 switch (vin->format.field) { in rvin_mc_validate_format()
1073 /* Use VIN hardware to combine the two fields */ in rvin_mc_validate_format()
1084 if (fmt.format.width != vin->format.width || in rvin_mc_validate_format()
1085 fmt.format.height != vin->format.height || in rvin_mc_validate_format()
1086 fmt.format.code != vin->mbus_code) in rvin_mc_validate_format()
1092 static int rvin_set_stream(struct rvin_dev *vin, int on) in rvin_set_stream() argument
1101 if (!vin->info->use_mc) { in rvin_set_stream()
1102 ret = v4l2_subdev_call(vin->parallel->subdev, video, s_stream, in rvin_set_stream()
1108 pad = media_entity_remote_pad(&vin->pad); in rvin_set_stream()
1115 media_pipeline_stop(&vin->vdev.entity); in rvin_set_stream()
1119 ret = rvin_mc_validate_format(vin, sd, pad); in rvin_set_stream()
1125 * starts of multiple VIN instances as they might share in rvin_set_stream()
1129 mdev = vin->vdev.entity.graph_obj.mdev; in rvin_set_stream()
1131 pipe = sd->entity.pipe ? sd->entity.pipe : &vin->vdev.pipe; in rvin_set_stream()
1132 ret = __media_pipeline_start(&vin->vdev.entity, pipe); in rvin_set_stream()
1141 media_pipeline_stop(&vin->vdev.entity); in rvin_set_stream()
1148 struct rvin_dev *vin = vb2_get_drv_priv(vq); in rvin_start_streaming() local
1153 vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage, in rvin_start_streaming()
1154 &vin->scratch_phys, GFP_KERNEL); in rvin_start_streaming()
1155 if (!vin->scratch) { in rvin_start_streaming()
1156 spin_lock_irqsave(&vin->qlock, flags); in rvin_start_streaming()
1157 return_all_buffers(vin, VB2_BUF_STATE_QUEUED); in rvin_start_streaming()
1158 spin_unlock_irqrestore(&vin->qlock, flags); in rvin_start_streaming()
1159 vin_err(vin, "Failed to allocate scratch buffer\n"); in rvin_start_streaming()
1163 ret = rvin_set_stream(vin, 1); in rvin_start_streaming()
1165 spin_lock_irqsave(&vin->qlock, flags); in rvin_start_streaming()
1166 return_all_buffers(vin, VB2_BUF_STATE_QUEUED); in rvin_start_streaming()
1167 spin_unlock_irqrestore(&vin->qlock, flags); in rvin_start_streaming()
1171 spin_lock_irqsave(&vin->qlock, flags); in rvin_start_streaming()
1173 vin->sequence = 0; in rvin_start_streaming()
1175 ret = rvin_capture_start(vin); in rvin_start_streaming()
1177 return_all_buffers(vin, VB2_BUF_STATE_QUEUED); in rvin_start_streaming()
1178 rvin_set_stream(vin, 0); in rvin_start_streaming()
1181 spin_unlock_irqrestore(&vin->qlock, flags); in rvin_start_streaming()
1184 dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch, in rvin_start_streaming()
1185 vin->scratch_phys); in rvin_start_streaming()
1192 struct rvin_dev *vin = vb2_get_drv_priv(vq); in rvin_stop_streaming() local
1196 spin_lock_irqsave(&vin->qlock, flags); in rvin_stop_streaming()
1198 vin->state = STOPPING; in rvin_stop_streaming()
1203 rvin_capture_stop(vin); in rvin_stop_streaming()
1206 if (!rvin_capture_active(vin)) { in rvin_stop_streaming()
1207 vin->state = STOPPED; in rvin_stop_streaming()
1211 spin_unlock_irqrestore(&vin->qlock, flags); in rvin_stop_streaming()
1213 spin_lock_irqsave(&vin->qlock, flags); in rvin_stop_streaming()
1216 if (vin->state != STOPPED) { in rvin_stop_streaming()
1222 vin_err(vin, "Failed stop HW, something is seriously broken\n"); in rvin_stop_streaming()
1223 vin->state = STOPPED; in rvin_stop_streaming()
1227 return_all_buffers(vin, VB2_BUF_STATE_ERROR); in rvin_stop_streaming()
1229 spin_unlock_irqrestore(&vin->qlock, flags); in rvin_stop_streaming()
1231 rvin_set_stream(vin, 0); in rvin_stop_streaming()
1234 rvin_disable_interrupts(vin); in rvin_stop_streaming()
1237 dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch, in rvin_stop_streaming()
1238 vin->scratch_phys); in rvin_stop_streaming()
1251 void rvin_dma_unregister(struct rvin_dev *vin) in rvin_dma_unregister() argument
1253 mutex_destroy(&vin->lock); in rvin_dma_unregister()
1255 v4l2_device_unregister(&vin->v4l2_dev); in rvin_dma_unregister()
1258 int rvin_dma_register(struct rvin_dev *vin, int irq) in rvin_dma_register() argument
1260 struct vb2_queue *q = &vin->queue; in rvin_dma_register()
1264 ret = v4l2_device_register(vin->dev, &vin->v4l2_dev); in rvin_dma_register()
1268 mutex_init(&vin->lock); in rvin_dma_register()
1269 INIT_LIST_HEAD(&vin->buf_list); in rvin_dma_register()
1271 spin_lock_init(&vin->qlock); in rvin_dma_register()
1273 vin->state = STOPPED; in rvin_dma_register()
1276 vin->queue_buf[i] = NULL; in rvin_dma_register()
1281 q->lock = &vin->lock; in rvin_dma_register()
1282 q->drv_priv = vin; in rvin_dma_register()
1288 q->dev = vin->dev; in rvin_dma_register()
1292 vin_err(vin, "failed to initialize VB2 queue\n"); in rvin_dma_register()
1297 ret = devm_request_irq(vin->dev, irq, rvin_irq, IRQF_SHARED, in rvin_dma_register()
1298 KBUILD_MODNAME, vin); in rvin_dma_register()
1300 vin_err(vin, "failed to request irq\n"); in rvin_dma_register()
1306 rvin_dma_unregister(vin); in rvin_dma_register()
1317 * as it's only possible to do so when no VIN in the group is
1320 int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel) in rvin_set_channel_routing() argument
1325 ret = pm_runtime_get_sync(vin->dev); in rvin_set_channel_routing()
1327 pm_runtime_put_noidle(vin->dev); in rvin_set_channel_routing()
1332 vnmc = rvin_read(vin, VNMC_REG); in rvin_set_channel_routing()
1333 rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG); in rvin_set_channel_routing()
1337 rvin_write(vin, ifmd, VNCSI_IFMD_REG); in rvin_set_channel_routing()
1339 vin_dbg(vin, "Set IFMD 0x%x\n", ifmd); in rvin_set_channel_routing()
1342 rvin_write(vin, vnmc, VNMC_REG); in rvin_set_channel_routing()
1344 pm_runtime_put(vin->dev); in rvin_set_channel_routing()