commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=15de174ca24d24571164b366d391232579466614
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Scott Jiang <[email protected]>
---
 drivers/media/platform/blackfin/bfin_display.c |  198 +++++++++++-------------
 1 files changed, 90 insertions(+), 108 deletions(-)

diff --git a/drivers/media/platform/blackfin/bfin_display.c b/drivers/media/platform/blackfin/bfin_display.c
index 7e2255a..b727511 100644
--- a/drivers/media/platform/blackfin/bfin_display.c
+++ b/drivers/media/platform/blackfin/bfin_display.c
@@ -66,7 +66,7 @@ struct bfin_disp_device {
 	/* v4l2 control handler */
 	struct v4l2_ctrl_handler ctrl_handler;
 	/* device node data */
-	struct video_device *video_dev;
+	struct video_device video_dev;
 	/* sub device instance */
 	struct v4l2_subdev *sd;
 	/* display config */
@@ -149,8 +149,6 @@ static const struct bfin_disp_format bfin_disp_formats[] = {
 };
 #define DISP_MAX_FMTS ARRAY_SIZE(bfin_disp_formats)
 
-static irqreturn_t bfin_disp_isr(int irq, void *dev_id);
-
 static struct bfin_disp_buffer *to_bfin_disp_vb(struct vb2_buffer *vb)
 {
 	return container_of(vb, struct bfin_disp_buffer, vb);
@@ -201,7 +199,7 @@ static void bfin_disp_free_encoder_formats(struct bfin_disp_device *disp)
 static int bfin_disp_open(struct file *file)
 {
 	struct bfin_disp_device *disp = video_drvdata(file);
-	struct video_device *vfd = disp->video_dev;
+	struct video_device *vfd = &disp->video_dev;
 	struct bfin_disp_fh *bfin_disp_fh;
 
 	if (!disp->sd) {
@@ -363,6 +361,36 @@ static void bfin_disp_unlock(struct vb2_queue *vq)
 	mutex_unlock(&disp->mutex);
 }
 
+static irqreturn_t bfin_disp_isr(int irq, void *dev_id)
+{
+	struct ppi_if *ppi = dev_id;
+	struct bfin_disp_device *disp = ppi->priv;
+	struct timeval timevalue;
+	struct vb2_buffer *vb = &disp->cur_frm->vb;
+	dma_addr_t addr;
+
+	spin_lock(&disp->lock);
+
+	if (!list_empty(&disp->dma_queue)) {
+		do_gettimeofday(&timevalue);
+		vb->v4l2_buf.timestamp = timevalue;
+		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+		disp->cur_frm = list_entry(disp->dma_queue.next,
+				struct bfin_disp_buffer, list);
+		list_del(&disp->cur_frm->list);
+	}
+
+	clear_dma_irqstat(ppi->info->dma_ch);
+
+	addr = vb2_dma_contig_plane_dma_addr(&disp->cur_frm->vb, 0);
+	ppi->ops->update_addr(ppi, (unsigned long)addr);
+	ppi->ops->start(ppi);
+
+	spin_unlock(&disp->lock);
+
+	return IRQ_HANDLED;
+}
+
 static int bfin_disp_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct bfin_disp_device *disp = vb2_get_drv_priv(vq);
@@ -526,36 +554,6 @@ static int bfin_disp_dqbuf(struct file *file, void *priv,
 				buf, file->f_flags & O_NONBLOCK);
 }
 
-static irqreturn_t bfin_disp_isr(int irq, void *dev_id)
-{
-	struct ppi_if *ppi = dev_id;
-	struct bfin_disp_device *disp = ppi->priv;
-	struct timeval timevalue;
-	struct vb2_buffer *vb = &disp->cur_frm->vb;
-	dma_addr_t addr;
-
-	spin_lock(&disp->lock);
-
-	if (!list_empty(&disp->dma_queue)) {
-		do_gettimeofday(&timevalue);
-		vb->v4l2_buf.timestamp = timevalue;
-		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
-		disp->cur_frm = list_entry(disp->dma_queue.next,
-				struct bfin_disp_buffer, list);
-		list_del(&disp->cur_frm->list);
-	}
-
-	clear_dma_irqstat(ppi->info->dma_ch);
-
-	addr = vb2_dma_contig_plane_dma_addr(&disp->cur_frm->vb, 0);
-	ppi->ops->update_addr(ppi, (unsigned long)addr);
-	ppi->ops->start(ppi);
-
-	spin_unlock(&disp->lock);
-
-	return IRQ_HANDLED;
-}
-
 static int bfin_disp_streamon(struct file *file, void *priv,
 				enum v4l2_buf_type buf_type)
 {
@@ -706,6 +704,8 @@ static int bfin_disp_s_output(struct file *file, void *priv, unsigned int index)
 		return ret;
 	}
 	disp->cur_output = index;
+	/* update tvnorms from the subdevice */
+	disp->video_dev.tvnorms = config->outputs[index].std;
 	/* if this route has specific config, update ppi control */
 	if (route->ppi_control)
 		config->ppi_control = route->ppi_control;
@@ -933,22 +933,19 @@ static int bfin_disp_probe(struct platform_device *pdev)
 	int ret;
 
 	config = pdev->dev.platform_data;
-	if (!config) {
-		v4l2_err(pdev->dev.driver, "Unable to get board config\n");
+	if (!config || !config->num_outputs) {
+		v4l2_err(pdev->dev.driver, "Invalid board config\n");
 		return -ENODEV;
 	}
 
 	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
-	if (!disp) {
-		v4l2_err(pdev->dev.driver, "Unable to alloc disp\n");
+	if (!disp)
 		return -ENOMEM;
-	}
 
 	disp->cfg = config;
 
 	disp->ppi = ppi_create_instance(config->ppi_info);
 	if (!disp->ppi) {
-		v4l2_err(pdev->dev.driver, "Unable to create ppi\n");
 		ret = -ENODEV;
 		goto err_free_dev;
 	}
@@ -960,31 +957,12 @@ static int bfin_disp_probe(struct platform_device *pdev)
 		goto err_free_ppi;
 	}
 
-	vfd = video_device_alloc();
-	if (!vfd) {
-		ret = -ENOMEM;
-		v4l2_err(pdev->dev.driver, "Unable to alloc video device\n");
-		goto err_cleanup_ctx;
-	}
-
-	/* initialize field of video device */
-	vfd->release    = video_device_release;
-	vfd->fops       = &bfin_disp_fops;
-	vfd->ioctl_ops  = &bfin_disp_ioctl_ops;
-	vfd->tvnorms    = 0;
-	vfd->v4l2_dev   = &disp->v4l2_dev;
-	vfd->vfl_dir    = VFL_DIR_TX;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
-	strncpy(vfd->name, DISPLAY_DRV_NAME, sizeof(vfd->name));
-	disp->video_dev = vfd;
-
 	ret = v4l2_device_register(&pdev->dev, &disp->v4l2_dev);
 	if (ret) {
 		v4l2_err(pdev->dev.driver,
 				"Unable to register v4l2 device\n");
-		goto err_release_vdev;
+		goto err_cleanup_ctx;
 	}
-	v4l2_info(&disp->v4l2_dev, "v4l2 device registered\n");
 
 	disp->v4l2_dev.ctrl_handler = &disp->ctrl_handler;
 	ret = v4l2_ctrl_handler_init(&disp->ctrl_handler, 0);
@@ -995,6 +973,10 @@ static int bfin_disp_probe(struct platform_device *pdev)
 	}
 
 	spin_lock_init(&disp->lock);
+	mutex_init(&disp->mutex);
+	/* init video dma queues */
+	INIT_LIST_HEAD(&disp->dma_queue);
+
 	/* initialize queue */
 	q = &disp->buffer_queue;
 	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
@@ -1011,55 +993,36 @@ static int bfin_disp_probe(struct platform_device *pdev)
 		goto err_free_handler;
 	}
 
-	mutex_init(&disp->mutex);
-
-	/* init video dma queues */
-	INIT_LIST_HEAD(&disp->dma_queue);
-
+	/* initialize field of video device */
+	vfd = &disp->video_dev;
+	vfd->release    = video_device_release_empty;
+	vfd->fops       = &bfin_disp_fops;
+	vfd->ioctl_ops  = &bfin_disp_ioctl_ops;
+	vfd->tvnorms    = V4L2_STD_UNKNOWN;
+	vfd->v4l2_dev   = &disp->v4l2_dev;
+	vfd->vfl_dir    = VFL_DIR_TX;
+	vfd->queue      = q;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+	strncpy(vfd->name, DISPLAY_DRV_NAME, sizeof(vfd->name));
+	/* provide a mutex to v4l2 core */
 	vfd->lock = &disp->mutex;
 
-	/* register video device */
-	ret = video_register_device(disp->video_dev, VFL_TYPE_GRABBER, -1);
-	if (ret) {
-		v4l2_err(&disp->v4l2_dev,
-				"Unable to register video device\n");
-		goto err_free_handler;
-	}
-	video_set_drvdata(disp->video_dev, disp);
-	v4l2_info(&disp->v4l2_dev, "video device registered as: %s\n",
-			video_device_node_name(vfd));
-
 	/* load up the subdevice */
 	i2c_adap = i2c_get_adapter(config->i2c_adapter_id);
 	if (!i2c_adap) {
 		v4l2_err(&disp->v4l2_dev,
 				"Unable to find i2c adapter\n");
-		goto err_unreg_vdev;
+		goto err_free_handler;
 
 	}
 	disp->sd = v4l2_i2c_new_subdev_board(&disp->v4l2_dev,
-						 i2c_adap,
-						 &config->board_info,
-						 NULL);
-	if (disp->sd) {
-		int i;
-		if (!config->num_outputs) {
-			v4l2_err(&disp->v4l2_dev,
-					"Unable to work without output\n");
-			goto err_unreg_vdev;
-		}
-
-		/* update tvnorms from the sub devices */
-		for (i = 0; i < config->num_outputs; i++)
-			vfd->tvnorms |= config->outputs[i].std;
-	} else {
+			i2c_adap, &config->board_info, NULL);
+	if (!disp->sd) {
 		v4l2_err(&disp->v4l2_dev,
 				"Unable to register sub device\n");
-		goto err_unreg_vdev;
+		goto err_put_adap;
 	}
 
-	v4l2_info(&disp->v4l2_dev, "v4l2 sub device registered\n");
-
 	/*
 	 * explicitly set output, otherwise some boards
 	 * may not work at the state as we expected
@@ -1068,10 +1031,12 @@ static int bfin_disp_probe(struct platform_device *pdev)
 	ret = v4l2_subdev_call(disp->sd, video, s_routing,
 				route->output, route->output, 0);
 	if ((ret < 0) && (ret != -ENOIOCTLCMD)) {
-		v4l2_err(&disp->v4l2_dev, "Failed to set output\n");
-		goto err_unreg_vdev;
+		v4l2_err(&disp->v4l2_dev, "Unable to set output\n");
+		goto err_unreg_sd;
 	}
 	disp->cur_output = 0;
+	/* update tvnorms from the subdevice */
+	vfd->tvnorms = config->outputs[0].std;
 	/* if this route has specific config, update ppi control */
 	if (route->ppi_control)
 		config->ppi_control = route->ppi_control;
@@ -1083,7 +1048,7 @@ static int bfin_disp_probe(struct platform_device *pdev)
 		if (ret) {
 			v4l2_err(&disp->v4l2_dev,
 					"Unable to get std\n");
-			goto err_unreg_vdev;
+			goto err_unreg_sd;
 		}
 		disp->std = std;
 	}
@@ -1094,7 +1059,7 @@ static int bfin_disp_probe(struct platform_device *pdev)
 		if (ret) {
 			v4l2_err(&disp->v4l2_dev,
 					"Unable to get dv timings\n");
-			goto err_unreg_vdev;
+			goto err_unreg_sd;
 		}
 		disp->dv_timings = dv_timings;
 	}
@@ -1102,19 +1067,32 @@ static int bfin_disp_probe(struct platform_device *pdev)
 	if (ret) {
 		v4l2_err(&disp->v4l2_dev,
 				"Unable to create encoder formats table\n");
-		goto err_unreg_vdev;
+		goto err_unreg_sd;
+	}
+
+	/* register video device */
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
+	if (ret) {
+		v4l2_err(&disp->v4l2_dev,
+				"Unable to register video device\n");
+		goto err_free_ef;
 	}
+	video_set_drvdata(vfd, disp);
+	v4l2_info(&disp->v4l2_dev, "video device registered as: %s\n",
+			video_device_node_name(vfd));
+
 	return 0;
-err_unreg_vdev:
-	video_unregister_device(disp->video_dev);
-	disp->video_dev = NULL;
+err_free_ef:
+	bfin_disp_free_encoder_formats(disp);
+err_unreg_sd:
+	v4l2_device_unregister_subdev(disp->sd);
+	i2c_unregister_device(v4l2_get_subdevdata(disp->sd));
+err_put_adap:
+	i2c_put_adapter(i2c_adap);
 err_free_handler:
 	v4l2_ctrl_handler_free(&disp->ctrl_handler);
 err_unreg_v4l2:
 	v4l2_device_unregister(&disp->v4l2_dev);
-err_release_vdev:
-	if (disp->video_dev)
-		video_device_release(disp->video_dev);
 err_cleanup_ctx:
 	vb2_dma_contig_cleanup_ctx(disp->alloc_ctx);
 err_free_ppi:
@@ -1128,10 +1106,14 @@ static int bfin_disp_remove(struct platform_device *pdev)
 {
 	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
 	struct bfin_disp_device *disp = container_of(v4l2_dev,
-						struct bfin_disp_device, v4l2_dev);
+					struct bfin_disp_device, v4l2_dev);
+	struct i2c_client *client = v4l2_get_subdevdata(disp->sd);
 
+	video_unregister_device(&disp->video_dev);
 	bfin_disp_free_encoder_formats(disp);
-	video_unregister_device(disp->video_dev);
+	v4l2_device_unregister_subdev(disp->sd);
+	i2c_unregister_device(client);
+	i2c_put_adapter(client->adapter);
 	v4l2_ctrl_handler_free(&disp->ctrl_handler);
 	v4l2_device_unregister(v4l2_dev);
 	vb2_dma_contig_cleanup_ctx(disp->alloc_ctx);
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to