Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:

 - Missing MAINTAINERS entries were added for several drivers

 - Adds V4L2 support for DMABUF handling, allowing zero-copy buffer
   sharing between V4L2 devices and GPU

 - Got rid of all warnings when compiling with W=1 on x86

 - Add a new driver for Exynos hardware (s3c-camif)

 - Several bug fixes, cleanups and driver improvements

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (243 commits)
  [media] omap3isp: Replace cpu_is_omap3630() with ISP revision check
  [media] omap3isp: Prepare/unprepare clocks before/after enable/disable
  [media] omap3isp: preview: Add support for 8-bit formats at the sink pad
  [media] omap3isp: Replace printk with dev_*
  [media] omap3isp: Find source pad from external entity
  [media] omap3isp: Configure CSI-2 phy based on platform data
  [media] omap3isp: Add PHY routing configuration
  [media] omap3isp: Add CSI configuration registers from control block to ISP resources
  [media] omap3isp: Remove unneeded module memory address definitions
  [media] omap3isp: Use monotonic timestamps for statistics buffers
  [media] uvcvideo: Fix control value clamping for unsigned integer controls
  [media] uvcvideo: Mark first output terminal as default video node
  [media] uvcvideo: Add VIDIOC_[GS]_PRIORITY support
  [media] uvcvideo: Return -ENOTTY for unsupported ioctls
  [media] uvcvideo: Set device_caps in VIDIOC_QUERYCAP
  [media] uvcvideo: Don't fail when an unsupported format is requested
  [media] uvcvideo: Return -EACCES when trying to access a read/write-only control
  [media] uvcvideo: Set error_idx properly for extended controls API failures
  [media] rtl28xxu: add NOXON DAB/DAB+ USB dongle rev 2
  [media] fc2580: write some registers conditionally
  ...
This commit is contained in:
Linus Torvalds
2012-12-13 19:22:22 -08:00
314개의 변경된 파일7781개의 추가작업 그리고 1890개의 파일을 삭제

파일 보기

@@ -103,7 +103,8 @@ static const struct isp_res_mapping isp_res_maps[] = {
1 << OMAP3_ISP_IOMEM_RESZ |
1 << OMAP3_ISP_IOMEM_SBL |
1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
1 << OMAP3_ISP_IOMEM_CSIPHY2,
1 << OMAP3_ISP_IOMEM_CSIPHY2 |
1 << OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
},
{
.isp_rev = ISP_REVISION_15_0,
@@ -120,7 +121,8 @@ static const struct isp_res_mapping isp_res_maps[] = {
1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 |
1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 |
1 << OMAP3_ISP_IOMEM_CSIPHY1 |
1 << OMAP3_ISP_IOMEM_CSI2C_REGS2,
1 << OMAP3_ISP_IOMEM_CSI2C_REGS2 |
1 << OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
},
};
@@ -1331,7 +1333,8 @@ void omap3isp_subclk_disable(struct isp_device *isp,
* isp_enable_clocks - Enable ISP clocks
* @isp: OMAP3 ISP device
*
* Return 0 if successful, or clk_enable return value if any of tthem fails.
* Return 0 if successful, or clk_prepare_enable return value if any of them
* fails.
*/
static int isp_enable_clocks(struct isp_device *isp)
{
@@ -1348,14 +1351,11 @@ static int isp_enable_clocks(struct isp_device *isp)
* has to be twice of what is set on OMAP3430 to get
* the required value for cam_mclk
*/
if (cpu_is_omap3630())
divisor = 1;
else
divisor = 2;
divisor = isp->revision == ISP_REVISION_15_0 ? 1 : 2;
r = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
r = clk_prepare_enable(isp->clock[ISP_CLK_CAM_ICK]);
if (r) {
dev_err(isp->dev, "clk_enable cam_ick failed\n");
dev_err(isp->dev, "failed to enable cam_ick clock\n");
goto out_clk_enable_ick;
}
r = clk_set_rate(isp->clock[ISP_CLK_DPLL4_M5_CK],
@@ -1364,9 +1364,9 @@ static int isp_enable_clocks(struct isp_device *isp)
dev_err(isp->dev, "clk_set_rate for dpll4_m5_ck failed\n");
goto out_clk_enable_mclk;
}
r = clk_enable(isp->clock[ISP_CLK_CAM_MCLK]);
r = clk_prepare_enable(isp->clock[ISP_CLK_CAM_MCLK]);
if (r) {
dev_err(isp->dev, "clk_enable cam_mclk failed\n");
dev_err(isp->dev, "failed to enable cam_mclk clock\n");
goto out_clk_enable_mclk;
}
rate = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
@@ -1374,17 +1374,17 @@ static int isp_enable_clocks(struct isp_device *isp)
dev_warn(isp->dev, "unexpected cam_mclk rate:\n"
" expected : %d\n"
" actual : %ld\n", CM_CAM_MCLK_HZ, rate);
r = clk_enable(isp->clock[ISP_CLK_CSI2_FCK]);
r = clk_prepare_enable(isp->clock[ISP_CLK_CSI2_FCK]);
if (r) {
dev_err(isp->dev, "clk_enable csi2_fck failed\n");
dev_err(isp->dev, "failed to enable csi2_fck clock\n");
goto out_clk_enable_csi2_fclk;
}
return 0;
out_clk_enable_csi2_fclk:
clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
clk_disable_unprepare(isp->clock[ISP_CLK_CAM_MCLK]);
out_clk_enable_mclk:
clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
clk_disable_unprepare(isp->clock[ISP_CLK_CAM_ICK]);
out_clk_enable_ick:
return r;
}
@@ -1395,9 +1395,9 @@ out_clk_enable_ick:
*/
static void isp_disable_clocks(struct isp_device *isp)
{
clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
clk_disable(isp->clock[ISP_CLK_CSI2_FCK]);
clk_disable_unprepare(isp->clock[ISP_CLK_CAM_ICK]);
clk_disable_unprepare(isp->clock[ISP_CLK_CAM_MCLK]);
clk_disable_unprepare(isp->clock[ISP_CLK_CSI2_FCK]);
}
static const char *isp_clocks[] = {
@@ -1678,7 +1678,7 @@ isp_register_subdev_group(struct isp_device *isp,
adapter = i2c_get_adapter(board_info->i2c_adapter_id);
if (adapter == NULL) {
printk(KERN_ERR "%s: Unable to get I2C adapter %d for "
dev_err(isp->dev, "%s: Unable to get I2C adapter %d for "
"device %s\n", __func__,
board_info->i2c_adapter_id,
board_info->board_info->type);
@@ -1688,7 +1688,7 @@ isp_register_subdev_group(struct isp_device *isp,
subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
board_info->board_info, NULL);
if (subdev == NULL) {
printk(KERN_ERR "%s: Unable to register subdev %s\n",
dev_err(isp->dev, "%s: Unable to register subdev %s\n",
__func__, board_info->board_info->type);
continue;
}
@@ -1713,7 +1713,7 @@ static int isp_register_entities(struct isp_device *isp)
isp->media_dev.link_notify = isp_pipeline_link_notify;
ret = media_device_register(&isp->media_dev);
if (ret < 0) {
printk(KERN_ERR "%s: Media device registration failed (%d)\n",
dev_err(isp->dev, "%s: Media device registration failed (%d)\n",
__func__, ret);
return ret;
}
@@ -1721,7 +1721,7 @@ static int isp_register_entities(struct isp_device *isp)
isp->v4l2_dev.mdev = &isp->media_dev;
ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
if (ret < 0) {
printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n",
dev_err(isp->dev, "%s: V4L2 device registration failed (%d)\n",
__func__, ret);
goto done;
}
@@ -1766,6 +1766,7 @@ static int isp_register_entities(struct isp_device *isp)
struct media_entity *input;
unsigned int flags;
unsigned int pad;
unsigned int i;
sensor = isp_register_subdev_group(isp, subdevs->subdevs);
if (sensor == NULL)
@@ -1807,13 +1808,25 @@ static int isp_register_entities(struct isp_device *isp)
break;
default:
printk(KERN_ERR "%s: invalid interface type %u\n",
__func__, subdevs->interface);
dev_err(isp->dev, "%s: invalid interface type %u\n",
__func__, subdevs->interface);
ret = -EINVAL;
goto done;
}
ret = media_entity_create_link(&sensor->entity, 0, input, pad,
for (i = 0; i < sensor->entity.num_pads; i++) {
if (sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
break;
}
if (i == sensor->entity.num_pads) {
dev_err(isp->dev,
"%s: no source pad in external entity\n",
__func__);
ret = -EINVAL;
goto done;
}
ret = media_entity_create_link(&sensor->entity, i, input, pad,
flags);
if (ret < 0)
goto done;
@@ -2096,7 +2109,11 @@ static int __devinit isp_probe(struct platform_device *pdev)
isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
/* Clocks */
/* Clocks
*
* The ISP clock tree is revision-dependent. We thus need to enable ICLK
* manually to read the revision before calling __omap3isp_get().
*/
ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
if (ret < 0)
goto error;
@@ -2105,6 +2122,16 @@ static int __devinit isp_probe(struct platform_device *pdev)
if (ret < 0)
goto error;
ret = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
if (ret < 0)
goto error;
isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
dev_info(isp->dev, "Revision %d.%d found\n",
(isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
if (__omap3isp_get(isp, false) == NULL) {
ret = -ENODEV;
goto error;
@@ -2115,10 +2142,6 @@ static int __devinit isp_probe(struct platform_device *pdev)
goto error_isp;
/* Memory resources */
isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
dev_info(isp->dev, "Revision %d.%d found\n",
(isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
for (m = 0; m < ARRAY_SIZE(isp_res_maps); m++)
if (isp->revision == isp_res_maps[m].isp_rev)
break;

파일 보기

@@ -70,6 +70,8 @@ enum isp_mem_resources {
OMAP3_ISP_IOMEM_CSI2C_REGS1,
OMAP3_ISP_IOMEM_CSIPHY1,
OMAP3_ISP_IOMEM_CSI2C_REGS2,
OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
OMAP3_ISP_IOMEM_LAST
};
@@ -125,9 +127,6 @@ struct isp_reg {
struct isp_platform_callback {
u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
int (*csiphy_config)(struct isp_csiphy *phy,
struct isp_csiphy_dphy_cfg *dphy,
struct isp_csiphy_lanes_cfg *lanes);
};
/*

파일 보기

@@ -517,7 +517,7 @@ int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
} while (soft_reset_retries < 5);
if (soft_reset_retries == 5) {
printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
dev_err(isp->dev, "CSI2: Soft reset try count exceeded!\n");
return -EBUSY;
}
@@ -535,8 +535,8 @@ int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
} while (--i > 0);
if (i == 0) {
printk(KERN_ERR
"CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
dev_err(isp->dev,
"CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
return -EBUSY;
}

파일 보기

@@ -32,34 +32,92 @@
#include "ispreg.h"
#include "ispcsiphy.h"
/*
* csiphy_lanes_config - Configuration of CSIPHY lanes.
*
* Updates HW configuration.
* Called with phy->mutex taken.
*/
static void csiphy_lanes_config(struct isp_csiphy *phy)
static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, u32 iface,
bool ccp2_strobe)
{
unsigned int i;
u32 reg;
u32 reg = isp_reg_readl(
phy->isp, OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0);
u32 shift, mode;
reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
for (i = 0; i < phy->num_data_lanes; i++) {
reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
reg |= (phy->lanes.data[i].pol <<
ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
reg |= (phy->lanes.data[i].pos <<
ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
switch (iface) {
case ISP_INTERFACE_CCP2B_PHY1:
reg &= ~OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2;
shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT;
break;
case ISP_INTERFACE_CSI2C_PHY1:
shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT;
mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY;
break;
case ISP_INTERFACE_CCP2B_PHY2:
reg |= OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2;
shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT;
break;
case ISP_INTERFACE_CSI2A_PHY2:
shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT;
mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY;
break;
}
reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
reg |= phy->lanes.clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
reg |= phy->lanes.clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
/* Select data/clock or data/strobe mode for CCP2 */
switch (iface) {
case ISP_INTERFACE_CCP2B_PHY1:
case ISP_INTERFACE_CCP2B_PHY2:
if (ccp2_strobe)
mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_STROBE;
else
mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_CLOCK;
}
isp_reg_writel(phy->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
reg &= ~(OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_MASK << shift);
reg |= mode << shift;
isp_reg_writel(phy->isp, reg,
OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0);
}
static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on,
bool ccp2_strobe)
{
u32 csirxfe = OMAP343X_CONTROL_CSIRXFE_PWRDNZ
| OMAP343X_CONTROL_CSIRXFE_RESET;
/* Only the CCP2B on PHY1 is configurable. */
if (iface != ISP_INTERFACE_CCP2B_PHY1)
return;
if (!on) {
isp_reg_writel(phy->isp, 0,
OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0);
return;
}
if (ccp2_strobe)
csirxfe |= OMAP343X_CONTROL_CSIRXFE_SELFORM;
isp_reg_writel(phy->isp, csirxfe,
OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0);
}
/*
* Configure OMAP 3 CSI PHY routing.
* @phy: relevant phy device
* @iface: ISP_INTERFACE_*
* @on: power on or off
* @ccp2_strobe: false: data/clock, true: data/strobe
*
* Note that the underlying routing configuration registers are part of the
* control (SCM) register space and part of the CORE power domain on both 3430
* and 3630, so they will not hold their contents in off-mode. This isn't an
* issue since the MPU power domain is forced on whilst the ISP is in use.
*/
static void csiphy_routing_cfg(struct isp_csiphy *phy, u32 iface, bool on,
bool ccp2_strobe)
{
if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL]
&& on)
return csiphy_routing_cfg_3630(phy, iface, ccp2_strobe);
if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE])
return csiphy_routing_cfg_3430(phy, iface, on, ccp2_strobe);
}
/*
@@ -99,7 +157,7 @@ static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
} while ((reg != power >> 2) && (retry_count < 100));
if (retry_count == 100) {
printk(KERN_ERR "CSI2 CIO set power failed!\n");
dev_err(phy->isp->dev, "CSI2 CIO set power failed!\n");
return -EBUSY;
}
@@ -107,43 +165,28 @@ static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
}
/*
* csiphy_dphy_config - Configure CSI2 D-PHY parameters.
*
* Called with phy->mutex taken.
* TCLK values are OK at their reset values
*/
static void csiphy_dphy_config(struct isp_csiphy *phy)
{
u32 reg;
/* Set up ISPCSIPHY_REG0 */
reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG0);
reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
ISPCSIPHY_REG0_THS_SETTLE_MASK);
reg |= phy->dphy.ths_term << ISPCSIPHY_REG0_THS_TERM_SHIFT;
reg |= phy->dphy.ths_settle << ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
/* Set up ISPCSIPHY_REG1 */
reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG1);
reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
ISPCSIPHY_REG1_TCLK_MISS_MASK |
ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
reg |= phy->dphy.tclk_term << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
reg |= phy->dphy.tclk_miss << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
reg |= phy->dphy.tclk_settle << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
}
static int csiphy_config(struct isp_csiphy *phy,
struct isp_csiphy_dphy_cfg *dphy,
struct isp_csiphy_lanes_cfg *lanes)
#define TCLK_TERM 0
#define TCLK_MISS 1
#define TCLK_SETTLE 14
static int omap3isp_csiphy_config(struct isp_csiphy *phy)
{
struct isp_csi2_device *csi2 = phy->csi2;
struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
struct isp_v4l2_subdevs_group *subdevs = pipe->external->host_priv;
struct isp_csiphy_lanes_cfg *lanes;
int csi2_ddrclk_khz;
unsigned int used_lanes = 0;
unsigned int i;
u32 reg;
if (subdevs->interface == ISP_INTERFACE_CCP2B_PHY1
|| subdevs->interface == ISP_INTERFACE_CCP2B_PHY2)
lanes = &subdevs->bus.ccp2.lanecfg;
else
lanes = &subdevs->bus.csi2.lanecfg;
/* Clock and data lanes verification */
for (i = 0; i < phy->num_data_lanes; i++) {
@@ -162,10 +205,61 @@ static int csiphy_config(struct isp_csiphy *phy,
if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
return -EINVAL;
mutex_lock(&phy->mutex);
phy->dphy = *dphy;
phy->lanes = *lanes;
mutex_unlock(&phy->mutex);
/*
* The PHY configuration is lost in off mode, that's not an
* issue since the MPU power domain is forced on whilst the
* ISP is in use.
*/
csiphy_routing_cfg(phy, subdevs->interface, true,
subdevs->bus.ccp2.phy_layer);
/* DPHY timing configuration */
/* CSI-2 is DDR and we only count used lanes. */
csi2_ddrclk_khz = pipe->external_rate / 1000
/ (2 * hweight32(used_lanes)) * pipe->external_width;
reg = isp_reg_readl(csi2->isp, phy->phy_regs, ISPCSIPHY_REG0);
reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
ISPCSIPHY_REG0_THS_SETTLE_MASK);
/* THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1. */
reg |= (DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1)
<< ISPCSIPHY_REG0_THS_TERM_SHIFT;
/* THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3. */
reg |= (DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3)
<< ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
isp_reg_writel(csi2->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
reg = isp_reg_readl(csi2->isp, phy->phy_regs, ISPCSIPHY_REG1);
reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
ISPCSIPHY_REG1_TCLK_MISS_MASK |
ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
reg |= TCLK_TERM << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
reg |= TCLK_MISS << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
reg |= TCLK_SETTLE << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
isp_reg_writel(csi2->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
/* DPHY lane configuration */
reg = isp_reg_readl(csi2->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
for (i = 0; i < phy->num_data_lanes; i++) {
reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
reg |= (lanes->data[i].pol <<
ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
reg |= (lanes->data[i].pos <<
ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
}
reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
reg |= lanes->clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
reg |= lanes->clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
isp_reg_writel(csi2->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
return 0;
}
@@ -190,8 +284,9 @@ int omap3isp_csiphy_acquire(struct isp_csiphy *phy)
if (rval < 0)
goto done;
csiphy_dphy_config(phy);
csiphy_lanes_config(phy);
rval = omap3isp_csiphy_config(phy);
if (rval < 0)
goto done;
rval = csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_ON);
if (rval) {
@@ -211,6 +306,14 @@ void omap3isp_csiphy_release(struct isp_csiphy *phy)
{
mutex_lock(&phy->mutex);
if (phy->phy_in_use) {
struct isp_csi2_device *csi2 = phy->csi2;
struct isp_pipeline *pipe =
to_isp_pipeline(&csi2->subdev.entity);
struct isp_v4l2_subdevs_group *subdevs =
pipe->external->host_priv;
csiphy_routing_cfg(phy, subdevs->interface, false,
subdevs->bus.ccp2.phy_layer);
csiphy_power_autoswitch_enable(phy, false);
csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
regulator_disable(phy->vdd);
@@ -227,8 +330,6 @@ int omap3isp_csiphy_init(struct isp_device *isp)
struct isp_csiphy *phy1 = &isp->isp_csiphy1;
struct isp_csiphy *phy2 = &isp->isp_csiphy2;
isp->platform_cb.csiphy_config = csiphy_config;
phy2->isp = isp;
phy2->csi2 = &isp->isp_csi2a;
phy2->num_data_lanes = ISP_CSIPHY2_NUM_DATA_LANES;

파일 보기

@@ -32,14 +32,6 @@
struct isp_csi2_device;
struct regulator;
struct isp_csiphy_dphy_cfg {
u8 ths_term;
u8 ths_settle;
u8 tclk_term;
unsigned tclk_miss:1;
u8 tclk_settle;
};
struct isp_csiphy {
struct isp_device *isp;
struct mutex mutex; /* serialize csiphy configuration */
@@ -52,8 +44,6 @@ struct isp_csiphy {
unsigned int phy_regs;
u8 num_data_lanes; /* number of CSI2 Data Lanes supported */
struct isp_csiphy_lanes_cfg lanes;
struct isp_csiphy_dphy_cfg dphy;
};
int omap3isp_csiphy_acquire(struct isp_csiphy *phy);

파일 보기

@@ -74,11 +74,14 @@ static void hist_reset_mem(struct ispstat *hist)
static void hist_dma_config(struct ispstat *hist)
{
struct isp_device *isp = hist->isp;
hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32;
hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT;
hist->dma_config.frame_count = 1;
hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT;
hist->dma_config.src_start = OMAP3ISP_HIST_REG_BASE + ISPHIST_DATA;
hist->dma_config.src_start = isp->mmio_base_phys[OMAP3_ISP_IOMEM_HIST]
+ ISPHIST_DATA;
hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC;
hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
}
@@ -479,6 +482,8 @@ int omap3isp_hist_init(struct isp_device *isp)
return -ENOMEM;
memset(hist, 0, sizeof(*hist));
hist->isp = isp;
if (HIST_CONFIG_DMA)
ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
hist_dma_cb, hist, &hist->dma_ch);
@@ -496,7 +501,6 @@ int omap3isp_hist_init(struct isp_device *isp)
hist->ops = &hist_ops;
hist->priv = hist_cfg;
hist->event_type = V4L2_EVENT_OMAP3ISP_HIST;
hist->isp = isp;
ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
if (ret) {

파일 보기

@@ -200,10 +200,10 @@ static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable)
if (enable)
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
ISPPRV_PCR_INVALAW);
else
isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
ISPPRV_PCR_INVALAW);
}
/*
@@ -1014,7 +1014,7 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
/*
* preview_config_input_format - Configure the input format
* @prev: The preview engine
* @format: Format on the preview engine sink pad
* @info: Sink pad format information
*
* Enable and configure CFA interpolation for Bayer formats and disable it for
* greyscale formats.
@@ -1025,22 +1025,29 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
* reordered to support non-GRBG Bayer patterns.
*/
static void preview_config_input_format(struct isp_prev_device *prev,
const struct v4l2_mbus_framefmt *format)
const struct isp_format_info *info)
{
struct isp_device *isp = to_isp_device(prev);
struct prev_params *params;
switch (format->code) {
case V4L2_MBUS_FMT_SGRBG10_1X10:
if (info->width == 8)
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_WIDTH);
else
isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_WIDTH);
switch (info->flavor) {
case V4L2_MBUS_FMT_SGRBG8_1X8:
prev->params.cfa_order = 0;
break;
case V4L2_MBUS_FMT_SRGGB10_1X10:
case V4L2_MBUS_FMT_SRGGB8_1X8:
prev->params.cfa_order = 1;
break;
case V4L2_MBUS_FMT_SBGGR10_1X10:
case V4L2_MBUS_FMT_SBGGR8_1X8:
prev->params.cfa_order = 2;
break;
case V4L2_MBUS_FMT_SGBRG10_1X10:
case V4L2_MBUS_FMT_SGBRG8_1X8:
prev->params.cfa_order = 3;
break;
default:
@@ -1081,7 +1088,8 @@ static void preview_config_input_size(struct isp_prev_device *prev, u32 active)
unsigned int elv = prev->crop.top + prev->crop.height - 1;
u32 features;
if (format->code != V4L2_MBUS_FMT_Y10_1X10) {
if (format->code != V4L2_MBUS_FMT_Y8_1X8 &&
format->code != V4L2_MBUS_FMT_Y10_1X10) {
sph -= 2;
eph += 2;
slv -= 2;
@@ -1389,6 +1397,7 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev)
static void preview_configure(struct isp_prev_device *prev)
{
struct isp_device *isp = to_isp_device(prev);
const struct isp_format_info *info;
struct v4l2_mbus_framefmt *format;
unsigned long flags;
u32 update;
@@ -1402,17 +1411,18 @@ static void preview_configure(struct isp_prev_device *prev)
/* PREV_PAD_SINK */
format = &prev->formats[PREV_PAD_SINK];
info = omap3isp_video_format_info(format->code);
preview_adjust_bandwidth(prev);
preview_config_input_format(prev, format);
preview_config_input_format(prev, info);
preview_config_input_size(prev, active);
if (prev->input == PREVIEW_INPUT_CCDC)
preview_config_inlineoffset(prev, 0);
else
preview_config_inlineoffset(prev,
ALIGN(format->width, 0x20) * 2);
preview_config_inlineoffset(prev, ALIGN(format->width, 0x20) *
info->bpp);
preview_setup_hw(prev, update, active);
@@ -1709,6 +1719,11 @@ __preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
/* previewer format descriptions */
static const unsigned int preview_input_fmts[] = {
V4L2_MBUS_FMT_Y8_1X8,
V4L2_MBUS_FMT_SGRBG8_1X8,
V4L2_MBUS_FMT_SRGGB8_1X8,
V4L2_MBUS_FMT_SBGGR8_1X8,
V4L2_MBUS_FMT_SGBRG8_1X8,
V4L2_MBUS_FMT_Y10_1X10,
V4L2_MBUS_FMT_SGRBG10_1X10,
V4L2_MBUS_FMT_SRGGB10_1X10,

파일 보기

@@ -29,83 +29,6 @@
#define CM_CAM_MCLK_HZ 172800000 /* Hz */
/* ISP Submodules offset */
#define L4_34XX_BASE 0x48000000
#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000)
#define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE
#define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset))
#define OMAP3ISP_CCP2_REG_OFFSET 0x0400
#define OMAP3ISP_CCP2_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CCP2_REG_OFFSET)
#define OMAP3ISP_CCP2_REG(offset) (OMAP3ISP_CCP2_REG_BASE + (offset))
#define OMAP3ISP_CCDC_REG_OFFSET 0x0600
#define OMAP3ISP_CCDC_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CCDC_REG_OFFSET)
#define OMAP3ISP_CCDC_REG(offset) (OMAP3ISP_CCDC_REG_BASE + (offset))
#define OMAP3ISP_HIST_REG_OFFSET 0x0A00
#define OMAP3ISP_HIST_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_HIST_REG_OFFSET)
#define OMAP3ISP_HIST_REG(offset) (OMAP3ISP_HIST_REG_BASE + (offset))
#define OMAP3ISP_H3A_REG_OFFSET 0x0C00
#define OMAP3ISP_H3A_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_H3A_REG_OFFSET)
#define OMAP3ISP_H3A_REG(offset) (OMAP3ISP_H3A_REG_BASE + (offset))
#define OMAP3ISP_PREV_REG_OFFSET 0x0E00
#define OMAP3ISP_PREV_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_PREV_REG_OFFSET)
#define OMAP3ISP_PREV_REG(offset) (OMAP3ISP_PREV_REG_BASE + (offset))
#define OMAP3ISP_RESZ_REG_OFFSET 0x1000
#define OMAP3ISP_RESZ_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_RESZ_REG_OFFSET)
#define OMAP3ISP_RESZ_REG(offset) (OMAP3ISP_RESZ_REG_BASE + (offset))
#define OMAP3ISP_SBL_REG_OFFSET 0x1200
#define OMAP3ISP_SBL_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_SBL_REG_OFFSET)
#define OMAP3ISP_SBL_REG(offset) (OMAP3ISP_SBL_REG_BASE + (offset))
#define OMAP3ISP_CSI2A_REGS1_REG_OFFSET 0x1800
#define OMAP3ISP_CSI2A_REGS1_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CSI2A_REGS1_REG_OFFSET)
#define OMAP3ISP_CSI2A_REGS1_REG(offset) \
(OMAP3ISP_CSI2A_REGS1_REG_BASE + (offset))
#define OMAP3ISP_CSIPHY2_REG_OFFSET 0x1970
#define OMAP3ISP_CSIPHY2_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CSIPHY2_REG_OFFSET)
#define OMAP3ISP_CSIPHY2_REG(offset) (OMAP3ISP_CSIPHY2_REG_BASE + (offset))
#define OMAP3ISP_CSI2A_REGS2_REG_OFFSET 0x19C0
#define OMAP3ISP_CSI2A_REGS2_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CSI2A_REGS2_REG_OFFSET)
#define OMAP3ISP_CSI2A_REGS2_REG(offset) \
(OMAP3ISP_CSI2A_REGS2_REG_BASE + (offset))
#define OMAP3ISP_CSI2C_REGS1_REG_OFFSET 0x1C00
#define OMAP3ISP_CSI2C_REGS1_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CSI2C_REGS1_REG_OFFSET)
#define OMAP3ISP_CSI2C_REGS1_REG(offset) \
(OMAP3ISP_CSI2C_REGS1_REG_BASE + (offset))
#define OMAP3ISP_CSIPHY1_REG_OFFSET 0x1D70
#define OMAP3ISP_CSIPHY1_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CSIPHY1_REG_OFFSET)
#define OMAP3ISP_CSIPHY1_REG(offset) (OMAP3ISP_CSIPHY1_REG_BASE + (offset))
#define OMAP3ISP_CSI2C_REGS2_REG_OFFSET 0x1DC0
#define OMAP3ISP_CSI2C_REGS2_REG_BASE (OMAP3ISP_REG_BASE + \
OMAP3ISP_CSI2C_REGS2_REG_OFFSET)
#define OMAP3ISP_CSI2C_REGS2_REG(offset) \
(OMAP3ISP_CSI2C_REGS2_REG_BASE + (offset))
/* ISP module register offset */
#define ISP_REVISION (0x000)
@@ -1583,4 +1506,26 @@
#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_MASK \
(0x7fffff << ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT)
/* -----------------------------------------------------------------------------
* CONTROL registers for CSI-2 phy routing
*/
/* OMAP343X_CONTROL_CSIRXFE */
#define OMAP343X_CONTROL_CSIRXFE_CSIB_INV (1 << 7)
#define OMAP343X_CONTROL_CSIRXFE_RESENABLE (1 << 8)
#define OMAP343X_CONTROL_CSIRXFE_SELFORM (1 << 10)
#define OMAP343X_CONTROL_CSIRXFE_PWRDNZ (1 << 12)
#define OMAP343X_CONTROL_CSIRXFE_RESET (1 << 13)
/* OMAP3630_CONTROL_CAMERA_PHY_CTRL */
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT 2
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT 0
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY 0x0
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_STROBE 0x1
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_CLOCK 0x2
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_GPI 0x3
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_MASK 0x3
/* CCP2B: set to receive data from PHY2 instead of PHY1 */
#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2 (1 << 4)
#endif /* OMAP3_ISP_REG_H */

파일 보기

@@ -257,7 +257,7 @@ static int isp_stat_buf_queue(struct ispstat *stat)
if (!stat->active_buf)
return STAT_NO_BUF;
do_gettimeofday(&stat->active_buf->ts);
ktime_get_ts(&stat->active_buf->ts);
stat->active_buf->buf_size = stat->buf_size;
if (isp_stat_buf_check_magic(stat, stat->active_buf)) {
@@ -537,7 +537,8 @@ int omap3isp_stat_request_statistics(struct ispstat *stat,
return PTR_ERR(buf);
}
data->ts = buf->ts;
data->ts.tv_sec = buf->ts.tv_sec;
data->ts.tv_usec = buf->ts.tv_nsec / NSEC_PER_USEC;
data->config_counter = buf->config_counter;
data->frame_number = buf->frame_number;
data->buf_size = buf->buf_size;

파일 보기

@@ -50,7 +50,7 @@ struct ispstat_buffer {
struct iovm_struct *iovm;
void *virt_addr;
dma_addr_t dma_addr;
struct timeval ts;
struct timespec ts;
u32 buf_size;
u32 frame_number;
u16 config_counter;

파일 보기

@@ -1392,7 +1392,8 @@ int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
if (ret < 0)
printk(KERN_ERR "%s: could not register video device (%d)\n",
dev_err(video->isp->dev,
"%s: could not register video device (%d)\n",
__func__, ret);
return ret;