コード例 #1
0
ファイル: fimc-mdevice.c プロジェクト: AllenDou/linux
/*
 * 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;
}
コード例 #2
0
ファイル: fimc-mdevice.c プロジェクト: dedzt16/dedzt16
/**
 * fimc_md_register_platform_entities - register FIMC and CSIS media entities
 */
static int fimc_md_register_platform_entities(struct fimc_md *fmd)
{
	struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
	struct device_driver *driver;
	int ret, i;

	driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type);
	if (!driver) {
		v4l2_warn(&fmd->v4l2_dev,
			 "%s driver not found, deffering probe\n",
			 FIMC_MODULE_NAME);
		return -EPROBE_DEFER;
	}

	ret = driver_for_each_device(driver, NULL, fmd,
				     fimc_register_callback);
	if (ret)
		return ret;

	driver = driver_find(FIMC_LITE_DRV_NAME, &platform_bus_type);
	if (driver && try_module_get(driver->owner)) {
		ret = driver_for_each_device(driver, NULL, fmd,
					     flite_register_callback);
		if (ret)
			return ret;
		module_put(driver->owner);
	}
	fmd->fimc_is_subdev=fimc_is_get_subdev();
	/*
	 * Check if there is any sensor on the MIPI-CSI2 bus and
	 * if not skip the s5p-csis module loading.
	 */
	if (pdata == NULL)
		return 0;
	for (i = 0; i < pdata->num_clients; i++) {
		if (pdata->isp_info[i].bus_type == FIMC_MIPI_CSI2) {
			ret = 1;
			break;
		}
	}
	if (!ret)
		return 0;

	driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type);
	if (!driver || !try_module_get(driver->owner)) {
		v4l2_warn(&fmd->v4l2_dev,
			 "%s driver not found, deffering probe\n",
			 CSIS_DRIVER_NAME);
		return -EPROBE_DEFER;
	}

	return driver_for_each_device(driver, NULL, fmd,
				      csis_register_callback);
}
コード例 #3
0
ファイル: hmm_bo.c プロジェクト: ddalex/XT890-Kernel-Gamma
static void hmm_bo_release(struct hmm_buffer_object *bo)
{
	struct hmm_bo_device *bdev;
	unsigned long flags;

	check_bo_null_return_void(bo);

	bdev = bo->bdev;

	/*
	 * remove it from buffer device's buffer object list.
	 */
	spin_lock_irqsave(&bdev->list_lock, flags);
	list_del(&bo->list);
	spin_unlock_irqrestore(&bdev->list_lock, flags);

	/*
	 * FIX ME:
	 *
	 * how to destroy the bo when it is stilled MMAPED?
	 *
	 * ideally, this will not happened as hmm_bo_release
	 * will only be called when kref reaches 0, and in mmap
	 * operation the hmm_bo_ref will eventually be called.
	 * so, if this happened, something goes wrong.
	 */
	if (bo->status & HMM_BO_MMAPED) {
		v4l2_err(&atomisp_dev,
			     "destroy bo which is MMAPED, do nothing\n");
		goto err;
	}

	if (bo->status & HMM_BO_BINDED) {
		v4l2_warn(&atomisp_dev,
			     "the bo is still binded, unbind it first...\n");
		hmm_bo_unbind(bo);
	}
	if (bo->status & HMM_BO_PAGE_ALLOCED) {
		v4l2_warn(&atomisp_dev,
			     "the pages is not freed, free pages first\n");
		hmm_bo_free_pages(bo);
	}
	if (bo->status & HMM_BO_VM_ALLOCED) {
		v4l2_warn(&atomisp_dev,
			     "the vm is still not freed, free vm first...\n");
		hmm_bo_free_vm(bo);
	}

	if (bo->release)
		bo->release(bo);
err:
	return;
}
コード例 #4
0
ファイル: hmm_bo.c プロジェクト: ddalex/XT890-Kernel-Gamma
/*
 * use this function to initialize pre-allocated hmm_buffer_object.
 * as hmm_buffer_object may be used as an embedded object in an upper
 * level object, a release callback must be provided. if it is
 * embedded in upper level object, set release call back to release
 * function of that object. if no upper level object, set release
 * callback to NULL.
 *
 * bo->kref is inited to 1.
 */
int hmm_bo_init(struct hmm_bo_device *bdev,
		struct hmm_buffer_object *bo,
		unsigned int pgnr, void (*release) (struct hmm_buffer_object *))
{
	unsigned long flags;

	if (bdev == NULL) {
		v4l2_warn(&atomisp_dev,
			    "NULL hmm_bo_device.\n");
		return -EINVAL;
	}

	/* hmm_bo_device must be already inited */
	var_equal_return(hmm_bo_device_inited(bdev), 0, -EINVAL,
			   "hmm_bo_device not inited yet.\n");

	/* prevent zero size buffer object */
	if (pgnr == 0) {
		v4l2_err(&atomisp_dev,
			    "0 size buffer is not allowed.\n");
		return -EINVAL;
	}

	memset(bo, 0, sizeof(*bo));

	kref_init(&bo->kref);

	mutex_init(&bo->mutex);

	INIT_LIST_HEAD(&bo->list);

	bo->pgnr = pgnr;
	bo->bdev = bdev;

	INIT_LIST_HEAD(&bo->pgblocks);

	bo->release = release;

	if (!bo->release)
		v4l2_warn(&atomisp_dev,
			    "no release callback specified.\n");

	/*
	 * add to active_bo_list
	 */
	spin_lock_irqsave(&bdev->list_lock, flags);
	list_add_tail(&bo->list, &bdev->active_bo_list);
	bo->status |= HMM_BO_ACTIVE;
	spin_unlock_irqrestore(&bdev->list_lock, flags);

	return 0;
}
コード例 #5
0
ファイル: hdpvr-i2c.c プロジェクト: 020gzh/linux
static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
			  int num)
{
	struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
	int retval = 0, addr;

	if (num <= 0)
		return 0;

	mutex_lock(&dev->i2c_mutex);

	addr = msgs[0].addr << 1;

	if (num == 1) {
		if (msgs[0].flags & I2C_M_RD)
			retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0,
						msgs[0].buf, msgs[0].len);
		else
			retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf,
						 msgs[0].len);
	} else if (num == 2) {
		if (msgs[0].addr != msgs[1].addr) {
			v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer "
				  "with conflicting target addresses\n");
			retval = -EINVAL;
			goto out;
		}

		if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
			v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with "
				  "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD,
				  msgs[1].flags & I2C_M_RD);
			retval = -EINVAL;
			goto out;
		}

		/*
		 * Write followed by atomic read is the only complex xfer that
		 * we actually support here.
		 */
		retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len,
					msgs[1].buf, msgs[1].len);
	} else {
		v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num);
	}

out:
	mutex_unlock(&dev->i2c_mutex);

	return retval ? retval : num;
}
コード例 #6
0
ファイル: camif-core.c プロジェクト: 513855417/linux
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;
}
コード例 #7
0
/**
 * m5mols_s_power - Main sensor power control function
 *
 * To prevent breaking the lens when the sensor is powered off the Soft-Landing
 * algorithm is called where available. The Soft-Landing algorithm availability
 * dependends on the firmware provider.
 */
static int m5mols_s_power(struct v4l2_subdev *sd, int on)
{
	struct m5mols_info *info = to_m5mols(sd);
	int ret;

	if (on) {
		ret = m5mols_sensor_power(info, true);
		if (!ret)
			ret = m5mols_fw_start(sd);
		return ret;
	}

	if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
		ret = m5mols_set_mode(info, REG_MONITOR);
		if (!ret)
			ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP);
		if (!ret)
			ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
		if (!ret)
			ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
					       0xff, -1);
		if (ret < 0)
			v4l2_warn(sd, "Soft landing lens failed\n");
	}

	ret = m5mols_sensor_power(info, false);
	info->ctrl_sync = 0;

	return ret;
}
コード例 #8
0
ファイル: isp_mmu.c プロジェクト: DanBjorklund/ME302C
/*Free L1 and L2 page table*/
void isp_mmu_exit(struct isp_mmu *mmu)
{
	unsigned int idx;
	unsigned int pte;
	phys_addr_t l1_pt, l2_pt;

	if (!mmu)
		return;

	if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) {
		v4l2_warn(&atomisp_dev,
			    "invalid L1PT: pte = 0x%x\n",
			    (unsigned int)mmu->l1_pte);
		return;
	}

	l1_pt = isp_pte_to_pgaddr(mmu, mmu->l1_pte);

	for (idx = 0; idx < ISP_L1PT_PTES; idx++) {
		pte = atomisp_get_pte(l1_pt, idx);

		if (ISP_PTE_VALID(mmu, pte)) {
			l2_pt = isp_pte_to_pgaddr(mmu, pte);

			free_page_table(mmu, l2_pt);
		}
	}

	free_page_table(mmu, l1_pt);

#ifdef USE_KMEM_CACHE
	kmem_cache_destroy(mmu->tbl_cache);
#endif
}
コード例 #9
0
ファイル: imx7-media-csi.c プロジェクト: grate-driver/linux
static void imx7_csi_dma_stop(struct imx7_csi *csi)
{
	unsigned long timeout_jiffies;
	unsigned long flags;
	int ret;

	/* mark next EOF interrupt as the last before stream off */
	spin_lock_irqsave(&csi->irqlock, flags);
	csi->last_eof = true;
	spin_unlock_irqrestore(&csi->irqlock, flags);

	/*
	 * and then wait for interrupt handler to mark completion.
	 */
	timeout_jiffies = msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT);
	ret = wait_for_completion_timeout(&csi->last_eof_completion,
					  timeout_jiffies);
	if (ret == 0)
		v4l2_warn(&csi->sd, "wait last EOF timeout\n");

	imx7_csi_hw_disable_irq(csi);

	imx7_csi_dma_unsetup_vb2_buf(csi, VB2_BUF_STATE_ERROR);

	imx_media_free_dma_buf(csi->dev, &csi->underrun_buf);
}
コード例 #10
0
/**
 * m5mols_s_power - Main sensor power control function
 *
 * To prevent breaking the lens when the sensor is powered off the Soft-Landing
 * algorithm is called where available. The Soft-Landing algorithm availability
 * dependends on the firmware provider.
 */
static int m5mols_s_power(struct v4l2_subdev *sd, int on)
{
	struct m5mols_info *info = to_m5mols(sd);
	int ret;

	mutex_lock(&info->lock);

	if (on) {
		ret = m5mols_sensor_power(info, true);
		if (!ret)
			ret = m5mols_fw_start(sd);
	} else {
		if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
			ret = m5mols_set_mode(info, REG_MONITOR);
			if (!ret)
				ret = m5mols_auto_focus_stop(info);
			if (ret < 0)
				v4l2_warn(sd, "Soft landing lens failed\n");
		}
		ret = m5mols_sensor_power(info, false);

		info->ctrl_sync = 0;
	}

	mutex_unlock(&info->lock);
	return ret;
}
コード例 #11
0
ファイル: si4713-i2c.c プロジェクト: 03199618/linux
/*
 * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful
 *		     for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS
 * @sdev: si4713_device structure for the device we are communicating
 * @usecs: timeout to wait for STC interrupt signal
 */
static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
{
	int err;
	u8 resp[SI4713_GET_STATUS_NRESP];

	/* Wait response from STC interrupt */
	if (!wait_for_completion_timeout(&sdev->work,
			usecs_to_jiffies(usecs) + 1))
		v4l2_warn(&sdev->sd,
			"%s: device took too much time to answer (%d usec).\n",
				__func__, usecs);

	/* Clear status bits */
	err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
					NULL, 0,
					resp, ARRAY_SIZE(resp),
					DEFAULT_TIMEOUT);

	if (err < 0)
		goto exit;

	v4l2_dbg(1, debug, &sdev->sd,
			"%s: status bits: 0x%02x\n", __func__, resp[0]);

	if (!(resp[0] & SI4713_STC_INT))
		err = -EIO;

exit:
	return err;
}
コード例 #12
0
ファイル: si4713.c プロジェクト: forgivemyheart/linux
/*
 * si4713_send_command - sends a command to si4713 and waits its response
 * @sdev: si4713_device structure for the device we are communicating
 * @command: command id
 * @args: command arguments we are sending (up to 7)
 * @argn: actual size of @args
 * @response: buffer to place the expected response from the device (up to 15)
 * @respn: actual size of @response
 * @usecs: amount of time to wait before reading the response (in usecs)
 */
static int si4713_send_command(struct si4713_device *sdev, const u8 command,
				const u8 args[], const int argn,
				u8 response[], const int respn, const int usecs)
{
	struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
	unsigned long until_jiffies;
	u8 data1[MAX_ARGS + 1];
	int err;

	if (!client->adapter)
		return -ENODEV;

	/* First send the command and its arguments */
	data1[0] = command;
	memcpy(data1 + 1, args, argn);
	DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1);

	err = i2c_master_send(client, data1, argn + 1);
	if (err != argn + 1) {
		v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
			command);
		return err < 0 ? err : -EIO;
	}

	until_jiffies = jiffies + usecs_to_jiffies(usecs) + 1;

	/* Wait response from interrupt */
	if (client->irq) {
		if (!wait_for_completion_timeout(&sdev->work,
				usecs_to_jiffies(usecs) + 1))
			v4l2_warn(&sdev->sd,
				"(%s) Device took too much time to answer.\n",
				__func__);
	}

	do {
		err = i2c_master_recv(client, response, respn);
		if (err != respn) {
			v4l2_err(&sdev->sd,
				"Error %d while reading response for command 0x%02x\n",
				err, command);
			return err < 0 ? err : -EIO;
		}

		DBG_BUFFER(&sdev->sd, "Response", response, respn);
		if (!check_command_failed(response[0]))
			return 0;

		if (client->irq)
			return -EBUSY;
		if (usecs <= 1000)
			usleep_range(usecs, 1000);
		else
			usleep_range(1000, 2000);
	} while (time_is_after_jiffies(until_jiffies));

	return -EBUSY;
}
コード例 #13
0
/*
 * set input are used to set current primary/secondary camera
 */
static int atomisp_s_input(struct file *file, void *fh, unsigned int input)
{
	struct video_device *vdev = video_devdata(file);
	struct atomisp_device *isp = video_get_drvdata(vdev);
	struct v4l2_subdev *camera = NULL;
	int ret;

	if (input >= ATOM_ISP_MAX_INPUTS || input > isp->input_cnt)
		return -EINVAL;

	mutex_lock(&isp->input_lock);
	camera = isp->inputs[input].camera;
	if (!camera) {
		mutex_unlock(&isp->input_lock);
		return -EINVAL;
	}

	if ((isp->isp_subdev.video_out_vf.capq.streaming == 1) ||
	    (isp->isp_subdev.video_out_mo.capq.streaming == 1) ||
	    (isp->isp_subdev.video_in.capq.streaming == 1)) {
		v4l2_err(&atomisp_dev,
			 "ISP is still streaming, stop first\n");
		mutex_unlock(&isp->input_lock);
		return -EINVAL;
	}

	/* power off the current sensor, as it is not used this time */
	if (isp->input_curr != input) {
		ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
				       core, s_power, 0);
		if (ret)
			v4l2_warn(&atomisp_dev,
				    "Failed to power-off sensor\n");
	}

	/* power on the new sensor */
	if (!isp->sw_contex.file_input) {
		ret = v4l2_subdev_call(isp->inputs[input].camera,
				       core, s_power, 1);

		if (ret) {
			v4l2_err(&atomisp_dev,
				    "Failed to power-on sensor\n");
			mutex_unlock(&isp->input_lock);
			return ret;
		}
		if (isp->inputs[input].motor)
			ret = v4l2_subdev_call(isp->inputs[input].motor, core,
					       init, 1);
	}

	isp->input_curr = input;

	mutex_unlock(&isp->input_lock);

	return 0;
}
コード例 #14
0
/* tunes the radio to the desired frequency */
static int zoltrix_s_frequency(struct radio_isa_card *isa, u32 freq)
{
	struct zoltrix *zol = container_of(isa, struct zoltrix, isa);
	struct v4l2_device *v4l2_dev = &isa->v4l2_dev;
	unsigned long long bitmask, f, m;
	bool stereo = isa->stereo;
	int i;

	if (freq == 0) {
		v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n");
		return -EINVAL;
	}

	m = (freq / 160 - 8800) * 2;
	f = (unsigned long long)m + 0x4d1c;

	bitmask = 0xc480402c10080000ull;
	i = 45;

	outb(0, isa->io);
	outb(0, isa->io);
	inb(isa->io + 3);            /* Zoltrix needs to be read to confirm */

	outb(0x40, isa->io);
	outb(0xc0, isa->io);

	bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31));
	while (i--) {
		if ((bitmask & 0x8000000000000000ull) != 0) {
			outb(0x80, isa->io);
			udelay(50);
			outb(0x00, isa->io);
			udelay(50);
			outb(0x80, isa->io);
			udelay(50);
		} else {
			outb(0xc0, isa->io);
			udelay(50);
			outb(0x40, isa->io);
			udelay(50);
			outb(0xc0, isa->io);
			udelay(50);
		}
		bitmask *= 2;
	}
	/* termination sequence */
	outb(0x80, isa->io);
	outb(0xc0, isa->io);
	outb(0x40, isa->io);
	udelay(1000);
	inb(isa->io + 2);
	udelay(1000);

	return zoltrix_s_mute_volume(isa, zol->muted, zol->curvol);
}
コード例 #15
0
/* si4713_probe - probe for the device */
static int si4713_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	struct si4713_device *sdev;
	int rval;

	sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
	if (!sdev) {
		dev_err(&client->dev, "Failed to alloc video device.\n");
		rval = -ENOMEM;
		goto exit;
	}

	sdev->platform_data = client->dev.platform_data;
	if (!sdev->platform_data) {
		v4l2_err(&sdev->sd, "No platform data registered.\n");
		rval = -ENODEV;
		goto free_sdev;
	}

	v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);

	mutex_init(&sdev->mutex);
	init_completion(&sdev->work);

	if (client->irq) {
		rval = request_irq(client->irq,
			si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
			client->name, sdev);
		if (rval < 0) {
			v4l2_err(&sdev->sd, "Could not request IRQ\n");
			goto free_sdev;
		}
		v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
	} else {
		v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
	}

	rval = si4713_initialize(sdev);
	if (rval < 0) {
		v4l2_err(&sdev->sd, "Failed to probe device information.\n");
		goto free_irq;
	}

	return 0;

free_irq:
	if (client->irq)
		free_irq(client->irq, sdev);
free_sdev:
	kfree(sdev);
exit:
	return rval;
}
コード例 #16
0
/*
 * In case we are monitoring the first frame interval after streamon
 * (when fim->num_skip = 0), we need a valid fim->last_ts before we
 * can begin. This only applies to the input capture method. It is not
 * possible to accurately measure the first FI after streamon using the
 * EOF method, so fim->num_skip minimum is set to 1 in that case, so this
 * function is a noop when the EOF method is used.
 */
static void fim_acquire_first_ts(struct imx_media_fim *fim)
{
	unsigned long ret;

	if (!fim->enabled || fim->num_skip > 0)
		return;

	ret = wait_for_completion_timeout(
		&fim->icap_first_event,
		msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
	if (ret == 0)
		v4l2_warn(fim->sd, "wait first icap event timeout\n");
}
コード例 #17
0
ファイル: media-dev.c プロジェクト: garyvan/openwrt-1.6
/*
 * 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;
}
コード例 #18
0
/**
 * m5mols_set_mode - set the M-5MOLS controller mode
 * @mode: the required operation mode
 *
 * The commands of M-5MOLS are grouped into specific modes. Each functionality
 * can be guaranteed only when the sensor is operating in mode which a command
 * belongs to.
 */
int m5mols_set_mode(struct m5mols_info *info, u8 mode)
{
	struct v4l2_subdev *sd = &info->sd;
	int ret = -EINVAL;
	u8 reg;

	if (mode < REG_PARAMETER || mode > REG_CAPTURE)
		return ret;

	ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
	if (ret || reg == mode)
		return ret;

	switch (reg) {
	case REG_PARAMETER:
		ret = m5mols_reg_mode(sd, REG_MONITOR);
		if (mode == REG_MONITOR)
			break;
		if (!ret)
			ret = m5mols_reg_mode(sd, REG_CAPTURE);
		break;

	case REG_MONITOR:
		if (mode == REG_PARAMETER) {
			ret = m5mols_reg_mode(sd, REG_PARAMETER);
			break;
		}

		ret = m5mols_reg_mode(sd, REG_CAPTURE);
		break;

	case REG_CAPTURE:
		ret = m5mols_reg_mode(sd, REG_MONITOR);
		if (mode == REG_MONITOR)
			break;
		if (!ret)
			ret = m5mols_reg_mode(sd, REG_PARAMETER);
		break;

	default:
		v4l2_warn(sd, "Wrong mode: %d\n", mode);
	}

	if (!ret)
		info->mode = mode;

	return ret;
}
コード例 #19
0
ファイル: isp_mmu.c プロジェクト: DanBjorklund/ME302C
/*MMU init for internal structure*/
int isp_mmu_init(struct isp_mmu *mmu, struct isp_mmu_client *driver)
{
	if (!mmu)		/* error */
		return -EINVAL;
	if (!driver)		/* error */
		return -EINVAL;

	if (!driver->name)
		v4l2_warn(&atomisp_dev,
			    "NULL name for MMU driver...\n");

	mmu->driver = driver;

	if (!driver->set_pd_base || !driver->tlb_flush_all) {
		v4l2_err(&atomisp_dev,
			    "set_pd_base or tlb_flush_all operation "
			     "not provided.\n");
		return -EINVAL;
	}

	if (!driver->tlb_flush_range)
		driver->tlb_flush_range = isp_mmu_flush_tlb_range_default;

	if (!driver->pte_valid_mask) {
		v4l2_err(&atomisp_dev,
			 "PTE_MASK is missing from mmu driver\n");
		return -EINVAL;
	}

	mmu->l1_pte = driver->null_pte;

	mutex_init(&mmu->pt_mutex);

	isp_mmu_flush_tlb(mmu);

#ifdef USE_KMEM_CACHE
	mmu->tbl_cache = kmem_cache_create("iopte_cache", ISP_PAGE_SIZE,
						//ISP_L1PT_PTES, SLAB_HWCACHE_ALIGN,
					   ISP_PAGE_SIZE, SLAB_HWCACHE_ALIGN,
					   NULL);
	if (!mmu->tbl_cache)
		return -ENOMEM;
#endif

	return 0;
}
コード例 #20
0
ファイル: si4713-i2c.c プロジェクト: 03199618/linux
/*
 * si4713_send_command - sends a command to si4713 and waits its response
 * @sdev: si4713_device structure for the device we are communicating
 * @command: command id
 * @args: command arguments we are sending (up to 7)
 * @argn: actual size of @args
 * @response: buffer to place the expected response from the device (up to 15)
 * @respn: actual size of @response
 * @usecs: amount of time to wait before reading the response (in usecs)
 */
static int si4713_send_command(struct si4713_device *sdev, const u8 command,
				const u8 args[], const int argn,
				u8 response[], const int respn, const int usecs)
{
	struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
	u8 data1[MAX_ARGS + 1];
	int err;

	if (!client->adapter)
		return -ENODEV;

	/* First send the command and its arguments */
	data1[0] = command;
	memcpy(data1 + 1, args, argn);
	DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1);

	err = i2c_master_send(client, data1, argn + 1);
	if (err != argn + 1) {
		v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
			command);
		return (err > 0) ? -EIO : err;
	}

	/* Wait response from interrupt */
	if (!wait_for_completion_timeout(&sdev->work,
				usecs_to_jiffies(usecs) + 1))
		v4l2_warn(&sdev->sd,
				"(%s) Device took too much time to answer.\n",
				__func__);

	/* Then get the response */
	err = i2c_master_recv(client, response, respn);
	if (err != respn) {
		v4l2_err(&sdev->sd,
			"Error while reading response for command 0x%02x\n",
			command);
		return (err > 0) ? -EIO : err;
	}

	DBG_BUFFER(&sdev->sd, "Response", response, respn);
	if (check_command_failed(response[0]))
		return -EBUSY;

	return 0;
}
コード例 #21
0
ファイル: imx7-media-csi.c プロジェクト: grate-driver/linux
static int imx7_csi_dma_start(struct imx7_csi *csi)
{
	struct imx_media_video_dev *vdev = csi->vdev;
	struct v4l2_pix_format *out_pix = &vdev->fmt.fmt.pix;
	int ret;

	ret = imx_media_alloc_dma_buf(csi->dev, &csi->underrun_buf,
				      out_pix->sizeimage);
	if (ret < 0) {
		v4l2_warn(&csi->sd, "consider increasing the CMA area\n");
		return ret;
	}

	csi->frame_sequence = 0;
	csi->last_eof = false;
	init_completion(&csi->last_eof_completion);

	imx7_csi_setup_vb2_buf(csi);

	return 0;
}
コード例 #22
0
ファイル: si4713.c プロジェクト: forgivemyheart/linux
/*
 * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful
 *		     for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS
 * @sdev: si4713_device structure for the device we are communicating
 * @usecs: timeout to wait for STC interrupt signal
 */
static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
{
	struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
	u8 resp[SI4713_GET_STATUS_NRESP];
	unsigned long start_jiffies = jiffies;
	int err;

	if (client->irq &&
	    !wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1))
		v4l2_warn(&sdev->sd,
			"(%s) Device took too much time to answer.\n", __func__);

	for (;;) {
		/* Clear status bits */
		err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
				NULL, 0,
				resp, ARRAY_SIZE(resp),
				DEFAULT_TIMEOUT);
		/* The USB device returns errors when it waits for the
		 * STC bit to be set. Hence polling */
		if (err >= 0) {
			v4l2_dbg(1, debug, &sdev->sd,
				"%s: status bits: 0x%02x\n", __func__, resp[0]);

			if (resp[0] & SI4713_STC_INT)
				return 0;
		}
		if (jiffies_to_usecs(jiffies - start_jiffies) > usecs)
			return err < 0 ? err : -EIO;
		/* We sleep here for 3-4 ms in order to avoid flooding the device
		 * with USB requests. The si4713 USB driver was developed
		 * by reverse engineering the Windows USB driver. The windows
		 * driver also has a ~2.5 ms delay between responses. */
		usleep_range(3000, 4000);
	}
}
コード例 #23
0
static int atomisp_register_entities(struct atomisp_device *isp)
{
	int ret = 0;
	int i = 0;
	struct v4l2_subdev *subdev = NULL;
	struct media_entity *input = NULL;
	unsigned int flags;
	unsigned int pad;

	isp->media_dev.dev = isp->dev;

	strlcpy(isp->media_dev.model, "Intel Atom ISP",
		sizeof(isp->media_dev.model));

	ret = media_device_register(&isp->media_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "%s: Media device registration "
			 "failed (%d)\n", __func__, ret);
		return ret;
	}

	isp->v4l2_dev.mdev = &isp->media_dev;
	ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"%s: V4L2 device registration failed (%d)\n",
			__func__, ret);
		goto v4l2_device_failed;
	}

	/*
	 * fixing me!
	 * not sub device exists on
	 * mrfld vp
	 */
	if (!IS_MRFLD) {
		ret = atomisp_subdev_probe(isp);
		if (ret < 0)
			goto lane4_and_subdev_probe_failed;
	}

	/* Register internal entities */
	ret =
	atomisp_mipi_csi2_register_entities(&isp->csi2_4p, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_mipi_csi2_register_entities 4p\n");
		goto lane4_and_subdev_probe_failed;
	}

	ret =
	atomisp_mipi_csi2_register_entities(&isp->csi2_1p, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_mipi_csi2_register_entities 1p\n");
		goto lane1_failed;
	}

	ret =
	atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_file_input_register_entities\n");
		goto file_input_register_failed;
	}

	ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n");
		goto tpg_register_failed;
	}

	ret =
	atomisp_subdev_register_entities(&isp->isp_subdev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_subdev_register_entities fail\n");
		goto subdev_register_failed;
	}

	for (i = 0; i < isp->input_cnt; i++) {
		subdev = isp->inputs[i].camera;
		switch (isp->inputs[i].port) {
		case ATOMISP_CAMERA_PORT_PRIMARY:
			input = &isp->csi2_4p.subdev.entity;
			pad = CSI2_PAD_SINK;
			flags = 0;
			break;
		case ATOMISP_CAMERA_PORT_SECONDARY:
			input = &isp->csi2_1p.subdev.entity;
			pad = CSI2_PAD_SINK;
			flags = 0;
			break;
		default:
			v4l2_dbg(1, dbg_level, &atomisp_dev,
				  "isp->inputs type not supported\n");
			break;
		}
		ret = media_entity_create_link(&subdev->entity, 0,
			input, pad, flags);
		if (ret < 0) {
			v4l2_err(&atomisp_dev,
				"snr to mipi csi link failed\n");
			goto link_failed;
		}
	}

	v4l2_dbg(1, dbg_level, &atomisp_dev,
		"FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt);
	isp->inputs[isp->input_cnt].type = FILE_INPUT;
	isp->inputs[isp->input_cnt].port = -1;
	isp->inputs[isp->input_cnt].shading_table = NULL;
	isp->inputs[isp->input_cnt].morph_table = NULL;
	isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd;

	if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) {
		v4l2_dbg(1, dbg_level, &atomisp_dev,
			"TPG detected, camera_cnt: %d\n", isp->input_cnt);
		isp->inputs[isp->input_cnt].type = TEST_PATTERN;
		isp->inputs[isp->input_cnt].port = -1;
		isp->inputs[isp->input_cnt].shading_table = NULL;
		isp->inputs[isp->input_cnt].morph_table = NULL;
		isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd;
	} else {
		v4l2_warn(&atomisp_dev,
			"too many atomisp inputs, TPG ignored.\n");
	}

	ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
	if (ret < 0)
		goto link_failed;

	return ret;

link_failed:
	atomisp_subdev_unregister_entities(&isp->isp_subdev);
subdev_register_failed:
	atomisp_tpg_unregister_entities(&isp->tpg);
tpg_register_failed:
	atomisp_file_input_unregister_entities(&isp->file_dev);
file_input_register_failed:
	atomisp_mipi_csi2_unregister_entities(&isp->csi2_1p);
lane1_failed:
	atomisp_mipi_csi2_unregister_entities(&isp->csi2_4p);
lane4_and_subdev_probe_failed:
	v4l2_device_unregister(&isp->v4l2_dev);
v4l2_device_failed:
	media_device_unregister(&isp->media_dev);
	return ret;
}
コード例 #24
0
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;
}
コード例 #25
0
ファイル: si4713.c プロジェクト: forgivemyheart/linux
/* si4713_probe - probe for the device */
static int si4713_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	struct si4713_device *sdev;
	struct v4l2_ctrl_handler *hdl;
	struct si4713_platform_data *pdata = client->dev.platform_data;
	struct device_node *np = client->dev.of_node;
	struct radio_si4713_platform_data si4713_pdev_pdata;
	struct platform_device *si4713_pdev;
	int rval;

	sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL);
	if (!sdev) {
		dev_err(&client->dev, "Failed to alloc video device.\n");
		rval = -ENOMEM;
		goto exit;
	}

	sdev->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
						   GPIOD_OUT_LOW);
	if (IS_ERR(sdev->gpio_reset)) {
		rval = PTR_ERR(sdev->gpio_reset);
		dev_err(&client->dev, "Failed to request gpio: %d\n", rval);
		goto exit;
	}

	sdev->vdd = devm_regulator_get_optional(&client->dev, "vdd");
	if (IS_ERR(sdev->vdd)) {
		rval = PTR_ERR(sdev->vdd);
		if (rval == -EPROBE_DEFER)
			goto exit;

		dev_dbg(&client->dev, "no vdd regulator found: %d\n", rval);
		sdev->vdd = NULL;
	}

	sdev->vio = devm_regulator_get_optional(&client->dev, "vio");
	if (IS_ERR(sdev->vio)) {
		rval = PTR_ERR(sdev->vio);
		if (rval == -EPROBE_DEFER)
			goto exit;

		dev_dbg(&client->dev, "no vio regulator found: %d\n", rval);
		sdev->vio = NULL;
	}

	v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);

	init_completion(&sdev->work);

	hdl = &sdev->ctrl_handler;
	v4l2_ctrl_handler_init(hdl, 20);
	sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);

	sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
	sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
	sdev->rds_compressed = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
	sdev->rds_art_head = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
	sdev->rds_stereo = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
	sdev->rds_tp = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
	sdev->rds_ta = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
	sdev->rds_ms = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
	sdev->rds_dyn_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
	sdev->rds_alt_freqs_enable = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, 0, 1, 1, 0);
	sdev->rds_alt_freqs = v4l2_ctrl_new_custom(hdl, &si4713_alt_freqs_ctrl, NULL);
	sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
			10, DEFAULT_RDS_DEVIATION);
	/*
	 * Report step as 8. From RDS spec, psname
	 * should be 8. But there are receivers which scroll strings
	 * sized as 8xN.
	 */
	sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
	/*
	 * Report step as 32 (2A block). From RDS spec,
	 * radio text should be 32 for 2A block. But there are receivers
	 * which scroll strings sized as 32xN. Setting default to 32.
	 */
	sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);

	sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
	sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
			MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
	sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
			MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);

	sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
	sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
			DEFAULT_ACOMP_GAIN);
	sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_THRESHOLD,
			MIN_ACOMP_THRESHOLD, MAX_ACOMP_THRESHOLD, 1,
			DEFAULT_ACOMP_THRESHOLD);
	sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
			MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
	sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
			MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);

	sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
	sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
			10, DEFAULT_PILOT_DEVIATION);
	sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
			1, DEFAULT_PILOT_FREQUENCY);

	sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_PREEMPHASIS,
			V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
	sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_POWER_LEVEL, 0, SI4713_MAX_POWER,
			1, DEFAULT_POWER_LEVEL);
	sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, SI4713_MAX_ANTCAP,
			1, 0);

	if (hdl->error) {
		rval = hdl->error;
		goto free_ctrls;
	}
	v4l2_ctrl_cluster(29, &sdev->mute);
	sdev->sd.ctrl_handler = hdl;

	if (client->irq) {
		rval = devm_request_irq(&client->dev, client->irq,
			si4713_handler, IRQF_TRIGGER_FALLING,
			client->name, sdev);
		if (rval < 0) {
			v4l2_err(&sdev->sd, "Could not request IRQ\n");
			goto free_ctrls;
		}
		v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
	} else {
		v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
	}

	rval = si4713_initialize(sdev);
	if (rval < 0) {
		v4l2_err(&sdev->sd, "Failed to probe device information.\n");
		goto free_ctrls;
	}

	if (!np && (!pdata || !pdata->is_platform_device))
		return 0;

	si4713_pdev = platform_device_alloc("radio-si4713", -1);
	if (!si4713_pdev) {
		rval = -ENOMEM;
		goto put_main_pdev;
	}

	si4713_pdev_pdata.subdev = client;
	rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
					sizeof(si4713_pdev_pdata));
	if (rval)
		goto put_main_pdev;

	rval = platform_device_add(si4713_pdev);
	if (rval)
		goto put_main_pdev;

	sdev->pd = si4713_pdev;

	return 0;

put_main_pdev:
	platform_device_put(si4713_pdev);
	v4l2_device_unregister_subdev(&sdev->sd);
free_ctrls:
	v4l2_ctrl_handler_free(hdl);
exit:
	return rval;
}
コード例 #26
0
ファイル: vpbe.c プロジェクト: AdrianHuang/linux-3.8.13
/**
 * 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;
}
コード例 #27
0
static int zol_setfreq(struct zoltrix *zol, unsigned long freq)
{
	/* tunes the radio to the desired frequency */
	struct v4l2_device *v4l2_dev = &zol->v4l2_dev;
	unsigned long long bitmask, f, m;
	unsigned int stereo = zol->stereo;
	int i;

	if (freq == 0) {
		v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n");
		return -EINVAL;
	}

	m = (freq / 160 - 8800) * 2;
	f = (unsigned long long)m + 0x4d1c;

	bitmask = 0xc480402c10080000ull;
	i = 45;

	mutex_lock(&zol->lock);

	zol->curfreq = freq;

	outb(0, zol->io);
	outb(0, zol->io);
	inb(zol->io + 3);            /* Zoltrix needs to be read to confirm */

	outb(0x40, zol->io);
	outb(0xc0, zol->io);

	bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31));
	while (i--) {
		if ((bitmask & 0x8000000000000000ull) != 0) {
			outb(0x80, zol->io);
			udelay(50);
			outb(0x00, zol->io);
			udelay(50);
			outb(0x80, zol->io);
			udelay(50);
		} else {
			outb(0xc0, zol->io);
			udelay(50);
			outb(0x40, zol->io);
			udelay(50);
			outb(0xc0, zol->io);
			udelay(50);
		}
		bitmask *= 2;
	}
	/* termination sequence */
	outb(0x80, zol->io);
	outb(0xc0, zol->io);
	outb(0x40, zol->io);
	udelay(1000);
	inb(zol->io + 2);

	udelay(1000);

	if (zol->muted) {
		outb(0, zol->io);
		outb(0, zol->io);
		inb(zol->io + 3);
		udelay(1000);
	}

	mutex_unlock(&zol->lock);

	if (!zol->muted)
		zol_setvol(zol, zol->curvol);
	return 0;
}
コード例 #28
0
ファイル: fimc-mdevice.c プロジェクト: 253627764/GT-I9500
/**
 * fimc_md_create_links - create default links between registered entities
 *
 * Parallel interface sensor entities are connected directly to FIMC capture
 * entities. The sensors using MIPI CSIS bus are connected through immutable
 * link with CSI receiver entity specified by mux_id. Any registered CSIS
 * entity has a link to each registered FIMC capture entity. Enabled links
 * are created by default between each subsequent registered sensor and
 * subsequent FIMC capture entity. The number of default active links is
 * determined by the number of available sensors or FIMC entities,
 * whichever is less.
 */
static int fimc_md_create_links(struct fimc_md *fmd)
{
	struct v4l2_subdev *sensor, *csis;
	struct fimc_sensor_info *s_info;
	struct s5p_fimc_isp_info *pdata;
	struct media_entity *source, *sink;
	int i, j, ret = 0;
	u32 flags = 0;

	for (j = 0; j < fmd->num_sensors; j++) {
		if (fmd->sensor[j].subdev == NULL) {
			v4l2_warn(&fmd->v4l2_dev,
				"fmd->sensor[%d].subdev = NULL!!\n", j);
			continue;
		}

		sensor = fmd->sensor[j].subdev;
		s_info = v4l2_get_subdev_hostdata(sensor);
		if (!s_info) {
			v4l2_warn(&fmd->v4l2_dev,
				"(%d) fimc_sensor_info = NULL!!\n", j);
			continue;
		}
		pdata = &s_info->pdata;
		switch (pdata->bus_type) {
		case FIMC_ITU_601...FIMC_ITU_656:
			/* TODO : add ITU configuration */
			break;
		case FIMC_MIPI_CSI2:
			/* 1. create link beween sensor and mipi-csi */
			if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
				"Wrong CSI channel id: %d\n", pdata->mux_id))
				return -EINVAL;
			csis = fmd->csis[pdata->mux_id].sd;
			if (WARN(csis == NULL,
				 "MIPI-CSI interface specified "
				 "but s5p-csis module is not loaded!\n"))
				return -EINVAL;

			ret = media_entity_create_link(&sensor->entity, 0,
					      &csis->entity, CSIS_PAD_SINK,
					      flags);
			if (ret)
				return ret;

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				  sensor->entity.name, csis->entity.name);

			/* 2. create link beween mipi-csi and fimc */
			source = &csis->entity;
			for (i = 0; i < FIMC_MAX_DEVS; i++) {
				if (!fmd->fimc[i])
					continue;
				/*
				 * Some FIMC variants are not fitted with camera capture
				 * interface. Skip creating a link from sensor for those.
				 */
				if (!fmd->fimc[i]->variant->has_cam_if)
					continue;
				sink = &fmd->fimc[i]->vid_cap.subdev.entity;

				ret = media_entity_create_link(source,
					CSIS_PAD_SOURCE,
					sink,
					FIMC_SD_PAD_SINK, flags);
				if (ret)
					return ret;

				/* Notify FIMC capture subdev entity */
				ret = media_entity_call(sink, link_setup,
					&sink->pads[FIMC_SD_PAD_SINK],
					&source->pads[CSIS_PAD_SOURCE], flags);

				if (ret)
					break;
				v4l2_info(&fmd->v4l2_dev,
					"created link [%s] %c> [%s]",
					source->name, flags ? '=' : '-',
					sink->name);
			}
			break;
		case FIMC_IS_WB:
			/* 1. create link beween sensor and mipi-csi */
			if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
				"Wrong CSI channel id: %d\n", pdata->mux_id))
				return -EINVAL;
			csis = fmd->csis[pdata->mux_id].sd;
			if (WARN(csis == NULL,
				 "MIPI-CSI interface specified "
				 "but s5p-csis module is not loaded!\n"))
				return -EINVAL;

			ret = media_entity_create_link(&sensor->entity, 0,
					      &csis->entity, CSIS_PAD_SINK,
					      flags);
			if (ret)
				return ret;

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				  sensor->entity.name, csis->entity.name);
			/* 2. create link beween mipi-csi and fimc-lite */
			source = &csis->entity;
			sink = &fmd->fimc_lite[pdata->mux_id]->subdev.entity;
			ret = media_entity_create_link(source, CSIS_PAD_SOURCE,
					sink, FLITE_SD_PAD_SINK,
					flags);
			if (ret)
				return ret;
			/* Notify FIMC-LITE subdev entity */
			ret = media_entity_call(sink, link_setup,
					&source->pads[CSIS_PAD_SOURCE],
					&sink->pads[FLITE_SD_PAD_SINK],
					flags);
			if (ret)
				break;

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				source->name, sink->name);
			/* 3. create link beween fimc-lite and fimc-is */
			source = &fmd->fimc_lite[pdata->mux_id]->subdev.entity;
			sink = &fmd->fimc_is->isp.subdev.entity;
			ret = media_entity_create_link(source,
					FLITE_SD_PAD_SOURCE,
					sink, FIMC_IS_SD_PAD_SINK,
					flags);
			if (ret)
				return ret;

			/* Notify FIMC-IS subdev entity */
			ret = media_entity_call(sink, link_setup,
					&source->pads[FLITE_SD_PAD_SOURCE],
					&sink->pads[FIMC_IS_SD_PAD_SINK],
					flags);

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				source->name, sink->name);

			/* 4. create link beween fimc-is and fimc */
			source = &fmd->fimc_is->isp.subdev.entity;
			for (i = 0; i < (FIMC_MAX_DEVS - 1); i++) {
				if (!fmd->fimc[i])
					continue;
				/*
				 * Some FIMC variants are not fitted with camera capture
				 * interface. Skip creating a link from sensor for those.
				 */
				if (!fmd->fimc[i]->variant->has_cam_if)
					continue;
				sink = &fmd->fimc[i]->vid_cap.subdev.entity;

				ret = media_entity_create_link(source,
					CSIS_PAD_SOURCE,
					sink,
					FIMC_SD_PAD_SINK, flags);
				if (ret)
					return ret;

				/* Notify FIMC capture subdev entity */
				ret = media_entity_call(sink, link_setup,
					&source->pads[CSIS_PAD_SOURCE],
					&sink->pads[FIMC_SD_PAD_SINK],
					flags);

				if (ret)
					break;
				v4l2_info(&fmd->v4l2_dev,
					"created link [%s] %c> [%s]",
					source->name, flags ? '=' : '-',
					sink->name);
			}
			break;
		default:
			v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",
				 pdata->bus_type);
			return -EINVAL;
		}
	}

	/* Create immutable link between each FIMC's subdev and video node */
	flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
	for (i = 0; i < FIMC_MAX_DEVS; i++) {
		if (!fmd->fimc[i])
			continue;
		source = &fmd->fimc[i]->vid_cap.subdev.entity;
		sink = &fmd->fimc[i]->vid_cap.vfd.entity;
		ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
					      sink, 0, flags);
		if (ret)
			break;
		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
				source->name, flags ? '=' : '-', sink->name);
	}
	return ret;
}
コード例 #29
0
static int atomisp_register_entities(struct atomisp_device *isp)
{
	int ret = 0;
	unsigned int i;

	isp->media_dev.dev = isp->dev;

	strlcpy(isp->media_dev.model, "Intel Atom ISP",
		sizeof(isp->media_dev.model));

	ret = media_device_register(&isp->media_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "%s: Media device registration "
			 "failed (%d)\n", __func__, ret);
		return ret;
	}

	isp->v4l2_dev.mdev = &isp->media_dev;
	ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"%s: V4L2 device registration failed (%d)\n",
			__func__, ret);
		goto v4l2_device_failed;
	}

	ret = atomisp_subdev_probe(isp);
	if (ret < 0)
		goto csi_and_subdev_probe_failed;

	/* Register internal entities */
	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
		ret = atomisp_mipi_csi2_register_entities(&isp->csi2_port[i],
								&isp->v4l2_dev);
		if (ret == 0)
			continue;

		/* error case */
		v4l2_err(&atomisp_dev,
			"failed to register the CSI port: %d\n", i);
		/* deregister all registered CSI ports */
		while (i--)
			atomisp_mipi_csi2_unregister_entities(
							&isp->csi2_port[i]);

		goto csi_and_subdev_probe_failed;
	}

	ret =
	atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_file_input_register_entities\n");
		goto file_input_register_failed;
	}

	ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n");
		goto tpg_register_failed;
	}

	for (i = 0; i < isp->num_of_streams; i++) {
		ret =
		atomisp_subdev_register_entities(&isp->isp_subdev[i],
						 &isp->v4l2_dev);
		if (ret < 0) {
			v4l2_err(&atomisp_dev,
				"atomisp_subdev_register_entities fail\n");
			goto subdev_register_failed;
		}
	}

	for (i = 0; i < isp->input_cnt; i++) {
		if (isp->inputs[i].port >= ATOMISP_CAMERA_NR_PORTS) {
			v4l2_err(&atomisp_dev,
					"isp->inputs port %d not supported\n",
					isp->inputs[i].port);
			ret = -EINVAL;
			goto link_failed;
		}

		ret = media_entity_create_link(
			&isp->inputs[i].camera->entity, 0,
			&isp->csi2_port[isp->inputs[i].port].subdev.entity,
			CSI2_PAD_SINK,
			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
		if (ret < 0) {
			dev_err(isp->dev,
				"link create from sensor to csi-2 receiver failed\n");
			goto link_failed;
		}
	}

	v4l2_dbg(1, dbg_level, &atomisp_dev,
		"FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt);
	isp->inputs[isp->input_cnt].type = FILE_INPUT;
	isp->inputs[isp->input_cnt].port = -1;
	isp->inputs[isp->input_cnt].shading_table = NULL;
	isp->inputs[isp->input_cnt].morph_table = NULL;
	isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd;

	if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) {
		v4l2_dbg(1, dbg_level, &atomisp_dev,
			"TPG detected, camera_cnt: %d\n", isp->input_cnt);
		isp->inputs[isp->input_cnt].type = TEST_PATTERN;
		isp->inputs[isp->input_cnt].port = -1;
		isp->inputs[isp->input_cnt].shading_table = NULL;
		isp->inputs[isp->input_cnt].morph_table = NULL;
		isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd;
	} else {
		v4l2_warn(&atomisp_dev,
			"too many atomisp inputs, TPG ignored.\n");
	}

	ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
	if (ret < 0)
		goto link_failed;

	return ret;

link_failed:
	for (i = 0; i < isp->num_of_streams; i++)
		atomisp_subdev_unregister_entities(&isp->isp_subdev[i]);
subdev_register_failed:
	while (i--)
		atomisp_subdev_unregister_entities(&isp->isp_subdev[i]);
	atomisp_tpg_unregister_entities(&isp->tpg);
tpg_register_failed:
	atomisp_file_input_unregister_entities(&isp->file_dev);
file_input_register_failed:
	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++)
		atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]);
csi_and_subdev_probe_failed:
	v4l2_device_unregister(&isp->v4l2_dev);
v4l2_device_failed:
	media_device_unregister(&isp->media_dev);
	return ret;
}
コード例 #30
0
ファイル: si4713-i2c.c プロジェクト: 03199618/linux
/* si4713_probe - probe for the device */
static int si4713_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	struct si4713_device *sdev;
	struct si4713_platform_data *pdata = client->dev.platform_data;
	struct v4l2_ctrl_handler *hdl;
	int rval, i;

	sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
	if (!sdev) {
		dev_err(&client->dev, "Failed to alloc video device.\n");
		rval = -ENOMEM;
		goto exit;
	}

	sdev->gpio_reset = -1;
	if (pdata && gpio_is_valid(pdata->gpio_reset)) {
		rval = gpio_request(pdata->gpio_reset, "si4713 reset");
		if (rval) {
			dev_err(&client->dev,
				"Failed to request gpio: %d\n", rval);
			goto free_sdev;
		}
		sdev->gpio_reset = pdata->gpio_reset;
		gpio_direction_output(sdev->gpio_reset, 0);
	}

	for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++)
		sdev->supplies[i].supply = si4713_supply_names[i];

	rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies),
				  sdev->supplies);
	if (rval) {
		dev_err(&client->dev, "Cannot get regulators: %d\n", rval);
		goto free_gpio;
	}

	v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);

	init_completion(&sdev->work);

	hdl = &sdev->ctrl_handler;
	v4l2_ctrl_handler_init(hdl, 20);
	sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);

	sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
	sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
	sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
			10, DEFAULT_RDS_DEVIATION);
	/*
	 * Report step as 8. From RDS spec, psname
	 * should be 8. But there are receivers which scroll strings
	 * sized as 8xN.
	 */
	sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
	/*
	 * Report step as 32 (2A block). From RDS spec,
	 * radio text should be 32 for 2A block. But there are receivers
	 * which scroll strings sized as 32xN. Setting default to 32.
	 */
	sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);

	sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
	sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
			MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
	sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
			MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);

	sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
	sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
			DEFAULT_ACOMP_GAIN);
	sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, MIN_ACOMP_THRESHOLD,
			MAX_ACOMP_THRESHOLD, 1,
			DEFAULT_ACOMP_THRESHOLD);
	sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
			MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
	sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
			MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);

	sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
	sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
			10, DEFAULT_PILOT_DEVIATION);
	sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
			1, DEFAULT_PILOT_FREQUENCY);

	sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_PREEMPHASIS,
			V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
	sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_POWER_LEVEL, 0, 120, 1, DEFAULT_POWER_LEVEL);
	sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, 191, 1, 0);

	if (hdl->error) {
		rval = hdl->error;
		goto free_ctrls;
	}
	v4l2_ctrl_cluster(20, &sdev->mute);
	sdev->sd.ctrl_handler = hdl;

	if (client->irq) {
		rval = request_irq(client->irq,
			si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
			client->name, sdev);
		if (rval < 0) {
			v4l2_err(&sdev->sd, "Could not request IRQ\n");
			goto put_reg;
		}
		v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
	} else {
		v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
	}

	rval = si4713_initialize(sdev);
	if (rval < 0) {
		v4l2_err(&sdev->sd, "Failed to probe device information.\n");
		goto free_irq;
	}

	return 0;

free_irq:
	if (client->irq)
		free_irq(client->irq, sdev);
free_ctrls:
	v4l2_ctrl_handler_free(hdl);
put_reg:
	regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
free_gpio:
	if (gpio_is_valid(sdev->gpio_reset))
		gpio_free(sdev->gpio_reset);
free_sdev:
	kfree(sdev);
exit:
	return rval;
}