static int setup_disp_channel2(struct fb_info *fbi) { int retval = 0; struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par; mxc_fbi->cur_ipu_buf = 1; if (mxc_fbi->alpha_chan_en) mxc_fbi->cur_ipu_alpha_buf = 1; fbi->var.xoffset = fbi->var.yoffset = 0; debug("%s: %x %d %d %d %lx %lx\n", __func__, mxc_fbi->ipu_ch, fbi->var.xres, fbi->var.yres, fbi->fix.line_length, fbi->fix.smem_start, fbi->fix.smem_start + (fbi->fix.line_length * fbi->var.yres)); retval = ipu_init_channel_buffer(mxc_fbi->ipu_ch, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi), fbi->var.xres, fbi->var.yres, fbi->fix.line_length, fbi->fix.smem_start + (fbi->fix.line_length * fbi->var.yres), fbi->fix.smem_start, 0, 0); if (retval) printf("ipu_init_channel_buffer error %d\n", retval); return retval; }
static int mxc_ipu_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; switch (cmd) { case IPU_INIT_CHANNEL: { ipu_channel_parm parm; if (copy_from_user (&parm, (ipu_channel_parm *) arg, sizeof(ipu_channel_parm))) { return -EFAULT; } if (!parm.flag) { ret = ipu_init_channel(parm.channel, &parm.params); } else { ret = ipu_init_channel(parm.channel, NULL); } } break; case IPU_UNINIT_CHANNEL: { ipu_channel_t ch; int __user *argp = (void __user *)arg; if (get_user(ch, argp)) return -EFAULT; ipu_uninit_channel(ch); } break; case IPU_INIT_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) { return -EFAULT; } ret = ipu_init_channel_buffer(parm.channel, parm.type, parm.pixel_fmt, parm.width, parm.height, parm.stride, parm.rot_mode, parm.phyaddr_0, parm.phyaddr_1, parm.u_offset, parm.v_offset); } break; case IPU_UPDATE_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) { return -EFAULT; } if ((parm.phyaddr_0 != (dma_addr_t) NULL) && (parm.phyaddr_1 == (dma_addr_t) NULL)) { ret = ipu_update_channel_buffer(parm.channel, parm.type, parm.bufNum, parm.phyaddr_0); } else if ((parm.phyaddr_0 == (dma_addr_t) NULL) && (parm.phyaddr_1 != (dma_addr_t) NULL)) { ret = ipu_update_channel_buffer(parm.channel, parm.type, parm.bufNum, parm.phyaddr_1); } else { ret = -1; } } break; case IPU_SELECT_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) { return -EFAULT; } ret = ipu_select_buffer(parm.channel, parm.type, parm.bufNum); } break; case IPU_LINK_CHANNELS: { ipu_channel_link link; if (copy_from_user (&link, (ipu_channel_link *) arg, sizeof(ipu_channel_link))) { return -EFAULT; } ret = ipu_link_channels(link.src_ch, link.dest_ch); } break; case IPU_UNLINK_CHANNELS: { ipu_channel_link link; if (copy_from_user (&link, (ipu_channel_link *) arg, sizeof(ipu_channel_link))) { return -EFAULT; } ret = ipu_unlink_channels(link.src_ch, link.dest_ch); } break; case IPU_ENABLE_CHANNEL: { ipu_channel_t ch; int __user *argp = (void __user *)arg; if (get_user(ch, argp)) return -EFAULT; ipu_enable_channel(ch); } break; case IPU_DISABLE_CHANNEL: { ipu_channel_info info; if (copy_from_user (&info, (ipu_channel_info *) arg, sizeof(ipu_channel_info))) { return -EFAULT; } ret = ipu_disable_channel(info.channel, info.stop); } break; case IPU_ENABLE_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_enable_irq(irq); } break; case IPU_DISABLE_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_disable_irq(irq); } break; case IPU_CLEAR_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_clear_irq(irq); } break; case IPU_FREE_IRQ: { ipu_irq_info info; if (copy_from_user (&info, (ipu_irq_info *) arg, sizeof(ipu_irq_info))) { return -EFAULT; } ipu_free_irq(info.irq, info.dev_id); } break; case IPU_REQUEST_IRQ_STATUS: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ret = ipu_get_irq_status(irq); } break; case IPU_SDC_INIT_PANEL: { ipu_sdc_panel_info sinfo; if (copy_from_user (&sinfo, (ipu_sdc_panel_info *) arg, sizeof(ipu_sdc_panel_info))) { return -EFAULT; } ret = ipu_sdc_init_panel(sinfo.panel, sinfo.pixel_clk, sinfo.width, sinfo.height, sinfo.pixel_fmt, sinfo.hStartWidth, sinfo.hSyncWidth, sinfo.hEndWidth, sinfo.vStartWidth, sinfo.vSyncWidth, sinfo.vEndWidth, sinfo.signal); } break; case IPU_SDC_SET_WIN_POS: { ipu_sdc_window_pos pos; if (copy_from_user (&pos, (ipu_sdc_window_pos *) arg, sizeof(ipu_sdc_window_pos))) { return -EFAULT; } ret = ipu_sdc_set_window_pos(pos.channel, pos.x_pos, pos.y_pos); } break; case IPU_SDC_SET_GLOBAL_ALPHA: { ipu_sdc_global_alpha g; if (copy_from_user (&g, (ipu_sdc_global_alpha *) arg, sizeof(ipu_sdc_global_alpha))) { return -EFAULT; } ret = ipu_sdc_set_global_alpha(g.enable, g.alpha); } break; case IPU_SDC_SET_COLOR_KEY: { ipu_sdc_color_key c; if (copy_from_user (&c, (ipu_sdc_color_key *) arg, sizeof(ipu_sdc_color_key))) { return -EFAULT; } ret = ipu_sdc_set_color_key(c.channel, c.enable, c.colorKey); } break; case IPU_SDC_SET_BRIGHTNESS: { uint8_t b; int __user *argp = (void __user *)arg; if (get_user(b, argp)) return -EFAULT; ret = ipu_sdc_set_brightness(b); } break; case IPU_REGISTER_GENERIC_ISR: { ipu_event_info info; if (copy_from_user (&info, (ipu_event_info *) arg, sizeof(ipu_event_info))) { return -EFAULT; } ret = ipu_request_irq(info.irq, mxc_ipu_generic_handler, 0, "video_sink", info.dev); } break; case IPU_GET_EVENT: /* User will have to allocate event_type structure and pass the pointer in arg */ { event_type ev; int r = -1; r = get_events(&ev); if (r == -1) { wait_event_interruptible(waitq, (pending_events != 0)); r = get_events(&ev); } ret = -1; if (r == 0) { if (!copy_to_user((event_type *) arg, &ev, sizeof(event_type))) { ret = 0; } } } break; case IPU_ADC_WRITE_TEMPLATE: { ipu_adc_template temp; if (copy_from_user (&temp, (ipu_adc_template *) arg, sizeof(temp))) { return -EFAULT; } ret = ipu_adc_write_template(temp.disp, temp.pCmd, temp.write); } break; case IPU_ADC_UPDATE: { ipu_adc_update update; if (copy_from_user (&update, (ipu_adc_update *) arg, sizeof(update))) { return -EFAULT; } ret = ipu_adc_set_update_mode(update.channel, update.mode, update.refresh_rate, update.addr, update.size); } break; case IPU_ADC_SNOOP: { ipu_adc_snoop snoop; if (copy_from_user (&snoop, (ipu_adc_snoop *) arg, sizeof(snoop))) { return -EFAULT; } ret = ipu_adc_get_snooping_status(snoop.statl, snoop.stath); } break; case IPU_ADC_CMD: { ipu_adc_cmd cmd; if (copy_from_user (&cmd, (ipu_adc_cmd *) arg, sizeof(cmd))) { return -EFAULT; } ret = ipu_adc_write_cmd(cmd.disp, cmd.type, cmd.cmd, cmd.params, cmd.numParams); } break; case IPU_ADC_INIT_PANEL: { ipu_adc_panel panel; if (copy_from_user (&panel, (ipu_adc_panel *) arg, sizeof(panel))) { return -EFAULT; } ret = ipu_adc_init_panel(panel.disp, panel.width, panel.height, panel.pixel_fmt, panel.stride, panel.signal, panel.addr, panel.vsync_width, panel.mode); } break; case IPU_ADC_IFC_TIMING: { ipu_adc_ifc_timing t; if (copy_from_user (&t, (ipu_adc_ifc_timing *) arg, sizeof(t))) { return -EFAULT; } ret = ipu_adc_init_ifc_timing(t.disp, t.read, t.cycle_time, t.up_time, t.down_time, t.read_latch_time, t.pixel_clk); } break; case IPU_CSI_INIT_INTERFACE: { ipu_csi_interface c; if (copy_from_user (&c, (ipu_csi_interface *) arg, sizeof(c))) return -EFAULT; ret = ipu_csi_init_interface(c.width, c.height, c.pixel_fmt, c.signal); } break; case IPU_CSI_ENABLE_MCLK: { ipu_csi_mclk m; if (copy_from_user(&m, (ipu_csi_mclk *) arg, sizeof(m))) return -EFAULT; ret = ipu_csi_enable_mclk(m.src, m.flag, m.wait); } break; case IPU_CSI_READ_MCLK_FLAG: { ret = ipu_csi_read_mclk_flag(); } break; case IPU_CSI_FLASH_STROBE: { bool strobe; int __user *argp = (void __user *)arg; if (get_user(strobe, argp)) return -EFAULT; ipu_csi_flash_strobe(strobe); } break; case IPU_CSI_GET_WIN_SIZE: { ipu_csi_window_size w; ipu_csi_get_window_size(&w.width, &w.height); if (copy_to_user ((ipu_csi_window_size *) arg, &w, sizeof(w))) return -EFAULT; } break; case IPU_CSI_SET_WIN_SIZE: { ipu_csi_window_size w; if (copy_from_user (&w, (ipu_csi_window_size *) arg, sizeof(w))) return -EFAULT; ipu_csi_set_window_size(w.width, w.height); } break; case IPU_CSI_SET_WINDOW: { ipu_csi_window p; if (copy_from_user (&p, (ipu_csi_window *) arg, sizeof(p))) return -EFAULT; ipu_csi_set_window_pos(p.left, p.top); } break; case IPU_PF_SET_PAUSE_ROW: { uint32_t p; int __user *argp = (void __user *)arg; if (get_user(p, argp)) return -EFAULT; ret = ipu_pf_set_pause_row(p); } break; default: break; } return ret; }
/*! * PrpENC enable channel setup function * * @param cam struct cam_data * mxc capture instance * * @return status */ static int prp_enc_setup(cam_data *cam) { ipu_channel_params_t enc; int err = 0; dma_addr_t dummy = cam->dummy_frame.buffer.m.offset; #ifdef CONFIG_MXC_MIPI_CSI2 void *mipi_csi2_info; int ipu_id; int csi_id; #endif CAMERA_TRACE("In prp_enc_setup\n"); if (!cam) { printk(KERN_ERR "cam private is NULL\n"); return -ENXIO; } memset(&enc, 0, sizeof(ipu_channel_params_t)); ipu_csi_get_window_size(cam->ipu, &enc.csi_prp_enc_mem.in_width, &enc.csi_prp_enc_mem.in_height, cam->csi); enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width; enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height; enc.csi_prp_enc_mem.csi = cam->csi; if (cam->rotation >= IPU_ROTATE_90_RIGHT) { enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height; enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width; } if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P; pr_info("YUV420\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YVU420P; pr_info("YVU420\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P; pr_info("YUV422P\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV; pr_info("YUYV\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY; pr_info("UYVY\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12; pr_info("NV12\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24; pr_info("BGR24\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24; pr_info("RGB24\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565; pr_info("RGB565\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32; pr_info("BGR32\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32; pr_info("RGB32\n"); } else { printk(KERN_ERR "format not supported\n"); return -EINVAL; } #ifdef CONFIG_MXC_MIPI_CSI2 mipi_csi2_info = mipi_csi2_get_info(); if (mipi_csi2_info) { if (mipi_csi2_get_status(mipi_csi2_info)) { ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); if (cam->ipu == ipu_get_soc(ipu_id) && cam->csi == csi_id) { enc.csi_prp_enc_mem.mipi_en = true; enc.csi_prp_enc_mem.mipi_vc = mipi_csi2_get_virtual_channel(mipi_csi2_info); enc.csi_prp_enc_mem.mipi_id = mipi_csi2_get_datatype(mipi_csi2_info); mipi_csi2_pixelclk_enable(mipi_csi2_info); } else { enc.csi_prp_enc_mem.mipi_en = false; enc.csi_prp_enc_mem.mipi_vc = 0; enc.csi_prp_enc_mem.mipi_id = 0; } } else { enc.csi_prp_enc_mem.mipi_en = false; enc.csi_prp_enc_mem.mipi_vc = 0; enc.csi_prp_enc_mem.mipi_id = 0; } } #endif err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc); if (err != 0) { printk(KERN_ERR "ipu_init_channel %d\n", err); return err; } grotation = cam->rotation; if (cam->rotation >= IPU_ROTATE_90_RIGHT) { if (cam->rot_enc_bufs_vaddr[0]) { dma_free_coherent(0, cam->rot_enc_buf_size[0], cam->rot_enc_bufs_vaddr[0], cam->rot_enc_bufs[0]); } if (cam->rot_enc_bufs_vaddr[1]) { dma_free_coherent(0, cam->rot_enc_buf_size[1], cam->rot_enc_bufs_vaddr[1], cam->rot_enc_bufs[1]); } cam->rot_enc_buf_size[0] = PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); cam->rot_enc_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0], &cam->rot_enc_bufs[0], GFP_DMA | GFP_KERNEL); if (!cam->rot_enc_bufs_vaddr[0]) { printk(KERN_ERR "alloc enc_bufs0\n"); return -ENOMEM; } cam->rot_enc_buf_size[1] = PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); cam->rot_enc_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1], &cam->rot_enc_bufs[1], GFP_DMA | GFP_KERNEL); if (!cam->rot_enc_bufs_vaddr[1]) { dma_free_coherent(0, cam->rot_enc_buf_size[0], cam->rot_enc_bufs_vaddr[0], cam->rot_enc_bufs[0]); cam->rot_enc_bufs_vaddr[0] = NULL; cam->rot_enc_bufs[0] = 0; printk(KERN_ERR "alloc enc_bufs1\n"); return -ENOMEM; } err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_width, enc.csi_prp_enc_mem.out_height, enc.csi_prp_enc_mem.out_width, IPU_ROTATE_NONE, cam->rot_enc_bufs[0], cam->rot_enc_bufs[1], 0, 0, 0); if (err != 0) { printk(KERN_ERR "CSI_PRP_ENC_MEM err\n"); return err; } err = ipu_init_channel(cam->ipu, MEM_ROT_ENC_MEM, NULL); if (err != 0) { printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n"); return err; } err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM, IPU_INPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_width, enc.csi_prp_enc_mem.out_height, enc.csi_prp_enc_mem.out_width, cam->rotation, cam->rot_enc_bufs[0], cam->rot_enc_bufs[1], 0, 0, 0); if (err != 0) { printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n"); return err; } err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_height, enc.csi_prp_enc_mem.out_width, cam->v2f.fmt.pix.bytesperline / bytes_per_pixel(enc.csi_prp_enc_mem. out_pixel_fmt), IPU_ROTATE_NONE, dummy, dummy, 0, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n"); return err; } err = ipu_link_channels(cam->ipu, CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM); if (err < 0) { printk(KERN_ERR "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n"); return err; } err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); return err; } err = ipu_enable_channel(cam->ipu, MEM_ROT_ENC_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n"); return err; } ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 0); ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 1); } else { err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_width, enc.csi_prp_enc_mem.out_height, cam->v2f.fmt.pix.bytesperline / bytes_per_pixel(enc.csi_prp_enc_mem. out_pixel_fmt), cam->rotation, dummy, dummy, 0, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n"); return err; } err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); return err; } } return err; }
/*! * Start the output stream * * @param vout structure vout_data * * * @return status 0 Success */ static int mxc_v4l2out_streamon(vout_data * vout) { ipu_channel_params_t params; int pp_in_buf[2]; u16 out_width; u16 out_height; ipu_channel_t display_input_ch = MEM_PP_MEM; bool use_direct_adc = false; if (!vout) return -EINVAL; if (queue_size(&vout->ready_q) < 2) { DPRINTK("2 buffers not been queued yet!\n"); return -EINVAL; } out_width = vout->crop_current.width; out_height = vout->crop_current.height; vout->next_done_ipu_buf = vout->next_rdy_ipu_buf = 0; vout->ipu_buf[0] = pp_in_buf[0] = dequeue_buf(&vout->ready_q); vout->ipu_buf[1] = pp_in_buf[1] = dequeue_buf(&vout->ready_q); /* Init Display Channel */ #ifdef CONFIG_FB_MXC_ASYNC_PANEL if (vout->cur_disp_output != DISP3) { int fbnum = vout->output_fb_num[vout->cur_disp_output]; mxcfb_set_refresh_mode(registered_fb[fbnum], MXCFB_REFRESH_OFF, 0); if (vout->rotate < IPU_ROTATE_90_RIGHT) { DPRINTK("Using PP direct to ADC channel\n"); use_direct_adc = true; vout->display_ch = MEM_PP_ADC; vout->post_proc_ch = MEM_PP_ADC; memset(¶ms, 0, sizeof(params)); params.mem_pp_adc.in_width = vout->v2f.fmt.pix.width; params.mem_pp_adc.in_height = vout->v2f.fmt.pix.height; params.mem_pp_adc.in_pixel_fmt = vout->v2f.fmt.pix.pixelformat; params.mem_pp_adc.out_width = out_width; params.mem_pp_adc.out_height = out_height; params.mem_pp_adc.out_pixel_fmt = SDC_FG_FB_FORMAT; #ifdef CONFIG_FB_MXC_EPSON_PANEL params.mem_pp_adc.out_left = 2 + vout->crop_current.left; #else params.mem_pp_adc.out_left = 12 + vout->crop_current.left; #endif params.mem_pp_adc.out_top = vout->crop_current.top; if (ipu_init_channel(vout->post_proc_ch, ¶ms) != 0) { DPRINTK(KERN_ERR "Error initializing PP chan\n"); return -EINVAL; } if (ipu_init_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, params.mem_pp_adc. in_pixel_fmt, params.mem_pp_adc.in_width, params.mem_pp_adc.in_height, params.mem_pp_adc.in_width, vout->rotate, vout-> queue_buf_paddr[pp_in_buf [0]], vout-> queue_buf_paddr[pp_in_buf [1]]) != 0) { DPRINTK(KERN_ERR "Error initializing PP " "in buf\n"); return -EINVAL; } if (ipu_init_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, params.mem_pp_adc. out_pixel_fmt, out_width, out_height, out_width, vout->rotate, NULL, NULL) != 0) { DPRINTK(KERN_ERR "Error initializing PP " "output buffer\n"); return -EINVAL; } } else { DPRINTK("Using ADC SYS2 channel\n"); vout->display_ch = ADC_SYS2; vout->post_proc_ch = MEM_PP_MEM; memset(¶ms, 0, sizeof(params)); params.adc_sys2.disp = vout->cur_disp_output; params.adc_sys2.ch_mode = WriteTemplateNonSeq; #ifdef CONFIG_FB_MXC_EPSON_PANEL params.adc_sys2.out_left = 2 + vout->crop_current.left; #else params.adc_sys2.out_left = 12 + vout->crop_current.left; #endif params.adc_sys2.out_top = vout->crop_current.top; if (ipu_init_channel(ADC_SYS2, ¶ms) < 0) return -EINVAL; if (ipu_init_channel_buffer(vout->display_ch, IPU_INPUT_BUFFER, SDC_FG_FB_FORMAT, out_width, out_height, out_width, IPU_ROTATE_NONE, vout->display_bufs[0], vout->display_bufs[1]) != 0) { DPRINTK(KERN_ERR "Error initializing SDC FG " "buffer\n"); return -EINVAL; } } } else #endif { /* Use SDC */ DPRINTK("Using SDC channel\n"); vout->display_ch = MEM_SDC_FG; vout->post_proc_ch = MEM_PP_MEM; ipu_init_channel(MEM_SDC_FG, NULL); ipu_sdc_set_window_pos(MEM_SDC_FG, vout->crop_current.left, vout->crop_current.top); if (ipu_init_channel_buffer(vout->display_ch, IPU_INPUT_BUFFER, SDC_FG_FB_FORMAT, out_width, out_height, out_width, IPU_ROTATE_NONE, vout->display_bufs[0], vout->display_bufs[1]) != 0) { DPRINTK(KERN_ERR "Error initializing SDC FG buffer\n"); return -EINVAL; } } /* Init PP */ if (use_direct_adc == false) { if (vout->rotate >= IPU_ROTATE_90_RIGHT) { out_width = vout->crop_current.height; out_height = vout->crop_current.width; } memset(¶ms, 0, sizeof(params)); params.mem_pp_mem.in_width = vout->v2f.fmt.pix.width; params.mem_pp_mem.in_height = vout->v2f.fmt.pix.height; params.mem_pp_mem.in_pixel_fmt = vout->v2f.fmt.pix.pixelformat; params.mem_pp_mem.out_width = out_width; params.mem_pp_mem.out_height = out_height; params.mem_pp_mem.out_pixel_fmt = SDC_FG_FB_FORMAT; if (ipu_init_channel(vout->post_proc_ch, ¶ms) != 0) { DPRINTK(KERN_ERR "Error initializing PP channel\n"); return -EINVAL; } if (ipu_init_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, params.mem_pp_mem.in_pixel_fmt, params.mem_pp_mem.in_width, params.mem_pp_mem.in_height, params.mem_pp_mem.in_width, IPU_ROTATE_NONE, vout->queue_buf_paddr[pp_in_buf[0]], vout-> queue_buf_paddr[pp_in_buf[1]]) != 0) { DPRINTK(KERN_ERR "Error initializing PP input buffer\n"); return -EINVAL; } if (vout->rotate >= IPU_ROTATE_90_RIGHT) { if (vout->rot_pp_bufs[0]) { mxc_free_buffers(vout->rot_pp_bufs, 2); } if (mxc_allocate_buffers(vout->rot_pp_bufs, 2, vout->sdc_fg_buf_size) < 0) { return -ENOBUFS; } if (ipu_init_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, params.mem_pp_mem. out_pixel_fmt, out_width, out_height, out_width, IPU_ROTATE_NONE, vout->rot_pp_bufs[0], vout->rot_pp_bufs[1]) != 0) { DPRINTK(KERN_ERR "Error initializing PP " "output buffer\n"); return -EINVAL; } if (ipu_init_channel(MEM_ROT_PP_MEM, NULL) != 0) { DPRINTK(KERN_ERR "Error initializing PP ROT " "channel\n"); return -EINVAL; } if (ipu_init_channel_buffer(MEM_ROT_PP_MEM, IPU_INPUT_BUFFER, params.mem_pp_mem. out_pixel_fmt, out_width, out_height, out_width, vout->rotate, vout->rot_pp_bufs[0], vout->rot_pp_bufs[1]) != 0) { DPRINTK(KERN_ERR "Error initializing PP ROT " "input buffer\n"); return -EINVAL; } /* swap width and height */ out_width = vout->crop_current.width; out_height = vout->crop_current.height; if (ipu_init_channel_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, params.mem_pp_mem. out_pixel_fmt, out_width, out_height, out_width, IPU_ROTATE_NONE, vout->display_bufs[0], vout->display_bufs[1]) != 0) { DPRINTK(KERN_ERR "Error initializing PP " "output buffer\n"); return -EINVAL; } if (ipu_link_channels(vout->post_proc_ch, MEM_ROT_PP_MEM) < 0) { return -EINVAL; } ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0); ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 1); ipu_enable_channel(MEM_ROT_PP_MEM); display_input_ch = MEM_ROT_PP_MEM; } else { if (ipu_init_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, params.mem_pp_mem. out_pixel_fmt, out_width, out_height, out_width, vout->rotate, vout->display_bufs[0], vout->display_bufs[1]) != 0) { DPRINTK(KERN_ERR "Error initializing PP " "output buffer\n"); return -EINVAL; } } if (ipu_link_channels(display_input_ch, vout->display_ch) < 0) { DPRINTK(KERN_ERR "Error linking ipu channels\n"); return -EINVAL; } } vout->state = STATE_STREAM_PAUSED; ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0); ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 1); if (use_direct_adc == false) { ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 0); ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 1); ipu_enable_channel(vout->post_proc_ch); ipu_enable_channel(vout->display_ch); } else { ipu_enable_channel(vout->post_proc_ch); } return 0; }
static long mxc_ipu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; switch (cmd) { case IPU_INIT_CHANNEL: { ipu_channel_parm parm; if (copy_from_user (&parm, (ipu_channel_parm *) arg, sizeof(ipu_channel_parm))) return -EFAULT; if (!parm.flag) { ret = ipu_init_channel(parm.channel, &parm.params); } else { ret = ipu_init_channel(parm.channel, NULL); } } break; case IPU_UNINIT_CHANNEL: { ipu_channel_t ch; int __user *argp = (void __user *)arg; if (get_user(ch, argp)) return -EFAULT; ipu_uninit_channel(ch); } break; case IPU_INIT_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) return -EFAULT; ret = ipu_init_channel_buffer( parm.channel, parm.type, parm.pixel_fmt, parm.width, parm.height, parm.stride, parm.rot_mode, parm.phyaddr_0, parm.phyaddr_1, parm.u_offset, parm.v_offset); } break; case IPU_UPDATE_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) return -EFAULT; if ((parm.phyaddr_0 != (dma_addr_t) NULL) && (parm.phyaddr_1 == (dma_addr_t) NULL)) { ret = ipu_update_channel_buffer( parm.channel, parm.type, parm.bufNum, parm.phyaddr_0); } else if ((parm.phyaddr_0 == (dma_addr_t) NULL) && (parm.phyaddr_1 != (dma_addr_t) NULL)) { ret = ipu_update_channel_buffer( parm.channel, parm.type, parm.bufNum, parm.phyaddr_1); } else { ret = -1; } } break; case IPU_SELECT_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) return -EFAULT; ret = ipu_select_buffer(parm.channel, parm.type, parm.bufNum); } break; case IPU_SELECT_MULTI_VDI_BUFFER: { uint32_t parm; if (copy_from_user (&parm, (uint32_t *) arg, sizeof(uint32_t))) return -EFAULT; ret = ipu_select_multi_vdi_buffer(parm); } break; case IPU_LINK_CHANNELS: { ipu_channel_link link; if (copy_from_user (&link, (ipu_channel_link *) arg, sizeof(ipu_channel_link))) return -EFAULT; ret = ipu_link_channels(link.src_ch, link.dest_ch); } break; case IPU_UNLINK_CHANNELS: { ipu_channel_link link; if (copy_from_user (&link, (ipu_channel_link *) arg, sizeof(ipu_channel_link))) return -EFAULT; ret = ipu_unlink_channels(link.src_ch, link.dest_ch); } break; case IPU_ENABLE_CHANNEL: { ipu_channel_t ch; int __user *argp = (void __user *)arg; if (get_user(ch, argp)) return -EFAULT; ipu_enable_channel(ch); } break; case IPU_DISABLE_CHANNEL: { ipu_channel_info info; if (copy_from_user (&info, (ipu_channel_info *) arg, sizeof(ipu_channel_info))) return -EFAULT; ret = ipu_disable_channel(info.channel, info.stop); } break; case IPU_ENABLE_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_enable_irq(irq); } break; case IPU_DISABLE_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_disable_irq(irq); } break; case IPU_CLEAR_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_clear_irq(irq); } break; case IPU_FREE_IRQ: { ipu_irq_info info; if (copy_from_user (&info, (ipu_irq_info *) arg, sizeof(ipu_irq_info))) return -EFAULT; ipu_free_irq(info.irq, info.dev_id); irq_info[info.irq].irq_pending = 0; } break; case IPU_REQUEST_IRQ_STATUS: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ret = ipu_get_irq_status(irq); } break; case IPU_REGISTER_GENERIC_ISR: { ipu_event_info info; if (copy_from_user (&info, (ipu_event_info *) arg, sizeof(ipu_event_info))) return -EFAULT; ret = ipu_request_irq(info.irq, mxc_ipu_generic_handler, 0, "video_sink", info.dev); if (ret == 0) init_waitqueue_head(&(irq_info[info.irq].waitq)); } break; case IPU_GET_EVENT: /* User will have to allocate event_type structure and pass the pointer in arg */ { ipu_event_info info; int r = -1; if (copy_from_user (&info, (ipu_event_info *) arg, sizeof(ipu_event_info))) return -EFAULT; r = get_events(&info); if (r == -1) { if ((file->f_flags & O_NONBLOCK) && (irq_info[info.irq].irq_pending == 0)) return -EAGAIN; wait_event_interruptible_timeout(irq_info[info.irq].waitq, (irq_info[info.irq].irq_pending != 0), 2 * HZ); r = get_events(&info); } ret = -1; if (r == 0) { if (!copy_to_user((ipu_event_info *) arg, &info, sizeof(ipu_event_info))) ret = 0; } } break; case IPU_ALOC_MEM: { ipu_mem_info info; if (copy_from_user (&info, (ipu_mem_info *) arg, sizeof(ipu_mem_info))) return -EFAULT; info.vaddr = dma_alloc_coherent(0, PAGE_ALIGN(info.size), &info.paddr, GFP_DMA | GFP_KERNEL); if (info.vaddr == 0) { printk(KERN_ERR "dma alloc failed!\n"); return -ENOBUFS; } if (copy_to_user((ipu_mem_info *) arg, &info, sizeof(ipu_mem_info)) > 0) return -EFAULT; } break; case IPU_FREE_MEM: { ipu_mem_info info; if (copy_from_user (&info, (ipu_mem_info *) arg, sizeof(ipu_mem_info))) return -EFAULT; if (info.vaddr) dma_free_coherent(0, PAGE_ALIGN(info.size), info.vaddr, info.paddr); else return -EFAULT; } break; case IPU_IS_CHAN_BUSY: { ipu_channel_t chan; if (copy_from_user (&chan, (ipu_channel_t *)arg, sizeof(ipu_channel_t))) return -EFAULT; if (ipu_is_channel_busy(chan)) ret = 1; else ret = 0; } break; case IPU_CALC_STRIPES_SIZE: { ipu_stripe_parm stripe_parm; if (copy_from_user (&stripe_parm, (ipu_stripe_parm *)arg, sizeof(ipu_stripe_parm))) return -EFAULT; ipu_calc_stripes_sizes(stripe_parm.input_width, stripe_parm.output_width, stripe_parm.maximal_stripe_width, stripe_parm.cirr, stripe_parm.equal_stripes, stripe_parm.input_pixelformat, stripe_parm.output_pixelformat, &stripe_parm.left, &stripe_parm.right); if (copy_to_user((ipu_stripe_parm *) arg, &stripe_parm, sizeof(ipu_stripe_parm)) > 0) return -EFAULT; } break; case IPU_UPDATE_BUF_OFFSET: { ipu_buf_offset_parm offset_parm; if (copy_from_user (&offset_parm, (ipu_buf_offset_parm *)arg, sizeof(ipu_buf_offset_parm))) return -EFAULT; ret = ipu_update_channel_offset(offset_parm.channel, offset_parm.type, offset_parm.pixel_fmt, offset_parm.width, offset_parm.height, offset_parm.stride, offset_parm.u_offset, offset_parm.v_offset, offset_parm.vertical_offset, offset_parm.horizontal_offset); } break; case IPU_CSC_UPDATE: { int param[5][3]; ipu_csc_update csc; if (copy_from_user(&csc, (void *) arg, sizeof(ipu_csc_update))) return -EFAULT; if (copy_from_user(¶m[0][0], (void *) csc.param, sizeof(param))) return -EFAULT; ipu_set_csc_coefficients(csc.channel, param); } break; default: break; } return ret; }
int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode, struct mxcfb_rect *update_region) { unsigned long start_addr; int ret_mode; uint32_t dummy; ipu_channel_params_t params; struct mxcfb_rect rect; struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par; uint32_t stride_pixels = (fbi->fix.line_length * 8) / fbi->var.bits_per_pixel; uint32_t memsize = fbi->fix.smem_len; if (mxc_fbi->cur_update_mode == mode) return mode; ret_mode = mxc_fbi->cur_update_mode; ipu_disable_irq(IPU_IRQ_ADC_SYS1_EOF); ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE, 0, 0, 0); #ifdef PARTIAL_REFRESH ipu_disable_irq(IPU_IRQ_ADC_SYS2_EOF); ipu_adc_set_update_mode(ADC_SYS2, IPU_ADC_REFRESH_NONE, 0, 0, 0); #endif ipu_disable_channel(ADC_SYS1, true); ipu_clear_irq(IPU_IRQ_ADC_SYS1_EOF); #ifdef PARTIAL_REFRESH ipu_disable_channel(ADC_SYS2, true); ipu_clear_irq(IPU_IRQ_ADC_SYS2_EOF); #endif ipu_adc_get_snooping_status(&dummy, &dummy); mxc_fbi->cur_update_mode = mode; switch (mode) { case MXCFB_REFRESH_OFF: if (ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE, 0, 0, 0) < 0) dev_err(fbi->device, "Error enabling auto refesh.\n"); if (ipu_adc_set_update_mode(ADC_SYS2, IPU_ADC_REFRESH_NONE, 0, 0, 0) < 0) dev_err(fbi->device, "Error enabling auto refesh.\n"); #if 0 ipu_init_channel_buffer(ADC_SYS2, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi->var.bits_per_pixel), 1, 1, 4, IPU_ROTATE_NONE, fbi->fix.smem_start, fbi->fix.smem_start, 0, 0); ipu_enable_channel(ADC_SYS2); ipu_select_buffer(ADC_SYS2, IPU_INPUT_BUFFER, 0); ipu_select_buffer(ADC_SYS2, IPU_INPUT_BUFFER, 1); msleep(10); #endif ipu_uninit_channel(ADC_SYS1); #ifdef PARTIAL_REFRESH ipu_uninit_channel(ADC_SYS2); #endif break; case MXCFB_REFRESH_PARTIAL: #ifdef PARTIAL_REFRESH ipu_adc_get_snooping_status(&dummy, &dummy); params.adc_sys2.disp = DISP0; params.adc_sys2.ch_mode = WriteTemplateNonSeq; params.adc_sys2.out_left = 0; params.adc_sys2.out_top = 0; ipu_init_channel(ADC_SYS2, ¶ms); if (ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE, 0, 0, 0) < 0) { dev_err(fbi->device, "Error enabling auto refesh.\n"); } if (ipu_adc_set_update_mode (ADC_SYS2, IPU_ADC_AUTO_REFRESH_SNOOP, 30, fbi->fix.smem_start, &memsize) < 0) { dev_err(fbi->device, "Error enabling auto refesh.\n"); } mxc_fbi->snoop_window_size = memsize; ipu_init_channel_buffer(ADC_SYS2, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi->var.bits_per_pixel), 1, 1, 4, IPU_ROTATE_NONE, fbi->fix.smem_start, 0, 0, 0); params.adc_sys1.disp = mxc_fbi->disp_num; params.adc_sys1.ch_mode = WriteTemplateNonSeq; params.adc_sys1.out_left = MXCFB_SCREEN_LEFT_OFFSET; params.adc_sys1.out_top = MXCFB_SCREEN_TOP_OFFSET; ipu_init_channel(ADC_SYS1, ¶ms); ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi->var.bits_per_pixel), MXCFB_SCREEN_WIDTH, MXCFB_SCREEN_HEIGHT, stride_pixels, IPU_ROTATE_NONE, fbi->fix.smem_start, 0, 0, 0); ipu_enable_channel(ADC_SYS1); ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0); ipu_enable_irq(IPU_IRQ_ADC_SYS1_EOF); break; #endif case MXCFB_REFRESH_AUTO: if (update_region == NULL) { update_region = ▭ rect.top = 0; rect.left = 0; rect.height = MXCFB_SCREEN_HEIGHT; rect.width = MXCFB_SCREEN_WIDTH; } params.adc_sys1.disp = mxc_fbi->disp_num; params.adc_sys1.ch_mode = WriteTemplateNonSeq; params.adc_sys1.out_left = MXCFB_SCREEN_LEFT_OFFSET + update_region->left; params.adc_sys1.out_top = MXCFB_SCREEN_TOP_OFFSET + update_region->top; ipu_init_channel(ADC_SYS1, ¶ms); /* Address aligned to line */ start_addr = update_region->top * fbi->fix.line_length; start_addr += fbi->fix.smem_start; start_addr += update_region->left * fbi->var.bits_per_pixel / 8; ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi->var.bits_per_pixel), update_region->width, update_region->height, stride_pixels, IPU_ROTATE_NONE, start_addr, 0, 0, 0); ipu_enable_channel(ADC_SYS1); ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0); if (ipu_adc_set_update_mode (ADC_SYS1, IPU_ADC_AUTO_REFRESH_SNOOP, 30, fbi->fix.smem_start, &memsize) < 0) dev_err(fbi->device, "Error enabling auto refesh.\n"); mxc_fbi->snoop_window_size = memsize; break; } return ret_mode; }
/*! * CSI ENC enable channel setup function * * @param cam struct cam_data * mxc capture instance * * @return status */ static int csi_enc_setup(cam_data *cam) { ipu_channel_params_t params; u32 pixel_fmt; int err = 0, sensor_protocol = 0; dma_addr_t dummy = cam->dummy_frame.buffer.m.offset; #ifdef CONFIG_MXC_MIPI_CSI2 void *mipi_csi2_info; int ipu_id; int csi_id; #endif CAMERA_TRACE("In csi_enc_setup\n"); if (!cam) { printk(KERN_ERR "cam private is NULL\n"); return -ENXIO; } memset(¶ms, 0, sizeof(ipu_channel_params_t)); params.csi_mem.csi = cam->csi; sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); switch (sensor_protocol) { case IPU_CSI_CLK_MODE_GATED_CLK: case IPU_CSI_CLK_MODE_NONGATED_CLK: case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: params.csi_mem.interlaced = false; break; case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: params.csi_mem.interlaced = true; break; default: printk(KERN_ERR "sensor protocol unsupported\n"); return -EINVAL; } if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) pixel_fmt = IPU_PIX_FMT_YUV420P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) pixel_fmt = IPU_PIX_FMT_YUV422P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) pixel_fmt = IPU_PIX_FMT_UYVY; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) pixel_fmt = IPU_PIX_FMT_YUYV; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) pixel_fmt = IPU_PIX_FMT_NV12; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) pixel_fmt = IPU_PIX_FMT_BGR24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) pixel_fmt = IPU_PIX_FMT_RGB24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) pixel_fmt = IPU_PIX_FMT_RGB565; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) pixel_fmt = IPU_PIX_FMT_BGR32; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) pixel_fmt = IPU_PIX_FMT_RGB32; else { printk(KERN_ERR "format not supported\n"); return -EINVAL; } ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_ENC, cam->csi, true, true); #ifdef CONFIG_MXC_MIPI_CSI2 mipi_csi2_info = mipi_csi2_get_info(); ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); if (cam->ipu == ipu_get_soc(ipu_id) && cam->csi == csi_id) { params.csi_mem.mipi_en = true; params.csi_mem.mipi_vc = mipi_csi2_get_virtual_channel(mipi_csi2_info); params.csi_mem.mipi_id = mipi_csi2_get_datatype(mipi_csi2_info); mipi_csi2_pixelclk_enable(mipi_csi2_info); } #endif err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); if (err != 0) { printk(KERN_ERR "ipu_init_channel %d\n", err); return err; } err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, pixel_fmt, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height, cam->v2f.fmt.pix.width, IPU_ROTATE_NONE, dummy, dummy, 0, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printk(KERN_ERR "CSI_MEM output buffer\n"); return err; } err = ipu_enable_channel(cam->ipu, CSI_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); return err; } return err; }
/*! * PrpENC enable channel setup function * * @param cam struct cam_data * mxc capture instance * * @return status */ static int prp_enc_setup(cam_data *cam) { ipu_channel_params_t enc; int err = 0; dma_addr_t dummy = 0xdeadbeaf; CAMERA_TRACE("In prp_enc_setup\n"); if (!cam) { printk(KERN_ERR "cam private is NULL\n"); return -ENXIO; } memset(&enc, 0, sizeof(ipu_channel_params_t)); ipu_csi_get_window_size(&enc.csi_prp_enc_mem.in_width, &enc.csi_prp_enc_mem.in_height, cam->csi); enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width; enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height; enc.csi_prp_enc_mem.csi = cam->csi; if (cam->rotation >= IPU_ROTATE_90_RIGHT) { enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height; enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width; } if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P; pr_info("YUV420\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P; pr_info("YUV422P\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV; pr_info("YUYV\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY; pr_info("UYVY\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12; pr_info("NV12\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24; pr_info("BGR24\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24; pr_info("RGB24\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565; pr_info("RGB565\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32; pr_info("BGR32\n"); } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) { enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32; pr_info("RGB32\n"); } else { printk(KERN_ERR "format not supported\n"); return -EINVAL; } err = ipu_init_channel(CSI_PRP_ENC_MEM, &enc); if (err != 0) { printk(KERN_ERR "ipu_init_channel %d\n", err); return err; } ipu_csi_enable_mclk_if(CSI_MCLK_ENC, cam->csi, true, true); grotation = cam->rotation; if (cam->rotation >= IPU_ROTATE_90_RIGHT) { if (cam->rot_enc_bufs_vaddr[0]) { dma_free_coherent(0, cam->rot_enc_buf_size[0], cam->rot_enc_bufs_vaddr[0], cam->rot_enc_bufs[0]); } if (cam->rot_enc_bufs_vaddr[1]) { dma_free_coherent(0, cam->rot_enc_buf_size[1], cam->rot_enc_bufs_vaddr[1], cam->rot_enc_bufs[1]); } cam->rot_enc_buf_size[0] = PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); cam->rot_enc_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0], &cam->rot_enc_bufs[0], GFP_DMA | GFP_KERNEL); if (!cam->rot_enc_bufs_vaddr[0]) { printk(KERN_ERR "alloc enc_bufs0\n"); return -ENOMEM; } cam->rot_enc_buf_size[1] = PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); cam->rot_enc_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1], &cam->rot_enc_bufs[1], GFP_DMA | GFP_KERNEL); if (!cam->rot_enc_bufs_vaddr[1]) { dma_free_coherent(0, cam->rot_enc_buf_size[0], cam->rot_enc_bufs_vaddr[0], cam->rot_enc_bufs[0]); cam->rot_enc_bufs_vaddr[0] = NULL; cam->rot_enc_bufs[0] = 0; printk(KERN_ERR "alloc enc_bufs1\n"); return -ENOMEM; } err = ipu_init_channel_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_width, enc.csi_prp_enc_mem.out_height, enc.csi_prp_enc_mem.out_width, IPU_ROTATE_NONE, cam->rot_enc_bufs[0], cam->rot_enc_bufs[1], 0, 0, 0); if (err != 0) { printk(KERN_ERR "CSI_PRP_ENC_MEM err\n"); return err; } err = ipu_init_channel(MEM_ROT_ENC_MEM, NULL); if (err != 0) { printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n"); return err; } err = ipu_init_channel_buffer(MEM_ROT_ENC_MEM, IPU_INPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_width, enc.csi_prp_enc_mem.out_height, enc.csi_prp_enc_mem.out_width, cam->rotation, cam->rot_enc_bufs[0], cam->rot_enc_bufs[1], 0, 0, 0); if (err != 0) { printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n"); return err; } err = ipu_init_channel_buffer(MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_height, enc.csi_prp_enc_mem.out_width, cam->v2f.fmt.pix.bytesperline / bytes_per_pixel(enc.csi_prp_enc_mem. out_pixel_fmt), IPU_ROTATE_NONE, dummy, dummy, 0, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n"); return err; } err = ipu_link_channels(CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM); if (err < 0) { printk(KERN_ERR "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n"); return err; } err = ipu_enable_channel(CSI_PRP_ENC_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); return err; } err = ipu_enable_channel(MEM_ROT_ENC_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n"); return err; } ipu_select_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 0); ipu_select_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 1); } else { err = ipu_init_channel_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, enc.csi_prp_enc_mem.out_pixel_fmt, enc.csi_prp_enc_mem.out_width, enc.csi_prp_enc_mem.out_height, cam->v2f.fmt.pix.bytesperline / bytes_per_pixel(enc.csi_prp_enc_mem. out_pixel_fmt), cam->rotation, dummy, dummy, 0, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n"); return err; } err = ipu_enable_channel(CSI_PRP_ENC_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); return err; } } return err; }
static irqreturn_t mxcfb_sys2_eof_irq_handler(int irq, void *dev_id) { ipu_channel_params_t params; struct fb_info *fbi = dev_id; struct mxcfb_info *mxc_fbi = fbi->par; uint32_t stat[2], seg_size; uint32_t lsb, msb; uint32_t update_height, start_line, start_addr, end_line, end_addr; uint32_t stride_pixels = (fbi->fix.line_length * 8) / fbi->var.bits_per_pixel; ipu_adc_get_snooping_status(&stat[0], &stat[1]); if (!stat[0] && !stat[1]) { dev_err(fbi->device, "error no bus snooping bits set\n"); return IRQ_HANDLED; } ipu_disable_irq(IPU_IRQ_ADC_SYS2_EOF); lsb = ffs(stat[0]); if (lsb) { lsb--; } else { lsb = ffs(stat[1]); lsb += 32 - 1; } msb = fls(stat[1]); if (msb) { msb += 32; } else { msb = fls(stat[0]); } seg_size = mxc_fbi->snoop_window_size / 64; start_addr = lsb * seg_size; /* starting address offset */ start_line = start_addr / fbi->fix.line_length; start_addr = start_line * fbi->fix.line_length; /* Addr aligned to line */ start_addr += fbi->fix.smem_start; end_addr = msb * seg_size; /* ending address offset */ end_line = end_addr / fbi->fix.line_length; end_line++; if (end_line > fbi->var.yres) { end_line = fbi->var.yres; } update_height = end_line - start_line; dev_dbg(fbi->device, "updating rows %d to %d, start addr = 0x%08X\n", start_line, end_line, start_addr); ipu_uninit_channel(ADC_SYS1); params.adc_sys1.disp = mxc_fbi->disp_num; params.adc_sys1.ch_mode = WriteTemplateNonSeq; params.adc_sys1.out_left = MXCFB_SCREEN_LEFT_OFFSET; params.adc_sys1.out_top = start_line; ipu_init_channel(ADC_SYS1, ¶ms); ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi->var.bits_per_pixel), MXCFB_SCREEN_WIDTH, update_height, stride_pixels, IPU_ROTATE_NONE, (dma_addr_t) start_addr, 0, 0, 0); ipu_enable_channel(ADC_SYS1); ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0); ipu_enable_irq(IPU_IRQ_ADC_SYS1_EOF); return IRQ_HANDLED; }
static int mxc_ipu_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; switch (cmd) { case IPU_INIT_CHANNEL: { ipu_channel_parm parm; if (copy_from_user (&parm, (ipu_channel_parm *) arg, sizeof(ipu_channel_parm))) return -EFAULT; if (!parm.flag) { ret = ipu_init_channel(parm.channel, &parm.params); } else { ret = ipu_init_channel(parm.channel, NULL); } } break; case IPU_UNINIT_CHANNEL: { ipu_channel_t ch; int __user *argp = (void __user *)arg; if (get_user(ch, argp)) return -EFAULT; ipu_uninit_channel(ch); } break; case IPU_INIT_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) return -EFAULT; ret = ipu_init_channel_buffer( parm.channel, parm.type, parm.pixel_fmt, parm.width, parm.height, parm.stride, parm.rot_mode, parm.phyaddr_0, parm.phyaddr_1, parm.u_offset, parm.v_offset); } break; case IPU_UPDATE_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) return -EFAULT; if ((parm.phyaddr_0 != (dma_addr_t) NULL) && (parm.phyaddr_1 == (dma_addr_t) NULL)) { ret = ipu_update_channel_buffer( parm.channel, parm.type, parm.bufNum, parm.phyaddr_0); } else if ((parm.phyaddr_0 == (dma_addr_t) NULL) && (parm.phyaddr_1 != (dma_addr_t) NULL)) { ret = ipu_update_channel_buffer( parm.channel, parm.type, parm.bufNum, parm.phyaddr_1); } else { ret = -1; } } break; case IPU_SELECT_CHANNEL_BUFFER: { ipu_channel_buf_parm parm; if (copy_from_user (&parm, (ipu_channel_buf_parm *) arg, sizeof(ipu_channel_buf_parm))) return -EFAULT; ret = ipu_select_buffer(parm.channel, parm.type, parm.bufNum); } break; case IPU_LINK_CHANNELS: { ipu_channel_link link; if (copy_from_user (&link, (ipu_channel_link *) arg, sizeof(ipu_channel_link))) return -EFAULT; ret = ipu_link_channels(link.src_ch, link.dest_ch); } break; case IPU_UNLINK_CHANNELS: { ipu_channel_link link; if (copy_from_user (&link, (ipu_channel_link *) arg, sizeof(ipu_channel_link))) return -EFAULT; ret = ipu_unlink_channels(link.src_ch, link.dest_ch); } break; case IPU_ENABLE_CHANNEL: { ipu_channel_t ch; int __user *argp = (void __user *)arg; if (get_user(ch, argp)) return -EFAULT; ipu_enable_channel(ch); } break; case IPU_DISABLE_CHANNEL: { ipu_channel_info info; if (copy_from_user (&info, (ipu_channel_info *) arg, sizeof(ipu_channel_info))) return -EFAULT; ret = ipu_disable_channel(info.channel, info.stop); } break; case IPU_ENABLE_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_enable_irq(irq); } break; case IPU_DISABLE_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_disable_irq(irq); } break; case IPU_CLEAR_IRQ: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ipu_clear_irq(irq); } break; case IPU_FREE_IRQ: { ipu_irq_info info; int i; if (copy_from_user (&info, (ipu_irq_info *) arg, sizeof(ipu_irq_info))) return -EFAULT; ipu_free_irq(info.irq, info.dev_id); for (i = 0; i < MAX_Q_SIZE; i++) { if (events[i].irq == info.irq) events[i].irq = 0; } } break; case IPU_REQUEST_IRQ_STATUS: { uint32_t irq; int __user *argp = (void __user *)arg; if (get_user(irq, argp)) return -EFAULT; ret = ipu_get_irq_status(irq); } break; case IPU_REGISTER_GENERIC_ISR: { ipu_event_info info; if (copy_from_user (&info, (ipu_event_info *) arg, sizeof(ipu_event_info))) return -EFAULT; ret = ipu_request_irq(info.irq, mxc_ipu_generic_handler, 0, "video_sink", info.dev); } break; case IPU_GET_EVENT: /* User will have to allocate event_type structure and pass the pointer in arg */ { ipu_event_info info; int r = -1; if (copy_from_user (&info, (ipu_event_info *) arg, sizeof(ipu_event_info))) return -EFAULT; r = get_events(&info); if (r == -1) { wait_event_interruptible_timeout(waitq, (pending_events != 0), HZ/10); r = get_events(&info); } ret = -1; if (r == 0) { if (!copy_to_user((ipu_event_info *) arg, &info, sizeof(ipu_event_info))) ret = 0; } } break; case IPU_ALOC_MEM: { ipu_mem_info info; if (copy_from_user (&info, (ipu_mem_info *) arg, sizeof(ipu_mem_info))) return -EFAULT; info.vaddr = dma_alloc_coherent(0, PAGE_ALIGN(info.size), &info.paddr, GFP_DMA | GFP_KERNEL); if (info.vaddr == 0) { printk(KERN_ERR "dma alloc failed!\n"); return -ENOBUFS; } if (copy_to_user((ipu_mem_info *) arg, &info, sizeof(ipu_mem_info)) > 0) return -EFAULT; } break; case IPU_FREE_MEM: { ipu_mem_info info; if (copy_from_user (&info, (ipu_mem_info *) arg, sizeof(ipu_mem_info))) return -EFAULT; if (info.vaddr) dma_free_coherent(0, PAGE_ALIGN(info.size), info.vaddr, info.paddr); else return -EFAULT; } break; case IPU_IS_CHAN_BUSY: { ipu_channel_t chan; if (copy_from_user (&chan, (ipu_channel_t *)arg, sizeof(ipu_channel_t))) return -EFAULT; if (ipu_is_channel_busy(chan)) ret = 1; else ret = 0; } break; default: break; } return ret; }
static int csi_enc_setup(cam_data *cam) { ipu_channel_params_t params; int err = 0, sensor_protocol = 0; #ifdef CONFIG_MXC_MIPI_CSI2 void *mipi_csi2_info; int ipu_id; int csi_id; #endif CAMERA_TRACE("In csi_enc_setup\n"); if (!cam) { printk(KERN_ERR "cam private is NULL\n"); return -ENXIO; } memset(¶ms, 0, sizeof(ipu_channel_params_t)); params.csi_mem.csi = cam->csi; sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); switch (sensor_protocol) { case IPU_CSI_CLK_MODE_GATED_CLK: case IPU_CSI_CLK_MODE_NONGATED_CLK: case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: params.csi_mem.interlaced = false; break; case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: params.csi_mem.interlaced = true; break; default: printk(KERN_ERR "sensor protocol unsupported\n"); return -EINVAL; } #ifdef CONFIG_MXC_MIPI_CSI2 mipi_csi2_info = mipi_csi2_get_info(); if (mipi_csi2_info) { if (mipi_csi2_get_status(mipi_csi2_info)) { ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); if (cam->ipu == ipu_get_soc(ipu_id) && cam->csi == csi_id) { params.csi_mem.mipi_en = true; params.csi_mem.mipi_vc = mipi_csi2_get_virtual_channel(mipi_csi2_info); params.csi_mem.mipi_id = mipi_csi2_get_datatype(mipi_csi2_info); mipi_csi2_pixelclk_enable(mipi_csi2_info); } else { params.csi_mem.mipi_en = false; params.csi_mem.mipi_vc = 0; params.csi_mem.mipi_id = 0; } } else { params.csi_mem.mipi_en = false; params.csi_mem.mipi_vc = 0; params.csi_mem.mipi_id = 0; } } #endif if (cam->vf_bufs_vaddr[0]) { dma_free_coherent(0, cam->vf_bufs_size[0], cam->vf_bufs_vaddr[0], (dma_addr_t) cam->vf_bufs[0]); } if (cam->vf_bufs_vaddr[1]) { dma_free_coherent(0, cam->vf_bufs_size[1], cam->vf_bufs_vaddr[1], (dma_addr_t) cam->vf_bufs[1]); } csi_mem_bufsize = cam->crop_current.width * cam->crop_current.height * 3/2; cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize); cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, cam->vf_bufs_size[0], (dma_addr_t *) & cam->vf_bufs[0], GFP_DMA | GFP_KERNEL); if (cam->vf_bufs_vaddr[0] == NULL) { printk(KERN_ERR "Error to allocate vf buffer\n"); err = -ENOMEM; goto out_2; } cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize); cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, cam->vf_bufs_size[1], (dma_addr_t *) & cam->vf_bufs[1], GFP_DMA | GFP_KERNEL); if (cam->vf_bufs_vaddr[1] == NULL) { printk(KERN_ERR "Error to allocate vf buffer\n"); err = -ENOMEM; goto out_1; } pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]); err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); if (err != 0) { printk(KERN_ERR "ipu_init_channel %d\n", err); goto out_1; } if ((cam->crop_current.width == cam->win.w.width) && (cam->crop_current.height == cam->win.w.height) && (vf_out_format == IPU_PIX_FMT_NV12) && (cam->rotation < IPU_ROTATE_VERT_FLIP)) { err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, IPU_PIX_FMT_NV12, cam->crop_current.width, cam->crop_current.height, cam->crop_current.width, IPU_ROTATE_NONE, fbi->fix.smem_start + (fbi->fix.line_length * fbvar.yres), fbi->fix.smem_start, 0, cam->offset.u_offset, cam->offset.u_offset); } else { err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, IPU_PIX_FMT_NV12, cam->crop_current.width, cam->crop_current.height, cam->crop_current.width, IPU_ROTATE_NONE, cam->vf_bufs[0], cam->vf_bufs[1], 0, cam->offset.u_offset, cam->offset.u_offset); } if (err != 0) { printk(KERN_ERR "CSI_MEM output buffer\n"); goto out_1; } err = ipu_enable_channel(cam->ipu, CSI_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); goto out_1; } csi_buffer_num = 0; ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0); ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1); return err; out_1: if (cam->vf_bufs_vaddr[0]) { dma_free_coherent(0, cam->vf_bufs_size[0], cam->vf_bufs_vaddr[0], (dma_addr_t) cam->vf_bufs[0]); cam->vf_bufs_vaddr[0] = NULL; cam->vf_bufs[0] = 0; } if (cam->vf_bufs_vaddr[1]) { dma_free_coherent(0, cam->vf_bufs_size[1], cam->vf_bufs_vaddr[1], (dma_addr_t) cam->vf_bufs[1]); cam->vf_bufs_vaddr[1] = NULL; cam->vf_bufs[1] = 0; } out_2: return err; }
/*! * CSI ENC enable channel setup function * * @param cam struct cam_data * mxc capture instance * * @return status */ static int csi_enc_setup(cam_data *cam) { ipu_channel_params_t params; u32 pixel_fmt; int err = 0, sensor_protocol = 0; dma_addr_t dummy = cam->dummy_frame.buffer.m.offset; CAMERA_TRACE("In csi_enc_setup\n"); if (!cam) { printk(KERN_ERR "cam private is NULL\n"); return -ENXIO; } memset(¶ms, 0, sizeof(ipu_channel_params_t)); params.csi_mem.csi = cam->csi; sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); switch (sensor_protocol) { case IPU_CSI_CLK_MODE_GATED_CLK: case IPU_CSI_CLK_MODE_NONGATED_CLK: case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: params.csi_mem.interlaced = false; break; case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: params.csi_mem.interlaced = true; break; default: printk(KERN_ERR "sensor protocol unsupported\n"); return -EINVAL; } if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) pixel_fmt = IPU_PIX_FMT_YUV420P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) pixel_fmt = IPU_PIX_FMT_YVU420P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) pixel_fmt = IPU_PIX_FMT_YUV422P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) pixel_fmt = IPU_PIX_FMT_UYVY; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) pixel_fmt = IPU_PIX_FMT_YUYV; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) pixel_fmt = IPU_PIX_FMT_NV12; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) pixel_fmt = IPU_PIX_FMT_BGR24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) pixel_fmt = IPU_PIX_FMT_RGB24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) pixel_fmt = IPU_PIX_FMT_RGB565; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) pixel_fmt = IPU_PIX_FMT_BGR32; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) pixel_fmt = IPU_PIX_FMT_RGB32; else { printk(KERN_ERR "format not supported\n"); return -EINVAL; } err = cam_mipi_csi2_enable(cam, ¶ms.csi_mem.mipi); if (err) return err; err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); if (err != 0) { printk(KERN_ERR "ipu_init_channel %d\n", err); return err; } err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, pixel_fmt, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height, cam->v2f.fmt.pix.bytesperline, cam->rotation, dummy, dummy, 0, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printk(KERN_ERR "CSI_MEM output buffer\n"); return err; } err = ipu_enable_channel(cam->ipu, CSI_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); return err; } return err; }
/*! * CSI ENC enable channel setup function * * @param cam struct cam_data * mxc capture instance * * @return status */ static int csi_enc_setup(cam_data *cam) { ipu_channel_params_t params; u32 pixel_fmt; int err = 0, sensor_protocol = 0; dma_addr_t dummy0 = 0x97BBB800; dma_addr_t dummy1 = 0x97B00000; if (!cam) { printf("cam private is NULL\n"); return -ENXIO; } //printf("csi_enc_setup\n"); memset(¶ms, 0, sizeof(ipu_channel_params_t)); params.csi_mem.csi = cam->csi; sensor_protocol = ipu_csi_get_sensor_protocol(cam->csi); // printf("csi_enc_setup: sensor_protocol: %d, pixelformat: 0x%x\n", sensor_protocol, cam->v2f.fmt.pix.pixelformat); switch (sensor_protocol) { case IPU_CSI_CLK_MODE_GATED_CLK: case IPU_CSI_CLK_MODE_NONGATED_CLK: case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: params.csi_mem.interlaced = 0; break; case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: params.csi_mem.interlaced = 1; break; default: printf("sensor protocol unsupported\n"); return -EINVAL; } if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) pixel_fmt = IPU_PIX_FMT_YUV420P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) pixel_fmt = IPU_PIX_FMT_YUV422P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) pixel_fmt = IPU_PIX_FMT_UYVY; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) pixel_fmt = IPU_PIX_FMT_YUYV; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) pixel_fmt = IPU_PIX_FMT_NV12; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) pixel_fmt = IPU_PIX_FMT_BGR24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) pixel_fmt = IPU_PIX_FMT_RGB24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) pixel_fmt = IPU_PIX_FMT_RGB565; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) pixel_fmt = IPU_PIX_FMT_BGR32; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) pixel_fmt = IPU_PIX_FMT_RGB32; else if(cam->v2f.fmt.pix.pixelformat == IPU_PIX_FMT_GENERIC) pixel_fmt = IPU_PIX_FMT_GENERIC; else { printf("format not supported\n"); return -EINVAL; } ipu_csi_enable_mclk(cam->csi, 1, 1); err = ipu_init_channel(CSI_MEM, ¶ms); if (err != 0) { printf("ipu_init_channel %d\n", err); return err; } // printf("csi_enc_setup -> ipu_init_channel_buffer \n"); err = ipu_init_channel_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, pixel_fmt, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height, cam->v2f.fmt.pix.width, dummy1, 0, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printf("CSI_MEM output buffer\n"); return err; } err = ipu_enable_channel(CSI_MEM); if (err < 0) { printf("ipu_enable_channel CSI_MEM\n"); return err; } return err; }
static void mxcfb_update_region(struct fb_info *fbi, uint32_t statl, uint32_t stath) { ipu_channel_params_t params; struct mxcfb_info *mxc_fbi = fbi->par; uint32_t seg_size; uint32_t lsb, msb; uint32_t update_height, start_line, start_addr, end_line, end_addr; uint32_t stride_pixels = (fbi->fix.line_length * 8) / fbi->var.bits_per_pixel; lsb = ffs(statl); if (lsb) { lsb--; } else { lsb = ffs(stath); lsb += 32 - 1; } msb = fls(stath); if (msb) { msb += 32; } else { msb = fls(statl); } seg_size = mxc_fbi->snoop_window_size / 64; start_addr = lsb * seg_size; // starting address offset start_line = start_addr / fbi->fix.line_length; start_addr = start_line * fbi->fix.line_length; // Addr aligned to line start_addr += fbi->fix.smem_start; end_addr = msb * seg_size; // ending address offset end_line = end_addr / fbi->fix.line_length; end_line++; if (end_line > fbi->var.yres) { end_line = fbi->var.yres; } update_height = end_line - start_line; dev_dbg(fbi->device, "updating rows %d to %d, start addr = 0x%08X\n", start_line, end_line, start_addr); ipu_uninit_channel(ADC_SYS1); params.adc_sys1.disp = mxc_fbi->disp_num; params.adc_sys1.ch_mode = WriteTemplateNonSeq; params.adc_sys1.out_left = MXCFB_SCREEN_LEFT_OFFSET; params.adc_sys1.out_top = start_line; ipu_init_channel(ADC_SYS1, ¶ms); ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi->var.bits_per_pixel), MXCFB_SCREEN_WIDTH, update_height, stride_pixels, IPU_ROTATE_NONE, (dma_addr_t) start_addr, 0, 0, 0); ipu_enable_channel(ADC_SYS1); ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0); ipu_enable_irq(IPU_IRQ_ADC_SYS1_EOF); }
/*! * CSI ENC enable channel setup function * * @param cam struct cam_data * mxc capture instance * * @return status */ static int csi_enc_setup(cam_data *cam) { ipu_channel_params_t params; u32 pixel_fmt; int err = 0; dma_addr_t dummy = 0xdeadbeaf; CAMERA_TRACE("In csi_enc_setup\n"); if (!cam) { printk(KERN_ERR "cam private is NULL\n"); return -ENXIO; } memset(¶ms, 0, sizeof(ipu_channel_params_t)); params.csi_mem.csi = cam->csi; if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) pixel_fmt = IPU_PIX_FMT_YUV420P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) pixel_fmt = IPU_PIX_FMT_YUV422P; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) pixel_fmt = IPU_PIX_FMT_UYVY; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) pixel_fmt = IPU_PIX_FMT_NV12; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) pixel_fmt = IPU_PIX_FMT_BGR24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) pixel_fmt = IPU_PIX_FMT_RGB24; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) pixel_fmt = IPU_PIX_FMT_RGB565; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) pixel_fmt = IPU_PIX_FMT_BGR32; else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) pixel_fmt = IPU_PIX_FMT_RGB32; else { printk(KERN_ERR "format not supported\n"); return -EINVAL; } ipu_csi_enable_mclk_if(CSI_MCLK_ENC, cam->csi, true, true); err = ipu_init_channel(CSI_MEM, ¶ms); if (err != 0) { printk(KERN_ERR "ipu_init_channel %d\n", err); return err; } err = ipu_init_channel_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, pixel_fmt, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height, cam->v2f.fmt.pix.width, IPU_ROTATE_NONE, dummy, dummy, cam->offset.u_offset, cam->offset.v_offset); if (err != 0) { printk(KERN_ERR "CSI_MEM output buffer\n"); return err; } err = ipu_enable_channel(CSI_MEM); if (err < 0) { printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); return err; } return err; }
/*! * This function handles PP_IOCTL_INIT calls. It initializes the PP channels, * interrupt handlers, and channel buffers. * * @return This function returns 0 on success or negative error code on error */ static int mxc_pp_init(pp_init_params * pp_init) { ipu_channel_params_t params; int err = 0; FUNC_START; memset(¶ms, 0, sizeof(params)); pp_data.mode = pp_init->mode; pp_data.in_stride = pp_init->in_stride; pp_data.out_stride = pp_init->out_stride; if(pp_data.mode <= PP_PP_ROT) { pp_data.rot = (ipu_rotate_mode_t)pp_init->rot; if(pp_data.mode == PP_PP_ROT) pp_data.mid_stride = pp_init->mid_stride; } pp_data.in_width = pp_init->in_width; pp_data.in_height = pp_init->in_height; pp_data.in_pixel_fmt = pp_init->in_pixel_fmt; pp_data.out_width = pp_init->out_width; pp_data.out_height = pp_init->out_height; pp_data.out_pixel_fmt = pp_init->out_pixel_fmt; if(pp_data.mode >= PP_PP_ROT) { pp_data.ic_combine_en = pp_init->ic_combine_en; params.mem_pp_mem.graphics_combine_en = (bool)pp_data.ic_combine_en; } if(pp_data.ic_combine_en != 0) { pp_data.in_comb_width = pp_init->in_comb_width; pp_data.in_comb_height = pp_init->in_comb_height; pp_data.in_comb_stride = pp_init->in_comb_stride; pp_data.in_comb_pixel_fmt = pp_init->in_comb_pixel_fmt; } /* ipu_unlink_channels(MEM_PP_MEM, MEM_ROT_PP_MEM); */ if(pp_data.mode == PP_PP) { params.mem_pp_mem.in_width = pp_data.in_width; params.mem_pp_mem.in_height = pp_data.in_height; params.mem_pp_mem.in_pixel_fmt = pp_data.in_pixel_fmt; params.mem_pp_mem.out_width = pp_data.out_width; params.mem_pp_mem.out_height = pp_data.out_height; params.mem_pp_mem.out_pixel_fmt = pp_data.out_pixel_fmt; err = ipu_init_channel(MEM_PP_MEM, ¶ms); if(err < 0) { printk("mxc_ipu_pp: error initializing MEM_PP_MEM channel\n"); goto err0; } err = ipu_init_channel_buffer(MEM_PP_MEM, IPU_INPUT_BUFFER, pp_data.in_pixel_fmt, pp_data.in_width, pp_data.in_height, pp_data.in_stride, IPU_ROTATE_NONE, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing PP input buffer\n"); goto err0; } err = ipu_init_channel_buffer(MEM_PP_MEM, IPU_OUTPUT_BUFFER, pp_data.out_pixel_fmt, pp_data.out_width, pp_data.out_height, pp_data.out_stride, IPU_ROTATE_NONE, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing PP output buffer\n"); goto err0; } if(pp_data.ic_combine_en != 0) { err = ipu_init_channel_buffer(MEM_PP_MEM, IPU_SEC_INPUT_BUFFER, pp_data.in_comb_pixel_fmt, pp_data.in_comb_width, pp_data.in_comb_height, pp_data.in_comb_stride, IPU_ROTATE_NONE, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing PP second input buffer\n"); goto err0; } } } else if(pp_data.mode == PP_ROT) { err = ipu_init_channel(MEM_ROT_PP_MEM, ¶ms); if(err < 0) { printk("mxc_ipu_pp: error initializing MEM_ROT_PP_MEM channel\n"); goto err0; } err = ipu_init_channel_buffer(MEM_ROT_PP_MEM, IPU_INPUT_BUFFER, pp_data.in_pixel_fmt, pp_data.in_width, pp_data.in_height, pp_data.in_stride, pp_data.rot, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing ROT input buffer\n"); goto err0; } err = ipu_init_channel_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, pp_data.out_pixel_fmt, pp_data.out_width, pp_data.out_height, pp_data.out_stride, IPU_ROTATE_NONE, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing ROT output buffer\n"); goto err0; } } else if(pp_data.mode == PP_PP_ROT) { err = ipu_init_channel(MEM_ROT_PP_MEM, ¶ms); if(err < 0) { printk("mxc_ipu_pp: error initializing MEM_ROT_PP_MEM channel\n"); goto err0; } params.mem_pp_mem.in_width = pp_data.in_width; params.mem_pp_mem.in_height = pp_data.in_height; params.mem_pp_mem.in_pixel_fmt = pp_data.in_pixel_fmt; if(pp_data.rot >= IPU_ROTATE_90_RIGHT) { params.mem_pp_mem.out_width = pp_data.out_height; params.mem_pp_mem.out_height = pp_data.out_width; } else { params.mem_pp_mem.out_width = pp_data.out_width; params.mem_pp_mem.out_height = pp_data.out_height; } params.mem_pp_mem.out_pixel_fmt = pp_data.out_pixel_fmt; err = ipu_init_channel(MEM_PP_MEM, ¶ms); if(err < 0) { printk("mxc_ipu_pp: error initializing MEM_PP_MEM channel\n"); goto err0; } /* err = ipu_link_channels(MEM_PP_MEM, MEM_ROT_PP_MEM); */ if(err < 0) { printk("mxc_ipu_pp: error linking MEM_PP_MEM to MEM_ROT_PP_MEM\n"); goto err0; } err = ipu_init_channel_buffer(MEM_PP_MEM, IPU_INPUT_BUFFER, pp_data.in_pixel_fmt, pp_data.in_width, pp_data.in_height, pp_data.in_stride, IPU_ROTATE_NONE, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing PP_PP_ROT input buffer\n"); goto err0; } if(pp_data.rot >= IPU_ROTATE_90_RIGHT) { err = ipu_init_channel_buffer(MEM_PP_MEM, IPU_OUTPUT_BUFFER, pp_data.out_pixel_fmt, pp_data.out_height, pp_data.out_width, pp_data.mid_stride, IPU_ROTATE_NONE, NULL, NULL); } else { err = ipu_init_channel_buffer(MEM_PP_MEM, IPU_OUTPUT_BUFFER, pp_data.out_pixel_fmt, pp_data.out_width, pp_data.out_height, pp_data.out_stride, IPU_ROTATE_NONE, NULL, NULL); } if(err < 0) { printk("mxc_ipu_pp: error initializing PP_PP_ROT middle output buffer\n"); goto err0; } if(pp_data.ic_combine_en != 0) { err = ipu_init_channel_buffer(MEM_PP_MEM, IPU_SEC_INPUT_BUFFER, pp_data.in_comb_pixel_fmt, pp_data.in_comb_width, pp_data.in_comb_height, pp_data.in_comb_stride, IPU_ROTATE_NONE, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing PP second input buffer\n"); goto err0; } } if(pp_data.rot >= IPU_ROTATE_90_RIGHT) { err = ipu_init_channel_buffer(MEM_ROT_PP_MEM, IPU_INPUT_BUFFER, pp_data.out_pixel_fmt, pp_data.out_height, pp_data.out_width, pp_data.mid_stride, pp_data.rot, NULL, NULL); } else { err = ipu_init_channel_buffer(MEM_ROT_PP_MEM, IPU_INPUT_BUFFER, pp_data.out_pixel_fmt, pp_data.out_width, pp_data.out_height, pp_data.out_stride, pp_data.rot, NULL, NULL); } if(err < 0) { printk("mxc_ipu_pp: error initializing ROT input buffer\n"); goto err0; } err = ipu_init_channel_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, pp_data.out_pixel_fmt, pp_data.out_width, pp_data.out_height, pp_data.out_stride, IPU_ROTATE_NONE, NULL, NULL); if(err < 0) { printk("mxc_ipu_pp: error initializing ROT output buffer\n"); goto err0; } } FUNC_END; return 0; err0: return err; }