static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~1); ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & 0x0317f313); ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | 1); ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~0x10000); ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10); if (pcdev->active) { pcdev->active->state = VIDEOBUF_ACTIVE; ceu_write(pcdev, CDAYR, videobuf_to_dma_contig(pcdev->active)); ceu_write(pcdev, CAPSR, 0x1); /* start capture */ } }
static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { struct soc_camera_device *icd = pcdev->icd; dma_addr_t phys_addr_top, phys_addr_bottom; /* The hardware is _very_ picky about this sequence. Especially * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge * several not-so-well documented interrupt sources in CETCR. */ ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_CPEIE); ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & CEU_CETCR_MAGIC); ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_CPEIE); ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); if (!pcdev->active) return; phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: phys_addr_top += icd->width * icd->height; ceu_write(pcdev, CDACR, phys_addr_top); if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } } pcdev->active->state = VIDEOBUF_ACTIVE; ceu_write(pcdev, CAPSR, 0x1); /* start capture */ }
static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { struct soc_camera_device *icd = pcdev->icd; dma_addr_t phys_addr_top, phys_addr_bottom; ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_CPEIE); ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & CEU_CETCR_MAGIC); ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_CPEIE); ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); if (!pcdev->active) return; phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->user_width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: phys_addr_top += icd->user_width * icd->user_height; ceu_write(pcdev, CDACR, phys_addr_top); if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->user_width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } } pcdev->active->state = VIDEOBUF_ACTIVE; ceu_write(pcdev, CAPSR, 0x1); }
static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) { unsigned long timeout = jiffies + 10 * HZ; while ((ceu_read(pcdev, CSTSR) & 1) && time_before(jiffies, timeout)) msleep(1); if (time_after(jiffies, timeout)) { dev_err(pcdev->ici.v4l2_dev.dev, "Timeout waiting for frame end! Interface problem?\n"); return; } while (ceu_read(pcdev, CAPSR) & (1 << 16)) udelay(10); if (capsr & ~(1 << 16)) ceu_write(pcdev, CAPSR, capsr); }
static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, struct v4l2_control *ctrl) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; u32 val; switch (ctrl->id) { case V4L2_CID_SHARPNESS: val = ceu_read(pcdev, CLFCR); ctrl->value = val ^ 1; return 0; } return -ENOIOCTLCMD; }
static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; if (pcdev->icd) return -EBUSY; dev_info(icd->dev.parent, "SuperH Mobile CEU driver attached to camera %d\n", icd->devnum); pm_runtime_get_sync(ici->v4l2_dev.dev); ceu_write(pcdev, CAPSR, 1 << 16); while (ceu_read(pcdev, CSTSR) & 1) msleep(1); pcdev->icd = icd; return 0; }
static u32 capture_save_reset(struct sh_mobile_ceu_dev *pcdev) { u32 capsr = ceu_read(pcdev, CAPSR); ceu_write(pcdev, CAPSR, 1 << 16); return capsr; }