162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * camss-vfe-gen1.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Qualcomm MSM Camera Subsystem - VFE Common functionality for Gen 1 versions of hw (4.1, 4.7..) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2020 Linaro Ltd. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "camss.h" 1162306a36Sopenharmony_ci#include "camss-vfe.h" 1262306a36Sopenharmony_ci#include "camss-vfe-gen1.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* Max number of frame drop updates per frame */ 1562306a36Sopenharmony_ci#define VFE_FRAME_DROP_UPDATES 2 1662306a36Sopenharmony_ci#define VFE_NEXT_SOF_MS 500 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciint vfe_gen1_halt(struct vfe_device *vfe) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci unsigned long time; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci reinit_completion(&vfe->halt_complete); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci vfe->ops_gen1->halt_request(vfe); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci time = wait_for_completion_timeout(&vfe->halt_complete, 2762306a36Sopenharmony_ci msecs_to_jiffies(VFE_HALT_TIMEOUT_MS)); 2862306a36Sopenharmony_ci if (!time) { 2962306a36Sopenharmony_ci dev_err(vfe->camss->dev, "VFE halt timeout\n"); 3062306a36Sopenharmony_ci return -EIO; 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci return 0; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int vfe_disable_output(struct vfe_line *line) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct vfe_device *vfe = to_vfe(line); 3962306a36Sopenharmony_ci struct vfe_output *output = &line->output; 4062306a36Sopenharmony_ci const struct vfe_hw_ops *ops = vfe->ops; 4162306a36Sopenharmony_ci unsigned long flags; 4262306a36Sopenharmony_ci unsigned long time; 4362306a36Sopenharmony_ci unsigned int i; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci output->gen1.wait_sof = 1; 4862306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci time = wait_for_completion_timeout(&output->sof, msecs_to_jiffies(VFE_NEXT_SOF_MS)); 5162306a36Sopenharmony_ci if (!time) 5262306a36Sopenharmony_ci dev_err(vfe->camss->dev, "VFE sof timeout\n"); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 5562306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) 5662306a36Sopenharmony_ci vfe->ops_gen1->wm_enable(vfe, output->wm_idx[i], 0); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci ops->reg_update(vfe, line->id); 5962306a36Sopenharmony_ci output->wait_reg_update = 1; 6062306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci time = wait_for_completion_timeout(&output->reg_update, msecs_to_jiffies(VFE_NEXT_SOF_MS)); 6362306a36Sopenharmony_ci if (!time) 6462306a36Sopenharmony_ci dev_err(vfe->camss->dev, "VFE reg update timeout\n"); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (line->id != VFE_LINE_PIX) { 6962306a36Sopenharmony_ci vfe->ops_gen1->wm_frame_based(vfe, output->wm_idx[0], 0); 7062306a36Sopenharmony_ci vfe->ops_gen1->bus_disconnect_wm_from_rdi(vfe, output->wm_idx[0], line->id); 7162306a36Sopenharmony_ci vfe->ops_gen1->enable_irq_wm_line(vfe, output->wm_idx[0], line->id, 0); 7262306a36Sopenharmony_ci vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[0], 0); 7362306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 7462306a36Sopenharmony_ci } else { 7562306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 7662306a36Sopenharmony_ci vfe->ops_gen1->wm_line_based(vfe, output->wm_idx[i], NULL, i, 0); 7762306a36Sopenharmony_ci vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[i], 0); 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci vfe->ops_gen1->enable_irq_pix_line(vfe, 0, line->id, 0); 8162306a36Sopenharmony_ci vfe->ops_gen1->set_module_cfg(vfe, 0); 8262306a36Sopenharmony_ci vfe->ops_gen1->set_realign_cfg(vfe, line, 0); 8362306a36Sopenharmony_ci vfe->ops_gen1->set_xbar_cfg(vfe, output, 0); 8462306a36Sopenharmony_ci vfe->ops_gen1->set_camif_cmd(vfe, 0); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci vfe->ops_gen1->camif_wait_for_stop(vfe, vfe->camss->dev); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/* 9562306a36Sopenharmony_ci * vfe_gen1_disable - Disable streaming on VFE line 9662306a36Sopenharmony_ci * @line: VFE line 9762306a36Sopenharmony_ci * 9862306a36Sopenharmony_ci * Return 0 on success or a negative error code otherwise 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ciint vfe_gen1_disable(struct vfe_line *line) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci struct vfe_device *vfe = to_vfe(line); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci vfe_disable_output(line); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci vfe_put_output(line); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci mutex_lock(&vfe->stream_lock); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (vfe->stream_count == 1) 11162306a36Sopenharmony_ci vfe->ops_gen1->bus_enable_wr_if(vfe, 0); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci vfe->stream_count--; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci mutex_unlock(&vfe->stream_lock); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci return 0; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic void vfe_output_init_addrs(struct vfe_device *vfe, 12162306a36Sopenharmony_ci struct vfe_output *output, u8 sync, 12262306a36Sopenharmony_ci struct vfe_line *line) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci u32 ping_addr; 12562306a36Sopenharmony_ci u32 pong_addr; 12662306a36Sopenharmony_ci unsigned int i; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci output->gen1.active_buf = 0; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 13162306a36Sopenharmony_ci if (output->buf[0]) 13262306a36Sopenharmony_ci ping_addr = output->buf[0]->addr[i]; 13362306a36Sopenharmony_ci else 13462306a36Sopenharmony_ci ping_addr = 0; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (output->buf[1]) 13762306a36Sopenharmony_ci pong_addr = output->buf[1]->addr[i]; 13862306a36Sopenharmony_ci else 13962306a36Sopenharmony_ci pong_addr = ping_addr; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci vfe->ops_gen1->wm_set_ping_addr(vfe, output->wm_idx[i], ping_addr); 14262306a36Sopenharmony_ci vfe->ops_gen1->wm_set_pong_addr(vfe, output->wm_idx[i], pong_addr); 14362306a36Sopenharmony_ci if (sync) 14462306a36Sopenharmony_ci vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]); 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void vfe_output_frame_drop(struct vfe_device *vfe, 14962306a36Sopenharmony_ci struct vfe_output *output, 15062306a36Sopenharmony_ci u32 drop_pattern) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci u8 drop_period; 15362306a36Sopenharmony_ci unsigned int i; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* We need to toggle update period to be valid on next frame */ 15662306a36Sopenharmony_ci output->drop_update_idx++; 15762306a36Sopenharmony_ci output->drop_update_idx %= VFE_FRAME_DROP_UPDATES; 15862306a36Sopenharmony_ci drop_period = VFE_FRAME_DROP_VAL + output->drop_update_idx; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 16162306a36Sopenharmony_ci vfe->ops_gen1->wm_set_framedrop_period(vfe, output->wm_idx[i], drop_period); 16262306a36Sopenharmony_ci vfe->ops_gen1->wm_set_framedrop_pattern(vfe, output->wm_idx[i], drop_pattern); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci vfe->ops->reg_update(vfe, container_of(output, struct vfe_line, output)->id); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic int vfe_enable_output(struct vfe_line *line) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct vfe_device *vfe = to_vfe(line); 17162306a36Sopenharmony_ci struct vfe_output *output = &line->output; 17262306a36Sopenharmony_ci const struct vfe_hw_ops *ops = vfe->ops; 17362306a36Sopenharmony_ci struct media_entity *sensor; 17462306a36Sopenharmony_ci unsigned long flags; 17562306a36Sopenharmony_ci unsigned int frame_skip = 0; 17662306a36Sopenharmony_ci unsigned int i; 17762306a36Sopenharmony_ci u16 ub_size; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci ub_size = vfe->ops_gen1->get_ub_size(vfe->id); 18062306a36Sopenharmony_ci if (!ub_size) 18162306a36Sopenharmony_ci return -EINVAL; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci sensor = camss_find_sensor(&line->subdev.entity); 18462306a36Sopenharmony_ci if (sensor) { 18562306a36Sopenharmony_ci struct v4l2_subdev *subdev = media_entity_to_v4l2_subdev(sensor); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci v4l2_subdev_call(subdev, sensor, g_skip_frames, &frame_skip); 18862306a36Sopenharmony_ci /* Max frame skip is 29 frames */ 18962306a36Sopenharmony_ci if (frame_skip > VFE_FRAME_DROP_VAL - 1) 19062306a36Sopenharmony_ci frame_skip = VFE_FRAME_DROP_VAL - 1; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci ops->reg_update_clear(vfe, line->id); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (output->state > VFE_OUTPUT_RESERVED) { 19862306a36Sopenharmony_ci dev_err(vfe->camss->dev, "Output is not in reserved state %d\n", output->state); 19962306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 20062306a36Sopenharmony_ci return -EINVAL; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci output->state = VFE_OUTPUT_IDLE; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci output->buf[0] = vfe_buf_get_pending(output); 20562306a36Sopenharmony_ci output->buf[1] = vfe_buf_get_pending(output); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci if (!output->buf[0] && output->buf[1]) { 20862306a36Sopenharmony_ci output->buf[0] = output->buf[1]; 20962306a36Sopenharmony_ci output->buf[1] = NULL; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (output->buf[0]) 21362306a36Sopenharmony_ci output->state = VFE_OUTPUT_SINGLE; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci if (output->buf[1]) 21662306a36Sopenharmony_ci output->state = VFE_OUTPUT_CONTINUOUS; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci switch (output->state) { 21962306a36Sopenharmony_ci case VFE_OUTPUT_SINGLE: 22062306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 1 << frame_skip); 22162306a36Sopenharmony_ci break; 22262306a36Sopenharmony_ci case VFE_OUTPUT_CONTINUOUS: 22362306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 3 << frame_skip); 22462306a36Sopenharmony_ci break; 22562306a36Sopenharmony_ci default: 22662306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 0); 22762306a36Sopenharmony_ci break; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci output->sequence = 0; 23162306a36Sopenharmony_ci output->gen1.wait_sof = 0; 23262306a36Sopenharmony_ci output->wait_reg_update = 0; 23362306a36Sopenharmony_ci reinit_completion(&output->sof); 23462306a36Sopenharmony_ci reinit_completion(&output->reg_update); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci vfe_output_init_addrs(vfe, output, 0, line); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (line->id != VFE_LINE_PIX) { 23962306a36Sopenharmony_ci vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[0], 1); 24062306a36Sopenharmony_ci vfe->ops_gen1->enable_irq_wm_line(vfe, output->wm_idx[0], line->id, 1); 24162306a36Sopenharmony_ci vfe->ops_gen1->bus_connect_wm_to_rdi(vfe, output->wm_idx[0], line->id); 24262306a36Sopenharmony_ci vfe->ops_gen1->wm_set_subsample(vfe, output->wm_idx[0]); 24362306a36Sopenharmony_ci vfe->ops_gen1->set_rdi_cid(vfe, line->id, 0); 24462306a36Sopenharmony_ci vfe->ops_gen1->wm_set_ub_cfg(vfe, output->wm_idx[0], 24562306a36Sopenharmony_ci (ub_size + 1) * output->wm_idx[0], ub_size); 24662306a36Sopenharmony_ci vfe->ops_gen1->wm_frame_based(vfe, output->wm_idx[0], 1); 24762306a36Sopenharmony_ci vfe->ops_gen1->wm_enable(vfe, output->wm_idx[0], 1); 24862306a36Sopenharmony_ci vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[0]); 24962306a36Sopenharmony_ci } else { 25062306a36Sopenharmony_ci ub_size /= output->wm_num; 25162306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 25262306a36Sopenharmony_ci vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[i], 1); 25362306a36Sopenharmony_ci vfe->ops_gen1->wm_set_subsample(vfe, output->wm_idx[i]); 25462306a36Sopenharmony_ci vfe->ops_gen1->wm_set_ub_cfg(vfe, output->wm_idx[i], 25562306a36Sopenharmony_ci (ub_size + 1) * output->wm_idx[i], ub_size); 25662306a36Sopenharmony_ci vfe->ops_gen1->wm_line_based(vfe, output->wm_idx[i], 25762306a36Sopenharmony_ci &line->video_out.active_fmt.fmt.pix_mp, i, 1); 25862306a36Sopenharmony_ci vfe->ops_gen1->wm_enable(vfe, output->wm_idx[i], 1); 25962306a36Sopenharmony_ci vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]); 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci vfe->ops_gen1->enable_irq_pix_line(vfe, 0, line->id, 1); 26262306a36Sopenharmony_ci vfe->ops_gen1->set_module_cfg(vfe, 1); 26362306a36Sopenharmony_ci vfe->ops_gen1->set_camif_cfg(vfe, line); 26462306a36Sopenharmony_ci vfe->ops_gen1->set_realign_cfg(vfe, line, 1); 26562306a36Sopenharmony_ci vfe->ops_gen1->set_xbar_cfg(vfe, output, 1); 26662306a36Sopenharmony_ci vfe->ops_gen1->set_demux_cfg(vfe, line); 26762306a36Sopenharmony_ci vfe->ops_gen1->set_scale_cfg(vfe, line); 26862306a36Sopenharmony_ci vfe->ops_gen1->set_crop_cfg(vfe, line); 26962306a36Sopenharmony_ci vfe->ops_gen1->set_clamp_cfg(vfe); 27062306a36Sopenharmony_ci vfe->ops_gen1->set_camif_cmd(vfe, 1); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci ops->reg_update(vfe, line->id); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic int vfe_get_output(struct vfe_line *line) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci struct vfe_device *vfe = to_vfe(line); 28362306a36Sopenharmony_ci struct vfe_output *output; 28462306a36Sopenharmony_ci struct v4l2_format *f = &line->video_out.active_fmt; 28562306a36Sopenharmony_ci unsigned long flags; 28662306a36Sopenharmony_ci int i; 28762306a36Sopenharmony_ci int wm_idx; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci output = &line->output; 29262306a36Sopenharmony_ci if (output->state > VFE_OUTPUT_RESERVED) { 29362306a36Sopenharmony_ci dev_err(vfe->camss->dev, "Output is running\n"); 29462306a36Sopenharmony_ci goto error; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci output->state = VFE_OUTPUT_RESERVED; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci output->gen1.active_buf = 0; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci switch (f->fmt.pix_mp.pixelformat) { 30162306a36Sopenharmony_ci case V4L2_PIX_FMT_NV12: 30262306a36Sopenharmony_ci case V4L2_PIX_FMT_NV21: 30362306a36Sopenharmony_ci case V4L2_PIX_FMT_NV16: 30462306a36Sopenharmony_ci case V4L2_PIX_FMT_NV61: 30562306a36Sopenharmony_ci output->wm_num = 2; 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci default: 30862306a36Sopenharmony_ci output->wm_num = 1; 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 31362306a36Sopenharmony_ci wm_idx = vfe_reserve_wm(vfe, line->id); 31462306a36Sopenharmony_ci if (wm_idx < 0) { 31562306a36Sopenharmony_ci dev_err(vfe->camss->dev, "Can not reserve wm\n"); 31662306a36Sopenharmony_ci goto error_get_wm; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci output->wm_idx[i] = wm_idx; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci output->drop_update_idx = 0; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci return 0; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cierror_get_wm: 32862306a36Sopenharmony_ci for (i--; i >= 0; i--) 32962306a36Sopenharmony_ci vfe_release_wm(vfe, output->wm_idx[i]); 33062306a36Sopenharmony_ci output->state = VFE_OUTPUT_OFF; 33162306a36Sopenharmony_cierror: 33262306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return -EINVAL; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ciint vfe_gen1_enable(struct vfe_line *line) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci struct vfe_device *vfe = to_vfe(line); 34062306a36Sopenharmony_ci int ret; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci mutex_lock(&vfe->stream_lock); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (!vfe->stream_count) { 34562306a36Sopenharmony_ci vfe->ops_gen1->enable_irq_common(vfe); 34662306a36Sopenharmony_ci vfe->ops_gen1->bus_enable_wr_if(vfe, 1); 34762306a36Sopenharmony_ci vfe->ops_gen1->set_qos(vfe); 34862306a36Sopenharmony_ci vfe->ops_gen1->set_ds(vfe); 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci vfe->stream_count++; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci mutex_unlock(&vfe->stream_lock); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci ret = vfe_get_output(line); 35662306a36Sopenharmony_ci if (ret < 0) 35762306a36Sopenharmony_ci goto error_get_output; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci ret = vfe_enable_output(line); 36062306a36Sopenharmony_ci if (ret < 0) 36162306a36Sopenharmony_ci goto error_enable_output; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci vfe->was_streaming = 1; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci return 0; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cierror_enable_output: 36862306a36Sopenharmony_ci vfe_put_output(line); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cierror_get_output: 37162306a36Sopenharmony_ci mutex_lock(&vfe->stream_lock); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (vfe->stream_count == 1) 37462306a36Sopenharmony_ci vfe->ops_gen1->bus_enable_wr_if(vfe, 0); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci vfe->stream_count--; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci mutex_unlock(&vfe->stream_lock); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci return ret; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic void vfe_output_update_ping_addr(struct vfe_device *vfe, 38462306a36Sopenharmony_ci struct vfe_output *output, u8 sync, 38562306a36Sopenharmony_ci struct vfe_line *line) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci u32 addr; 38862306a36Sopenharmony_ci unsigned int i; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 39162306a36Sopenharmony_ci if (output->buf[0]) 39262306a36Sopenharmony_ci addr = output->buf[0]->addr[i]; 39362306a36Sopenharmony_ci else 39462306a36Sopenharmony_ci addr = 0; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci vfe->ops_gen1->wm_set_ping_addr(vfe, output->wm_idx[i], addr); 39762306a36Sopenharmony_ci if (sync) 39862306a36Sopenharmony_ci vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]); 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic void vfe_output_update_pong_addr(struct vfe_device *vfe, 40362306a36Sopenharmony_ci struct vfe_output *output, u8 sync, 40462306a36Sopenharmony_ci struct vfe_line *line) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci u32 addr; 40762306a36Sopenharmony_ci unsigned int i; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 41062306a36Sopenharmony_ci if (output->buf[1]) 41162306a36Sopenharmony_ci addr = output->buf[1]->addr[i]; 41262306a36Sopenharmony_ci else 41362306a36Sopenharmony_ci addr = 0; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci vfe->ops_gen1->wm_set_pong_addr(vfe, output->wm_idx[i], addr); 41662306a36Sopenharmony_ci if (sync) 41762306a36Sopenharmony_ci vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]); 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic void vfe_buf_update_wm_on_next(struct vfe_device *vfe, 42262306a36Sopenharmony_ci struct vfe_output *output) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci switch (output->state) { 42562306a36Sopenharmony_ci case VFE_OUTPUT_CONTINUOUS: 42662306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 3); 42762306a36Sopenharmony_ci break; 42862306a36Sopenharmony_ci case VFE_OUTPUT_SINGLE: 42962306a36Sopenharmony_ci default: 43062306a36Sopenharmony_ci dev_err_ratelimited(vfe->camss->dev, 43162306a36Sopenharmony_ci "Next buf in wrong state! %d\n", 43262306a36Sopenharmony_ci output->state); 43362306a36Sopenharmony_ci break; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic void vfe_buf_update_wm_on_last(struct vfe_device *vfe, 43862306a36Sopenharmony_ci struct vfe_output *output) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci switch (output->state) { 44162306a36Sopenharmony_ci case VFE_OUTPUT_CONTINUOUS: 44262306a36Sopenharmony_ci output->state = VFE_OUTPUT_SINGLE; 44362306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 1); 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci case VFE_OUTPUT_SINGLE: 44662306a36Sopenharmony_ci output->state = VFE_OUTPUT_STOPPING; 44762306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 0); 44862306a36Sopenharmony_ci break; 44962306a36Sopenharmony_ci default: 45062306a36Sopenharmony_ci dev_err_ratelimited(vfe->camss->dev, 45162306a36Sopenharmony_ci "Last buff in wrong state! %d\n", 45262306a36Sopenharmony_ci output->state); 45362306a36Sopenharmony_ci break; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic void vfe_buf_update_wm_on_new(struct vfe_device *vfe, 45862306a36Sopenharmony_ci struct vfe_output *output, 45962306a36Sopenharmony_ci struct camss_buffer *new_buf, 46062306a36Sopenharmony_ci struct vfe_line *line) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci int inactive_idx; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci switch (output->state) { 46562306a36Sopenharmony_ci case VFE_OUTPUT_SINGLE: 46662306a36Sopenharmony_ci inactive_idx = !output->gen1.active_buf; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci if (!output->buf[inactive_idx]) { 46962306a36Sopenharmony_ci output->buf[inactive_idx] = new_buf; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci if (inactive_idx) 47262306a36Sopenharmony_ci vfe_output_update_pong_addr(vfe, output, 0, line); 47362306a36Sopenharmony_ci else 47462306a36Sopenharmony_ci vfe_output_update_ping_addr(vfe, output, 0, line); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 3); 47762306a36Sopenharmony_ci output->state = VFE_OUTPUT_CONTINUOUS; 47862306a36Sopenharmony_ci } else { 47962306a36Sopenharmony_ci vfe_buf_add_pending(output, new_buf); 48062306a36Sopenharmony_ci dev_err_ratelimited(vfe->camss->dev, 48162306a36Sopenharmony_ci "Inactive buffer is busy\n"); 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci case VFE_OUTPUT_IDLE: 48662306a36Sopenharmony_ci if (!output->buf[0]) { 48762306a36Sopenharmony_ci output->buf[0] = new_buf; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci vfe_output_init_addrs(vfe, output, 1, line); 49062306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 1); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci output->state = VFE_OUTPUT_SINGLE; 49362306a36Sopenharmony_ci } else { 49462306a36Sopenharmony_ci vfe_buf_add_pending(output, new_buf); 49562306a36Sopenharmony_ci dev_err_ratelimited(vfe->camss->dev, 49662306a36Sopenharmony_ci "Output idle with buffer set!\n"); 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci break; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci case VFE_OUTPUT_CONTINUOUS: 50162306a36Sopenharmony_ci default: 50262306a36Sopenharmony_ci vfe_buf_add_pending(output, new_buf); 50362306a36Sopenharmony_ci break; 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci/* 50862306a36Sopenharmony_ci * vfe_isr_halt_ack - Process halt ack 50962306a36Sopenharmony_ci * @vfe: VFE Device 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_cistatic void vfe_isr_halt_ack(struct vfe_device *vfe) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci complete(&vfe->halt_complete); 51462306a36Sopenharmony_ci vfe->ops_gen1->halt_clear(vfe); 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci/* 51862306a36Sopenharmony_ci * vfe_isr_sof - Process start of frame interrupt 51962306a36Sopenharmony_ci * @vfe: VFE Device 52062306a36Sopenharmony_ci * @line_id: VFE line 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_cistatic void vfe_isr_sof(struct vfe_device *vfe, enum vfe_line_id line_id) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci struct vfe_output *output; 52562306a36Sopenharmony_ci unsigned long flags; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 52862306a36Sopenharmony_ci output = &vfe->line[line_id].output; 52962306a36Sopenharmony_ci if (output->gen1.wait_sof) { 53062306a36Sopenharmony_ci output->gen1.wait_sof = 0; 53162306a36Sopenharmony_ci complete(&output->sof); 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci/* 53762306a36Sopenharmony_ci * vfe_isr_reg_update - Process reg update interrupt 53862306a36Sopenharmony_ci * @vfe: VFE Device 53962306a36Sopenharmony_ci * @line_id: VFE line 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_cistatic void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci struct vfe_output *output; 54462306a36Sopenharmony_ci struct vfe_line *line = &vfe->line[line_id]; 54562306a36Sopenharmony_ci unsigned long flags; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 54862306a36Sopenharmony_ci vfe->ops->reg_update_clear(vfe, line_id); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci output = &line->output; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci if (output->wait_reg_update) { 55362306a36Sopenharmony_ci output->wait_reg_update = 0; 55462306a36Sopenharmony_ci complete(&output->reg_update); 55562306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 55662306a36Sopenharmony_ci return; 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci if (output->state == VFE_OUTPUT_STOPPING) { 56062306a36Sopenharmony_ci /* Release last buffer when hw is idle */ 56162306a36Sopenharmony_ci if (output->last_buffer) { 56262306a36Sopenharmony_ci vb2_buffer_done(&output->last_buffer->vb.vb2_buf, 56362306a36Sopenharmony_ci VB2_BUF_STATE_DONE); 56462306a36Sopenharmony_ci output->last_buffer = NULL; 56562306a36Sopenharmony_ci } 56662306a36Sopenharmony_ci output->state = VFE_OUTPUT_IDLE; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /* Buffers received in stopping state are queued in */ 56962306a36Sopenharmony_ci /* dma pending queue, start next capture here */ 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci output->buf[0] = vfe_buf_get_pending(output); 57262306a36Sopenharmony_ci output->buf[1] = vfe_buf_get_pending(output); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci if (!output->buf[0] && output->buf[1]) { 57562306a36Sopenharmony_ci output->buf[0] = output->buf[1]; 57662306a36Sopenharmony_ci output->buf[1] = NULL; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (output->buf[0]) 58062306a36Sopenharmony_ci output->state = VFE_OUTPUT_SINGLE; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (output->buf[1]) 58362306a36Sopenharmony_ci output->state = VFE_OUTPUT_CONTINUOUS; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci switch (output->state) { 58662306a36Sopenharmony_ci case VFE_OUTPUT_SINGLE: 58762306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 2); 58862306a36Sopenharmony_ci break; 58962306a36Sopenharmony_ci case VFE_OUTPUT_CONTINUOUS: 59062306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 3); 59162306a36Sopenharmony_ci break; 59262306a36Sopenharmony_ci default: 59362306a36Sopenharmony_ci vfe_output_frame_drop(vfe, output, 0); 59462306a36Sopenharmony_ci break; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci vfe_output_init_addrs(vfe, output, 1, &vfe->line[line_id]); 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 60162306a36Sopenharmony_ci} 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci/* 60462306a36Sopenharmony_ci * vfe_isr_wm_done - Process write master done interrupt 60562306a36Sopenharmony_ci * @vfe: VFE Device 60662306a36Sopenharmony_ci * @wm: Write master id 60762306a36Sopenharmony_ci */ 60862306a36Sopenharmony_cistatic void vfe_isr_wm_done(struct vfe_device *vfe, u8 wm) 60962306a36Sopenharmony_ci{ 61062306a36Sopenharmony_ci struct camss_buffer *ready_buf; 61162306a36Sopenharmony_ci struct vfe_output *output; 61262306a36Sopenharmony_ci dma_addr_t *new_addr; 61362306a36Sopenharmony_ci unsigned long flags; 61462306a36Sopenharmony_ci u32 active_index; 61562306a36Sopenharmony_ci u64 ts = ktime_get_ns(); 61662306a36Sopenharmony_ci unsigned int i; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci active_index = vfe->ops_gen1->wm_get_ping_pong_status(vfe, wm); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci if (vfe->wm_output_map[wm] == VFE_LINE_NONE) { 62362306a36Sopenharmony_ci dev_err_ratelimited(vfe->camss->dev, 62462306a36Sopenharmony_ci "Received wm done for unmapped index\n"); 62562306a36Sopenharmony_ci goto out_unlock; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci output = &vfe->line[vfe->wm_output_map[wm]].output; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci if (output->gen1.active_buf == active_index && 0) { 63062306a36Sopenharmony_ci dev_err_ratelimited(vfe->camss->dev, 63162306a36Sopenharmony_ci "Active buffer mismatch!\n"); 63262306a36Sopenharmony_ci goto out_unlock; 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci output->gen1.active_buf = active_index; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci ready_buf = output->buf[!active_index]; 63762306a36Sopenharmony_ci if (!ready_buf) { 63862306a36Sopenharmony_ci dev_err_ratelimited(vfe->camss->dev, 63962306a36Sopenharmony_ci "Missing ready buf %d %d!\n", 64062306a36Sopenharmony_ci !active_index, output->state); 64162306a36Sopenharmony_ci goto out_unlock; 64262306a36Sopenharmony_ci } 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci ready_buf->vb.vb2_buf.timestamp = ts; 64562306a36Sopenharmony_ci ready_buf->vb.sequence = output->sequence++; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci /* Get next buffer */ 64862306a36Sopenharmony_ci output->buf[!active_index] = vfe_buf_get_pending(output); 64962306a36Sopenharmony_ci if (!output->buf[!active_index]) { 65062306a36Sopenharmony_ci /* No next buffer - set same address */ 65162306a36Sopenharmony_ci new_addr = ready_buf->addr; 65262306a36Sopenharmony_ci vfe_buf_update_wm_on_last(vfe, output); 65362306a36Sopenharmony_ci } else { 65462306a36Sopenharmony_ci new_addr = output->buf[!active_index]->addr; 65562306a36Sopenharmony_ci vfe_buf_update_wm_on_next(vfe, output); 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci if (active_index) 65962306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) 66062306a36Sopenharmony_ci vfe->ops_gen1->wm_set_ping_addr(vfe, output->wm_idx[i], new_addr[i]); 66162306a36Sopenharmony_ci else 66262306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) 66362306a36Sopenharmony_ci vfe->ops_gen1->wm_set_pong_addr(vfe, output->wm_idx[i], new_addr[i]); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci if (output->state == VFE_OUTPUT_STOPPING) 66862306a36Sopenharmony_ci output->last_buffer = ready_buf; 66962306a36Sopenharmony_ci else 67062306a36Sopenharmony_ci vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci return; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ciout_unlock: 67562306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci/* 67962306a36Sopenharmony_ci * vfe_queue_buffer - Add empty buffer 68062306a36Sopenharmony_ci * @vid: Video device structure 68162306a36Sopenharmony_ci * @buf: Buffer to be enqueued 68262306a36Sopenharmony_ci * 68362306a36Sopenharmony_ci * Add an empty buffer - depending on the current number of buffers it will be 68462306a36Sopenharmony_ci * put in pending buffer queue or directly given to the hardware to be filled. 68562306a36Sopenharmony_ci * 68662306a36Sopenharmony_ci * Return 0 on success or a negative error code otherwise 68762306a36Sopenharmony_ci */ 68862306a36Sopenharmony_cistatic int vfe_queue_buffer(struct camss_video *vid, struct camss_buffer *buf) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci struct vfe_line *line = container_of(vid, struct vfe_line, video_out); 69162306a36Sopenharmony_ci struct vfe_device *vfe = to_vfe(line); 69262306a36Sopenharmony_ci struct vfe_output *output; 69362306a36Sopenharmony_ci unsigned long flags; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci output = &line->output; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci spin_lock_irqsave(&vfe->output_lock, flags); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci vfe_buf_update_wm_on_new(vfe, output, buf, line); 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci spin_unlock_irqrestore(&vfe->output_lock, flags); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci return 0; 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci#define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N)) 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ciint vfe_word_per_line(u32 format, u32 width) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci int val = 0; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci switch (format) { 71362306a36Sopenharmony_ci case V4L2_PIX_FMT_NV12: 71462306a36Sopenharmony_ci case V4L2_PIX_FMT_NV21: 71562306a36Sopenharmony_ci case V4L2_PIX_FMT_NV16: 71662306a36Sopenharmony_ci case V4L2_PIX_FMT_NV61: 71762306a36Sopenharmony_ci val = CALC_WORD(width, 1, 8); 71862306a36Sopenharmony_ci break; 71962306a36Sopenharmony_ci case V4L2_PIX_FMT_YUYV: 72062306a36Sopenharmony_ci case V4L2_PIX_FMT_YVYU: 72162306a36Sopenharmony_ci case V4L2_PIX_FMT_UYVY: 72262306a36Sopenharmony_ci case V4L2_PIX_FMT_VYUY: 72362306a36Sopenharmony_ci val = CALC_WORD(width, 2, 8); 72462306a36Sopenharmony_ci break; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci return val; 72862306a36Sopenharmony_ci} 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ciconst struct vfe_isr_ops vfe_isr_ops_gen1 = { 73162306a36Sopenharmony_ci .reset_ack = vfe_isr_reset_ack, 73262306a36Sopenharmony_ci .halt_ack = vfe_isr_halt_ack, 73362306a36Sopenharmony_ci .reg_update = vfe_isr_reg_update, 73462306a36Sopenharmony_ci .sof = vfe_isr_sof, 73562306a36Sopenharmony_ci .comp_done = vfe_isr_comp_done, 73662306a36Sopenharmony_ci .wm_done = vfe_isr_wm_done, 73762306a36Sopenharmony_ci}; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ciconst struct camss_video_ops vfe_video_ops_gen1 = { 74062306a36Sopenharmony_ci .queue_buffer = vfe_queue_buffer, 74162306a36Sopenharmony_ci .flush_buffers = vfe_flush_buffers, 74262306a36Sopenharmony_ci}; 743