/*
 * Sensor subdevice helper functions
 */
static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
				   struct fimc_sensor_info *s_info)
{
	struct i2c_adapter *adapter;
	struct v4l2_subdev *sd = NULL;

	if (!s_info || !fmd)
		return NULL;

	adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num);
	if (!adapter)
		return NULL;
	sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
				       s_info->pdata->board_info, NULL);
	if (IS_ERR_OR_NULL(sd)) {
		i2c_put_adapter(adapter);
		v4l2_err(&fmd->v4l2_dev, "Failed to acquire subdev\n");
		return NULL;
	}
	v4l2_set_subdev_hostdata(sd, s_info);
	sd->grp_id = SENSOR_GROUP_ID;

	v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
		  s_info->pdata->board_info->type);
	return sd;
}
Beispiel #2
0
/*
 * Sensor subdevice helper functions
 */
static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
				   struct fimc_sensor_info *s_info)
{
	struct i2c_adapter *adapter;
	struct v4l2_subdev *sd = NULL;

	if (!s_info || !fmd)
		return NULL;

	adapter = i2c_get_adapter(s_info->pdata.i2c_bus_num);
	if (!adapter) {
		v4l2_warn(&fmd->v4l2_dev,
			  "Failed to get I2C adapter %d, deferring probe\n",
			  s_info->pdata.i2c_bus_num);
		return ERR_PTR(-EPROBE_DEFER);
	}
	sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
				       s_info->pdata.board_info, NULL);
	if (IS_ERR_OR_NULL(sd)) {
		i2c_put_adapter(adapter);
		v4l2_warn(&fmd->v4l2_dev,
			  "Failed to acquire subdev %s, deferring probe\n",
			  s_info->pdata.board_info->type);
		return ERR_PTR(-EPROBE_DEFER);
	}
	v4l2_set_subdev_hostdata(sd, s_info);
	sd->grp_id = SENSOR_GROUP_ID;

	v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
		  s_info->pdata.board_info->type);
	return sd;
}
struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
		struct i2c_adapter *adapter, const char *client_type,
		u8 addr, const unsigned short *probe_addrs)
{
	struct i2c_board_info info;

	memset(&info, 0, sizeof(info));
	strlcpy(info.type, client_type, sizeof(info.type));
	info.addr = addr;

	return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
}
Beispiel #4
0
static int camif_register_sensor(struct camif_dev *camif)
{
	struct s3c_camif_sensor_info *sensor = &camif->pdata.sensor;
	struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
	struct i2c_adapter *adapter;
	struct v4l2_subdev_format format;
	struct v4l2_subdev *sd;
	int ret;

	camif->sensor.sd = NULL;

	if (sensor->i2c_board_info.addr == 0)
		return -EINVAL;

	adapter = i2c_get_adapter(sensor->i2c_bus_num);
	if (adapter == NULL) {
		v4l2_warn(v4l2_dev, "failed to get I2C adapter %d\n",
			  sensor->i2c_bus_num);
		return -EPROBE_DEFER;
	}

	sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter,
				       &sensor->i2c_board_info, NULL);
	if (sd == NULL) {
		i2c_put_adapter(adapter);
		v4l2_warn(v4l2_dev, "failed to acquire subdev %s\n",
			  sensor->i2c_board_info.type);
		return -EPROBE_DEFER;
	}
	camif->sensor.sd = sd;

	v4l2_info(v4l2_dev, "registered sensor subdevice %s\n", sd->name);

	/* Get initial pixel format and set it at the camif sink pad */
	format.pad = 0;
	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
	ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);

	if (ret < 0)
		return 0;

	format.pad = CAMIF_SD_PAD_SINK;
	v4l2_subdev_call(&camif->subdev, pad, set_fmt, NULL, &format);

	v4l2_info(sd, "Initial format from sensor: %dx%d, %#x\n",
		  format.format.width, format.format.height,
		  format.format.code);
	return 0;
}
Beispiel #5
0
static struct v4l2_subdev *
unicam_register_subdev_group(struct unicam_device *unicam,
		struct unicam_subdev_i2c_board_info *i2c_info)
{
	struct v4l2_subdev *sensor = NULL;
	struct i2c_adapter *adapter;

	if (i2c_info == NULL)
		return NULL;

	adapter = i2c_get_adapter(i2c_info->i2c_adapter_id);
	if (adapter == NULL) {
		dev_err(unicam->dev, "unabled to get i2c adapter %d for"
				"device %s\n", i2c_info->i2c_adapter_id,
				i2c_info->board_info.type);
		return NULL;
	}

	sensor = v4l2_i2c_new_subdev_board(&unicam->v4l2_dev, adapter,
			&i2c_info->board_info, NULL);

	return sensor;
}
Beispiel #6
0
static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
        struct s5p_fimc_isp_info *isp_info)
{
    struct i2c_adapter *i2c_adap;
    struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
    struct v4l2_subdev *sd = NULL;

    i2c_adap = i2c_get_adapter(isp_info->i2c_bus_num);
    if (!i2c_adap)
        return ERR_PTR(-ENOMEM);

    sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
                                   isp_info->board_info, NULL);
    if (!sd) {
        v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
        return NULL;
    }

    v4l2_info(&vid_cap->v4l2_dev, "subdevice %s registered successfuly\n",
              isp_info->board_info->type);

    return sd;
}
Beispiel #7
0
/*
 * Sensor subdevice helper functions
 */
static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
						struct fimc_source_info *si)
{
	struct i2c_adapter *adapter;
	struct v4l2_subdev *sd = NULL;

	if (!si || !fmd)
		return NULL;
	/*
	 * If FIMC bus type is not Writeback FIFO assume it is same
	 * as sensor_bus_type.
	 */
	si->fimc_bus_type = si->sensor_bus_type;

	adapter = i2c_get_adapter(si->i2c_bus_num);
	if (!adapter) {
		v4l2_warn(&fmd->v4l2_dev,
			  "Failed to get I2C adapter %d, deferring probe\n",
			  si->i2c_bus_num);
		return ERR_PTR(-EPROBE_DEFER);
	}
	sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
						si->board_info, NULL);
	if (IS_ERR_OR_NULL(sd)) {
		i2c_put_adapter(adapter);
		v4l2_warn(&fmd->v4l2_dev,
			  "Failed to acquire subdev %s, deferring probe\n",
			  si->board_info->type);
		return ERR_PTR(-EPROBE_DEFER);
	}
	v4l2_set_subdev_hostdata(sd, si);
	sd->grp_id = GRP_ID_SENSOR;

	v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
		  sd->name);
	return sd;
}
Beispiel #8
0
/*
 * iss_register_subdev_group - Register a group of subdevices
 * @iss: OMAP4 ISS device
 * @board_info: I2C subdevs board information array
 *
 * 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.
 *
 * Return a pointer to the sensor media entity if it has been successfully
 * registered, or NULL otherwise.
 */
static struct v4l2_subdev *
iss_register_subdev_group(struct iss_device *iss,
			  struct iss_subdev_i2c_board_info *board_info)
{
	struct v4l2_subdev *sensor = NULL;
	unsigned int first;

	if (!board_info->board_info)
		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) {
			dev_err(iss->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(&iss->v4l2_dev, adapter,
				board_info->board_info, NULL);
		if (!subdev) {
			dev_err(iss->dev, "Unable to register subdev %s\n",
				board_info->board_info->type);
			continue;
		}

		if (first)
			sensor = subdev;
	}

	return sensor;
}
static int atomisp_subdev_probe(struct atomisp_device *isp)
{
	struct atomisp_platform_data *pdata = NULL;
	struct intel_v4l2_subdev_table *subdevs;
	struct v4l2_subdev *subdev = NULL;
	struct i2c_adapter *adapter = NULL;
	struct i2c_board_info *board_info;
	int raw_index = -1;

	/*
	 * fixing me!
	 * currently no function intel_get_v4l2_subdev_table()
	 * defined in board specific source code
	 */
#ifndef CONFIG_X86_MRFLD
	pdata = (struct atomisp_platform_data *)intel_get_v4l2_subdev_table();
#else
	pdata = NULL;
#endif
	if (pdata == NULL) {
		v4l2_err(&atomisp_dev, "no platform data available\n");
		return -ENODEV;
	}

	for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) {
		board_info = &subdevs->v4l2_subdev.board_info;

		adapter = i2c_get_adapter(subdevs->v4l2_subdev.i2c_adapter_id);
		if (adapter == NULL) {
			v4l2_err(&atomisp_dev,
				    "Failed to find i2c adapter for subdev %s\n"
				    , board_info->type);
			break;
		}

		subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
				board_info, NULL);

		if (subdev == NULL) {
			v4l2_warn(&atomisp_dev,
				    "Subdev %s detection fail\n",
				    board_info->type);
			continue;
		}

		v4l2_info(&atomisp_dev,
			    "Subdev %s successfully register\n",
			  board_info->type);

		switch (subdevs->type) {
		case RAW_CAMERA:
			raw_index = isp->input_cnt;
		case SOC_CAMERA:
			if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) {
				v4l2_warn(&atomisp_dev,
					"too many atomisp inputs, ignored\n");
				break;
			}

			isp->inputs[isp->input_cnt].type = subdevs->type;
			isp->inputs[isp->input_cnt].port = subdevs->port;
			isp->inputs[isp->input_cnt].camera = subdev;
			isp->inputs[isp->input_cnt].shading_table = NULL;
			isp->inputs[isp->input_cnt].morph_table = NULL;
			/*
			 * initialize the subdev frame size, then next we can
			 * judge whether frame_size store effective value via
			 * pixel_format.
			 */
			isp->inputs[isp->input_cnt].frame_size.pixel_format = 0;
			isp->input_cnt++;
			break;
		case CAMERA_MOTOR:
			isp->motor = subdev;
			break;
		case LED_FLASH:
		case XENON_FLASH:
			isp->flash = subdev;
			break;
		default:
			v4l2_dbg(1, dbg_level, &atomisp_dev,
				"unkonw subdev probed\n");
			break;
		}

	}

	/*
	 * HACK: Currently VCM belongs to primary sensor only, but correct
	 * approach must be to acquire from platform code which sensor
	 * owns it.
	 */
	if (isp->motor && raw_index >= 0)
		isp->inputs[raw_index].motor = isp->motor;

	/*Check camera for at least one subdev in it */
	if (!isp->inputs[0].camera) {
		v4l2_err(&atomisp_dev, "atomisp: "
		       "no camera attached or fail to detect\n");
		return -ENODEV;
	}
	return 0;
}
Beispiel #10
0
static int __devinit hdmi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	int ret;
	unsigned int irq_type;

	dev_dbg(dev, "probe start\n");

	hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(dev, "out of memory\n");
		ret = -ENOMEM;
		goto fail;
	}

	hdmi_dev->dev = dev;

	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_hdev;

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(dev, "get memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* External hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(dev, "get external interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->ext_irq = res->start;

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (res == NULL) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->int_irq = res->start;

	/* workqueue for HPD */
	hdmi_dev->hpd_wq = create_workqueue("hdmi-hpd");
	if (hdmi_dev->hpd_wq == NULL)
		ret = -ENXIO;
	INIT_WORK(&hdmi_dev->hpd_work, s5p_hpd_kobject_uevent);

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail_regs;
	}

	drv_data = (struct hdmi_driver_data *)
		platform_get_device_id(pdev)->driver_data;
	dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

	phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
	if (phy_adapter == NULL) {
		dev_err(dev, "adapter request failed\n");
		ret = -ENXIO;
		goto fail_vdev;
	}

	hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
		phy_adapter, &hdmiphy_info, NULL);
	/* on failure or not adapter is no longer useful */
	i2c_put_adapter(phy_adapter);
	if (hdmi_dev->phy_sd == NULL) {
		dev_err(dev, "missing subdev for hdmiphy\n");
		ret = -ENODEV;
		goto fail_vdev;
	}

	/* HDMI PHY power off
	 * HDMI PHY is on as default configuration
	 * So, HDMI PHY must be turned off if it's not used */
	clk_enable(hdmi_dev->res.hdmiphy);
	v4l2_subdev_call(hdmi_dev->phy_sd, core, s_power, 0);
	clk_disable(hdmi_dev->res.hdmiphy);

	pm_runtime_enable(dev);

	/* irq setting by TV power on/off status */
	if (!pm_runtime_suspended(hdmi_dev->dev)) {
		hdmi_dev->curr_irq = hdmi_dev->int_irq;
		irq_type = 0;
		s5p_v4l2_int_src_hdmi_hpd();
	} else {
		if (s5p_v4l2_hpd_read_gpio())
			atomic_set(&hdmi_dev->hpd_state, HPD_HIGH);
		else
			atomic_set(&hdmi_dev->hpd_state, HPD_LOW);
		hdmi_dev->curr_irq = hdmi_dev->ext_irq;
		irq_type = IRQ_TYPE_EDGE_BOTH;
		s5p_v4l2_int_src_ext_hpd();
	}

	hdmi_dev->hpd_user_checked = false;

	ret = request_irq(hdmi_dev->curr_irq, hdmi_irq_handler,
			irq_type, "hdmi", hdmi_dev);

	if (ret) {
		dev_err(dev, "request interrupt failed.\n");
		goto fail_vdev;
	}

	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);

	/* default audio configuration : enable audio */
	hdmi_dev->audio_enable = 1;
	hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_irq;

	hdmi_entity_info_print(hdmi_dev);

	/* initialize hdcp resource */
	ret = hdcp_prepare(hdmi_dev);
	if (ret)
		goto fail_irq;

	dev_info(dev, "probe sucessful\n");

	return 0;

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail_irq:
	free_irq(hdmi_dev->curr_irq, hdmi_dev);

fail_regs:
	iounmap(hdmi_dev->regs);

fail_init:
	hdmi_resources_cleanup(hdmi_dev);

fail_hdev:
	kfree(hdmi_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}
Beispiel #11
0
/**
 * vpbe_initialize() - Initialize the vpbe display controller
 * @vpbe_dev - vpbe device ptr
 *
 * Master frame buffer device drivers calls this to initialize vpbe
 * display controller. This will then registers v4l2 device and the sub
 * devices and sets a current encoder sub device for display. v4l2 display
 * device driver is the master and frame buffer display device driver is
 * the slave. Frame buffer display driver checks the initialized during
 * probe and exit if not initialized. Returns status.
 */
static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
{
	struct encoder_config_info *enc_info;
	struct amp_config_info *amp_info;
	struct v4l2_subdev **enc_subdev;
	struct osd_state *osd_device;
	struct i2c_adapter *i2c_adap;
	int output_index;
	int num_encoders;
	int ret = 0;
	int err;
	int i;

	/*
	 * v4l2 abd FBDev frame buffer devices will get the vpbe_dev pointer
	 * from the platform device by iteration of platform drivers and
	 * matching with device name
	 */
	if (NULL == vpbe_dev || NULL == dev) {
		printk(KERN_ERR "Null device pointers.\n");
		return -ENODEV;
	}

	if (vpbe_dev->initialized)
		return 0;

	mutex_lock(&vpbe_dev->lock);

	if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
		/* We have dac clock available for platform */
		vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
		if (IS_ERR(vpbe_dev->dac_clk)) {
			ret =  PTR_ERR(vpbe_dev->dac_clk);
			goto fail_mutex_unlock;
		}
		if (clk_prepare_enable(vpbe_dev->dac_clk)) {
			ret =  -ENODEV;
			goto fail_mutex_unlock;
		}
	}

	/* first enable vpss clocks */
	vpss_enable_clock(VPSS_VPBE_CLOCK, 1);

	/* First register a v4l2 device */
	ret = v4l2_device_register(dev, &vpbe_dev->v4l2_dev);
	if (ret) {
		v4l2_err(dev->driver,
			"Unable to register v4l2 device.\n");
		goto fail_clk_put;
	}
	v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");

	err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev,
			       platform_device_get);
	if (err < 0)
		return err;

	vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev,
					   vpbe_dev->cfg->venc.module_name);
	/* register venc sub device */
	if (vpbe_dev->venc == NULL) {
		v4l2_err(&vpbe_dev->v4l2_dev,
			"vpbe unable to init venc sub device\n");
		ret = -ENODEV;
		goto fail_dev_unregister;
	}
	/* initialize osd device */
	osd_device = vpbe_dev->osd_device;

	if (NULL != osd_device->ops.initialize) {
		err = osd_device->ops.initialize(osd_device);
		if (err) {
			v4l2_err(&vpbe_dev->v4l2_dev,
				 "unable to initialize the OSD device");
			err = -ENOMEM;
			goto fail_dev_unregister;
		}
	}

	/*
	 * Register any external encoders that are configured. At index 0 we
	 * store venc sd index.
	 */
	num_encoders = vpbe_dev->cfg->num_ext_encoders + 1;
	vpbe_dev->encoders = kmalloc(
				sizeof(struct v4l2_subdev *)*num_encoders,
				GFP_KERNEL);
	if (NULL == vpbe_dev->encoders) {
		v4l2_err(&vpbe_dev->v4l2_dev,
			"unable to allocate memory for encoders sub devices");
		ret = -ENOMEM;
		goto fail_dev_unregister;
	}

	i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
	for (i = 0; i < (vpbe_dev->cfg->num_ext_encoders + 1); i++) {
		if (i == 0) {
			/* venc is at index 0 */
			enc_subdev = &vpbe_dev->encoders[i];
			*enc_subdev = vpbe_dev->venc;
			continue;
		}
		enc_info = &vpbe_dev->cfg->ext_encoders[i];
		if (enc_info->is_i2c) {
			enc_subdev = &vpbe_dev->encoders[i];
			*enc_subdev = v4l2_i2c_new_subdev_board(
						&vpbe_dev->v4l2_dev, i2c_adap,
						&enc_info->board_info, NULL);
			if (*enc_subdev)
				v4l2_info(&vpbe_dev->v4l2_dev,
					  "v4l2 sub device %s registered\n",
					  enc_info->module_name);
			else {
				v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s"
					 " failed to register",
					 enc_info->module_name);
				ret = -ENODEV;
				goto fail_kfree_encoders;
			}
		} else
			v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
				 " currently not supported");
	}
	/* Add amplifier subdevice for dm365 */
	if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) &&
			vpbe_dev->cfg->amp != NULL) {
		amp_info = vpbe_dev->cfg->amp;
		if (amp_info->is_i2c) {
			vpbe_dev->amp = v4l2_i2c_new_subdev_board(
			&vpbe_dev->v4l2_dev, i2c_adap,
			&amp_info->board_info, NULL);
			if (!vpbe_dev->amp) {
				v4l2_err(&vpbe_dev->v4l2_dev,
					 "amplifier %s failed to register",
					 amp_info->module_name);
				ret = -ENODEV;
				goto fail_kfree_encoders;
			}
			v4l2_info(&vpbe_dev->v4l2_dev,
					  "v4l2 sub device %s registered\n",
					  amp_info->module_name);
		} else {
			    vpbe_dev->amp = NULL;
			    v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers"
			    " currently not supported");
		}
	} else {
	    vpbe_dev->amp = NULL;
	}

	/* set the current encoder and output to that of venc by default */
	vpbe_dev->current_sd_index = 0;
	vpbe_dev->current_out_index = 0;
	output_index = 0;

	mutex_unlock(&vpbe_dev->lock);

	printk(KERN_NOTICE "Setting default output to %s\n", def_output);
	ret = vpbe_set_default_output(vpbe_dev);
	if (ret) {
		v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s",
			 def_output);
		return ret;
	}

	printk(KERN_NOTICE "Setting default mode to %s\n", def_mode);
	ret = vpbe_set_default_mode(vpbe_dev);
	if (ret) {
		v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s",
			 def_mode);
		return ret;
	}
	vpbe_dev->initialized = 1;
	/* TBD handling of bootargs for default output and mode */
	return 0;

fail_kfree_encoders:
	kfree(vpbe_dev->encoders);
fail_dev_unregister:
	v4l2_device_unregister(&vpbe_dev->v4l2_dev);
fail_clk_put:
	if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
		clk_disable_unprepare(vpbe_dev->dac_clk);
		clk_put(vpbe_dev->dac_clk);
	}
fail_mutex_unlock:
	mutex_unlock(&vpbe_dev->lock);
	return ret;
}
Beispiel #12
0
static int ovisp_camera_init_client(struct ovisp_camera_dev *camdev,
					struct ovisp_camera_client *client,
					int index)
{
	struct ovisp_camera_subdev *csd = &camdev->csd[index];
	int i2c_adapter_id;
	int err = 0;
	int ret;

	if (!client->board_info) {
		CAMERA_PRINT("Invalid client info\n");
		return -EINVAL;
	}

	if (client->flags & CAMERA_CLIENT_INDEP_I2C)
		i2c_adapter_id = client->i2c_adapter_id;
	else
		i2c_adapter_id = camdev->pdata->i2c_adapter_id;

	if (client->flags & CAMERA_CLIENT_ISP_BYPASS)
		csd->bypass = 1;
	else
		csd->bypass = 0;

	ret = ovisp_camera_get_mclk(camdev, client, index);
	if (ret)
		return ret;

	ret = isp_dev_call(camdev->isp, init, NULL);
	if (ret) {
		CAMERA_PRINT("Failed to init isp\n");
		clk_put(csd->mclk);
		return -EINVAL;
	}

	ret = ovisp_subdev_power_on(camdev, client, index);
	if (ret) {
		CAMERA_PRINT("Failed to power on subdev(%s)\n",
			client->board_info->type);
		clk_put(csd->mclk);
		err = -ENODEV;
		goto isp_dev_release;
	}

	csd->i2c_adap = i2c_get_adapter(i2c_adapter_id);
	if (!csd->i2c_adap) {
		CAMERA_PRINT("Cannot get I2C adapter(%d)\n",
			i2c_adapter_id);
		clk_put(csd->mclk);
		err = -ENODEV;
		goto subdev_power_off;
	}

	csd->sd = v4l2_i2c_new_subdev_board(&camdev->v4l2_dev,
		csd->i2c_adap,
		client->board_info,
		NULL);
	if (!csd->sd) {
		CAMERA_PRINT("Cannot get subdev(%s)\n",
			client->board_info->type);
		clk_put(csd->mclk);
		i2c_put_adapter(csd->i2c_adap);
		err = -EIO;
		goto subdev_power_off;
	}

subdev_power_off:
	ret = ovisp_subdev_power_off(camdev, client, index);
	if (ret) {
		CAMERA_PRINT("Failed to power off subdev(%s)\n",
			client->board_info->type);
		err = -EINVAL;
	}

isp_dev_release:
	ret = isp_dev_call(camdev->isp, release, NULL);
	if (ret) {
		CAMERA_PRINT("Failed to init isp\n");
		err = -EINVAL;
	}

	return err;
}
Beispiel #13
0
/*
 * Assign v4l2 device and subdev to fimc
 * it is called per every fimc ctrl registering
 */
static int fimc_configure_subdev(struct platform_device *pdev, int id)
{
	struct s3c_platform_fimc *pdata;
	struct s3c_platform_camera *cam;
	struct i2c_adapter *i2c_adap;
	struct i2c_board_info *i2c_info;
	struct v4l2_subdev *sd;
	struct fimc_control *ctrl;
	unsigned short addr;
	char *name;

	ctrl = get_fimc_ctrl(id);
	pdata = to_fimc_plat(&pdev->dev);
	cam = pdata->camera[id];

	/* Subdev registration */
	if (cam) {
		i2c_adap = i2c_get_adapter(cam->i2c_busnum);
		if (!i2c_adap) {
			fimc_info1("subdev i2c_adapter missing-skip "
							"registration\n");
		}

		i2c_info = cam->info;
		if (!i2c_info) {
			fimc_err("%s: subdev i2c board info missing\n",
								__func__);
			return -ENODEV;
		}

		name = i2c_info->type;
		if (!name) {
			fimc_info1("subdev i2c dirver name missing-skip "
				"registration\n");
			return -ENODEV;
		}

		addr = i2c_info->addr;
		if (!addr) {
			fimc_info1("subdev i2c address missing-skip "
							"registration\n");
			return -ENODEV;
		}

		/*
		 * NOTE: first time subdev being registered,
		 * s_config is called and try to initialize subdev device
		 * but in this point, we are not giving MCLK and power to subdev
		 * so nothing happens but pass platform data through
		 */
		sd = v4l2_i2c_new_subdev_board(&ctrl->v4l2_dev, i2c_adap,
				name, i2c_info, &addr);
		if (!sd) {
			fimc_err("%s: v4l2 subdev board registering failed\n",
				__func__);
		}

		/* Assign camera device to fimc */
		fimc_dev->camera[cam->id] = cam;

		/* Assign subdev to proper camera device pointer */
		fimc_dev->camera[cam->id]->sd = sd;
	}

	return 0;
}
Beispiel #14
0
/*
 * vpif_probe: This function creates device entries by register itself to the
 * V4L2 driver and initializes fields of each channel objects
 */
static __init int vpif_probe(struct platform_device *pdev)
{
	struct vpif_subdev_info *subdevdata;
	struct vpif_display_config *config;
	int i, j = 0, k, q, m, err = 0;
	struct i2c_adapter *i2c_adap;
	struct common_obj *common;
	struct channel_obj *ch;
	struct video_device *vfd;
	struct resource *res;
	int subdev_count;

	vpif_dev = &pdev->dev;

	err = initialize_vpif();

	if (err) {
		v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
		return err;
	}

	err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
	if (err) {
		v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
		return err;
	}

	k = 0;
	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
		for (i = res->start; i <= res->end; i++) {
			if (request_irq(i, vpif_channel_isr, IRQF_DISABLED,
					"DM646x_Display",
				(void *)(&vpif_obj.dev[k]->channel_id))) {
				err = -EBUSY;
				goto vpif_int_err;
			}
		}
		k++;
	}

	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {

		/* Get the pointer to the channel object */
		ch = vpif_obj.dev[i];

		/* Allocate memory for video device */
		vfd = video_device_alloc();
		if (vfd == NULL) {
			for (j = 0; j < i; j++) {
				ch = vpif_obj.dev[j];
				video_device_release(ch->video_dev);
			}
			err = -ENOMEM;
			goto vpif_int_err;
		}

		/* Initialize field of video device */
		*vfd = vpif_video_template;
		vfd->v4l2_dev = &vpif_obj.v4l2_dev;
		vfd->release = video_device_release;
		snprintf(vfd->name, sizeof(vfd->name),
			 "DM646x_VPIFDisplay_DRIVER_V%d.%d.%d",
			 (VPIF_DISPLAY_VERSION_CODE >> 16) & 0xff,
			 (VPIF_DISPLAY_VERSION_CODE >> 8) & 0xff,
			 (VPIF_DISPLAY_VERSION_CODE) & 0xff);

		/* Set video_dev to the video device */
		ch->video_dev = vfd;
	}

	for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
		ch = vpif_obj.dev[j];
		/* Initialize field of the channel objects */
		atomic_set(&ch->usrs, 0);
		for (k = 0; k < VPIF_NUMOBJECTS; k++) {
			ch->common[k].numbuffers = 0;
			common = &ch->common[k];
			common->io_usrs = 0;
			common->started = 0;
			spin_lock_init(&common->irqlock);
			mutex_init(&common->lock);
			common->numbuffers = 0;
			common->set_addr = NULL;
			common->ytop_off = common->ybtm_off = 0;
			common->ctop_off = common->cbtm_off = 0;
			common->cur_frm = common->next_frm = NULL;
			memset(&common->fmt, 0, sizeof(common->fmt));
			common->numbuffers = config_params.numbuffers[k];

		}
		ch->initialized = 0;
		ch->channel_id = j;
		if (j < 2)
			ch->common[VPIF_VIDEO_INDEX].numbuffers =
			    config_params.numbuffers[ch->channel_id];
		else
			ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;

		memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));

		/* Initialize prio member of channel object */
		v4l2_prio_init(&ch->prio);
		ch->common[VPIF_VIDEO_INDEX].fmt.type =
						V4L2_BUF_TYPE_VIDEO_OUTPUT;
		ch->video_dev->lock = &common->lock;

		/* register video device */
		vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
				(int)ch, (int)&ch->video_dev);

		err = video_register_device(ch->video_dev,
					  VFL_TYPE_GRABBER, (j ? 3 : 2));
		if (err < 0)
			goto probe_out;

		video_set_drvdata(ch->video_dev, ch);
	}

	i2c_adap = i2c_get_adapter(1);
	config = pdev->dev.platform_data;
	subdev_count = config->subdev_count;
	subdevdata = config->subdevinfo;
	vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
								GFP_KERNEL);
	if (vpif_obj.sd == NULL) {
		vpif_err("unable to allocate memory for subdevice pointers\n");
		err = -ENOMEM;
		goto probe_out;
	}

	for (i = 0; i < subdev_count; i++) {
		vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
						i2c_adap,
						&subdevdata[i].board_info,
						NULL);
		if (!vpif_obj.sd[i]) {
			vpif_err("Error registering v4l2 subdevice\n");
			goto probe_subdev_out;
		}

		if (vpif_obj.sd[i])
			vpif_obj.sd[i]->grp_id = 1 << i;
	}

	v4l2_info(&vpif_obj.v4l2_dev,
			"DM646x VPIF display driver initialized\n");
	return 0;

probe_subdev_out:
	kfree(vpif_obj.sd);
probe_out:
	for (k = 0; k < j; k++) {
		ch = vpif_obj.dev[k];
		video_unregister_device(ch->video_dev);
		video_device_release(ch->video_dev);
		ch->video_dev = NULL;
	}
vpif_int_err:
	v4l2_device_unregister(&vpif_obj.v4l2_dev);
	vpif_err("VPIF IRQ request failed\n");
	for (q = k; k >= 0; k--) {
		for (m = i; m >= res->start; m--)
			free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id));
		res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1);
		m = res->end;
	}

	return err;
}
Beispiel #15
0
static int __devinit hdmi_probe(struct platform_device *pdev)
{
	struct s5p_hdmi_platdata *pdata;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	struct generic_pm_domain *genpd;
	int ret;

	dev_dbg(dev, "probe start\n");

	hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(dev, "out of memory\n");
		ret = -ENOMEM;
		goto fail;
	}

	hdmi_dev->dev = dev;

	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_hdev;

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(dev, "get memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* External hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(dev, "get external interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->ext_irq = res->start;

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (res == NULL) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->int_irq = res->start;

	INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
	INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);
	mutex_init(&hdmi_dev->mutex);

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail_regs;
	}

	drv_data = (struct hdmi_driver_data *)
		platform_get_device_id(pdev)->driver_data;
	dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

	phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
	if (phy_adapter == NULL) {
		dev_err(dev, "adapter request failed\n");
		ret = -ENXIO;
		goto fail_vdev;
	}

	hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
		phy_adapter, &hdmiphy_info, NULL);
	/* on failure or not adapter is no longer useful */
	i2c_put_adapter(phy_adapter);
	if (hdmi_dev->phy_sd == NULL) {
		dev_err(dev, "missing subdev for hdmiphy\n");
		ret = -ENODEV;
		goto fail_vdev;
	}

	pdata = pdev->dev.platform_data;

	/* HDMI PHY power off
	 * HDMI PHY is on as default configuration
	 * So, HDMI PHY must be turned off if it's not used */
	if (pdata->hdmiphy_enable)
		pdata->hdmiphy_enable(pdev, 1);
	v4l2_subdev_call(hdmi_dev->phy_sd, core, s_power, 0);
	if (pdata->hdmiphy_enable)
		pdata->hdmiphy_enable(pdev, 0);

#ifdef CONFIG_PM_GENERIC_DOMAINS
	genpd = dev_to_genpd(hdmi_dev->dev);
	if (IS_ERR(genpd)) {
		dev_err(dev, "failed get genpd\n");
		goto fail_vdev;
	}
	genpd->domain.ops.suspend = hdmi_suspend;
	genpd->domain.ops.resume = hdmi_resume;
#endif

	pm_runtime_enable(dev);

	hdmi_dev->hpd_switch.name = "hdmi";
	switch_dev_register(&hdmi_dev->hpd_switch);
	hdmi_dev->hpd_audio_switch.name = "hdmi_audio";
	switch_dev_register(&hdmi_dev->hpd_audio_switch);

	ret = request_irq(hdmi_dev->int_irq, hdmi_irq_handler,
			0, "hdmi-int", hdmi_dev);
	if (ret) {
		dev_err(dev, "request int interrupt failed.\n");
		goto fail_vdev;
	}
	disable_irq(hdmi_dev->int_irq);

	s5p_v4l2_int_src_ext_hpd();
	ret = request_irq(hdmi_dev->ext_irq, hdmi_irq_handler_ext,
			IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
	if (ret) {
		dev_err(dev, "request ext interrupt failed.\n");
		goto fail_ext;
	}

	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);

	/* default audio configuration : disable audio */
	hdmi_dev->audio_enable = 0;
	hdmi_dev->audio_channel_count = 2;
	hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->color_range = 3;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* default aspect ratio is 16:9 */
	hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_irq;

	hdmi_entity_info_print(hdmi_dev);

	/* initialize hdcp resource */
	ret = hdcp_prepare(hdmi_dev);
	if (ret)
		goto fail_irq;

	queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
					  msecs_to_jiffies(1000));

	dev_info(dev, "probe sucessful\n");

	hdmi_debugfs_init(hdmi_dev);

	return 0;

fail_irq:
	free_irq(hdmi_dev->ext_irq, hdmi_dev);

fail_ext:
	free_irq(hdmi_dev->int_irq, hdmi_dev);

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail_regs:
	iounmap(hdmi_dev->regs);

fail_init:
	hdmi_resources_cleanup(hdmi_dev);

fail_hdev:
	kfree(hdmi_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}
static int register_i2c_devices(struct vpfe_device *vpfe_dev)
{
	struct vpfe_config *vpfe_cfg;
	struct i2c_adapter *i2c_adap;
	int i, k, ret;
	unsigned int num_subdevs;
	struct vpfe_subdev_info *sdinfo;

	vpfe_cfg = vpfe_dev->cfg;

	i2c_adap = i2c_get_adapter(1);
	num_subdevs = vpfe_cfg->num_subdevs;

	vpfe_dev->sd = kzalloc(sizeof(struct v4l2_subdev *) *num_subdevs,
			       GFP_KERNEL);

	if (NULL == vpfe_dev->sd) {
		v4l2_err(&vpfe_dev->v4l2_dev,
			"unable to allocate memory for subdevice pointers\n");
		return -ENOMEM;
	}

	for (i = 0, k = 0; i < num_subdevs; i++) {
		sdinfo = &vpfe_cfg->sub_devs[i];
		/**
		 * register subdevices based on interface setting. Currently
		 * tvp5146 and mt9p031 cannot co-exists due to i2c address
		 * conflicts. So only one of them is registered. Re-visit this
		 * once we have support for i2c switch handling in i2c driver
		 * framework
		 */

		if (interface == sdinfo->is_camera) {
			/* setup input path */
			if (vpfe_cfg->setup_input) {
				if (vpfe_cfg->setup_input(sdinfo->grp_id) < 0) {
					ret = -EFAULT;
					v4l2_info(&vpfe_dev->v4l2_dev, "could"
							" not setup input for %s\n",
							sdinfo->module_name);
					goto probe_sd_out;
				}
			}
			/* Load up the subdevice */
			vpfe_dev->sd[k] =
				v4l2_i2c_new_subdev_board(
						  &vpfe_dev->v4l2_dev,
						  i2c_adap,
						  &sdinfo->board_info,
						  NULL,
						1);
			if (vpfe_dev->sd[k]) {
				v4l2_info(&vpfe_dev->v4l2_dev,
						"v4l2 sub device %s registered\n",
						sdinfo->module_name);

				vpfe_dev->sd[k]->grp_id = sdinfo->grp_id;
				k++;

				sdinfo->registered = 1;
			}
			} else {
				v4l2_info(&vpfe_dev->v4l2_dev,
						"v4l2 sub device %s register fails\n",
						sdinfo->module_name);
			}
	}

	vpfe_dev->num_subdevs = k;
	return 0;

probe_sd_out:
	kzfree(vpfe_dev->sd);
	return ret;
}
Beispiel #17
0
int em28xx_init_camera(struct em28xx *dev)
{
	struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
	struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus];
	struct em28xx_v4l2 *v4l2 = dev->v4l2;

	switch (dev->em28xx_sensor) {
	case EM28XX_MT9V011:
	{
		struct mt9v011_platform_data pdata;
		struct i2c_board_info mt9v011_info = {
			.type = "mt9v011",
			.addr = client->addr,
			.platform_data = &pdata,
		};

		v4l2->sensor_xres = 640;
		v4l2->sensor_yres = 480;

		/*
		 * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
		 * the Silvercrest cam I have here for testing - for higher
		 * resolutions, a high clock cause horizontal artifacts, so we
		 * need to use a lower xclk frequency.
		 * Yet, it would be possible to adjust xclk depending on the
		 * desired resolution, since this affects directly the
		 * frame rate.
		 */
		dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
		v4l2->sensor_xtal = 4300000;
		pdata.xtal = v4l2->sensor_xtal;
		if (NULL ==
		    v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
					      &mt9v011_info, NULL))
			return -ENODEV;
		v4l2->vinmode = EM28XX_VINMODE_RGB8_GRBG;
		v4l2->vinctl = 0x00;

		break;
	}
	case EM28XX_MT9M001:
		v4l2->sensor_xres = 1280;
		v4l2->sensor_yres = 1024;

		em28xx_initialize_mt9m001(dev);

		v4l2->vinmode = EM28XX_VINMODE_RGB8_BGGR;
		v4l2->vinctl = 0x00;

		break;
	case EM28XX_MT9M111:
		v4l2->sensor_xres = 640;
		v4l2->sensor_yres = 512;

		dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
		em28xx_initialize_mt9m111(dev);

		v4l2->vinmode = EM28XX_VINMODE_YUV422_UYVY;
		v4l2->vinctl = 0x00;

		break;
	case EM28XX_OV2640:
	{
		struct v4l2_subdev *subdev;
		struct i2c_board_info ov2640_info = {
			.type = "ov2640",
			.flags = I2C_CLIENT_SCCB,
			.addr = client->addr,
		};
		struct v4l2_subdev_format format = {
			.which = V4L2_SUBDEV_FORMAT_ACTIVE,
		};

		/*
		 * FIXME: sensor supports resolutions up to 1600x1200, but
		 * resolution setting/switching needs to be modified to
		 * - switch sensor output resolution (including further
		 *   configuration changes)
		 * - adjust bridge xclk
		 * - disable 16 bit (12 bit) output formats on high resolutions
		 */
		v4l2->sensor_xres = 640;
		v4l2->sensor_yres = 480;

		subdev =
		     v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
					       &ov2640_info, NULL);
		if (subdev == NULL)
			return -ENODEV;

		format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
		format.format.width = 640;
		format.format.height = 480;
		v4l2_subdev_call(subdev, pad, set_fmt, NULL, &format);

		/* NOTE: for UXGA=1600x1200 switch to 12MHz */
		dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
		v4l2->vinmode = EM28XX_VINMODE_YUV422_YUYV;
		v4l2->vinctl = 0x00;

		break;
	}
	case EM28XX_NOSENSOR:
	default:
		return -EINVAL;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(em28xx_init_camera);
static int atomisp_subdev_probe(struct atomisp_device *isp)
{
	const struct atomisp_platform_data *pdata;
	struct intel_v4l2_subdev_table *subdevs;
	int raw_index = -1;

	pdata = atomisp_get_platform_data();
	if (pdata == NULL) {
		dev_err(isp->dev, "no platform data available\n");
		return 0;
	}

	for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) {
		struct v4l2_subdev *subdev;
		struct i2c_board_info *board_info =
			&subdevs->v4l2_subdev.board_info;
		struct i2c_adapter *adapter =
			i2c_get_adapter(subdevs->v4l2_subdev.i2c_adapter_id);

		if (adapter == NULL) {
			dev_err(isp->dev,
				"Failed to find i2c adapter for subdev %s\n",
				board_info->type);
			break;
		}

		subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
				board_info, NULL);

		if (subdev == NULL) {
			dev_warn(isp->dev, "Subdev %s detection fail\n",
				 board_info->type);
			continue;
		}

		dev_info(isp->dev, "Subdev %s successfully register\n",
			 board_info->type);

		switch (subdevs->type) {
		case RAW_CAMERA:
			raw_index = isp->input_cnt;
			dev_dbg(isp->dev, "raw_index: %d\n", raw_index);
		case SOC_CAMERA:
			dev_dbg(isp->dev, "SOC_INDEX: %d\n", isp->input_cnt);
			if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) {
				dev_warn(isp->dev,
					 "too many atomisp inputs, ignored\n");
				break;
			}

			isp->inputs[isp->input_cnt].type = subdevs->type;
			isp->inputs[isp->input_cnt].port = subdevs->port;
			isp->inputs[isp->input_cnt].camera = subdev;
			isp->inputs[isp->input_cnt].shading_table = NULL;
			isp->inputs[isp->input_cnt].morph_table = NULL;
			/*
			 * initialize the subdev frame size, then next we can
			 * judge whether frame_size store effective value via
			 * pixel_format.
			 */
			isp->inputs[isp->input_cnt].frame_size.pixel_format = 0;
			isp->input_cnt++;
			break;
		case CAMERA_MOTOR:
			isp->motor = subdev;
			break;
		case LED_FLASH:
		case XENON_FLASH:
			isp->flash = subdev;
			break;
		default:
			dev_dbg(isp->dev, "unknown subdev probed\n");
			break;
		}

	}

	/*
	 * HACK: Currently VCM belongs to primary sensor only, but correct
	 * approach must be to acquire from platform code which sensor
	 * owns it.
	 */
	if (isp->motor && raw_index >= 0)
		isp->inputs[raw_index].motor = isp->motor;

	/* Proceed even if no modules detected. For COS mode and no modules. */
	if (!isp->inputs[0].camera)
		dev_warn(isp->dev, "no camera attached or fail to detect\n");

	if (IS_ISP2400)
		return mrfld_csi_lane_config(isp);

	return 0;
}
static __init int vpif_probe(struct platform_device *pdev)
{
	struct vpif_subdev_info *subdevdata;
	struct vpif_capture_config *config;
	int i, j, k, m, q, err;
	struct i2c_adapter *i2c_adap;
	struct channel_obj *ch;
	struct common_obj *common;
	struct video_device *vfd;
	struct resource *res;
	int subdev_count;

	vpif_dev = &pdev->dev;

	err = initialize_vpif();
	if (err) {
		v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
		return err;
	}

	k = 0;
	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
		for (i = res->start; i <= res->end; i++) {
			if (request_irq(i, vpif_channel_isr, IRQF_DISABLED,
					"DM646x_Capture",
				(void *)(&vpif_obj.dev[k]->channel_id))) {
				err = -EBUSY;
				i--;
				goto vpif_int_err;
			}
		}
		k++;
	}

	for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
		/* Get the pointer to the channel object */
		ch = vpif_obj.dev[i];
		/* Allocate memory for video device */
		vfd = video_device_alloc();
		if (NULL == vfd) {
			for (j = 0; j < i; j++) {
				ch = vpif_obj.dev[j];
				video_device_release(ch->video_dev);
			}
			err = -ENOMEM;
			goto vpif_dev_alloc_err;
		}

		/* Initialize field of video device */
		*vfd = vpif_video_template;
		vfd->v4l2_dev = &vpif_obj.v4l2_dev;
		vfd->release = video_device_release;
		snprintf(vfd->name, sizeof(vfd->name),
			 "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
			 (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
			 (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
			 (VPIF_CAPTURE_VERSION_CODE) & 0xff);
		/* Set video_dev to the video device */
		ch->video_dev = vfd;
	}

	for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
		ch = vpif_obj.dev[j];
		ch->channel_id = j;
		common = &(ch->common[VPIF_VIDEO_INDEX]);
		spin_lock_init(&common->irqlock);
		mutex_init(&common->lock);
		/* Initialize prio member of channel object */
		v4l2_prio_init(&ch->prio);
		err = video_register_device(ch->video_dev,
					    VFL_TYPE_GRABBER, (j ? 1 : 0));
		if (err)
			goto probe_out;

		video_set_drvdata(ch->video_dev, ch);

	}

	i2c_adap = i2c_get_adapter(1);
	config = pdev->dev.platform_data;

	subdev_count = config->subdev_count;
	vpif_obj.sd = kmalloc(sizeof(struct v4l2_subdev *) * subdev_count,
				GFP_KERNEL);
	if (vpif_obj.sd == NULL) {
		vpif_err("unable to allocate memory for subdevice pointers\n");
		err = -ENOMEM;
		goto probe_out;
	}

	err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
	if (err) {
		v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
		goto probe_subdev_out;
	}

	for (i = 0; i < subdev_count; i++) {
		subdevdata = &config->subdev_info[i];
		vpif_obj.sd[i] =
			v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
						  i2c_adap,
						  subdevdata->name,
						  &subdevdata->board_info,
						  NULL);

		if (!vpif_obj.sd[i]) {
			vpif_err("Error registering v4l2 subdevice\n");
			goto probe_subdev_out;
		}
		v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
			  subdevdata->name);

		if (vpif_obj.sd[i])
			vpif_obj.sd[i]->grp_id = 1 << i;
	}
	v4l2_info(&vpif_obj.v4l2_dev, "DM646x VPIF Capture driver"
		  " initialized\n");

	return 0;

probe_subdev_out:
	/* free sub devices memory */
	kfree(vpif_obj.sd);

	j = VPIF_CAPTURE_MAX_DEVICES;
probe_out:
	v4l2_device_unregister(&vpif_obj.v4l2_dev);
	for (k = 0; k < j; k++) {
		/* Get the pointer to the channel object */
		ch = vpif_obj.dev[k];
		/* Unregister video device */
		video_unregister_device(ch->video_dev);
	}

vpif_dev_alloc_err:
	k = VPIF_CAPTURE_MAX_DEVICES-1;
	res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
	i = res->end;

vpif_int_err:
	for (q = k; q >= 0; q--) {
		for (m = i; m >= (int)res->start; m--)
			free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id));

		res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1);
		if (res)
			i = res->end;
	}
	return err;
}
static int hdmi_probe(struct platform_device *pdev)
{
	struct s5p_hdmi_platdata *pdata = NULL;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	int ret;

	dev_info(dev, "probe start\n");

	hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_device), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(&pdev->dev, "no memory for hdmi device\n");
		return -ENOMEM;
	}
	hdmi_dev->dev = dev;

	hdmi_dev->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!hdmi_dev->pdata) {
		dev_err(&pdev->dev, "no memory for state\n");
		return -ENOMEM;
	}

	/* store platform data ptr to mixer context */
	if (dev->of_node) {
		of_property_read_u32(dev->of_node, "ip_ver", &hdmi_dev->pdata->ip_ver);
		pdata = hdmi_dev->pdata;
	} else {
		hdmi_dev->pdata = dev->platform_data;
		pdata = hdmi_dev->pdata;
	}
	dev_info(dev, "HDMI ip version %d\n", pdata->ip_ver);

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "get hdmi memory resource failed.\n");
		return -ENXIO;
	}
	hdmi_dev->regs = devm_request_and_ioremap(&pdev->dev, res);
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "failed to claim register region for hdmi\n");
		return -ENOENT;
	}

	/* mapping HDMIPHY_APB registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!res) {
		dev_err(dev, "get hdmiphy memory resource failed.\n");
		return -ENXIO;
	}
	hdmi_dev->phy_regs = devm_request_and_ioremap(&pdev->dev, res);
	if (hdmi_dev->phy_regs == NULL) {
		dev_err(dev, "failed to claim register region for hdmiphy\n");
		return -ENOENT;
	}

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		return -ENXIO;
	}
	ret = devm_request_irq(dev, res->start, hdmi_irq_handler,
			0, "hdmi-int", hdmi_dev);
	if (ret) {
		dev_err(dev, "request int interrupt failed.\n");
		return ret;
	} else {
		hdmi_dev->int_irq = res->start;
		disable_irq(hdmi_dev->int_irq);
		dev_info(dev, "success request hdmi-int irq\n");
	}

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail;
	}

	INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
	INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);

	/* setting the clocks */
	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_vdev;

	/* setting the GPIO */
	ret = hdmi_set_gpio(hdmi_dev);
	if (ret) {
		dev_err(dev, "failed to get GPIO\n");
		goto fail_clk;
	}

	/* External hpd */
	hdmi_dev->ext_irq = gpio_to_irq(hdmi_dev->res.gpio_hpd);
	ret = devm_request_irq(dev, hdmi_dev->ext_irq, hdmi_irq_handler_ext,
			IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
	if (ret) {
		dev_err(dev, "request ext interrupt failed.\n");
		goto fail_gpio;
	} else {
		dev_info(dev, "success request hdmi-ext irq\n");
	}

	hdmi_dev->hpd_switch.name = "hdmi";
	ret = switch_dev_register(&hdmi_dev->hpd_switch);
	if (ret) {
		dev_err(dev, "request switch class failed.\n");
		goto fail_gpio;
	}

	mutex_init(&hdmi_dev->mutex);

	if (soc_is_exynos5250()) {
		drv_data = (struct hdmi_driver_data *)
			platform_get_device_id(pdev)->driver_data;
		dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

		phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
		if (phy_adapter == NULL) {
			dev_err(dev, "adapter request failed\n");
			ret = -ENXIO;
			goto fail_switch;
		}

		hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
				phy_adapter, &hdmiphy_info, NULL);
		/* on failure or not adapter is no longer useful */
		i2c_put_adapter(phy_adapter);
		if (hdmi_dev->phy_sd == NULL) {
			dev_err(dev, "missing subdev for hdmiphy\n");
			ret = -ENODEV;
			goto fail_switch;
		}
	}

	hdmi_dev->cur_timings =
		hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].dv_timings;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].conf;

	/* default audio configuration : enable audio */
	hdmi_dev->audio_enable = 1;
	hdmi_dev->audio_channel_count = 2;
	hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->color_range = HDMI_RGB709_0_255;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* default aspect ratio is 16:9 */
	hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

	/* default HDMI streaming is stoped */
	hdmi_dev->streaming = HDMI_STOP;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_switch;

	hdmi_entity_info_print(hdmi_dev);

	pm_runtime_enable(dev);

	/* initialize hdcp resource */
	ret = hdcp_prepare(hdmi_dev);
	if (ret)
		goto fail_switch;

	/* work after booting */
	queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
					msecs_to_jiffies(1500));
	/* TODO : Check the PHY power off is implemented at pm_domains
	 * If not, PHY power off should be applied at here */

	dev_info(dev, "probe sucessful\n");

	hdmi_debugfs_init(hdmi_dev);

	return 0;

fail_switch:
	switch_dev_unregister(&hdmi_dev->hpd_switch);
	mutex_destroy(&hdmi_dev->mutex);

fail_gpio:
	gpio_free(hdmi_dev->res.gpio_hpd);
	gpio_free(hdmi_dev->res.gpio_ls);
	gpio_free(hdmi_dev->res.gpio_dcdc);

fail_clk:
	hdmi_resources_cleanup(hdmi_dev);

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}
int em28xx_init_camera(struct em28xx *dev)
{
	char clk_name[V4L2_SUBDEV_NAME_SIZE];
	struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
	struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus];
	struct em28xx_v4l2 *v4l2 = dev->v4l2;
	int ret = 0;

	v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
			  i2c_adapter_id(adap), client->addr);
	v4l2->clk = v4l2_clk_register_fixed(clk_name, -EINVAL);
	if (IS_ERR(v4l2->clk))
		return PTR_ERR(v4l2->clk);

	switch (dev->em28xx_sensor) {
	case EM28XX_MT9V011:
	{
		struct mt9v011_platform_data pdata;
		struct i2c_board_info mt9v011_info = {
			.type = "mt9v011",
			.addr = client->addr,
			.platform_data = &pdata,
		};

		v4l2->sensor_xres = 640;
		v4l2->sensor_yres = 480;

		/*
		 * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
		 * the Silvercrest cam I have here for testing - for higher
		 * resolutions, a high clock cause horizontal artifacts, so we
		 * need to use a lower xclk frequency.
		 * Yet, it would be possible to adjust xclk depending on the
		 * desired resolution, since this affects directly the
		 * frame rate.
		 */
		dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
		v4l2->sensor_xtal = 4300000;
		pdata.xtal = v4l2->sensor_xtal;
		if (NULL ==
		    v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
					      &mt9v011_info, NULL)) {
			ret = -ENODEV;
			break;
		}
		/* probably means GRGB 16 bit bayer */
		v4l2->vinmode = 0x0d;
		v4l2->vinctl = 0x00;

		break;
	}
	case EM28XX_MT9M001:
		v4l2->sensor_xres = 1280;
		v4l2->sensor_yres = 1024;

		em28xx_initialize_mt9m001(dev);

		/* probably means BGGR 16 bit bayer */
		v4l2->vinmode = 0x0c;
		v4l2->vinctl = 0x00;

		break;
	case EM28XX_MT9M111:
		v4l2->sensor_xres = 640;
		v4l2->sensor_yres = 512;

		dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
		em28xx_initialize_mt9m111(dev);

		v4l2->vinmode = 0x0a;
		v4l2->vinctl = 0x00;

		break;
	case EM28XX_OV2640:
	{
		struct v4l2_subdev *subdev;
		struct i2c_board_info ov2640_info = {
			.type = "ov2640",
			.flags = I2C_CLIENT_SCCB,
			.addr = client->addr,
			.platform_data = &camlink,
		};
		struct v4l2_mbus_framefmt fmt;

		/*
		 * FIXME: sensor supports resolutions up to 1600x1200, but
		 * resolution setting/switching needs to be modified to
		 * - switch sensor output resolution (including further
		 *   configuration changes)
		 * - adjust bridge xclk
		 * - disable 16 bit (12 bit) output formats on high resolutions
		 */
		v4l2->sensor_xres = 640;
		v4l2->sensor_yres = 480;

		subdev =
		     v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
					       &ov2640_info, NULL);
		if (NULL == subdev) {
			ret = -ENODEV;
			break;
		}

		fmt.code = MEDIA_BUS_FMT_YUYV8_2X8;
		fmt.width = 640;
		fmt.height = 480;
		v4l2_subdev_call(subdev, video, s_mbus_fmt, &fmt);

		/* NOTE: for UXGA=1600x1200 switch to 12MHz */
		dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
		v4l2->vinmode = 0x08;
		v4l2->vinctl = 0x00;

		break;
	}
	case EM28XX_NOSENSOR:
	default:
		ret = -EINVAL;
	}

	if (ret < 0) {
		v4l2_clk_unregister_fixed(v4l2->clk);
		v4l2->clk = NULL;
	}

	return ret;
}
EXPORT_SYMBOL_GPL(em28xx_init_camera);
Beispiel #22
0
static int __devinit hdmi_probe(struct platform_device *pdev)
{
	struct s5p_hdmi_platdata *pdata;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	int ret;

	dev_dbg(dev, "probe start\n");

	hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(dev, "out of memory\n");
		ret = -ENOMEM;
		goto fail;
	}

	hdmi_dev->dev = dev;

	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_hdev;

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(dev, "get hdmi memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "hdmi register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* mapping HDMIPHY_APB registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (res == NULL) {
		dev_err(dev, "get hdmiphy memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->phy_regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->phy_regs == NULL) {
		dev_err(dev, "hdmiphy register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* External hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(dev, "get external interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->ext_irq = res->start;

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (res == NULL) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->int_irq = res->start;

	INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
	INIT_DELAYED_WORK(&hdmi_dev->hdmi_probe_work, hdmiphy_poweroff_work);
	INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);
	mutex_init(&hdmi_dev->mutex);

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail_lock;
	}

	pdata = pdev->dev.platform_data;
	dev_info(dev, "hdmi ip version = %d\n", pdata->ip_ver);

	/* store hdmi platform data to hdmi context */
	hdmi_dev->pdata = pdata;

	if (soc_is_exynos5250()) {
		drv_data = (struct hdmi_driver_data *)
			platform_get_device_id(pdev)->driver_data;
		dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

		phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
		if (phy_adapter == NULL) {
			dev_err(dev, "adapter request failed\n");
			ret = -ENXIO;
			goto fail_vdev;
		}

		hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
				phy_adapter, &hdmiphy_info, NULL);
		/* on failure or not adapter is no longer useful */
		i2c_put_adapter(phy_adapter);
		if (hdmi_dev->phy_sd == NULL) {
			dev_err(dev, "missing subdev for hdmiphy\n");
			ret = -ENODEV;
			goto fail_vdev;
		}
	}

	hdmi_dev->hpd_switch.name = "hdmi";
	ret = switch_dev_register(&hdmi_dev->hpd_switch);
	if (ret) {
		dev_err(dev, "request switch class failed.\n");
		goto fail_vdev;
	}

	ret = request_irq(hdmi_dev->int_irq, hdmi_irq_handler,
			0, "hdmi-int", hdmi_dev);
	if (ret) {
		dev_err(dev, "request int interrupt failed.\n");
		goto fail_switch;
	}
	disable_irq(hdmi_dev->int_irq);

	s5p_v4l2_int_src_ext_hpd();
	ret = request_irq(hdmi_dev->ext_irq, hdmi_irq_handler_ext,
			IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
	if (ret) {
		dev_err(dev, "request ext interrupt failed.\n");
		goto fail_ext;
	}

	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);

	/* default audio configuration : disable audio */
	hdmi_dev->audio_enable = 0;
	hdmi_dev->audio_channel_count = 2;
	//hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->sample_rate = 48000;
	hdmi_dev->sample_size = DEFAULT_SAMPLE_SIZE;
	hdmi_dev->color_range = HDMI_RGB709_0_255;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* default aspect ratio is 16:9 */
	hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

	/* default HDMI streaming is stoped */
	hdmi_dev->streaming = HDMI_STOP;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_irq;

	hdmi_entity_info_print(hdmi_dev);

	pm_runtime_enable(dev);

	//if {(edid_supports_hdmi(hdmi_dev)) {
#if 1 
		/* initialize hdcp resource */
		ret = hdcp_prepare(hdmi_dev);
		if (ret)
			goto fail_irq;
#endif
//	}

	/* work after booting */
	queue_delayed_work(system_nrt_wq, &hdmi_dev->hdmi_probe_work,
					msecs_to_jiffies(1500));
	queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
					msecs_to_jiffies(1500));

	dev_info(dev, "probe sucessful\n");

	hdmi_debugfs_init(hdmi_dev);

	return 0;

fail_irq:
	free_irq(hdmi_dev->ext_irq, hdmi_dev);

fail_ext:
	free_irq(hdmi_dev->int_irq, hdmi_dev);

fail_switch:
	switch_dev_unregister(&hdmi_dev->hpd_switch);

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail_lock:
	mutex_destroy(&hdmi_dev->mutex);

fail_regs:
	iounmap(hdmi_dev->regs);

fail_init:
	hdmi_resources_cleanup(hdmi_dev);

fail_hdev:
	kfree(hdmi_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}