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; }
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; }
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; }
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; }