diff --git a/drivers/video/compression/npcm750_ece.c b/drivers/video/compression/npcm750_ece.c index 29a7df7883d3e0..c017303012b329 100644 --- a/drivers/video/compression/npcm750_ece.c +++ b/drivers/video/compression/npcm750_ece.c @@ -38,7 +38,10 @@ #define HEX_CTRL 0x0040 #define HEX_RECT_OFFSET 0x0048 -#define CDREADY 0x100 +#define FIFOSTSI 0x003 +#define FIFOSTSE 0x030 +#define ACDREADY BIT(10) +#define CDREADY BIT(8) #define ENC_GAP 0x1f00 #define ENC_GAP_OFFSET 8 #define ENC_MIN_GAP_SIZE 4 @@ -67,6 +70,14 @@ #define ECE_TILE_W 16 #define ECE_TILE_H 16 +#define ECE_IOC_MAGIC 'k' +#define ECE_IOCGETED _IOR(ECE_IOC_MAGIC, 1, struct ece_ioctl_cmd) +#define ECE_IOCSETFB _IOW(ECE_IOC_MAGIC, 2, struct ece_ioctl_cmd) +#define ECE_IOCSETLP _IOW(ECE_IOC_MAGIC, 3, struct ece_ioctl_cmd) +#define ECE_IOCGET_OFFSET _IOR(ECE_IOC_MAGIC, 4, u32) +#define ECE_IOCCLEAR_OFFSET _IO(ECE_IOC_MAGIC, 5) +#define ECE_IOC_MAXNR 5 + struct ece_ioctl_cmd { unsigned int framebuf; unsigned int gap_len; @@ -79,12 +90,6 @@ struct ece_ioctl_cmd { int lp; }; -#define ECE_IOC_MAGIC 'k' -#define ECE_IOCGETED _IOR(ECE_IOC_MAGIC, 1, struct ece_ioctl_cmd) -#define ECE_IOCSETFB _IOW(ECE_IOC_MAGIC, 2, struct ece_ioctl_cmd) -#define ECE_IOCSETLP _IOW(ECE_IOC_MAGIC, 3, struct ece_ioctl_cmd) -#define ECE_IOC_MAXNR 3 - struct npcm750_ece { struct mutex mlock; /* protect ioctl*/ struct device *dev; @@ -92,171 +97,79 @@ struct npcm750_ece { struct cdev *dev_cdevp; struct class *ece_class; dev_t dev_t; - void __iomem *ece_base_addr; + void __iomem *base_addr; char __iomem *ed_buffer; u32 smem_len; u32 smem_start; - u32 width; - u32 height; u32 lin_pitch; u32 enc_gap; - int initialised; }; -static u32 ece_set_fb_addr(struct npcm750_ece *ece, u32 buffer); -static u32 ece_is_rect_compressed(struct npcm750_ece *ece); -static u32 ece_get_ed_size(struct npcm750_ece *ece); -static void ece_clear_rect_offset(struct npcm750_ece *ece); -static void ece_enc_rect(struct npcm750_ece *ece, - u32 r_off_x, u32 r_off_y, u32 r_w, u32 r_h); -static void ece_clear_drs(struct npcm750_ece *ece); -static void ece_set_lp(struct npcm750_ece *ece, u32 pitch); -static u32 ece_set_enc_dba(struct npcm750_ece *ece); +struct npcm750_ece *registered_ece; -static int -drv_mmap(struct file *file, struct vm_area_struct *vma) +static void update_bits(struct npcm750_ece *ece, u32 offset, + unsigned long mask, u32 bits) { - struct npcm750_ece *ece = file->private_data; - unsigned long start; - u32 len; - - if (!ece) - return -ENODEV; - - start = ece->smem_start; - len = ece->smem_len; + u32 t = readl(ece->base_addr + offset); - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - fb_pgprotect(file, vma, start); - return vm_iomap_memory(vma, start, len); + t &= ~mask; + t |= bits & mask; + writel(t, ece->base_addr + offset); } -struct npcm750_ece *registered_ece; - -static int drv_open(struct inode *inode, struct file *filp) +/* Rectangle Compressed Data Ready */ +static void +ece_clear_drs(struct npcm750_ece *ece) { - if (!registered_ece) - return -ENODEV; - - filp->private_data = registered_ece; - - return 0; + update_bits(ece, DDA_STS, CDREADY, CDREADY); } -long drv_ioctl(struct file *filp, unsigned int cmd, unsigned long args) +/* Clear Offset of Compressed Rectangle*/ +static void ece_clear_rect_offset(struct npcm750_ece *ece) { - int err = 0; - struct ece_ioctl_cmd data; - struct npcm750_ece *ece = filp->private_data; - - mutex_lock(&ece->mlock); - memset(&data, 0, sizeof(data)); - - err = copy_from_user(&data, (int __user *)args, sizeof(data)) - ? -EFAULT : 0; - if (err) { - mutex_unlock(&ece->mlock); - return err; - } - - switch (cmd) { - case ECE_IOCSETLP: - if (!(data.lp % ECE_MIN_LP) && data.lp <= ECE_MAX_LP) - ece_set_lp(ece, data.lp); - - if (data.w != ece->width || data.h != ece->height) { - ece->width = data.w; - ece->height = data.h; - ece_set_enc_dba(ece); - } - break; - case ECE_IOCSETFB: - if (!data.framebuf) { - err = -EFAULT; - break; - } - ece_set_fb_addr(ece, data.framebuf); - break; - case ECE_IOCGETED: - { - u32 ed_size = 0; - - ece_enc_rect(ece, data.x, data.y, data.w, data.h); - ed_size = ece_get_ed_size(ece); - ece_clear_rect_offset(ece); - - ece->enc_gap = - (readl(ece->ece_base_addr + HEX_CTRL) & ENC_GAP) - >> ENC_GAP_OFFSET; - - if (ece->enc_gap == 0) - ece->enc_gap = ENC_MIN_GAP_SIZE; - - data.gap_len = ece->enc_gap; - data.len = ed_size; - err = copy_to_user((int __user *)args, &data, sizeof(data)) - ? -EFAULT : 0; - break; - } - default: - break; - } - - mutex_unlock(&ece->mlock); - - return err; + writel(0, ece->base_addr + HEX_RECT_OFFSET); } -static int drv_release(struct inode *inode, struct file *filp) +/* Read Offset of Compressed Rectangle*/ +static u32 ece_read_rect_offset(struct npcm750_ece *ece) { - return 0; + return readl(ece->base_addr + HEX_RECT_OFFSET); } -struct file_operations const drv_fops = { - .unlocked_ioctl = drv_ioctl, - .open = drv_open, - .release = drv_release, - .mmap = drv_mmap, -}; +/* Return TRUE if a rectangle finished to be compressed */ +static u32 ece_is_rect_compressed(struct npcm750_ece *ece) +{ + u32 temp = readl(ece->base_addr + DDA_STS); + + if (!(temp & CDREADY)) + return 0; -static u32 ece_get_ed_size(struct npcm750_ece *ece) + return 1; +} + +static u32 ece_get_ed_size(struct npcm750_ece *ece, u32 offset) { - u32 size = 0; - int count = 0; + u32 size; + char *buffer = ece->ed_buffer + offset; - while (ece_is_rect_compressed(ece) != CDREADY) + while (!ece_is_rect_compressed(ece)) ; - do { - size = (u32)(ece->ed_buffer[0] - | (ece->ed_buffer[1] << 8) - | (ece->ed_buffer[2] << 16) - | (ece->ed_buffer[3] << 24)); - count++; - } while (size == 0 && count < 30); + size = (u32)(buffer[0] + | (buffer[1] << 8) + | (buffer[2] << 16) + | (buffer[3] << 24)); ece_clear_drs(ece); return size; } -static void ece_clear_rect_offset(struct npcm750_ece *ece) -{ - u32 temp = 0; - - writel(temp, ece->ece_base_addr + HEX_RECT_OFFSET); -} /* This routine reset the FIFO as a bypass for Z1 chip */ -static void fifo_reset_bypass(struct npcm750_ece *ece) +static void ece_fifo_reset_bypass(struct npcm750_ece *ece) { - u32 temp = 0; - - temp = readl(ece->ece_base_addr + DDA_CTRL); - temp &= (~ECEEN); - writel(temp, ece->ece_base_addr + DDA_CTRL); - - temp |= ECEEN; - writel(temp, ece->ece_base_addr + DDA_CTRL); + update_bits(ece, DDA_CTRL, ECEEN, ~ECEEN); + update_bits(ece, DDA_CTRL, ECEEN, ECEEN); } /* This routine Encode the desired rectangle */ @@ -271,9 +184,9 @@ static void ece_enc_rect(struct npcm750_ece *ece, u32 w_size = ECE_TILE_W; u32 h_size = ECE_TILE_H; - fifo_reset_bypass(ece); + ece_fifo_reset_bypass(ece); - writel(rect_offset, ece->ece_base_addr + RECT_XY); + writel(rect_offset, ece->base_addr + RECT_XY); w_tile = r_w / ECE_TILE_W; h_tile = r_h / ECE_TILE_H; @@ -293,20 +206,22 @@ static void ece_enc_rect(struct npcm750_ece *ece, | ((w_tile - 1) << ECE_RECT_DIMEN_WR_OFFSET) | ((h_tile - 1) << ECE_RECT_DIMEN_HR_OFFSET); - writel(temp, ece->ece_base_addr + RECT_DIMEN); + writel(temp, ece->base_addr + RECT_DIMEN); } /* This routine sets the Encoded Data base address */ -static u32 ece_set_enc_dba(struct npcm750_ece *ece) +static u32 ece_set_enc_dba(struct npcm750_ece *ece, u32 addr) { - writel(ece->smem_start, ece->ece_base_addr + ED_BA); + writel(addr, ece->base_addr + ED_BA); + return 0; } /* This routine sets the Frame Buffer base address */ static u32 ece_set_fb_addr(struct npcm750_ece *ece, u32 buffer) { - writel(buffer, ece->ece_base_addr + FBR_BA); + writel(buffer, ece->base_addr + FBR_BA); + return 0; } @@ -337,74 +252,183 @@ static void ece_set_lp(struct npcm750_ece *ece, u32 pitch) } ece->lin_pitch = pitch; - writel(lp, ece->ece_base_addr + RESOL); + writel(lp, ece->base_addr + RESOL); } -/* Return TRUE if a rectangle finished to be compressed */ -static u32 ece_is_rect_compressed(struct npcm750_ece *ece) +/* Stop and reset the ECE state machine */ +static void ece_reset(struct npcm750_ece *ece) { - u32 temp = readl(ece->ece_base_addr + DDA_STS); + update_bits(ece, DDA_CTRL, ECEEN, ~ECEEN); + update_bits(ece, HEX_CTRL, ENCDIS, ENCDIS); + update_bits(ece, DDA_CTRL, ECEEN, ECEEN); + update_bits(ece, HEX_CTRL, ENCDIS, ~ENCDIS); - return (temp & CDREADY); + ece_clear_rect_offset(ece); } -/* Rectangle Compressed Data Ready */ -static void -ece_clear_drs(struct npcm750_ece *ece) +/* Initialise the ECE block and interface library */ +static int ece_initialise(struct npcm750_ece *ece) { - u32 temp = 0; + ece_reset(ece); + ece_clear_drs(ece); + ece_set_enc_dba(ece, ece->smem_start); + ece->lin_pitch = DEFAULT_LP; - temp = readl(ece->ece_base_addr + DDA_STS); - temp |= CDREADY; - writel(temp, ece->ece_base_addr + DDA_STS); - temp = readl(ece->ece_base_addr + DDA_STS); + return 0; } -/* Stop and reset the ECE state machine */ -static void ece_reset(struct npcm750_ece *ece) +/* Disable the ECE block*/ +static int ece_deinit(struct npcm750_ece *ece) +{ + update_bits(ece, DDA_CTRL, ECEEN, ~ECEEN); + update_bits(ece, HEX_CTRL, ENCDIS, ENCDIS); + ece_clear_rect_offset(ece); + ece_clear_drs(ece); + + return 0; +} + +static int +npcm750_ece_mmap(struct file *file, struct vm_area_struct *vma) { - u32 temp = 0; + struct npcm750_ece *ece = file->private_data; + unsigned long start; + u32 len; - temp = readl(ece->ece_base_addr + DDA_CTRL); - temp &= (~ECEEN); - writel(temp, ece->ece_base_addr + DDA_CTRL); + if (!ece) + return -ENODEV; - temp |= ECEEN; - writel(temp, ece->ece_base_addr + DDA_CTRL); + start = ece->smem_start; + len = ece->smem_len; - /* Reset ECE Encoder */ - temp = readl(ece->ece_base_addr + HEX_CTRL); - temp |= ENCDIS; - writel(temp, ece->ece_base_addr + HEX_CTRL); + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + fb_pgprotect(file, vma, start); + return vm_iomap_memory(vma, start, len); +} - /* Enable encoding */ - temp = readl(ece->ece_base_addr + HEX_CTRL); - temp &= (~ENCDIS); - writel(temp, ece->ece_base_addr + HEX_CTRL); +static int npcm750_ece_open(struct inode *inode, struct file *filp) +{ + if (!registered_ece) + return -ENODEV; - temp = 0; - writel(temp, ece->ece_base_addr + HEX_RECT_OFFSET); + filp->private_data = registered_ece; - ece->enc_gap = - (readl(ece->ece_base_addr + HEX_CTRL) & ENC_GAP) - >> ENC_GAP_OFFSET; + ece_initialise(registered_ece); - if (ece->enc_gap == 0) - ece->enc_gap = ENC_MIN_GAP_SIZE; + return 0; } -/* Initialise the ECE block and interface library */ -static int ece_initialise(struct npcm750_ece *ece) +static int npcm750_ece_release(struct inode *inode, struct file *filp) { - if (!ece->initialised) { - ece_reset(ece); - ece_clear_drs(ece); - ece->initialised = 1; - } + struct npcm750_ece *ece = filp->private_data; + + ece_deinit(ece); return 0; } +long npcm750_ece_ioctl(struct file *filp, unsigned int cmd, unsigned long args) +{ + int err = 0; + struct npcm750_ece *ece = filp->private_data; + + mutex_lock(&ece->mlock); + + switch (cmd) { + case ECE_IOCCLEAR_OFFSET: + + ece_clear_rect_offset(ece); + + break; + case ECE_IOCGET_OFFSET: + { + u32 offset = ece_read_rect_offset(ece); + + err = copy_to_user((int __user *)args, &offset, sizeof(offset)) + ? -EFAULT : 0; + break; + } + case ECE_IOCSETLP: + { + struct ece_ioctl_cmd data; + + err = copy_from_user(&data, (int __user *)args, sizeof(data)) + ? -EFAULT : 0; + if (err) { + mutex_unlock(&ece->mlock); + return err; + } + + if (!(data.lp % ECE_MIN_LP) && data.lp <= ECE_MAX_LP) + ece_set_lp(ece, data.lp); + + break; + } + case ECE_IOCSETFB: + { + struct ece_ioctl_cmd data; + + err = copy_from_user(&data, (int __user *)args, sizeof(data)) + ? -EFAULT : 0; + if (err) { + mutex_unlock(&ece->mlock); + return err; + } + + if (!data.framebuf) { + err = -EFAULT; + break; + } + + ece_set_fb_addr(ece, data.framebuf); + break; + } + case ECE_IOCGETED: + { + struct ece_ioctl_cmd data; + u32 ed_size = 0; + u32 offset = 0; + + err = copy_from_user(&data, (int __user *)args, sizeof(data)) + ? -EFAULT : 0; + if (err) { + mutex_unlock(&ece->mlock); + return err; + } + + offset = ece_read_rect_offset(ece); + ece_enc_rect(ece, data.x, data.y, data.w, data.h); + ed_size = ece_get_ed_size(ece, offset); + + ece->enc_gap = + (readl(ece->base_addr + HEX_CTRL) & ENC_GAP) + >> ENC_GAP_OFFSET; + + if (ece->enc_gap == 0) + ece->enc_gap = ENC_MIN_GAP_SIZE; + + data.gap_len = ece->enc_gap; + data.len = ed_size; + err = copy_to_user((int __user *)args, &data, sizeof(data)) + ? -EFAULT : 0; + break; + } + default: + break; + } + + mutex_unlock(&ece->mlock); + + return err; +} + +struct file_operations const npcm750_ece_fops = { + .unlocked_ioctl = npcm750_ece_ioctl, + .open = npcm750_ece_open, + .release = npcm750_ece_release, + .mmap = npcm750_ece_mmap, +}; + static int npcm750_ece_device_create(struct npcm750_ece *ece) { int ret; @@ -421,7 +445,7 @@ static int npcm750_ece_device_create(struct npcm750_ece *ece) if (!dev_cdevp) goto err; - cdev_init(dev_cdevp, &drv_fops); + cdev_init(dev_cdevp, &npcm750_ece_fops); dev_cdevp->owner = THIS_MODULE; ece->dev_t = dev; ret = cdev_add(dev_cdevp, MKDEV(MAJOR(dev), MINOR(dev)), 1); @@ -488,11 +512,11 @@ static int npcm750_ece_probe(struct platform_device *pdev) goto err; } - ece->ece_base_addr = of_iomap(pdev->dev.of_node, 0); - if (IS_ERR(ece->ece_base_addr)) { + ece->base_addr = of_iomap(pdev->dev.of_node, 0); + if (IS_ERR(ece->base_addr)) { dev_err(&pdev->dev, "%s: failed to ioremap ece base address\n", __func__); - ret = PTR_ERR(ece->ece_base_addr); + ret = PTR_ERR(ece->base_addr); goto err; } @@ -505,14 +529,6 @@ static int npcm750_ece_probe(struct platform_device *pdev) goto err; } - ece_initialise(ece); - - ece->width = DEFAULT_WIDTH; - ece->height = DEFAULT_HEIGHT; - ece->lin_pitch = DEFAULT_LP; - - ece_set_enc_dba(ece); - registered_ece = ece; pr_info("NPCM750 ECE Driver probed\n"); diff --git a/drivers/video/vcd/npcm750_vcd.c b/drivers/video/vcd/npcm750_vcd.c index 94768b7df78cd3..9ceb7d48675af3 100644 --- a/drivers/video/vcd/npcm750_vcd.c +++ b/drivers/video/vcd/npcm750_vcd.c @@ -24,7 +24,6 @@ #include #include #include - #include "vcd.h" #define VCD_IOC_MAGIC 'v' @@ -108,8 +107,7 @@ npcm750_vcd_release(struct inode *inode, struct file *file) { struct vcd_inst *vcd = file->private_data; - if (vcd->smem_base) - memset(vcd->smem_base, 0x00, vcd->smem_len); + vcd_deinit(vcd); return 0; } @@ -117,14 +115,19 @@ npcm750_vcd_release(struct inode *inode, struct file *file) static int npcm750_vcd_open(struct inode *inode, struct file *file) { - int res = 0; + int ret = 0; if (!registered_vcd) return -ENODEV; file->private_data = registered_vcd; - return res; + ret = vcd_init(registered_vcd); + if (ret) + dev_err(registered_vcd->dev, "%s: failed to init vcd module\n", + __func__); + + return ret; } static long @@ -143,22 +146,23 @@ npcm750_do_vcd_ioctl(struct vcd_inst *vcd, unsigned int cmd, case VCD_IOCSENDCMD: { int vcd_cmd; + unsigned long timeout; ret = copy_from_user(&vcd_cmd, argp, sizeof(vcd_cmd)) ? -EFAULT : 0; + vcd_command(vcd, vcd_cmd); - if (vcd_cmd > 0) { - unsigned long timeout; - /* Wait for cmd to complete */ - timeout = jiffies + VCD_OP_TIMEOUT; - while (!vcd_is_op_ok(vcd)) { - if (time_after(jiffies, timeout)) { - vcd_reset(vcd); - break; - } - cpu_relax(); + + /* Wait for cmd to complete */ + timeout = jiffies + VCD_OP_TIMEOUT; + while (!vcd_is_op_ok(vcd)) { + if (time_after(jiffies, timeout)) { + vcd_reset(vcd); + break; } + cpu_relax(); } + break; } case VCD_IOCCHKRES: @@ -359,13 +363,6 @@ static int npcm750_vcd_probe(struct platform_device *pdev) if (ret) goto err; - ret = vcd_init(vcd); - if (ret) { - dev_err(&pdev->dev, "%s: failed to init vcd module\n", - __func__); - goto err; - } - irq = of_irq_get(pdev->dev.of_node, 0); ret = request_irq(irq, npcm750_vcd_interrupt, IRQF_SHARED, vcd_name, vcd->dev); diff --git a/drivers/video/vcd/vcd.c b/drivers/video/vcd/vcd.c index 67a1f29608217c..112fcb58faf716 100644 --- a/drivers/video/vcd/vcd.c +++ b/drivers/video/vcd/vcd.c @@ -404,6 +404,8 @@ void vcd_free_frame_memory(struct vcd_inst *vcd) if (vcd->smem_base) dma_free_coherent(vcd->dev, PAGE_ALIGN(vcd->smem_len), vcd->smem_base, vcd->smem_start); + + vcd->smem_base = NULL; } u8 vcd_is_busy(struct vcd_inst *vcd) @@ -424,7 +426,6 @@ u8 vcd_is_done(struct vcd_inst *vcd) u8 vcd_is_op_ok(struct vcd_inst *vcd) { struct vcd_reg *reg = vcd->reg; - u8 changed = 0; u32 vdisp = read32(reg->cap_res) & VCD_CAPRES_MASK; u32 vcd_stat = read32(reg->vcd_stat); u32 mask = VCD_STAT_DONE | @@ -436,9 +437,8 @@ u8 vcd_is_op_ok(struct vcd_inst *vcd) vcd->info.pixel_clk == 0) return 1; - changed = ((vcd->info.hdisp != vcd_get_hres(vcd)) || - (vcd->info.vdisp != vcd_get_vres(vcd))); - if (changed) + if ((vcd->info.hdisp != vcd_get_hres(vcd)) || + (vcd->info.vdisp != vcd_get_vres(vcd))) return 1; return ((vcd_stat & mask) == 0) && (vcd_get_cur_line(vcd) == vdisp); @@ -519,7 +519,6 @@ vcd_merge_rect(struct vcd_inst *vcd, struct vcd_list_info *list_info) struct list_head *head = &vcd->list.list; struct vcd_diff_list *list = list_info->list; struct vcd_diff_list *first = list_info->first; - int cont_x = 0, cont_y = 0; if (!first) { first = list; @@ -527,17 +526,15 @@ vcd_merge_rect(struct vcd_inst *vcd, struct vcd_list_info *list_info) list_add_tail(&list->list, head); vcd->diff_cnt++; } else { - if (((list->diff.x - - (first->diff.x + cont_x * 16)) == 16) && + if (((list->diff.x == + (first->diff.x + first->diff.w))) && (list->diff.y == first->diff.y)) { first->diff.w += list->diff.w; - cont_x++; kfree(list); - } else if (((list->diff.y - - (first->diff.y + cont_y * 16)) == 16) && + } else if (((list->diff.y == + (first->diff.y + first->diff.h))) && (list->diff.x == first->diff.x)) { first->diff.h += list->diff.h; - cont_y++; kfree(list); } else if (((list->diff.y > first->diff.y) && (list->diff.y < (first->diff.y + first->diff.h))) && @@ -547,9 +544,7 @@ vcd_merge_rect(struct vcd_inst *vcd, struct vcd_list_info *list_info) } else { list_add_tail(&list->list, head); vcd->diff_cnt++; - first = list; - cont_x = 0; - cont_y = 0; + list_info->first = list; } } } @@ -710,10 +705,10 @@ int vcd_init(struct vcd_inst *vcd) & (~VCD_MODE_VS_EDGE), reg->vcd_mode); vcd_set_frame_addrs(vcd, vcd->frame_start, vcd->frame_start); - vcd_check_res(vcd); vcd_init_diff_bit(vcd, 1); vcd_set_color_mode(vcd, VCD_MODE_CM_565); vcd_set_int(vcd, VCD_INTE_VAL); + vcd_check_res(vcd); return 0; } @@ -721,7 +716,9 @@ void vcd_deinit(struct vcd_inst *vcd) { struct vcd_reg *reg = vcd->reg; + vcd_set_int(vcd, 0); vcd_free_frame_memory(vcd); vcd_free_diff_table(vcd); write32(read32(reg->vcd_mode) & ~VCD_MODE_VCDE, reg->vcd_mode); + memset(&vcd->info, 0, sizeof(struct vcd_info)); }