#include <media/omap3isp.h>
#include "devices.h"
-static struct i2c_board_info cm_t35_isp_i2c_boardinfo[] = {
+static struct isp_platform_subdev cm_t35_isp_subdevs[] = {
{
- I2C_BOARD_INFO("mt9t001", 0x5d),
- },
- {
- I2C_BOARD_INFO("tvp5150", 0x5c),
- },
-};
-
-static struct isp_subdev_i2c_board_info cm_t35_isp_primary_subdevs[] = {
- {
- .board_info = &cm_t35_isp_i2c_boardinfo[0],
- .i2c_adapter_id = 3,
- },
- { NULL, 0, },
-};
-
-static struct isp_subdev_i2c_board_info cm_t35_isp_secondary_subdevs[] = {
- {
- .board_info = &cm_t35_isp_i2c_boardinfo[1],
+ .board_info = &(struct i2c_board_info){
+ I2C_BOARD_INFO("mt9t001", 0x5d)
+ },
.i2c_adapter_id = 3,
- },
- { NULL, 0, },
-};
-
-static struct isp_v4l2_subdevs_group cm_t35_isp_subdevs[] = {
- {
- .subdevs = cm_t35_isp_primary_subdevs,
- .interface = ISP_INTERFACE_PARALLEL,
- .bus = {
- .parallel = {
- .clk_pol = 1,
+ .bus = &(struct isp_bus_cfg){
+ .interface = ISP_INTERFACE_PARALLEL,
+ .bus = {
+ .parallel = {
+ .clk_pol = 1,
+ },
},
},
},
{
- .subdevs = cm_t35_isp_secondary_subdevs,
- .interface = ISP_INTERFACE_PARALLEL,
- .bus = {
- .parallel = {
- .clk_pol = 0,
+ .board_info = &(struct i2c_board_info){
+ I2C_BOARD_INFO("tvp5150", 0x5c),
+ },
+ .i2c_adapter_id = 3,
+ .bus = &(struct isp_bus_cfg){
+ .interface = ISP_INTERFACE_PARALLEL,
+ .bus = {
+ .parallel = {
+ .clk_pol = 0,
+ },
},
},
},
- { NULL, 0, },
+ { 0 },
};
static struct isp_platform_data cm_t35_isp_pdata = {
*/
void omap3isp_configure_bridge(struct isp_device *isp,
enum ccdc_input_entity input,
- const struct isp_parallel_platform_data *pdata,
+ const struct isp_parallel_cfg *parcfg,
unsigned int shift, unsigned int bridge)
{
u32 ispctrl_val;
switch (input) {
case CCDC_INPUT_PARALLEL:
ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
- ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
- shift += pdata->data_lane_shift * 2;
+ ispctrl_val |= parcfg->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
+ shift += parcfg->data_lane_shift * 2;
break;
case CCDC_INPUT_CSI2A:
}
/*
- * isp_register_subdev_group - Register a group of subdevices
+ * isp_register_subdev - Register a sub-device
* @isp: OMAP3 ISP device
- * @board_info: I2C subdevs board information array
+ * @isp_subdev: platform data related to a sub-device
*
- * Register all I2C subdevices in the board_info array. The array must be
- * terminated by a NULL entry, and the first entry must be the sensor.
+ * Register an I2C sub-device which has not been registered by other
+ * means (such as the Device Tree).
*
- * Return a pointer to the sensor media entity if it has been successfully
+ * Return a pointer to the sub-device if it has been successfully
* registered, or NULL otherwise.
*/
static struct v4l2_subdev *
-isp_register_subdev_group(struct isp_device *isp,
- struct isp_subdev_i2c_board_info *board_info)
+isp_register_subdev(struct isp_device *isp,
+ struct isp_platform_subdev *isp_subdev)
{
- struct v4l2_subdev *sensor = NULL;
- unsigned int first;
+ struct i2c_adapter *adapter;
+ struct v4l2_subdev *sd;
- if (board_info->board_info == NULL)
+ if (isp_subdev->board_info == NULL)
return NULL;
- for (first = 1; board_info->board_info; ++board_info, first = 0) {
- struct v4l2_subdev *subdev;
- struct i2c_adapter *adapter;
-
- adapter = i2c_get_adapter(board_info->i2c_adapter_id);
- if (adapter == NULL) {
- 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);
- continue;
- }
-
- subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
- board_info->board_info, NULL);
- if (subdev == NULL) {
- dev_err(isp->dev, "%s: Unable to register subdev %s\n",
- __func__, board_info->board_info->type);
- continue;
- }
+ adapter = i2c_get_adapter(isp_subdev->i2c_adapter_id);
+ if (adapter == NULL) {
+ dev_err(isp->dev,
+ "%s: Unable to get I2C adapter %d for device %s\n",
+ __func__, isp_subdev->i2c_adapter_id,
+ isp_subdev->board_info->type);
+ return NULL;
+ }
- if (first)
- sensor = subdev;
+ sd = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
+ isp_subdev->board_info, NULL);
+ if (sd == NULL) {
+ dev_err(isp->dev, "%s: Unable to register subdev %s\n",
+ __func__, isp_subdev->board_info->type);
+ return NULL;
}
- return sensor;
+ return sd;
}
static int isp_link_entity(
static int isp_register_entities(struct isp_device *isp)
{
struct isp_platform_data *pdata = isp->pdata;
- struct isp_v4l2_subdevs_group *subdevs;
+ struct isp_platform_subdev *isp_subdev;
int ret;
isp->media_dev.dev = isp->dev;
goto done;
/* Register external entities */
- for (subdevs = pdata ? pdata->subdevs : NULL;
- subdevs && subdevs->subdevs; ++subdevs) {
- struct v4l2_subdev *sensor;
+ for (isp_subdev = pdata ? pdata->subdevs : NULL;
+ isp_subdev && isp_subdev->board_info; isp_subdev++) {
+ struct v4l2_subdev *sd;
- sensor = isp_register_subdev_group(isp, subdevs->subdevs);
- if (sensor == NULL)
+ sd = isp_register_subdev(isp, isp_subdev);
+
+ /*
+ * No bus information --- this is either a flash or a
+ * lens subdev.
+ */
+ if (!sd || !isp_subdev->bus)
continue;
- sensor->host_priv = subdevs;
+ sd->host_priv = isp_subdev->bus;
- ret = isp_link_entity(isp, &sensor->entity, subdevs->interface);
+ ret = isp_link_entity(isp, &sd->entity,
+ isp_subdev->bus->interface);
if (ret < 0)
goto done;
}
void omap3isp_pipeline_cancel_stream(struct isp_pipeline *pipe);
void omap3isp_configure_bridge(struct isp_device *isp,
enum ccdc_input_entity input,
- const struct isp_parallel_platform_data *pdata,
+ const struct isp_parallel_cfg *buscfg,
unsigned int shift, unsigned int bridge);
struct isp_device *omap3isp_get(struct isp_device *isp);
/*
* ccdc_config_sync_if - Set CCDC sync interface configuration
* @ccdc: Pointer to ISP CCDC device.
- * @pdata: Parallel interface platform data (may be NULL)
+ * @parcfg: Parallel interface platform data (may be NULL)
* @data_size: Data size
*/
static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
- struct isp_parallel_platform_data *pdata,
+ struct isp_parallel_cfg *parcfg,
unsigned int data_size)
{
struct isp_device *isp = to_isp_device(ccdc);
break;
}
- if (pdata && pdata->data_pol)
+ if (parcfg && parcfg->data_pol)
syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
- if (pdata && pdata->hs_pol)
+ if (parcfg && parcfg->hs_pol)
syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
/* The polarity of the vertical sync signal output by the BT.656
* decoder is not documented and seems to be active low.
*/
- if ((pdata && pdata->vs_pol) || ccdc->bt656)
+ if ((parcfg && parcfg->vs_pol) || ccdc->bt656)
syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
- if (pdata && pdata->fld_pol)
+ if (parcfg && parcfg->fld_pol)
syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
static void ccdc_configure(struct isp_ccdc_device *ccdc)
{
struct isp_device *isp = to_isp_device(ccdc);
- struct isp_parallel_platform_data *pdata = NULL;
+ struct isp_parallel_cfg *parcfg = NULL;
struct v4l2_subdev *sensor;
struct v4l2_mbus_framefmt *format;
const struct v4l2_rect *crop;
if (!ret)
ccdc->bt656 = cfg.type == V4L2_MBUS_BT656;
- pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
+ parcfg = &((struct isp_bus_cfg *)sensor->host_priv)
->bus.parallel;
}
else
bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
- omap3isp_configure_bridge(isp, ccdc->input, pdata, shift, bridge);
+ omap3isp_configure_bridge(isp, ccdc->input, parcfg, shift, bridge);
/* Configure the sync interface. */
- ccdc_config_sync_if(ccdc, pdata, depth_out);
+ ccdc_config_sync_if(ccdc, parcfg, depth_out);
syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
/* We've got a parallel sensor here. */
if (ccdc->input == CCDC_INPUT_PARALLEL) {
- struct isp_parallel_platform_data *pdata =
- &((struct isp_v4l2_subdevs_group *)
+ struct isp_parallel_cfg *parcfg =
+ &((struct isp_bus_cfg *)
media_entity_to_v4l2_subdev(link->source->entity)
->host_priv)->bus.parallel;
- parallel_shift = pdata->data_lane_shift * 2;
+ parallel_shift = parcfg->data_lane_shift * 2;
} else {
parallel_shift = 0;
}
/*
* ccp2_phyif_config - Initialize CCP2 phy interface config
* @ccp2: Pointer to ISP CCP2 device
- * @pdata: CCP2 platform data
+ * @buscfg: CCP2 platform data
*
* Configure the CCP2 physical interface module from platform data.
*
* Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.
*/
static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
- const struct isp_ccp2_platform_data *pdata)
+ const struct isp_ccp2_cfg *buscfg)
{
struct isp_device *isp = to_isp_device(ccp2);
u32 val;
ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE;
/* Data/strobe physical layer */
BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,
- pdata->phy_layer);
+ buscfg->phy_layer);
BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,
- pdata->strobe_clk_pol);
+ buscfg->strobe_clk_pol);
isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
if (!(val & ISPCCP2_CTRL_MODE)) {
- if (pdata->ccp2_mode == ISP_CCP2_MODE_CCP2)
+ if (buscfg->ccp2_mode == ISP_CCP2_MODE_CCP2)
dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
- if (pdata->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
+ if (buscfg->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
/* Strobe mode requires CCP2 */
return -EIO;
}
*/
static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
{
- const struct isp_v4l2_subdevs_group *pdata;
+ const struct isp_bus_cfg *buscfg;
struct v4l2_mbus_framefmt *format;
struct media_pad *pad;
struct v4l2_subdev *sensor;
pad = media_entity_remote_pad(&ccp2->pads[CCP2_PAD_SINK]);
sensor = media_entity_to_v4l2_subdev(pad->entity);
- pdata = sensor->host_priv;
+ buscfg = sensor->host_priv;
- ret = ccp2_phyif_config(ccp2, &pdata->bus.ccp2);
+ ret = ccp2_phyif_config(ccp2, &buscfg->bus.ccp2);
if (ret < 0)
return ret;
- ccp2_vp_config(ccp2, pdata->bus.ccp2.vpclk_div + 1);
+ ccp2_vp_config(ccp2, buscfg->bus.ccp2.vpclk_div + 1);
v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);
format = &ccp2->formats[CCP2_PAD_SINK];
ccp2->if_cfg.data_start = lines;
- ccp2->if_cfg.crc = pdata->bus.ccp2.crc;
+ ccp2->if_cfg.crc = buscfg->bus.ccp2.crc;
ccp2->if_cfg.format = format->code;
ccp2->if_cfg.data_size = format->height;
static int csi2_configure(struct isp_csi2_device *csi2)
{
- const struct isp_v4l2_subdevs_group *pdata;
+ const struct isp_bus_cfg *buscfg;
struct isp_device *isp = csi2->isp;
struct isp_csi2_timing_cfg *timing = &csi2->timing[0];
struct v4l2_subdev *sensor;
pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]);
sensor = media_entity_to_v4l2_subdev(pad->entity);
- pdata = sensor->host_priv;
+ buscfg = sensor->host_priv;
csi2->frame_skip = 0;
v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
- csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
+ csi2->ctrl.vp_out_ctrl = buscfg->bus.csi2.vpclk_div;
csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE;
- csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
+ csi2->ctrl.ecc_enable = buscfg->bus.csi2.crc;
timing->ionum = 1;
timing->force_rx_mode = 1;
{
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_bus_cfg *buscfg = 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;
+ if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1
+ || buscfg->interface == ISP_INTERFACE_CCP2B_PHY2)
+ lanes = &buscfg->bus.ccp2.lanecfg;
else
- lanes = &subdevs->bus.csi2.lanecfg;
+ lanes = &buscfg->bus.csi2.lanecfg;
/* Clock and data lanes verification */
for (i = 0; i < phy->num_data_lanes; i++) {
* 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);
+ csiphy_routing_cfg(phy, buscfg->interface, true,
+ buscfg->bus.ccp2.phy_layer);
/* DPHY timing configuration */
/* CSI-2 is DDR and we only count used lanes. */
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_bus_cfg *buscfg = pipe->external->host_priv;
- csiphy_routing_cfg(phy, subdevs->interface, false,
- subdevs->bus.ccp2.phy_layer);
+ csiphy_routing_cfg(phy, buscfg->interface, false,
+ buscfg->bus.ccp2.phy_layer);
csiphy_power_autoswitch_enable(phy, false);
csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
regulator_disable(phy->vdd);
};
/**
- * struct isp_parallel_platform_data - Parallel interface platform data
+ * struct isp_parallel_cfg - Parallel interface configuration
* @data_lane_shift: Data lane shifter
* ISP_LANE_SHIFT_0 - CAMEXT[13:0] -> CAM[13:0]
* ISP_LANE_SHIFT_2 - CAMEXT[13:2] -> CAM[11:0]
* @data_pol: Data polarity
* 0 - Normal, 1 - One's complement
*/
-struct isp_parallel_platform_data {
+struct isp_parallel_cfg {
unsigned int data_lane_shift:2;
unsigned int clk_pol:1;
unsigned int hs_pol:1;
};
/**
- * struct isp_ccp2_platform_data - CCP2 interface platform data
+ * struct isp_ccp2_cfg - CCP2 interface configuration
* @strobe_clk_pol: Strobe/clock polarity
* 0 - Non Inverted, 1 - Inverted
* @crc: Enable the cyclic redundancy check
* ISP_CCP2_PHY_DATA_STROBE - Data/strobe physical layer
* @vpclk_div: Video port output clock control
*/
-struct isp_ccp2_platform_data {
+struct isp_ccp2_cfg {
unsigned int strobe_clk_pol:1;
unsigned int crc:1;
unsigned int ccp2_mode:1;
};
/**
- * struct isp_csi2_platform_data - CSI2 interface platform data
+ * struct isp_csi2_cfg - CSI2 interface configuration
* @crc: Enable the cyclic redundancy check
* @vpclk_div: Video port output clock control
*/
-struct isp_csi2_platform_data {
+struct isp_csi2_cfg {
unsigned crc:1;
unsigned vpclk_div:2;
struct isp_csiphy_lanes_cfg lanecfg;
};
-struct isp_subdev_i2c_board_info {
- struct i2c_board_info *board_info;
- int i2c_adapter_id;
-};
-
-struct isp_v4l2_subdevs_group {
- struct isp_subdev_i2c_board_info *subdevs;
+struct isp_bus_cfg {
enum isp_interface_type interface;
union {
- struct isp_parallel_platform_data parallel;
- struct isp_ccp2_platform_data ccp2;
- struct isp_csi2_platform_data csi2;
+ struct isp_parallel_cfg parallel;
+ struct isp_ccp2_cfg ccp2;
+ struct isp_csi2_cfg csi2;
} bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
};
+struct isp_platform_subdev {
+ struct i2c_board_info *board_info;
+ int i2c_adapter_id;
+ struct isp_bus_cfg *bus;
+};
+
struct isp_platform_xclk {
const char *dev_id;
const char *con_id;
struct isp_platform_data {
struct isp_platform_xclk xclks[2];
- struct isp_v4l2_subdevs_group *subdevs;
+ struct isp_platform_subdev *subdevs;
void (*set_constraints)(struct isp_device *isp, bool enable);
};