static int sh_mobile_ceu_try_bus_param(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; unsigned long camera_flags, common_flags; camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, make_bus_param(pcdev)); if (!common_flags) return -EINVAL; return 0; }
static int mx3_camera_try_bus_param(struct soc_camera_device *icd, const unsigned int depth) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); dev_dbg(icd->dev.parent, "request bus width %d bit: %d\n", depth, ret); if (ret < 0) return ret; camera_flags = icd->ops->query_bus_param(icd); ret = soc_camera_bus_param_compatible(camera_flags, bus_flags); if (ret < 0) dev_warn(icd->dev.parent, "Flags incompatible: camera %lx, host %lx\n", camera_flags, bus_flags); return ret; }
static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx1_camera_dev *pcdev = ici->priv; unsigned long camera_flags, common_flags; unsigned int csicr1; int ret; camera_flags = icd->ops->query_bus_param(icd); /* MX1 supports only 8bit buswidth */ common_flags = soc_camera_bus_param_compatible(camera_flags, CSI_BUS_FLAGS); if (!common_flags) return -EINVAL; /* Make choises, based on platform choice */ if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { if (!pcdev->pdata || pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH) common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; else common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; } if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { if (!pcdev->pdata || pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING) common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; else common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; } if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) && (common_flags & SOCAM_DATA_ACTIVE_LOW)) { if (!pcdev->pdata || pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH) common_flags &= ~SOCAM_DATA_ACTIVE_LOW; else common_flags &= ~SOCAM_DATA_ACTIVE_HIGH; } ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) return ret; csicr1 = __raw_readl(pcdev->base + CSICR1); if (common_flags & SOCAM_PCLK_SAMPLE_RISING) csicr1 |= CSICR1_REDGE; if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) csicr1 |= CSICR1_SOF_POL; if (common_flags & SOCAM_DATA_ACTIVE_LOW) csicr1 |= CSICR1_DATA_POL; __raw_writel(csicr1, pcdev->base + CSICR1); return 0; }
static int omap1_cam_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct omap1_cam_dev *pcdev = ici->priv; struct device *dev = icd->dev.parent; const struct soc_camera_format_xlate *xlate; const struct soc_mbus_pixelfmt *fmt; unsigned long camera_flags, common_flags; u32 ctrlclock, mode; int ret; camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, SOCAM_BUS_FLAGS); if (!common_flags) return -EINVAL; /* Make choices, possibly based on platform configuration */ if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { if (!pcdev->pdata || pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING) common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; else common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; } ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) return ret; ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); if (ctrlclock & LCLK_EN) CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); if (common_flags & SOCAM_PCLK_SAMPLE_RISING) { dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n"); ctrlclock |= POLCLK; } else { dev_dbg(dev, "CTRLCLOCK_REG &= ~POLCLK\n"); ctrlclock &= ~POLCLK; } CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); if (ctrlclock & LCLK_EN) CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); /* select bus endianess */ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); fmt = xlate->host_fmt; mode = CAM_READ(pcdev, MODE) & ~(RAZ_FIFO | IRQ_MASK | DMA); if (fmt->order == SOC_MBUS_ORDER_LE) { dev_dbg(dev, "MODE_REG &= ~ORDERCAMD\n"); CAM_WRITE(pcdev, MODE, mode & ~ORDERCAMD); } else { dev_dbg(dev, "MODE_REG |= ORDERCAMD\n"); CAM_WRITE(pcdev, MODE, mode | ORDERCAMD); } return 0; }
static int mx2_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx2_camera_dev *pcdev = ici->priv; unsigned long camera_flags, common_flags; int ret = 0; int bytesperline; u32 csicr1 = pcdev->csicr1; camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, MX2_BUS_FLAGS); if (!common_flags) return -EINVAL; if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH) common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; else common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; } if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING) common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; else common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; } ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) return ret; if (common_flags & SOCAM_PCLK_SAMPLE_RISING) csicr1 |= CSICR1_REDGE; if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) csicr1 |= CSICR1_INV_PCLK; if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) csicr1 |= CSICR1_SOF_POL; if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH) csicr1 |= CSICR1_HSYNC_POL; if (pcdev->platform_flags & MX2_CAMERA_SWAP16) csicr1 |= CSICR1_SWAP16_EN; if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) csicr1 |= CSICR1_EXT_VSYNC; if (pcdev->platform_flags & MX2_CAMERA_CCIR) csicr1 |= CSICR1_CCIR_EN; if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE) csicr1 |= CSICR1_CCIR_MODE; if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK) csicr1 |= CSICR1_GCLK_MODE; if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) csicr1 |= CSICR1_INV_DATA; if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB) csicr1 |= CSICR1_PACK_DIR; pcdev->csicr1 = csicr1; bytesperline = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); if (bytesperline < 0) return bytesperline; if (mx27_camera_emma(pcdev)) { ret = mx27_camera_emma_prp_reset(pcdev); if (ret) return ret; if (pcdev->discard_buffer) dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size, pcdev->discard_buffer, pcdev->discard_buffer_dma); /* * I didn't manage to properly enable/disable the prp * on a per frame basis during running transfers, * thus we allocate a buffer here and use it to * discard frames when no buffer is available. * Feel free to work on this ;) */ pcdev->discard_size = icd->user_height * bytesperline; pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, pcdev->discard_size, &pcdev->discard_buffer_dma, GFP_KERNEL); if (!pcdev->discard_buffer) return -ENOMEM; mx27_camera_emma_buf_init(icd, bytesperline); } else if (cpu_is_mx25()) { writel((bytesperline * icd->user_height) >> 2, pcdev->base_csi + CSIRXCNT); writel((bytesperline << 16) | icd->user_height, pcdev->base_csi + CSIIMAG_PARA); } writel(pcdev->csicr1, pcdev->base_csi + CSICR1); return 0; }
static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; unsigned long bus_flags, camera_flags, common_flags; u32 dw, sens_conf; const struct soc_mbus_pixelfmt *fmt; int buswidth; int ret; const struct soc_camera_format_xlate *xlate; struct device *dev = icd->dev.parent; fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); if (!fmt) return -EINVAL; buswidth = fmt->bits_per_sample; ret = test_platform_param(mx3_cam, buswidth, &bus_flags); xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(dev, "Format %x not found\n", pixfmt); return -EINVAL; } dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret); if (ret < 0) return ret; camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); dev_dbg(dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", camera_flags, bus_flags, common_flags); if (!common_flags) { dev_dbg(dev, "no common flags"); return -EINVAL; } /* Make choices, based on platform preferences */ if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { if (mx3_cam->platform_flags & MX3_CAMERA_HSP) common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; else common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; } if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { if (mx3_cam->platform_flags & MX3_CAMERA_VSP) common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; else common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; } if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) && (common_flags & SOCAM_DATA_ACTIVE_LOW)) { if (mx3_cam->platform_flags & MX3_CAMERA_DP) common_flags &= ~SOCAM_DATA_ACTIVE_HIGH; else common_flags &= ~SOCAM_DATA_ACTIVE_LOW; } if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { if (mx3_cam->platform_flags & MX3_CAMERA_PCP) common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; else common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; } /* * Make the camera work in widest common mode, we'll take care of * the rest */ if (common_flags & SOCAM_DATAWIDTH_15) common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | SOCAM_DATAWIDTH_15; else if (common_flags & SOCAM_DATAWIDTH_10) common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | SOCAM_DATAWIDTH_10; else if (common_flags & SOCAM_DATAWIDTH_8) common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | SOCAM_DATAWIDTH_8; else common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | SOCAM_DATAWIDTH_4; ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) { dev_dbg(dev, "camera set_bus_param(%lx) returned %d\n", common_flags, ret); return ret; } /* * So far only gated clock mode is supported. Add a line * (3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) | * below and select the required mode when supporting other * synchronisation protocols. */ sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) & ~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) | (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) | (1 << CSI_SENS_CONF_DATA_POL_SHIFT) | (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) | (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) | (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT)); /* TODO: Support RGB and YUV formats */ /* This has been set in mx3_camera_activate(), but we clear it above */ sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER; if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; if (common_flags & SOCAM_DATA_ACTIVE_LOW) sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; /* Just do what we're asked to do */ switch (xlate->host_fmt->bits_per_sample) { case 4: dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; break; case 8: dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; break; case 10: dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; break; default: /* * Actually it can only be 15 now, default is just to silence * compiler warnings */ case 15: dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; } csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); dev_dbg(dev, "Set SENS_CONF to %x\n", sens_conf | dw); return 0; }
static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; int ret; unsigned long camera_flags, common_flags, value; int yuv_lineskip; struct sh_mobile_ceu_cam *cam = icd->host_priv; u32 capsr = capture_save_reset(pcdev); camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, make_bus_param(pcdev)); if (!common_flags) return -EINVAL; ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) return ret; switch (common_flags & SOCAM_DATAWIDTH_MASK) { case SOCAM_DATAWIDTH_8: pcdev->is_16bit = 0; break; case SOCAM_DATAWIDTH_16: pcdev->is_16bit = 1; break; default: return -EINVAL; } ceu_write(pcdev, CRCNTR, 0); ceu_write(pcdev, CRCMPR, 0); value = 0x00000010; yuv_lineskip = 0; switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: yuv_lineskip = 1; case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: switch (cam->camera_fmt->fourcc) { case V4L2_PIX_FMT_UYVY: value = 0x00000000; break; case V4L2_PIX_FMT_VYUY: value = 0x00000100; break; case V4L2_PIX_FMT_YUYV: value = 0x00000200; break; case V4L2_PIX_FMT_YVYU: value = 0x00000300; break; default: BUG(); } } if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21 || icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61) value ^= 0x00000100; value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; value |= pcdev->is_16bit ? 1 << 12 : 0; ceu_write(pcdev, CAMCR, value); ceu_write(pcdev, CAPCR, 0x00300000); ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); mdelay(1); ceu_write(pcdev, CFLCR, pcdev->cflcr); value = 0x00000017; if (yuv_lineskip) value &= ~0x00000010; ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, icd->user_width, icd->user_height); capture_restore(pcdev, capsr); return 0; }